Subversion Repositories oidplus

Rev

Rev 686 | Rev 771 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 686 Rev 750
1
<?php
1
<?php
2
 
2
 
3
/**
3
/**
4
 * WEID<=>OID Converter
4
 * WEID<=>OID Converter
5
 * (c) Webfan.de, ViaThinkSoft
5
 * (c) Webfan.de, ViaThinkSoft
6
 * Revision 2021-12-08
6
 * Revision 2021-12-08
7
 **/
7
 **/
8
 
8
 
9
// What is a WEID?
9
// What is a WEID?
10
//     A WEID (WEhowski IDentifier) is an alternative representation of an
10
//     A WEID (WEhowski IDentifier) is an alternative representation of an
11
//     OID (Object IDentifier) defined by Till Wehowski.
11
//     OID (Object IDentifier) defined by Till Wehowski.
12
//     In OIDs, arcs are in decimal base 10. In WEIDs, the arcs are in base 36.
12
//     In OIDs, arcs are in decimal base 10. In WEIDs, the arcs are in base 36.
13
//     Also, each WEID has a check digit at the end (called WeLohn Check Digit).
13
//     Also, each WEID has a check digit at the end (called WeLohn Check Digit).
14
//
14
//
15
// Changes in the December 2021 definition by Daniel Marschall:
15
// Changes in the December 2021 definition by Daniel Marschall:
16
//     - There are several classes of WEIDs which have different OID bases:
16
//     - There are several classes of WEIDs which have different OID bases:
17
//           "Class C" WEID:  weid:EXAMPLE-3      (base .1.3.6.1.4.1.37553.8.)
17
//           "Class C" WEID:  weid:EXAMPLE-3      (base .1.3.6.1.4.1.37553.8.)
18
//                            oid:1.3.6.1.4.1.37553.8.32488192274
18
//                            oid:1.3.6.1.4.1.37553.8.32488192274
19
//           "Class B" WEID:  weid:pen:SX0-7PR-6  (base .1.3.6.1.4.1.)
19
//           "Class B" WEID:  weid:pen:SX0-7PR-6  (base .1.3.6.1.4.1.)
20
//                            oid:1.3.6.1.4.1.37476.9999
20
//                            oid:1.3.6.1.4.1.37476.9999
21
//           "Class A" WEID:  weid:root:2-RR-2    (base .)
21
//           "Class A" WEID:  weid:root:2-RR-2    (base .)
22
//                            oid:2.999
22
//                            oid:2.999
23
//     - The namespace (weid:, weid:pen:, weid:root:) is now case insensitive.
23
//     - The namespace (weid:, weid:pen:, weid:root:) is now case insensitive.
24
//     - Padding with '0' characters is valid (e.g. weid:000EXAMPLE-3)
24
//     - Padding with '0' characters is valid (e.g. weid:000EXAMPLE-3)
25
//       The paddings do not count into the WeLuhn check-digit.
25
//       The paddings do not count into the WeLuhn check-digit.
26
 
26
 
