Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
101 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
5
 * Copyright 2019 Daniel Marschall, ViaThinkSoft
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
require_once __DIR__ . '/../../../../includes/oidplus.inc.php';
21
 
22
OIDplus::init(true);
23
 
180 daniel-mar 24
originHeaders();
101 daniel-mar 25
 
26
// Step 0: Get request parameter
27
 
28
if (php_sapi_name() == 'cli') {
386 daniel-mar 29
        if ($_SERVER['argc'] != 2) {
30
                echo _L('Syntax').': '.$_SERVER['argv'][0].' <query>'."\n";
101 daniel-mar 31
                exit(2);
32
        }
386 daniel-mar 33
        $query = $_SERVER['argv'][1];
101 daniel-mar 34
} else {
35
        if (!isset($_REQUEST['query'])) {
36
                http_response_code(400);
360 daniel-mar 37
                die('<h1>'._L('Error').'</h1><p>'._L('Argument "%1" is missing','query').'<p>');
101 daniel-mar 38
        }
39
        $query = $_REQUEST['query'];
40
}
41
 
42
$authTokens = explode('$', $query);
43
$query = array_shift($authTokens);
104 daniel-mar 44
 
45
$authToken = trim(OIDplus::config()->getValue('whois_auth_token'));
46
if (empty($authToken)) $authToken = false;
47
 
101 daniel-mar 48
$show_confidential = $authToken && in_array($authToken, $authTokens);
49
 
50
$query = str_replace('oid:.', 'oid:', $query); // allow leading dot
51
 
52
// Step 1: Collect data
53
 
54
$out = array();
55
 
56
$out[] = "query: $query";
57
 
58
$distance = null;
59
$found = null;
60
 
61
try {
62
        $obj = OIDplusObject::findFitting($query);
63
        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
64
} catch (Exception $e) {
65
        $obj = null;
66
}
67
 
68
if (!$obj) {
69
        $found = false;
70
} else {
71
        $query = $obj->nodeId(); // this may sanitize/canonize identifiers
261 daniel-mar 72
        $res = OIDplus::db()->query("select * from ###objects where id = ?", array($obj->nodeId()));
236 daniel-mar 73
        if ($res->num_rows() > 0) {
101 daniel-mar 74
                $found = true;
75
                $distance = 0;
76
        } else {
77
                $found = false;
78
                $objParent = OIDplusObject::parse($query)->getParent();
79
                if ($objParent) {
261 daniel-mar 80
                        $res = OIDplus::db()->query("select * from ###objects where id = ?", array($objParent->nodeId()));
101 daniel-mar 81
                        $distance = $objParent->distance($query);
236 daniel-mar 82
                        assert($res->num_rows() > 0);
101 daniel-mar 83
 
84
                        $query = $objParent->nodeId();
85
                        $obj = $objParent;
86
                }
87
        }
88
}
89
 
90
$continue = null;
91
if (!$found) {
92
        if (!is_null($distance)) {
360 daniel-mar 93
                $out[] = "result: Not found; superior object found"; // DO NOT TRANSLATE!
94
                $out[] = "distance: $distance"; // DO NOT TRANSLATE
101 daniel-mar 95
                $continue = true;
96
        } else {
360 daniel-mar 97
                $out[] = "result: Not found"; // DO NOT TRANSLATE!
101 daniel-mar 98
                $continue = false;
99
        }
100
} else {
360 daniel-mar 101
        $out[] = "result: Found"; // DO NOT TRANSLATE!
101 daniel-mar 102
        $continue = true;
103
}
104
 
