Subversion Repositories oidplus

Compare Revisions

No changes between revisions

Regard whitespace Rev 225 → Rev 226

/trunk_oldversion/includes/.htaccess
0,0 → 1,3
Order Deny,Allow
Deny From All
 
/trunk_oldversion/includes/OidDerConverter.class.phps
0,0 → 1,380
<?php
 
/*
* OidDerConverter.class.php, Version 1.1; Based on version 1.11 of oid.c
* Copyright 2014-2015 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
 
// Note: Leading zeros are permitted in dotted notation.
 
// TODO: define output format as parameter; don't force the user to use hexStrToArray
 
class OidDerConverter {
 
/**
* @arg $str "\x12\x23" or "12 34"
* @return array(0x12, 0x23)
*/
// Doesn't need to be public, but it is a nice handy function, especially in the testcases
public static function hexStrToArray($str) {
$out = array();
 
$str = str_replace('\x', ' ', $str);
$str = trim($str);
$ary = explode(' ', $str);
 
foreach ($ary as &$a) {
$out[] = hexdec($a);
}
 
return $out;
}
 
/**
* @return Outputs .<oid> for an absolute OID and <oid> for a relative OID.
*/
public static function derToOID($abBinary, $verbose=false) {
$output_oid = array();
$output_absolute = true;
 
if (count($abBinary) < 3) {
if ($verbose) fprintf(STDERR, "Encoded OID must have at least three bytes!\n");
return false;
}
 
$nBinary = count($abBinary);
$ll = gmp_init(0);
$fOK = false;
$fSub = 0; // Subtract value from next number output. Used when encoding {2 48} and up
 
// 0 = Universal Class Identifier Tag (can be more than 1 byte, but not in our case)
// 1 = Length part (may have more than 1 byte!)
// 2 = First two arc encoding
// 3 = Encoding of arc three and higher
$part = 0;
 
$lengthbyte_count = 0;
$lengthbyte_pos = 0;
$lengthfinished = false;
 
$arcBeginning = true;
 
foreach ($abBinary as $nn => &$pb) {
if ($part == 0) { // Class Tag
// Leading octet
// Bit 7 / Bit 6 = Universal (00), Application (01), Context (10), Private(11)
// Bit 5 = Primitive (0), Constructed (1)
// Bit 4..0 = 00000 .. 11110 => Tag 0..30, 11111 for Tag > 30 (following bytes with the highest bit as "more" bit)
// --> We don't need to respect 11111 (class-tag encodes in more than 1 octet)
// as we terminate when the tag is not of type OID or RELATEIVE-OID
// See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson.
 
// Class: 8. - 7. bit
// 0 (00) = Universal
// 1 (01) = Application
// 2 (10) = Context
// 3 (11) = Private
$cl = (($pb & 0xC0) >> 6) & 0x03;
if ($cl != 0) {
if ($verbose) fprintf(STDERR, "Error at type: The OID tags are only defined as UNIVERSAL class tags.\n");
return false;
}
 
// Primitive/Constructed: 6. bit
// 0 = Primitive
// 1 = Constructed
$pc = $pb & 0x20;
if ($pc != 0) {
if ($verbose) fprintf(STDERR, "Error at type: OIDs must be primitive, not constructed.\n");
return false;
}
 
// Tag number: 5. - 1. bit
$tag = $pb & 0x1F;
if ($tag == 0x0D) {
$isRelative = true;
} else if ($tag == 0x06) {
$isRelative = false;
} else {
if ($verbose) fprintf(STDERR, "Error at type: The tag number is neither an absolute OID (0x06) nor a relative OID (0x0D).\n");
return false;
}
 
// Output
$output_absolute = !$isRelative;
 
$part++;
} else if ($part == 1) { // Length
// Find out the length and save it into $ll
 
// [length] is encoded as follows:
// 0x00 .. 0x7F = The actual length is in this byte, followed by [data].
// 0x80 + n = The length of [data] is spread over the following 'n' bytes. (0 < n < 0x7F)
// 0x80 = "indefinite length" (only constructed form) -- Invalid
// 0xFF = Reserved for further implementations -- Invalid
// See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson.
 
if ($nn == 1) { // The first length byte
$lengthbyte_pos = 0;
if (($pb & 0x80) != 0) {
// 0x80 + n => The length is spread over the following 'n' bytes
$lengthfinished = false;
$lengthbyte_count = $pb & 0x7F;
if ($lengthbyte_count == 0x00) {
if ($verbose) fprintf(STDERR, "Length value 0x80 is invalid (\"indefinite length\") for primitive types.\n");
return false;
} else if ($lengthbyte_count == 0x7F) {
if ($verbose) fprintf(STDERR, "Length value 0xFF is reserved for further extensions.\n");
return false;
}
$fOK = false;
} else {
// 0x01 .. 0x7F => The actual length
 
if ($pb == 0x00) {
if ($verbose) fprintf(STDERR, "Length value 0x00 is invalid for an OID.\n");
return false;
}
 
$ll = gmp_init($pb);
$lengthfinished = true;
$lengthbyte_count = 0;
$fOK = true;
}
} else {
if ($lengthbyte_count > $lengthbyte_pos) {
$ll = gmp_mul($ll, 0x100);
$ll = gmp_add($ll, $pb);
$lengthbyte_pos++;
}
 
if ($lengthbyte_count == $lengthbyte_pos) {
$lengthfinished = true;
$fOK = true;
}
}
 
if ($lengthfinished) { // The length is now in $ll
if (gmp_cmp($ll, $nBinary - 2 - $lengthbyte_count) != 0) {
if ($verbose) fprintf(STDERR, "Invalid length (%d entered, but %s expected)\n", $nBinary - 2, gmp_strval($ll, 10));
return false;
}
$ll = gmp_init(0); // reset for later usage
$fOK = true;
$part++;
if ($isRelative) $part++; // Goto step 3!
}
} else if ($part == 2) { // First two arcs
$first = $pb / 40;
$second = $pb % 40;
if ($first > 2) {
$first = 2;
$output_oid[] = $first;
$arcBeginning = true;
 
if (($pb & 0x80) != 0) {
// 2.48 and up => 2+ octets
// Output in "part 3"
 
if ($arcBeginning && ($pb == 0x80)) {
if ($verbose) fprintf(STDERR, "Encoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n");
return false;
} else {
$arcBeginning = false;
}
 
$ll = gmp_add($ll, ($pb & 0x7F));
$fSub = 80;
$fOK = false;
} else {
// 2.0 till 2.47 => 1 octet
$second = $pb - 80;
$output_oid[] = $second;
$arcBeginning = true;
$fOK = true;
$ll = gmp_init(0);
}
} else {
// 0.0 till 0.37 => 1 octet
// 1.0 till 1.37 => 1 octet
$output_oid[] = $first;
$output_oid[] = $second;
$arcBeginning = true;
$fOK = true;
$ll = gmp_init(0);
}
$part++;
} else if ($part == 3) { // Arc three and higher
if (($pb & 0x80) != 0) {
if ($arcBeginning && ($pb == 0x80)) {
if ($verbose) fprintf(STDERR, "Encoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n");
return false;
} else {
$arcBeginning = false;
}
 
$ll = gmp_mul($ll, 0x80);
$ll = gmp_add($ll, ($pb & 0x7F));
$fOK = false;
} else {
$fOK = true;
$ll = gmp_mul($ll, 0x80);
$ll = gmp_add($ll, $pb);
$ll = gmp_sub($ll, $fSub);
$output_oid[] = gmp_strval($ll, 10);
 
// Happens only if 0x80 paddings are allowed
// $fOK = gmp_cmp($ll, 0) >= 0;
$ll = gmp_init(0);
$fSub = 0;
$arcBeginning = true;
}
}
}
 
if (!$fOK) {
if ($verbose) fprintf(STDERR, "Encoding error. The OID is not constructed properly.\n");
return false;
}
 
return ($output_absolute ? '.' : '').implode('.', $output_oid);
}
 
// Doesn't need to be public, but it is a nice handy function, especially in the testcases
public static function hexarrayToStr($ary, $nCHex=false) {
$str = '';
if ($ary === false) return false;
foreach ($ary as &$a) {
if ($nCHex) {
$str .= sprintf("\"\\x%02X", $a);
} else {
$str .= sprintf("%02X ", $a);
}
}
return trim($str);
}
 
public static function oidToDER($oid, $isRelative=false, $verbose=false) {
if ($oid[0] == '.') { // MIB notation
$oid = substr($oid, 1);
$isRelative = false;
}
 
$cl = 0x00; // Class. Always UNIVERSAL (00)
 
// Tag for Universal Class
if ($isRelative) {
$cl |= 0x0D;
} else {
$cl |= 0x06;
}
 
$arcs = explode('.', $oid);
 
$b = 0;
$isjoint = false;
$abBinary = array();
 
if ((!$isRelative) && (count($arcs) < 2)) {
if ($verbose) fprintf(STDERR, "Encoding error. The minimum depth of an encodeable absolute OID is 2. (e.g. 2.999)\n");
return false;
}
 
foreach ($arcs as $n => &$arc) {
if (!preg_match('@^\d+$@', $arc)) {
if ($verbose) fprintf(STDERR, "Encoding error. Arc '%s' is invalid.\n", $arc);
return false;
}
 
$l = gmp_init($arc, 10);
 
if ((!$isRelative) && ($n == 0)) {
if (gmp_cmp($l, 2) > 0) {
if ($verbose) fprintf(STDERR, "Encoding error. The top arc is limited to 0, 1 and 2.\n");
return false;
}
$b += 40 * gmp_intval($l);
$isjoint = gmp_cmp($l, 2) == 0;
} else if ((!$isRelative) && ($n == 1)) {
if ((!$isjoint) && (gmp_cmp($l, 39) > 0)) {
if ($verbose) fprintf(STDERR, "Encoding error. The second arc is limited to 0..39 for root arcs 0 and 1.\n");
return false;
}
 
if (gmp_cmp($l, 47) > 0) {
$l = gmp_add($l, 80);
self::makeBase128($l, 1, $abBinary);
} else {
$b += gmp_intval($l);
$abBinary[] = $b;
}
} else {
self::makeBase128($l, 1, $abBinary);
}
}
 
$output = array();
 
// Write class-tag
$output[] = $cl;
 
// Write length
$nBinary = count($abBinary);
if ($nBinary <= 0x7F) {
$output[] = $nBinary;
} else {
$lengthCount = 0;
$nBinaryWork = $nBinary;
do {
$lengthCount++;
$nBinaryWork /= 0x100;
} while ($nBinaryWork > 0);
 
if ($lengthCount >= 0x7F) {
if ($verbose) fprintf(STDERR, "The length cannot be encoded.\n");
return false;
}
 
$output[] = 0x80 + $lengthCount;
 
$nBinaryWork = $nBinary;
do {
$output[] = nBinaryWork & 0xFF;
$nBinaryWork /= 0x100;
} while ($nBinaryWork > 0);
}
 
foreach ($abBinary as $b) {
$output[] = $b;
}
 
return $output;
}
 
protected static function makeBase128($l, $first, &$abBinary) {
if (gmp_cmp($l, 127) > 0) {
$l2 = gmp_div($l, 128);
self::makeBase128($l2 , 0, $abBinary);
}
$l = gmp_mod($l, 128);
 
if ($first) {
$abBinary[] = gmp_intval($l);
} else {
$abBinary[] = 0x80 | gmp_intval($l);
}
}
}
/trunk_oldversion/includes/config.inc.php
0,0 → 1,21
<?php
 
require_once __DIR__.'/oid_utils.inc.php';
 
# TODO: diese konfiguration auch zur konfiguration von "is oid valid" nutzen
# 0 = "."
# 1 = ".2"
# 2 = ".2.999"
define('HIGHLIGHT_OID_MINLEN', 2);
define('ALLOW_LEADING_ZEROES', false);
define('LEADING_DOT_POLICY', OID_DOT_OPTIONAL);
# define('HIGHLIGHT_REQUIRES_WHITESPACE_DELIMITERS', false);
 
define('OIDINFO_EXPORT_ENABLED', true);
define('OIDINFO_EXPORT_SUBMITTER_FIRST_NAME', 'Daniel');
define('OIDINFO_EXPORT_SUBMITTER_LAST_NAME', 'Marschall');
define('OIDINFO_EXPORT_SUBMITTER_EMAIL', 'info@daniel-marschall.de');
define('OIDINFO_EXPORT_SUBMITTER_ONLY_MONOSPACE', false); # False = auto determinate
 
define('OIDINFO_EXPORT_SIMPLEPINGPROVIDER', 'viathinksoft.de:49500'); // MUST show all oid-info.com values, not a local RA's OID repository!
 
/trunk_oldversion/includes/gui.inc.php
0,0 → 1,115
<?php
 
if (!defined('OID_REGEX')) {
define('OID_REGEX', oid_detection_regex(HIGHLIGHT_OID_MINLEN, ALLOW_LEADING_ZEROES, LEADING_DOT_POLICY, true /* HIGHLIGHT_REQUIRES_WHITESPACE_DELIMITERS */));
}
 
function queryInfo($query) {
return '<p class="green">Executed query <a href="?action=query&amp;query='.urlencode($query).'">'.htmlentities($query).'</a></p>';
}
 
function showHTML($cont, $db, $show_internal_links=true, $monospace=true) {
$cont = htmlentities($cont);
# $cont = str_replace(' ', '&nbsp;', $cont);
# $cont = nl2br($cont);
 
$rm = $db->getRedactedMessage();
 
# TODO: htmlentities() bei den indexes usw
# TODO: <...> problem - wird hinzugefĆ¼gt
 
# TODO: als plugins?
 
// Recognize index links
if ($show_internal_links) {
$cont = preg_replace('@(index(\\((.+)\\)|):\\s*)([^\\s#].+)@', '\\1<a href="?action=show_index&amp;ns=\\3&amp;index=\\4">\\4</a>', $cont);
}
 
// Recognize web links
$cont = preg_replace('@([a-zA-Z]+://[^\\s]+)@', '<a href="\\1">\\1</a>', $cont);
 
// Recognize E-Mail links
$cont = preg_replace('@([^\\s:]+)\\@([^\\s]+)@', '<a href="mailto:\\1(at)\\2">\\1(at)\\2</a>', $cont); # TODO: antispam
 
// Recognize OID links (with or without leading dot)
if ($show_internal_links) {
$cont = preg_replace(OID_REGEX, '<a href="?action=show_oid&amp;oid=\\1">\\1</a>', $cont);
} else {
$cont = preg_replace(OID_REGEX, '<a href="http://www.oid-info.com/get/\\1">\\1</a>', $cont);
}
 
// Decorate the "redacted" message
if ($show_internal_links) {
$cont = str_replace($rm, "<a href=\"?action=auth_tokens\" style=\"text-decoration:none\"><span style=\"background:black;color:white\">$rm</span></a>", $cont);
} else {
$cont = str_replace($rm, "<span style=\"background:black;color:white\">$rm</span>", $cont);
}
 
// Recognize all UUIDs (except if the UUID is already linked as uuid-index)
if ($show_internal_links) {
$cont = preg_replace('@\\b([A-Fa-f0-9]{8}\\-[A-Fa-f0-9]{4}\\-[A-Fa-f0-9]{4}\\-[A-Fa-f0-9]{4}\\-[A-Fa-f0-9]{12})\\b(?!</a>|">)@', '<a href="?action=uuid_info&amp;uuid=\\1">\\1</a>', $cont);
}
 
if (($monospace) && ($cont != '')) {
return '<pre>'.$cont.'</pre>';
} else {
return $cont;
}
}
 
function showException($e) {
ob_start();
if (!headers_sent()) header('HTTP/1.1 500 Internal Server Error');
$title = 'Database error';
echo page_header($title);
$msg = $e;
$msg = str_replace(__DIR__, '.', $msg);
?>
<h2><?php echo $title; ?></h2>
<p>An internal error occurred while reading the Volcano database. Please contact the administrator and try again later.</p>
<p>Error message:</p>
<p><pre><?php echo $msg; ?></pre></p>
<?php
echo page_footer();
$cont = ob_get_contents();
ob_end_clean();
return $cont;
}
 
function page_header($title='', $systemID='') { # TODO: w3c
ob_start();
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<?php if ($systemID) echo '<meta name="X-OidPlus-SystemID" content="'.$systemID.' ('.uuid_numeric_value($systemID).')" />'."\n"; ?>
<title><?php echo htmlentities($title); ?></title>
<link href="style.css" rel="stylesheet" type="text/css" />
<meta name="robots" content="noindex" /><!-- because system is outdated -->
</head>
 
<body>
 
<?php
$cont = ob_get_contents();
ob_end_clean();
return $cont;
}
 
function page_footer() { # TODO: auch version anzeigen
ob_start();
?>
 
<p style="text-align:center">OID+ web interface &copy; 2012 - <?php echo date('Y'); ?> <a href="http://www.viathinksoft.de/">ViaThinkSoft</a>.</p>
 
</body>
 
</html><?php
$cont = ob_get_contents();
ob_end_clean();
return $cont;
}
 
/trunk_oldversion/includes/ip_function.inc.php
0,0 → 1,61
<?php
 
/*
* IP functions
* Copyright 2015 Daniel Marschall, ViaThinkSoft
* Version 2015-10-27
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
function get_real_ip() {
/* Eindeutige IP Adresse erhalten, auch bei Proxies und (neu:) von SSH connections im CLI modus */
// http://lists.phpbar.de/pipermail/php/Week-of-Mon-20040322/007749.html
// Modificated by VTS
// Version: 2015-10-27
 
// TODO: ipv6
 
if (isset($_SERVER['SSH_CLIENT'])) { $ary = explode(' ', $_SERVER['SSH_CLIENT']); return $ary[0]; }
if (isset($_SERVER['SSH_CONNECTION'])) { $ary = explode(' ', $_SERVER['SSH_CONNECTION']); return $ary[0]; }
 
$client_ip = (isset($_SERVER['HTTP_CLIENT_IP'])) ? $_SERVER['HTTP_CLIENT_IP'] : '';
 
// It is not secure to use these, since they are not validated: http://www.thespanner.co.uk/2007/12/02/faking-the-unexpected/
// $x_forwarded_for = (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
$x_forwarded_for = '';
 
$remote_addr = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '';
 
if (!empty($client_ip)) {
$ip_expl = explode('.', $client_ip);
$referer = explode('.', $remote_addr);
if ($referer[0] != $ip_expl[0]) {
$ip = array_reverse($ip_expl);
$return = implode('.', $ip);
} else {
$return = $client_ip;
}
} else if (!empty($x_forwarded_for)) {
if (strstr($x_forwarded_for, ',')) {
$ip_expl = explode(',', $x_forwarded_for);
$return = end($ip_expl);
} else {
$return = $x_forwarded_for;
}
} else {
$return = $remote_addr;
}
unset ($client_ip, $x_forwarded_for, $remote_addr, $ip_expl);
return $return;
}
/trunk_oldversion/includes/ipv4_functions.inc.php
0,0 → 1,664
<?php
 
/*
* IPv4 functions for PHP
* Copyright 2012-2019 Daniel Marschall, ViaThinkSoft
* Version 2019-03-11
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
// TODO: oop, exceptions?
 
// Very small self-test:
/*
function ipv4_selftest() {
$iv_b = ipv4_complete('1.2');
$iv_m = 20;
$r = ipv4_cidr2range($iv_b, $iv_m);
echo "$iv_b/$iv_m => $r[0] - $r[1]\n";
 
$rev = ipv4_range2cidr($r[0], $r[1]);
$rev = implode("\n", $rev);
echo "$r[0] - $r[1] => $rev [";
$ok = $rev == "$iv_b/$iv_m";
echo $ok ? 'OK' : 'Mismatch';
echo "]\n";
echo "In-CIDR-Test: ";
echo ipv4_in_cidr("$iv_b/$iv_m", "$iv_b/$iv_m") ? 'OK' : 'Fail';
echo "\n";
}
ipv4_selftest();
*/
 
function ipv4_cidr2range($baseip_or_cidr, $subnet='') {
# (C) 2012 ViaThinkSoft
# Version 1.1
# This function converts an CIDR notation <baseip>/<subnet> into an IPv4 address block array($low_ip, $high_ip)
 
if (strpos($baseip_or_cidr, '/') !== false) {
$tmp = explode('/', $baseip_or_cidr, 2);
$baseip_or_cidr = $tmp[0];
$subnet = $tmp[1];
unset($tmp);
}
 
if (($subnet < 0) || ($subnet > 32)) return false;
 
$maxint32 = 0xFFFFFFFF;
$netmask = $maxint32 << (32-$subnet);
$netmask = $netmask & $maxint32; // crop to 32 bits
$wildcard = $maxint32 ^ $netmask; // ~$netmask;
 
$x = ipv4_incomplete_ip2long($baseip_or_cidr) & $netmask;
$nums = $wildcard;
$low = long2ip($x);
$high = long2ip($x + $nums);
 
return array($low, $high);
}
 
function ipv4_range2cidr($baseip, $topip, $shortening=false) {
# (C) 2012 ViaThinkSoft
# Version 1.0
# This function converts an IPv4 address block into valid CIDR blocks (There may be multiple blocks!)
 
$out = array();
if (ipv4_cmp($baseip, $topip) > 0) return false;
while (ipv4_incomplete_ip2long($baseip)-1 != ipv4_incomplete_ip2long($topip)) {
$i = -1;
do {
$i++;
$range = ipv4_cidr2range($baseip, $i);
$l = $range[0];
$t = $range[1];
} while ((ipv4_cmp($l, $baseip) != 0) || (ipv4_cmp($t, $topip) > 0));
 
# Shortening: Stroke ".0" at the end
if ($shortening) $baseip = ipv4_shortening($baseip);
 
$out[] = "$baseip/$i";
$baseip = ipv4_add($t, 1);
}
return $out;
}
 
function ipv4_shortening($ip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return preg_replace("|(\\.0{1,3}){0,3}\$|ismU", '', $ip);
}
 
function ipv4_add($baseip, $num) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return long2ip(ipv4_incomplete_ip2long($baseip) + $num);
}
 
function ipv4_sub($baseip, $num) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return long2ip(ipv4_incomplete_ip2long($baseip) - $num);
}
 
function ipv4_cmp($a, $b) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$a = ipv4_incomplete_ip2long($a);
$b = ipv4_incomplete_ip2long($b);
 
if ($a == $b) return 0;
if ($a < $b) return -1;
if ($a > $b) return 1;
}
 
function ipv4_in_cidr($haystack, $needle) {
# (C) 2012 ViaThinkSoft
# Version 1.1
 
$x = explode('/', $haystack);
$ha = ipv4_cidr2range($x[0], $x[1]);
 
$x = explode('/', $needle);
if (!isset($x[1])) $x[1] = '32'; // single IP
$ne = ipv4_cidr2range($x[0], $x[1]);
 
$ha_low = ipv4_incomplete_ip2long($ha[0]);
$ha_hig = ipv4_incomplete_ip2long($ha[1]);
$ne_low = ipv4_incomplete_ip2long($ne[0]);
$ne_hig = ipv4_incomplete_ip2long($ne[1]);
 
# HA: low[ ]high
# NE: low[ ]high
 
return ($ne_low >= $ha_low) && ($ne_hig <= $ha_hig);
}
 
