Subversion Repositories oidplus

Rev

Rev 251 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  
  24. originHeaders();
  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);
  37.                 die("<h1>Error</h1><p>Argument 'query' is missing<p>");
  38.         }
  39.         $query = $_REQUEST['query'];
  40. }
  41.  
  42. $authTokens = explode('$', $query);
  43. $query = array_shift($authTokens);
  44.  
  45. $authToken = trim(OIDplus::config()->getValue('whois_auth_token'));
  46. if (empty($authToken)) $authToken = false;
  47.  
  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
  72.         $res = OIDplus::db()->query("select * from ###objects where id = ?", array($obj->nodeId()));
  73.         if ($res->num_rows() > 0) {
  74.                 $found = true;
  75.                 $distance = 0;
  76.         } else {
  77.                 $found = false;
  78.                 $objParent = OIDplusObject::parse($query)->getParent();
  79.                 if ($objParent) {
  80.                         $res = OIDplus::db()->query("select * from ###objects where id = ?", array($objParent->nodeId()));
  81.                         $distance = $objParent->distance($query);
  82.                         assert($res->num_rows() > 0);
  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 {
  111.                 $out[] = "status: Information available";
  112.  
  113.                 assert($row = $res->fetch_object());
  114.                 $obj = OIDplusObject::parse($row->id);
  115.  
  116.                 if (!empty($row->parent) && (!is_root($row->parent))) {
  117.                         $out[] = 'parent: ' . $row->parent . show_asn1_appendix($row->parent);
  118.                 }
  119.                 $out[] = 'name: ' . $row->title;
  120.  
  121.                 $cont = $row->description;
  122.                 $cont = preg_replace('@<a[^>]+href\s*=\s*["\']([^\'"]+)["\'][^>]*>(.+)<\s*/\s*a\s*>@ismU', '\2 (\1)', $cont);
  123.                 $out[] = 'description: ' . trim(html_entity_decode(strip_tags($cont)));
  124.  
  125.                 if (substr($query,0,4) === 'oid:') {
  126.                         $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
  127.                         while ($row2 = $res2->fetch_object()) {
  128.                                 $out[] = 'identifier: ' . $row2->name;
  129.                         }
  130.  
  131.                         $res2 = OIDplus::db()->query("select * from ###asn1id where standardized = ? and oid = ?", array(true, $row->id));
  132.                         while ($row2 = $res2->fetch_object()) {
  133.                                 $out[] = 'standardized-id: ' . $row2->name;
  134.                         }
  135.  
  136.                         $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
  137.                         while ($row2 = $res2->fetch_object()) {
  138.                                 $out[] = 'unicode-label: ' . $row2->name;
  139.                         }
  140.  
  141.                         $res2 = OIDplus::db()->query("select * from ###iri where longarc = ? and oid = ?", array(true, $row->id));
  142.                         while ($row2 = $res2->fetch_object()) {
  143.                                 $out[] = 'long-arc: ' . $row2->name;
  144.                         }
  145.                 }
  146.  
  147.                 $out[] = 'created: ' . $row->created;
  148.                 $out[] = 'updated: ' . $row->updated;
  149.  
  150.                 $res2 = OIDplus::db()->query("select * from ###objects where parent = ? order by ".OIDplus::db()->natOrder('id'), array($row->id));
  151.                 if ($res2->num_rows() == 0) {
  152.                         // $out[] = 'subordinate: (none)';
  153.                 }
  154.                 while ($row2 = $res2->fetch_object()) {
  155.                         $out[] = 'subordinate: ' . $row2->id . show_asn1_appendix($row2->id);
  156.                 }
  157.  
  158.                 $out[] = '';
  159.  
  160.                 $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
  161.                 if ($row2 = $res2->fetch_object()) {
  162.                         $out[] = 'ra: '.(!empty($row2->ra_name) ? $row2->ra_name : $row2->email);
  163.                         $out[] = 'ra-status: Information available';
  164.                         $out[] = 'ra-name: ' . $row2->ra_name;
  165.                         $out[] = 'ra-email: ' . $row->ra_email;
  166.                         $out[] = 'ra-personal-name: ' . $row2->personal_name;
  167.                         $out[] = 'ra-organization: ' . $row2->organization;
  168.                         $out[] = 'ra-office: ' . $row2->office;
  169.                         if ($row2->privacy && !$show_confidential) {
  170.                                 $out[] = 'ra-street: ' . (!empty($row2->street) ? '(redacted)' : '');
  171.                                 $out[] = 'ra-town: ' . (!empty($row2->zip_town) ? '(redacted)' : '');
  172.                                 $out[] = 'ra-country: ' . (!empty($row2->country) ? '(redacted)' : '');
  173.                                 $out[] = 'ra-phone: ' . (!empty($row2->phone) ? '(redacted)' : '');
  174.                                 $out[] = 'ra-mobile: ' . (!empty($row2->mobile) ? '(redacted)' : '');
  175.                                 $out[] = 'ra-fax: ' . (!empty($row2->fax) ? '(redacted)' : '');
  176.                         } else {
  177.                                 $out[] = 'ra-street: ' . $row2->street;
  178.                                 $out[] = 'ra-zip_town: ' . $row2->zip_town;
  179.                                 $out[] = 'ra-country: ' . $row2->country;
  180.                                 $out[] = 'ra-phone: ' . $row2->phone;
  181.                                 $out[] = 'ra-mobile: ' . $row2->mobile;
  182.                                 $out[] = 'ra-fax: ' . $row2->fax;
  183.                         }
  184.                         $out[] = 'ra-created: ' . $row2->registered;
  185.                         $out[] = 'ra-updated: ' . $row2->updated;
  186.                 } else {
  187.                         $out[] = 'ra: '.$row->ra_email;
  188.                         $out[] = "ra-status: Information unavailable";
  189.                 }
  190.         }
  191. }
  192.  
  193. // Step 2: Format output
  194.  
  195. ob_start();
  196.  
  197. $format = isset($_REQUEST['format']) ? $_REQUEST['format'] : 'txt';
  198.  
  199. if ($format == 'txt') {
  200.         header('Content-Type:text/plain; charset=UTF-8');
  201.  
  202.         $longest_key = 0;
  203.         foreach ($out as $line) {
  204.                 $longest_key = max($longest_key, strlen(trim(explode(':',$line,2)[0])));
  205.         }
  206.  
  207.         echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\n";
  208.  
  209.         foreach ($out as $line) {
  210.                 if (trim($line) == '') {
  211.                         echo "\n";
  212.                         continue;
  213.                 }
  214.  
  215.                 $ary = explode(':', $line, 2);
  216.  
  217.                 $key = trim($ary[0]);
  218.  
  219.                 $value = trim($ary[1]);
  220.                 $value = wordwrap($value, OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80) - $longest_key - strlen(':') - OIDplus::config()->getValue('webwhois_output_format_spacer', 2));
  221.                 $value = str_replace("\n", "\n$key:".str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)), $value);
  222.  
  223.                 echo $key.':' . str_repeat(' ', $longest_key-strlen($key)) . str_repeat(' ', OIDplus::config()->getValue('webwhois_output_format_spacer', 2)) . (!empty($value) ? $value : '.') . "\n";
  224.         }
  225.  
  226.         echo '% ' . str_repeat('*', OIDplus::config()->getValue('webwhois_output_format_max_line_length', 80)-2)."\n";
  227.  
  228.         $cont = ob_get_contents();
  229.         ob_end_clean();
  230.  
  231.         echo $cont;
  232.  
  233.         if (OIDplus::getPkiStatus(true)) {
  234.                 $signature = '';
  235.                 if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  236.                         $signature = base64_encode($signature);
  237.                         $signature = wordwrap($signature, 80, "\n", true);
  238.  
  239.                         $signature = "-----BEGIN RSA SIGNATURE-----\n".
  240.                                      "$signature\n".
  241.                                      "-----END RSA SIGNATURE-----\n";
  242.                         echo $signature;
  243.                 }
  244.         }
  245. }
  246.  
  247. if ($format == 'json') {
  248.         $ary = array();
  249.  
  250.         $current_section = array();
  251.         $ary[] = &$current_section;
  252.  
  253.         foreach ($out as $line) {
  254.                 if ($line == '') {
  255.                         unset($current_section);
  256.                         $current_section = array();
  257.                         $ary[] = &$current_section;
  258.                 } else {
  259.                         list($key,$val) = explode(':', $line, 2);
  260.                         $val = trim($val);
  261.                         if (!isset($current_section[$key])) {
  262.                                 $current_section[$key] = $val;
  263.                         } elseif (is_array($current_section[$key])) {
  264.                                 $current_section[$key][] = $val;
  265.                         } else {
  266.                                 $current_section[$key] = array($current_section[$key], $val);
  267.                         }
  268.                 }
  269.         }
  270.         $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)
  271.  
  272.         if (OIDplus::getPkiStatus(true)) {
  273.                 $cont = json_encode($ary);
  274.                 $signature = '';
  275.                 if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  276.                         $signature = base64_encode($signature);
  277.                         $ary['signature'] = array('content' => $cont, 'signature' => $signature);
  278.                 }
  279.         }
  280.         header('Content-Type:application/json; charset=UTF-8');
  281.         echo json_encode($ary);
  282. }
  283.  
  284. if ($format == 'xml') {
  285.         $xml = '<whois><section>';
  286.         foreach ($out as $line) {
  287.                 if ($line == '') {
  288.                         $xml .= '</section><section>';
  289.                 } else {
  290.                         list($key,$val) = explode(':', $line, 2);
  291.                         $val = trim($val);
  292.                         $xml .= "<$key>".htmlspecialchars($val)."</$key>";
  293.                 }
  294.         }
  295.         $xml .= '</section></whois>';
  296.  
  297.         if (OIDplus::getPkiStatus(true)) {
  298.                 $cont = $xml;
  299.                 $signature = '';
  300.                 if (@openssl_sign($cont, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  301.                         $signature = base64_encode($signature);
  302.                         $xml .= "<signature><content>".htmlspecialchars($cont)."</content><signature>".htmlspecialchars($signature)."</signature></signature>";
  303.                 }
  304.         }
  305.  
  306.         header('Content-Type:application/xml; charset=UTF-8');
  307.         echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
  308.         echo '<root>'.$xml.'</root>';
  309. }
  310.  
  311. # ---
  312.  
  313. function show_asn1_appendix($id) {
  314.         if (substr($id,0,4) === 'oid:') {
  315.                 $appendix_asn1ids = array();
  316.                 $res3 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($id));
  317.                 while ($row3 = $res3->fetch_object()) {
  318.                         $appendix_asn1ids[] = $row3->name;
  319.                 }
  320.  
  321.                 $appendix = implode(', ', $appendix_asn1ids);
  322.                 if (!empty($appendix)) $appendix = " ($appendix)";
  323.         } else {
  324.                 $appendix = '';
  325.         }
  326.         return $appendix;
  327. }
  328.  
  329. function is_root($id) {
  330.         return empty(explode(':',$id,2)[1]);
  331. }
  332.