Rev 683 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
635 | daniel-mar | 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 | */ |