function ipv4_complete($short_form) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$short_form = trim($short_form);
if ($short_form == '') return '0.0.0.0';
$c = substr_count($short_form, '.');
if ($c > 3) return false;
if ($c == 3) return $short_form;
$c = substr_count($short_form, '.');
$short_form .= str_repeat('.0', 3-$c);
return $short_form;
}
 
function ipv4_incomplete_ip2long($ip) {
# (C) 2012-2014 ViaThinkSoft
# Version 1.2
 
# return sprintf('%u', ip2long(ipv4_complete($ip)));
return sprintf('%u', ip2long(ipv4_normalize($ip)));
}
 
// IMPORTANT! $cmp_ary[x]=y MUST HAVE x<=y !
function ipv4_merge_address_blocks($data, $debug = false, $shortening = false) {
# (C) 2012-2013 ViaThinkSoft
# Version 2.2
 
if ($debug !== false) $STARTZEIT = time();
 
// 1. Convert IPs to numbers
 
$cmp_ary = array();
foreach ($data as $a => &$b) {
$a = ipv4_incomplete_ip2long($a);
$b = ipv4_incomplete_ip2long($b);
 
$cmp_ary[$a] = $b;
unset($a);
unset($b);
}
 
// 2. Sort array
 
ksort($cmp_ary);
 
// 3. Merge the blocks in an intelligent way (and remove redundant blocks)
 
# Merge overlapping blocks
# [ ]
# [ ] -> [ ]
 
# Merge neighbor blocks
# [ ][ ] -> [ ]
 
# Remove redundant blocks
# [ ] -> [ ]
# [ ]
 
$merge_count = 0;
$redundant_deleted_count = 0;
$round_count = 0;
do {
if ($debug !== false) {
$LAUFZEIT = time() - $STARTZEIT;
echo $debug."Merging... $round_count rounds; merged $merge_count blocks; deleted $redundant_deleted_count redundant blocks; time: $LAUFZEIT seconds\r";
}
 
$round_count++;
 
$clean = true;
 
foreach ($cmp_ary as $a => &$b) {
foreach ($cmp_ary as $x => &$y) {
// x in range [a+1..b+1] ?
if ($x<=$a) continue;
if ($x>$b+1) break;
 
// Merge
$clean = false;
if ($y>$b) {
$merge_count++;
$b = $y;
unset($cmp_ary[$x]);
} else {
$redundant_deleted_count++;
unset($cmp_ary[$x]);
}
}
}
} while (!$clean);
 
if ($debug !== false) {
$LAUFZEIT = time() - $STARTZEIT;
echo $debug."Merge completed. $round_count rounds; merged $merge_count blocks; deleted $redundant_deleted_count redundant blocks; time: $LAUFZEIT seconds\n";
}
 
// 4. Convert back to IPs
 
$out_ary = array();
foreach ($cmp_ary as $a => &$b) {
$a = long2ip($a);
$b = long2ip($b);
if ($shortening) {
$a = ipv4_shortening($a);
$b = ipv4_shortening($b);
}
$out_ary[$a] = $b;
}
 
return $out_ary;
}
 
function ipv4_merge_arrays($data_a, $data_b) {
# (C) 2012 ViaThinkSoft
# Version 1.2
 
$normalized_data_a = array();
foreach ($data_a as $from => &$to) {
$normalized_data_a[ipv4_normalize($from)] = ipv4_normalize($to);
}
 
$normalized_data_b = array();
foreach ($data_b as $from => &$to) {
$normalized_data_b[ipv4_normalize($from)] = ipv4_normalize($to);
}
 
$data = array();
 
foreach ($normalized_data_a as $from => &$to) {
if (isset($normalized_data_b[$from])) {
$data[$from] = ipv4_max($to, $normalized_data_b[$from]);
} else {
$data[$from] = $to;
}
}
 
foreach ($normalized_data_b as $from => &$to) {
if (!isset($normalized_data_a[$from])) {
$data[$from] = $to;
}
}
 
return $data;
}
 
function ipv4_valid($ip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
# return ipv4_incomplete_ip2long($ip) !== false;
return ip2long($ip) !== false;
}
 
function ipv4_normalize($ip) {
# (C) 2012-2013 ViaThinkSoft
# Version 1.1.1
 
# Example:
# 100.010.001.000 -> 100.10.1.0
 
$ip = ipv4_complete($ip);
if (!$ip) return false;
 
# ip2long buggy: 001.0.0.0 wird nicht akzeptiert
## $cry = explode('.', $ip);
## $cry[0] = preg_replace('@^0+@', '', $cry[0]); if ($cry[0] == '') $cry[0] = '0';
## $cry[1] = preg_replace('@^0+@', '', $cry[1]); if ($cry[1] == '') $cry[1] = '0';
## $cry[2] = preg_replace('@^0+@', '', $cry[2]); if ($cry[2] == '') $cry[2] = '0';
## $cry[3] = preg_replace('@^0+@', '', $cry[3]); if ($cry[3] == '') $cry[3] = '0';
## $ip = implode('.', $cry);
## return $ip;
 
return preg_replace('@^0{0,2}([0-9]{1,3})\.0{0,2}([0-9]{1,3})\.0{0,2}([0-9]{1,3})\.0{0,2}([0-9]{1,3})$@', '\\1.\\2.\\3.\\4', $ip);
}
 
function ipv4_expand($ip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
# Example:
# 100.10.1.0 -> 100.010.001.000
 
$ip = ipv4_complete($ip);
if (!$ip) return false;
 
$cry = explode('.', $ip);
$cry[0] = str_pad($cry[0], 3, '0', STR_PAD_LEFT);
$cry[1] = str_pad($cry[1], 3, '0', STR_PAD_LEFT);
$cry[2] = str_pad($cry[2], 3, '0', STR_PAD_LEFT);
$cry[3] = str_pad($cry[3], 3, '0', STR_PAD_LEFT);
return implode('.', $cry);
}
 
function ipv4_min($ip_a, $ip_b) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
if (ipv4_cmp($ip_a, $ip_b) == -1) {
return $ip_a;
} else {
return $ip_b;
}
}
 
function ipv4_max($ip_a, $ip_b) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
if (ipv4_cmp($ip_a, $ip_b) == 1) {
return $ip_a;
} else {
return $ip_b;
}
}
 
function ipv4_ipcount($data) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$cnt = 0;
 
foreach ($data as $from => &$to) {
$cnt += ipv4_incomplete_ip2long($to) - ipv4_incomplete_ip2long($from);
}
 
return $cnt;
}
 
function ipv4_read_file($file) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$data = array();
 
$lines = file($file);
foreach ($lines as &$line) {
$rng = ipv4_line2range($line);
$data[$rng[0]] = $rng[1];
}
 
return $data;
}
 
function ipv4_line2range($line) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$line = trim($line);
 
if (strpos($line, '/') !== false) {
$rng = ipv4_cidr2range($line);
} else {
$rng = explode('-', $line);
$rng[0] = trim($rng[0]);
$rng[1] = trim($rng[1]);
$rng[0] = ipv4_normalize($rng[0]);
if (!isset($rng[1])) $rng[1] = $rng[0];
$rng[1] = ipv4_normalize($rng[1]);
}
 
return $rng;
}
 
# --- New 16,12,12
 
define('IPV4_BITS', 32);
 
function ipv4_distance($ipOrCIDR_Searchterm, $ipOrCIDR_Candidate) {
$ary = ipv4_cidr_split($ipOrCIDR_Searchterm);
$ip = $ary[0];
 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
return false;
}
 
$ary = ipv4_cidr_split($ipOrCIDR_Candidate);
$ip = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
if (!is_numeric($cidr_bits)) return false;
 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
return false;
}
 
$x = ipv4_trackdown($ipOrCIDR_Searchterm);
 
if (ipv4_in_cidr($x[0], $ip.'/'.$cidr_bits)) {
$ary = ipv4_cidr_split($x[0]);
$cidr_bits2 = $ary[1];
if ($cidr_bits2 > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
return $cidr_bits2-$cidr_bits;
}
 
$i = 0;
$max = false;
foreach ($x as &$y) {
if (ipv4_in_cidr($ip.'/'.$cidr_bits, $y)) {
$max = $i;
}
$i++;
}
 
return $max;
}
 
function ipv4_cidr_split($ipOrCIDR) {
$ary = explode('/', $ipOrCIDR, 2);
$cidr_bits = isset($ary[1]) ? $ary[1] : IPV4_BITS;
if ($cidr_bits > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
if (!is_numeric($cidr_bits)) return false;
$ip = $ary[0];
return array($ip, $cidr_bits);
}
 
function ipv4_equals($ipOrCIDRA, $ipOrCIDRB) {
return ipv4_normalize_range($ipOrCIDRA) == ipv4_normalize_range($ipOrCIDRB);
}
 
function ipv4_cidr_min_ip($ipOrCIDR) {
$ary = ipv4_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$m = ip2bin($ipOrCIDR);
$m = substr($m, 0, $cidr_bits) . str_repeat('0', IPV4_BITS-$cidr_bits);
 
return bin2ip($m);
}
 
function ipv4_cidr_max_ip($ipOrCIDR) {
$ary = ipv4_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$m = ip2bin($ipOrCIDR);
$m = substr($m, 0, $cidr_bits) . str_repeat('1', IPV4_BITS-$cidr_bits);
 
return bin2ip($m);
}
 
function ipv4_normalize_range($ipOrCIDR) {
$ary = ipv4_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$m = ip2bin($ipOrCIDR);
$m = substr($m, 0, $cidr_bits) . str_repeat('0', IPV4_BITS-$cidr_bits);
 
return bin2ip($m) . '/' . $cidr_bits;
}
 
function ipv4_trackdown($ipOrCIDR) {
$ary = ipv4_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV4_BITS) return false; // throw new Exception('CIDR bits > '.IPV4_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$out = array();
$m = ip2bin($ipOrCIDR);
 
for ($i=$cidr_bits; $i>=0; $i--) {
$m = substr($m, 0, $i) . str_repeat('0', IPV4_BITS-$i);
$out[] = bin2ip($m) . '/' . $i;
}
 
return $out;
}
 
# ---
 
if (!function_exists('ip2bin')) {
function ip2bin($ip) {
# Source: http://php.net/manual/en/function.ip2long.php#104163
# modified by VTS
 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
return base_convert(ip2long($ip), 10, 2);
}
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
return false;
}
if (($ip_n = inet_pton($ip)) === false) {
return false;
}
$bits = 15; // 16 x 8 bit = 128bit (ipv6)
$ipbin = ''; # added by vts to avoid warning
while ($bits >= 0) {
$bin = sprintf('%08b', (ord($ip_n[$bits])));
$ipbin = $bin.$ipbin;
$bits--;
}
return $ipbin;
}
}
 
if (!function_exists('bin2ip')) {
function bin2ip($bin) {
# Source: http://php.net/manual/en/function.ip2long.php#104163
# modified by VTS
 
if (strlen($bin) <= 32) { // 32bits (ipv4)
return long2ip(base_convert($bin, 2, 10));
}
if (strlen($bin) != 128) {
return false;
}
$pad = 128 - strlen($bin);
for ($i = 1; $i <= $pad; $i++) {
$bin = '0'.$bin;
}
$bits = 0;
$ipv6 = ''; # added by vts to avoid warning
while ($bits <= 7) {
$bin_part = substr($bin,($bits*16),16);
$ipv6 .= dechex(bindec($bin_part)) . ':';
$bits++;
}
return inet_ntop(inet_pton(substr($ipv6, 0, -1)));
}
}
 
# --- TEST
 
/*
assert(ipv4_normalize('100.010.001.000') == '100.10.1.0');
assert(ipv4_normalize('100.010.01.000') == '100.10.1.0');
assert(ipv4_normalize('100.10.001.000') == '100.10.1.0');
assert(ipv4_normalize('1.010.001.000') == '1.10.1.0');
assert(ipv4_normalize('1.10.001.000') == '1.10.1.0');
 
assert(ipv4_distance('192.168.0.0/16', '192.168.64.0/18') == -2);
assert(ipv4_distance('192.168.0.0/17', '192.168.64.0/18') == -1);
assert(ipv4_distance('192.168.64.0/18', '192.168.64.0/18') == 0);
assert(ipv4_distance('192.168.64.0/19', '192.168.64.0/18') == 1);
assert(ipv4_distance('192.168.64.0/20', '192.168.64.0/18') == 2);
 
assert(ipv4_distance('192.168.69.202/31', '192.168.69.200/31') === false);
assert(ipv4_distance('192.168.69.201/32', '192.168.69.200/32') === false);
assert(ipv4_distance('192.168.69.201', '192.168.69.200') === false);
*/
 
/*
$test = '192.168.69.123';
$x = ipv4_trackdown($test);
foreach ($x as &$cidr) {
$min = ipv4_cidr_min_ip($cidr);
$max = ipv4_cidr_max_ip($cidr);
echo "$cidr ($min - $max)\n";
}
*/
 
 
 
 
function ipv4_sort($ary) {
$f = array();
foreach ($ary as $c) {
$a = explode('/', $c);
$ip = $a[0];
$bits = isset($a[1]) ? $a[1] : 32;
 
$d = ip2bin($ip);
 
# ord('*') must be smaller than ord('0')
$d = substr($d, 0, $bits).str_repeat('*', 32-$bits);
 
$f[$d] = $c;
}
 
return $f;
}
 
function ipv4_make_tree($ary) {
$ary = ipv4_sort($ary);
 
if (count($ary) == 0) return array();
 
$sub_begin = '';
$sub_begin_ip = '';
foreach ($ary as $n => $d) {
$sub_begin = substr($n, 0, strpos($n, '*'));
$sub_begin_ip = $d;
unset($ary[$n]);
break;
}
 
$sub = array();
$nonsub = array();
foreach ($ary as $n => $d) {
if (substr($n, 0, strlen($sub_begin)) == $sub_begin) {
$sub[$n] = $d;
} else {
$nonsub[$n] = $d;
}
}
 
$out = array();
$out[$sub_begin_ip] = ipv4_make_tree($sub);
 
$a = ipv4_make_tree($nonsub);
 
$out = array_merge($out, $a);
 
return $out;
}
 
/trunk_oldversion/includes/ipv6_functions.inc.php
0,0 → 1,766
<?php
 
/*
* IPv6 functions for PHP
* Copyright 2012-2020 Daniel Marschall, ViaThinkSoft
* Version 2020-02-28
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
# This library requires either the GMP extension (or BCMath if gmp_supplement.inc.php is present)
 
// TODO: oop, exceptions?
// TODO: variant without gmp ?
// TODO: IPv6 auflƶsung 'ffff::192.168.69.1' -> 'ffff:0000:0000:0000:0000:0000:c0a8:4501' geht nicht!!!
 
if (file_exists(__DIR__ . '/gmp_supplement.inc.php')) include_once __DIR__ . '/gmp_supplement.inc.php';
 
define('GMP_ONE', gmp_init('1'));
 
// Very small self-test:
/*
function ipv6_selftest() {
$iv_b = 'c0ff:ee00::';
$iv_m = 32;
$r = ipv6_cidr2range($iv_b, $iv_m);
echo "$iv_b/$iv_m => $r[0] - $r[1]\n";
 
$rev = ipv6_range2cidr($r[0], $r[1]);
$rev = implode("\n", $rev);
echo "$r[0] - $r[1] => $rev [";
$ok = $rev == "$iv_b/$iv_m";
echo $ok ? 'OK' : 'Mismatch';
echo "]\n";
echo "In-CIDR-Test: ";
echo ipv6_in_cidr("$iv_b/$iv_m", "$iv_b/$iv_m") ? 'OK' : 'Fail';
echo "\n";
}
ipv6_selftest();
*/
 
$cache_ipv6_cidr2range = array();
function ipv6_cidr2range($baseip_or_cidr, $subnet='') {
# (C) 2012 ViaThinkSoft
# Version 1.1
# This function converts an CIDR notation <baseip>/<subnet> into an IPv6 address block array($low_ip, $high_ip)
 
global $cache_ipv6_cidr2range;
$vvv = $baseip_or_cidr.'|'.$subnet;
if (isset($cache_ipv6_cidr2range[$vvv])) return $cache_ipv6_cidr2range[$vvv];
 
if (strpos($baseip_or_cidr, '/') !== false) {
$tmp = explode('/', $baseip_or_cidr, 2);
$baseip_or_cidr = $tmp[0];
$subnet = $tmp[1];
unset($tmp);
}
 
if (($subnet < 0) || ($subnet > 128)) {
$cache_ipv6_cidr2range[$vvv] = false;
return false;
}
 
$maxint128 = gmp_sub(gmp_pow('2', 128), GMP_ONE); # TODO: GMP_TWO ?
$netmask = gmp_shiftl($maxint128, 128-$subnet);
$netmask = gmp_and($netmask, $maxint128); // crop to 128 bit
$wildcard = gmp_xor($maxint128, $netmask);
 
$x = gmp_and(ip2long6($baseip_or_cidr), $netmask);
$nums = $wildcard;
$low = long2ip6($x);
$high = long2ip6(gmp_add($x, $nums));
 
$out = array($low, $high);
$cache_ipv6_cidr2range[$vvv] = $out;
return $out;
}
 
$cache_ipv6_range2cidr = array();
function ipv6_range2cidr($baseip, $topip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
# This function converts an IPv6 address block into valid CIDR blocks (There may be multiple blocks!)
 
global $cache_ipv6_range2cidr;
$vvv = $baseip.'|'.$topip;
if (isset($cache_ipv6_range2cidr[$vvv])) return $cache_ipv6_range2cidr[$vvv];
 
$out = array();
if (ipv6_cmp($baseip, $topip) > 0) {
$cache_ipv6_range2cidr[$vvv] = false;
return false;
}
while (gmp_cmp(gmp_sub(ip2long6($baseip), GMP_ONE), ip2long6($topip)) != 0) {
$i = -1;
do {
$i++;
$range = ipv6_cidr2range($baseip, $i);
$l = $range[0];
$t = $range[1];
} while ((ipv6_cmp($l, $baseip) != 0) || (ipv6_cmp($t, $topip) > 0));
 
$out[] = "$baseip/$i";
$baseip = ipv6_add($t, GMP_ONE);
}
 
$cache_ipv6_range2cidr[$vvv] = $out;
return $out;
}
 
function ipv6_add($baseip, $num) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return long2ip6(gmp_add(ip2long6($baseip), $num));
}
 
function ipv6_sub($baseip, $num) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return long2ip6(gmp_sub(ip2long6($baseip), $num));
}
 
function ipv6_cmp($a, $b) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return gmp_cmp(ip2long6($a), ip2long6($b));
}
 
$cache_ipv6_in_cidr = array();
function ipv6_in_cidr($haystack, $needle) {
# (C) 2012 ViaThinkSoft
# Version 1.1
 
global $cache_ipv6_in_cidr;
$vvv = $haystack.'|'.$needle;
if (isset($cache_ipv6_in_cidr[$vvv])) return $cache_ipv6_in_cidr[$vvv];
 
$x = explode('/', $haystack);
$ha = ipv6_cidr2range($x[0], $x[1]);
 
$x = explode('/', $needle);
if (!isset($x[1])) $x[1] = 128; // single IP
$ne = ipv6_cidr2range($x[0], $x[1]);
 
$ha_low = ip2long6($ha[0]);
$ha_hig = ip2long6($ha[1]);
$ne_low = ip2long6($ne[0]);
$ne_hig = ip2long6($ne[1]);
 
# HA: low[ ]high
# NE: low[ ]high
 
$out = (gmp_cmp($ne_low, $ha_low) >= 0) && (gmp_cmp($ne_hig, $ha_hig) <= 0);
$cache_ipv6_in_cidr[$vvv] = $out;
return $out;
}
 
// IMPORTANT! $cmp_ary[x]=y MUST HAVE x<=y !
function ipv6_merge_address_blocks($data, $debug = false) {
# (C) 2012-2013 ViaThinkSoft
# Version 2.2
 
if ($debug !== false) $STARTZEIT = time();
 
// 1. Convert IPs to numbers
 
$cmp_ary = array();
foreach ($data as $a => &$b) {
$a = ip2long6($a);
$b = ip2long6($b);
 
$cmp_ary[gmp_strval($a)] = gmp_strval($b);
unset($a);
unset($b);
}
 
// 2. Sort array
 
ksort($cmp_ary);
 
// 3. Merge the blocks in an intelligent way (and remove redundant blocks)
 
# Merge overlapping blocks
# [ ]
# [ ] -> [ ]
 
# Merge neighbor blocks
# [ ][ ] -> [ ]
 
# Remove redundant blocks
# [ ] -> [ ]
# [ ]
 
$merge_count = 0;
$redundant_deleted_count = 0;
$round_count = 0;
do {
if ($debug !== false) {
$LAUFZEIT = time() - $STARTZEIT;
echo $debug."Merging... $round_count rounds; merged $merge_count blocks; deleted $redundant_deleted_count redundant blocks; time: $LAUFZEIT seconds\r";
}
 
$round_count++;
 
$clean = true;
 
foreach ($cmp_ary as $a => &$b) {
foreach ($cmp_ary as $x => &$y) {
// x in range [a+1..b+1] ?
if (gmp_cmp(gmp_init($x), gmp_init($a)) <= 0) continue;
if (gmp_cmp(gmp_init($x), gmp_add(gmp_init($b), GMP_ONE)) > 0) break;
 
// Merge
$clean = false;
if (gmp_cmp(gmp_init($y), gmp_init($b)) > 0) {
$merge_count++;
$b = $y;
unset($cmp_ary[$x]);
} else {
$redundant_deleted_count++;
unset($cmp_ary[$x]);
}
}
}
} while (!$clean);
 
if ($debug !== false) {
$LAUFZEIT = time() - $STARTZEIT;
echo $debug."Merge completed. $round_count rounds; merged $merge_count blocks; deleted $redundant_deleted_count redundant blocks; time: $LAUFZEIT seconds\n";
}
 
// 4. Convert back to IPs
 
$out_ary = array();
foreach ($cmp_ary as $a => &$b) {
$a = long2ip6(gmp_init($a));
$b = long2ip6(gmp_init($b));
$out_ary[$a] = $b;
}
 
return $out_ary;
}
 
function ipv6_merge_arrays($data_a, $data_b) {
# (C) 2012 ViaThinkSoft
# Version 1.2
 
$normalized_data_a = array();
foreach ($data_a as $from => &$to) {
$normalized_data_a[ipv6_normalize($from)] = ipv6_normalize($to);
}
 
$normalized_data_b = array();
foreach ($data_b as $from => &$to) {
$normalized_data_b[ipv6_normalize($from)] = ipv6_normalize($to);
}
 
$data = array();
 
foreach ($normalized_data_a as $from => &$to) {
if (isset($normalized_data_b[$from])) {
$data[$from] = ipv6_max($to, $normalized_data_b[$from]);
} else {
$data[$from] = $to;
}
}
 
foreach ($normalized_data_b as $from => &$to) {
if (!isset($normalized_data_a[$from])) {
$data[$from] = $to;
}
}
 
return $data;
}
 
function ipv6_valid($ip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
return ip2long6($ip) !== false;
}
 
function ipv6_normalize($ip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
# Example:
# 2001:0000:0000::1 -> 2001::1
 
$long = ip2long6($ip);
if ($long == -1 || $long === FALSE) return false;
return long2ip6($long);
}
 
