Subversion Repositories oidplus

Rev

Rev 790 | Rev 830 | 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
758 daniel-mar 5
 * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft
635 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
 
20
require_once __DIR__ . '/../../../../../includes/oidplus.inc.php';
21
 
762 daniel-mar 22
//define('XML_URN', 'urn:oid:1.3.6.1.4.1.37476.2.5.2.5.1.1');
23
define('XML_URN', 'urn:ietf:id:viathinksoft-oidip-02');
24
 
25
// define('XML_URN_URL', 'https://oidplus.viathinksoft.com/oidplus/plugins/publicPages/100_whois/whois/xml_schema.xsd');
801 daniel-mar 26
define('XML_URN_URL', OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'xml_schema.xsd');
762 daniel-mar 27
 
635 daniel-mar 28
OIDplus::init(true);
29
set_exception_handler(array('OIDplusGui', 'html_exception_handler'));
30
 
31
if (OIDplus::baseConfig()->getValue('DISABLE_PLUGIN_OIDplusPagePublicWhois', false)) {
32
        throw new OIDplusException(_L('This plugin was disabled by the system administrator!'));
33
}
34
 
35
originHeaders();
36
 
37
// Step 0: Get request parameter
38
 
39
if (PHP_SAPI == 'cli') {
40
        if ($_SERVER['argc'] != 2) {
41
                echo _L('Syntax').': '.$_SERVER['argv'][0].' <query>'."\n";
42
                exit(2);
43
        }
44
        $query = $_SERVER['argv'][1];
45
} else {
46
        if (!isset($_REQUEST['query'])) {
47
                http_response_code(400);
48
                die('<h1>'._L('Error').'</h1><p>'._L('Argument "%1" is missing','query').'<p>');
49
        }
50
        $query = $_REQUEST['query'];
51
}
52
 
53
// Split input into query, authTokens and serverCommands
54
$tokens = explode('$', $query);
55
$query = array_shift($tokens);
56
$authTokens[] = array();
57
$serverCommands = array();
58
foreach ($tokens as $token) {
59
        if (strpos($token,'=') !== false) {
60
                $tmp = explode('=',$token,2);
61
                $serverCommands[strtolower($tmp[0])] = $tmp[1];
62
        } else {
63
                $authTokens[] = $token;
64
        }
65
}
66
 
67
$query = str_replace('oid:.', 'oid:', $query); // allow leading dot
68
 
765 daniel-mar 69
if (isset($_REQUEST['format'])) {
70
        $format = $_REQUEST['format'];
71
} else if (isset($serverCommands['format'])) {
72
        $format = $serverCommands['format'];
73
} else {
74
        $format = 'text'; // default
75
}
76
 
77
$unimplemented_format = ($format != 'text') && ($format != 'json') && ($format != 'xml');
78
if ($unimplemented_format) {
79
        $format = 'text';
80
}
81
 
635 daniel-mar 82
// Step 1: Collect data
83
 
84
$out = array();
85
 
86
$out[] = "query: $query";
87
 
775 daniel-mar 88
$query = OIDplus::prefilterQuery($query, false);
773 daniel-mar 89
 
