Subversion Repositories oidplus

Rev

Rev 236 | 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
define('OUTPUT_FORMAT_SPACER', 2);
21
define('OUTPUT_FORMAT_MAX_LINE_LENGTH', 80);
22
 
23
# ---
24
 
25
require_once __DIR__ . '/../../../../includes/oidplus.inc.php';
26
 
27
OIDplus::init(true);
28
 
180 daniel-mar 29
originHeaders();
101 daniel-mar 30
 
31
// Step 0: Get request parameter
32
 
33
if (php_sapi_name() == 'cli') {
34
        if ($argc != 2) {
35
                echo "Syntax: $argv[0] <query>\n";
36
                exit(2);
37
        }
38
        $query = $argv[1];
39
} else {
40
        if (!isset($_REQUEST['query'])) {
41
                http_response_code(400);
42
                echo "Argument 'query' is missing\n";
43
                die();
44
        }
45
        $query = $_REQUEST['query'];
46
}
47
 
48
$authTokens = explode('$', $query);
49
$query = array_shift($authTokens);
104 daniel-mar 50
 
51
$authToken = trim(OIDplus::config()->getValue('whois_auth_token'));
52
if (empty($authToken)) $authToken = false;
53
 
101 daniel-mar 54
$show_confidential = $authToken && in_array($authToken, $authTokens);
55
 
56
$query = str_replace('oid:.', 'oid:', $query); // allow leading dot
57
 
58
// Step 1: Collect data
59
 
60
$out = array();
61
 
62
$out[] = "query: $query";
63
 
64
$distance = null;
65
$found = null;
66
 
67
try {
68
        $obj = OIDplusObject::findFitting($query);
69
        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
70
} catch (Exception $e) {
71
        $obj = null;
72
}
73
 
74
if (!$obj) {
75
        $found = false;
76
} else {
77
        $query = $obj->nodeId(); // this may sanitize/canonize identifiers
150 daniel-mar 78
        $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = ?", array($obj->nodeId()));
236 daniel-mar 79
        if ($res->num_rows() > 0) {
101 daniel-mar 80
                $found = true;
81
                $distance = 0;
82
        } else {
83
                $found = false;
84
                $objParent = OIDplusObject::parse($query)->getParent();
85
                if ($objParent) {
150 daniel-mar 86
                        $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = ?", array($objParent->nodeId()));
101 daniel-mar 87
                        $distance = $objParent->distance($query);
236 daniel-mar 88
                        assert($res->num_rows() > 0);
101 daniel-mar 89
 
90
                        $query = $objParent->nodeId();
91
                        $obj = $objParent;
92
                }
93
        }
94
}
95
 
96
$continue = null;
97
if (!$found) {
98
        if (!is_null($distance)) {
99
                $out[] = "result: Not found; superior object found";
100
                $out[] = "distance: $distance";
101
                $continue = true;
102
        } else {
103
                $out[] = "result: Not found";
104
                $continue = false;
105
        }
106
} else {
107
        $out[] = "result: Found";
108
        $continue = true;
109
}
110
 
111
if ($continue) {
112
        $out[] = "";
113
        $out[] = "object: $query";
114
        if ($obj->isConfidential() && !$show_confidential) {
115
                $out[] = "status: Confidential";
116
        } else {
125 daniel-mar 117
                $out[] = "status: Information available";
101 daniel-mar 118
 
236 daniel-mar 119
                $row = $res->fetch_object();
101 daniel-mar 120
                $obj = OIDplusObject::parse($row->id);
121
 
122
                if (!empty($row->parent) && (!is_root($row->parent))) {
123
                        $out[] = 'parent: ' . $row->parent . show_asn1_appendix($row->parent);
124
                }
125
                $out[] = 'name: ' . $row->title;
126
 
127
                $cont = $row->description;
128
                $cont = preg_replace('@<a[^>]+href\s*=\s*["\']([^\'"]+)["\'][^>]*>(.+)<\s*/\s*a\s*>@ismU', '\2 (\1)', $cont);
129
                $out[] = 'description: ' . trim(html_entity_decode(strip_tags($cont)));
130
 
131
                if (substr($query,0,4) === 'oid:') {
150 daniel-mar 132
                        $res2 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = ?", array($row->id));
236 daniel-mar 133
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 134
                                $out[] = 'identifier: ' . $row2->name;
135
                        }
136
 
239 daniel-mar 137
                        $res2 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."asn1id where standardized = ? and oid = ?", array(true, $row->id));
236 daniel-mar 138
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 139
                                $out[] = 'standardized-id: ' . $row2->name;
140
                        }
141
 
