Subversion Repositories oidplus

Rev

Rev 851 | Rev 940 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
635 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
5
 * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
if (!defined('INSIDE_OIDPLUS')) die();
21
 
22
class OIDplusPageAdminOIDInfoExport extends OIDplusPagePluginAdmin {
23
 
24
        /*private*/ const QUERY_LIST_OIDINFO_OIDS_V1 = '1.3.6.1.4.1.37476.2.5.2.1.5.1';
25
        /*private*/ const QUERY_GET_OIDINFO_DATA_V1  = '1.3.6.1.4.1.37476.2.5.2.1.6.1';
26
 
27
        public function action($actionID, $params) {
28
 
29
                if ($actionID == 'import_xml_file') {
30
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
31
                                throw new OIDplusException(_L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')));
32
                        }
33
 
34
                        if (!isset($_FILES['userfile'])) {
35
                                throw new OIDplusException(_L('Please choose a file.'));
36
                        }
37
 
38
                        $xml_contents = file_get_contents($_FILES['userfile']['tmp_name']);
39
 
40
                        $errors = array();
41
                        list($count_imported_oids, $count_already_existing, $count_errors, $count_warnings) = $this->oidinfoImportXML($xml_contents, $errors, $replaceExistingOIDs=false, $orphan_mode=self::ORPHAN_AUTO_DEORPHAN);
42
                        if (count($errors) > 0) {
43
                                // Note: These "errors" can also be warnings (partial success)
44
                                // TODO: since the output can be very long, should we really show it in a JavaScript alert() ?!
45
                                return array(
46
                                        "status" => -1,
47
                                        "count_imported_oids" => $count_imported_oids,
48
                                        "count_already_existing" => $count_already_existing,
49
                                        "count_errors" => $count_errors,
50
                                        "count_warnings" => $count_warnings,
51
                                        "error" => implode("\n",$errors)
52
                                );
53
                        } else {
54
                                return array(
55
                                        "status" => 0,
56
                                        "count_imported_oids" => $count_imported_oids,
57
                                        "count_already_existing" => $count_already_existing,
58
                                        "count_errors" => $count_errors,
59
                                        "count_warnings" => $count_warnings
60
                                );
61
                        }
62
                } else if ($actionID == 'import_oidinfo_oid') {
63
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
64
                                throw new OIDplusException(_L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')));
65
                        }
66
 
67
                        _CheckParamExists($params, 'oid');
68
 
69
                        $oid = $params['oid'];
70
 
71
                        $query = self::QUERY_GET_OIDINFO_DATA_V1;
72
 
73
                        $payload = array(
74
                                "query" => $query, // we must repeat the query because we want to sign it
75
                                "system_id" => OIDplus::getSystemId(false),
76
                                "oid" => $oid
77
                        );
78
 
79
                        $signature = '';
830 daniel-mar 80
                        if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 81
                                if (!OIDplus::getPkiStatus()) {
82
                                        throw new OIDplusException(_L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.'));
83
                                } else {
84
                                        throw new OIDplusException(_L('Signature failed'));
85
                                }
86
                        }
87
 
88
                        $data = array(
89
                                "payload" => $payload,
90
                                "signature" => base64_encode($signature)
91
                        );
92
 
93
                        if (!function_exists('curl_init')) {
94
                                throw new OIDplusException(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
95
                        }
96
 
699 daniel-mar 97
                        if (OIDplus::getEditionInfo()['vendor'] != 'ViaThinkSoft') {
98
                                // The oid-info.com import functionality is a confidential API between ViaThinkSoft and oid-info.com and cannot be used in forks of OIDplus
99
                                throw new OIDplusException(_L('This feature is only available in the ViaThinkSoft edition of OIDplus'));
100
                        }
101
 
635 daniel-mar 102
                        $ch = curl_init();
103
                        if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
104
                        curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
715 daniel-mar 105
                        curl_setopt($ch, CURLOPT_USERAGENT, 'ViaThinkSoft-OIDplus/2.0');
635 daniel-mar 106
                        curl_setopt($ch, CURLOPT_POST, 1);
107
                        if (function_exists('gzdeflate')) {
108
                                $compressed = "1";
109
                                $data2 = gzdeflate(json_encode($data));
110
                        } else {
111
                                $compressed = "0";
112
                                $data2 = json_encode($data);
113
                        }
114
                        curl_setopt($ch, CURLOPT_POSTFIELDS, "query=".urlencode($query)."&compressed=$compressed&data=".urlencode(base64_encode($data2)));
115
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
116
                        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
117
                        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
118
                        if (!($res = @curl_exec($ch))) {
119
                                throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
120
                        }
121
                        curl_close($ch);
122
 
123
                        $json = @json_decode($res, true);
124
 
125
                        if (!$json) {
126
                                return array(
127
                                        "status" => -1,
128
                                        "error" => _L('JSON reply from ViaThinkSoft decoding error: %1',$res)
129
                                );
130
                        }
131
 
132
                        if (isset($json['error']) || ($json['status'] < 0)) {
133
                                return array(
134
                                        "status" => -1,
135
                                        "error" => isset($json['error']) ? $json['error'] : _L('Received error status code: %1',$json['status'])
136
                                );
137
                        }
138
 
139
                        $errors = array();
140
                        list($count_imported_oids, $count_already_existing, $count_errors, $count_warnings) = $this->oidinfoImportXML('<oid-database>'.$json['xml'].'</oid-database>', $errors, $replaceExistingOIDs=false, $orphan_mode=self::ORPHAN_DISALLOW_ORPHANS);
141
                        if (count($errors) > 0) {
142
                                return array("status" => -1, "error" => implode("\n",$errors));
143
                        } else if ($count_imported_oids <> 1) {
144
                                return array("status" => -1, "error" => _L('Imported %1, but expected to import 1',$count_imported_oids));
145
                        } else {
146
                                return array("status" => 0);
147
                        }
148
                } else {
149
                        throw new OIDplusException(_L('Unknown action ID'));
150
                }
151
        }
152
 
153
        public function init($html=true) {
154
                // Nothing
155
        }
156
 
157
        public function gui($id, &$out, &$handled) {
158
                $ary = explode('$', $id);
159
                if (isset($ary[1])) {
160
                        $id = $ary[0];
161
                        $tab = $ary[1];
162
                } else {
163
                        $tab = 'export';
164
                }
165
                if ($id === 'oidplus:oidinfo_compare_export') {
166
                        $handled = true;
167
                        $out['title'] = _L('List OIDs in your system which are missing at oid-info.com');
801 daniel-mar 168
                        $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
635 daniel-mar 169
 
170
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
800 daniel-mar 171
                                $out['icon'] = 'img/error.png';
635 daniel-mar 172
                                $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
173
                                return;
174
                        }
175
 
176
                        $query = self::QUERY_LIST_OIDINFO_OIDS_V1;
177
 
178
                        $payload = array(
179
                                "query" => $query, // we must repeat the query because we want to sign it
180
                                "system_id" => OIDplus::getSystemId(false),
181
                                "show_all" => 1 // this is required so that the VTS OIDRA gets no false notifications for adding the systems in the directory 1.3.6.1.4.1.37476.30.9
182
                        );
183
 
184
                        $signature = '';
830 daniel-mar 185
                        if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 186
                                if (!OIDplus::getPkiStatus()) {
187
                                        throw new OIDplusException(_L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.'));
188
                                } else {
189
                                        throw new OIDplusException(_L('Signature failed'));
190
                                }
191
                        }
192
 
193
                        $data = array(
194
                                "payload" => $payload,
195
                                "signature" => base64_encode($signature)
196
                        );
197
 
198
                        if (!function_exists('curl_init')) {
199
                                throw new OIDplusException(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
200
                        }
201
 
699 daniel-mar 202
                        if (OIDplus::getEditionInfo()['vendor'] != 'ViaThinkSoft') {
203
                                // The oid-info.com import functionality is a confidential API between ViaThinkSoft and oid-info.com and cannot be used in forks of OIDplus
204
                                throw new OIDplusException(_L('This feature is only available in the ViaThinkSoft edition of OIDplus'));
205
                        }
206
 
635 daniel-mar 207
                        $ch = curl_init();
208
                        if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
209
                        curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
715 daniel-mar 210
                        curl_setopt($ch, CURLOPT_USERAGENT, 'ViaThinkSoft-OIDplus/2.0');
635 daniel-mar 211
                        curl_setopt($ch, CURLOPT_POST, 1);
212
                        if (function_exists('gzdeflate')) {
213
                                $compressed = "1";
214
                                $data2 = gzdeflate(json_encode($data));
215
                        } else {
216
                                $compressed = "0";
217
                                $data2 = json_encode($data);
218
                        }
219
                        curl_setopt($ch, CURLOPT_POSTFIELDS, "query=".urlencode($query)."&compressed=$compressed&data=".urlencode(base64_encode($data2)));
220
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
221
                        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
222
                        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
223
                        if (!($res = @curl_exec($ch))) {
224
                                throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
225
                        }
226
                        curl_close($ch);
227
 
228
                        $out['text'] = '<p><a '.OIDplus::gui()->link('oidplus:datatransfer$export').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to data transfer main page').'</a></p>';
229
 
230
                        $json = @json_decode($res, true);
231
 
232
                        if (!$json) {
800 daniel-mar 233
                                $out['icon'] = 'img/error.png';
635 daniel-mar 234
                                $out['text'] .= _L('JSON reply from ViaThinkSoft decoding error: %1',$res);
235
                                return;
236
                        }
237
 
238
                        if (isset($json['error']) || ($json['status'] < 0)) {
800 daniel-mar 239
                                $out['icon'] = 'img/error.png';
635 daniel-mar 240
                                if (isset($json['error'])) {
241
                                        $out['text'] .= _L('Received error: %1',$json['error']);
242
                                } else {
243
                                        $out['text'] .= _L('Received error status code: %1',$json['status']);
244
                                }
245
                                return;
246
                        }
247
 
248
                        if (isset($json['error']) || ($json['status'] < 0)) {
249
                                $out['text'] .= '<p>'._L('Error: %1',htmlentities($json['error'])).'</p>';
250
                        } else {
251
                                // TODO: If roots were created or deleted recently, we must do a re-query of the registration, so that the "roots" information at the directory service gets refreshed
252
                                if (count($json['roots']) == 0) $out['text'] .= '<p>'._L('In order to use this feature, you need to have at least one (root) OID added in your system, and the system needs to report the newly added root to the directory service (the reporting interval is 1 hour).').'</p>';
253
                                foreach ($json['roots'] as $root) {
254
                                        $oid = $root['oid'];
255
                                        $out['text'] .= '<h2>'._L('Root OID %1',$oid).'</h2>';
256
                                        if ($root['verified']) {
257
                                                $count = 0;
258
                                                $out['text'] .= '<div class="container box"><div id="suboid_table" class="table-responsive">';
259
                                                $out['text'] .= '<table class="table table-bordered table-striped">';
260
                                                $out['text'] .= '<tr><th colspan="3">'._L('Actions').'</th><th>'._L('OID').'</th></tr>';
261
 
262
                                                $lookup_nonoid = array();
263
                                                $row_lookup = array();
264
 
265
                                                $all_local_oids_of_root = array();
266
                                                $res = OIDplus::db()->query("select * from ###objects where confidential <> 1");
267
                                                while ($row = $res->fetch_object()) {
268
                                                        $obj = OIDplusObject::parse($row->id);
269
                                                        if (!$obj) continue; // can happen when object type is not enabled
270
                                                        if ($obj->isConfidential()) continue; // This will also exclude OIDs which are descendants of confidential OIDs
271
                                                        if (strpos($row->id, 'oid:') === 0) {
272
                                                                $oid = substr($row->id,strlen('oid:'));
273
                                                                if (strpos($oid.'.', $root['oid']) === 0) {
274
                                                                        $row_lookup[$oid] = $row;
275
                                                                        $all_local_oids_of_root[] = $oid;
276
                                                                }
277
                                                        } else {
278
                                                                $aids = $obj->getAltIds();
279
                                                                foreach ($aids as $aid) {
280
                                                                        if ($aid->getNamespace() == 'oid') {
281
                                                                                $oid = $aid->getId();
282
                                                                                if (strpos($oid.'.', $root['oid']) === 0) {
283
                                                                                        $row_lookup[$oid] = $row;
284
                                                                                        $all_local_oids_of_root[] = $oid;
285
                                                                                        $lookup_nonoid[$oid] = $row->id;
286
                                                                                }
287
                                                                        }
288
                                                                }
289
                                                        }
290
                                                }
291
 
292
                                                natsort($all_local_oids_of_root);
293
                                                foreach ($all_local_oids_of_root as $local_oid) {
294
                                                        if (!in_array($local_oid, $root['children'])) {
295
                                                                $count++;
296
 
297
                                                                // Start: Build oid-info.com create URL
298
 
299
                                                                $row = $row_lookup[$local_oid];
300
 
301
                                                                $url = "http://www.oid-info.com/cgi-bin/manage?f=".oid_up($local_oid)."&a=create";
302
 
303
                                                                $tmp = explode('.',$local_oid);
304
                                                                $url .= "&nb=".urlencode(array_pop($tmp));
305
 
306
                                                                $asn1_ids = array();
307
                                                                $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
308
                                                                while ($row2 = $res2->fetch_object()) {
309
                                                                        $asn1_ids[] = $row2->name; // 'unicode-label' is currently not in the standard format (oid.xsd)
310
                                                                }
311
                                                                $url .= "&id=".array_shift($asn1_ids); // urlencode() is already done (see above)
312
                                                                $url .= "&syn_id=".implode('%0A', $asn1_ids); // urlencode() is already done (see above)
313
 
314
                                                                $iri_ids = array();
315
                                                                $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
316
                                                                while ($row2 = $res2->fetch_object()) {
317
                                                                        $iri_ids[] = $row2->name;
318
                                                                }
319
                                                                $url .= "&unicode_label_list=".implode('%0A', $iri_ids); // urlencode() is already done (see above)
320
 
321
                                                                if (!empty($row->title)) {
322
                                                                        $tmp_description = $row->title;
323
                                                                        $tmp_information = $row->description;/** @phpstan-ignore-line */
324
                                                                        if (trim($row->title) == trim(strip_tags($row->description))) {/** @phpstan-ignore-line */
325
                                                                                $tmp_information = '';
326
                                                                        }
327
                                                                } else if (isset($asn1_ids[0])) {
328
                                                                        $tmp_description = '"'.$asn1_ids[0].'"';
329
                                                                        $tmp_information = $row->description;
330
                                                                } else if (isset($iri_ids[0])) {
331
                                                                        $tmp_description = '"'.$iri_ids[0].'"';
332
                                                                        $tmp_information = $row->description;
333
                                                                } else if (!empty($row->description)) {
334
                                                                        $tmp_description = $row->description;
335
                                                                        $tmp_information = '';
336
                                                                } else if (!empty($row->comment)) {
337
                                                                        $tmp_description = $row->comment;
338
                                                                        $tmp_information = '';
339
                                                                } else {
340
                                                                        $tmp_description = '<i>No description available</i>'; // do not translate
341
                                                                        $tmp_information = '';
342
                                                                }
343
 
344
                                                                if ($tmp_information != '') {
345
                                                                        $tmp_information .= '<br/><br/>';
346
                                                                }
347
 
801 daniel-mar 348
                                                                $tmp_information .= 'See <a href="'.OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL).'?goto='.urlencode($id).'">more information</a>.'; // do not translate
635 daniel-mar 349
 
350
                                                                if (explode(':',$id,2)[0] != 'oid') {
351
                                                                        $tmp_information = "Object: $id\n\n" . $tmp_information; // do not translate
352
                                                                }
353
 
354
                                                                $url .= "&description=".urlencode(self::repair_relative_links($tmp_description));
355
                                                                $url .= "&info=".urlencode(self::repair_relative_links($tmp_information));
356
 
357
                                                                $url .= "&current_registrant_email=".urlencode($row->ra_email);
358
 
359
                                                                $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
790 daniel-mar 360
                                                                if ($res2->any()) {
635 daniel-mar 361
                                                                        $row2 = $res2->fetch_object();
362
 
363
                                                                        $tmp = array();
364
                                                                        if (!empty($row2->personal_name)) {
365
                                                                                $name_ary = split_firstname_lastname($row2->personal_name);
366
                                                                                $tmp_first_name = $name_ary[0];
367
                                                                                $tmp_last_name  = $name_ary[1];
368
                                                                                if (!empty($row2->ra_name)       ) $tmp[] = $row2->ra_name;
369
                                                                                if (!empty($row2->office)        ) $tmp[] = $row2->office;
370
                                                                                if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
371
                                                                        } else {
372
                                                                                $tmp_first_name = $row2->ra_name;
373
                                                                                $tmp_last_name  = '';
374
                                                                                if (!empty($row2->personal_name) ) $tmp[] = $row2->personal_name;
375
                                                                                if (!empty($row2->office)        ) $tmp[] = $row2->office;
376
                                                                                if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
377
                                                                        }
378
 
379
                                                                        if (empty($tmp_first_name) || empty($tmp_last_name)) {
380
                                                                                $name = self::split_name($tmp_first_name.' '.$tmp_last_name);
381
                                                                                $tmp_first_name = $name[0];
382
                                                                                $tmp_last_name = $name[1];
383
                                                                        }
384
                                                                        $url .= "&current_registrant_first_name=".urlencode($tmp_first_name);
385
                                                                        $url .= "&current_registrant_last_name=".urlencode($tmp_last_name);
386
 
387
                                                                        if ((count($tmp) > 0) && ($tmp[0] == $row2->ra_name)) array_shift($tmp);
388
                                                                        $tmp = array_unique($tmp);
389
 
390
                                                                        if (!$row2->privacy) {
391
                                                                                if (!empty($row2->street))   $tmp[] = $row2->street;
392
                                                                                if (!empty($row2->zip_town)) $tmp[] = $row2->zip_town;
393
                                                                                if (!empty($row2->country))  $tmp[] = $row2->country;
394
                                                                                $url .= "&current_registrant_tel=".urlencode(!empty($row2->phone) ? $row2->phone : $row2->mobile);
395
                                                                                $url .= "&current_registrant_fax=".urlencode($row2->fax);
396
                                                                        }
397
                                                                        if (empty($row2->zip_town) && empty($row2->country)) {
398
                                                                                // The address is useless if we do neither know city nor country
399
                                                                                // Ignore it
400
                                                                        } else {
401
                                                                                $tmp = self::split_address_country(implode("<br/>", $tmp));
402
                                                                                $url .= "&current_registrant_address=".urlencode($tmp[0]);
403
                                                                                $url .= "&current_registrant_country=".urlencode($tmp[1]);
404
                                                                        }
405
                                                                }
406
                                                                if (!empty($row->updated)) {
407
                                                                        $tmp = explode('-', self::_formatdate($row->updated));
408
                                                                        $url .= "&modification_year=".urlencode($tmp[0]);
409
                                                                        $url .= "&modification_month=".urlencode($tmp[1]);
410
                                                                        $url .= "&modification_day=".urlencode($tmp[2]);
411
                                                                }
412
 
413
                                                                //$url .= "&submitter_last_name=".urlencode($xml->{'submitter'}->{'last-name'});
414
                                                                //$url .= "&submitter_first_name=".urlencode($xml->{'submitter'}->{'first-name'});
415
                                                                //$url .= "&submitter_email=".urlencode($xml->{'submitter'}->{'email'});
416
 
417
                                                                // End: Build oid-info.com create URL
418
 
419
                                                                // Note: "Actions" is at the left, because it has a fixed width, so the user can continue clicking without the links moving if the OID length changes between lines
420
                                                                $out['text'] .= '<tr id="missing_oid_'.str_replace('.','_',$local_oid).'">'.
421
                                                                '<td><a '.OIDplus::gui()->link(isset($lookup_nonoid[$local_oid]) ? $lookup_nonoid[$local_oid] : 'oid:'.$local_oid, true).'>'._L('View local OID').'</a></td>'.
422
                                                                '<td><a href="javascript:OIDplusPageAdminOIDInfoExport.removeMissingOid(\''.$local_oid.'\');">'._L('Ignore for now').'</a></td>'.
423
                                                                '<td><a target="_blank" href="'.$url.'">'._L('Add to oid-info.com manually').'</a></td>'.
424
                                                                '<td>'.$local_oid.'</td>'.
425
                                                                '</tr>';
426
                                                        }
427
                                                }
428
                                                if ($count == 0) {
429
                                                        $out['text'] .= '<tr><td colspan="4">'._L('No missing OIDs found').'</td></tr>';
430
                                                }
431
                                                $out['text'] .= '</table></div></div>';
432
                                        } else {
433
                                                $out['text'] .= '<p>'._L('This root is not validated. Please send an email to %1 in order to request ownership verification of this root OID.',$json['vts_verification_email']).'</p>';
434
                                        }
435
                                }
436
                        }
437
                }
438
 
439
                if ($id === 'oidplus:oidinfo_compare_import') {
440
                        $handled = true;
441
                        $out['title'] = _L('List OIDs at oid-info.com which are missing in your system');
801 daniel-mar 442
                        $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
635 daniel-mar 443
 
444
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
800 daniel-mar 445
                                $out['icon'] = 'img/error.png';
635 daniel-mar 446
                                $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
447
                                return;
448
                        }
449
 
450
                        $query = self::QUERY_LIST_OIDINFO_OIDS_V1;
451
 
452
                        $payload = array(
453
                                "query" => $query, // we must repeat the query because we want to sign it
454
                                "system_id" => OIDplus::getSystemId(false),
455
                                "show_all" => 0
456
                        );
457
 
458
                        $signature = '';
830 daniel-mar 459
                        if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 460
                                if (!OIDplus::getPkiStatus()) {
461
                                        throw new OIDplusException(_L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.'));
462
                                } else {
463
                                        throw new OIDplusException(_L('Signature failed'));
464
                                }
465
                        }
466
 
467
                        $data = array(
468
                                "payload" => $payload,
469
                                "signature" => base64_encode($signature)
470
                        );
471
 
472
                        if (!function_exists('curl_init')) {
473
                                throw new OIDplusException(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
474
                        }
475
 
699 daniel-mar 476
                        if (OIDplus::getEditionInfo()['vendor'] != 'ViaThinkSoft') {
477
                                // The oid-info.com import functionality is a confidential API between ViaThinkSoft and oid-info.com and cannot be used in forks of OIDplus
478
                                throw new OIDplusException(_L('This feature is only available in the ViaThinkSoft edition of OIDplus'));
479
                        }
480
 
635 daniel-mar 481
                        $ch = curl_init();
482
                        if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
483
                        curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
715 daniel-mar 484
                        curl_setopt($ch, CURLOPT_USERAGENT, 'ViaThinkSoft-OIDplus/2.0');
635 daniel-mar 485
                        curl_setopt($ch, CURLOPT_POST, 1);
486
                        if (function_exists('gzdeflate')) {
487
                                $compressed = "1";
488
                                $data2 = gzdeflate(json_encode($data));
489
                        } else {
490
                                $compressed = "0";
491
                                $data2 = json_encode($data);
492
                        }
493
                        curl_setopt($ch, CURLOPT_POSTFIELDS, "query=".urlencode($query)."&compressed=$compressed&data=".urlencode(base64_encode($data2)));
494
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
495
                        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
496
                        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
497
                        if (!($res = @curl_exec($ch))) {
498
                                throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
499
                        }
500
                        curl_close($ch);
501
 
502
                        $out['text'] = '<p><a '.OIDplus::gui()->link('oidplus:datatransfer$import').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to data transfer main page').'</a></p>';
503
 
504
                        $json = @json_decode($res, true);
505
 
506
                        if (!$json) {
800 daniel-mar 507
                                $out['icon'] = 'img/error.png';
635 daniel-mar 508
                                $out['text'] .= _L('JSON reply from ViaThinkSoft decoding error: %1',$res);
509
                                return;
510
                        }
511
 
512
                        if (isset($json['error']) || ($json['status'] < 0)) {
800 daniel-mar 513
                                $out['icon'] = 'img/error.png';
635 daniel-mar 514
                                if (isset($json['error'])) {
515
                                        $out['text'] .= _L('Received error: %1',$json['error']);
516
                                } else {
517
                                        $out['text'] .= _L('Received error status code: %1',$json['status']);
518
                                }
519
                                return;
520
                        }
521
 
522
                        $all_local_oids = array();
523
                        $res = OIDplus::db()->query("select id from ###objects");
524
                        while ($row = $res->fetch_array()) {
525
                                if (strpos($row['id'], 'oid:') === 0) {
526
                                        $all_local_oids[] = substr($row['id'],strlen('oid:'));
527
                                } else {
528
                                        $obj = OIDplusObject::parse($row['id']);
529
                                        if (!$obj) continue; // can happen when object type is not enabled
530
                                        $aids = $obj->getAltIds();
531
                                        foreach ($aids as $aid) {
532
                                                if ($aid->getNamespace() == 'oid') {
533
                                                        $all_local_oids[] = $aid->getId();
534
                                                }
535
                                        }
536
                                }
537
                        }
538
 
539
                        if (isset($json['error']) || ($json['status'] < 0)) {
540
                                $out['text'] .= '<p>'._L('Error: %1',htmlentities($json['error'])).'</p>';
541
                        } else {
542
                                // TODO: If roots were created or deleted recently, we must do a re-query of the registration, so that the "roots" information at the directory service gets refreshed
543
                                if (count($json['roots']) == 0) $out['text'] .= '<p>'._L('In order to use this feature, you need to have at least one (root) OID added in your system, and the system needs to report the newly added root to the directory service (the reporting interval is 1 hour).').'</p>';
544
                                foreach ($json['roots'] as $root) {
545
                                        $oid = $root['oid'];
546
                                        $out['text'] .= '<h2>'._L('Root OID %1',$oid).'</h2>';
547
                                        // TODO: "Import all" button
548
                                        if ($root['verified']) {
549
                                                $count = 0;
550
                                                $out['text'] .= '<div class="container box"><div id="suboid_table" class="table-responsive">';
551
                                                $out['text'] .= '<table class="table table-bordered table-striped">';
552
                                                $out['text'] .= '<tr><th colspan="4">'._L('Actions').'</th><th>'._L('OID').'</th></tr>';
553
                                                natsort($root['children']);
554
                                                foreach ($root['children'] as $child_oid) {
555
                                                        if (!in_array($child_oid, $all_local_oids)) {
556
                                                                $count++;
557
                                                                // Note: "Actions" is at the left, because it has a fixed width, so the user can continue clicking without the links moving if the OID length changes between lines
558
                                                                $out['text'] .= '<tr id="missing_oid_'.str_replace('.','_',$child_oid).'">'.
559
                                                                '<td><a target="_blank" href="http://www.oid-info.com/get/'.$child_oid.'">'._L('View OID at oid-info.com').'</a></td>'.
560
                                                                '<td><a href="javascript:OIDplusPageAdminOIDInfoExport.removeMissingOid(\''.$child_oid.'\');">'._L('Ignore for now').'</a></td>'.
561
                                                                '<td><a href="mailto:admin@oid-info.com">'._L('Report illegal OID').'</a></td>'.
562
                                                                (strpos($child_oid,'1.3.6.1.4.1.37476.30.9.') === 0 ? '<td>&nbsp;</td>' : '<td><a href="javascript:OIDplusPageAdminOIDInfoExport.importMissingOid(\''.$child_oid.'\');">'._L('Import OID').'</a></td>').
563
                                                                '<td>'.$child_oid.'</td>'.
564
                                                                '</tr>';
565
                                                        }
566
                                                }
567
                                                if ($count == 0) {
568
                                                        $out['text'] .= '<tr><td colspan="5">'._L('No extra OIDs found').'</td></tr>';
569
                                                }
570
                                                $out['text'] .= '</table></div></div>';
571
                                        } else {
572
                                                $out['text'] .= '<p>'._L('This root is not validated. Please send an email to %1 in order to request ownership verification of this root OID.',$json['vts_verification_email']).'</p>';
573
                                        }
574
                                }
575
                        }
576
                }
577
 
578
                if ($id === 'oidplus:datatransfer') {
579
                        $handled = true;
580
                        $out['title'] = _L('Data Transfer');
801 daniel-mar 581
                        $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
635 daniel-mar 582
 
583
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
800 daniel-mar 584
                                $out['icon'] = 'img/error.png';
635 daniel-mar 585
                                $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
586
                                return;
587
                        }
588
 
890 daniel-mar 589
                        $out['text'] = '<noscript>';
590
                        $out['text'] .= '<p>'._L('You need to enable JavaScript to use the login area.').'</p>';
591
                        $out['text'] .= '</noscript>';
635 daniel-mar 592
 
890 daniel-mar 593
                        $out['text'] .= '<br><div id="dataTransferArea" style="visibility: hidden"><div id="dataTransferTab" class="container" style="width:100%;">';
594
 
635 daniel-mar 595
                        // ---------------- Tab control
596
                        $out['text'] .= OIDplus::gui()->tabBarStart();
597
                        $out['text'] .= OIDplus::gui()->tabBarElement('export', _L('Export'), $tab === 'export');
598
                        $out['text'] .= OIDplus::gui()->tabBarElement('import', _L('Import'), $tab === 'import');
599
                        $out['text'] .= OIDplus::gui()->tabBarEnd();
600
                        $out['text'] .= OIDplus::gui()->tabContentStart();
601
                        // ---------------- "Export" tab
602
                        $tabcont  = '<h2>'._L('Generate XML file containing all OIDs').'</h2>';
603
                        $tabcont .= '<p>'._L('These XML files are following the <a %1>XML schema</a> of <b>oid-info.com</b>. They can be used for various purposes though.','href="http://www.oid-info.com/oid.xsd" target="_blank"').'</p>';
801 daniel-mar 604
                        $tabcont .= '<p><input type="button" onclick="window.open(\''.OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'oidinfo_export.php\',\'_blank\')" value="'._L('Generate XML (all OIDs)').'"></p>';
605
                        $tabcont .= '<p><input type="button" onclick="window.open(\''.OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'oidinfo_export.php?online=1\',\'_blank\')" value="'._L('Generate XML (only OIDs which do not exist at oid-info.com)').'"></p>';
635 daniel-mar 606
                        $tabcont .= '<p><a href="http://www.oid-info.com/submit.htm" target="_blank">'._L('Upload XML files manually to oid-info.com').'</a></p>';
607
                        $tabcont .= '<br><p>'._L('Attention: Do not use this XML Export/Import to exchange, backup or restore data between OIDplus systems!<br>It will cause various loss of information, e.g. because Non-OIDs like GUIDs are converted in OIDs and can\'t be converted back.').'</p>';
608
                        $tabcont .= '<h2>'._L('Automatic export to oid-info.com').'</h2>';
609
                        $privacy_level = OIDplus::config()->getValue('reg_privacy');
610
                        if ($privacy_level == 0) {
611
                                $tabcont .= '<p>'._L('All your OIDs will automatically submitted to oid-info.com through the remote directory service in regular intervals.').' (<a '.OIDplus::gui()->link('oidplus:srv_registration').'>'._L('Change preference').'</a>)</p>';
612
                        } else {
613
                                $tabcont .= '<p>'._L('If you set the privacy option to "0" (your system is registered), then all your OIDs will be automatically exported to oid-info.com.').' (<a '.OIDplus::gui()->link('oidplus:srv_registration').'>'._L('Change preference').'</a>)</p>';
614
                        }
615
                        $tabcont .= '<h2>'._L('Comparison with oid-info.com').'</h2>';
616
                        $tabcont .= '<p><a '.OIDplus::gui()->link('oidplus:oidinfo_compare_export').'>'._L('List OIDs in your system which are missing at oid-info.com').'</a></p>';
617
                        $out['text'] .= OIDplus::gui()->tabContentPage('export', $tabcont, $tab === 'export');
618
                        // ---------------- "Import" tab
619
                        $tabcont  = '<h2>'._L('Import XML file').'</h2>';
620
                        $tabcont .= '<p>'._L('These XML files are following the <a %1>XML schema</a> of <b>oid-info.com</b>.','href="http://www.oid-info.com/oid.xsd" target="_blank"').'</p>';
621
                        // TODO: we need a waiting animation!
622
                        $tabcont .= '<form action="javascript:void(0);" onsubmit="return OIDplusPageAdminOIDInfoExport.uploadXmlFileOnSubmit(this);" enctype="multipart/form-data" id="uploadXmlFileForm">';
623
                        $tabcont .= '<div>'._L('Choose XML file here').':<input type="file" name="userfile" value="" id="userfile">';
624
                        $tabcont .= '<br><input type="submit" value="'._L('Import XML').'"></div>';
625
                        $tabcont .= '</form>';
626
                        $tabcont .= '<br><p>'._L('Attention: Do not use this XML Export/Import to exchange, backup or restore data between OIDplus systems!<br>It will cause various loss of information, e.g. because Non-OIDs like GUIDs are converted in OIDs and can\'t be converted back.').'</p>';
627
                        $tabcont .= '<h2>'._L('Comparison with oid-info.com').'</h2>';
628
                        $tabcont .= '<p><a '.OIDplus::gui()->link('oidplus:oidinfo_compare_import').'>'._L('List OIDs at oid-info.com which are missing in your system').'</a></p>';
629
                        $out['text'] .= OIDplus::gui()->tabContentPage('import', $tabcont, $tab === 'import');
630
                        $out['text'] .= OIDplus::gui()->tabContentEnd();
631
                        // ---------------- Tab control END
632
 
633
                        $out['text'] .= '</div></div><script>$("#dataTransferArea")[0].style.visibility = "visible";</script>';
634
                }
635
        }