765 daniel-mar 90
if ($unimplemented_format) {
91
        $out[] = 'result: Service error';
92
        $out[] = 'message: Format is not implemented';
93
} else {
635 daniel-mar 94
 
765 daniel-mar 95
        $distance = null;
96
        $found = null;
635 daniel-mar 97
 
765 daniel-mar 98
        try {
99
                $obj = OIDplusObject::findFitting($query);
100
                if (!$obj) $obj = OIDplusObject::parse($query); // in case we didn't find anything fitting, we take it as it is and later use getParent() to find something else
101
                $query = $obj->nodeId();
102
        } catch (Exception $e) {
103
                $obj = null;
104
        }
635 daniel-mar 105
 
765 daniel-mar 106
        $only_wellknown_ids_found = false;
635 daniel-mar 107
        $continue = false;
108
 
765 daniel-mar 109
        if (!$obj) {
110
                $out[] = "result: Not found"; // DO NOT TRANSLATE!
111
                $continue = false;
112
                $res = null;
113
        } else {
114
                $obj = null;
115
                $distance = 0;
635 daniel-mar 116
 
765 daniel-mar 117
                $init_query = $query;
635 daniel-mar 118
                while (true) {
765 daniel-mar 119
                        $res = OIDplus::db()->query("select * from ###objects where id = ?", array($query));
790 daniel-mar 120
                        if ($res->any()) {
635 daniel-mar 121
                                $obj = OIDplusObject::parse($query);
122
                                if ($distance > 0) {
123
                                        $out[] = "result: Not found; superior object found"; // DO NOT TRANSLATE!
124
                                        $out[] = "distance: $distance"; // DO NOT TRANSLATE
125
                                } else {
126
                                        $out[] = "result: Found"; // DO NOT TRANSLATE!
127
                                }
128
                                $continue = true;
129
                                break;
130
                        }
131
 
765 daniel-mar 132
                        if (substr($query,0,4) === 'oid:') {
133
                                $query_prev = $query;
134
                                $query = 'oid:'.oid_up(explode(':',$query,2)[1]);
135
                                if ($query == $query_prev) break;
136
                                $distance++;
137
                        } else {
138
                                // getParent() will find the parent which DOES exist in the DB.
139
                                // It does not need to be the direct parent (like ->one_up() does)
140
                                $obj = OIDplusObject::parse($query)->getParent(); // For objects, we assume that they are parents of each other
141
                                if ($obj) {
142
                                        $res = OIDplus::db()->query("select * from ###objects where id = ?", array($obj->nodeId()));
143
                                        $distance = $obj->distance($query);
790 daniel-mar 144
                                        assert($res->any());
635 daniel-mar 145
 
765 daniel-mar 146
                                        $query = $obj->nodeId();
147
                                }
635 daniel-mar 148
 
765 daniel-mar 149
                                if ($distance > 0) {
150
                                        $out[] = "result: Not found; superior object found"; // DO NOT TRANSLATE!
151
                                        $out[] = "distance: $distance"; // DO NOT TRANSLATE
152
                                }
153
                                $continue = true;
154
 
155
                                break;
156
                        }
635 daniel-mar 157
                }
158
 
765 daniel-mar 159
                if ((substr($query,0,4) === 'oid:') && (!$obj)) {
160
                        $query = $init_query;
161
                        $distance = 0;
162
                        while (true) {
163
                                $res = OIDplus::db()->query("select * from ###asn1id where oid = ? union select * from ###iri where oid = ?", array($query, $query));
790 daniel-mar 164
                                if ($res->any()) {
765 daniel-mar 165
                                        $obj = OIDplusObject::parse($query);
166
                                        $res = null;
167
                                        if ($distance > 0) {
168
                                                $out[] = "result: Not found; superior object found"; // DO NOT TRANSLATE!
169
                                                $out[] = "distance: $distance"; // DO NOT TRANSLATE
170
                                        } else {
171
                                                $out[] = "result: Found"; // DO NOT TRANSLATE!
172
                                        }
173
                                        $only_wellknown_ids_found = true; // Information partially available
174
                                        $continue = true;
175
                                        break;
176
                                }
177
                                $query_prev = $query;
178
                                $query = 'oid:'.oid_up(explode(':',$query,2)[1]);
179
                                if ($query == $query_prev) break;
180
                                $distance++;
181
                        }
182
                }
635 daniel-mar 183
 
765 daniel-mar 184
                if (!$obj) {
185
                        $out[] = "result: Not found"; // DO NOT TRANSLATE!
186
                        $continue = false;
635 daniel-mar 187
                }
188
 
765 daniel-mar 189
                $found = $distance == 0;
190
        }
635 daniel-mar 191
 
765 daniel-mar 192
        if ($continue) {
193
                $out[] = "";
194
                $out[] = "object: $query"; // DO NOT TRANSLATE!
195
                if (!allowObjectView($obj, $authTokens)) {
196
                        $out[] = "status: Information unavailable"; // DO NOT TRANSLATE!
197
                        $out[] = "attribute: confidential"; // DO NOT TRANSLATE!
198
                } else {
199
                        if ($only_wellknown_ids_found) {
200
                                $out[] = "status: Information partially available"; // DO NOT TRANSLATE!
201
                        } else {
202
                                $out[] = "status: Information available"; // DO NOT TRANSLATE!
635 daniel-mar 203
                        }
204
 
765 daniel-mar 205
                        $row = $res ? $res->fetch_object() : null;
635 daniel-mar 206
 
765 daniel-mar 207
                        if (!is_null($row)) {
208
                                $out[] = 'name: ' . $row->title; // DO NOT TRANSLATE!
635 daniel-mar 209
 
765 daniel-mar 210
                                $cont = $row->description;
211
                                $cont = preg_replace('@<a[^>]+href\s*=\s*["\']([^\'"]+)["\'][^>]*>(.+)<\s*/\s*a\s*>@ismU', '\2 (\1)', $cont);
212
                                $cont = preg_replace('@<br.*>@', "\n", $cont);
213
                                $cont = preg_replace('@\\n+@', "\n", $cont);
214
                                $out[] = 'description: ' . trim(html_entity_decode(strip_tags($cont))); // DO NOT TRANSLATE!
635 daniel-mar 215
                        }
216
 
765 daniel-mar 217
                        if (substr($query,0,4) === 'oid:') {
218
                                $out[] = 'asn1-notation: ' . $obj->getAsn1Notation(false); // DO NOT TRANSLATE!
219
                                $out[] = 'iri-notation: ' . $obj->getIriNotation(false); // DO NOT TRANSLATE!
635 daniel-mar 220
 
765 daniel-mar 221
                                $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($obj->nodeId()));
222
                                while ($row2 = $res2->fetch_object()) {
223
                                        $out[] = 'identifier: ' . $row2->name; // DO NOT TRANSLATE!
224
                                }
730 daniel-mar 225
 
765 daniel-mar 226
                                $res2 = OIDplus::db()->query("select * from ###asn1id where standardized = ? and oid = ?", array(true, $obj->nodeId()));
227
                                while ($row2 = $res2->fetch_object()) {
228
                                        $out[] = 'standardized-id: ' . $row2->name; // DO NOT TRANSLATE!
229
                                }
635 daniel-mar 230
 
765 daniel-mar 231
                                $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($obj->nodeId()));
232
                                while ($row2 = $res2->fetch_object()) {
233
                                        $out[] = 'unicode-label: ' . $row2->name; // DO NOT TRANSLATE!
234
                                }
635 daniel-mar 235
 
765 daniel-mar 236
                                $res2 = OIDplus::db()->query("select * from ###iri where longarc = ? and oid = ?", array(true, $obj->nodeId()));
237
                                while ($row2 = $res2->fetch_object()) {
238
                                        $out[] = 'long-arc: ' . $row2->name; // DO NOT TRANSLATE!
239
                                }
635 daniel-mar 240
                        }
241
 
765 daniel-mar 242
                        if ($obj->isConfidential()) { // yes, we use isConfidential() instead of allowObjectView()!
243
                                $out[] = 'attribute: confidential'; // DO NOT TRANSLATE!
635 daniel-mar 244
                        }
245
 
765 daniel-mar 246
                        if ($obj->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
247
                                // Also ask $obj for extra attributes:
248
                                // This way we could add various additional information, e.g. IPv4/6 range analysis, interpretation of GUID, etc. (TODO)
249
                                $obj->whoisObjectAttributes($obj->nodeId(), $out);
250
                        }
635 daniel-mar 251
 
765 daniel-mar 252
                        foreach (OIDplus::getPagePlugins() as $plugin) {
253
                                if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
254
                                        $plugin->whoisObjectAttributes($obj->nodeId(), $out);
255
                                }
256
                        }