27
class WeidOidConverter {
27
class WeidOidConverter {
28
 
28
 
29
        protected static function weLuhnGetCheckDigit($str) {
29
        protected static function weLuhnGetCheckDigit($str) {
30
                // Padding zeros don't count to the check digit (December 2021)
30
                // Padding zeros don't count to the check digit (December 2021)
31
                $ary = explode('-', $str);
31
                $ary = explode('-', $str);
32
                foreach ($ary as &$a) {
32
                foreach ($ary as &$a) {
33
                        $a = ltrim($a, '0');
33
                        $a = ltrim($a, '0');
34
                        if ($a === '') $a = '0';
34
                        if ($a === '') $a = '0';
35
                }
35
                }
36
                $str = implode('-', $ary);
36
                $str = implode('-', $ary);
37
 
37
 
38
                // remove separators of the WEID string
38
                // remove separators of the WEID string
39
                $wrkstr = str_replace('-', '', $str);
39
                $wrkstr = str_replace('-', '', $str);
40
 
40
 
41
                // Replace 'a' with '10', 'b' with '11', etc.
41
                // Replace 'a' with '10', 'b' with '11', etc.
42
                for ($i=0; $i<26; $i++) {
42
                for ($i=0; $i<26; $i++) {
43
                        $wrkstr = str_ireplace(chr(ord('a')+$i), (string)($i+10), $wrkstr);
43
                        $wrkstr = str_ireplace(chr(ord('a')+$i), (string)($i+10), $wrkstr);
44
                }
44
                }
45
 
45
 
46
                // At the end, $wrkstr should only contain digits! Verify it!
46
                // At the end, $wrkstr should only contain digits! Verify it!
47
                for ($i=0; $i<strlen($wrkstr); $i++) {
47
                for ($i=0; $i<strlen($wrkstr); $i++) {
48
                        if (($wrkstr[$i]<'0') || ($wrkstr[$i]>'9')) return false;
48
                        if (($wrkstr[$i]<'0') || ($wrkstr[$i]>'9')) return false;
49
                }
49
                }
50
 
50
 
51
                // Now do the standard Luhn algorithm
51
                // Now do the standard Luhn algorithm
52
                $nbdigits = strlen($wrkstr);
52
                $nbdigits = strlen($wrkstr);
53
                $parity = $nbdigits & 1; // mod 2
53
                $parity = $nbdigits & 1; // mod 2
54
                $sum = 0;
54
                $sum = 0;
55
                for ($n=$nbdigits-1; $n>=0; $n--) {
55
                for ($n=$nbdigits-1; $n>=0; $n--) {
56
                        $digit = (int)$wrkstr[$n];
56
                        $digit = (int)$wrkstr[$n];
57
                        if (($n & 1) != $parity) $digit *= 2;
57
                        if (($n & 1) != $parity) $digit *= 2;
58
                        if ($digit > 9) $digit -= 9;
58
                        if ($digit > 9) $digit -= 9;
59
                        $sum += $digit;
59
                        $sum += $digit;
60
                }
60
                }
61
                return ($sum%10) == 0 ? 0 : 10-($sum%10);
61
                return ($sum%10) == 0 ? 0 : 10-($sum%10);
62
        }
62
        }
63
 
63
 
64
        // Translates a weid to an oid
64
        // Translates a weid to an oid
65
        // "weid:EXAMPLE-3" becomes "1.3.6.1.4.1.37553.8.32488192274"
65
        // "weid:EXAMPLE-3" becomes "1.3.6.1.4.1.37553.8.32488192274"
66
        // If it failed (e.g. wrong namespace, wrong checksum, etc.) then false is returned.
66
        // If it failed (e.g. wrong namespace, wrong checksum, etc.) then false is returned.
67
        // If the weid ends with '?', then it will be replaced with the checksum,
67
        // If the weid ends with '?', then it will be replaced with the checksum,
68
        // e.g. weid:EXAMPLE-? becomes weid:EXAMPLE-3
68
        // e.g. weid:EXAMPLE-? becomes weid:EXAMPLE-3
69
        public static function weid2oid(&$weid) {
69
        public static function weid2oid(&$weid) {
70
 
70
 
71
                $p = strrpos($weid,':');
71
                $p = strrpos($weid,':');
72
                $namespace = substr($weid, 0, $p+1);
72
                $namespace = substr($weid, 0, $p+1);
73
                $rest = substr($weid, $p+1);
73
                $rest = substr($weid, $p+1);
74
 
74
 
75
                $namespace = strtolower($namespace); // namespace is case insensitive
75
                $namespace = strtolower($namespace); // namespace is case insensitive
76
                if ($namespace == 'weid:') {
76
                if ($namespace == 'weid:') {
77
                        // Class C
77
                        // Class C
78
                        $base = '1-3-6-1-4-1-SZ5-8';
78
                        $base = '1-3-6-1-4-1-SZ5-8';
79
                } else if ($namespace == 'weid:pen:') {
79
                } else if ($namespace == 'weid:pen:') {
80
                        // Class B
80
                        // Class B
81
                        $base = '1-3-6-1-4-1';
81
                        $base = '1-3-6-1-4-1';
82
                } else if ($namespace == 'weid:root:') {
82
                } else if ($namespace == 'weid:root:') {
83
                        // Class A
83
                        // Class A
84
                        $base = '';
84
                        $base = '';
85
                } else {
85
                } else {
86
                        // Wrong namespace
86
                        // Wrong namespace
87
                        return false;
87
                        return false;
88
                }
88
                }
89
 
89
 
90
                $weid = $rest;
90
                $weid = $rest;
91
 
91
 
92
                $elements = array_merge(($base != '') ? explode('-', $base) : array(), explode('-', $weid));
92
                $elements = array_merge(($base != '') ? explode('-', $base) : array(), explode('-', $weid));
93
                $actual_checksum = array_pop($elements);
93
                $actual_checksum = array_pop($elements);
94
                $expected_checksum = self::weLuhnGetCheckDigit(implode('-',$elements));
94
                $expected_checksum = self::weLuhnGetCheckDigit(implode('-',$elements));
95
                if ($actual_checksum != '?') {
95
                if ($actual_checksum != '?') {
96
                        if ($actual_checksum != $expected_checksum) return false; // wrong checksum
96
                        if ($actual_checksum != $expected_checksum) return false; // wrong checksum
97
                } else {
97
                } else {
98
                        // If checksum is '?', it will be replaced by the actual checksum,
98
                        // If checksum is '?', it will be replaced by the actual checksum,
99
                        // e.g. weid:EXAMPLE-? becomes weid:EXAMPLE-3
99
                        // e.g. weid:EXAMPLE-? becomes weid:EXAMPLE-3
100
                        $weid = str_replace('?', $expected_checksum, $weid);
100
                        $weid = str_replace('?', $expected_checksum, $weid);
101
                }
101
                }
102
                foreach ($elements as &$arc) {
102
                foreach ($elements as &$arc) {
103
                        //$arc = strtoupper(base_convert($arc, 36, 10));
103
                        //$arc = strtoupper(base_convert($arc, 36, 10));
104
                        $arc = strtoupper(self::base_convert_bigint($arc, 36, 10));
104
                        $arc = strtoupper(self::base_convert_bigint($arc, 36, 10));
105
                }
105
                }
106
                $oidstr = implode('.', $elements);
106
                $oidstr = implode('.', $elements);
107
 
107
 
108
                $weid = $namespace . $weid; // add namespace again
108
                $weid = strtolower($namespace) . strtoupper($weid); // add namespace again
109
 
109
 
110
                return $oidstr;
110
                return $oidstr;
111
        }
111
        }
112
 
112
 
113
        // Converts an OID to WEID
113
        // Converts an OID to WEID
114
        // "1.3.6.1.4.1.37553.8.32488192274" becomes "weid:EXAMPLE-3"
114
        // "1.3.6.1.4.1.37553.8.32488192274" becomes "weid:EXAMPLE-3"
115
        public static function oid2weid($oid) {
115
        public static function oid2weid($oid) {
116
                if (substr($oid,0,1) === '.') $oid = substr($oid,1); // remove leading dot
116
                if (substr($oid,0,1) === '.') $oid = substr($oid,1); // remove leading dot
117
 
117
 
118
                if ($oid !== '') {
118
                if ($oid !== '') {
119
                        $elements = explode('.', $oid);
119
                        $elements = explode('.', $oid);
120
                        foreach ($elements as &$arc) {
120
                        foreach ($elements as &$arc) {
121
                                //$arc = strtoupper(base_convert($arc, 10, 36));
121
                                //$arc = strtoupper(base_convert($arc, 10, 36));
122
                                $arc = strtoupper(self::base_convert_bigint($arc, 10, 36));
122
                                $arc = strtoupper(self::base_convert_bigint($arc, 10, 36));
123
                        }
123
                        }
124
                        $weidstr = implode('-', $elements);
124
                        $weidstr = implode('-', $elements);
125
                } else {
125
                } else {
126
                        $weidstr = '';
126
                        $weidstr = '';
127
                }
127
                }
128
 
128
 
129
                $is_class_c = (strpos($weidstr, '1-3-6-1-4-1-SZ5-8-') === 0) ||
129
                $is_class_c = (strpos($weidstr, '1-3-6-1-4-1-SZ5-8-') === 0) ||
130
                              ($weidstr === '1-3-6-1-4-1-SZ5-8');
130
                              ($weidstr === '1-3-6-1-4-1-SZ5-8');
131
                $is_class_b = ((strpos($weidstr, '1-3-6-1-4-1-') === 0) ||
131
                $is_class_b = ((strpos($weidstr, '1-3-6-1-4-1-') === 0) ||
132
                              ($weidstr === '1-3-6-1-4-1'))
132
                              ($weidstr === '1-3-6-1-4-1'))
133
                              && !$is_class_c;
133
                              && !$is_class_c;
134
                $is_class_a = !$is_class_b && !$is_class_c;
134
                $is_class_a = !$is_class_b && !$is_class_c;
135
 
135
 
136
                $checksum = self::weLuhnGetCheckDigit($weidstr);
136
                $checksum = self::weLuhnGetCheckDigit($weidstr);
137
 
137
 
138
                if ($is_class_c) {
138
                if ($is_class_c) {
139
                        $weidstr = substr($weidstr, strlen('1-3-6-1-4-1-SZ5-8-'));
139
                        $weidstr = substr($weidstr, strlen('1-3-6-1-4-1-SZ5-8-'));
140
                        $namespace = 'weid:';
140
                        $namespace = 'weid:';
141
                } else if ($is_class_b) {
141
                } else if ($is_class_b) {
142
                        $weidstr = substr($weidstr, strlen('1-3-6-1-4-1-'));
142
                        $weidstr = substr($weidstr, strlen('1-3-6-1-4-1-'));
143
                        $namespace = 'weid:pen:';
143
                        $namespace = 'weid:pen:';
144
                } else if ($is_class_a) {
144
                } else if ($is_class_a) {
145
                        // $weidstr stays
145
                        // $weidstr stays
146
                        $namespace = 'weid:root:';
146
                        $namespace = 'weid:root:';
147
                } else {
147
                } else {
148
                        // should not happen
148
                        // should not happen
149
                        return false;
149
                        return false;
150
                }
150
                }
151
 
151
 
152
                return $namespace . ($weidstr == '' ? $checksum : $weidstr . '-' . $checksum);
152
                return $namespace . ($weidstr == '' ? $checksum : $weidstr . '-' . $checksum);
153
        }
153
        }
154
 
154
 
155
        protected static function base_convert_bigint($numstring, $frombase, $tobase) {
155
        protected static function base_convert_bigint($numstring, $frombase, $tobase) {
156
                $frombase_str = '';
156
                $frombase_str = '';
157
                for ($i=0; $i<$frombase; $i++) {
157
                for ($i=0; $i<$frombase; $i++) {
158
                        $frombase_str .= strtoupper(base_convert((string)$i, 10, 36));
158
                        $frombase_str .= strtoupper(base_convert((string)$i, 10, 36));
159
                }
159
                }
160
 
160
 
161
                $tobase_str = '';
161
                $tobase_str = '';
162
                for ($i=0; $i<$tobase; $i++) {
162
                for ($i=0; $i<$tobase; $i++) {
163
                        $tobase_str .= strtoupper(base_convert((string)$i, 10, 36));
163
                        $tobase_str .= strtoupper(base_convert((string)$i, 10, 36));
164
                }
164
                }
165
 
165
 
166
                $length = strlen($numstring);
166
                $length = strlen($numstring);
167
                $result = '';
167
                $result = '';
168
                $number = array();
168
                $number = array();
169
                for ($i = 0; $i < $length; $i++) {
169
                for ($i = 0; $i < $length; $i++) {
170
                        $number[$i] = stripos($frombase_str, $numstring[$i]);
170
                        $number[$i] = stripos($frombase_str, $numstring[$i]);
171
                }
171
                }
172
                do { // Loop until whole number is converted
172
                do { // Loop until whole number is converted
173
                        $divide = 0;
173
                        $divide = 0;
174
                        $newlen = 0;
174
                        $newlen = 0;
175
                        for ($i = 0; $i < $length; $i++) { // Perform division manually (which is why this works with big numbers)
175
                        for ($i = 0; $i < $length; $i++) { // Perform division manually (which is why this works with big numbers)
176
                                $divide = $divide * $frombase + $number[$i];
176
                                $divide = $divide * $frombase + $number[$i];
177
                                if ($divide >= $tobase) {
177
                                if ($divide >= $tobase) {
178
                                        $number[$newlen++] = (int)($divide / $tobase);
178
                                        $number[$newlen++] = (int)($divide / $tobase);
179
                                        $divide = $divide % $tobase;
179
                                        $divide = $divide % $tobase;
180
                                } else if ($newlen > 0) {
180
                                } else if ($newlen > 0) {
181
                                        $number[$newlen++] = 0;
181
                                        $number[$newlen++] = 0;
182
                                }
182
                                }
183
                        }
183
                        }
184
                        $length = $newlen;
184
                        $length = $newlen;
185
                        $result = $tobase_str[$divide] . $result; // Divide is basically $numstring % $tobase (i.e. the new character)
185
                        $result = $tobase_str[$divide] . $result; // Divide is basically $numstring % $tobase (i.e. the new character)
186
                }
186
                }
187
                while ($newlen != 0);
187
                while ($newlen != 0);
188
 
188
 
189
                return $result;
189
                return $result;
190
        }
190
        }
191
}
191
}
192
 
