Subversion Repositories oidplus

Rev

Rev 350 | 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. class OIDplusPageAdminOIDInfoExport extends OIDplusPagePluginAdmin {
  21.  
  22.         /*private*/ const QUERY_LIST_OIDINFO_OIDS_V1 = '1.3.6.1.4.1.37476.2.5.2.1.5.1';
  23.         /*private*/ const QUERY_GET_OIDINFO_DATA_V1  = '1.3.6.1.4.1.37476.2.5.2.1.6.1';
  24.  
  25.         public function action($actionID, $params) {
  26.  
  27.                 if ($actionID == 'import_xml_file') {
  28.                         if (!OIDplus::authUtils()::isAdminLoggedIn()) {
  29.                                 throw new OIDplusException(_L('You need to log in as administrator.'));
  30.                         }
  31.  
  32.                         if (!isset($_FILES['userfile'])) {
  33.                                 throw new OIDplusException(_L('Please choose a file.'));
  34.                         }
  35.  
  36.                         $xml_contents = file_get_contents($_FILES['userfile']['tmp_name']);
  37.  
  38.                         $errors = array();
  39.                         list($count_imported_oids, $count_already_existing, $count_errors, $count_warnings) = $this->oidinfoImportXML($xml_contents, $errors, $replaceExistingOIDs=false, $orphan_mode=self::ORPHAN_AUTO_DEORPHAN);
  40.                         if (count($errors) > 0) {
  41.                                 // Note: These "errors" can also be warnings (partial success)
  42.                                 // TODO XXX: since the output can be very long, should we really show it in a JavaScript alert() ?!
  43.                                 return array(
  44.                                         "status" => 1,
  45.                                         "count_imported_oids" => $count_imported_oids,
  46.                                         "count_already_existing" => $count_already_existing,
  47.                                         "count_errors" => $count_errors,
  48.                                         "count_warnings" => $count_warnings,
  49.                                         "error" => implode("\n",$errors)
  50.                                 );
  51.                         } else {
  52.                                 return array(
  53.                                         "status" => 0,
  54.                                         "count_imported_oids" => $count_imported_oids,
  55.                                         "count_already_existing" => $count_already_existing,
  56.                                         "count_errors" => $count_errors,
  57.                                         "count_warnings" => $count_warnings
  58.                                 );
  59.                         }
  60.                 } else if ($actionID == 'import_oidinfo_oid') {
  61.                         if (!OIDplus::authUtils()::isAdminLoggedIn()) {
  62.                                 throw new OIDplusException(_L('You need to log in as administrator.'));
  63.                         }
  64.  
  65.                         $oid = $params['oid'];
  66.  
  67.                         $query = self::QUERY_GET_OIDINFO_DATA_V1;
  68.  
  69.                         $payload = array(
  70.                                 "query" => $query, // we must repeat the query because we want to sign it
  71.                                 "system_id" => OIDplus::getSystemId(false),
  72.                                 "oid" => $oid
  73.                         );
  74.  
  75.                         $signature = '';
  76.                         if (!@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  77.                                 if (!OIDplus::getPkiStatus()) {
  78.                                         throw new OIDplusException(_L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.'));
  79.                                 } else {
  80.                                         throw new OIDplusException(_L('Signature failed'));
  81.                                 }
  82.                         }
  83.  
  84.                         $data = array(
  85.                                 "payload" => $payload,
  86.                                 "signature" => base64_encode($signature)
  87.                         );
  88.  
  89.                         $ch = curl_init();
  90.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  91.                         curl_setopt($ch, CURLOPT_POST, 1);
  92.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=$query&data=".base64_encode(json_encode($data)));
  93.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  94.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  95.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  96.                         if (!($res = @curl_exec($ch))) {
  97.                                 throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
  98.                         }
  99.                         curl_close($ch);
  100.  
  101.                         $json = json_decode($res, true);
  102.  
  103.                         if (!$json) {
  104.                                 return array("status" => 1, "error" => _L('JSON reply from ViaThinkSoft decoding error: %1',$res));
  105.                         }
  106.  
  107.                         if (isset($json['error']) || ($json['status'] != 0)) {
  108.                                 return array("status" => 1, "error" => $json['error']);
  109.                         } else {
  110.                                 $errors = array();
  111.                                 list($count_imported_oids, $count_already_existing, $count_errors, $count_warnings) = $this->oidinfoImportXML('<oid-database>'.$json['xml'].'</oid-database>', $errors, $replaceExistingOIDs=false, $orphan_mode=self::ORPHAN_DISALLOW_ORPHANS);
  112.                                 if (count($errors) > 0) {
  113.                                         return array("status" => 1, "error" => implode("\n",$errors));
  114.                                 } else if ($count_imported_oids <> 1) {
  115.                                         return array("status" => 1, "error" => _L('Imported %1, but expected to import 1',$count_imported_oids));
  116.                                 } else {
  117.                                         return array("status" => 0);
  118.                                 }
  119.  
  120.                         }
  121.                 } else {
  122.                         throw new OIDplusException(_L('Unknown action ID'));
  123.                 }
  124.         }
  125.  
  126.         public function init($html=true) {
  127.                 // Nothing
  128.         }
  129.  
  130.         public function gui($id, &$out, &$handled) {
  131.                 if ($id === 'oidplus:oidinfo_compare_export') {
  132.                         $handled = true;
  133.                         $out['title'] = _L('List OIDs in your system which are missing at oid-info.com');
  134.                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  135.  
  136.                         if (!OIDplus::authUtils()::isAdminLoggedIn()) {
  137.                                 $out['icon'] = 'img/error_big.png';
  138.                                 $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login')).'</p>';
  139.                                 return;
  140.                         }
  141.  
  142.                         $query = self::QUERY_LIST_OIDINFO_OIDS_V1;
  143.  
  144.                         $payload = array(
  145.                                 "query" => $query, // we must repeat the query because we want to sign it
  146.                                 "system_id" => OIDplus::getSystemId(false),
  147.                                 "show_all" => 1 // this is required so that the VTS OIDRA gets no false notifications for adding the systems in the directory 1.3.6.1.4.1.37476.30.9
  148.                         );
  149.  
  150.                         $signature = '';
  151.                         if (!@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  152.                                 if (!OIDplus::getPkiStatus()) {
  153.                                         throw new OIDplusException(_L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.'));
  154.                                 } else {
  155.                                         throw new OIDplusException(_L('Signature failed'));
  156.                                 }
  157.                         }
  158.  
  159.                         $data = array(
  160.                                 "payload" => $payload,
  161.                                 "signature" => base64_encode($signature)
  162.                         );
  163.  
  164.                         $ch = curl_init();
  165.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  166.                         curl_setopt($ch, CURLOPT_POST, 1);
  167.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=$query&data=".base64_encode(json_encode($data)));
  168.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  169.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  170.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  171.                         if (!($res = @curl_exec($ch))) {
  172.                                 throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
  173.                         }
  174.                         curl_close($ch);
  175.  
  176.                         $json = json_decode($res, true);
  177.  
  178.                         if (!$json) {
  179.                                 $out['icon'] = 'img/error_big.png';
  180.                                 $out['text'] = _L('JSON reply from ViaThinkSoft decoding error: %1',$res);
  181.                                 return;
  182.                         }
  183.  
  184.                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:datatransfer').'><img src="img/arrow_back.png" width="16"> '._L('Go back to data transfer main page').'</a>'; // TODO: How to automatically jump to the "Export" tab?
  185.  
  186.                         if (isset($json['error']) || ($json['status'] != 0)) {
  187.                                 $out['text'] .= '<p>'._L('Error: %1',htmlentities($json['error'])).'</p>';
  188.                         } else {
  189.                                 // TODO: If roots were created or deleted recently, we must do a re-query of the registration, so that the "roots" information at the directory service gets refreshed
  190.                                 if (count($json['roots']) == 0) $out['text'] .= '<p>'._L('In order to use this feature, you need to have at least one (root) OID added in your system, and the system needs to report the newly added root to the directory service (the reporting interval is 1 hour).').'</p>';
  191.                                 foreach ($json['roots'] as $root) {
  192.                                         $oid = $root['oid'];
  193.                                         $out['text'] .= '<h2>'._L('Root OID %1',$oid).'</h2>';
  194.                                         if ($root['verified']) {
  195.                                                 $count = 0;
  196.                                                 $out['text'] .= '<div class="container box"><div id="suboid_table" class="table-responsive">';
  197.                                                 $out['text'] .= '<table class="table table-bordered table-striped">';
  198.                                                 $out['text'] .= '<tr><th colspan="3">'._L('Actions').'</th><th>'._L('OID').'</th></tr>';
  199.  
  200.                                                 $lookup_nonoid = array();
  201.                                                 $row_lookup = array();
  202.  
  203.                                                 $all_local_oids_of_root = array();
  204.                                                 $res = OIDplus::db()->query("select * from ###objects where confidential <> 1");
  205.                                                 while ($row = $res->fetch_object()) {
  206.                                                         $obj = OIDplusObject::parse($row->id);
  207.                                                         if (!$obj) continue; // can happen when object type is not enabled
  208.                                                         if ($obj->isConfidential()) continue; // This will also exclude OIDs which are descendants of confidential OIDs
  209.                                                         if (strpos($row->id, 'oid:') === 0) {
  210.                                                                 $oid = substr($row->id,strlen('oid:'));
  211.                                                                 if (strpos($oid.'.', $root['oid']) === 0) {
  212.                                                                         $row_lookup[$oid] = $row;
  213.                                                                         $all_local_oids_of_root[] = $oid;
  214.                                                                 }
  215.                                                         } else {
  216.                                                                 $aids = $obj->getAltIds();
  217.                                                                 foreach ($aids as $aid) {
  218.                                                                         if ($aid->getNamespace() == 'oid') {
  219.                                                                                 $oid = $aid->getId();
  220.                                                                                 if (strpos($oid.'.', $root['oid']) === 0) {
  221.                                                                                         $row_lookup[$oid] = $row;
  222.                                                                                         $all_local_oids_of_root[] = $oid;
  223.                                                                                         $lookup_nonoid[$oid] = $row->id;
  224.                                                                                 }
  225.                                                                         }
  226.                                                                 }
  227.                                                         }
  228.                                                 }
  229.  
  230.                                                 natsort($all_local_oids_of_root);
  231.                                                 foreach ($all_local_oids_of_root as $local_oid) {
  232.                                                         if (!in_array($local_oid, $root['children'])) {
  233.                                                                 $count++;
  234.  
  235.                                                                 // Start: Build oid-info.com create URL
  236.  
  237.                                                                 $row = $row_lookup[$local_oid];
  238.  
  239.                                                                 $url = "http://www.oid-info.com/cgi-bin/manage?f=".oid_up($local_oid)."&a=create";
  240.  
  241.                                                                 $tmp = explode('.',$local_oid);
  242.                                                                 $url .= "&nb=".urlencode(array_pop($tmp));
  243.  
  244.                                                                 $asn1_ids = array();
  245.                                                                 $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
  246.                                                                 while ($row2 = $res2->fetch_object()) {
  247.                                                                         $asn1_ids[] = $row2->name; // 'unicode-label' is currently not in the standard format (oid.xsd)
  248.                                                                 }
  249.                                                                 $url .= "&id=".array_shift($asn1_ids); // urlencode wurde schon oben gemacht
  250.                                                                 $url .= "&syn_id=".implode('%0A', $asn1_ids); // urlencode wurde schon oben gemacht
  251.  
  252.                                                                 $iri_ids = array();
  253.                                                                 $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
  254.                                                                 while ($row2 = $res2->fetch_object()) {
  255.                                                                         $iri_ids[] = $row2->name;
  256.                                                                 }
  257.                                                                 $url .= "&unicode_label_list=".implode('%0A', $iri_ids); // urlencode wurde schon oben gemacht
  258.  
  259.                                                                 if (!empty($row->title)) {
  260.                                                                         $tmp_description = $row->title;
  261.                                                                         $tmp_information = $row->description;
  262.                                                                         if (trim($row->title) == trim(strip_tags($row->description))) {
  263.                                                                                 $tmp_information = '';
  264.                                                                         }
  265.                                                                 } else if (isset($asn1_ids[0])) {
  266.                                                                         $tmp_description = '"'.$asn1_ids[0].'"';
  267.                                                                         $tmp_information = $row->description;
  268.                                                                 } else if (isset($iri_ids[0])) {
  269.                                                                         $tmp_description = '"'.$iri_ids[0].'"';
  270.                                                                         $tmp_information = $row->description;
  271.                                                                 } else if (!empty($row->description)) {
  272.                                                                         $tmp_description = $row->description;
  273.                                                                         $tmp_information = '';
  274.                                                                 } else if (!empty($row->comment)) {
  275.                                                                         $tmp_description = $row->comment;
  276.                                                                         $tmp_information = '';
  277.                                                                 } else {
  278.                                                                         $tmp_description = '<i>No description available</i>'; // do not translate
  279.                                                                         $tmp_information = '';
  280.                                                                 }
  281.  
  282.                                                                 if ($tmp_information != '') {
  283.                                                                         $tmp_information .= '<br/><br/>';
  284.                                                                 }
  285.  
  286.                                                                 $tmp_information .= 'See <a href="'.OIDplus::getSystemUrl(false).'?goto='.urlencode($id).'">more information</a>.'; // do not translate
  287.  
  288.                                                                 if (explode(':',$id,2)[0] != 'oid') {
  289.                                                                         $tmp_information = "Object: $id\n\n" . $tmp_information; // do not translate
  290.                                                                 }
  291.  
  292.                                                                 $url .= "&description=".urlencode(self::repair_relative_links($tmp_description));
  293.                                                                 $url .= "&info=".urlencode(self::repair_relative_links($tmp_information));
  294.  
  295.                                                                 $url .= "&current_registrant_email=".urlencode($row->ra_email);
  296.  
  297.                                                                 $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
  298.                                                                 if ($res2->num_rows() > 0) {
  299.                                                                         $row2 = $res2->fetch_object();
  300.  
  301.                                                                         $tmp = array();
  302.                                                                         if (!empty($row2->personal_name)) {
  303.                                                                                 $name_ary = split_firstname_lastname($row2->personal_name);
  304.                                                                                 $tmp_first_name = $name_ary[0];
  305.                                                                                 $tmp_last_name  = $name_ary[1];
  306.                                                                                 if (!empty($row2->ra_name)       ) $tmp[] = $row2->ra_name;
  307.                                                                                 if (!empty($row2->office)        ) $tmp[] = $row2->office;
  308.                                                                                 if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
  309.                                                                         } else {
  310.                                                                                 $tmp_first_name = $row2->ra_name;
  311.                                                                                 $tmp_last_name  = '';
  312.                                                                                 if (!empty($row2->personal_name) ) $tmp[] = $row2->personal_name;
  313.                                                                                 if (!empty($row2->office)        ) $tmp[] = $row2->office;
  314.                                                                                 if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
  315.                                                                         }
  316.  
  317.                                                                         if (empty($tmp_first_name) || empty($tmp_last_name)) {
  318.                                                                                 $name = self::split_name($tmp_first_name.' '.$tmp_last_name);
  319.                                                                                 $tmp_first_name = $name[0];
  320.                                                                                 $tmp_last_name = $name[1];
  321.                                                                         }
  322.                                                                         $url .= "&current_registrant_first_name=".urlencode($tmp_first_name);
  323.                                                                         $url .= "&current_registrant_last_name=".urlencode($tmp_last_name);
  324.  
  325.                                                                         if ((count($tmp) > 0) && ($tmp[0] == $row2->ra_name)) array_shift($tmp);
  326.                                                                         array_unique($tmp);
  327.  
  328.                                                                         if (!$row2->privacy) {
  329.                                                                                 if (!empty($row2->street))   $tmp[] = $row2->street;
  330.                                                                                 if (!empty($row2->zip_town)) $tmp[] = $row2->zip_town;
  331.                                                                                 if (!empty($row2->country))  $tmp[] = $row2->country;
  332.                                                                                 $url .= "&current_registrant_tel=".urlencode(!empty($row2->phone) ? $row2->phone : $row2->mobile);
  333.                                                                                 $url .= "&current_registrant_fax=".urlencode($row2->fax);
  334.                                                                         }
  335.                                                                         if (empty($row2->zip_town) && empty($row2->country)) {
  336.                                                                                 // The address is useless if we do neither know city nor country
  337.                                                                                 // Ignore it
  338.                                                                         } else {
  339.                                                                                 $tmp = self::split_address_country(implode("<br/>", $tmp));
  340.                                                                                 $url .= "&current_registrant_address=".urlencode($tmp[0]);
  341.                                                                                 $url .= "&current_registrant_country=".urlencode($tmp[1]);
  342.                                                                         }
  343.                                                                 }
  344.                                                                 if (!empty($row->updated)) {
  345.                                                                         $tmp = explode('-', self::_formatdate($row->updated));
  346.                                                                         $url .= "&modification_year=".urlencode($tmp[0]);
  347.                                                                         $url .= "&modification_month=".urlencode($tmp[1]);
  348.                                                                         $url .= "&modification_day=".urlencode($tmp[2]);
  349.                                                                 }
  350.  
  351.                                                                 //$url .= "&submitter_last_name=".urlencode($xml->{'submitter'}->{'last-name'});
  352.                                                                 //$url .= "&submitter_first_name=".urlencode($xml->{'submitter'}->{'first-name'});
  353.                                                                 //$url .= "&submitter_email=".urlencode($xml->{'submitter'}->{'email'});
  354.  
  355.                                                                 // End: Build oid-info.com create URL
  356.  
  357.                                                                 // Note: "Actions" is at the left, because it has a fixed width, so the user can continue clicking without the links moving if the OID length changes between lines
  358.                                                                 $out['text'] .= '<tr id="missing_oid_'.str_replace('.','_',$local_oid).'">'.
  359.                                                                 '<td><a '.OIDplus::gui()->link(isset($lookup_nonoid[$local_oid]) ? $lookup_nonoid[$local_oid] : 'oid:'.$local_oid, true).'>'._L('View local OID').'</a></td>'.
  360.                                                                 '<td><a href="javascript:removeMissingOid(\''.$local_oid.'\');">'._L('Ignore for now').'</a></td>'.
  361.                                                                 '<td><a target="_blank" href="'.$url.'">'._L('Add to oid-info.com manually').'</a></td>'.
  362.                                                                 '<td>'.$local_oid.'</td>'.
  363.                                                                 '</tr>';
  364.                                                         }
  365.                                                 }
  366.                                                 if ($count == 0) {
  367.                                                         $out['text'] .= '<tr><td colspan="4">'._L('No missing OIDs found').'</td></tr>';
  368.                                                 }
  369.                                                 $out['text'] .= '</table></div></div>';
  370.                                         } else {
  371.                                                 $out['text'] .= '<p>'._L('This root is not validated. Please send an email to %1 in order to request ownership verification of this root OID.',$json['vts_verification_email']).'</p>';
  372.                                         }
  373.                                 }
  374.                         }
  375.                 }
  376.  
  377.                 if ($id === 'oidplus:oidinfo_compare_import') {
  378.                         $handled = true;
  379.                         $out['title'] = _L('List OIDs at oid-info.com which are missing in your system');
  380.                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  381.  
  382.                         if (!OIDplus::authUtils()::isAdminLoggedIn()) {
  383.                                 $out['icon'] = 'img/error_big.png';
  384.                                 $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login')).'</p>';
  385.                                 return;
  386.                         }
  387.  
  388.                         $query = self::QUERY_LIST_OIDINFO_OIDS_V1;
  389.  
  390.                         $payload = array(
  391.                                 "query" => $query, // we must repeat the query because we want to sign it
  392.                                 "system_id" => OIDplus::getSystemId(false),
  393.                                 "show_all" => 0
  394.                         );
  395.  
  396.                         $signature = '';
  397.                         if (!@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  398.                                 if (!OIDplus::getPkiStatus()) {
  399.                                         throw new OIDplusException(_L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.'));
  400.                                 } else {
  401.                                         throw new OIDplusException(_L('Signature failed'));
  402.                                 }
  403.                         }
  404.  
  405.                         $data = array(
  406.                                 "payload" => $payload,
  407.                                 "signature" => base64_encode($signature)
  408.                         );
  409.  
  410.                         $ch = curl_init();
  411.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  412.                         curl_setopt($ch, CURLOPT_POST, 1);
  413.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=$query&data=".base64_encode(json_encode($data)));
  414.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  415.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  416.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  417.                         if (!($res = @curl_exec($ch))) {
  418.                                 throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
  419.                         }
  420.                         curl_close($ch);
  421.  
  422.                         $json = json_decode($res, true);
  423.  
  424.                         if (!$json) {
  425.                                 $out['icon'] = 'img/error_big.png';
  426.                                 $out['text'] = _L('JSON reply from ViaThinkSoft decoding error: %1',$res);
  427.                                 return;
  428.                         }
  429.  
  430.                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:datatransfer').'><img src="img/arrow_back.png" width="16"> '._L('Go back to data transfer main page').'</a>'; // TODO: How to automatically jump to the "Import" tab?
  431.  
  432.                         $all_local_oids = array();
  433.                         $res = OIDplus::db()->query("select id from ###objects");
  434.                         while ($row = $res->fetch_array()) {
  435.                                 if (strpos($row['id'], 'oid:') === 0) {
  436.                                         $all_local_oids[] = substr($row['id'],strlen('oid:'));
  437.                                 } else {
  438.                                         $obj = OIDplusObject::parse($row['id']);
  439.                                         if (!$obj) continue; // can happen when object type is not enabled
  440.                                         $aids = $obj->getAltIds();
  441.                                         foreach ($aids as $aid) {
  442.                                                 if ($aid->getNamespace() == 'oid') {
  443.                                                         $all_local_oids[] = $aid->getId();
  444.                                                 }
  445.                                         }
  446.                                 }
  447.                         }
  448.  
  449.                         if (isset($json['error']) || ($json['status'] != 0)) {
  450.                                 $out['text'] .= '<p>'._L('Error: %1',htmlentities($json['error'])).'</p>';
  451.                         } else {
  452.                                 // TODO: If roots were created or deleted recently, we must do a re-query of the registration, so that the "roots" information at the directory service gets refreshed
  453.                                 if (count($json['roots']) == 0) $out['text'] .= '<p>'._L('In order to use this feature, you need to have at least one (root) OID added in your system, and the system needs to report the newly added root to the directory service (the reporting interval is 1 hour).').'</p>';
  454.                                 foreach ($json['roots'] as $root) {
  455.                                         $oid = $root['oid'];
  456.                                         $out['text'] .= '<h2>'._L('Root OID %1',$oid).'</h2>';
  457.                                         // TODO: "Import all" button
  458.                                         if ($root['verified']) {
  459.                                                 $count = 0;
  460.                                                 $out['text'] .= '<div class="container box"><div id="suboid_table" class="table-responsive">';
  461.                                                 $out['text'] .= '<table class="table table-bordered table-striped">';
  462.                                                 $out['text'] .= '<tr><th colspan="4">'._L('Actions').'</th><th>'._L('OID').'</th></tr>';
  463.                                                 natsort($root['children']);
  464.                                                 foreach ($root['children'] as $child_oid) {
  465.                                                         if (!in_array($child_oid, $all_local_oids)) {
  466.                                                                 $count++;
  467.                                                                 // Note: "Actions" is at the left, because it has a fixed width, so the user can continue clicking without the links moving if the OID length changes between lines
  468.                                                                 $out['text'] .= '<tr id="missing_oid_'.str_replace('.','_',$child_oid).'">'.
  469.                                                                 '<td><a target="_blank" href="http://www.oid-info.com/get/'.$child_oid.'">'._L('View OID at oid-info.com').'</a></td>'.
  470.                                                                 '<td><a href="javascript:removeMissingOid(\''.$child_oid.'\');">'._L('Ignore for now').'</a></td>'.
  471.                                                                 '<td><a href="mailto:admin@oid-info.com">'._L('Report illegal OID').'</a></td>'.
  472.                                                                 (strpos($child_oid,'1.3.6.1.4.1.37476.30.9.') === 0 ? '<td>&nbsp;</td>' : '<td><a href="javascript:importMissingOid(\''.$child_oid.'\');">'._L('Import OID').'</a></td>').
  473.                                                                 '<td>'.$child_oid.'</td>'.
  474.                                                                 '</tr>';
  475.                                                         }
  476.                                                 }
  477.                                                 if ($count == 0) {
  478.                                                         $out['text'] .= '<tr><td colspan="5">'._L('No extra OIDs found').'</td></tr>';
  479.                                                 }
  480.                                                 $out['text'] .= '</table></div></div>';
  481.                                         } else {
  482.                                                 $out['text'] .= '<p>'._L('This root is not validated. Please send an email to %1 in order to request ownership verification of this root OID.',$json['vts_verification_email']).'</p>';
  483.                                         }
  484.                                 }
  485.                         }
  486.                 }
  487.  
  488.                 if ($id === 'oidplus:datatransfer') {
  489.                         $handled = true;
  490.                         $out['title'] = _L('Data Transfer');
  491.                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  492.  
  493.                         if (!OIDplus::authUtils()::isAdminLoggedIn()) {
  494.                                 $out['icon'] = 'img/error_big.png';
  495.                                 $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login')).'</p>';
  496.                                 return;
  497.                         }
  498.  
  499.                         $out['text'] = '';
  500.  
  501.                         $out['text'] .= '<div id="oidinfoMainArea" style="visibility: hidden"><div id="oidinfoMainTab" class="container" style="width:100%;">';
  502.                         $out['text'] .= '<br>';
  503.                         $out['text'] .= '<ul class="nav nav-pills">';
  504.                         $out['text'] .= '                       <li class="active">';
  505.                         $out['text'] .= '                       <a href="#1a" data-toggle="tab">'._L('Export').'</a>';
  506.                         $out['text'] .= '                       </li>';
  507.                         $out['text'] .= '                       <li><a href="#2a" data-toggle="tab">'._L('Import').'</a>';
  508.                         $out['text'] .= '                       </li>';
  509.                         $out['text'] .= '               </ul>';
  510.                         $out['text'] .= '                       <div class="tab-content clearfix">';
  511.                         $out['text'] .= '                         <div class="tab-pane active" id="1a">';
  512.                         // ---------------- Start "Export" tab
  513.                         $out['text'] .= '<h2>'._L('Generate XML file containing all OIDs').'</h2>';
  514.                         $out['text'] .= '<p>'._L('These XML files are following the <a %1>XML schema</a> of <b>oid-info.com</b>. They can be used for various purposes though.','href="http://www.oid-info.com/oid.xsd" target="_blank"').'</p>';
  515.                         $out['text'] .= '<p><input type="button" onclick="window.open(\''.OIDplus::webpath(__DIR__).'oidinfo_export.php\',\'_blank\')" value="'._L('Generate XML (all OIDs)').'"></p>';
  516.                         $out['text'] .= '<p><input type="button" onclick="window.open(\''.OIDplus::webpath(__DIR__).'oidinfo_export.php?online=1\',\'_blank\')" value="'._L('Generate XML (only OIDs which do not exist at oid-info.com)').'"></p>';
  517.                         $out['text'] .= '<p><a href="http://www.oid-info.com/submit.htm" target="_blank">'._L('Upload XML files manually to oid-info.com').'</a></p>';
  518.                         $out['text'] .= '<br><p>'._L('Attention: Do not use this XML Export/Import to exchange, backup or restore data between OIDplus systems!<br>It will cause various loss of information, e.g. because Non-OIDs like GUIDs are converted in OIDs and can\'t be converted back.').'</p>';
  519.                         $out['text'] .= '<h2>'._L('Automatic export to oid-info.com').'</h2>';
  520.                         $privacy_level = OIDplus::config()->getValue('reg_privacy');
  521.                         if ($privacy_level == 0) {
  522.                                 $out['text'] .= '<p>'._L('All your OIDs will automatically submitted to oid-info.com through the remote directory service in regular intervals.').' (<a '.OIDplus::gui()->link('oidplus:srv_registration').'>'._L('Change preference').'</a>)</p>';
  523.                         } else {
  524.                                 $out['text'] .= '<p>'._L('If you set the privacy option to "0" (your system is registered), then all your OIDs will be automatically exported to oid-info.com.').' (<a '.OIDplus::gui()->link('oidplus:srv_registration').'>'._L('Change preference').'</a>)</p>';
  525.                         }
  526.                         $out['text'] .= '<h2>'._L('Comparison with oid-info.com').'</h2>';
  527.                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:oidinfo_compare_export').'>'._L('List OIDs in your system which are missing at oid-info.com').'</a></p>';
  528.                         // ---------------- End "Export" tab
  529.                         $out['text'] .= '                               </div>';
  530.                         $out['text'] .= '                               <div class="tab-pane" id="2a">';
  531.                         // ---------------- Start "Import" tab
  532.                         $out['text'] .= '<h2>'._L('Import XML file').'</h2>';
  533.                         $out['text'] .= '<p>'._L('These XML files are following the <a %1>XML schema</a> of <b>oid-info.com</b>.','href="http://www.oid-info.com/oid.xsd" target="_blank"').'</p>';
  534.                         // TODO XXX: we need a waiting animation!
  535.                         $out['text'] .= '<form onsubmit="return uploadXmlFileOnSubmit(this);" enctype="multipart/form-data" id="uploadXmlFileForm">';
  536.                         $out['text'] .= '<div>'._L('Choose XML file here').':<input type="file" name="userfile" value="" id="userfile">';
  537.                         $out['text'] .= '<br><input type="submit" value="'._L('Import XML').'"></div>';
  538.                         $out['text'] .= '</form>';
  539.                         $out['text'] .= '<br><p>'._L('Attention: Do not use this XML Export/Import to exchange, backup or restore data between OIDplus systems!<br>It will cause various loss of information, e.g. because Non-OIDs like GUIDs are converted in OIDs and can\'t be converted back.').'</p>';
  540.                         $out['text'] .= '<h2>'._L('Comparison with oid-info.com').'</h2>';
  541.                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:oidinfo_compare_import').'>'._L('List OIDs at oid-info.com which are missing in your system').'</a></p>';
  542.                         // ---------------- End "Import" tab
  543.                         $out['text'] .= '                               </div>';
  544.                         $out['text'] .= '                       </div>';
  545.                         $out['text'] .= '  </div></div>';
  546.  
  547.                         $out['text'] .= '<script>document.getElementById("oidinfoMainArea").style.visibility = "visible";</script>';
  548.                 }
  549.         }
  550.  
  551.         public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
  552.                 if (!OIDplus::authUtils()::isAdminLoggedIn()) return false;
  553.  
  554.                 if (file_exists(__DIR__.'/treeicon.png')) {
  555.                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon.png';
  556.                 } else {
  557.                         $tree_icon = null; // default icon (folder)
  558.                 }
  559.  
  560.                 $json[] = array(
  561.                         'id' => 'oidplus:datatransfer',
  562.                         'icon' => $tree_icon,
  563.                         'text' => _L('Data Transfer')
  564.                 );
  565.  
  566.                 return true;
  567.         }
  568.  
  569.         public function tree_search($request) {
  570.                 return false;
  571.         }
  572.  
  573.         public static function outputXML($only_non_existing) {
  574.                 // This file contains class OIDInfoAPI.
  575.                 // We cannot include this in init(), because the init
  576.                 // of the registration plugin (OIDplusPageAdminRegistration) uses
  577.                 // OIDplusPageAdminOIDInfoExport::outputXML() before
  578.                 // OIDplusPageAdminOIDInfoExport::init() ,
  579.                 // because OIDplusPageAdminRegistration::init() comes first sometimes.
  580.                 require_once __DIR__ . '/oidinfo_api.inc.php';
  581.  
  582.                 $oa = new OIDInfoAPI();
  583.                 $oa->addSimplePingProvider('viathinksoft.de:49500');
  584.  
  585.                 $email = OIDplus::config()->getValue('admin_email');
  586.                 if (empty($email)) $email = 'unknown@example.com';
  587.  
  588.                 echo $oa->xmlAddHeader(OIDplus::config()->getValue('system_title'), isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'Export interface', $email); // do not translate
  589.  
  590.                 $params['allow_html'] = true;
  591.                 $params['allow_illegal_email'] = true; // It should be enabled, because the creator could have used some kind of human-readable anti-spam technique
  592.                 $params['soft_correct_behavior'] = OIDInfoAPI::SOFT_CORRECT_BEHAVIOR_NONE;
  593.                 $params['do_online_check'] = false; // Flag to disable this online check, because it generates a lot of traffic and runtime.
  594.                 $params['do_illegality_check'] = true;
  595.                 $params['do_simpleping_check'] = $only_non_existing;
  596.                 $params['auto_extract_name'] = '';
  597.                 $params['auto_extract_url'] = '';
  598.                 $params['always_output_comment'] = false;
  599.                 $params['creation_allowed_check'] = $only_non_existing;
  600.                 $params['tolerant_htmlentities'] = true;
  601.                 $params['ignore_xhtml_light'] = false;
  602.  
  603.                 $nonConfidential = OIDplusObject::getAllNonConfidential();
  604.                 natsort($nonConfidential);
  605.  
  606.                 foreach ($nonConfidential as $id) {
  607.                         $res = OIDplus::db()->query("select * from ###objects where id = ?", array($id));
  608.                         if ($row = $res->fetch_object()) {
  609.                                 $elements['identifier'] = array();
  610.                                 $res2 = OIDplus::db()->query("select * from ###asn1id where oid = ?", array($row->id));
  611.                                 while ($row2 = $res2->fetch_object()) {
  612.                                         $elements['identifier'][] = $row2->name; // 'unicode-label' is currently not in the standard format (oid.xsd)
  613.                                 }
  614.  
  615.                                 $elements['unicode-label'] = array();
  616.                                 $res2 = OIDplus::db()->query("select * from ###iri where oid = ?", array($row->id));
  617.                                 while ($row2 = $res2->fetch_object()) {
  618.                                         $elements['unicode-label'][] = $row2->name;
  619.                                 }
  620.  
  621.                                 if (!empty($row->title)) {
  622.                                         $elements['description'] = $row->title;
  623.                                         $elements['information'] = $row->description;
  624.                                         if (trim($row->title) == trim(strip_tags($row->description))) {
  625.                                                 $elements['information'] = '';
  626.                                         }
  627.                                 } else if (isset($elements['identifier'][0])) {
  628.                                         $elements['description'] = '"'.$elements['identifier'][0].'"';
  629.                                         $elements['information'] = $row->description;
  630.                                 } else if (isset($elements['unicode-label'][0])) {
  631.                                         $elements['description'] = '"'.$elements['unicode-label'][0].'"';
  632.                                         $elements['information'] = $row->description;
  633.                                 } else if (!empty($row->description)) {
  634.                                         $elements['description'] = $row->description;
  635.                                         $elements['information'] = '';
  636.                                 } else if (!empty($row->comment)) {
  637.                                         $elements['description'] = $row->comment;
  638.                                         $elements['information'] = '';
  639.                                 } else {
  640.                                         $elements['description'] = '<i>No description available</i>'; // do not translate
  641.                                         $elements['information'] = '';
  642.                                 }
  643.  
  644.                                 if ($elements['information'] != '') {
  645.                                         $elements['information'] .= '<br/><br/>';
  646.                                 }
  647.  
  648.                                 $elements['information'] .= 'See <a href="'.OIDplus::getSystemUrl(false).'?goto='.urlencode($id).'">more information</a>.'; // do not translate
  649.  
  650.                                 if (explode(':',$id,2)[0] != 'oid') {
  651.                                         $elements['information'] = "Object: $id\n\n" . $elements['information']; // do not translate
  652.                                 }
  653.  
  654.                                 $elements['description'] = self::repair_relative_links($elements['description']);
  655.                                 $elements['information'] = self::repair_relative_links($elements['information']);
  656.  
  657.                                 $elements['first-registrant']['first-name'] = '';
  658.                                 $elements['first-registrant']['last-name'] = '';
  659.                                 $elements['first-registrant']['address'] = '';
  660.                                 $elements['first-registrant']['email'] = '';
  661.                                 $elements['first-registrant']['phone'] = '';
  662.                                 $elements['first-registrant']['fax'] = '';
  663.                                 $elements['first-registrant']['creation-date'] = self::_formatdate($row->created);
  664.  
  665.                                 $elements['current-registrant']['first-name'] = '';
  666.                                 $elements['current-registrant']['last-name'] = '';
  667.                                 $elements['current-registrant']['email'] = $row->ra_email;
  668.                                 $elements['current-registrant']['phone'] = '';
  669.                                 $elements['current-registrant']['fax'] = '';
  670.                                 $elements['current-registrant']['address'] = '';
  671.  
  672.                                 $res2 = OIDplus::db()->query("select * from ###ra where email = ?", array($row->ra_email));
  673.                                 if ($res2->num_rows() > 0) {
  674.                                         $row2 = $res2->fetch_object();
  675.  
  676.                                         $tmp = array();
  677.                                         if (!empty($row2->personal_name)) {
  678.                                                 $name_ary = split_firstname_lastname($row2->personal_name);
  679.                                                 $elements['current-registrant']['first-name'] = $name_ary[0];
  680.                                                 $elements['current-registrant']['last-name']  = $name_ary[1];
  681.                                                 if (!empty($row2->ra_name)       ) $tmp[] = $row2->ra_name;
  682.                                                 if (!empty($row2->office)        ) $tmp[] = $row2->office;
  683.                                                 if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
  684.                                         } else {
  685.                                                 $elements['current-registrant']['first-name'] = $row2->ra_name;
  686.                                                 $elements['current-registrant']['last-name']  = '';
  687.                                                 if (!empty($row2->personal_name) ) $tmp[] = $row2->personal_name;
  688.                                                 if (!empty($row2->office)        ) $tmp[] = $row2->office;
  689.                                                 if (!empty($row2->organization)  ) $tmp[] = $row2->organization;
  690.                                         }
  691.  
  692.                                         if ((count($tmp) > 0) && ($tmp[0] == $row2->ra_name)) array_shift($tmp);
  693.                                         array_unique($tmp);
  694.  
  695.                                         if (!$row2->privacy) {
  696.                                                 if (!empty($row2->street))   $tmp[] = $row2->street;
  697.                                                 if (!empty($row2->zip_town)) $tmp[] = $row2->zip_town;
  698.                                                 if (!empty($row2->country))  $tmp[] = $row2->country;
  699.                                                 $elements['current-registrant']['phone'] = !empty($row2->phone) ? $row2->phone : $row2->mobile;
  700.                                                 $elements['current-registrant']['fax'] = $row2->fax;
  701.                                         }
  702.                                         if (empty($row2->zip_town) && empty($row2->country)) {
  703.                                                 // The address is useless if we do neither know city nor country
  704.                                                 // Ignore it
  705.                                                 $elements['current-registrant']['address'] = '';
  706.                                         } else {
  707.                                                 $elements['current-registrant']['address'] = implode("<br/>", $tmp);
  708.                                         }
  709.                                 }
  710.                                 $elements['current-registrant']['modification-date'] = self::_formatdate($row->updated);
  711.  
  712.                                 // Request from O.D. 20 May 2019: First registrant should not be empty (especially for cases where Creation and Modify Dates are the same)
  713.                                 // Actually, this is a problem because we don't know the first registrant.
  714.                                 // However, since oidinfo gets their XML very fast (if using registration), it is likely that the reported RA is still the same...
  715.                                 // ... and changes at the RA are not reported to oid-info.com anyways - the XML is only for creation
  716.  
  717.                                 $elements['first-registrant']['first-name'] = $elements['current-registrant']['first-name'];
  718.                                 $elements['first-registrant']['last-name']  = $elements['current-registrant']['last-name'];
  719.                                 $elements['first-registrant']['address']    = $elements['current-registrant']['address'];
  720.                                 $elements['first-registrant']['email']      = $elements['current-registrant']['email'];
  721.                                 $elements['first-registrant']['phone']      = $elements['current-registrant']['phone'];
  722.                                 $elements['first-registrant']['fax']        = $elements['current-registrant']['fax'];
  723.  
  724.                                 $elements['current-registrant']['first-name'] = '';
  725.                                 $elements['current-registrant']['last-name'] = '';
  726.                                 $elements['current-registrant']['address'] = '';
  727.                                 $elements['current-registrant']['email'] = '';
  728.                                 $elements['current-registrant']['phone'] = '';
  729.                                 $elements['current-registrant']['fax'] = '';
  730.                                 $elements['current-registrant']['modification-date'] = '';
  731.  
  732.                                 // End request O.D. 20 May 2019
  733.  
  734.                                 $obj = OIDplusObject::parse($row->id);
  735.  
  736.                                 list($ns,$id) = explode(':',$obj->nodeId());
  737.                                 if ($ns == 'oid') {
  738.                                         echo $oa->createXMLEntry($id, $elements, $params, $comment=$obj->nodeId());
  739.                                 }
  740.  
  741.                                 $alt_ids = $obj->getAltIds(); // TODO: slow!
  742.                                 foreach ($alt_ids as $alt_id) {
  743.                                         $ns = $alt_id->getNamespace();
  744.                                         $id = $alt_id->getId();
  745.                                         $desc = $alt_id->getDescription();
  746.                                         if ($ns == 'oid') {
  747.                                                 if (strpos($id, '2.25.') === 0) continue; // don't spam the uuid arc with GUID objects
  748.                                                 echo $oa->createXMLEntry($id, $elements, $params, $comment=$obj->nodeId());
  749.                                         }
  750.                                 }
  751.                         }
  752.                 }
  753.  
  754.                 echo $oa->xmlAddFooter();
  755.         }
  756.  
  757.         private static function _formatdate($str) {
  758.                 $str = explode(' ',$str)[0];
  759.                 if ($str == '0000-00-00') $str = '';
  760.                 return $str;
  761.         }
  762.  
  763.         private static function repair_relative_links($str) {
  764.                 $str = preg_replace_callback('@(href\s*=\s*([\'"]))(.+)(\\2)@ismU', function($treffer) {
  765.                         $url = $treffer[3];
  766.                         if ((stripos($url,'http:') !== 0) && (stripos($url,'https:') !== 0) && (stripos($url,'ftp:') !== 0)) {
  767.                                 if (stripos($url,'www.') === 0) {
  768.                                         $url .= 'http://' . $url;
  769.                                 } else {
  770.                                         $url = OIDplus::getSystemUrl() . $url;
  771.                                 }
  772.                         }
  773.                         return $treffer[1].$url.$treffer[4];
  774.                 }, $str);
  775.                 return $str;
  776.         }
  777.  
  778.         private static function split_address_country($address) {
  779.                 global $oidinfo_countries;
  780.                 $ary = explode("\n", $address);
  781.                 $last_line = array_pop($ary);
  782.                 $rest = implode("\n", $ary);
  783.                 if (isset($oidinfo_countries[$last_line])) {
  784.                         return array($rest, $oidinfo_countries[$last_line]);
  785.                 } else {
  786.                         return array($rest."\n".$last_line, '');
  787.                 }
  788.         }
  789.  
  790.         private static function split_name($name) {
  791.                 // uses regex that accepts any word character or hyphen in last name
  792.                 // https://stackoverflow.com/questions/13637145/split-text-string-into-first-and-last-name-in-php
  793.                 $name = trim($name);
  794.                 $last_name = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name);
  795.                 $first_name = trim( preg_replace('#'.$last_name.'#', '', $name ) );
  796.                 return array($first_name, $last_name);
  797.         }
  798.  
  799.         /*protected*/ const ORPHAN_IGNORE = 0;
  800.         /*protected*/ const ORPHAN_AUTO_DEORPHAN = 1;
  801.         /*protected*/ const ORPHAN_DISALLOW_ORPHANS = 2;
  802.  
  803.         protected function oidinfoImportXML($xml_contents, &$errors, $replaceExistingOIDs=false, $orphan_mode=self::ORPHAN_AUTO_DEORPHAN) {
  804.                 // TODO XXX: Implement RA import (let the user decide)
  805.                 // TODO XXX: Let the user decide about $replaceExistingOIDs
  806.                 // TODO XXX: Let the user decide if "created=now" should be set (this is good when the XML files is created by the user itself to do bulk-inserts)
  807.  
  808.                 $xml_contents = str_replace('<description>', '<description><![CDATA[', $xml_contents);
  809.                 $xml_contents = str_replace('</description>', ']]></description>', $xml_contents);
  810.  
  811.                 $xml_contents = str_replace('<information>', '<information><![CDATA[', $xml_contents);
  812.                 $xml_contents = str_replace('</information>', ']]></information>', $xml_contents);
  813.  
  814.                 $xml = @simplexml_load_string($xml_contents);
  815.  
  816.                 $count_already_existing = 0;
  817.                 $count_errors = 0;
  818.                 $count_warnings = 0;
  819.  
  820.                 if (!$xml) {
  821.                         $errors[] = _L('Cannot read XML data. The XML file is probably invalid.');
  822.                         $count_errors++;
  823.                         return array(0, 0, 1, 0);
  824.                 }
  825.  
  826.                 $ok_oids = array();
  827.  
  828.                 foreach ($xml->oid as $xoid) {
  829.  
  830.                         if (isset($xoid->{'dot-notation'})) {
  831.                                 $dot_notation = $xoid->{'dot-notation'}->__toString();
  832.                         } else if (isset($xoid->{'asn1-notation'})) {
  833.                                 $dot_notation = asn1_to_dot($xoid->{'asn1-notation'}->__toString());
  834.                         } else {
  835.                                 $errors[] = _L('Cannot find dot notation because fields asn1-notation and dot-notation are both not existing');
  836.                                 $count_errors++;
  837.                                 continue;
  838.                         }
  839.  
  840.                         $id = "oid:$dot_notation";
  841.                         $title = isset($xoid->{'description'}) ? $xoid->{'description'}->__toString() : '';
  842.                         $info = isset($xoid->{'description'}) ? $xoid->{'information'}->__toString() : '';
  843.  
  844.                         if (isset($xoid->{'current-registrant'}->email)) {
  845.                                 $ra = $xoid->{'current-registrant'}->email->__toString();
  846.                         } else if (isset($xoid->{'first-registrant'}->email)) {
  847.                                 $ra = $xoid->{'first-registrant'}->email->__toString();
  848.                         } else {
  849.                                 $ra = '';
  850.                         }
  851.  
  852.                         if (!oid_valid_dotnotation($dot_notation, false, false)) {
  853.                                 $errors[] = _L('Ignored OID %1 because its dot notation is illegal or was not found',$dot_notation);
  854.                                 $count_errors++;
  855.                                 continue;
  856.                         }
  857.  
  858.                         $parent = 'oid:'.oid_up($dot_notation);
  859.  
  860.                         if ($orphan_mode === self::ORPHAN_DISALLOW_ORPHANS) {
  861.                                 $res = OIDplus::db()->query("select * from ###objects where id = ?", array($parent));
  862.                                 if ($res->num_rows() === 0) {
  863.                                         $errors[] = _L('Cannot import %1, because its parent is not in the database.',$dot_notation);
  864.                                         $count_errors++;
  865.                                         continue;
  866.                                 }
  867.                         }
  868.  
  869.                         $res = OIDplus::db()->query("select * from ###objects where id = ?", array($id));
  870.                         if ($res->num_rows() > 0) {
  871.                                 if ($replaceExistingOIDs) {
  872.                                         // TODO: better do this (and the following insert) as transaction
  873.                                         OIDplus::db()->query("delete from ###asn1id where oid = ?", array($id));
  874.                                         OIDplus::db()->query("delete from ###iri where oid = ?", array($id));
  875.                                         OIDplus::db()->query("delete from ###objects where id = ?", array($id));
  876.                                 } else {
  877.                                         //$errors[] = "Ignore OID '$dot_notation' because it already exists";
  878.                                         //$count_errors++;
  879.                                         $count_already_existing++;
  880.                                         continue;
  881.                                 }
  882.                         }
  883.  
  884.                         OIDplus::db()->query("insert into ###objects (id, parent, title, description, confidential, ra_email) values (?, ?, ?, ?, ?, ?)", array($id, $parent, $title, $info, 0, $ra));
  885.  
  886.                         $this_oid_has_warnings = false;
  887.  
  888.                         // ---------------------------------------------------------------------
  889.  
  890.                         $asn1ids = array();
  891.                         if (isset($xoid->{'identifier'})) {
  892.                                 $asn1ids[] = $xoid->{'identifier'}->__toString();
  893.                         }
  894.                         if (isset($xoid->{'asn1-notation'})) {
  895.                                 $last_id = asn1_last_identifier($xoid->{'asn1-notation'}->__toString());
  896.                                 if ($last_id) {
  897.                                         $asn1ids[] = $last_id;
  898.                                 }
  899.                         }
  900.                         if (isset($xoid->{'synonymous-identifier'})) {
  901.                                 foreach ($xoid->{'synonymous-identifier'} as $synid) {
  902.                                         $asn1ids[] = $synid->__toString();
  903.                                 }
  904.                         }
  905.                         $asn1ids = array_unique($asn1ids);
  906.                         foreach ($asn1ids as $asn1id) {
  907.                                 if (!oid_id_is_valid($asn1id)) {
  908.                                         $errors[] = _L('Warning').' ['._L('OID %1',$dot_notation).']: '._L('Ignored alphanumeric identifier %1, because it is invalid',$asn1id);
  909.                                         $this_oid_has_warnings = true;
  910.                                 } else {
  911.                                         OIDplus::db()->query("delete from ###asn1id where oid = ? and name = ?", array($id, $asn1id));
  912.                                         OIDplus::db()->query("insert into ###asn1id (oid, name) values (?, ?)", array($id, $asn1id));
  913.                                 }
  914.                         }
  915.  
  916.                         // ---------------------------------------------------------------------
  917.  
  918.                         if (isset($xoid->{'unicode-label'})) {
  919.                                 $iris = array();
  920.                                 foreach ($xoid->{'unicode-label'} as $iri) {
  921.                                         $iris[] = $iri->__toString();
  922.                                 }
  923.                                 $iris = array_unique($iris);
  924.                                 foreach ($iris as $iri) {
  925.                                         if (!iri_arc_valid($iri, false)) {
  926.                                                 $errors[] = _L('Warning').' ['._L('OID %1',$dot_notation).']: '._L('Ignored Unicode label %1, because it is invalid',$iri);
  927.                                                 $this_oid_has_warnings = true;
  928.                                         } else {
  929.                                                 OIDplus::db()->query("delete from ###iri where oid = ? and name = ?", array($id, $iri));
  930.                                                 OIDplus::db()->query("insert into ###iri (oid, name) values (?, ?)", array($id, $iri));
  931.                                         }
  932.                                 }
  933.                         }
  934.  
  935.                         if ($this_oid_has_warnings) $count_warnings++;
  936.                         $ok_oids[] = $id;
  937.                 }
  938.  
  939.                 // De-orphanize
  940.                 //if ($orphan_mode === self::ORPHAN_AUTO_DEORPHAN) OIDplus::db()->query("update ###objects set parent = 'oid:' where parent like 'oid:%' and parent not in (select id from ###objects)");
  941.                 foreach ($ok_oids as $id) {
  942.                         // De-orphanize if neccessary
  943.                         if ($orphan_mode === self::ORPHAN_AUTO_DEORPHAN) {
  944.                                 $res = OIDplus::db()->query("select * from ###objects where id = ? and parent not in (select id from ###objects)", array($id));
  945.                                 if ($res->num_rows() > 0) {
  946.                                         $errors[] = _L("%1 was de-orphaned (placed as root OID) because its parent is not existing.",$id);
  947.                                         $count_warnings++;
  948.                                         OIDplus::db()->query("update ###objects set parent = 'oid:' where id = ? and parent not in (select id from ###objects)", array($id));
  949.                                 }
  950.                         }
  951.  
  952.                         // We do the logging at the end, otherwise SUPOIDRA() might not work correctly if the OIDs were not imported in order or if there were orphans
  953.                         OIDplus::logger()->log("[INFO]OID($id)+[INFO]SUPOID($id)+[INFO]SUPOIDRA($id)!/[INFO]A!", "Object '$id' was automatically created by the XML import tool");
  954.                 }
  955.  
  956.                 $count_imported_oids = count($ok_oids);
  957.  
  958.                 return array($count_imported_oids, $count_already_existing, $count_errors, $count_warnings);
  959.  
  960.         }
  961.  
  962. }