Subversion Repositories oidplus

Rev

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

  1. <?php
  2.  
  3. /**
  4.  * WEID<=>OID Converter
  5.  * (c) Webfan.de, ViaThinkSoft
  6.  **/
  7.  
  8. class WeidOidConverter {
  9.  
  10.         protected static function weLuhnGetCheckDigit($str) {
  11.                 $wrkstr = str_replace('-', '', $str); // remove separators
  12.                 for ($i=0; $i<36; $i++) {
  13.                         $wrkstr = str_ireplace(chr(ord('a')+$i), (string)($i+10), $wrkstr);
  14.                 }
  15.                 $nbdigits = strlen($wrkstr);
  16.                 $parity = $nbdigits & 1;
  17.                 $sum = 0;
  18.                 for ($n=$nbdigits-1; $n>=0; $n--) {
  19.                         $digit = $wrkstr[$n];
  20.                         if (($n & 1) != $parity) $digit *= 2;
  21.                         if ($digit > 9) $digit -= 9;
  22.                         $sum += $digit;
  23.                 }
  24.                 return ($sum%10) == 0 ? 0 : 10-($sum%10);
  25.         }
  26.  
  27.         public static function weid2oid(&$weid, $namespace='weid:', $base='1-3-6-1-4-1-SZ5-8') {
  28.                 if (stripos($weid, $namespace) !== 0) return false; // wrong namespace
  29.                 $weid = explode(':', $weid, 2)[1]; // remove namespace
  30.  
  31.                 $elements = array_merge(explode('-', $base), explode('-', $weid));
  32.                 $actual_checksum = array_pop($elements);
  33.                 $expected_checksum = self::weLuhnGetCheckDigit(implode('-',$elements));
  34.                 if ($actual_checksum != '?') {
  35.                         if ($actual_checksum != $expected_checksum) return false; // wrong checksum
  36.                 } else {
  37.                         // If checksum is '?', it will be replaced by the actual checksum,
  38.                         // e.g. weid:EXAMPLE-? becomes weid:EXAMPLE-3
  39.                         $weid = str_replace('?', $expected_checksum, $weid);
  40.                 }
  41.                 foreach ($elements as &$arc) {
  42.                         //$arc = strtoupper(base_convert($arc, 36, 10));
  43.                         $arc = strtoupper(self::base_convert_bigint($arc, 36, 10));
  44.                 }
  45.                 $oidstr = implode('.', $elements);
  46.  
  47.                 return $oidstr;
  48.         }
  49.  
  50.         public static function oid2weid($oid, $namespace='weid:', $base='1-3-6-1-4-1-SZ5-8') {
  51.                 $elements = explode('.', $oid);
  52.                 foreach ($elements as &$arc) {
  53.                         //$arc = strtoupper(base_convert($arc, 10, 36));
  54.                         $arc = strtoupper(self::base_convert_bigint($arc, 10, 36));
  55.                 }
  56.                 $weidstr = implode('-', $elements);
  57.  
  58.                 if (stripos($weidstr.'-', $base.'-') !== 0) return false; // wrong base
  59.  
  60.                 return $namespace . substr($weidstr.'-'.self::weLuhnGetCheckDigit($weidstr), strlen($base.'-'));
  61.         }
  62.  
  63.         protected static function base_convert_bigint($numstring, $frombase, $tobase) {
  64.                 $frombase_str = '';
  65.                 for ($i=0; $i<$frombase; $i++) {
  66.                         $frombase_str .= strtoupper(base_convert((string)$i, 10, 36));
  67.                 }
  68.  
  69.                 $tobase_str = '';
  70.                 for ($i=0; $i<$tobase; $i++) {
  71.                         $tobase_str .= strtoupper(base_convert((string)$i, 10, 36));
  72.                 }
  73.  
  74.                 $length = strlen($numstring);
  75.                 $result = '';
  76.                 $number = array();
  77.                 for ($i = 0; $i < $length; $i++) {
  78.                         $number[$i] = stripos($frombase_str, $numstring[$i]);
  79.                 }
  80.                 do { // Loop until whole number is converted
  81.                         $divide = 0;
  82.                         $newlen = 0;
  83.                         for ($i = 0; $i < $length; $i++) { // Perform division manually (which is why this works with big numbers)
  84.                                 $divide = $divide * $frombase + $number[$i];
  85.                                 if ($divide >= $tobase) {
  86.                                         $number[$newlen++] = (int)($divide / $tobase);
  87.                                         $divide = $divide % $tobase;
  88.                                 } else if ($newlen > 0) {
  89.                                         $number[$newlen++] = 0;
  90.                                 }
  91.                         }
  92.                         $length = $newlen;
  93.                         $result = $tobase_str[$divide] . $result; // Divide is basically $numstring % $tobase (i.e. the new character)
  94.                 }
  95.                 while ($newlen != 0);
  96.  
  97.                 return $result;
  98.         }
  99. }
  100.  
  101. # --- TESTCASE ---
  102.  
  103. /*
  104. $lines = file('E:\__fastphp\weid_test.txt');
  105. $cnt = 0;
  106. foreach ($lines as $line) {
  107.         $line = trim($line);
  108.         if (empty($line)) continue;
  109.         list($testcase_oid, $testcase_weid) = explode("\t", $line);
  110.  
  111.         $weid = WeidOidConverter::oid2weid($testcase_oid);
  112.         if ($weid != $testcase_weid) echo "OID2WEID ERROR: '$testcase_oid' = '$weid' (should be: '$testcase_weid')\n";
  113.  
  114.         $oid = WeidOidConverter::weid2oid($testcase_weid);
  115.         if ($oid != $testcase_oid) echo "WEID2OID ERROR: '$testcase_weid' = '$oid' (should be: '$testcase_oid')\n";
  116.  
  117.         $cnt++;
  118. }
  119.  
  120. echo "Done, checked $cnt testcases!\n";
  121.  
  122. $weid = 'weid:EXAMPLE-?';
  123. echo "Autocomplete test: '$weid' => '".WeidOidConverter::weid2oid($weid)."' (checksum corrected to: '$weid')\n";
  124. */
  125.