Subversion Repositories oidplus

Rev

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

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