636
 
637
        public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
638
                if (!OIDplus::authUtils()->isAdminLoggedIn()) return false;
639
 
800 daniel-mar 640
                if (file_exists(__DIR__.'/img/main_icon16.png')) {
801 daniel-mar 641
                        $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png';
635 daniel-mar 642
                } else {
643
                        $tree_icon = null; // default icon (folder)
644
                }
645
 
646
                $json[] = array(
647
                        'id' => 'oidplus:datatransfer',
648
                        'icon' => $tree_icon,
649
                        'text' => _L('Data Transfer')
650
                );
651
 
652
                return true;
653
        }
654
 
655
        public function tree_search($request) {
656
                return false;
657
        }
658
 
659
        public static function outputXML($only_non_existing) {
660
                // This file contains class OIDInfoAPI.
661
                // We cannot include this in init(), because the init
662
                // of the registration plugin (OIDplusPageAdminRegistration) uses
663
                // OIDplusPageAdminOIDInfoExport::outputXML() before
664
                // OIDplusPageAdminOIDInfoExport::init() ,
665
                // because OIDplusPageAdminRegistration::init() comes first sometimes.
666
                require_once __DIR__ . '/oidinfo_api.inc.php';
667
 
668
                $oa = new OIDInfoAPI();
724 daniel-mar 669
                if ($only_non_existing) {
670
                        if (!function_exists('socket_create')) {
671
                                throw new OIDplusException(_L('You must install the PHP "sockets" in order to check for non-existing OIDs.'));
672
                        }
673
                        $oa->addSimplePingProvider('viathinksoft.de:49500');
674
                }
635 daniel-mar 675
 
676
                $email = OIDplus::config()->getValue('admin_email');
677
                if (empty($email)) $email = 'unknown@example.com';
678
 
724 daniel-mar 679
                $sys_title = OIDplus::config()->getValue('system_title');
680
                $name1 = !empty($sys_title) ? $sys_title : 'OIDplus 2.0';
681
                $name2 = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'Export interface';
682
                echo $oa->xmlAddHeader($name1, $name2, $email); // do not translate
635 daniel-mar 683
 
684
                $params['allow_html'] = true;
685
                $params['allow_illegal_email'] = true; // It should be enabled, because the creator could have used some kind of human-readable anti-spam technique
686
                $params['soft_correct_behavior'] = OIDInfoAPI::SOFT_CORRECT_BEHAVIOR_NONE;
687
                $params['do_online_check'] = false; // Flag to disable this online check, because it generates a lot of traffic and runtime.
688
                $params['do_illegality_check'] = true;
689
                $params['do_simpleping_check'] = $only_non_existing;
690
                $params['auto_extract_name'] = '';
691
                $params['auto_extract_url'] = '';
692
                $params['always_output_comment'] = false;
693
                $params['creation_allowed_check'] = $only_non_existing;
694
                $params['tolerant_htmlentities'] = true;
695
                $params['ignore_xhtml_light'] = false;
696
 
697
                $nonConfidential = OIDplusObject::getAllNonConfidential();
698
                natsort($nonConfidential);
699
 
700
                foreach ($nonConfidential as $id) {
701
                        $res = OIDplus::db()->query("select * from ###objects where id = ?", array($id));
702
                        if ($row = $res->fetch_object()) {
703
                                $elements['identifier'] = array();
704
                                $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
705
                                while ($row2 = $res2->fetch_object()) {
706
                                        $elements['identifier'][] = $row2->name; // 'unicode-label' is currently not in the standard format (oid.xsd)
707
                                }
708
 
709
                                $elements['unicode-label'] = array();
710
                                $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
711
                                while ($row2 = $res2->fetch_object()) {
712
                                        $elements['unicode-label'][] = $row2->name;
713
                                }
714
 
715
                                if (!empty($row->title)) {
716
                                        $elements['description'] = $row->title;
717
                                        $elements['information'] = $row->description;/** @phpstan-ignore-line */
718
                                        if (trim($row->title) == trim(strip_tags($row->description))) {/** @phpstan-ignore-line */
719
                                                $elements['information'] = '';
720
                                        }
721
                                } else if (isset($elements['identifier'][0])) {
722
                                        $elements['description'] = '"'.$elements['identifier'][0].'"';
723
                                        $elements['information'] = $row->description;
724
                                } else if (isset($elements['unicode-label'][0])) {
725
                                        $elements['description'] = '"'.$elements['unicode-label'][0].'"';
726
                                        $elements['information'] = $row->description;
727
                                } else if (!empty($row->description)) {
728
                                        $elements['description'] = $row->description;
729
                                        $elements['information'] = '';
730
                                } else if (!empty($row->comment)) {
731
                                        $elements['description'] = $row->comment;
732
                                        $elements['information'] = '';
733
                                } else {
734
                                        $elements['description'] = '<i>No description available</i>'; // do not translate
735
                                        $elements['information'] = '';
736
                                }
737
 
738
                                if ($elements['information'] != '') {
739
                                        $elements['information'] .= '<br/><br/>';
740
                                }
741
 
801 daniel-mar 742
                                $elements['information'] .= 'See <a href="'.OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL).'?goto='.urlencode($id).'">more information</a>.'; // do not translate
635 daniel-mar 743
 
744
                                if (explode(':',$id,2)[0] != 'oid') {
745
                                        $elements['information'] = "Object: $id\n\n" . $elements['information']; // do not translate
746
                                }
747
 
748
                                $elements['description'] = self::repair_relative_links($elements['description']);
749
                                $elements['information'] = self::repair_relative_links($elements['information']);
750
 
751
                                $elements['first-registrant']['first-name'] = '';
752
                                $elements['first-registrant']['last-name'] = '';
753
                                $elements['first-registrant']['address'] = '';
754
                                $elements['first-registrant']['email'] = '';
755
                                $elements['first-registrant']['phone'] = '';
756
                                $elements['first-registrant']['fax'] = '';
757
                                $elements['first-registrant']['creation-date'] = self::_formatdate($row->created);
758
 
759
                                $elements['current-registrant']['first-name'] = '';
760
                                $elements['current-registrant']['last-name'] = '';
761
                                $elements['current-registrant']['email'] = $row->ra_email;
762
                                $elements['current-registrant']['phone'] = '';
763
                                $elements['current-registrant']['fax'] = '';
764
                                $elements['current-registrant']['address'] = '';
765
 
766
                                $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
790 daniel-mar 767
                                if ($res2->any()) {
635 daniel-mar 768
                                        $row2 = $res2->fetch_object();
769
 
770
                                        $tmp = array();
771
                                        if (!empty($row2->personal_name)) {
772
                                                $name_ary = split_firstname_lastname($row2->personal_name);
773
                                                $elements['current-registrant']['first-name'] = $name_ary[0];
774
                                                $elements['current-registrant']['last-name']  = $name_ary[1];
775
                                                if (!empty($row2->ra_name)       ) $tmp[] = $row2->ra_name;
776
                                                if (!empty($row2->office)        ) $tmp[] = $row2->office;
777
                                                if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
778
                                        } else {
779
                                                $elements['current-registrant']['first-name'] = $row2->ra_name;
780
                                                $elements['current-registrant']['last-name']  = '';
781
                                                if (!empty($row2->personal_name) ) $tmp[] = $row2->personal_name;
782
                                                if (!empty($row2->office)        ) $tmp[] = $row2->office;
783
                                                if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
784
                                        }
785
 
786
                                        if ((count($tmp) > 0) && ($tmp[0] == $row2->ra_name)) array_shift($tmp);
787
                                        $tmp = array_unique($tmp);
788
 
789
                                        if (!$row2->privacy) {
790
                                                if (!empty($row2->street))   $tmp[] = $row2->street;
791
                                                if (!empty($row2->zip_town)) $tmp[] = $row2->zip_town;
792
                                                if (!empty($row2->country))  $tmp[] = $row2->country;
793
                                                $elements['current-registrant']['phone'] = !empty($row2->phone) ? $row2->phone : $row2->mobile;
794
                                                $elements['current-registrant']['fax'] = $row2->fax;
795
                                        }
796
                                        if (empty($row2->zip_town) && empty($row2->country)) {
797
                                                // The address is useless if we do neither know city nor country
798
                                                // Ignore it
799
                                                $elements['current-registrant']['address'] = '';
800
                                        } else {
801
                                                $elements['current-registrant']['address'] = implode("<br/>", $tmp);
802
                                        }
803
                                }
804
                                $elements['current-registrant']['modification-date'] = self::_formatdate($row->updated);
805
 
806
                                // Request from O.D. 20 May 2019: First registrant should not be empty (especially for cases where Creation and Modify Dates are the same)
807
                                // Actually, this is a problem because we don't know the first registrant.
808
                                // However, since oidinfo gets their XML very fast (if using registration), it is likely that the reported RA is still the same...
809
                                // ... and changes at the RA are not reported to oid-info.com anyways - the XML is only for creation
810
 
811
                                $elements['first-registrant']['first-name'] = $elements['current-registrant']['first-name'];
812
                                $elements['first-registrant']['last-name']  = $elements['current-registrant']['last-name'];
813
                                $elements['first-registrant']['address']    = $elements['current-registrant']['address'];
814
                                $elements['first-registrant']['email']      = $elements['current-registrant']['email'];
815
                                $elements['first-registrant']['phone']      = $elements['current-registrant']['phone'];
816
                                $elements['first-registrant']['fax']        = $elements['current-registrant']['fax'];
817
 
818
                                $elements['current-registrant']['first-name'] = '';
819
                                $elements['current-registrant']['last-name'] = '';
820
                                $elements['current-registrant']['address'] = '';
821
                                $elements['current-registrant']['email'] = '';
822
                                $elements['current-registrant']['phone'] = '';
823
                                $elements['current-registrant']['fax'] = '';
824
                                $elements['current-registrant']['modification-date'] = '';
825
 
826
                                // End request O.D. 20 May 2019
827
 
828
                                $obj = OIDplusObject::parse($row->id);
829
 
830
                                list($ns,$id) = explode(':',$obj->nodeId());
831
                                if ($ns == 'oid') {
832
                                        echo $oa->createXMLEntry($id, $elements, $params, $comment=$obj->nodeId());
833
                                } else {
834
                                        $alt_ids = $obj->getAltIds(); // TODO: slow!
835
                                        foreach ($alt_ids as $alt_id) {
836
                                                $ns = $alt_id->getNamespace();
837
                                                $id = $alt_id->getId();
838
                                                $desc = $alt_id->getDescription();
839
                                                if ($ns == 'oid') {
840
                                                        if (strpos($id, '2.25.') === 0) continue; // don't spam the uuid arc with GUID objects
841
                                                        echo $oa->createXMLEntry($id, $elements, $params, $comment=$obj->nodeId());
842
                                                }
843
                                        }
844
                                }
845
                        }
846
                }