105
if ($continue) {
106
        $out[] = "";
360 daniel-mar 107
        $out[] = "object: $query"; // DO NOT TRANSLATE!
101 daniel-mar 108
        if ($obj->isConfidential() && !$show_confidential) {
360 daniel-mar 109
                $out[] = "status: Information unavailable"; // DO NOT TRANSLATE!
110
                $out[] = "attribute: confidential"; // DO NOT TRANSLATE!
101 daniel-mar 111
        } else {
360 daniel-mar 112
                $out[] = "status: Information available"; // DO NOT TRANSLATE!
101 daniel-mar 113
 
262 daniel-mar 114
                $row = $res->fetch_object();
115
                assert($row);
101 daniel-mar 116
                $obj = OIDplusObject::parse($row->id);
117
 
360 daniel-mar 118
                $out[] = 'name: ' . $row->title; // DO NOT TRANSLATE!
337 daniel-mar 119
 
120
                $cont = $row->description;
121
                $cont = preg_replace('@<a[^>]+href\s*=\s*["\']([^\'"]+)["\'][^>]*>(.+)<\s*/\s*a\s*>@ismU', '\2 (\1)', $cont);
122
                $cont = preg_replace('@<br.*>@', "\n", $cont);
123
                $cont = preg_replace('@\\n+@', "\n", $cont);
360 daniel-mar 124
                $out[] = 'description: ' . trim(html_entity_decode(strip_tags($cont))); // DO NOT TRANSLATE!
337 daniel-mar 125
 
101 daniel-mar 126
                if (substr($query,0,4) === 'oid:') {
360 daniel-mar 127
                        $out[] = 'asn1-notation: ' . $obj->getAsn1Notation(false); // DO NOT TRANSLATE!
128
                        $out[] = 'iri-notation: ' . $obj->getIriNotation(false); // DO NOT TRANSLATE!
337 daniel-mar 129
 
261 daniel-mar 130
                        $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
236 daniel-mar 131
                        while ($row2 = $res2->fetch_object()) {
360 daniel-mar 132
                                $out[] = 'identifier: ' . $row2->name; // DO NOT TRANSLATE!
101 daniel-mar 133
                        }
134
 
261 daniel-mar 135
                        $res2 = OIDplus::db()->query("select * from ###asn1id where standardized = ? and oid = ?", array(true, $row->id));
236 daniel-mar 136
                        while ($row2 = $res2->fetch_object()) {
360 daniel-mar 137
                                $out[] = 'standardized-id: ' . $row2->name; // DO NOT TRANSLATE!
101 daniel-mar 138
                        }
139
 
261 daniel-mar 140
                        $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
236 daniel-mar 141
                        while ($row2 = $res2->fetch_object()) {
360 daniel-mar 142
                                $out[] = 'unicode-label: ' . $row2->name; // DO NOT TRANSLATE!
101 daniel-mar 143
                        }
144
 
261 daniel-mar 145
                        $res2 = OIDplus::db()->query("select * from ###iri where longarc = ? and oid = ?", array(true, $row->id));
236 daniel-mar 146
                        while ($row2 = $res2->fetch_object()) {
360 daniel-mar 147
                                $out[] = 'long-arc: ' . $row2->name; // DO NOT TRANSLATE!
101 daniel-mar 148
                        }
149
                }
336 daniel-mar 150
 
337 daniel-mar 151
                // TODO: Field "attribute: confidential" if OID is hidden
336 daniel-mar 152
 
337 daniel-mar 153
                foreach (OIDplus::getPagePlugins() as $plugin) {
154
                        if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
155
                                $plugin->whoisObjectAttributes($row->id, $out);
156
                        }
157
                }
336 daniel-mar 158
 
159
                if (!empty($row->parent) && (!is_root($row->parent))) {
360 daniel-mar 160
                        $out[] = 'parent: ' . $row->parent . show_asn1_appendix($row->parent); // DO NOT TRANSLATE!
322 daniel-mar 161
                }
101 daniel-mar 162
 
261 daniel-mar 163
                $res2 = OIDplus::db()->query("select * from ###objects where parent = ? order by ".OIDplus::db()->natOrder('id'), array($row->id));
236 daniel-mar 164
                if ($res2->num_rows() == 0) {
101 daniel-mar 165
                        // $out[] = 'subordinate: (none)';
166
                }
236 daniel-mar 167
                while ($row2 = $res2->fetch_object()) {
360 daniel-mar 168
                        $out[] = 'subordinate: ' . $row2->id . show_asn1_appendix($row2->id); // DO NOT TRANSLATE!
101 daniel-mar 169
                }
170
 
360 daniel-mar 171
                $out[] = 'created: ' . $row->created; // DO NOT TRANSLATE!
172
                $out[] = 'updated: ' . $row->updated; // DO NOT TRANSLATE!
336 daniel-mar 173
 
101 daniel-mar 174
                $out[] = '';
175
 
261 daniel-mar 176
                $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
236 daniel-mar 177
                if ($row2 = $res2->fetch_object()) {
360 daniel-mar 178
                        $out[] = 'ra: '.(!empty($row2->ra_name) ? $row2->ra_name : (!empty($row2->email) ? $row2->email : _L('Unknown'))); // DO NOT TRANSLATE!
179
                        $out[] = 'ra-status: Information available'; // DO NOT TRANSLATE!
336 daniel-mar 180
 
181
                        $tmp = array();
182
                        if (!empty($row2->office)) $tmp[] = $row2->office;
183
                        if (!empty($row2->organization)) $tmp[] = $row2->organization;
184
                        $tmp = implode(', ', $tmp);
185
 
360 daniel-mar 186
                        $out[] = 'ra-contact-name: ' . $row2->personal_name.(!empty($tmp) ? " ($tmp)" : ''); // DO NOT TRANSLATE!
101 daniel-mar 187
                        if ($row2->privacy && !$show_confidential) {
336 daniel-mar 188
                                if (!empty($row2->street) || !empty($row2->zip_town) || !empty($row2->country)) {
360 daniel-mar 189
                                        $out[] = 'ra-address: '._L('(redacted)'); // DO NOT TRANSLATE!
336 daniel-mar 190
                                }
360 daniel-mar 191
                                $out[] = 'ra-phone: ' . (!empty($row2->phone) ? _L('(redacted)') : ''); // DO NOT TRANSLATE!
192
                                $out[] = 'ra-mobile: ' . (!empty($row2->mobile) ? _L('(redacted)') : ''); // DO NOT TRANSLATE!
193
                                $out[] = 'ra-fax: ' . (!empty($row2->fax) ? _L('(redacted)') : ''); // DO NOT TRANSLATE!
101 daniel-mar 194
                        } else {
360 daniel-mar 195
                                if (!empty($row2->street))   $out[] = 'ra-address: ' . $row2->street; // DO NOT TRANSLATE!
196
                                if (!empty($row2->zip_town)) $out[] = 'ra-address: ' . $row2->zip_town; // DO NOT TRANSLATE!
197
                                if (!empty($row2->country))  $out[] = 'ra-address: ' . $row2->country; // DO NOT TRANSLATE!
198
                                $out[] = 'ra-phone: ' . $row2->phone; // DO NOT TRANSLATE!
199
                                $out[] = 'ra-mobile: ' . $row2->mobile; // DO NOT TRANSLATE!
200
                                $out[] = 'ra-fax: ' . $row2->fax; // DO NOT TRANSLATE!
101 daniel-mar 201
                        }
360 daniel-mar 202
                        $out[] = 'ra-email: ' . $row->ra_email; // DO NOT TRANSLATE!
322 daniel-mar 203
                        foreach (OIDplus::getPagePlugins() as $plugin) {
204
                                if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
205
                                        $plugin->whoisRaAttributes($row->ra_email, $out);
206
                                }
207
                        }
360 daniel-mar 208
                        $out[] = 'ra-created: ' . $row2->registered; // DO NOT TRANSLATE!
209
                        $out[] = 'ra-updated: ' . $row2->updated; // DO NOT TRANSLATE!
101 daniel-mar 210
                } else {
360 daniel-mar 211
                        $out[] = 'ra: '.(!empty($row->ra_email) ? $row->ra_email : _L('Unknown')); // DO NOT TRANSLATE!
322 daniel-mar 212
                        foreach (OIDplus::getPagePlugins() as $plugin) {
213
                                if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
214
                                        $plugin->whoisRaAttributes($row->ra_email, $out);
215
                                }
216
                        }