function ipv6_expand($ip) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
# Example:
# 2001::1 -> 2001:0000:0000:0000:0000:0000:0000:0000
 
$long = ip2long6($ip);
if ($long == -1 || $long === FALSE) return false;
return long2ip6($long, false);
}
 
function ipv6_min($ip_a, $ip_b) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
if (ipv6_cmp($ip_a, $ip_b) == -1) {
return $ip_a;
} else {
return $ip_b;
}
}
 
function ipv6_max($ip_a, $ip_b) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
if (ipv6_cmp($ip_a, $ip_b) == 1) {
return $ip_a;
} else {
return $ip_b;
}
}
 
function ipv6_ipcount($data) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$cnt = gmp_init('0');
 
foreach ($data as $from => &$to) {
$cnt = gmp_add($cnt, gmp_sub(ip2long6($to), ip2long6($from)));
}
 
return gmp_strval($cnt, 10);
}
 
function ipv6_read_file($file) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$data = array();
 
$lines = file($file);
foreach ($lines as &$line) {
$rng = ipv6_line2range($line);
$data[$rng[0]] = $rng[1];
}
 
return $data;
}
 
function ipv6_line2range($line) {
# (C) 2012 ViaThinkSoft
# Version 1.0
 
$line = trim($line);
 
if (strpos($line, '/') !== false) {
$rng = ipv6_cidr2range($line);
} else {
$rng = explode('-', $line);
$rng[0] = trim($rng[0]);
$rng[1] = trim($rng[1]);
$rng[0] = ipv6_normalize($rng[0]);
if (!isset($rng[1])) $rng[1] = $rng[0];
$rng[1] = ipv6_normalize($rng[1]);
}
 
return $rng;
}
 
# ---
 
if (!function_exists('gmp_shiftl')) {
function gmp_shiftl($x, $n) { // shift left
// http://www.php.net/manual/en/ref.gmp.php#99788
return gmp_mul($x, gmp_pow('2', $n));
}
}
 
if (!function_exists('gmp_shiftr')) {
function gmp_shiftr($x, $n) { // shift right
// http://www.php.net/manual/en/ref.gmp.php#99788
return gmp_div($x, gmp_pow('2', $n));
}
}
 
$cache_ip2long6 = array();
function ip2long6($ipv6) {
// Source:
// http://www.netz-guru.de/2009/11/07/php-ipv6-ip2long-und-long2ip-funktionen/
// Slightly modified
 
global $cache_ip2long6;
if (isset($cache_ip2long6[$ipv6])) return $cache_ip2long6[$ipv6];
 
if ($ipv6 == '') $ipv6 = '::';
 
if (filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$cache_ip2long6[$ipv6] = false;
return false;
}
 
$ip_n = @inet_pton($ipv6);
if ($ip_n === false) {
$cache_ip2long6[$ipv6] = false;
return false; // modified
}
$bytes = 16; // 16 bytes x 8 bit/byte = 128bit
$ipv6long = '';
 
while ($bytes > 0) {
$bin = sprintf('%08b',(ord($ip_n[$bytes-1])));
$ipv6long = $bin.$ipv6long;
$bytes--;
}
 
// $out = gmp_strval(gmp_init($ipv6long, 2), 10);
$out = gmp_init($ipv6long, 2);
$cache_ip2long6[$ipv6] = $out;
return $out;
}
 
$cache_long2ip6 = array();
function long2ip6($ipv6long, $compress=true) {
// Source:
// http://www.netz-guru.de/2009/11/07/php-ipv6-ip2long-und-long2ip-funktionen/
// Slightly modified
 
global $cache_long2ip6;
$vvv = ($compress ? 'T' : 'F').$ipv6long;
if (isset($cache_long2ip6[$vvv])) return $cache_long2ip6[$vvv];
 
// $bin = gmp_strval(gmp_init($ipv6long, 10), 2);
$bin = gmp_strval($ipv6long, 2);
if (strlen($bin) < 128) {
$pad = 128 - strlen($bin);
for ($i = 1; $i <= $pad; $i++) {
$bin = '0'.$bin;
}
}
 
$bytes = 0;
$ipv6 = '';
while ($bytes < 8) { // 16 bytes x 8 bit/byte = 128bit
$bin_part = substr($bin,($bytes*16),16);
$part = dechex(bindec($bin_part));
if (!$compress) {
$part = str_pad($part, 4, '0', STR_PAD_LEFT);
}
$ipv6 .= $part.':';
$bytes++;
}
 
if ($compress) {
$out = inet_ntop(inet_pton(substr($ipv6, 0, -1)));
} else {
$out = substr($ipv6, 0, strlen($ipv6)-1);
}
$cache_long2ip6[$vvv] = $out;
return $out;
}
 
# --- New 16,12,12
 
define('IPV6_BITS', 128);
 
$global_ipv6_distance = array();
function ipv6_distance($ipOrCIDR_Searchterm, $ipOrCIDR_Candidate) {
global $global_ipv6_distance;
$vvv = $ipOrCIDR_Searchterm.'|'.$ipOrCIDR_Candidate;
if (isset($global_ipv6_distance[$vvv])) return $global_ipv6_distance[$vvv];
 
$ary = ipv6_cidr_split($ipOrCIDR_Searchterm);
$ip = $ary[0];
 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$global_ipv6_distance[$vvv] = false;
return false;
}
 
$ary = ipv6_cidr_split($ipOrCIDR_Candidate);
$ip = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV6_BITS) {
$global_ipv6_distance[$vvv] = false;
return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
}
if (!is_numeric($cidr_bits)) return false;
 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$global_ipv6_distance[$vvv] = false;
return false;
}
 
$x = ipv6_trackdown($ipOrCIDR_Searchterm);
 
if (ipv6_in_cidr($x[0], $ip.'/'.$cidr_bits)) {
$ary = ipv6_cidr_split($x[0]);
$cidr_bits2 = $ary[1];
if ($cidr_bits2 > IPV6_BITS) {
$global_ipv6_distance[$vvv] = false;
return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
}
$out = $cidr_bits2-$cidr_bits;
$global_ipv6_distance[$vvv] = $out;
return $out;
}
 
$i = 0;
$max = false;
foreach ($x as &$y) {
if (ipv6_in_cidr($ip.'/'.$cidr_bits, $y)) {
$max = $i;
}
$i++;
}
 
$global_ipv6_distance[$vvv] = $max;
return $max;
}
 
function ipv6_cidr_split($ipOrCIDR) {
$ary = explode('/', $ipOrCIDR, 2);
$cidr_bits = isset($ary[1]) ? $ary[1] : IPV6_BITS;
if ($cidr_bits > IPV6_BITS) return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
if (!is_numeric($cidr_bits)) return false;
$ip = $ary[0];
return array($ip, $cidr_bits);
}
 
function ipv6_equals($ipOrCIDRA, $ipOrCIDRB) {
return ipv6_normalize_range($ipOrCIDRA) == ipv6_normalize_range($ipOrCIDRB);
}
 
function ipv6_cidr_min_ip($ipOrCIDR) {
$ary = ipv6_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV6_BITS) return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$m = ip2bin($ipOrCIDR);
$m = substr($m, 0, $cidr_bits) . str_repeat('0', IPV6_BITS-$cidr_bits);
 
return bin2ip($m);
}
 
function ipv6_cidr_max_ip($ipOrCIDR) {
$ary = ipv6_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV6_BITS) return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$m = ip2bin($ipOrCIDR);
$m = substr($m, 0, $cidr_bits) . str_repeat('1', IPV6_BITS-$cidr_bits);
 
return bin2ip($m);
}
 
function ipv6_normalize_range($ipOrCIDR) {
# 2001:1800::1/21
# --> 2001:1800::/21
 
# 2001:1af8:4100:a061:0001::1337
# --> 2001:1af8:4100:a061:1::1337/128
 
$ary = ipv6_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV6_BITS) return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$m = ip2bin($ipOrCIDR);
$m = substr($m, 0, $cidr_bits) . str_repeat('0', IPV6_BITS-$cidr_bits);
 
return bin2ip($m) . '/' . $cidr_bits;
}
 
function ipv6_trackdown($ipOrCIDR) {
$ary = ipv6_cidr_split($ipOrCIDR);
$ipOrCIDR = $ary[0];
$cidr_bits = $ary[1];
if ($cidr_bits > IPV6_BITS) return false; // throw new Exception('CIDR bits > '.IPV6_BITS);
if (!is_numeric($cidr_bits)) return false;
 
$out = array();
$m = ip2bin($ipOrCIDR);
for ($i=$cidr_bits; $i>=0; $i--) {
$m = substr($m, 0, $i) . str_repeat('0', IPV6_BITS-$i);
$out[] = bin2ip($m) . '/' . $i;
}
 
return $out;
}
 
function ipv6_sort($ary) {
$f = array();
foreach ($ary as $c) {
$a = explode('/', $c);
$ip = $a[0];
$bits = isset($a[1]) ? $a[1] : 128;
 
$d = ip2bin($ip);
 
# ord('*') must be smaller than ord('0')
$d = substr($d, 0, $bits).str_repeat('*', 128-$bits);
 
$f[$d] = $c;
}
 
return $f;
}
 
function ipv6_make_tree($ary) {
$ary = ipv6_sort($ary);
 
if (count($ary) == 0) return array();
 
$sub_begin = '';
$sub_begin_ip = '';
foreach ($ary as $n => $d) {
$sub_begin = substr($n, 0, strpos($n, '*'));
$sub_begin_ip = $d;
unset($ary[$n]);
break;
}
 
$sub = array();
$nonsub = array();
foreach ($ary as $n => $d) {
if (substr($n, 0, strlen($sub_begin)) == $sub_begin) {
$sub[$n] = $d;
} else {
$nonsub[$n] = $d;
}
}
 
$out = array();
$out[$sub_begin_ip] = ipv6_make_tree($sub);
 
$a = ipv6_make_tree($nonsub);
 
$out = array_merge($out, $a);
 
return $out;
}
 
# ---
 
if (!function_exists('ip2bin')) {
$cache_ip2bin = array();
function ip2bin($ip) {
# Source: http://php.net/manual/en/function.ip2long.php#104163
# modified by VTS
 
global $cache_ip2bin;
if (isset($cache_ip2bin[$ip])) return $cache_ip2bin[$ip];
 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
$out = base_convert(ip2long($ip), 10, 2);
$cache_ip2bin[$ip] = $out;
return $out;
}
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$cache_ip2bin[$ip] = false;
return false;
}
if (($ip_n = inet_pton($ip)) === false) {
$cache_ip2bin[$ip] = false;
return false;
}
$bits = 15; // 16 x 8 bit = 128bit (ipv6)
$ipbin = ''; # added by vts to avoid warning
while ($bits >= 0) {
$bin = sprintf('%08b', (ord($ip_n[$bits])));
$ipbin = $bin.$ipbin;
$bits--;
}
 
$cache_ip2bin[$ip] = $ipbin;
return $ipbin;
}
}
 
if (!function_exists('bin2ip')) {
$cache_bin2ip = array();
function bin2ip($bin) {
# Source: http://php.net/manual/en/function.ip2long.php#104163
# modified by VTS
 
global $cache_bin2ip;
if (isset($cache_bin2ip[$bin])) return $cache_bin2ip[$bin];
 
if (strlen($bin) <= 32) { // 32bits (ipv4)
$out = long2ip(base_convert($bin, 2, 10));
$cache_bin2ip[$bin] = $out;
return $out;
}
if (strlen($bin) != 128) {
$cache_bin2ip[$bin] = false;
return false;
}
$pad = 128 - strlen($bin);
for ($i = 1; $i <= $pad; $i++) {
$bin = '0'.$bin;
}
$bits = 0;
$ipv6 = ''; # added by vts to avoid warning
while ($bits <= 7) {
$bin_part = substr($bin,($bits*16),16);
$ipv6 .= dechex(bindec($bin_part)) . ':';
$bits++;
}
 
$out = inet_ntop(inet_pton(substr($ipv6, 0, -1)));
$cache_bin2ip[$bin] = $out;
return $out;
}
}
 
# --- TEST
 
/*
assert(ipv6_normalize('2001:0000:0000::1') == '2001::1');
 
assert(ipv6_distance('2001:1ae0::/27', '2001:1af8::/29') == -2);
assert(ipv6_distance('2001:1af0::/28', '2001:1af8::/29') == -1);
assert(ipv6_distance('2001:1af8::/29', '2001:1af8::/29') == 0);
assert(ipv6_distance('2001:1af8::/30', '2001:1af8::/29') == 1);
assert(ipv6_distance('2001:1af8::/31', '2001:1af8::/29') == 2);
 
assert(ipv6_distance('2001:1af8:4100:a061:0001::1336/127', '2001:1af8:4100:a061:0001::1335/127') === false);
assert(ipv6_distance('2001:1af8:4100:a061:0001::1336/128', '2001:1af8:4100:a061:0001::1337/128') === false);
assert(ipv6_distance('2001:1af8:4100:a061:0001::1336', '2001:1af8:4100:a061:0001::1337') === false);
*/
 
/*
$test = '2001:1af8:4100:a061:0001::1337';
$x = ipv6_trackdown($test);
foreach ($x as &$cidr) {
$min = ipv6_cidr_min_ip($cidr);
$max = ipv6_cidr_max_ip($cidr);
echo "$cidr ($min - $max)\n";
}
*/
/trunk_oldversion/includes/mac_utils.inc.php
0,0 → 1,130
<?php
 