847
 
848
                echo $oa->xmlAddFooter();
849
        }
850
 
851
        private static function _formatdate($str) {
852
                $str = explode(' ',$str)[0];
853
                if ($str == '0000-00-00') $str = '';
854
                return $str;
855
        }
856
 
857
        private static function repair_relative_links($str) {
858
                $str = preg_replace_callback('@(href\s*=\s*([\'"]))(.+)(\\2)@ismU', function($treffer) {
859
                        $url = $treffer[3];
860
                        if ((stripos($url,'http:') !== 0) && (stripos($url,'https:') !== 0) && (stripos($url,'ftp:') !== 0)) {
861
                                if (stripos($url,'www.') === 0) {
862
                                        $url .= 'http://' . $url;
863
                                } else {
801 daniel-mar 864
                                        $url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . $url; // TODO: Canonical or not?
635 daniel-mar 865
                                }
866
                        }
867
                        return $treffer[1].$url.$treffer[4];
868
                }, $str);
869
                return $str;
870
        }
871
 
872
        private static function split_address_country($address) {
873
                global $oidinfo_countries;
874
                $ary = explode("\n", $address);
875
                $last_line = array_pop($ary);
876
                $rest = implode("\n", $ary);
877
                if (isset($oidinfo_countries[$last_line])) {
878
                        return array($rest, $oidinfo_countries[$last_line]);
879
                } else {
880
                        return array($rest."\n".$last_line, '');
881
                }
882
        }