635 daniel-mar 257
 
765 daniel-mar 258
                        if (substr($query,0,4) === 'oid:') {
259
                                $sParent = 'oid:'.oid_up(explode(':',$query,2)[1]);
635 daniel-mar 260
 
765 daniel-mar 261
                                $objTest = OIDplusObject::parse($sParent);
262
                                if (allowObjectView($objTest, $authTokens)) {
263
                                        $out[] = 'parent: ' . $sParent . show_asn1_appendix($sParent); // DO NOT TRANSLATE!
264
                                } else {
265
                                        $out[] = 'parent: ' . $sParent; // DO NOT TRANSLATE!
266
                                }
267
                        } else if (!is_null($row) && !empty($row->parent) && (!is_root($row->parent))) {
268
                                $sParent = $row->parent;
269
                                $out[] = 'parent: ' . $row->parent; // DO NOT TRANSLATE!
270
                        }
635 daniel-mar 271
 
765 daniel-mar 272
                        $res2 = OIDplus::db()->query("select * from ###objects where parent = ? order by ".OIDplus::db()->natOrder('id'), array($obj->nodeId()));
273
                        while ($row2 = $res2->fetch_object()) {
274
                                $objTest = OIDplusObject::parse($row2->id);
275
                                if (allowObjectView($objTest, $authTokens)) {
276
                                        $out[] = 'subordinate: ' . $row2->id . show_asn1_appendix($row2->id); // DO NOT TRANSLATE!
277
                                } else {
278
                                        $out[] = 'subordinate: ' . $row2->id; // DO NOT TRANSLATE!
635 daniel-mar 279
                                }
280
                        }
