Subversion Repositories oidplus

Rev

Rev 331 | 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') {
29
        if ($argc != 2) {
30
                echo "Syntax: $argv[0] <query>\n";
31
                exit(2);
32
        }
33
        $query = $argv[1];
34
} else {
35
        if (!isset($_REQUEST['query'])) {
36
                http_response_code(400);
240 daniel-mar 37
                die("<h1>Error</h1><p>Argument 'query' is missing<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)) {
93
                $out[] = "result: Not found; superior object found";
94
                $out[] = "distance: $distance";
95
                $continue = true;
96
        } else {
97
                $out[] = "result: Not found";
98
                $continue = false;
99
        }
100
} else {
101
        $out[] = "result: Found";
102
        $continue = true;
103
}
104
 
105
if ($continue) {
106
        $out[] = "";
107
        $out[] = "object: $query";
108
        if ($obj->isConfidential() && !$show_confidential) {
109
                $out[] = "status: Confidential";
110
        } else {
125 daniel-mar 111
                $out[] = "status: Information available";
101 daniel-mar 112
 
262 daniel-mar 113
                $row = $res->fetch_object();
114
                assert($row);
101 daniel-mar 115
                $obj = OIDplusObject::parse($row->id);
116
 
117
                if (!empty($row->parent) && (!is_root($row->parent))) {
118
                        $out[] = 'parent: ' . $row->parent . show_asn1_appendix($row->parent);
119
                }
120
                $out[] = 'name: ' . $row->title;
121
 
122
                $cont = $row->description;
123
                $cont = preg_replace('@<a[^>]+href\s*=\s*["\']([^\'"]+)["\'][^>]*>(.+)<\s*/\s*a\s*>@ismU', '\2 (\1)', $cont);
332 daniel-mar 124
                $cont = preg_replace('@<br.*>@', "\n", $cont);
125
                $cont = preg_replace('@\\n+@', "\n", $cont);
101 daniel-mar 126
                $out[] = 'description: ' . trim(html_entity_decode(strip_tags($cont)));
127
 
128
                if (substr($query,0,4) === 'oid:') {
261 daniel-mar 129
                        $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
236 daniel-mar 130
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 131
                                $out[] = 'identifier: ' . $row2->name;
132
                        }
133
 
261 daniel-mar 134
                        $res2 = OIDplus::db()->query("select * from ###asn1id where standardized = ? and oid = ?", array(true, $row->id));
236 daniel-mar 135
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 136
                                $out[] = 'standardized-id: ' . $row2->name;
137
                        }
138
 
261 daniel-mar 139
                        $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
236 daniel-mar 140
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 141
                                $out[] = 'unicode-label: ' . $row2->name;
142
                        }
143
 
261 daniel-mar 144
                        $res2 = OIDplus::db()->query("select * from ###iri where longarc = ? and oid = ?", array(true, $row->id));
236 daniel-mar 145
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 146
                                $out[] = 'long-arc: ' . $row2->name;
147
                        }
148
                }
322 daniel-mar 149
                foreach (OIDplus::getPagePlugins() as $plugin) {
150
                        if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
151
                                $plugin->whoisObjectAttributes($row->id, $out);
152
                        }
153
                }
101 daniel-mar 154
                $out[] = 'created: ' . $row->created;
155
                $out[] = 'updated: ' . $row->updated;
156
 
261 daniel-mar 157
                $res2 = OIDplus::db()->query("select * from ###objects where parent = ? order by ".OIDplus::db()->natOrder('id'), array($row->id));
236 daniel-mar 158
                if ($res2->num_rows() == 0) {
101 daniel-mar 159
                        // $out[] = 'subordinate: (none)';
160
                }
236 daniel-mar 161
                while ($row2 = $res2->fetch_object()) {
101 daniel-mar 162
                        $out[] = 'subordinate: ' . $row2->id . show_asn1_appendix($row2->id);
163
                }
164
 
165
                $out[] = '';
166
 
261 daniel-mar 167
                $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