883
 
884
        private static function split_name($name) {
885
                // uses regex that accepts any word character or hyphen in last name
886
                // https://stackoverflow.com/questions/13637145/split-text-string-into-first-and-last-name-in-php
887
                $name = trim($name);
888
                $last_name = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name);
889
                $first_name = trim( preg_replace('#'.preg_quote($last_name,'#').'#', '', $name ) );
890
                return array($first_name, $last_name);
891
        }
892
 
893
        /*protected*/ const ORPHAN_IGNORE = 0;
894
        /*protected*/ const ORPHAN_AUTO_DEORPHAN = 1;
895
        /*protected*/ const ORPHAN_DISALLOW_ORPHANS = 2;
896
 
897
        protected function oidinfoImportXML($xml_contents, &$errors, $replaceExistingOIDs=false, $orphan_mode=self::ORPHAN_AUTO_DEORPHAN) {
898
                // TODO: Implement RA import (let the user decide)
899
                // TODO: Let the user decide about $replaceExistingOIDs
900
                // TODO: Let the user decide if "created=now" should be set (this is good when the XML files is created by the user itself to do bulk-inserts)
901
 
902
                $xml_contents = str_replace('<description>', '<description><![CDATA[', $xml_contents);
903
                $xml_contents = str_replace('</description>', ']]></description>', $xml_contents);
904
 
905
                $xml_contents = str_replace('<information>', '<information><![CDATA[', $xml_contents);
906
                $xml_contents = str_replace('</information>', ']]></information>', $xml_contents);
907
 
908
                $xml = @simplexml_load_string($xml_contents);
909
 
910
                $count_already_existing = 0;
911
                $count_errors = 0;
912
                $count_warnings = 0;
913
 
914
                if (!$xml) {
915
                        $errors[] = _L('Cannot read XML data. The XML file is probably invalid.');
916
                        $count_errors++;
917
                        return array(0, 0, 1, 0);
918
                }
919
 
920
                $ok_oids = array();
921
 
922
                foreach ($xml->oid as $xoid) {
923
 
924
                        if (isset($xoid->{'dot-notation'})) {
925
                                $dot_notation = $xoid->{'dot-notation'}->__toString();
926
                        } else if (isset($xoid->{'asn1-notation'})) {
927
                                $dot_notation = asn1_to_dot($xoid->{'asn1-notation'}->__toString());
928
                        } else {
929
                                $errors[] = _L('Cannot find dot notation because fields asn1-notation and dot-notation are both not existing');
930
                                $count_errors++;
931
                                continue;
932
                        }
933
 
934
                        $id = "oid:$dot_notation";
935
                        $title = isset($xoid->{'description'}) ? $xoid->{'description'}->__toString() : '';
936
                        $info = isset($xoid->{'description'}) ? $xoid->{'information'}->__toString() : '';
937
 
938
                        if (isset($xoid->{'current-registrant'}->email)) {
939
                                $ra = $xoid->{'current-registrant'}->email->__toString();
940
                        } else if (isset($xoid->{'first-registrant'}->email)) {
941
                                $ra = $xoid->{'first-registrant'}->email->__toString();
942
                        } else {
943
                                $ra = '';
944
                        }
945
 
946
                        if (!oid_valid_dotnotation($dot_notation, false, false)) {
947
                                $errors[] = _L('Ignored OID %1 because its dot notation is illegal or was not found',$dot_notation);
948
                                $count_errors++;
949
                                continue;
950
                        }
951
 
952
                        $parent = 'oid:'.oid_up($dot_notation);
953
 
954
                        if ($orphan_mode === self::ORPHAN_DISALLOW_ORPHANS) {
955
                                $res = OIDplus::db()->query("select * from ###objects where id = ?", array($parent));
790 daniel-mar 956
                                if (!$res->any()) {
635 daniel-mar 957
                                        $errors[] = _L('Cannot import %1, because its parent is not in the database.',$dot_notation);
958
                                        $count_errors++;
959
                                        continue;
960
                                }
961
                        }
962
 
963
                        $res = OIDplus::db()->query("select * from ###objects where id = ?", array($id));
790 daniel-mar 964
                        if ($res->any()) {
635 daniel-mar 965
                                if ($replaceExistingOIDs) {
966
                                        // TODO: better do this (and the following insert) as transaction
967
                                        OIDplus::db()->query("delete from ###asn1id where oid = ?", array($id));
968
                                        OIDplus::db()->query("delete from ###iri where oid = ?", array($id));
969
                                        OIDplus::db()->query("delete from ###objects where id = ?", array($id));
970
                                } else {
971
                                        //$errors[] = "Ignore OID '$dot_notation' because it already exists";
972
                                        //$count_errors++;
973
                                        $count_already_existing++;
974
                                        continue;
975
                                }
976
                        }
977
 
978
                        OIDplus::db()->query("insert into ###objects (id, parent, title, description, confidential, ra_email) values (?, ?, ?, ?, ?, ?)", array($id, $parent, $title, $info, 0, $ra));
979
 
980
                        $this_oid_has_warnings = false;
981
 
982
                        // ---------------------------------------------------------------------
983
 
984
                        $asn1ids = array();
985
                        if (isset($xoid->{'identifier'})) {
986
                                $asn1ids[] = $xoid->{'identifier'}->__toString();
987
                        }
988
                        if (isset($xoid->{'asn1-notation'})) {
989
                                $last_id = asn1_last_identifier($xoid->{'asn1-notation'}->__toString());
990
                                if ($last_id) {
991
                                        $asn1ids[] = $last_id;
992
                                }
993
                        }
994
                        if (isset($xoid->{'synonymous-identifier'})) {
995
                                foreach ($xoid->{'synonymous-identifier'} as $synid) {
996
                                        $asn1ids[] = $synid->__toString();
997
                                }
998
                        }
999
                        $asn1ids = array_unique($asn1ids);
1000
                        foreach ($asn1ids as $asn1id) {
1001
                                if (!oid_id_is_valid($asn1id)) {
1002
                                        $errors[] = _L('Warning').' ['._L('OID %1',$dot_notation).']: '._L('Ignored alphanumeric identifier %1, because it is invalid',$asn1id);
1003
                                        $this_oid_has_warnings = true;
1004
                                } else {
1005
                                        OIDplus::db()->query("delete from ###asn1id where oid = ? and name = ?", array($id, $asn1id));
1006
                                        OIDplus::db()->query("insert into ###asn1id (oid, name) values (?, ?)", array($id, $asn1id));
1007
                                }
1008
                        }
1009
 
1010
                        // ---------------------------------------------------------------------
1011
 
1012
                        if (isset($xoid->{'unicode-label'})) {
1013
                                $iris = array();
1014
                                foreach ($xoid->{'unicode-label'} as $iri) {
1015
                                        $iris[] = $iri->__toString();
1016
                                }
1017
                                $iris = array_unique($iris);
1018
                                foreach ($iris as $iri) {
1019
                                        if (!iri_arc_valid($iri, false)) {
1020
                                                $errors[] = _L('Warning').' ['._L('OID %1',$dot_notation).']: '._L('Ignored Unicode label %1, because it is invalid',$iri);
1021
                                                $this_oid_has_warnings = true;
1022
                                        } else {
1023
                                                OIDplus::db()->query("delete from ###iri where oid = ? and name = ?", array($id, $iri));
1024
                                                OIDplus::db()->query("insert into ###iri (oid, name) values (?, ?)", array($id, $iri));
1025
                                        }
1026
                                }
1027
                        }
1028
 
1029
                        if ($this_oid_has_warnings) $count_warnings++;
1030
                        $ok_oids[] = $id;
1031
                }
1032
 
1033
                // De-orphanize
1034
                //if ($orphan_mode === self::ORPHAN_AUTO_DEORPHAN) OIDplus::db()->query("update ###objects set parent = 'oid:' where parent like 'oid:%' and parent not in (select id from ###objects)");
1035
                foreach ($ok_oids as $id) {
1036
                        // De-orphanize if neccessary
1037
                        if ($orphan_mode === self::ORPHAN_AUTO_DEORPHAN) {
1038
                                $res = OIDplus::db()->query("select * from ###objects where id = ? and parent not in (select id from ###objects)", array($id));
790 daniel-mar 1039
                                if ($res->any()) {
635 daniel-mar 1040
                                        $errors[] = _L("%1 was de-orphaned (placed as root OID) because its parent is not existing.",$id);
1041
                                        $count_warnings++;
1042
                                        OIDplus::db()->query("update ###objects set parent = 'oid:' where id = ? and parent not in (select id from ###objects)", array($id));
1043
                                }
1044
                        }
1045
 
1046
                        // We do the logging at the end, otherwise SUPOIDRA() might not work correctly if the OIDs were not imported in order or if there were orphans
1047
                        OIDplus::logger()->log("[INFO]OID($id)+[INFO]SUPOID($id)+[INFO]SUPOIDRA($id)!/[INFO]A!", "Object '$id' was automatically created by the XML import tool");
1048
                }
1049
 
1050
                $count_imported_oids = count($ok_oids);
1051
 
1052
                return array($count_imported_oids, $count_already_existing, $count_errors, $count_warnings);
1053
 
1054
        }
1055
 
1056
}