Subversion Repositories oidplus

Rev

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
*/