360 daniel-mar 217
                        $out[] = "ra-status: Information unavailable"; // DO NOT TRANSLATE!
101 daniel-mar 218
                }
219
        }
220
}
221
 
222
// Step 2: Format output
223
 
224
ob_start();
225
 
201 daniel-mar 226
$format = isset($_REQUEST['format']) ? $_REQUEST['format'] : 'txt';
101 daniel-mar 227
 
201 daniel-mar 228
if ($format == 'txt') {
229
        header('Content-Type:text/plain; charset=UTF-8');
101 daniel-mar 230
 
201 daniel-mar 231
        $longest_key = 0;
232
        foreach ($out as $line) {
233
                $longest_key = max($longest_key, strlen(trim(explode(':',$line,2)[0])));
101 daniel-mar 234
        }
235
 
332 daniel-mar 236
        //echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\n";
101 daniel-mar 237
 
201 daniel-mar 238
        foreach ($out as $line) {
239
                if (trim($line) == '') {
240
                        echo "\n";
241
                        continue;
242
                }
101 daniel-mar 243
 
201 daniel-mar 244
                $ary = explode(':', $line, 2);
101 daniel-mar 245
 
201 daniel-mar 246
                $key = trim($ary[0]);
247
 
322 daniel-mar 248
                $value = isset($ary[1]) ? trim($ary[1]) : '';
346 daniel-mar 249
                $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));