/*
* MAC utils for PHP
* Copyright 2017 Daniel Marschall, ViaThinkSoft
* Version 19 August 2017
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
define('IEEE_MAC_REGISTRY', __DIR__ . '/web-data');
 
function mac_valid($mac) {
$mac = str_replace(array('-', ':'), '', $mac);
$mac = strtoupper($mac);
 
if (strlen($mac) != 12) return false;
 
$mac = preg_replace('@[0-9A-F]@', '', $mac);
 
return ($mac == '');
}
 
function _lookup_ieee_registry($file, $oui_name, $mac) {
$begin = substr($mac, 0, 2).'-'.substr($mac, 2, 2).'-'.substr($mac, 4, 2);
$f = file_get_contents($file);
 
$f = str_replace("\r", '', $f);
 
# We are using a positive-lookahead because entries like the MA-M references have a blank line between organization and address
preg_match_all('@^\s*'.preg_quote($begin, '@').'\s+\(hex\)\s+(\S+)\s+(.*)\n\n\s*(?=[0-9A-F])@ismU', "$f\n\nA", $m, PREG_SET_ORDER);
foreach ($m as $n) {
preg_match('@(\S+)\s+\(base 16\)(.*)$@ism', $n[2], $m);
 
if (preg_match('@(.+)\-(.+)@ism', $m[1], $o)) {
$z = hexdec(substr($mac, 6, 6));
$beg = hexdec($o[1]);
$end = hexdec($o[2]);
if (($z < $beg) || ($z > $end)) continue;
} else {
$beg = 0x000000;
$end = 0xFFFFFF;
}
 
$x = trim(preg_replace('@^\s+@ism', '', $m[2]));
 
# "PRIVATE" entries are only marked at the "(hex)" line, but not at the "(base16)" line
if ($x == '') $x = trim($n[1]);
 
$x = explode("\n", $x);
 
$ra_len = strlen(dechex($end-$beg));
 
$out = '';
$out .= sprintf("%-24s 0x%s\n", "IEEE $oui_name part:", substr($mac, 0, 12-$ra_len));
$out .= sprintf("%-24s 0x%s\n", "NIC specific part:", substr($mac, 12-$ra_len));
$out .= sprintf("%-24s %s\n", "Registrant:", $x[0]);
foreach ($x as $n => $y) {
if ($n == 0) continue;
else if ($n == 1) $out .= sprintf("%-24s %s\n", "Address of registrant:", $y);
else if ($n >= 2) $out .= sprintf("%-24s %s\n", "", $y);
}
 
// TODO: also print the date of last update of the OUI files
 
return $out;
}
 
return false;
}
 
function decode_mac($mac) {
if (!mac_valid($mac)) return false;
 
// Format MAC
$mac = strtoupper($mac);
$mac = preg_replace('@[^0-9A-F]@', '', $mac);
if (strlen($mac) != 12) {
# echo "Invalid MAC address\n";
return false;
}
$mac_ = preg_replace('@^(..)(..)(..)(..)(..)(..)$@', '\\1-\\2-\\3-\\4-\\5-\\6', $mac);
echo sprintf("%-24s %s\n", "MAC address:", $mac_);
 
// Empfaengergruppe
$ig = hexdec($mac[1]) & 1; // Bit #LSB+0 of Byte 1
$ig_ = ($ig == 0) ? '[0] Individual' : '[1] Group';
echo sprintf("%-24s %s\n", "I/G flag:", $ig_);
 
// Vergabestelle
$ul = hexdec($mac[1]) & 2; // Bit #LSB+1 of Byte 1
$ul_ = ($ul == 0) ? '[0] Universally Administered Address (UAA)' : '[1] Locally Administered Address (LAA)';
echo sprintf("%-24s %s\n", "U/L flag:", $ul_);
 
// Query IEEE registries
// TODO: gilt OUI nur bei Individual UAA?
if (
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/mam.txt', 'OUI-28 (MA-M)', $mac)) ||
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/oui36.txt', 'OUI-36 (MA-S)', $mac)) ||
# The IEEE Registration Authority distinguishes between IABs and OUI-36 values. Both are 36-bit values which may be used to generate EUI-48 values, but IABs may not be used to generate EUI-64 values.[6]
# Note: The Individual Address Block (IAB) is an inactive registry activity, which has been replaced by the MA-S registry product as of January 1, 2014.
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/iab.txt', 'IAB', $mac))
) {
return $x;
} else {
return _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/oui.txt', 'OUI-24 (MA-L)', $mac);
}
 
// TODO
// FF-FF-FF-FF-FF-FF = Broadcast-Adresse
 
// TODO
// IP-Multicast
// 01-00-5E-00-00-00 bis 01-00-5E-7F-FF-FF (unterste 23 bit der MAC = unterste 23 Bit der IP) ...
// 224.0.0.1 -> 01-00-5e-00-00-01
// erste 4 Bits durch Class D konvention belegt. 5 bits sind unbekannt
 
// TODO: VRRP
// 00-00-5E-00-01-ID
}
/trunk_oldversion/includes/mac_utils.inc.phps
0,0 → 1,0
link mac_utils.inc.php
Property changes:
Added: svn:special
+*
\ No newline at end of property
/trunk_oldversion/includes/oid_illegality_rules
0,0 → 1,250
[1.3.6.1.4.1.37476.3.1.5.2]
 
-- Standard OID Illegality Rule Definition File
-- by Daniel Marschall and Olivier Dubuisson
-- Revision: 19 January 2020
-- This file contains all oid-info.com rules as of 2018_09_18_illegal_oid_table.csv
 
-- SYNTAX:
-- -- comment : comments are also allowed after a rule definition
-- 2.999.(11-).0 : the arc values 11 and below are illegal
-- 2.999.(11+).0 : the arc values 11 and above are illegal
-- 2.999.(1-5).0 : the arc values 1 to 5 are illegal
-- 2.999.(!3).0 : only arc 3 is valid, all others are invalid (added in version 2)
-- 2.999.*.0 : * is equal to (0+)
 
 
-- TODO: Add more constraints according to http://www.iana.org/assignments/smi-numbers/smi-numbers.xml
-- IANA REGISTRIES
-- 1.3.6.1 http://www.iana.org/assignments/smi-numbers/smi-numbers.xml
-- 1.3.6.1.1 http://www.iana.org/assignments/ldap-parameters/ldap-parameters-1.csv
-- 1.3.6.1.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-2.csv
-- 1.3.6.1.2.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-3.csv
-- 1.3.6.1.2.1.2.2.1.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-5.csv
-- 1.3.6.1.2.1.2.2.1.3.131 http://www.iana.org/assignments/smi-numbers/smi-numbers-6.csv
-- 1.3.6.1.2.1.10 http://www.iana.org/assignments/smi-numbers/smi-numbers-7.csv
-- 1.3.6.1.2.1.10.23 http://www.iana.org/assignments/smi-numbers/smi-numbers-8.csv
-- 1.3.6.1.2.1.10.166 http://www.iana.org/assignments/smi-numbers/smi-numbers-9.csv
-- 1.3.6.1.2.1.16 http://www.iana.org/assignments/smi-numbers/smi-numbers-10.csv
-- 1.3.6.1.2.1.16.20 http://www.iana.org/assignments/smi-numbers/smi-numbers-11.csv
-- 1.3.6.1.2.1.27 http://www.iana.org/assignments/smi-numbers/smi-numbers-13.csv
-- 1.3.6.1.2.1.27.4 (Registry is empty.)
-- 1.3.6.1.2.1.27.5 (Registry is empty.)
-- 1.3.6.1.2.1.28 ??????????????????????????????????
-- 1.3.6.1.2.1.28.2.1.24 http://www.iana.org/assignments/smi-numbers/smi-numbers-17.csv
-- 1.3.6.1.2.1.34 http://www.iana.org/assignments/smi-numbers/smi-numbers-18.csv
-- 1.3.6.1.2.1.153.4 (Registry is empty.)
-- 1.3.6.1.2.1.194.1.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-20.csv
-- 1.3.6.1.2.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-21.csv
-- 1.3.6.1.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-22.csv
-- 1.3.6.1.3.116 http://www.iana.org/assignments/smi-numbers/smi-numbers-23.csv
-- 1.3.6.1.4 http://www.iana.org/assignments/smi-numbers/smi-numbers-24.csv
-- 1.3.6.1.4.1 http://www.iana.org/assignments/enterprise-numbers
-- 1.3.6.1.5 http://www.iana.org/assignments/smi-numbers/smi-numbers-26.csv
-- 1.3.6.1.5.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-27.csv
-- 1.3.6.1.5.4 http://www.iana.org/assignments/smi-numbers/smi-numbers-28.csv
-- 1.3.6.1.5.5 http://www.iana.org/assignments/smi-numbers/smi-numbers-29.csv
-- 1.3.6.1.5.5.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-30.csv
-- 1.3.6.1.5.5.4 http://www.iana.org/assignments/smi-numbers/smi-numbers-31.csv
-- 1.3.6.1.5.5.8 http://www.iana.org/assignments/smi-numbers/smi-numbers-32.csv
-- 1.3.6.1.5.5.8.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-33.csv
-- 1.3.6.1.5.5.8.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-34.csv
-- 1.3.6.1.5.5.8.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-35.csv
-- 1.3.6.1.5.5.10 http://www.iana.org/assignments/smi-numbers/smi-numbers-36.csv
-- 1.3.6.1.5.5.11 http://www.iana.org/assignments/smi-numbers/ltans.csv
-- 1.3.6.1.5.5.11.0 http://www.iana.org/assignments/smi-numbers/ltans-module-identifiers.csv
-- 1.3.6.1.5.5.11.1 http://www.iana.org/assignments/smi-numbers/ltans-cms-content-types.csv
-- 1.3.6.1.5.5.11.2 http://www.iana.org/assignments/smi-numbers/ltans-ers-encryption-methods.csv
-- 1.3.6.1.5.5.12 http://www.iana.org/assignments/smi-numbers/smi-numbers-37.csv
-- 1.3.6.1.5.5.12.0 http://www.iana.org/assignments/smi-numbers/smi-numbers-38.csv
-- 1.3.6.1.5.5.12.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-39.csv
-- 1.3.6.1.5.5.12.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-40.csv
-- 1.3.6.1.5.5.12.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-41.csv
-- 1.3.6.1.5.5.12.4 http://www.iana.org/assignments/smi-numbers/smi-numbers-42.csv
-- 1.3.6.1.5.5.12.5 http://www.iana.org/assignments/smi-numbers/smi-numbers-43.csv
-- 1.3.6.1.5.5.12.6 http://www.iana.org/assignments/smi-numbers/smi-numbers-44.csv
-- 1.3.6.1.5.5.12.7 http://www.iana.org/assignments/smi-numbers/smi-numbers-45.csv
-- 1.3.6.1.5.5.13 http://www.iana.org/assignments/smi-numbers/smi-numbers-46.csv
-- 1.3.6.1.5.5.15 http://www.iana.org/assignments/smi-numbers/smi-numbers-47.csv
-- 1.3.6.1.5.5.15.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-48.csv
-- 1.3.6.1.5.5.15.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-49.csv
-- 1.3.6.1.5.6 http://www.iana.org/assignments/smi-numbers/smi-numbers-50.csv
-- 1.3.6.1.5.7 http://www.iana.org/assignments/smi-numbers/smi-numbers-51.csv
-- 1.3.6.1.5.7.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-52.csv
-- 1.3.6.1.5.7.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-53.csv
-- 1.3.6.1.5.7.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-54.csv
-- 1.3.6.1.5.7.4 http://www.iana.org/assignments/smi-numbers/smi-numbers-55.csv
-- 1.3.6.1.5.7.5 http://www.iana.org/assignments/smi-numbers/smi-numbers-56.csv
-- 1.3.6.1.5.7.6 http://www.iana.org/assignments/smi-numbers/smi-numbers-57.csv
-- 1.3.6.1.5.7.7 http://www.iana.org/assignments/smi-numbers/smi-numbers-58.csv
-- 1.3.6.1.6 http://www.iana.org/assignments/smi-numbers/smi-numbers-59.csv
-- 1.3.6.1.6.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-60.csv
-- 1.3.6.1.6.2 ??? Not listed in http://www.iana.org/assignments/smi-numbers/smi-numbers.xml
-- 1.3.6.1.6.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-61.csv
-- 1.3.6.1.7 http://www.iana.org/assignments/smi-numbers/smi-numbers-64.csv
-- 1.3.6.1.7.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-65.csv
-- 1.3.6.1.7.1.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-66.csv
-- 1.3.6.1.7.1.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-67.csv
-- 1.3.6.1.7.1.2.1 http://www.iana.org/assignments/smi-numbers/smi-numbers-68.csv
-- 1.3.6.1.7.1.2.2 http://www.iana.org/assignments/smi-numbers/smi-numbers-69.csv
-- 1.3.6.1.7.1.3 http://www.iana.org/assignments/smi-numbers/smi-numbers-70.csv
-- 1.3.6.1.8 http://www.iana.org/assignments/media-feature-tags/media-feature-tags.xhtml
-- 1.3.6.1.8.1 http://www.iana.org/assignments/media-feature-tags/media-feature-tags-1.csv
-- 1.3.6.1.8.2 (No registrations at this time.)
-- 1.3.6.1.8.3 http://www.iana.org/assignments/media-feature-tags/media-feature-tags-3.csv
-- 1.3.6.1.8.4 http://www.iana.org/assignments/media-feature-tags/media-feature-tags-4.csv
 
 
-- CATEGORY: Currently "not expected" OID arc values - once the RAs are reaching a specific arc value, these limits have to be increased
0.(10+) -- itu, currently max 9
1.(4+) -- iso, currently max 3
1.3.6.(2+) -- dod
1.3.6.1.(9+) -- internet
1.3.6.1.2.(3+) -- mgmt
1.3.6.1.2.1.(301+) -- mib-2 (Sep 2015: max 233)
1.3.6.1.2.1.0.* -- reserved
1.3.6.1.2.1.1.(10+) -- system (Sep 2015: max 9)
1.3.6.1.4.(2+) -- private (Sep 2015: max 1)
2.(1000+) -- joint-iso-itu-t (Sep 2015: max 51 & 999)
2.1.(124+) -- asn1 (Sep 2015: max 10 & 123)
2.5.29.(81+) -- OIDs underneath {joint-iso-itu-t(2) ds(5) certificateExtension(29)} have a number less or equal to 80 in the current edition of Rec. ITU-T X.509 | ISO/IEC 9594-8
2.16.840.1.113883.3.(10000+) -- externalUseRoots (Dec 2017: upper bound set to 10,000)
1.3.6.1.3.(147+) -- The highest experiment number is currently (Sep 2015): 126 , see http://www.iana.org/assignments/smi-numbers/smi-numbers.xml
-- Various vendors claim to have arcs higher than the current number: hippisw(147), ipsecSaMonModule(500), ipsecMIB(503), host(999), ppvpnTcMIB(1111), nhrpMIB(9999)
1.3.6.1.5.(8+) -- OIDs underneath 1.3.6.1.5 are not expected (at this point in time) to have a number greater than 7 ( http://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-26 )
1.3.6.1.5.2.(6+) -- At this point in time (Apr 2019) OIDs allocated by Kerberos version 2 underneath 1.3.6.1.5.2 are not expected to have a number greater than 5.
-- see https://web.mit.edu/kerberos/krb5-oids/krb5-oids.asn
1.3.6.1.5.7.1.(5+) -- OIDs underneath 1.3.6.1.5.7.1 are not expected (at this point in time) to have a number greater than 4 ( https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-52 )
 
-- CATEGORY: Reserved
1.1.3.* -- Reserved for ISO/IEC 9834-3
 
-- CATEGORY: Unassigned country codes
1.2.1
1.2.2
1.2.6 -- was 1.3.6 meant?
1.2.10
1.2.16
1.2.39
1.2.110 -- According to the secretary of the ISO 3166 maintenance Agency (16 June 2003), country code 110 is un-assigned in ISO 3166-1; it does not represent any country
1.2.158 -- This OID is not used since Taiwan is not an ISO National Body. All OIDs for Taiwan are registered under {joint-iso-itu-t(2) country(16) taiwan(158)}
1.2.886 -- Country code 886 has been abused in 1998 because someone at Taiwan Chungwa Telecom originally believed 886 was an ITU assignment for Taiwan Numeric Code, but the 886 country code ( http://unstats.un.org/unsd/methods/m49/m49chang.htm#ftni ) was assigned to Yemen before that country merged with Democratic Yemen. Taiwan has NO RIGHT to use this arc. The Statistic Division of the United Nations may assign this arc to any country without any notice, so keep using this arc will be a big trouble. Note that the use of this illegal OID should be avoided in any new document and/or standard. All existing OID should be transfered to the 2.16.158 arc which is assigned to Taiwan. Also read Conflicts over Taiwan OIDs: http://www.alvestrand.no/objectid/taiwan.html
1.2.3166
1.2.57958
 
-- CATEGORY: Example OIDS
2.999.* -- OID 2.999 is only used for creating (informal) examples, hence child OIDs do not need to be described in the OID repository, as the same child OID can be reused by someone else for a different purpose
1.3.6.1.4.1.37476.9999.* -- ViaThinkSoft example OID (obsolete in favor of 2.999)
 
-- CATEGORY: Illegal usage (hijacking / collission)
1.3.6.1.2.1.1.7.* -- Illegal redefintion of 1.3.6.1.2.1.1.7 (defined in IETF RFC 1213 without child nodes) by agilent-wanstats.mib as "sysServices"
2.16.158.3 -- Institute for Information Industry claims to have this OID but the Registration Authority for the superior OID confirmed that this OID was never assigned to III
2.16.158.5 -- Taiwan-CA.com, Inc. (TaiCA) claims to have this OID but the Registration Authority for the superior OID confirmed that this OID was never assigned to them
2.16.158.6 -- CHIEF Telecom Inc. (www.chief.com.tw) claims to use this OID but it is illegal because Taiwan non-government organizations are registered under {joint-iso-itu-t(2) country(16) tw(158) organization(1)}
2.16.158.7 -- Organizations have OIDs under {joint-iso-itu-t(2) country(16) tw(158) organization(1)}
1.3.6.1.4.1.(65665+) -- There are illegal definitions of the arcs 65665, 76561 and 123456 found on the internet.
 
-- CATEGORY: Definitions
2.27.(128+) -- Child OIDs are limited to 127 so that the OID can encode in 2 octets.
0.(40+) -- According to Rec. ITU-T X.660 | ISO/IEC 9834-1, "the arcs beneath root arcs 0 and 1 are restricted to forty arcs numbered 0 to 39"
1.(40+) -- According to Rec. ITU-T X.660 | ISO/IEC 9834-1, "the arcs beneath root arcs 0 and 1 are restricted to forty arcs numbered 0 to 39"
1.0.1 -- International Standard ISO 1:2002 is about "Geometrical Product Specifications (GPS) -- Standard reference temperature for geometrical product specification and verification", hence does not define OIDs
1.0.16 -- International Standard ISO 16:1975 is about "Acoustics -- Standard tuning frequency (Standard musical pitch)", hence does not define OIDs
2.25.(340282366920938463463374607431768211456+) -- UUIDs cannot be greater than 2^128-1
1.3.6.1.4.1.37476.30.9.(2147483648+) -- The last arc (system ID) may only have 31 bits
 
-- CATEGORY: Cancelled, withdrawn and rejected OIDs
1.0.29192.2.2.3 -- This OID was allocated to the "Speck" family of block ciphers in ISO/IEC 29192-2 PDAM1 in 2017 but this proposed amendment has been cancelled
1.3.6.1.4.1.37476.9000.36 -- Withdrawn FreeOID by ViaThinkSoft (spam), https://www.viathinksoft.de/freeoid/display_oid.php?oid=36
2.16.840.1.113883.3.20 -- Rejected in the HL7 OID Registry
2.16.840.1.113883.13.(223-225) -- Entered in error in HL7 OID Registry
2.16.840.1.113883.3.24.6.1 -- Entered in error in HL7 OID Registry; The correct OID is 2.16.840.1.113883.4.344
2.16.840.1.113883.3.24.6.2 -- Entered in error in HL7 OID Registry; The correct OID is 2.16.840.1.113883.4.345
2.16.840.1.113883.3.41 -- Rejected by HL7 because it is a duplicate of 2.16.840.1.113883.6.14
2.16.840.1.113883.3.4831.3 -- rejected by HL7: http://www.hl7.org/oid/index.cfm?Comp_OID=2.16.840.1.113883.3.4831.3
 
-- CATEGORY: Misdefined in specifications
1.2.840.113549.1.9.16.0.999 -- According to IETF RFC Errata 3866 ( https://www.rfc-editor.org/errata_search.php?eid=3866 ), the correct number is 49 and not 999 as wrongly specified in IETF RFC 6210
1.0.10118.3.0.61 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 7} (the mistake was found when proofreading ISO/IEC 10118-3:2018 for publication, so it will be corrected in a technical corrigendum or amendment)
1.0.10118.3.0.62 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 8} (the mistake was found when proofreading ISO/IEC 10118-3:2018 for publication, so it will be corrected in a technical corrigendum or amendment)
1.0.10118.3.0.63 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 9} (the mistake was found when proofreading ISO/IEC 10118-3:2018 for publication, so it will be corrected in a technical corrigendum or amendment)
1.0.10118.3.0.64 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 10} (the mistake was found when proofreading ISO/IEC 10118-3:2018 for publication, so it will be corrected in a technical corrigendum or amendment)
1.0.10118.3.0.66 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 11} (the mistake was found when proofreading ISO/IEC 10118-3:2018 for publication, so it will be corrected in a technical corrigendum or amendment)
1.0.10118.3.0.67 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 12} (the mistake was found when proofreading ISO/IEC 10118-3:2018 for publication, so it will be corrected in a technical corrigendum or amendment)
0.0.24.752 -- There is a mistake in Rec. ITU-T X.792 (http://www.itu.int/ITU-T/formal-language/itu-t/x/x792/1999/AuditASN1Module.html) where number 752 is used instead of 792.
 
-- CATEGORY: Not assigned by IANA (probably mistyped)
1.3.6.1.5.5.7.3.0 -- OID 1.3.6.1.5.5.7.3.0 has not been assigned by IANA ( https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.3 )
1.3.6.1.5.5.1.4 -- Not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-30
1.3.6.1.5.5.1.5 -- Not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-30
1.3.6.1.5.5.1.6 -- Not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-30
1.3.6.1.5.5.1.7 -- Not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-30
1.3.6.1.5.5.1.8 -- Not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-30
1.3.6.1.2.1.10.10 -- OID not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-7
1.3.6.1.2.1.10.1 -- OID not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-7
1.3.6.1.2.1.10.2 -- OID not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-7
1.3.6.1.5.4.(1+) -- The only child OID defined in the SMI Security for Confidentiality Codes ( https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-28 ) is reserved(0)
1.3.6.1.2.1.10.9999 -- OID not allocated at https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-7
1.3.0 -- OID not defined at http://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml
1.3.6.1.1.2.0 -- OID not defined at http://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml
1.3.6.1.2.2.1.17 -- OID not defined at http://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml
1.3.6.1.2.2.1.22 -- OID not defined at http://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml
 
-- CATEGORY: Not defined by IETF (probably mistyped)
1.3.6.1.6.3.1.2.2.6.1000 -- Not defined in IETF RFC 3418
1.3.6.1.2.1.10.18.6.1.(24+) -- IETF RFC 4805 ( https://tools.ietf.org/html/rfc4805 ) only defines 23 child OIDs of 1.3.6.1.2.1.10.18.6.1
1.3.6.1.2.1.10.18.8.1.(14+) -- IETF RFC 4805 ( https://tools.ietf.org/html/rfc4805 ) only defines 13 child OIDs of 1.3.6.1.2.1.10.18.8.1
1.3.6.1.2.1.3.1.(2+) -- According to IETF RFC 1213 ( https://tools.ietf.org/html/rfc1213 ), there is only one child OID underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) at(3) atTable(1)}
1.3.6.1.2.1.39.1.2.(2+) -- According to IETF RFC 1697 ( https://tools.ietf.org/html/rfc1697 ), there is only one child OID underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) rdbmsMIB(39) rdbmsObjects(1) rdbmsDbInfoTable(2)}
1.3.6.1.2.1.39.1.3.(2+) -- According to IETF RFC 1697 ( https://tools.ietf.org/html/rfc1697 ), there is only one child OID underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) rdbmsMIB(39) rdbmsObjects(1) rdbmsDbParamTable(3)}
1.3.6.1.2.1.39.3.1.(2+) -- According to IETF RFC 1697 ( https://tools.ietf.org/html/rfc1697 ), there is only one child OID underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) rdbmsMIB(39) rdbmsConformance(3) rdbmsCompliances(1)}
1.3.6.1.2.1.39.3.2.(2+) -- According to IETF RFC 1697 ( https://tools.ietf.org/html/rfc1697 ), there is only one child OID underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) rdbmsMIB(39) rdbmsConformance(3) rdbmsGroups(2)}
1.3.6.1.2.1.39.(4+) -- According to IETF RFC 1697 ( https://tools.ietf.org/html/rfc1697 ), there are only three child OIDs underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) rdbmsMIB(39)}
1.3.6.1.2.1.4.21.1.(14+) -- IETF RFC 1213 ( http://www.ietf.org/rfc/rfc1213.txt ) defines child OIDs up to number 13 underneath OID 1.3.6.1.2.1.4.21.1
1.3.6.1.1.1.3 -- OID 1.3.6.1.1.1.3 is not defined in IETF RFC 2307 ( https://tools.ietf.org/html/rfc2307.html ). directoryOperTable OBJECT-TYPE is identified by OID 1.3.6.1.4.1.358.4.6.1.3
1.3.6.1.2.1.99.1.1.(2+) -- IETF RFC 3433 ( https://tools.ietf.org/html/rfc3433.html ) defines only one child OID underneath OID 1.3.6.1.2.1.99.1.1
1.3.6.1.2.1.25.1.(8+) -- OIDs underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) host(25) hrSystem(1)} do not have a number greater than 7 in IETF RFC 2790 ( https://tools.ietf.org/html/rfc2790.html )
1.3.6.1.2.1.10.23.(5+) -- OIDs underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) transmission(10) ppp(23)} are not expected to have a number greater than 4 ( https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-8 )
1.3.6.1.2.1.4.(40+) -- Child OIDs of 1.3.6.1.2.1.4 do not have a number greater to 39 in IETF RFC 4293 ( https://datatracker.ietf.org/doc/rfc4293/ )
1.3.6.1.2.1.69.10 -- Not assigned in IETF RFC 4639 ( https://tools.ietf.org/html/rfc4639 )
1.3.6.1.2.1.69.4 -- Not assigned in IETF RFC 4639 ( https://tools.ietf.org/html/rfc4639 ), use {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) docsSubMgt(125)} instead
 
-- CATEGORY: Not assigned (probably mistyped)
2.16.840.1.113883.3.44.21 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) hl7(113883) externalUseRoots(3) stmarys(4421)}
2.16.840.1.11422 -- The correct OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) 114222}
2.16.840.1.(113526-) -- Childs OIDs of 2.16.840.1 have a number greater than or equal to 113,527
1.3.6.1.2.1.10.10.1.1.2 -- This OID is not defined in ACC-MIB (v1) ( http://www.mibdepot.com/cgi-bin/getmib3.cgi?win=mib_a&i=1&n=ACC-MIB&r=ericsson&f=mib_txt_12_3_1_5&v=v1&t=tree#dot5Group )
1.3.6.1.2.1.10.7.20 -- The correct OID is {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) powerEthernetMIB(105)}
1.3.6.1.2.1.10.7.300 -- The correct OID is {iso(1) member-body(2) us(840) ieee802dot3(10006) snmpmibs(300)}
1.3.6.1.2.1.39.1.4.2 -- The correct OID is {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) transmission(10) sonetMIB(39) sonetObjects(1) sonetFarEndLine(4) sonetFarEndLineIntervalTable(2)}
1.3.6.1.2.2.2.1.(7+) -- OIDs underneath {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) pib(2) frameworkPib(2) frwkBasePibClasses(1)} cannot be greater than 6 because there are only 6 OBJECT-TYPEs defined in IETF RFC 3318 ( https://tools.ietf.org/html/rfc3318.html )
1.3.6.1.4.1.1226.685 -- The correct OID is 1.3.6.1.4.1.1226.1.685
1.3.6.1.4.1.23.2.8889 -- No such OID underneath {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 23 mibDoc(2)}
1.3.12.999 -- Not assigned by Ecma International
0.0.0 -- Not a series of ITU-T Recommendations
0.3.18 -- Not an assigned DNIC
0.0.8.0 -- Not an H-series ITU-T Recommendation
0.0.23 -- The W-series of ITU-T Recommendations does not exist
2.16.840.1.113883.3.3724.1 -- The correct OID is 2.16.840.1.113883.3.3724
2.49.0.0.174.24900174 -- Invalid WMO OID, see http://alerting.worldweather.org/authorities.php , correct is 2.49.0.0.174.0
2.49.0.0.768.249007680 -- Invalid WMO OID, see http://alerting.worldweather.org/authorities.php , correct is 2.49.0.0.768.0
2.49.0.2.0.0 -- Invalid WMO OID, see http://alerting.worldweather.org/authorities.php , correct is 2.49.0.2.0
0.1.* -- There is no OID underneath OID 0.1
1.2.826.1004 -- The correct OID is 1.2.826.0.1004
1.2.826.1147 -- The correct OID is 1.2.826.0.1147
1.2.826.1296 -- The correct OID is 1.2.826.0.1296
1.2.840.63
1.2.840.802 -- The right OID for IEEE 802.3ad is 1.2.840.10006
1.2.840.1006
1.2.840.10008.421292 -- not assigned by DICOM
1.2.840.11789
2.2.840 -- was 1.2.840 meant?
2.16.840.1.113883.3.0 -- Not assigned by HL7
2.16.840.101 -- The right OID is {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)}
1.3.6.1.1.250
1.3.6.1.5.2.(0-1) -- kerberosV5
1.3.6.1.5.2.3.0 -- Not allocated by Kerberos version 2
1.3.6.1.5.2.4.0 -- Not allocated by Kerberos version 2
0.0.17.3303.(!127) -- The only child OID underneath 0.0.17.3303 is 127
 
-- END OF FILE --
/trunk_oldversion/includes/oid_plus.inc.php
0,0 → 1,21
<?php
 
error_reporting(E_ALL | E_NOTICE | E_DEPRECATED | E_STRICT);
 
// Note: There may not be a function include_all(), otherwise, global variables (e.g. for caching) cannot be used in the included units.
 
// Load Core Stuff
foreach (sorted_glob(__DIR__ . '/../core/*.php') as $filename) include_once $filename;
 
// Load Search Providers
// Load Authentification Providers
// Load Field Extenders
foreach (sorted_glob(__DIR__ . '/../plugins/*/*.php') as $filename) include_once $filename;
 
# ---
 
function sorted_glob($mask) {
$files = glob($mask);
sort($files);
return $files;
}
/trunk_oldversion/includes/oid_utils.inc.php
0,0 → 1,831
<?php
 
/*
* OID-Utilities for PHP
* Copyright 2011-2019 Daniel Marschall, ViaThinkSoft
* Version 2019-03-25
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
// All functions in this library are compatible with leading zeroes (not recommended) and leading dots
 
// TODO: change the function names, so that they have a uniform naming schema, and rename "oid identifier" into "asn.1 alphanumeric identifier"
// TODO: Function for finding a shared ancestor, e.g. oid_shared_ancestor('2.999.1.2.3', '2.999.4.5') == '2.999'
 
define('OID_DOT_FORBIDDEN', 0);
define('OID_DOT_OPTIONAL', 1);
define('OID_DOT_REQUIRED', 2);
 
/**
* Checks if an OID has a valid dot notation.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $oid (string)<br />
* An OID in dot notation.
* @param $allow_leading_zeroes (bool)<br />
* true of leading zeroes are allowed or not.
* @param $allow_leading_dot (bool)<br />
* true of leading dots are allowed or not.
* @return (bool) true if the dot notation is valid.
**/
function oid_valid_dotnotation($oid, $allow_leading_zeroes=true, $allow_leading_dot=false, $min_len=0) {
$regex = oid_validation_regex($allow_leading_zeroes, $allow_leading_dot, $min_len);
 
return preg_match($regex, $oid, $m) ? true : false;
}
 
/**
* Returns a full regular expression to validate an OID in dot-notation
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $allow_leading_zeroes (bool)<br />
* true of leading zeroes are allowed or not.
* @param $allow_leading_dot (bool)<br />
* true of leading dots are allowed or not.
* @return (string) The regular expression
**/
function oid_validation_regex($allow_leading_zeroes=true, $allow_leading_dot=false, $min_len=0) {
$leading_dot_policy = $allow_leading_dot ? OID_DOT_OPTIONAL : OID_DOT_FORBIDDEN;
 
$part_regex = oid_part_regex($min_len, $allow_leading_zeroes, $leading_dot_policy);
 
return '@^'.$part_regex.'$@';
}
 