730 daniel-mar 281
 
765 daniel-mar 282
                        if (!is_null($row)) {
283
                                if ($row->created) $out[] = 'created: ' . date('Y-m-d H:i:s', strtotime($row->created)); // DO NOT TRANSLATE!
284
                                if ($row->updated) $out[] = 'updated: ' . date('Y-m-d H:i:s', strtotime($row->updated)); // DO NOT TRANSLATE!
730 daniel-mar 285
                        }
286
 
765 daniel-mar 287
                        $out[] = '';
288
 
289
                        $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array(is_null($row) ? '' : $row->ra_email));
290
                        if ($row2 = $res2->fetch_object()) {
291
                                $out[] = 'ra: '.(!empty($row2->ra_name) ? $row2->ra_name : (!empty($row2->email) ? $row2->email : _L('Unknown'))); // DO NOT TRANSLATE!
292
                                $out[] = 'ra-status: Information available'; // DO NOT TRANSLATE!
293
 
294
                                $tmp = array();
295
                                if (!empty($row2->office)) $tmp[] = $row2->office;
296
                                if (!empty($row2->organization)) $tmp[] = $row2->organization;
297
                                $tmp = implode(', ', $tmp);
298
 
299
                                $out[] = 'ra-contact-name: ' . $row2->personal_name.(!empty($tmp) ? " ($tmp)" : ''); // DO NOT TRANSLATE!
300
                                if (!allowRAView($row2, $authTokens)) {
301
                                        if (!empty($row2->street) || !empty($row2->zip_town) || !empty($row2->country)) {
302
                                                $out[] = 'ra-address: '._L('(redacted)'); // DO NOT TRANSLATE!
303
                                        }
304
                                        $out[] = 'ra-phone: ' . (!empty($row2->phone) ? _L('(redacted)') : ''); // DO NOT TRANSLATE!
305
                                        $out[] = 'ra-mobile: ' . (!empty($row2->mobile) ? _L('(redacted)') : ''); // DO NOT TRANSLATE!
306
                                        $out[] = 'ra-fax: ' . (!empty($row2->fax) ? _L('(redacted)') : ''); // DO NOT TRANSLATE!
307
                                } else {
308
                                        if (!empty($row2->street))   $out[] = 'ra-address: ' . $row2->street; // DO NOT TRANSLATE!
309
                                        if (!empty($row2->zip_town)) $out[] = 'ra-address: ' . $row2->zip_town; // DO NOT TRANSLATE!
310
                                        if (!empty($row2->country))  $out[] = 'ra-address: ' . $row2->country; // DO NOT TRANSLATE!
311
                                        $out[] = 'ra-phone: ' . $row2->phone; // DO NOT TRANSLATE!
312
                                        $out[] = 'ra-mobile: ' . $row2->mobile; // DO NOT TRANSLATE!
313
                                        $out[] = 'ra-fax: ' . $row2->fax; // DO NOT TRANSLATE!
635 daniel-mar 314
                                }
765 daniel-mar 315
                                $out[] = 'ra-email: ' . $row->ra_email; // DO NOT TRANSLATE!
635 daniel-mar 316
 
765 daniel-mar 317
                                $ra = new OIDplusRA($row->ra_email);
318
                                if ($ra->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
319
                                        $ra->whoisRaAttributes($row->ra_email, $out); /** @phpstan-ignore-line */
320
                                }
635 daniel-mar 321
 
322
                                foreach (OIDplus::getPagePlugins() as $plugin) {
323
                                        if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
324
                                                $plugin->whoisRaAttributes($row->ra_email, $out);
325
                                        }
326
                                }
765 daniel-mar 327
 
328
                                if ($row2->privacy) { // yes, we use row2->privacy() instead of allowRAView()!
329
                                        $out[] = 'ra-attribute: confidential'; // DO NOT TRANSLATE!
330
                                }
331
 
332
                                if ($row2->registered) $out[] = 'ra-created: ' . date('Y-m-d H:i:s', strtotime($row2->registered)); // DO NOT TRANSLATE!
333
                                if ($row2->updated)    $out[] = 'ra-updated: ' . date('Y-m-d H:i:s', strtotime($row2->updated)); // DO NOT TRANSLATE!
334
                        } else {
335
                                $out[] = 'ra: '.(!is_null($row) && !empty($row->ra_email) ? $row->ra_email : _L('Unknown')); // DO NOT TRANSLATE!
336
                                if (!is_null($row)) {
337
                                        foreach (OIDplus::getPagePlugins() as $plugin) {
338
                                                if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
339
                                                        $plugin->whoisRaAttributes($row->ra_email, $out);
340
                                                }
341
                                        }
342
                                }