236 daniel-mar 168
                if ($row2 = $res2->fetch_object()) {
101 daniel-mar 169
                        $out[] = 'ra: '.(!empty($row2->ra_name) ? $row2->ra_name : $row2->email);
125 daniel-mar 170
                        $out[] = 'ra-status: Information available';
101 daniel-mar 171
                        $out[] = 'ra-name: ' . $row2->ra_name;
172
                        $out[] = 'ra-email: ' . $row->ra_email;
332 daniel-mar 173
                        $out[] = 'ra-personal-name: ' . $row2->personal_name; // Note: This is currently not in the RFC
101 daniel-mar 174
                        $out[] = 'ra-organization: ' . $row2->organization;
332 daniel-mar 175
                        $out[] = 'ra-office: ' . $row2->office; // Note: This is currently not in the RFC
101 daniel-mar 176
                        if ($row2->privacy && !$show_confidential) {
332 daniel-mar 177
                                // TODO: Follow new RFC draft and only return only "ra-address"
101 daniel-mar 178
                                $out[] = 'ra-street: ' . (!empty($row2->street) ? '(redacted)' : '');
179
                                $out[] = 'ra-town: ' . (!empty($row2->zip_town) ? '(redacted)' : '');
180
                                $out[] = 'ra-country: ' . (!empty($row2->country) ? '(redacted)' : '');
181
                                $out[] = 'ra-phone: ' . (!empty($row2->phone) ? '(redacted)' : '');
182
                                $out[] = 'ra-mobile: ' . (!empty($row2->mobile) ? '(redacted)' : '');
183
                                $out[] = 'ra-fax: ' . (!empty($row2->fax) ? '(redacted)' : '');
184
                        } else {
332 daniel-mar 185
                                // TODO: Follow new RFC draft and only return only "ra-address"
101 daniel-mar 186
                                $out[] = 'ra-street: ' . $row2->street;
330 daniel-mar 187
                                $out[] = 'ra-town: ' . $row2->zip_town;
101 daniel-mar 188
                                $out[] = 'ra-country: ' . $row2->country;
189
                                $out[] = 'ra-phone: ' . $row2->phone;
190
                                $out[] = 'ra-mobile: ' . $row2->mobile;
191
                                $out[] = 'ra-fax: ' . $row2->fax;
192
                        }
322 daniel-mar 193
                        foreach (OIDplus::getPagePlugins() as $plugin) {
194
                                if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
195
                                        $plugin->whoisRaAttributes($row->ra_email, $out);
196
                                }
197
                        }
101 daniel-mar 198
                        $out[] = 'ra-created: ' . $row2->registered;
199
                        $out[] = 'ra-updated: ' . $row2->updated;
200
                } else {
201
                        $out[] = 'ra: '.$row->ra_email;
322 daniel-mar 202
                        foreach (OIDplus::getPagePlugins() as $plugin) {
203
                                if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.4')) {
204
                                        $plugin->whoisRaAttributes($row->ra_email, $out);
205
                                }
206
                        }
125 daniel-mar 207
                        $out[] = "ra-status: Information unavailable";
101 daniel-mar 208
                }
209
        }
210
}
211
 
212
// Step 2: Format output
213
 
214
ob_start();
215
 
201 daniel-mar 216
$format = isset($_REQUEST['format']) ? $_REQUEST['format'] : 'txt';
101 daniel-mar 217
 
201 daniel-mar 218
if ($format == 'txt') {
219
        header('Content-Type:text/plain; charset=UTF-8');
101 daniel-mar 220
 
201 daniel-mar 221
        $longest_key = 0;
222
        foreach ($out as $line) {
223
                $longest_key = max($longest_key, strlen(trim(explode(':',$line,2)[0])));
101 daniel-mar 224
        }
225
 
332 daniel-mar 226
        //echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\n";
101 daniel-mar 227
 
201 daniel-mar 228
        foreach ($out as $line) {
229
                if (trim($line) == '') {
230
                        echo "\n";
231
                        continue;
232
                }
101 daniel-mar 233
 
201 daniel-mar 234
                $ary = explode(':', $line, 2);
101 daniel-mar 235
 
201 daniel-mar 236
                $key = trim($ary[0]);
237
 
322 daniel-mar 238
                $value = isset($ary[1]) ? trim($ary[1]) : '';
261 daniel-mar 239
                $value = wordwrap($value, OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80) - $longest_key - strlen(':') - OIDplus::config()->getValue('webwhois_output_format_spacer', 2));
240
                $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 241
 
261 daniel-mar 242
                echo $key.':' . str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)) . (!empty($value) ? $value : '.') . "\n";
201 daniel-mar 243
        }
244
 
332 daniel-mar 245
        //echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\n";
201 daniel-mar 246
 
247
        $cont = ob_get_contents();
248
        ob_end_clean();
249
 
250
        echo $cont;
251
 
227 daniel-mar 252
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 253
                $signature = '';
239 daniel-mar 254
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 255
                        $signature = base64_encode($signature);
332 daniel-mar 256
                        $signature = wordwrap($signature, 78, "\n", true);