/**
* Returns a partial regular expression which matches valid OIDs in dot notation.
* It can be inserted into regular expressions.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $min_len (int)<br />
* 0="." and greater will be recognized, but not ""<br />
* 1=".2" and greater will be recognized<br />
* 2=".2.999" and greater will be recognized (default)<br />
* etc.
* @param $allow_leading_zeroes (bool)<br />
* true: ".2.0999" will be recognized<br />
* false: ".2.0999" won't be recognized (default)
* @param $leading_dot_policy (int)<br />
* 0 (OID_DOT_FORBIDDEN): forbidden<br />
* 1 (OID_DOT_OPTIONAL) : optional (default)<br />
* 2 (OID_DOT_REQUIRED) : enforced
* @return (string) A regular expression which matches OIDs in dot notation
**/
function oid_part_regex($min_len=2, $allow_leading_zeroes=false, $leading_dot_policy=OID_DOT_OPTIONAL) {
switch ($leading_dot_policy) {
case 0: // forbidden
$lead_dot = '';
break;
case 1: // optional
$lead_dot = '\\.{0,1}';
break;
case 2: // enforced
$lead_dot = '\\.';
break;
default:
assert(false);
break;
}
 
$lead_zero = $allow_leading_zeroes ? '0*' : '';
$zero_till_thirtynine = '(([0-9])|([1-3][0-9]))'; // second arc is limited to 0..39 if root arc is 0..1
$singledot_option = ($min_len == 0) && ($leading_dot_policy != OID_DOT_FORBIDDEN) ? '|\\.' : '';
$only_root_option = ($min_len <= 1) ? '|('.$lead_dot.$lead_zero.'[0-2])' : '';
 
$regex = '
(
(
(
('.$lead_dot.$lead_zero.'[0-1])
\\.'.$lead_zero.$zero_till_thirtynine.'
(\\.'.$lead_zero.'(0|[1-9][0-9]*)){'.max(0, $min_len-2).',}
)|(
('.$lead_dot.$lead_zero.'[2])
(\\.'.$lead_zero.'(0|[1-9][0-9]*)){'.max(0, $min_len-1).',}
)
'.$only_root_option.'
'.$singledot_option.'
)
)';
 
// Remove the indentations which are used to maintain this large regular expression in a human friendly way
$regex = str_replace("\n", '', $regex);
$regex = str_replace("\r", '', $regex);
$regex = str_replace("\t", '', $regex);
$regex = str_replace(' ', '', $regex);
 
return $regex;
}
 
/**
* Searches all OIDs in $text and outputs them as array.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $text (string)<br />
* The text to be parsed
* @param $min_len (int)<br />
* 0="." and greater will be recognized, but not ""<br />
* 1=".2" and greater will be recognized<br />
* 2=".2.999" and greater will be recognized (default)<br />
* etc.
* @param $allow_leading_zeroes (bool)<br />
* true: ".2.0999" will be recognized<br />
* false: ".2.0999" won't be recognized (default)
* @param $leading_dot_policy (int)<br />
* 0 (OID_DOT_FORBIDDEN): forbidden<br />
* 1 (OID_DOT_OPTIONAL) : optional (default)<br />
* 2 (OID_DOT_REQUIRED) : enforced
* @param $requires_whitespace_delimiters (bool)<br />
* true: "2.999" will be recognized, as well as " 2.999 " (default)<br />
* false: "2.999!" will be reconigzed, as well as "2.999.c" (this might be used in in documentations with templates)
* @return (array<string>) An array of OIDs in dot notation
**/
function parse_oids($text, $min_len=2, $allow_leading_zeroes=false, $leading_dot_policy=OID_DOT_OPTIONAL, $requires_whitespace_delimiters=true) {
$regex = oid_detection_regex($min_len, $allow_leading_zeroes, $leading_dot_policy, $requires_whitespace_delimiters);
 
preg_match_all($regex, $text, $matches);
return $matches[1];
}
 
/**
* Returns a full regular expression for detecting OIDs in dot notation inside a text.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $min_len (int)<br />
* 0="." and greater will be recognized, but not ""<br />
* 1=".2" and greater will be recognized<br />
* 2=".2.999" and greater will be recognized (default)<br />
* etc.
* @param $allow_leading_zeroes (bool)<br />
* true: ".2.0999" will be recognized<br />
* false: ".2.0999" won't be recognized (default)
* @param $leading_dot_policy (int)<br />
* 0 (OID_DOT_FORBIDDEN): forbidden<br />
* 1 (OID_DOT_OPTIONAL) : optional (default)<br />
* 2 (OID_DOT_REQUIRED) : enforced
* @param $requires_whitespace_delimiters (bool)<br />
* true: "2.999" will be recognized, as well as " 2.999 " (default)<br />
* false: "2.999!" will be reconigzed, as well as "2.999.c" (this might be used in in documentations with templates)
* @return (string) The regular expression
**/
function oid_detection_regex($min_len=2, $allow_leading_zeroes=false, $leading_dot_policy=OID_DOT_OPTIONAL, $requires_whitespace_delimiters=true) {
if ($requires_whitespace_delimiters) {
// A fully qualified regular expression which can be used by preg_match()
$begin_condition = '(?<=^|\\s)';
$end_condition = '(?=\\s|$)';
} else {
// A partial expression which can be used inside another regular expression
$begin_condition = '(?<![\d])';
$end_condition = '(?![\d])';
}
 
$part_regex = oid_part_regex($min_len, $allow_leading_zeroes, $leading_dot_policy);
 
return '@'.$begin_condition.$part_regex.$end_condition.'@';
}
 
/**
* Returns the parent of an OID in dot notation or the OID itself, if it is the root.<br />
* Leading dots and leading zeroes are tolerated.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-16
* @param $oid (string)<br />
* An OID in dot notation.
* @return (string) The parent OID in dot notation.
**/
function oid_up($oid) {
$oid = sanitizeOID($oid, 'auto');
if ($oid === false) return false;
 
$p = strrpos($oid, '.');
if ($p === false) return $oid;
if ($p == 0) return '.';
 
return substr($oid, 0, $p);
}
 
/**
* Outputs the depth of an OID.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $oid (string) An OID in dot notation (with or without leading dot)
* @return (int) The depth of the OID, e.g. 2.999 and .2.999 has the length 2.
**/
function oid_len($oid) {
if ($oid == '') return 0;
if ($oid[0] == '.') $oid = substr($oid, 1);
return substr_count($oid, '.')+1;
}
function oid_depth($oid) {
return oid_len($oid);
}
 
/**
* Lists all parents of an OID.
* This function tolerates leading dots. The parent of '.' stays '.'.
* The OID will not be checked for validity!
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-17
* @param $oid (string)<br />
* An OID in dot notation.
* @return (array<string>) An array with all parent OIDs.
**/
function oid_parents($oid) {
$parents = array();
 
while (oid_len($oid) > 1) {
$oid = oid_up($oid);
$parents[] = $oid;
}
 
if (substr($oid, 0, 1) == '.') $parents[] = '.';
 
return $parents;
}
 
/*
assert(oid_parents('.1.2.999') == array('.1.2', '.1', '.'));
assert(oid_parents('1.2.999') == array('1.2', '1'));
assert(oid_parents('.') == array('.'));
assert(oid_parents('') == array());
*/
 
/**
* Sorts an array containing OIDs in dot notation.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $ary (array<string>)<br />
* An array of OIDs in dot notation.<br />
* This array will be changed by this method.
* @param $output_with_leading_dot (bool)<br />
* true: The array will be normalized to OIDs with a leading dot.
* false: The array will be normalized to OIDs without a leading dot. (default)
* @return Nothing
**/
function oidSort(&$ary, $output_with_leading_dot=false) {
$out = array();
 
$none = $output_with_leading_dot ? '.' : '';
 
$d = array();
foreach ($ary as &$oid) {
if (($oid == '') || ($oid == '.')) {
$out[] = $none;
} else {
$oid = sanitizeOID($oid, 'auto'); // strike leading zeroes
$bry = explode('.', $oid, 2);
$firstarc = $bry[0];
$rest = (isset($bry[1])) ? $bry[1] : '';
$d[$firstarc][] = $rest;
}
}
unset($oid);
ksort($d);
 
foreach ($d as $firstarc => &$data) {
oidSort($data);
foreach ($data as &$rest) {
$out[] = ($output_with_leading_dot ? '.' : '')."$firstarc" . (($rest != $none) ? ".$rest" : '');
}
}
unset($data);
 
$ary = $out;
}
 
/**
* Removes leading zeroes from an OID in dot notation.
* @author Daniel Marschall, ViaThinkSoft
* @version 2015-08-17
* @param $oid (string)<br />
* An OID in dot notation.
* @param $leading_dot (bool)<br />
* true: The OID is valid, if it contains a leading dot.<br />
* false (default): The OID is valid, if it does not contain a leading dot.
* 'auto: Allow both
* @return (mixed) The OID without leading dots, or <code>false</code> if the OID is syntactically wrong.
**/
$oid_sanitize_cache = array();
function sanitizeOID($oid, $leading_dot=false) {
if ($leading_dot) $leading_dot = substr($oid,0,1) == '.';
 
// We are using a cache, since this function is used very often by OID+
global $oid_sanitize_cache;
$v = ($leading_dot ? 'T' : 'F').$oid;
if (isset($oid_sanitize_cache[$v])) return $oid_sanitize_cache[$v];
 
if ($leading_dot) {
if ($oid == '.') return '';
} else {
if ($oid == '') return '';
}
 
$out = '';
$ary = explode('.', $oid);
foreach ($ary as $n => &$a) {
if (($leading_dot) && ($n == 0)) {
if ($a != '') return false;
continue;
}
 
if (!ctype_digit($a)) return false; // does contain something other than digits
 
// strike leading zeroes
$a = preg_replace("@^0+@", '', $a);
if ($a == '') $a = 0;
 
if (($leading_dot) || ($n != 0)) $out .= '.';
$out .= $a;
}
unset($a);
unset($ary);
 
$oid_sanitize_cache[$v] = $out;
return $out;
}
 
/**
* Shows the top arc of an OID.
* This function tolerates leading dots.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-16
* @param $oid (string)<br />
* An OID in dot notation.
* @return (mixed) The top arc of the OID or empty string if it is already the root ('.')
**/
function oid_toparc($oid) {
$leadingdot = substr($oid,0,1) == '.';
 
$oid = sanitizeOID($oid, $leadingdot);
if ($oid === false) return false;
 
if (!$leadingdot) $oid = '.'.$oid;
 
$p = strrpos($oid, '.');
if ($p === false) return false;
$r = substr($oid, $p+1);
 
if ($leadingdot) {
# if ($r == '') return '.';
return $r;
} else {
return substr($r, 1);
}
}
 
/**
* Calculates the distance between two OIDs.
* This function tolerates leading dots and leading zeroes.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-20
* @param $a (string)<br />
* An OID.
* @param $b (string)<br />
* An OID.
* @return (string) false if both OIDs do not have a child-parent or parent-child relation, e.g. oid_distance('2.999.1.2.3', '2.999.4.5') = false, or if one of the OIDs is syntactially invalid<br />
* >0 if $a is more specific than $b , e.g. oid_distance('2.999.1.2', '2.999') = 2<br />
* <0 if $a is more common than $b , e.g. oid_distance('2.999', '2.999.1.2') = -2
**/
function oid_distance($a, $b) {
if (substr($a,0,1) == '.') $a = substr($a,1);
if (substr($b,0,1) == '.') $b = substr($b,1);
 
$a = sanitizeOID($a, false);
if ($a === false) return false;
$b = sanitizeOID($b, false);
if ($b === false) return false;
 
$ary = explode('.', $a);
$bry = explode('.', $b);
 
$min_len = min(count($ary), count($bry));
 
for ($i=0; $i<$min_len; $i++) {
if ($ary[$i] != $bry[$i]) return false;
}
 
return count($ary) - count($bry);
}
 
/*
assert(oid_distance('2.999.1.2.3', '2.999.4.5') === false);
assert(oid_distance('2.999.1.2', '2.999') === 2);
assert(oid_distance('2.999', '2.999.1.2') === -2);
*/
 
/**
* Adds a leading dot to an OID.
* Leading zeroes are tolerated.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-20
* @param $oid (string)<br />
* An OID.
* @return (string) The OID with a leading dot or false if the OID is syntactially wrong.
**/
function oid_add_leading_dot($oid) {
$oid = sanitizeOID($oid, 'auto');
if ($oid === false) return false;
 
if ($oid[0] != '.') $oid = '.'.$oid;
return $oid;
}
 
/**
* Removes a leading dot to an OID.
* Leading zeroes are tolerated.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-20
* @param $oid (string)<br />
* An OID.
* @return (string) The OID without a leading dot or false if the OID is syntactially wrong.
**/
function oid_remove_leading_dot($oid) {
$oid = sanitizeOID($oid, 'auto');
if ($oid === false) return false;
 
if (substr($oid,0,1) == '.') $oid = substr($oid, 1);
return $oid;
}
 
 
# === OID-IRI NOTATION FUNCTIONS ===
 
if (!function_exists('mb_ord')) {
# http://stackoverflow.com/a/24755772/3544341
function mb_ord($char, $encoding = 'UTF-8') {
if ($encoding === 'UCS-4BE') {
list(, $ord) = (strlen($char) === 4) ? @unpack('N', $char) : @unpack('n', $char);
return $ord;
} else {
return mb_ord(mb_convert_encoding($char, 'UCS-4BE', $encoding), 'UCS-4BE');
}
}
}
 
function iri_char_valid($c, $firstchar, $lastchar) {
// see Rec. ITU-T X.660, clause 7.5
 
if (($firstchar || $lastchar) && ($c == '-')) return false;
 
if ($c == '-') return true;
if ($c == '.') return true;
if ($c == '_') return true;
if ($c == '~') return true;
if (($c >= '0') && ($c <= '9') && (!$firstchar)) return true;
if (($c >= 'A') && ($c <= 'Z')) return true;
if (($c >= 'a') && ($c <= 'z')) return true;
 
$v = mb_ord($c);
 
if (($v >= 0x000000A0) && ($v <= 0x0000DFFE)) return true;
if (($v >= 0x0000F900) && ($v <= 0x0000FDCF)) return true;
if (($v >= 0x0000FDF0) && ($v <= 0x0000FFEF)) return true;
if (($v >= 0x00010000) && ($v <= 0x0001FFFD)) return true;
if (($v >= 0x00020000) && ($v <= 0x0002FFFD)) return true;
if (($v >= 0x00030000) && ($v <= 0x0003FFFD)) return true;
if (($v >= 0x00040000) && ($v <= 0x0004FFFD)) return true;
if (($v >= 0x00050000) && ($v <= 0x0005FFFD)) return true;
if (($v >= 0x00060000) && ($v <= 0x0006FFFD)) return true;
if (($v >= 0x00070000) && ($v <= 0x0007FFFD)) return true;
if (($v >= 0x00080000) && ($v <= 0x0008FFFD)) return true;
if (($v >= 0x00090000) && ($v <= 0x0009FFFD)) return true;
if (($v >= 0x000A0000) && ($v <= 0x000AFFFD)) return true;
if (($v >= 0x000B0000) && ($v <= 0x000BFFFD)) return true;
if (($v >= 0x000C0000) && ($v <= 0x000CFFFD)) return true;
if (($v >= 0x000D0000) && ($v <= 0x000DFFFD)) return true;
if (($v >= 0x000E1000) && ($v <= 0x000EFFFD)) return true;
 
// Note: Rec. ITU-T X.660, clause 7.5.3 would also forbid ranges which are marked in ISO/IEC 10646 as "(This position shall not be used)"
// But tool implementers should be tolerate them, since these limitations can be removed in future.
 
return false;
}
 
function iri_arc_valid($arc, $allow_numeric=true) {
if ($arc == '') return false;
 
if ($allow_numeric && preg_match('@^(\\d+)$@', $arc, $m)) return true; # numeric arc
 
// Question: Should we strip RTL/LTR characters?
 
if (mb_substr($arc, 2, 2) == '--') return false; // see Rec. ITU-T X.660, clause 7.5.4
 
$array = array();
preg_match_all('/./u', $arc, $array, PREG_SET_ORDER);
$len = count($array);
foreach ($array as $i => $char) {
if (!iri_char_valid($char[0], $i==0, $i==$len-1)) return false;
}
 
return true;
}
 
/**
* Checks if an IRI identifier is valid or not.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-17
* @param $iri (string)<br />
* An OID in OID-IRI notation, e.g. /Example/test
* @return (bool) true if the IRI identifier is valid.
**/
function iri_valid($iri) {
if ($iri == '/') return true; // OK?
 
if (substr($iri, 0, 1) != '/') return false;
 
$ary = explode('/', $iri);
array_shift($ary);
foreach ($ary as $a) {
if (!iri_arc_valid($a)) return false;
}
 
return true;
}
 
/*
assert(iri_arc_valid('ABCDEF'));
assert(!iri_arc_valid('-ABCDEF'));
assert(!iri_arc_valid('ABCDEF-'));
assert(!iri_arc_valid(' ABCDEF'));
assert(!iri_arc_valid('2 ABCDEF'));
assert(!iri_arc_valid(''));
 
assert(!iri_valid(''));
assert(iri_valid('/'));
assert(iri_valid('/hello/world'));
assert(iri_valid('/123/world'));
assert(!iri_valid('/hello/0world'));
assert(!iri_valid('/hello/xo--test'));
assert(!iri_valid('/hello/-super-/sd'));
*/
 
/**
* Returns an associative array in the form 'ASN.1' => '/2/1' .
* @author Daniel Marschall, ViaThinkSoft
* @version 2018-01-05
* @see http://itu.int/go/X660
* @return (array) An associative array in the form 'ASN.1' => '/2/1' .
**/
function iri_get_long_arcs() {
$iri_long_arcs = array();
$iri_long_arcs['ASN.1'] = '/2/1';
$iri_long_arcs['Country'] = '/2/16';
$iri_long_arcs['International-Organizations'] = '/2/23';
$iri_long_arcs['UUID'] = '/2/25';
$iri_long_arcs['Tag-Based'] = '/2/27';
$iri_long_arcs['BIP'] = '/2/41';
$iri_long_arcs['Telebiometrics'] = '/2/42';
$iri_long_arcs['Cybersecurity'] = '/2/48';
$iri_long_arcs['Alerting'] = '/2/49';
$iri_long_arcs['OIDResolutionSystem'] = '/2/50';
$iri_long_arcs['GS1'] = '/2/51';
$iri_long_arcs['Example'] = '/2/999'; // English
$iri_long_arcs['Exemple'] = '/2/999'; // French
$iri_long_arcs['Ejemplo'] = '/2/999'; // Spanish
$iri_long_arcs["\u{0627}\u{0644}\u{0645}\u{062B}\u{0627}\u{0644}"] = '/2/999'; // Arabic
$iri_long_arcs["\u{8303}\u{4F8B}"] = '/2/999'; // Chinese
$iri_long_arcs["\u{041F}\u{0440}\u{0438}\u{043C}\u{0435}\u{0440}"] = '/2/999'; // Russian
$iri_long_arcs["\u{C608}\u{C81C}"] = '/2/999'; // Korean
$iri_long_arcs["\u{4F8B}"] = '/2/999'; // Japanese
$iri_long_arcs['Beispiel'] = '/2/999'; // German
return $iri_long_arcs;
}
 
/**
* Tries to shorten/simplify an IRI by applying "long arcs", e.g. /2/999/123 -> /Example/123 .
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-28
* @param $iri (string)<br />
* An OID in OID-IRI notation, e.g. /Example/test
* @return (string) The modified IRI.
**/
function iri_add_longarcs($iri) {
$iri_long_arcs = iri_get_long_arcs();
 
// TODO: $iri valid?
 
$ary = explode('/', $iri);
 
$ary_number_iri = $ary;
if ($ary_number_iri[1] == 'Joint-ISO-ITU-T') $ary_number_iri[1] = '2';
/*
if ($ary_number_iri[1] == '2') {
// TODO: /2/Example -> /2/999 -> /Example
} else {
// Currently, only long arcs inside .2 are defined
// return $iri;
}
*/
$number_iri = implode('/', $ary_number_iri);
 
foreach ($iri_long_arcs as $cur_longarc => $cur_iri) {
// TODO: $cur_iri valid?
 
if (strpos($number_iri.'/', $cur_iri.'/') === 0) {
$cnt = substr_count($cur_iri, '/');
for ($i=1; $i<$cnt; $i++) {
array_shift($ary);
}
$ary[0] = '';
$ary[1] = $cur_longarc;
$iri = implode('/', $ary);
break;
}
}
 
return $iri;
}
 
# === FUNCTIONS FOR OIDS IN ASN.1 NOTATION ===
 
/**
* Checks if an ASN.1 identifier is valid.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $id (string)<br />
* An ASN.1 identifier, e.g. "example". Not "example(99)" or "99" and not a path like "{ 2 999 }"
* Note: Use asn1_path_valid() for validating a whole ASN.1 notation path.
* @return (bool) true, if the identifier is valid: It begins with an lowercase letter and contains only 0-9, a-z, A-Z and "-"
**/
# TODO: umbenennen in asn1_alpha_id_valid
function oid_id_is_valid($id) {
return preg_match('/^([a-z][a-zA-Z0-9-]*)$/', $id);
}
 
/**
* Checks if the ASN.1 notation of an OID is valid.
* This function does not tolerate leading zeros.
* This function will fail (return false) if there are unresolved symbols, e.g. {iso test} is not valid while { iso 123 } is valid.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-17
* @param $asn (string)<br />
* An OID in ASN.1 notation.
* @return (bools) true if the identifier is valid.
**/
function asn1_path_valid($asn1) {
return asn1_to_dot($asn1) != false;
}
 
/**
* Returns an array of standardized ASN.1 alphanumeric identifiers which do not require a numeric identifier, e.g. { 2 example }
* The array has the form '0.0.a' -> '0.0.1'
* @author Daniel Marschall, ViaThinkSoft
* @version 2019-03-25
* @see http://www.oid-info.com/name-forms.htm
* @return (array) Associative array of standardized ASN.1 alphanumeric identifiers
**/
function asn1_get_standardized_array() {
 
// Taken from oid-info.com
// http://www.oid-info.com/name-forms.htm
$standardized = array();
$standardized['itu-t'] = '0';
$standardized['ccitt'] = '0';
$standardized['iso'] = '1';
$standardized['joint-iso-itu-t'] = '2';
$standardized['joint-iso-ccitt'] = '2';
$standardized['0.recommendation'] = '0.0';
$standardized['0.0.a'] = '0.0.1';
$standardized['0.0.b'] = '0.0.2';
$standardized['0.0.c'] = '0.0.3';
$standardized['0.0.d'] = '0.0.4';
$standardized['0.0.e'] = '0.0.5';
$standardized['0.0.f'] = '0.0.6';
$standardized['0.0.g'] = '0.0.7';
$standardized['0.0.h'] = '0.0.8';
$standardized['0.0.i'] = '0.0.9';
$standardized['0.0.j'] = '0.0.10';
$standardized['0.0.k'] = '0.0.11';
$standardized['0.0.l'] = '0.0.12';
$standardized['0.0.m'] = '0.0.13';
$standardized['0.0.n'] = '0.0.14';
$standardized['0.0.o'] = '0.0.15';
$standardized['0.0.p'] = '0.0.16';
$standardized['0.0.q'] = '0.0.17';
$standardized['0.0.r'] = '0.0.18';
$standardized['0.0.s'] = '0.0.19';
$standardized['0.0.t'] = '0.0.20';
$standardized['0.0.u'] = '0.0.21';
$standardized['0.0.v'] = '0.0.22';
$standardized['0.0.w'] = '0.0.23'; // actually, this OID does not exist
$standardized['0.0.x'] = '0.0.24';
$standardized['0.0.y'] = '0.0.25';
$standardized['0.0.z'] = '0.0.26';
$standardized['0.question'] = '0.1';
$standardized['0.administration'] = '0.2';
$standardized['0.network-operator'] = '0.3';
$standardized['0.identified-organization'] = '0.4';
$standardized['1.standard'] = '1.0';
$standardized['1.registration-authority'] = '1.1';
$standardized['1.member-body'] = '1.2';
$standardized['1.identified-organization'] = '1.3';
return $standardized;
}
 