261 daniel-mar 250
                $value = str_replace("\n", "\n$key:".str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)), $value);
201 daniel-mar 251
 
339 daniel-mar 252
                if (!empty($value)) {
253
                        echo $key.':' . str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)) . $value . "\n";
254
                }
201 daniel-mar 255
        }
256
 
332 daniel-mar 257
        //echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\n";
201 daniel-mar 258
 
259
        $cont = ob_get_contents();
260
        ob_end_clean();
261
 
262
        echo $cont;
263
 
227 daniel-mar 264
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 265
                $signature = '';
239 daniel-mar 266
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 267
                        $signature = base64_encode($signature);
346 daniel-mar 268
                        $signature = mb_wordwrap($signature, OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80) - strlen('% '), "\n", true);
332 daniel-mar 269
                        $signature = "% -----BEGIN RSA SIGNATURE-----\n".
270
                                     preg_replace('/^/m', '% ', $signature)."\n".
271
                                     "% -----END RSA SIGNATURE-----\n";
201 daniel-mar 272
                        echo $signature;
273
                }
274
        }
101 daniel-mar 275
}
276
 
201 daniel-mar 277
if ($format == 'json') {
278
        $ary = array();
101 daniel-mar 279
 
201 daniel-mar 280
        $current_section = array();
281
        $ary[] = &$current_section;
101 daniel-mar 282
 
201 daniel-mar 283
        foreach ($out as $line) {
284
                if ($line == '') {
285
                        unset($current_section);
286
                        $current_section = array();
287
                        $ary[] = &$current_section;
288
                } else {
289
                        list($key,$val) = explode(':', $line, 2);
290
                        $val = trim($val);
339 daniel-mar 291
                        if (!empty($val)) {
292
                                if (!isset($current_section[$key])) {
293
                                        $current_section[$key] = $val;
294
                                } elseif (is_array($current_section[$key])) {
295
                                        $current_section[$key][] = $val;
296
                                } else {
297
                                        $current_section[$key] = array($current_section[$key], $val);
298
                                }
201 daniel-mar 299
                        }
300
                }
301
        }
331 daniel-mar 302
        $ary = array(
303
                // https://code.visualstudio.com/docs/languages/json#_mapping-in-the-json
304
                // Note that this syntax is VS Code-specific and not part of the JSON Schema specification.
305
                //'$schema' => 'https://oidplus.viathinksoft.com/oidplus/plugins/publicPages/100_whois/whois/json_schema.json',
306
                '$schema' => OIDplus::getSystemUrl().'plugins/publicPages/100_whois/whois/json_schema.json',
101 daniel-mar 307
 
331 daniel-mar 308
                // 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)
309
                'whois' => $ary
310
        );
311
 
227 daniel-mar 312
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 313
                $cont = json_encode($ary);
314
                $signature = '';
239 daniel-mar 315
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 316
                        $signature = base64_encode($signature);
317
                        $ary['signature'] = array('content' => $cont, 'signature' => $signature);
318
                }