192
 
193
 
193
 
194
# --- Usage Example ---
194
# --- Usage Example ---
195
 
195
 
196
/*
196
/*
197
echo "Class C tests:\n\n";
197
echo "Class C tests:\n\n";
198
 
198
 
199
var_dump($oid = '1.3.6.1.4.1.37553.8')."\n";
199
var_dump($oid = '1.3.6.1.4.1.37553.8')."\n";
200
var_dump(WeidOidConverter::oid2weid($oid))."\n";
200
var_dump(WeidOidConverter::oid2weid($oid))."\n";
201
$weid = 'weid:?';
201
$weid = 'weid:?';
202
var_dump(WeidOidConverter::weid2oid($weid))."\n";
202
var_dump(WeidOidConverter::weid2oid($weid))."\n";
203
var_dump($weid)."\n";
203
var_dump($weid)."\n";
204
echo "\n";
204
echo "\n";
205
 
205
 
206
var_dump($oid = '1.3.6.1.4.1.37553.8.32488192274')."\n";
206
var_dump($oid = '1.3.6.1.4.1.37553.8.32488192274')."\n";
207
var_dump(WeidOidConverter::oid2weid($oid))."\n";
207
var_dump(WeidOidConverter::oid2weid($oid))."\n";
208
$weid = 'weid:EXAMPLE-?';
208
$weid = 'weid:EXAMPLE-?';
209
var_dump(WeidOidConverter::weid2oid($weid))."\n";
209
var_dump(WeidOidConverter::weid2oid($weid))."\n";
210
var_dump($weid)."\n";
210
var_dump($weid)."\n";
211
$weid = 'weid:00000example-?';
211
$weid = 'weid:00000example-?';
212
var_dump(WeidOidConverter::weid2oid($weid))."\n";
212
var_dump(WeidOidConverter::weid2oid($weid))."\n";
213
var_dump($weid)."\n";
213
var_dump($weid)."\n";
214
echo "\n";
214
echo "\n";
215
 
215
 
216
echo "Class B tests:\n\n";
216
echo "Class B tests:\n\n";
217
 
217
 
218
var_dump($oid = '1.3.6.1.4.1')."\n";
218
var_dump($oid = '1.3.6.1.4.1')."\n";
219
var_dump(WeidOidConverter::oid2weid($oid))."\n";
219
var_dump(WeidOidConverter::oid2weid($oid))."\n";
220
$weid = 'weid:pen:?';
220
$weid = 'weid:pen:?';
221
var_dump(WeidOidConverter::weid2oid($weid))."\n";
221
var_dump(WeidOidConverter::weid2oid($weid))."\n";
222
var_dump($weid)."\n";
222
var_dump($weid)."\n";
223
echo "\n";
223
echo "\n";
224
 
224
 
225
var_dump($oid = '1.3.6.1.4.1.37553.7.99.99.99')."\n";
225
var_dump($oid = '1.3.6.1.4.1.37553.7.99.99.99')."\n";
226
var_dump(WeidOidConverter::oid2weid($oid))."\n";
226
var_dump(WeidOidConverter::oid2weid($oid))."\n";
227
$weid = 'weid:pen:SZ5-7-2R-2R-2R-?';
227
$weid = 'weid:pen:SZ5-7-2R-2R-2R-?';
228
var_dump(WeidOidConverter::weid2oid($weid))."\n";
228
var_dump(WeidOidConverter::weid2oid($weid))."\n";
229
var_dump($weid)."\n";
229
var_dump($weid)."\n";
230
$weid = 'weid:pen:000SZ5-7-02R-00002R-002r-?';
230
$weid = 'weid:pen:000SZ5-7-02R-00002R-002r-?';
231
var_dump(WeidOidConverter::weid2oid($weid))."\n";
231
var_dump(WeidOidConverter::weid2oid($weid))."\n";
232
var_dump($weid)."\n";
232
var_dump($weid)."\n";
233
echo "\n";
233
echo "\n";
234
 
234
 
235
var_dump($oid = '1.3.6.1.4.1.37476.9999')."\n";
235
var_dump($oid = '1.3.6.1.4.1.37476.9999')."\n";
236
var_dump(WeidOidConverter::oid2weid($oid))."\n";
236
var_dump(WeidOidConverter::oid2weid($oid))."\n";
237
$weid = 'weid:pen:SX0-7PR-?';
237
$weid = 'weid:pen:SX0-7PR-?';
238
var_dump(WeidOidConverter::weid2oid($weid))."\n";
238
var_dump(WeidOidConverter::weid2oid($weid))."\n";
239
var_dump($weid)."\n";
239
var_dump($weid)."\n";
240
echo "\n";
240
echo "\n";
241
 
241
 
242
echo "Class A tests:\n\n";
242
echo "Class A tests:\n\n";
243
 
243
 
244
var_dump($oid = '')."\n";
244
var_dump($oid = '')."\n";
245
var_dump(WeidOidConverter::oid2weid($oid))."\n";
245
var_dump(WeidOidConverter::oid2weid($oid))."\n";
246
$weid = 'weid:root:?';
246
$weid = 'weid:root:?';
247
var_dump(WeidOidConverter::weid2oid($weid))."\n";
247
var_dump(WeidOidConverter::weid2oid($weid))."\n";
248
var_dump($weid)."\n";
248
var_dump($weid)."\n";
249
echo "\n";
249
echo "\n";
250
 
250
 
251
var_dump($oid = '.2.999')."\n";
251
var_dump($oid = '.2.999')."\n";
252
var_dump(WeidOidConverter::oid2weid($oid))."\n";
252
var_dump(WeidOidConverter::oid2weid($oid))."\n";
253
$weid = 'weid:root:2-RR-?';
253
$weid = 'weid:root:2-RR-?';
254
var_dump(WeidOidConverter::weid2oid($weid))."\n";
254
var_dump(WeidOidConverter::weid2oid($weid))."\n";
255
var_dump($weid)."\n";
255
var_dump($weid)."\n";
256
echo "\n";
256
echo "\n";
257
 
257
 
258
var_dump($oid = '2.999')."\n";
258
var_dump($oid = '2.999')."\n";
259
var_dump(WeidOidConverter::oid2weid($oid))."\n";
259
var_dump(WeidOidConverter::oid2weid($oid))."\n";
260
$weid = 'weid:root:2-RR-?';
260
$weid = 'weid:root:2-RR-?';
261
var_dump(WeidOidConverter::weid2oid($weid))."\n";
261
var_dump(WeidOidConverter::weid2oid($weid))."\n";
262
var_dump($weid)."\n";
262
var_dump($weid)."\n";
263
echo "\n";
263
echo "\n";
264
*/
264
*/
265
 
265