/**
* Converts an OID in ASN.1 notation into an OID in dot notation and tries to resolve well-known identifiers.<br />
* e.g. {joint-iso-itu-t(2) example(999) 1 2 3} --> 2.999.1.2.3<br />
* e.g. {iso 3} --> 1.3
* This function does not tolerate leading zeros.
* This function will fail (return false) if there are unresolved symbols, e.g. {iso test} will not be resolved to 1.test
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-17
* @param $asn (string)<br />
* An OID in ASN.1 notation.
* @return (string) An OID in dot notation without leading dot or false if the path is invalid.
**/
function asn1_to_dot($asn) {
$standardized = asn1_get_standardized_array();
 
// Clean up
$asn = preg_replace('@^\\{(.+)\\}$@', '\\1', $asn, -1, $count);
if ($count == 0) return false; // { and } are required. The asn.1 path will NOT be trimmed by this function
 
// If identifier is set, apply it (no check if it overrides a standardized identifier)
$asn = preg_replace('|\s*([a-z][a-zA-Z0-9-]*)\s*\((\d+)\)|', ' \\2', $asn);
$asn = trim($asn);
 
// Set dots
$asn = preg_replace('|\s+|', '.', $asn);
 
// Apply standardized identifiers (case sensitive)
$asn .= '.';
foreach ($standardized as $s => $r) {
$asn = preg_replace("|^$s|", $r, $asn);
}
$asn = substr($asn, 0, strlen($asn)-1);
 
// Check if all numbers are OK
// -> every arc must be resolved
// -> numeric arcs must not have a leading zero
// -> invalid stuff will be recognized, e.g. a "(1)" without an identifier in front of it
$ary = explode('.', $asn);
foreach ($ary as $a) {
if (!preg_match('@^(0|([1-9]\\d*))$@', $a, $m)) return false;
}
 
return $asn;
}
 
/*
assert(asn1_to_dot('{2 999 (1)}') == false);
assert(asn1_to_dot('{2 999 test}') == false);
assert(asn1_to_dot('{2 999 1}') == '2.999.1');
assert(asn1_to_dot(' {2 999 1} ') == false);
assert(asn1_to_dot('2 999 1') == false);
assert(asn1_to_dot('{2 999 01}') == false);
assert(asn1_to_dot('{ 0 question 123 }') == '0.1.123');
assert(asn1_to_dot('{ iso }') == '1');
assert(asn1_to_dot('{ iso(1) }') == '1');
assert(asn1_to_dot('{ iso(2) }') == '2');
assert(asn1_to_dot('{ iso 3 }') == '1.3');
*/
 
/**
* "Soft corrects" an invalid ASN.1 identifier.<br />
* Attention, by "soft correcting" the ID, it is not authoritative anymore, and might not be able to be resolved by ORS.
* @author Daniel Marschall, ViaThinkSoft
* @version 2014-12-09
* @param $id (string)<br />
* An ASN.1 identifier.
* @param $append_id_prefix (bool)<br />
* true (default): If the identifier doesn't start with a-Z, the problem will be solved by prepending "id-" to the identifier.<br />
* false: If the identifier doesn't start with a-Z, then the problem cannot be solved (method returns empty string).
* @return (string) The "soft corrected" ASN.1 identifier.<br />
* Invalid characters will be removed.<br />
* Uncorrectable start elements (0-9 or "-") will be either removed or solved by prepending "id-" (see <code>$append_id_prefix</code>)<br />
* If the identifier begins with an upper case letter, the letter will be converted into lower case.
**/
function oid_soft_correct_id($id, $append_id_prefix = true) {
// Convert "_" to "-"
$id = str_replace('_', '-', $id);
 
// Remove invalid characters
$id = preg_replace('/[^a-zA-Z0-9-]+/', '', $id);
 
// Remove uncorrectable start elements (0-9 or "-")
if ($append_id_prefix) {
$id = preg_replace('/^([^a-zA-Z]+)/', 'id-$1', $id);
} else {
$id = preg_replace('/^([^a-zA-Z]+)/', '', $id);
}
 
// "Correct" upper case beginning letter by converting it to lower case
if (preg_match('/^[A-Z]/', $id)) {
$id = strtolower($id[0]) . substr($id, 1);
}
 
return $id;
}
 
/trunk_oldversion/includes/oidinfo_api.inc.php
0,0 → 1,1074
<?php
 
/*
* OID-Info.com API for PHP
* Copyright 2019 Daniel Marschall, ViaThinkSoft
* Version 2019-11-06
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
error_reporting(E_ALL | E_NOTICE | E_STRICT | E_DEPRECATED);
 
if(!defined('STDIN')) define('STDIN', fopen('php://stdin', 'rb'));
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'wb'));
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'wb'));
 
if (file_exists(__DIR__ . '/oid_utils.inc.phps')) require_once __DIR__ . '/oid_utils.inc.phps';
if (file_exists(__DIR__ . '/oid_utils.inc.php')) require_once __DIR__ . '/oid_utils.inc.php';
if (file_exists(__DIR__ . '/xml_utils.inc.phps')) require_once __DIR__ . '/xml_utils.inc.phps';
if (file_exists(__DIR__ . '/xml_utils.inc.php')) require_once __DIR__ . '/xml_utils.inc.php';
if (file_exists(__DIR__ . '/../includes/oid_utils.inc.php')) require_once __DIR__ . '/../includes/oid_utils.inc.php';
if (file_exists(__DIR__ . '/../includes/xml_utils.inc.php')) require_once __DIR__ . '/../includes/xml_utils.inc.php';
if (file_exists(__DIR__ . '/../../includes/oid_utils.inc.php')) require_once __DIR__ . '/../../includes/oid_utils.inc.php';
if (file_exists(__DIR__ . '/../../includes/xml_utils.inc.php')) require_once __DIR__ . '/../../includes/xml_utils.inc.php';
if (file_exists(__DIR__ . '/../../../includes/oid_utils.inc.php')) require_once __DIR__ . '/../../../includes/oid_utils.inc.php';
if (file_exists(__DIR__ . '/../../../includes/xml_utils.inc.php')) require_once __DIR__ . '/../../../includes/xml_utils.inc.php';
 
class OIDInfoException extends Exception {
}
 
class OIDInfoAPI {
 
# --- PART 0: Constants
 
// First digit of the ping result
// "-" = error
// "0" = OID does not exist
// "1" = OID does exist, but is not approved yet
// "2" = OID does exist and is accessible
/*private*/ const PING_IDX_EXISTS = 0;
 
// Second digit of the ping result
// "-" = error
// "0" = The OID may not be created
// "1" = OID is not an illegal OID, and none of its ascendant is a leaf and its parent OID is not frozen
/*private*/ const PING_IDX_MAY_CREATE = 1;
 
/*private*/ const SOFT_CORRECT_BEHAVIOR_NONE = 0;
/*private*/ const SOFT_CORRECT_BEHAVIOR_LOWERCASE_BEGINNING = 1;
/*private*/ const SOFT_CORRECT_BEHAVIOR_ALL_POSSIBLE = 2;
 
/*public*/ const DEFAULT_ILLEGALITY_RULE_FILE = __DIR__ . '/oid_illegality_rules';
 
# --- Part 1: "Ping API" for checking if OIDs are available or allowed to create
 
public $verbosePingProviders = array('https://misc.daniel-marschall.de/oid-repository/ping_oid.php?oid={OID}');
 
private $pingCache = array();
 
public $pingCacheMaxAge = 3600;
 
public function clearPingCache() {
$this->pingCache = array();
}
 
public function checkOnlineExists($oid) {
if (!self::strictCheckSyntax($oid)) return false;
 
$pingResult = $this->pingOID($oid);
$ret = $pingResult[self::PING_IDX_EXISTS] >= 1;
return $ret;
}
 
public function checkOnlineAvailable($oid) {
if (!self::strictCheckSyntax($oid)) return false;
 
$pingResult = $this->pingOID($oid);
$ret = $pingResult[self::PING_IDX_EXISTS] == 2;
return $ret;
}
 
public function checkOnlineAllowed($oid) {
if (!self::strictCheckSyntax($oid)) return false;
 
$pingResult = $this->pingOID($oid);
return $pingResult[self::PING_IDX_MAY_CREATE] == 1;
}
 
public function checkOnlineMayCreate($oid) {
if (!self::strictCheckSyntax($oid)) return false;
 
$pingResult = $this->pingOID($oid);
 
// OID is either illegal, or one of their parents are leaf or frozen
# if (!checkOnlineAllowed($oid)) return false;
if ($pingResult[self::PING_IDX_MAY_CREATE] == 0) return false;
 
// The OID exists already, so we don't need to create it again
# if ($this->checkOnlineExists($oid)) return false;
if ($pingResult[self::PING_IDX_EXISTS] >= 1) return false;
 
return true;
}
 
protected function pingOID($oid) {
if (isset($this->pingCache[$oid])) {
$cacheAge = $this->pingCache[$oid][0] - time();
if ($cacheAge <= $this->pingCacheMaxAge) {
return $this->pingCache[$oid][1];
}
}
 
if (count($this->verbosePingProviders) == 0) {
throw new OIDInfoException("No verbose ping provider available!");
}
 
$res = false;
foreach ($this->verbosePingProviders as $url) {
$url = str_replace('{OID}', $oid, $url);
$cn = @file_get_contents($url);
if ($cn === false) continue;
$loc_res = trim($cn);
if (strpos($loc_res, '-') === false) {
$res = $loc_res;
break;
}
}
if ($res === false) {
throw new OIDInfoException("Could not ping OID $oid status!");
}
 
// if ($this->pingCacheMaxAge >= 0) {
$this->pingCache[$oid] = array(time(), $res);
//}
 
return $res;
}
 
# --- PART 2: Syntax checking
 
public static function strictCheckSyntax($oid) {
return oid_valid_dotnotation($oid, false, false, 1);
}
 
// Returns false if $oid has wrong syntax
// Return an OID without leading dot or zeroes, if the syntax is acceptable
public static function trySanitizeOID($oid) {
// Allow leading dots and leading zeroes, but remove then afterwards
$ok = oid_valid_dotnotation($oid, true, true, 1);
if ($ok === false) return false;
 
return sanitizeOID($oid, $oid[0] == '.');
}
 
# --- PART 3: XML file creation
 
protected static function eMailValid($email) {
# TODO: use isemail project
 
if (empty($email)) return false;
 
if (strpos($email, '@') === false) return false;
 
$ary = explode('@', $email, 2);
if (!isset($ary[1])) return false;
if (strpos($ary[1], '.') === false) return false;
 
return true;
}
 
public function softCorrectEMail($email, $params) {
$email = str_replace(' ', '', $email);
$email = str_replace('&', '@', $email);
$email = str_replace('(at)', '@', $email);
$email = str_replace('[at]', '@', $email);
$email = str_replace('(dot)', '.', $email);
$email = str_replace('[dot]', '.', $email);
$email = trim($email);
 
if (!$params['allow_illegal_email'] && !self::eMailValid($email)) {
return '';
}
 
return $email;
}
 
public function softCorrectPhone($phone, $params) {
// TODO: if no "+", add "+1" , but only if address is in USA
// TODO: or use param to fixate country if it is not known
/*
NOTE: with german phone numbers, this will cause trouble, even if we assume "+49"
06223 / 1234
shall be
+49 6223 1234
and not
+49 06223 1234
*/
 
$phone = str_replace('-', ' ', $phone);
$phone = str_replace('.', ' ', $phone);
$phone = str_replace('/', ' ', $phone);
$phone = str_replace('(', ' ', $phone);
$phone = str_replace(')', ' ', $phone);
 
// HL7 registry has included this accidently
$phone = str_replace('&quot;', '', $phone);
 
$phone = trim($phone);
 
return $phone;
}
 
private static function strip_to_xhtml_light($str, $allow_strong_text=false) {
// <strong> is allowed in the XSD, but not <b>
$str = str_ireplace('<b>', '<strong>', $str);
$str = str_ireplace('</b>', '</strong>', $str);
 
if (!$allow_strong_text) {
// <strong> is only used for very important things like the word "deprecated". It should therefore not used for anything else
$str = str_ireplace('<strong>', '', $str);
$str = str_ireplace('</strong>', '', $str);
}
 
$str = preg_replace('@<\s*script.+<\s*/script.*>@isU', '', $str);
$str = preg_replace('@<\s*style.+<\s*/style.*>@isU', '', $str);
 
$str = preg_replace_callback(
'@<(\s*/{0,1}\d*)([^\s/>]+)(\s*[^>]*)>@i',
function ($treffer) {
// see http://oid-info.com/xhtml-light.xsd
$whitelist = array('a', 'br', 'code', 'em', 'font', 'img', 'li', 'strong', 'sub', 'sup', 'ul');
 
$pre = $treffer[1];
$tag = $treffer[2];
$attrib = $treffer[3];
if (in_array($tag, $whitelist)) {
return '<'.$pre.$tag.$attrib.'>';
} else {
return '';
}
}, $str);
 
return $str;
}
 
const OIDINFO_CORRECT_DESC_OPTIONAL_ENDING_DOT = 0;
const OIDINFO_CORRECT_DESC_ENFORCE_ENDING_DOT = 1;
const OIDINFO_CORRECT_DESC_DISALLOW_ENDING_DOT = 2;
 
public function correctDesc($desc, $params, $ending_dot_policy=self::OIDINFO_CORRECT_DESC_OPTIONAL_ENDING_DOT, $enforce_xhtml_light=false) {
$desc = trim($desc);
 
$desc = preg_replace('@<!\\[CDATA\\[(.+)\\]\\]>@ismU', '\\1', $desc);
 
if (substr_count($desc, '>') != substr_count($desc, '<')) {
$params['allow_html'] = false;
}
 
$desc = str_replace("\r", '', $desc);
 
if (!$params['allow_html']) {
// htmlentities_numeric() does this for us
/*
$desc = str_replace('&', '&amp;', $desc);
$desc = str_replace('<', '&lt;', $desc);
$desc = str_replace('>', '&gt;', $desc);
$desc = str_replace('"', '&quot;', $desc);
$desc = str_replace("'", '&#39;', $desc); // &apos; is not HTML. It is XML
*/
 
$desc = str_replace("\n", '<br />', $desc);
} else {
// Some problems we had with HL7 registry
$desc = preg_replace('@&lt;(/{0,1}(p|i|b|u|ul|li))&gt;@ismU', '<\\1>', $desc);
# preg_match_all('@&lt;[^ :\\@]+&gt;@ismU', $desc, $m);
# if (count($m[0]) > 0) print_r($m);
 
$desc = preg_replace('@<i>(.+)&lt;i/&gt;@ismU', '<i>\\1</i>', $desc);
$desc = str_replace('<p><p>', '</p><p>', $desc);
 
// <p> are not supported by oid-info.com
$desc = str_replace('<p>', '<br /><br />', $desc);
$desc = str_replace('</p>', '', $desc);
}
 
// Escape unicode characters as numeric &#...;
// The XML 1.0 standard does only has a few entities, but nothing like e.g. &euro; , so we prefer numeric
 
//$desc = htmlentities_numeric($desc, $params['allow_html']);
if (!$params['allow_html']) $desc = htmlentities($desc);
$desc = html_named_to_numeric_entities($desc);
 
// Remove HTML tags which are not allowed
if ($params['allow_html'] && (!$params['ignore_xhtml_light']) && $enforce_xhtml_light) {
// oid-info.com does only allow a few HTML tags
// see http://oid-info.com/xhtml-light.xsd
$desc = self::strip_to_xhtml_light($desc);
}
 
// Solve some XML problems...
$desc = preg_replace('@<\s*br\s*>@ismU', '<br/>', $desc); // auto close <br>
$desc = preg_replace('@(href\s*=\s*)(["\'])(.*)&([^#].*)(\2)@ismU', '\1\2\3&amp;\4\5', $desc); // fix "&" inside href-URLs to &amp;
// TODO: what do we do if there are more XHTML errors (e.g. additional open tags) which would make the XML invalid?
 
// "Trim" <br/>
do { $desc = preg_replace('@^\s*<\s*br\s*/{0,1}\s*>@isU', '', $desc, -1, $count); } while ($count > 0); // left trim
do { $desc = preg_replace('@<\s*br\s*/{0,1}\s*>\s*$@isU', '', $desc, -1, $count); } while ($count > 0); // right trim
 
// Correct double-encoded stuff
if (!isset($params['tolerant_htmlentities']) || $params['tolerant_htmlentities']) {
do {
$old_desc = $desc;
# Full list of entities: https://www.freeformatter.com/html-entities.html
# Max: 8 chars ( &thetasym; )
# Min: 2 chars ( lt,gt,ni,or,ne,le,ge,Mu,Nu,Xi,Pi,mu,nu,xi,pi )
$desc = preg_replace('@(&|&amp;)(#|&#35;)(\d+);@ismU', '&#\3;', $desc);
$desc = preg_replace('@(&|&amp;)([a-zA-Z0-9]{2,8});@ismU', '&\2;', $desc);
} while ($old_desc != $desc);
}
 
// TODO: use the complete list of oid-info.com
// TODO: Make this step optional using $params
/*
Array
(
[0] => Root OID for
[1] => OID for
[2] => OID identifying
[3] => Top arc for
[4] => Arc for
[5] => arc root
[6] => Node for
[7] => Leaf node for
[8] => This OID describes
[9] => [tT]his oid
[10] => This arc describes
[11] => This identifies
[12] => Identifies a
[13] => [Oo]bject [Ii]dentifier
[14] => Identifier for
[15] => This [Ii]dentifier is for
[16] => Identifiers used by
[17] => identifier$
[18] => This branch
[19] => Branch for
[20] => Child tree for
[21] => Child for
[22] => Subtree for
[23] => Sub-OID
[24] => Tree for
[25] => Child object
[26] => Parent OID
[27] => root for
[28] => Assigned for
[29] => Used to identify
[30] => Used in
[31] => Used for
[32] => For use by
[33] => Entry for
[34] => This is for
[35] => ["]?OID["]?
[36] => ^OID
[37] => OID$
[38] => oid
[39] => oid$
[40] => OIDs
)
$x = 'Root OID for ; OID for ; OID identifying ; Top arc for ; Arc for ; arc root; Node for ; Leaf node for ; This OID describes ; [tT]his oid ; This arc describes ; This identifies ; Identifies a ; [Oo]bject [Ii]dentifier; Identifier for ; This [Ii]dentifier is for ; Identifiers used by ; identifier$; This branch ; Branch for ; Child tree for ; Child for ; Subtree for ; Sub-OID; Tree for ; Child object; Parent OID; root for ; Assigned for ; Used to identify ; Used in ; Used for ; For use by ; Entry for ; This is for ; ["]?OID["]? ; ^OID ; OID$; oid ; oid$; OIDs';
$ary = explode('; ', $x);
print_r($ary);
*/
$desc = preg_replace("@^Root OID for the @i", '', $desc);
$desc = preg_replace("@^Root OID for @i", '', $desc);
$desc = preg_replace("@^OID root for the @i", '', $desc);
$desc = preg_replace("@^OID root for @i", '', $desc);
$desc = preg_replace("@^This OID will be used for @i", '', $desc);
$desc = preg_replace("@^This will be a generic OID for the @i", '', $desc);
$desc = preg_replace("@^OID for @i", '', $desc);
$desc = preg_replace("@ Root OID$@i", '', $desc);
$desc = preg_replace("@ OID$@i", '', $desc);
$desc = preg_replace("@ OID Namespace$@i", '', $desc);
$desc = preg_replace("@^OID for @i", '', $desc);
 
$desc = rtrim($desc);
if ($ending_dot_policy == self::OIDINFO_CORRECT_DESC_ENFORCE_ENDING_DOT) {
if (($desc != '') && (substr($desc, -1)) != '.') $desc .= '.';
} else if ($ending_dot_policy == self::OIDINFO_CORRECT_DESC_DISALLOW_ENDING_DOT) {
$desc = preg_replace('@\\.$@', '', $desc);
}
 
return $desc;
}
 
public function xmlAddHeader($firstName, $lastName, $email) {
// TODO: encode
 
$firstName = htmlentities_numeric($firstName);
if (empty($firstName)) {
throw new OIDInfoException("Please supply a first name");
}
 
$lastName = htmlentities_numeric($lastName);
if (empty($lastName)) {
throw new OIDInfoException("Please supply a last name");
}
 
$email = htmlentities_numeric($email);
if (empty($email)) {
throw new OIDInfoException("Please supply an email address");
}
 
// $out = "<!DOCTYPE oid-database>\n\n";
$out = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
$out .= '<oid-database xmlns="http://oid-info.com"'."\n";
$out .= ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'."\n";
$out .= ' xsi:schemaLocation="http://oid-info.com '."\n";
$out .= ' http://oid-info.com/oid.xsd">'."\n";
$out .= "\t<submitter>\n";
$out .= "\t\t<first-name>$firstName</first-name>\n";
$out .= "\t\t<last-name>$lastName</last-name>\n";
$out .= "\t\t<email>$email</email>\n";
$out .= "\t</submitter>\n";
 
if (!self::eMailValid($email)) {
throw new OIDInfoException("eMail address '$email' is invalid");
}
 
return $out;
}
 
public function xmlAddFooter() {
return "</oid-database>\n";
}
 