319
        }
339 daniel-mar 320
 
321
        // Good JSON schema validator here: https://www.jsonschemavalidator.net
201 daniel-mar 322
        header('Content-Type:application/json; charset=UTF-8');
323
        echo json_encode($ary);
324
}
101 daniel-mar 325
 
201 daniel-mar 326
if ($format == 'xml') {
327
        $xml = '<whois><section>';
328
        foreach ($out as $line) {
329
                if ($line == '') {
330
                        $xml .= '</section><section>';
331
                } else {
332
                        list($key,$val) = explode(':', $line, 2);
333
                        $val = trim($val);
339 daniel-mar 334
                        if (!empty($val)) {
335
                                $xml .= "<$key>".htmlspecialchars($val)."</$key>";
336
                        }
201 daniel-mar 337
                }
338
        }
339
        $xml .= '</section></whois>';
101 daniel-mar 340
 
339 daniel-mar 341
        $xml = preg_replace('@<section><(.+)>(.+)</section>@ismU', '<\\1Section><\\1>\\2</\\1Section>', $xml);
342
 
227 daniel-mar 343
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 344
                $cont = $xml;
345
                $signature = '';
239 daniel-mar 346
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 347
                        $signature = base64_encode($signature);
348
                        $xml .= "<signature><content>".htmlspecialchars($cont)."</content><signature>".htmlspecialchars($signature)."</signature></signature>";
349
                }
101 daniel-mar 350
        }
201 daniel-mar 351
 
339 daniel-mar 352
        // Good XSD validator here: https://www.liquid-technologies.com/online-xsd-validator
201 daniel-mar 353
        header('Content-Type:application/xml; charset=UTF-8');
354
        echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
339 daniel-mar 355
        echo '<root xmlns="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.1.1"';
330 daniel-mar 356
        echo '      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
386 daniel-mar 357
        //echo '      xsi:schemaLocation="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.1.1 https://oidplus.viathinksoft.com/oidplus/plugins/publicPages/100_whois/whois/xml_schema.xsd">';
358
        echo '      xsi:schemaLocation="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.1.1 '.OIDplus::getSystemUrl().'plugins/publicPages/100_whois/whois/xml_schema.xsd">';
330 daniel-mar 359
        echo $xml;
360
        echo '</root>';
101 daniel-mar 361
}
362
 
363
# ---
364
 
365
function show_asn1_appendix($id) {
366
        if (substr($id,0,4) === 'oid:') {
367
                $appendix_asn1ids = array();
261 daniel-mar 368
                $res3 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($id));
236 daniel-mar 369
                while ($row3 = $res3->fetch_object()) {
101 daniel-mar 370
                        $appendix_asn1ids[] = $row3->name;
371
                }
372
 
373
                $appendix = implode(', ', $appendix_asn1ids);
374
                if (!empty($appendix)) $appendix = " ($appendix)";
375
        } else {
376
                $appendix = '';
377
        }
378
        return $appendix;
379
}
380
 
381
function is_root($id) {
382
        return empty(explode(':',$id,2)[1]);
360 daniel-mar 383
}