Subversion Repositories oidplus

Rev

Rev 731 | Rev 760 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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