343
                                $out[] = "ra-status: Information unavailable"; // DO NOT TRANSLATE!
635 daniel-mar 344
                        }
345
                }
346
        }
347
}
348
 
349
// Step 2: Format output
350
 
765 daniel-mar 351
if ($format == 'text') {
635 daniel-mar 352
        header('Content-Type:text/plain; charset=UTF-8');
353
 
354
        $longest_key = 0;
355
        foreach ($out as $line) {
356
                $longest_key = max($longest_key, strlen(trim(explode(':',$line,2)[0])));
357
        }
358
 
359
        ob_start();
360
 
361
        //echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\r\n";
362
 
363
        foreach ($out as $line) {
364
                if (trim($line) == '') {
365
                        echo "\r\n";
366
                        continue;
367
                }
368
 
369
                $ary = explode(':', $line, 2);
370
 
371
                $key = trim($ary[0]);
372
 
373
                $value = isset($ary[1]) ? trim($ary[1]) : '';
674 daniel-mar 374
 
375
                // Normalize line-breaks to \r\n, otherwise mb_wordwrap won't work correctly
376
                $value = str_replace("\r\n", "\n", $value);
377
                $value = str_replace("\r", "\n", $value);
378
                $value = str_replace("\n", "\r\n", $value);
379
 
635 daniel-mar 380
                $value = mb_wordwrap($value, OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80) - $longest_key - strlen(':') - OIDplus::config()->getValue('webwhois_output_format_spacer', 2), "\r\n");
381
                $value = str_replace("\r\n", "\r\n$key:".str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)), $value);
382
 
383
                if (!empty($value)) {
384
                        echo $key.':' . str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)) . $value . "\r\n";
385
                }
386
        }
387
 
388
        //echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\r\n";
389
 
390
        $cont = ob_get_contents();
391
        ob_end_clean();
392
 
393
        echo $cont;
394
 
395
        if (OIDplus::getPkiStatus()) {
396
                $signature = '';
397
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
398
                        $signature = base64_encode($signature);
399
                        $signature = mb_wordwrap($signature, OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80) - strlen('% '), "\r\n", true);
400
                        $signature = "% -----BEGIN RSA SIGNATURE-----\r\n".
401
                                     preg_replace('/^/m', '% ', $signature)."\r\n".
402
                                     "% -----END RSA SIGNATURE-----\r\n";
403
                        echo $signature;
404
                }
405
        }
406
}
407
 
408
if ($format == 'json') {
409
        $ary = array();
410
 
411
        $current_section = array();
412
        $ary[] = &$current_section;
413
 
414
        foreach ($out as $line) {
415
                if ($line == '') {
416
                        unset($current_section);
417
                        $current_section = array();
418
                        $ary[] = &$current_section;
419
                } else {
420
                        list($key,$val) = explode(':', $line, 2);
421
                        $val = trim($val);
422
                        if (!empty($val)) {
423
                                if (!isset($current_section[$key])) {
424
                                        $current_section[$key] = $val;
425
                                } elseif (is_array($current_section[$key])) {
426
                                        $current_section[$key][] = $val;
427
                                } else {
428
                                        $current_section[$key] = array($current_section[$key], $val);
429
                                }
430
                        }
431
                }
432
        }
433
        $ary = array(
434
                // https://code.visualstudio.com/docs/languages/json#_mapping-in-the-json
435
                // Note that this syntax is VS Code-specific and not part of the JSON Schema specification.
436
                //'$schema' => 'https://oidplus.viathinksoft.com/oidplus/plugins/publicPages/100_whois/whois/json_schema.json',
801 daniel-mar 437
                '$schema' => OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'json_schema.json',
635 daniel-mar 438
 
439
                // we need this NAMED root, otherwise PHP will name the sections "0", "1", "2" if the array is not sequencial (e.g. because "signature" is added)
758 daniel-mar 440
                'oidip' => $ary
635 daniel-mar 441
        );
442
 
443
        if (OIDplus::getPkiStatus()) {
444
                $cont = json_encode($ary);
445
                $signature = '';
446
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
447
                        $signature = base64_encode($signature);
448
                        $ary['signature'] = array('content' => $cont, 'signature' => $signature);
449
                }
450
        }
451
 
452
        // Good JSON schema validator here: https://www.jsonschemavalidator.net