/*
-- CODE TEMPLATE --
 
$params['allow_html'] = false; // Allow HTML in <description> and <information>
$params['allow_illegal_email'] = true; // We should allow it, because we don't know if the user has some kind of human-readable anti-spam technique
$params['soft_correct_behavior'] = OIDInfoAPI::SOFT_CORRECT_BEHAVIOR_NONE;
$params['do_online_check'] = false; // Flag to disable this online check, because it generates a lot of traffic and runtime.
$params['do_illegality_check'] = true;
$params['do_simpleping_check'] = true;
$params['auto_extract_name'] = '';
$params['auto_extract_url'] = '';
$params['always_output_comment'] = false; // Also output comment if there was an error (e.g. OID already existing)
$params['creation_allowed_check'] = true;
$params['tolerant_htmlentities'] = true;
$params['ignore_xhtml_light'] = false;
 
$elements['synonymous-identifier'] = ''; // string or array
$elements['description'] = '';
$elements['information'] = '';
 
$elements['first-registrant']['first-name'] = '';
$elements['first-registrant']['last-name'] = '';
$elements['first-registrant']['address'] = '';
$elements['first-registrant']['email'] = '';
$elements['first-registrant']['phone'] = '';
$elements['first-registrant']['fax'] = '';
$elements['first-registrant']['creation-date'] = '';
 
$elements['current-registrant']['first-name'] = '';
$elements['current-registrant']['last-name'] = '';
$elements['current-registrant']['address'] = '';
$elements['current-registrant']['email'] = '';
$elements['current-registrant']['phone'] = '';
$elements['current-registrant']['fax'] = '';
$elements['current-registrant']['modification-date'] = '';
 
$oid = '1.2.3';
 
$comment = 'test';
 
echo $oa->createXMLEntry($oid, $elements, $params, $comment);
*/
public function createXMLEntry($oid, $elements, $params, $comment='') {
// Backward compatibility
if (!isset($params['do_csv_check'])) $params['do_simpleping_check'] = true;
 
// Set default behavior
if (!isset($params['allow_html'])) $params['allow_html'] = false; // Allow HTML in <description> and <information>
if (!isset($params['allow_illegal_email'])) $params['allow_illegal_email'] = true; // We should allow it, because we don't know if the user has some kind of human-readable anti-spam technique
if (!isset($params['soft_correct_behavior'])) $params['soft_correct_behavior'] = self::SOFT_CORRECT_BEHAVIOR_NONE;
if (!isset($params['do_online_check'])) $params['do_online_check'] = false; // Flag to disable this online check, because it generates a lot of traffic and runtime.
if (!isset($params['do_illegality_check'])) $params['do_illegality_check'] = true;
if (!isset($params['do_simpleping_check'])) $params['do_simpleping_check'] = true;
if (!isset($params['auto_extract_name'])) $params['auto_extract_name'] = '';
if (!isset($params['auto_extract_url'])) $params['auto_extract_url'] = '';
if (!isset($params['always_output_comment'])) $params['always_output_comment'] = false; // Also output comment if there was an error (e.g. OID already existing)
if (!isset($params['creation_allowed_check'])) $params['creation_allowed_check'] = true;
if (!isset($params['tolerant_htmlentities'])) $params['tolerant_htmlentities'] = true;
if (!isset($params['ignore_xhtml_light'])) $params['ignore_xhtml_light'] = false;
 
$out = '';
if (!empty($comment)) $out .= "\t\t<!-- $comment -->\n";
 
if ($params['always_output_comment']) {
$err = $out;
} else {
$err = false;
}
 
if (isset($elements['dotted_oid'])) {
throw new OIDInfoException("'dotted_oid' in the \$elements array is not supported. Please use the \$oid argument.");
}
if (isset($elements['value'])) {
// TODO: WHAT SHOULD WE DO WITH THAT?
throw new OIDInfoException("'value' in the \$elements array is currently not supported.");
}
 
$bak_oid = $oid;
$oid = self::trySanitizeOID($oid);
if ($oid === false) {
fwrite(STDOUT/*STDERR*/,"<!-- ERROR: Ignored '$bak_oid', because it is not a valid OID -->\n");
return $err;
}
 
if ($params['creation_allowed_check']) {
if (!$this->oidMayCreate($oid, $params['do_online_check'], $params['do_simpleping_check'], $params['do_illegality_check'])) {
fwrite(STDOUT/*STDERR*/,"<!-- ERROR: Creation of $oid disallowed -->\n");
return $err;
}
} else {
if ($params['do_illegality_check'] && ($this->illegalOid($oid))) {
fwrite(STDOUT/*STDERR*/,"<!-- ERROR: Creation of $oid disallowed -->\n");
return $err;
}
}
 
$elements['description'] = $this->correctDesc($elements['description'], $params, self::OIDINFO_CORRECT_DESC_DISALLOW_ENDING_DOT, true);
$elements['information'] = $this->correctDesc($elements['information'], $params, self::OIDINFO_CORRECT_DESC_ENFORCE_ENDING_DOT, true);
 
// Request by O.D. 26 August 2019
$elements['description'] = trim($elements['description']);
if (preg_match('@^[a-z]@', $elements['description'], $m)) {
$ending_dot_policy = self::OIDINFO_CORRECT_DESC_DISALLOW_ENDING_DOT; // for description
if (($ending_dot_policy != self::OIDINFO_CORRECT_DESC_ENFORCE_ENDING_DOT) && (strpos($elements['description'], ' ') === false)) { // <-- added by DM
$elements['description'] = '"' . $elements['description'] . '"';
}
}
// End request by O.D. 26. August 2019
 
if ($params['auto_extract_name'] || $params['auto_extract_url']) {
if (!empty($elements['information'])) $elements['information'] .= '<br /><br />';
if ($params['auto_extract_name'] || $params['auto_extract_url']) {
$elements['information'] .= 'Automatically extracted from <a href="'.$params['auto_extract_url'].'">'.$params['auto_extract_name'].'</a>.';
} else if ($params['auto_extract_name']) {
$elements['information'] .= 'Automatically extracted from '.$params['auto_extract_name'];
} else if ($params['auto_extract_url']) {
$hr_url = $params['auto_extract_url'];
// $hr_url = preg_replace('@^https{0,1}://@ismU', '', $hr_url);
$hr_url = preg_replace('@^http://@ismU', '', $hr_url);
$elements['information'] .= 'Automatically extracted from <a href="'.$params['auto_extract_url'].'">'.$hr_url.'</a>.';
}
}
 
// Validate ASN.1 ID
if (isset($elements['synonymous-identifier'])) {
if (!is_array($elements['synonymous-identifier'])) {
$elements['synonymous-identifier'] = array($elements['synonymous-identifier']);
}
foreach ($elements['synonymous-identifier'] as &$synid) {
if ($synid == '') {
$synid = null;
continue;
}
 
$behavior = $params['soft_correct_behavior'];
 
if ($behavior == self::SOFT_CORRECT_BEHAVIOR_NONE) {
if (!oid_id_is_valid($synid)) $synid = null;
} else if ($behavior == self::SOFT_CORRECT_BEHAVIOR_LOWERCASE_BEGINNING) {
$synid[0] = strtolower($synid[0]);
if (!oid_id_is_valid($synid)) $synid = null;
} else if ($behavior == self::SOFT_CORRECT_BEHAVIOR_ALL_POSSIBLE) {
$synid = oid_soft_correct_id($synid);
// if (!oid_id_is_valid($synid)) $synid = null;
} else {
throw new OIDInfoException("Unexpected soft-correction behavior for ASN.1 IDs");
}
}
}
 
// ATTENTION: the XML-generator will always add <dotted-oid> , but what will happen if additionally an
// asn1-path (<value>) is given? (the resulting OIDs might be inconsistent/mismatch)
if (isset($elements['value']) && (!asn1_path_valid($elements['value']))) {
unset($elements['value']);
}
 
// Validate IRI (currently not supported by oid-info.com, but the tag name is reserved)
if (isset($elements['iri'])) {
if (!is_array($elements['iri'])) {
$elements['iri'] = array($elements['iri']);
}
foreach ($elements['iri'] as &$iri) {
// Numeric-only nicht erlauben. Das wƤre ja nur in einem IRI-Pfad gĆ¼ltig, aber nicht als einzelner Identifier
if (!iri_arc_valid($iri, false)) $iri = null;
}
}
 
if (isset($elements['first-registrant']['phone']))
$elements['first-registrant']['phone'] = $this->softCorrectPhone($elements['first-registrant']['phone'], $params);
 
if (isset($elements['current-registrant']['phone']))
$elements['current-registrant']['phone'] = $this->softCorrectPhone($elements['current-registrant']['phone'], $params);
 
if (isset($elements['first-registrant']['fax']))
$elements['first-registrant']['fax'] = $this->softCorrectPhone($elements['first-registrant']['fax'], $params);
 
if (isset($elements['current-registrant']['fax']))
$elements['current-registrant']['fax'] = $this->softCorrectPhone($elements['current-registrant']['fax'], $params);
 
if (isset($elements['first-registrant']['email']))
$elements['first-registrant']['email'] = $this->softCorrectEMail($elements['first-registrant']['email'], $params);
 
if (isset($elements['current-registrant']['email']))
$elements['current-registrant']['email'] = $this->softCorrectEMail($elements['current-registrant']['email'], $params);
 
// TODO: if name is empty, but address has 1 line, take it as firstname (but remove hyperlink)
 
$out_loc = '';
foreach ($elements as $name => $val) {
if (($name == 'first-registrant') || ($name == 'current-registrant')) {
$out_loc2 = '';
foreach ($val as $name2 => $val2) {
if (is_null($val2)) continue;
if (empty($val2)) continue;
 
if (!is_array($val2)) $val2 = array($val2);
 
foreach ($val2 as $val3) {
// if (is_null($val3)) continue;
if (empty($val3)) continue;
 
if ($name2 == 'address') {
// $val3 = htmlentities_numeric($val3);
$val3 = $this->correctDesc($val3, $params, self::OIDINFO_CORRECT_DESC_DISALLOW_ENDING_DOT, true);
} else {
// $val3 = htmlentities_numeric($val3);
$val3 = $this->correctDesc($val3, $params, self::OIDINFO_CORRECT_DESC_DISALLOW_ENDING_DOT, false);
}
$out_loc2 .= "\t\t\t<$name2>".$val3."</$name2>\n";
}
}
 
if (!empty($out_loc2)) {
$out_loc .= "\t\t<$name>\n";
$out_loc .= $out_loc2;
$out_loc .= "\t\t</$name>\n";
}
} else {
// if (is_null($val)) continue;
if (empty($val) && ($name != 'description')) continue; // description is mandatory, according to http://oid-info.com/oid.xsd
 
if (!is_array($val)) $val = array($val);
 
foreach ($val as $val2) {
// if (is_null($val2)) continue;
if (empty($val2) && ($name != 'description')) continue; // description is mandatory, according to http://oid-info.com/oid.xsd
 
if (($name != 'description') && ($name != 'information')) { // don't correctDesc description/information, because we already did it above.
// $val2 = htmlentities_numeric($val2);
$val2 = $this->correctDesc($val2, $params, self::OIDINFO_CORRECT_DESC_OPTIONAL_ENDING_DOT, false);
}
$out_loc .= "\t\t<$name>".$val2."</$name>\n";
}
}
}
 
if (!empty($out)) {
$out = "\t<oid>\n"."\t\t".trim($out)."\n";
} else {
$out = "\t<oid>\n";
}
$out .= "\t\t<dot-notation>$oid</dot-notation>\n";
$out .= $out_loc;
$out .= "\t</oid>\n";
 
return $out;
}
 
# --- PART 4: Offline check if OIDs are illegal
 
protected $illegality_rules = array();
 
public function clearIllegalityRules() {
$this->illegality_rules = array();
}
 
public function loadIllegalityRuleFile($file) {
if (!file_exists($file)) {
throw new OIDInfoException("Error: File '$file' does not exist");
}
 
$lines = file($file);
 
if ($lines === false) {
throw new OIDInfoException("Error: Could not load '$file'");
}
 
$signature = trim(array_shift($lines));
if (($signature != '[1.3.6.1.4.1.37476.3.1.5.1]') && ($signature != '[1.3.6.1.4.1.37476.3.1.5.2]')) {
throw new OIDInfoException("'$file' does not seem to a valid illegality rule file (file format OID does not match. Signature $signature unexpected)");
}
 
foreach ($lines as $line) {
// Remove comments
$ary = explode('--', $line);
$rule = trim($ary[0]);
 
if ($rule !== '') $this->addIllegalityRule($rule);
}
}
 
public function addIllegalityRule($rule) {
$test = $rule;
$test = preg_replace('@\\.\\(!\\d+\\)@ismU', '.0', $test); // added in ver 2
$test = preg_replace('@\\.\\(\\d+\\+\\)@ismU', '.0', $test);
$test = preg_replace('@\\.\\(\\d+\\-\\)@ismU', '.0', $test);
$test = preg_replace('@\\.\\(\\d+\\-\\d+\\)@ismU', '.0', $test);
$test = preg_replace('@\\.\\*@ismU', '.0', $test);
 
if (!oid_valid_dotnotation($test, false, false, 1)) {
throw new OIDInfoException("Illegal illegality rule '$rule'.");
}
 
$this->illegality_rules[] = $rule;
}
 
private static function bigint_cmp($a, $b) {
if (function_exists('bccomp')) {
return bccomp($a, $b);
}
 
if (function_exists('gmp_cmp')) {
return gmp_cmp($a, $b);
}
 
if ($a > $b) return 1;
if ($a < $b) return -1;
return 0;
}
 
public function illegalOID($oid, &$illegal_root='') {
$bak = $oid;
$oid = self::trySanitizeOID($oid);
if ($oid === false) {
$illegal_root = $bak;
return true; // is illegal
}
 
$rules = $this->illegality_rules;
 
foreach ($rules as $rule) {
$rule = str_replace(array('(', ')'), '', $rule);
 
$oarr = explode('.', $oid);
$rarr = explode('.', $rule);
 
if (count($oarr) < count($rarr)) continue;
 
$rulefit = true;
 
$illrootary = array();
 
$vararcs = 0;
$varsfit = 0;
for ($i=0; $i<count($rarr); $i++) {
$oelem = $oarr[$i];
$relem = $rarr[$i];
 
$illrootary[] = $oelem;
 
if ($relem == '*') $relem = '0+';
 
$startchar = substr($relem, 0, 1);
$endchar = substr($relem, -1, 1);
if ($startchar == '!') { // added in ver 2
$vararcs++;
$relem = substr($relem, 1, strlen($relem)-1); // cut away first char
$cmp = self::bigint_cmp($oelem, $relem) != 0;
if ($cmp) $varsfit++;
} else if ($endchar == '+') {
$vararcs++;
$relem = substr($relem, 0, strlen($relem)-1); // cut away last char
$cmp = self::bigint_cmp($oelem, $relem) >= 0;
if ($cmp) $varsfit++;
} else if ($endchar == '-') {
$vararcs++;
$relem = substr($relem, 0, strlen($relem)-1); // cut away last char
$cmp = self::bigint_cmp($oelem, $relem) <= 0;
if ($cmp) $varsfit++;
} else if (strpos($relem, '-') !== false) {
$vararcs++;
$limarr = explode('-', $relem);
$limmin = $limarr[0];
$limmax = $limarr[1];
$cmp_min = self::bigint_cmp($oelem, $limmin) >= 0;
$cmp_max = self::bigint_cmp($oelem, $limmax) <= 0;
if ($cmp_min && $cmp_max) $varsfit++;
} else {
if ($relem != $oelem) {
$rulefit = false;
break;
}
}
}
 
if ($rulefit && ($vararcs == $varsfit)) {
$illegal_root = implode('.', $illrootary);
return true; // is illegal
}
}
 
$illegal_root = '';
return false; // not illegal
}
 
# --- PART 5: Misc functions
 
function __construct() {
if (file_exists(self::DEFAULT_ILLEGALITY_RULE_FILE)) {
$this->loadIllegalityRuleFile(self::DEFAULT_ILLEGALITY_RULE_FILE);
}
}
 
public static function getPublicURL($oid) {
return "http://oid-info.com/get/$oid";
}
 
public function oidExisting($oid, $onlineCheck=true, $useSimplePingProvider=true) {
$bak_oid = $oid;
$oid = self::trySanitizeOID($oid);
if ($oid === false) {
throw new OIDInfoException("'$bak_oid' is not a valid OID");
}
 
$canuseSimplePingProvider = $useSimplePingProvider && $this->simplePingProviderAvailable();
if ($canuseSimplePingProvider) {
if ($this->simplePingProviderCheckOID($oid)) return true;
}
if ($onlineCheck) {
return $this->checkOnlineExists($oid);
}
if ((!$canuseSimplePingProvider) && (!$onlineCheck)) {
throw new OIDInfoException("No simple or verbose checking method chosen/available");
}
return false;
}
 
public function oidMayCreate($oid, $onlineCheck=true, $useSimplePingProvider=true, $illegalityCheck=true) {
$bak_oid = $oid;
$oid = self::trySanitizeOID($oid);
if ($oid === false) {
throw new OIDInfoException("'$bak_oid' is not a valid OID");
}
 
if ($illegalityCheck && $this->illegalOID($oid)) return false;
 
$canuseSimplePingProvider = $useSimplePingProvider && $this->simplePingProviderAvailable();
if ($canuseSimplePingProvider) {
if ($this->simplePingProviderCheckOID($oid)) return false;
}
if ($onlineCheck) {
return $this->checkOnlineMayCreate($oid);
}
if ((!$canuseSimplePingProvider) && (!$onlineCheck)) {
throw new OIDInfoException("No simple or verbose checking method chosen/available");
}
return true;
}
 
# --- PART 6: Simple Ping Providers
# TODO: Question ... can't these provider concepts (SPP and VPP) not somehow be combined?
 
protected $simplePingProviders = array();
 
public function addSimplePingProvider($addr) {
if (!isset($this->simplePingProviders[$addr])) {
if (strtolower(substr($addr, -4, 4)) == '.csv') {
$this->simplePingProviders[$addr] = new CSVSimplePingProvider($addr);
} else {
$this->simplePingProviders[$addr] = new OIDSimplePingProvider($addr);
// $this->simplePingProviders[$addr]->connect();
}
}
return $this->simplePingProviders[$addr];
}
 
public function removeSimplePingProvider($addr) {
$this->simplePingProviders[$addr]->disconnect();
unset($this->simplePingProviders[$addr]);
}
 
public function removeAllSimplePingProviders() {
foreach ($this->simplePingProviders as $addr => $obj) {
$this->removeSimplePingProvider($addr);
}
}
 
public function listSimplePingProviders() {
$out = array();
foreach ($this->simplePingProviders as $addr => $obj) {
$out[] = $addr;
}
return $out;
}
 
public function simplePingProviderCheckOID($oid) {
if (!$this->simplePingProviderAvailable()) {
throw new OIDInfoException("No simple ping providers available.");
}
 
$one_null = false;
foreach ($this->simplePingProviders as $addr => $obj) {
$res = $obj->queryOID($oid);
if ($res) return true;
if ($res !== false) $one_null = true;
}
 
return $one_null ? null : false;
}
 
public function simplePingProviderAvailable() {
return count($this->simplePingProviders) >= 1;
}
 
}
 
interface IOIDSimplePingProvider {
public function queryOID($oid);
public function disconnect();
public function connect();
}
 
class CSVSimplePingProvider implements IOIDSimplePingProvider {
protected $csvfile = '';
protected $lines = array();
protected $filemtime = 0;
 
public function queryOID($oid) {
$this->reloadCSV();
return in_array($oid, $this->lines);
}
 
public function disconnect() {
// Nothing
}
 
public function connect() {
// Nothing
}
 
// TODO: This cannot handle big CSVs. We need to introduce the old code of "2016-09-02_old_oidinfo_api_with_csv_reader.zip" here.
protected function reloadCSV() {
if (!file_exists($this->csvfile)) {
throw new OIDInfoException("File '".$this->csvfile."' does not exist");
}
$filemtime = filemtime($this->csvfile);
if ($filemtime != $this->filemtime) {
$this->lines = file($csvfile);
$this->filemtime = $filemtime;
}
}
 
function __construct($csvfile) {
$this->csvfile = $csvfile;
$this->reloadCSV();
}
}
 
 
class OIDSimplePingProvider implements IOIDSimplePingProvider {
protected $addr = '';
protected $connected = false;
protected $socket = null;
 
const SPP_MAX_CONNECTION_ATTEMPTS = 3; // TODO: Auslagern in OIDInfoAPI Klasse...?
 
const DEFAULT_PORT = 49500;
 
protected function spp_reader_init() {
$this->spp_reader_uninit();
 
$ary = explode(':', $this->addr);
$host = $ary[0];
$service_port = isset($ary[1]) ? $ary[1] : self::DEFAULT_PORT;
$address = @gethostbyname($host);
if ($address === false) {
echo "gethostbyname() failed.\n"; // TODO: exceptions? (Auch alle "echos" darunter)
return false;
}
$this->socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($this->socket === false) {
echo "socket_create() failed: " . socket_strerror(socket_last_error()) . "\n";
return false;
}
$result = @socket_connect($this->socket, $address, $service_port);
if ($result === false) {
echo "socket_connect() failed: " . socket_strerror(socket_last_error($this->socket)) . "\n";
return false;
}
 
$this->connected = true;
}
 
protected function spp_reader_avail($oid, $failcount=0) {
$in = "${oid}\n\0"; // PHP's socket_send() does not send a trailing \n . There needs to be something after the \n ... :(
 
if ($failcount >= self::SPP_MAX_CONNECTION_ATTEMPTS) {
echo "Query $oid: CONNECTION FAILED!\n";
return null;
}
 
if (!$this->connected) {
$this->spp_reader_init();
}
 
$s = @socket_send($this->socket, $in, strlen($in), 0);
if ($s != strlen($in)) {
// echo "Query $oid: Sending failed\n";
$this->spp_reader_init();
if (!$this->socket) return null;
return $this->spp_reader_avail($oid, $failcount+1);
}
 
$out = @socket_read($this->socket, 2048);
if (trim($out) == '1') {
return true;
} else if (trim($out) == '0') {
return false;
} else {
// echo "Query $oid: Receiving failed\n";
$this->spp_reader_init();
if (!$this->socket) return null;
return $this->spp_reader_avail($oid, $failcount+1);
}
}
 
protected function spp_reader_uninit() {
if (!$this->connected) return;
@socket_close($this->socket);
$this->connected = false;
}
 
public function queryOID($oid) {
if (trim($oid) === 'bye') return null;
return $this->spp_reader_avail($oid);
}
 
public function disconnect() {
return $this->spp_reader_uninit();
}
 
public function connect() {
return $this->spp_reader_init();
}
 
function __construct($addr='localhost:49500') {
$this->addr = $addr;
}
 
}
/trunk_oldversion/includes/uuid_utils.inc.php
0,0 → 1,499
<?php
 