257
                        $signature = "% -----BEGIN RSA SIGNATURE-----\n".
258
                                     preg_replace('/^/m', '% ', $signature)."\n".
259
                                     "% -----END RSA SIGNATURE-----\n";
201 daniel-mar 260
                        echo $signature;
261
                }
262
        }
101 daniel-mar 263
}
264
 
201 daniel-mar 265
if ($format == 'json') {
266
        $ary = array();
101 daniel-mar 267
 
201 daniel-mar 268
        $current_section = array();
269
        $ary[] = &$current_section;
101 daniel-mar 270
 
201 daniel-mar 271
        foreach ($out as $line) {
272
                if ($line == '') {
273
                        unset($current_section);
274
                        $current_section = array();
275
                        $ary[] = &$current_section;
276
                } else {
277
                        list($key,$val) = explode(':', $line, 2);
278
                        $val = trim($val);
279
                        if (!isset($current_section[$key])) {
280
                                $current_section[$key] = $val;
281
                        } elseif (is_array($current_section[$key])) {
282
                                $current_section[$key][] = $val;
283
                        } else {
284
                                $current_section[$key] = array($current_section[$key], $val);
285
                        }
286
                }
287
        }
331 daniel-mar 288
        $ary = array(
289
                // https://code.visualstudio.com/docs/languages/json#_mapping-in-the-json
290
                // Note that this syntax is VS Code-specific and not part of the JSON Schema specification.
291
                //'$schema' => 'https://oidplus.viathinksoft.com/oidplus/plugins/publicPages/100_whois/whois/json_schema.json',
292
                '$schema' => OIDplus::getSystemUrl().'plugins/publicPages/100_whois/whois/json_schema.json',
101 daniel-mar 293
 
331 daniel-mar 294
                // 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)
295
                'whois' => $ary
296
        );
297
 
227 daniel-mar 298
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 299
                $cont = json_encode($ary);
300
                $signature = '';
239 daniel-mar 301
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 302
                        $signature = base64_encode($signature);
303
                        $ary['signature'] = array('content' => $cont, 'signature' => $signature);
304
                }
305
        }
306
        header('Content-Type:application/json; charset=UTF-8');
307
        echo json_encode($ary);
308
}
101 daniel-mar 309
 
201 daniel-mar 310
if ($format == 'xml') {
311
        $xml = '<whois><section>';
312
        foreach ($out as $line) {
313
                if ($line == '') {
314
                        $xml .= '</section><section>';
315
                } else {
316
                        list($key,$val) = explode(':', $line, 2);
317
                        $val = trim($val);
318
                        $xml .= "<$key>".htmlspecialchars($val)."</$key>";
319
                }
320
        }
321
        $xml .= '</section></whois>';
101 daniel-mar 322
 
227 daniel-mar 323
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 324
                $cont = $xml;
325
                $signature = '';
239 daniel-mar 326
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 327
                        $signature = base64_encode($signature);
328
                        $xml .= "<signature><content>".htmlspecialchars($cont)."</content><signature>".htmlspecialchars($signature)."</signature></signature>";
329
                }
101 daniel-mar 330
        }
201 daniel-mar 331
 
332
        header('Content-Type:application/xml; charset=UTF-8');
333
        echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
330 daniel-mar 334
        echo '<root xmlns="https://oidplus.viathinksoft.com"';
335
        echo '      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
331 daniel-mar 336
        //echo '      xsi:schemaLocation="https://oidplus.viathinksoft.com/oidplus/plugins/publicPages/100_whois/whois/xml_schema.xsd">';
337
        echo '      xsi:schemaLocation="'.OIDplus::getSystemUrl().'plugins/publicPages/100_whois/whois/xml_schema.xsd">';
330 daniel-mar 338
        echo $xml;
339
        echo '</root>';
101 daniel-mar 340
}
341
 
342
# ---
343
 
344
function show_asn1_appendix($id) {
345
        if (substr($id,0,4) === 'oid:') {
346
                $appendix_asn1ids = array();
261 daniel-mar 347
                $res3 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($id));
236 daniel-mar 348
                while ($row3 = $res3->fetch_object()) {
101 daniel-mar 349
                        $appendix_asn1ids[] = $row3->name;
350
                }
351
 
352
                $appendix = implode(', ', $appendix_asn1ids);
353
                if (!empty($appendix)) $appendix = " ($appendix)";
354
        } else {
355
                $appendix = '';
356
        }
357
        return $appendix;
358
}
359
 
360
function is_root($id) {
361
        return empty(explode(':',$id,2)[1]);
362
}