453
        header('Content-Type:application/json; charset=UTF-8');
454
        echo json_encode($ary);
455
}
456
 
457
if ($format == 'xml') {
758 daniel-mar 458
        $xml = '<oidip><section>';
635 daniel-mar 459
        foreach ($out as $line) {
460
                if ($line == '') {
461
                        $xml .= '</section><section>';
462
                } else {
463
                        list($key,$val) = explode(':', $line, 2);
464
                        $val = trim($val);
465
                        if (!empty($val)) {
466
                                $xml .= "<$key>".htmlspecialchars($val)."</$key>";
467
                        }
468
                }
469
        }
758 daniel-mar 470
        $xml .= '</section></oidip>';
635 daniel-mar 471
 
472
        $xml = preg_replace('@<section><(.+)>(.+)</section>@ismU', '<\\1Section><\\1>\\2</\\1Section>', $xml);
473
 
474
        if (OIDplus::getPkiStatus()) {
475
                $cont = $xml;
476
                $signature = '';
477
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
478
                        $signature = base64_encode($signature);
760 daniel-mar 479
                        $cdata = '<![CDATA['.str_replace(']]>', ']]]]><![CDATA[>', $cont).']]>';
480
                        $xml .= "<signatureSection><content>".$cdata."</content><signature>".htmlspecialchars($signature)."</signature></signatureSection>";
635 daniel-mar 481
                }
482
        }
483
 
484
        // Good XSD validator here: https://www.liquid-technologies.com/online-xsd-validator
485
        header('Content-Type:application/xml; charset=UTF-8');
486
        echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
762 daniel-mar 487
        echo '<root xmlns="'.XML_URN.'"';
635 daniel-mar 488
        echo '      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
762 daniel-mar 489
        echo '      xsi:schemaLocation="'.XML_URN.' '.XML_URN_URL.'">';
635 daniel-mar 490
        echo $xml;
491
        echo '</root>';
492
}
493
 
494
# ---
495
 
496
function show_asn1_appendix($id) {
497
        if (substr($id,0,4) === 'oid:') {
498
                $appendix_asn1ids = array();
499
                $res3 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($id));
500
                while ($row3 = $res3->fetch_object()) {
501
                        $appendix_asn1ids[] = $row3->name;
502
                }
503
 
504
                $appendix = implode(', ', $appendix_asn1ids);
505
                if (!empty($appendix)) $appendix = " ($appendix)";
506
        } else {
507
                $appendix = '';
508
        }
509
        return $appendix;
510
}
511
 
512
function is_root($id) {
513
        return empty(explode(':',$id,2)[1]);
514
}
515
 
516
function authTokenAccepted($content, $authTokens) {
517
        foreach ($authTokens as $token) {
518
                if (OIDplusPagePublicWhois::genWhoisAuthToken($content) == $token) return true;
519
        }
520
        return false;
521
}
522
 
523
function allowObjectView($obj, $authTokens) {
524
        // Master auth token
525
        $authToken = trim(OIDplus::config()->getValue('whois_auth_token'));
526
        if (empty($authToken)) $authToken = false;
527
        if ($authToken && in_array($authToken, $authTokens)) return true;
528
 
529
        // Per-OID auth tokens
530
        $curid = $obj->nodeId();
790 daniel-mar 531
        while (($res = OIDplus::db()->query("select parent, confidential from ###objects where id = ?", array($curid)))->any()) {
635 daniel-mar 532
                $row = $res->fetch_array();
533
                // Example: You have an auth Token for 2.999.1.2.3
534
                // This allows you to view 2.999.1.2.3 and all of its children,
535
                // as long as they are not confidential (then you need their auth token).
536
                // 2, 2.999, 2.999.1 and 2.999.1.2 are visible,
537
                // (because their existence is now obvious).
538
                if ($row['confidential'] && !authTokenAccepted($curid, $authTokens)) return false;
539
                $curid = $row['parent'];
540
        }
541
 
542
        // Allow
543
        return true;
544
}
545
 
546
function allowRAView($row, $authTokens) {
547
        // Master auth token
548
        $authToken = trim(OIDplus::config()->getValue('whois_auth_token'));
549
        if (empty($authToken)) $authToken = false;
550
        if ($authToken && in_array($authToken, $authTokens)) return true;
551
 
552
        // Per-RA auth tokens
553
        if ($row->privacy && !authTokenAccepted('ra:'.$row->ra_name, $authTokens)) return false;
554
 
555
        // Allow
556
        return true;
557
}