/*
* UUID utils for PHP
* Copyright 2011-2020 Daniel Marschall, ViaThinkSoft
* Version 2020-02-28
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
# This library requires either the GMP extension (or BCMath if gmp_supplement.inc.php is present)
 
if (file_exists(__DIR__ . '/mac_utils.inc.phps')) include_once __DIR__ . '/mac_utils.inc.phps';
if (file_exists(__DIR__ . '/gmp_supplement.inc.php')) include_once __DIR__ . '/gmp_supplement.inc.php';
 
define('UUID_NAMEBASED_NS_DNS', '6ba7b810-9dad-11d1-80b4-00c04fd430c8');
define('UUID_NAMEBASED_NS_URL', '6ba7b811-9dad-11d1-80b4-00c04fd430c8');
define('UUID_NAMEBASED_NS_OID', '6ba7b812-9dad-11d1-80b4-00c04fd430c8');
define('UUID_NAMEBASED_NS_X500_DN', '6ba7b814-9dad-11d1-80b4-00c04fd430c8');
 
function uuid_valid($uuid) {
$uuid = str_replace(array('-', '{', '}'), '', $uuid);
$uuid = strtoupper($uuid);
 
if (strlen($uuid) != 32) return false;
 
$uuid = preg_replace('@[0-9A-F]@', '', $uuid);
 
return ($uuid == '');
}
 
# TODO: Don't echo
function uuid_info($uuid) {
if (!uuid_valid($uuid)) return false;
 
# $uuid = str_replace(array('-', '{', '}'), '', $uuid);
$uuid = strtoupper($uuid);
$uuid = preg_replace('@[^0-9A-F]@', '', $uuid);
 
$x = hexdec(substr($uuid, 16, 1));
if ($x >= 14 /* 1110 */) $variant = 3;
else if ($x >= 12 /* 1100 */) $variant = 2;
else if ($x >= 8 /* 1000 */) $variant = 1;
else if ($x >= 0 /* 0000 */) $variant = 0;
 
 
switch ($variant) {
case 0:
echo sprintf("%-24s %s\n", "Variant:", "[0xx] NCS (reserved for backward compatibility)");
 
/*
* Internal structure of variant #0 UUIDs
*
* The first 6 octets are the number of 4 usec units of time that have
* passed since 1/1/80 0000 GMT. The next 2 octets are reserved for
* future use. The next octet is an address family. The next 7 octets
* are a host ID in the form allowed by the specified address family.
*
* Note that while the family field (octet 8) was originally conceived
* of as being able to hold values in the range [0..255], only [0..13]
* were ever used. Thus, the 2 MSB of this field are always 0 and are
* used to distinguish old and current UUID forms.
*
* +--------------------------------------------------------------+
* | high 32 bits of time | 0-3 .time_high
* +-------------------------------+-------------------------------
* | low 16 bits of time | 4-5 .time_low
* +-------+-----------------------+
* | reserved | 6-7 .reserved
* +---------------+---------------+
* | family | 8 .family
* +---------------+----------...-----+
* | node ID | 9-16 .node
* +--------------------------...-----+
*
*/
 
// Example of an UUID: 333a2276-0000-0000-0d00-00809c000000
 
# TODO: See https://github.com/cjsv/uuid/blob/master/Doc
 
# Timestamp: Count of 4us intervals since 01 Jan 1980 00:00:00 GMT
# 1/0,000004 = 250000
# Seconds between 1970 and 1980 : 315532800
# 250000*315532800=78883200000000
$timestamp = substr($uuid, 0, 12);
$ts = gmp_init($timestamp, 16);
$ts = gmp_add($ts, gmp_init("78883200000000"));
$ms = gmp_mod($ts, gmp_init("250000"));
$ts = gmp_div($ts, gmp_init("250000"));
$ts = gmp_strval($ts);
$ms = gmp_strval($ms);
$ts = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts");
 
$reserved = substr($uuid, 12, 4);
echo sprintf("%-24s %s\n", "Reserved:", "0x$reserved");
 
# Family 13 (dds) looks like node is 00 | nnnnnn 000000.
# Family 2 is presumably (ip).
# Not sure if anything else was used.
$family_hex = substr($uuid, 16, 2);
$family_dec = hexdec($family_hex);
if ($family_dec == 2) {
$family_ = 'IP';
} else if ($family_dec == 13) {
$family_ = 'DDS (Data Link)';
} else {
$family_ = "Unknown ($family_dec)"; # There are probably no more families
}
echo sprintf("%-24s %s\n", "Family:", "[0x$family_hex = $family_dec] $family_");
 
$nodeid = substr($uuid, 18, 14);
echo sprintf("%-24s %s\n", "Node ID:", "0x$nodeid");
# TODO: interprete node id (the family specifies it)
 
break;
case 1:
echo sprintf("%-24s %s\n", "Variant:", "[10x] RFC 4122 (Leach-Mealling-Salz)");
 
$version = hexdec(substr($uuid, 12, 1));
switch ($version) {
case 1:
echo sprintf("%-24s %s\n", "Version:", "[1] Time-based with unique random host identifier");
 
# Timestamp: Count of 100ns intervals since 15 Oct 1582 00:00:00
# 1/0,0000001 = 10000000
$timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).substr($uuid, 0, 8);
$ts = gmp_init($timestamp, 16);
$ts = gmp_sub($ts, gmp_init("122192928000000000"));
$ms = gmp_mod($ts, gmp_init("10000000"));
$ts = gmp_div($ts, gmp_init("10000000"));
$ts = gmp_strval($ts);
$ms = gmp_strval($ms);
$ts = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts");
 
$x = hexdec(substr($uuid, 16, 4));
$dec = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
$hex = substr($uuid, 16, 4);
echo sprintf("%-24s %s\n", "Clock ID:", "[0x$hex] $dec");
 
$x = substr($uuid, 20, 12);
$nodeid = '';
for ($i=0; $i<6; $i++) {
$nodeid .= substr($x, $i*2, 2);
if ($i != 5) $nodeid .= ':';
}
echo sprintf("%-24s %s\n", "Node ID:", "$nodeid");
 
if (function_exists('decode_mac')) {
echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n";
echo decode_mac($nodeid);
}
 
break;
case 2:
echo sprintf("%-24s %s\n", "Version:", "[2] DCE Security version");
 
# The time_low field (which represents an integer in the range [0, 232-1]) is interpreted as a local-ID; that is, an identifier (within the domain specified by clock_seq_low) meaningful to the local host. In the particular case of a POSIX host, when combined with a POSIX UID or POSIX GID domain in the clock_seq_low field (above), the time_low field represents a POSIX UID or POSIX GID, respectively.
$x = substr($uuid, 0, 8);
echo sprintf("%-24s %s\n", "Local ID:", "0x$x");
 
# The clock_seq_low field (which represents an integer in the range [0, 28-1]) is interpreted as a local domain (as represented by sec_rgy_domain_t; see sec_rgy_domain_t ); that is, an identifier domain meaningful to the local host. (Note that the data type sec_rgy_domain_t can potentially hold values outside the range [0, 28-1]; however, the only values currently registered are in the range [0, 2], so this type mismatch is not significant.) In the particular case of a POSIX host, the value sec_rgy_domain_person is to be interpreted as the "POSIX UID domain", and the value sec_rgy_domain_group is to be interpreted as the "POSIX GID domain".
$x = substr($uuid, 18, 2);
if ($x == '00') $domain_info = 'POSIX: User-ID / Non-POSIX: site-defined';
else if ($x == '01') $domain_info = 'POSIX: Group-ID / Non-POSIX: site-defined';
else $domain_info = 'site-defined';
echo sprintf("%-24s %s\n", "Local Domain:", "0x$x ($domain_info)");
 
# Timestamp: Count of 100ns intervals since 15 Oct 1582 00:00:00
# 1/0,0000001 = 10000000
$timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'00000000';
$ts = gmp_init($timestamp, 16);
$ts = gmp_sub($ts, gmp_init("122192928000000000"));
$ms = gmp_mod($ts, gmp_init("10000000"));
$ts = gmp_div($ts, gmp_init("10000000"));
$ts = gmp_strval($ts);
$ms = gmp_strval($ms);
$ts_min = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
 
$timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'FFFFFFFF';
$ts = gmp_init($timestamp, 16);
$ts = gmp_sub($ts, gmp_init("122192928000000000"));
$ms = gmp_mod($ts, gmp_init("10000000"));
$ts = gmp_div($ts, gmp_init("10000000"));
$ts = gmp_strval($ts);
$ms = gmp_strval($ms);
$ts_max = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
 
$timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'xxxxxxxx';
echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts_min - $ts_max");
 
$x = hexdec(substr($uuid, 16, 2).'00');
$dec_min = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
$x = hexdec(substr($uuid, 16, 2).'FF');
$dec_max = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
$hex = substr($uuid, 16, 2).'xx';
echo sprintf("%-24s %s\n", "Clock ID:", "[0x$hex] $dec_min - $dec_max");
 
$x = substr($uuid, 20, 12);
$nodeid = '';
for ($i=0; $i<6; $i++) {
$nodeid .= substr($x, $i*2, 2);
if ($i != 5) $nodeid .= ':';
}
echo sprintf("%-24s %s\n", "Node ID:", "$nodeid");
 
if (function_exists('decode_mac')) {
echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n";
echo decode_mac($nodeid);
}
 
break;
case 3:
echo sprintf("%-24s %s\n", "Version:", "[3] Name-based (MD5 hash)");
 
$hash = str_replace('-', '', strtolower($uuid));
$hash[12] = '?'; // was overwritten by version
$hash[16] = '?'; // was partially overwritten by variant
 
echo sprintf("%-24s %s\n", "MD5(Namespace+Subject):", "$hash");
 
break;
case 4:
echo sprintf("%-24s %s\n", "Version:", "[4] Random");
 
$rand = '';
for ($i=0; $i<16; $i++) {
$bin = base_convert(substr($uuid, $i*2, 2), 16, 2);
$bin = str_pad($bin, 8, "0", STR_PAD_LEFT);
 
if ($i == 6) {
$bin[0] = 'x';
$bin[1] = 'x';
} else if ($i == 8) {
$bin[0] = 'x';
$bin[1] = 'x';
$bin[2] = 'x';
$bin[3] = 'x';
}
 
$rand .= "$bin ";
}
 
echo sprintf("%-24s %s\n", "Random bits:", trim($rand));
 
break;
case 5:
echo sprintf("%-24s %s\n", "Version:", "[5] Name-based (SHA-1 hash)");
 
$hash = str_replace('-', '', strtolower($uuid));
$hash[12] = '?'; // was overwritten by version
$hash[16] = '?'; // was partially overwritten by variant
$hash .= '????????'; // was cut off
 
echo sprintf("%-24s %s\n", "SHA1(Namespace+Subject):", "$hash");
 
 
break;
default:
echo sprintf("%-24s %s\n", "Version:", "[$version] Unknown");
break;
}
 
break;
case 2:
echo sprintf("%-24s %s\n", "Variant:", "[110] Reserved for Microsoft Corporation");
break;
case 3:
echo sprintf("%-24s %s\n", "Variant:", "[111] Reserved for future use");
break;
}
}
 
function uuid_canonize($uuid) {
if (!uuid_valid($uuid)) return false;
return oid_to_uuid(uuid_to_oid($uuid));
}
 
function oid_to_uuid($oid) {
if (!is_uuid_oid($oid)) return false;
 
if ($oid[0] == '.') {
$oid = substr($oid, 1);
}
$ary = explode('.', $oid);
$val = $ary[2];
 
$x = gmp_init($val, 10);
$y = gmp_strval($x, 16);
$y = str_pad($y, 32, "0", STR_PAD_LEFT);
return substr($y, 0, 8).'-'.
substr($y, 8, 4).'-'.
substr($y, 12, 4).'-'.
substr($y, 16, 4).'-'.
substr($y, 20, 12);
}
 
function is_uuid_oid($oid, $only_allow_root=false) {
if ($oid[0] == '.') $oid = substr($oid, 1); // remove leading dot
 
$ary = explode('.', $oid);
 
if ($only_allow_root) {
if (count($ary) != 3) return false;
}
 
if ($ary[0] != '2') return false;
if ($ary[1] != '25') return false;
for ($i=2; $i<count($ary); $i++) {
$v = $ary[$i];
if (!is_numeric($v)) return false;
if ($i == 2) {
// Must be in the range of 128 bit UUID
$test = gmp_init($v, 10);
if (strlen(gmp_strval($test, 16)) > 32) return false;
}
if ($v < 0) return false;
}
 
return true;
}
 
function uuid_to_oid($uuid) {
if (!uuid_valid($uuid)) return false;
 
$uuid = str_replace(array('-', '{', '}'), '', $uuid);
$x = gmp_init($uuid, 16);
return '2.25.'.gmp_strval($x, 10); # TODO: parameter with or without leading dot
}
 
function gen_uuid($prefer_timebased = true) {
if ($prefer_timebased) $uuid = gen_uuid_timebased();
if ($uuid === false) $uuid = gen_uuid_random();
return $uuid;
}
 
// Version 1 (Time based) UUID
function gen_uuid_timebased() {
# On Debian: aptitude install php-uuid
# extension_loaded('uuid')
if (function_exists('uuid_create')) {
# OSSP uuid extension like seen in php5-uuid at Debian 8
/*
$x = uuid_create($context);
uuid_make($context, UUID_MAKE_V1);
uuid_export($context, UUID_FMT_STR, $uuid);
return trim($uuid);
*/
 
# PECL uuid extension like seen in php-uuid at Debian 9
return trim(uuid_create(UUID_TYPE_TIME));
}
 
# On Debian: aptitude install uuid-runtime
$out = array();
exec('uuidgen -t', $out, $ec);
if ($ec == 0) return $out[0];
 
# TODO: Implement the time based generation routine ourselves!
# At the moment we cannot determine the time based UUID
return false;
}
 
// Version 2 (DCE Security) UUID
function gen_uuid_dce($domain, $id) {
# Start with a version 1 UUID
$uuid = gen_uuid_timebased();
 
# Add ID
$uuid = str_pad(dechex($id), 8, '0', STR_PAD_LEFT) . substr($uuid, 8);
 
# Add domain
$uuid = substr($uuid,0,21) . str_pad(dechex($domain), 2, '0', STR_PAD_LEFT) . substr($uuid, 23);
 
# Change version to 2
$uuid[14] = '2';
 
return $uuid;
}
 
// Version 3 (MD5 name based) UUID
function gen_uuid_md5_namebased($namespace_uuid, $name) {
if (!uuid_valid($namespace_uuid)) return false;
$namespace_uuid = uuid_canonize($namespace_uuid);
$namespace_uuid = str_replace('-', '', $namespace_uuid);
$namespace_uuid = hex2bin($namespace_uuid);
 
$hash = md5($namespace_uuid.$name);
$hash[12] = '3'; // Set version: 3 = MD5
$hash[16] = dechex(hexdec($hash[16]) & 0x3 | 0x8); // Set variant to "10xx" (RFC4122)
 
return substr($hash, 0, 8).'-'.
substr($hash, 8, 4).'-'.
substr($hash, 12, 4).'-'.
substr($hash, 16, 4).'-'.
substr($hash, 20, 12);
}
 
// Version 4 (Random) UUID
function gen_uuid_random() {
# On Debian: aptitude install php-uuid
# extension_loaded('uuid')
if (function_exists('uuid_create')) {
# OSSP uuid extension like seen in php5-uuid at Debian 8
/*
$x = uuid_create($context);
uuid_make($context, UUID_MAKE_V4);
uuid_export($context, UUID_FMT_STR, $uuid);
return trim($uuid);
*/
 
# PECL uuid extension like seen in php-uuid at Debian 9
return trim(uuid_create(UUID_TYPE_RANDOM));
}
 
# On Debian: aptitude install uuid-runtime
$out = array();
exec('uuidgen -r', $out, $ec);
if ($ec == 0) return $out[0];
 
# On Debian Jessie: UUID V4 (Random)
if (file_exists('/proc/sys/kernel/random/uuid')) {
return file_get_contents('/proc/sys/kernel/random/uuid');
}
 
# Make the UUID by ourselves
# Source: http://rogerstringer.com/2013/11/15/generate-uuids-php
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0fff ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
);
}
 
// Version 5 (SHA1 name based) UUID
function gen_uuid_sha1_namebased($namespace_uuid, $name) {
$namespace_uuid = str_replace('-', '', $namespace_uuid);
$namespace_uuid = hex2bin($namespace_uuid);
 
$hash = sha1($namespace_uuid.$name);
$hash[12] = '5'; // Set version: 5 = SHA1
$hash[16] = dechex(hexdec($hash[16]) & 0x3 | 0x8); // Set variant to "10xx" (RFC4122)
 
return substr($hash, 0, 8).'-'.
substr($hash, 8, 4).'-'.
substr($hash, 12, 4).'-'.
substr($hash, 16, 4).'-'.
substr($hash, 20, 12);
}
 
function uuid_numeric_value($uuid) {
$oid = uuid_to_oid($uuid);
if (!$oid) return false;
return substr($oid, strlen('2.25.'));
}
 
function uuid_c_syntax($uuid) {
$uuid = str_replace('{', '', $uuid);
return '{ 0x' . substr($uuid, 0, 8) .
', 0x' . substr($uuid, 9, 4) .
', 0x' . substr($uuid, 14, 4) .
', { 0x' . substr($uuid, 19, 2).
', 0x' . substr($uuid, 21, 2) .
', 0x' . substr($uuid, 24, 2) .
', 0x' . substr($uuid, 26, 2) .
', 0x' . substr($uuid, 28, 2) .
', 0x' . substr($uuid, 30, 2) .
', 0x' . substr($uuid, 32, 2) .
', 0x' . substr($uuid, 34, 2) . ' } }';
}
 
# ---
 
// http://php.net/manual/de/function.hex2bin.php#113057
if ( !function_exists( 'hex2bin' ) ) {
function hex2bin( $str ) {
$sbin = "";
$len = strlen( $str );
for ( $i = 0; $i < $len; $i += 2 ) {
$sbin .= pack( "H*", substr( $str, $i, 2 ) );
}
 
return $sbin;
}
}
/trunk_oldversion/includes/xml_utils.inc.php
0,0 → 1,190
<?php
 
/*
* XML Encoding Utilities
* Copyright 2011-2019 Daniel Marschall, ViaThinkSoft
* Version 1.7
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
// http://www.viathinksoft.de/?page=codelib&showid=89
 
// Unicode-proof htmlentities.
// Returns 'normal' chars as chars and weirdos as numeric html entites.
// Source: http://www.php.net/manual/en/function.htmlentities.php#107985 ; modified
// Modified by Daniel Marschall, ViaThinkSoft
function htmlentities_numeric($str, $allow_html=false, $encode_linebreaks=false) {
// Convert $str to UTF-8 if it is not already
if (mb_detect_encoding($str, "auto", true) != 'UTF-8') {
# $str = mb_convert_encoding($str, 'UTF-8', 'Windows-1252');
# $str = mb_convert_encoding($str, 'UTF-8', 'auto');
$str = mb_convert_encoding($str, 'UTF-8');
}
 
// get rid of existing entities else double-escape
// DM 24.08.2016 Auskommentiert wegen oid+ xml export
// $str = html_entity_decode(stripslashes($str),ENT_QUOTES,'UTF-8');
 
$ar = preg_split('/(?<!^)(?!$)/u', $str); // return array of every multi-byte character
$str2 = '';
foreach ($ar as $c) {
$o = ord($c);
if (
(strlen($c) > 1) || /* multi-byte [unicode] */
($o < 32 || $o > 126) || /* <- control / latin weirdos -> */
($o > 33 && $o < 40) || /* quotes + ampersand */
($o > 59 && $o < 63) /* html */
) {
// convert to numeric entity
$c = mb_encode_numericentity($c, array(0x0, 0xffff, 0, 0xffff), 'UTF-8');
 
if ($allow_html) {
if ($c == '&#60;') $c = '<';
if ($c == '&#62;') $c = '>';
if ($c == '&#61;') $c = '=';
if ($c == '&#34;') $c = '"';
if ($c == '&#39;') $c = '\'';
if ($c == '&#38;') $c = '&'; // DM 24.08.2016 Re-Aktiviert wegen oid+ xml export
}
 
if (!$encode_linebreaks) {
if ($allow_html) {
if ($c == "&#10;") $c = "<br />";
if ($c == "&#13;") $c = "<br />";
} else {
if ($c == "&#10;") $c = "\n";
if ($c == "&#13;") $c = "\r";
}
}
}
$str2 .= $c;
}
return $str2;
}
 
function ordUTF8($c, $index = 0, &$bytes = null) {
// http://de.php.net/manual/en/function.ord.php#78032
 
$len = strlen($c);
$bytes = 0;
 
if ($index >= $len) {
return false;
}
 
$h = ord($c{$index});
 
if ($h <= 0x7F) {
$bytes = 1;
return $h;
} else if ($h < 0xC2) {
return false;
} else if ($h <= 0xDF && $index < $len - 1) {
$bytes = 2;
return ($h & 0x1F) << 6 | (ord($c{$index + 1}) & 0x3F);
} else if ($h <= 0xEF && $index < $len - 2) {
$bytes = 3;
return ($h & 0x0F) << 12 | (ord($c{$index + 1}) & 0x3F) << 6
| (ord($c{$index + 2}) & 0x3F);
} else if ($h <= 0xF4 && $index < $len - 3) {
$bytes = 4;
return ($h & 0x0F) << 18 | (ord($c{$index + 1}) & 0x3F) << 12
| (ord($c{$index + 2}) & 0x3F) << 6
| (ord($c{$index + 3}) & 0x3F);
} else {
return false;
}
}
 
function utf16_to_utf8($str) {
// http://betamode.de/2008/09/08/php-utf-16-zu-utf-8-konvertieren/
// http://www.moddular.org/log/utf16-to-utf8
 
$c0 = ord($str[0]);
$c1 = ord($str[1]);
if ($c0 == 0xFE && $c1 == 0xFF) {
$be = true;
} else if ($c0 == 0xFF && $c1 == 0xFE) {
$be = false;
} else {
return $str;
}
$str = substr($str, 2);
$len = strlen($str);
$dec = '';
for ($i = 0; $i < $len; $i += 2) {
$c = ($be) ? ord($str[$i]) << 8 | ord($str[$i + 1]) :
ord($str[$i + 1]) << 8 | ord($str[$i]);
if ($c >= 0x0001 && $c <= 0x007F) {
$dec .= chr($c);
} else if ($c > 0x07FF) {
$dec .= chr(0xE0 | (($c >> 12) & 0x0F));
$dec .= chr(0x80 | (($c >> 6) & 0x3F));
$dec .= chr(0x80 | (($c >> 0) & 0x3F));
} else {
$dec .= chr(0xC0 | (($c >> 6) & 0x1F));
$dec .= chr(0x80 | (($c >> 0) & 0x3F));
}
}
return $dec;
}
 
function html_named_to_numeric_entities($str) {
if (!function_exists('decodeNamedEntities')) {
function decodeNamedEntities($string) {
// https://stackoverflow.com/questions/20406599/how-to-encode-for-entity-igrave-not-defined-error-in-xml-feed
static $entities = NULL;
if (NULL === $entities) {
$entities = array_flip(
array_diff(
get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML401, 'UTF-8'),
get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_XML1, 'UTF-8')
)
);
}
return str_replace(array_keys($entities), $entities, $string);
}
}
 
if (!function_exists('mb_convert_encoding')) {
// https://riptutorial.com/php/example/15633/converting-unicode-characters-to-their-numeric-value-and-or-html-entities-using-php
function mb_convert_encoding($str, $to_encoding, $from_encoding = NULL) {
return iconv(($from_encoding === NULL) ? mb_internal_encoding() : $from_encoding, $to_encoding, $str);
}
}
 
if (!function_exists('mb_ord')) {
// https://riptutorial.com/php/example/15633/converting-unicode-characters-to-their-numeric-value-and-or-html-entities-using-php
function mb_ord($char, $encoding = 'UTF-8') {
if ($encoding === 'UCS-4BE') {
list(, $ord) = (strlen($char) === 4) ? @unpack('N', $char) : @unpack('n', $char);
return $ord;
} else {
return mb_ord(mb_convert_encoding($char, 'UCS-4BE', $encoding), 'UCS-4BE');
}
}
}
 
if (!function_exists('mb_htmlentities')) {
// https://riptutorial.com/php/example/15633/converting-unicode-characters-to-their-numeric-value-and-or-html-entities-using-php
function mb_htmlentities($string, $hex = true, $encoding = 'UTF-8') {
return preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function ($match) use ($hex) {
return sprintf($hex ? '&#x%X;' : '&#%d;', mb_ord($match[0]));
}, $string);
}
}
 
if (!mb_detect_encoding($str, 'UTF-8', true)) $str = utf8_encode($str);
return mb_htmlentities(decodeNamedEntities($str));
}