150 daniel-mar 142
                        $res2 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."iri where oid = ?", array($row->id));
236 daniel-mar 143
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 144
                                $out[] = 'unicode-label: ' . $row2->name;
145
                        }
146
 
239 daniel-mar 147
                        $res2 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."iri where longarc = ? and oid = ?", array(true, $row->id));
236 daniel-mar 148
                        while ($row2 = $res2->fetch_object()) {
101 daniel-mar 149
                                $out[] = 'long-arc: ' . $row2->name;
150
                        }
151
                }
152
 
153
                $out[] = 'created: ' . $row->created;
154
                $out[] = 'updated: ' . $row->updated;
155
 
150 daniel-mar 156
                $res2 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where parent = ? order by ".OIDplus::db()->natOrder('id'), array($row->id));
236 daniel-mar 157
                if ($res2->num_rows() == 0) {
101 daniel-mar 158
                        // $out[] = 'subordinate: (none)';
159
                }
236 daniel-mar 160
                while ($row2 = $res2->fetch_object()) {
101 daniel-mar 161
                        $out[] = 'subordinate: ' . $row2->id . show_asn1_appendix($row2->id);
162
                }
163
 
164
                $out[] = '';
165
 
150 daniel-mar 166
                $res2 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."ra where email = ?", array($row->ra_email));
236 daniel-mar 167
                if ($row2 = $res2->fetch_object()) {
101 daniel-mar 168
                        $out[] = 'ra: '.(!empty($row2->ra_name) ? $row2->ra_name : $row2->email);
125 daniel-mar 169
                        $out[] = 'ra-status: Information available';
101 daniel-mar 170
                        $out[] = 'ra-name: ' . $row2->ra_name;
171
                        $out[] = 'ra-email: ' . $row->ra_email;
172
                        $out[] = 'ra-personal-name: ' . $row2->personal_name;
173
                        $out[] = 'ra-organization: ' . $row2->organization;
174
                        $out[] = 'ra-office: ' . $row2->office;
175
                        if ($row2->privacy && !$show_confidential) {
176
                                $out[] = 'ra-street: ' . (!empty($row2->street) ? '(redacted)' : '');
177
                                $out[] = 'ra-town: ' . (!empty($row2->zip_town) ? '(redacted)' : '');
178
                                $out[] = 'ra-country: ' . (!empty($row2->country) ? '(redacted)' : '');
179
                                $out[] = 'ra-phone: ' . (!empty($row2->phone) ? '(redacted)' : '');
180
                                $out[] = 'ra-mobile: ' . (!empty($row2->mobile) ? '(redacted)' : '');
181
                                $out[] = 'ra-fax: ' . (!empty($row2->fax) ? '(redacted)' : '');
182
                        } else {
183
                                $out[] = 'ra-street: ' . $row2->street;
184
                                $out[] = 'ra-zip_town: ' . $row2->zip_town;
185
                                $out[] = 'ra-country: ' . $row2->country;
186
                                $out[] = 'ra-phone: ' . $row2->phone;
187
                                $out[] = 'ra-mobile: ' . $row2->mobile;
188
                                $out[] = 'ra-fax: ' . $row2->fax;
189
                        }
190
                        $out[] = 'ra-created: ' . $row2->registered;
191
                        $out[] = 'ra-updated: ' . $row2->updated;
192
                } else {
193
                        $out[] = 'ra: '.$row->ra_email;
125 daniel-mar 194
                        $out[] = "ra-status: Information unavailable";
101 daniel-mar 195
                }
196
        }
197
}
198
 
199
// Step 2: Format output
200
 
201
ob_start();
202
 
201 daniel-mar 203
$format = isset($_REQUEST['format']) ? $_REQUEST['format'] : 'txt';
101 daniel-mar 204
 
201 daniel-mar 205
if ($format == 'txt') {
206
        header('Content-Type:text/plain; charset=UTF-8');
101 daniel-mar 207
 
201 daniel-mar 208
        $longest_key = 0;
209
        foreach ($out as $line) {
210
                $longest_key = max($longest_key, strlen(trim(explode(':',$line,2)[0])));
101 daniel-mar 211
        }
212
 
201 daniel-mar 213
        echo '% ' . str_repeat('*', OUTPUT_FORMAT_MAX_LINE_LENGTH-2)."\n";
101 daniel-mar 214
 
201 daniel-mar 215
        foreach ($out as $line) {
216
                if (trim($line) == '') {
217
                        echo "\n";
218
                        continue;
219
                }
101 daniel-mar 220
 
201 daniel-mar 221
                $ary = explode(':', $line, 2);
101 daniel-mar 222
 
201 daniel-mar 223
                $key = trim($ary[0]);
224
 
225
                $value = trim($ary[1]);
226
                $value = wordwrap($value, OUTPUT_FORMAT_MAX_LINE_LENGTH - $longest_key - strlen(':') - OUTPUT_FORMAT_SPACER);
227
                $value = str_replace("\n", "\n$key:".str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OUTPUT_FORMAT_SPACER), $value);
228
 
229
                echo $key.':' . str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OUTPUT_FORMAT_SPACER) . (!empty($value) ? $value : '.') . "\n";
230
        }
231
 
232
        echo '% ' . str_repeat('*', OUTPUT_FORMAT_MAX_LINE_LENGTH-2)."\n";
233
 
234
        $cont = ob_get_contents();
235
        ob_end_clean();
236
 
237
        echo $cont;
238
 
227 daniel-mar 239
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 240
                $signature = '';
239 daniel-mar 241
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 242
                        $signature = base64_encode($signature);
243
                        $signature = wordwrap($signature, 80, "\n", true);
244
 
245
                        $signature = "-----BEGIN RSA SIGNATURE-----\n".
246
                                     "$signature\n".
247
                                     "-----END RSA SIGNATURE-----\n";
248
                        echo $signature;
249
                }
250
        }
101 daniel-mar 251
}
252
 
201 daniel-mar 253
if ($format == 'json') {
254
        $ary = array();
101 daniel-mar 255
 
201 daniel-mar 256
        $current_section = array();
257
        $ary[] = &$current_section;
101 daniel-mar 258
 
201 daniel-mar 259
        foreach ($out as $line) {
260
                if ($line == '') {
261
                        unset($current_section);
262
                        $current_section = array();
263
                        $ary[] = &$current_section;
264
                } else {
265
                        list($key,$val) = explode(':', $line, 2);
266
                        $val = trim($val);
267
                        if (!isset($current_section[$key])) {
268
                                $current_section[$key] = $val;
269
                        } elseif (is_array($current_section[$key])) {
270
                                $current_section[$key][] = $val;
271
                        } else {
272
                                $current_section[$key] = array($current_section[$key], $val);
273
                        }
274
                }
275
        }
276
        $ary = array('whois' => $ary); // 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)
101 daniel-mar 277
 
227 daniel-mar 278
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 279
                $cont = json_encode($ary);
280
                $signature = '';
239 daniel-mar 281
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 282
                        $signature = base64_encode($signature);
283
                        $ary['signature'] = array('content' => $cont, 'signature' => $signature);
284
                }
285
        }
286
        header('Content-Type:application/json; charset=UTF-8');
287
        echo json_encode($ary);
288
}
101 daniel-mar 289
 
201 daniel-mar 290
if ($format == 'xml') {
291
        $xml = '<whois><section>';
292
        foreach ($out as $line) {
293
                if ($line == '') {
294
                        $xml .= '</section><section>';
295
                } else {
296
                        list($key,$val) = explode(':', $line, 2);
297
                        $val = trim($val);
298
                        $xml .= "<$key>".htmlspecialchars($val)."</$key>";
299
                }
300
        }
301
        $xml .= '</section></whois>';
101 daniel-mar 302
 
227 daniel-mar 303
        if (OIDplus::getPkiStatus(true)) {
201 daniel-mar 304
                $cont = $xml;
305
                $signature = '';
239 daniel-mar 306
                if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
201 daniel-mar 307
                        $signature = base64_encode($signature);
308
                        $xml .= "<signature><content>".htmlspecialchars($cont)."</content><signature>".htmlspecialchars($signature)."</signature></signature>";
309
                }
101 daniel-mar 310
        }
201 daniel-mar 311
 
312
        header('Content-Type:application/xml; charset=UTF-8');
313
        echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
314
        echo '<root>'.$xml.'</root>';
101 daniel-mar 315
}
316
 
317
# ---
318
 
319
function show_asn1_appendix($id) {
320
        if (substr($id,0,4) === 'oid:') {
321
                $appendix_asn1ids = array();
150 daniel-mar 322
                $res3 = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = ?", array($id));
236 daniel-mar 323
                while ($row3 = $res3->fetch_object()) {
101 daniel-mar 324
                        $appendix_asn1ids[] = $row3->name;
325
                }
326
 
327
                $appendix = implode(', ', $appendix_asn1ids);
328
                if (!empty($appendix)) $appendix = " ($appendix)";
329
        } else {
330
                $appendix = '';
331
        }
332
        return $appendix;
333
}
334
 
335
function is_root($id) {
336
        return empty(explode(':',$id,2)[1]);
337
}