Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
919 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
919 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
919 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
919 daniel-mar 26
class OIDplusAid extends OIDplusObject {
1130 daniel-mar 27
        /**
28
         * @var string
29
         */
919 daniel-mar 30
        private $aid;
31
 
1116 daniel-mar 32
        /**
1130 daniel-mar 33
         * @param string $aid
1116 daniel-mar 34
         */
1130 daniel-mar 35
        public function __construct(string $aid) {
919 daniel-mar 36
                // TODO: syntax checks
37
                $this->aid = $aid;
38
        }
39
 
1116 daniel-mar 40
        /**
41
         * @param string $node_id
42
         * @return OIDplusAid|null
43
         */
44
        public static function parse(string $node_id)/*: ?OIDplusAid*/ {
919 daniel-mar 45
                @list($namespace, $aid) = explode(':', $node_id, 2);
1116 daniel-mar 46
                if ($namespace !== self::ns()) return null;
919 daniel-mar 47
                return new self($aid);
48
        }
49
 
1116 daniel-mar 50
        /**
51
         * @return string
52
         */
53
        public static function objectTypeTitle(): string {
959 daniel-mar 54
                return _L('Application Identifier (ISO/IEC 7816)');
919 daniel-mar 55
        }
56
 
1116 daniel-mar 57
        /**
58
         * @return string
59
         */
60
        public static function objectTypeTitleShort(): string {
919 daniel-mar 61
                return _L('AID');
62
        }
63
 
1116 daniel-mar 64
        /**
65
         * @return string
66
         */
67
        public static function ns(): string {
919 daniel-mar 68
                return 'aid';
69
        }
70
 
1116 daniel-mar 71
        /**
72
         * @return string
73
         */
74
        public static function root(): string {
919 daniel-mar 75
                return self::ns().':';
76
        }
77
 
1116 daniel-mar 78
        /**
79
         * @return bool
80
         */
81
        public function isRoot(): bool {
919 daniel-mar 82
                return $this->aid == '';
83
        }
84
 
1116 daniel-mar 85
        /**
86
         * @param bool $with_ns
87
         * @return string
88
         */
89
        public function nodeId(bool $with_ns=true): string {
919 daniel-mar 90
                return $with_ns ? self::root().$this->aid : $this->aid;
91
        }
92
 
1116 daniel-mar 93
        /**
94
         * @param string $str
95
         * @return string
96
         * @throws OIDplusException
97
         */
98
        public function addString(string $str): string {
919 daniel-mar 99
                $m = array();
922 daniel-mar 100
 
101
                $str = str_replace(' ','',$str);
931 daniel-mar 102
                $str = str_replace(':','',$str);
922 daniel-mar 103
 
919 daniel-mar 104
                if (!preg_match('@^[0-9a-fA-F]+$@', $str, $m)) {
105
                        throw new OIDplusException(_L('AID part needs to be hexadecimal'));
106
                }
107
 
925 daniel-mar 108
                if (strlen($this->nodeId(false).$str) > 32) {
924 daniel-mar 109
                        throw new OIDplusException(_L('An AID has a maximum length of 16 bytes'));
919 daniel-mar 110
                }
111
 
930 daniel-mar 112
                // removed, because for D2 76 00 01 86 F... it makes sense to have your root (which is inside a foreign RID) being your OIDplus root
113
                /*
925 daniel-mar 114
                $pre   = $this->nodeId(false);
115
                $add   = strtoupper($str);
116
                $after = $pre.$add;
117
                $rid = '?';
118
                $pix = '?';
119
                $p = aid_split_rid_pix($after, $rid, $pix);
120
                if ($p > 1) { // Why $p>1? For "F", there is no RID. We allow that somebody include "F" in the first node
121
                        if ((strlen($pre)<$p) && (strlen($after)>$p)) {
122
                                $rid = substr($rid,strlen($pre));
123
                                throw new OIDplusException(_L('This node would mix RID (registry ID) and PIX (application specific). Please split it into two nodes "%1" and "%2".',$rid,$pix));
124
                        }
125
                }
930 daniel-mar 126
                */
925 daniel-mar 127
 
128
                return $this->nodeId(true).strtoupper($str);
919 daniel-mar 129
        }
130
 
1116 daniel-mar 131
        /**
132
         * @param OIDplusObject $parent
133
         * @return string
1130 daniel-mar 134
         * @throws OIDplusException
1116 daniel-mar 135
         */
136
        public function crudShowId(OIDplusObject $parent): string {
919 daniel-mar 137
                return $this->chunkedNotation(false);
138
        }
139
 
1116 daniel-mar 140
        /**
141
         * @return string
1130 daniel-mar 142
         * @throws OIDplusException
1116 daniel-mar 143
         */
144
        public function crudInsertPrefix(): string {
919 daniel-mar 145
                return $this->isRoot() ? '' : $this->chunkedNotation(false);
146
        }
147
 
1116 daniel-mar 148
        /**
149
         * @param OIDplusObject|null $parent
150
         * @return string
151
         */
152
        public function jsTreeNodeName(OIDplusObject $parent = null): string {
919 daniel-mar 153
                if ($parent == null) return $this->objectTypeTitle();
154
                return substr($this->nodeId(), strlen($parent->nodeId()));
155
        }
156
 
1116 daniel-mar 157
        /**
158
         * @return string
159
         */
160
        public function defaultTitle(): string {
1261 daniel-mar 161
                //return $this->aid;
162
                return rtrim(chunk_split($this->aid, 2, ' '), ' ');
919 daniel-mar 163
        }
164
 
1116 daniel-mar 165
        /**
166
         * @return bool
167
         */
168
        public function isLeafNode(): bool {
962 daniel-mar 169
                // We don't know when an AID is "leaf", because an AID can have an arbitary length <= 16 Bytes.
170
                // But if it is 16 bytes long (32 nibbles), then we are 100% certain that it is a leaf node.
171
                return (strlen($this->nodeId(false)) == 32);
919 daniel-mar 172
        }
173
 
1116 daniel-mar 174
        /**
175
         * @param string $title
176
         * @param string $content
177
         * @param string $icon
178
         * @return void
179
         * @throws OIDplusException
180
         */
181
        public function getContentPage(string &$title, string &$content, string &$icon) {
919 daniel-mar 182
                $icon = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
183
 
184
                if ($this->isRoot()) {
185
                        $title = OIDplusAid::objectTypeTitle();
186
 
187
                        $res = OIDplus::db()->query("select * from ###objects where parent = ?", array(self::root()));
188
                        if ($res->any()) {
962 daniel-mar 189
                                $content  = '<p>'._L('Please select an item in the tree view at the left to show its contents.').'</p>';
919 daniel-mar 190
                        } else {
962 daniel-mar 191
                                $content  = '<p>'._L('Currently, no Application Identifiers are registered in the system.').'</p>';
919 daniel-mar 192
                        }
193
 
194
                        if (!$this->isLeafNode()) {
195
                                if (OIDplus::authUtils()->isAdminLoggedIn()) {
196
                                        $content .= '<h2>'._L('Manage root objects').'</h2>';
197
                                } else {
198
                                        $content .= '<h2>'._L('Available objects').'</h2>';
199
                                }
200
                                $content .= '%%CRUD%%';
201
                        }
202
                } else {
203
                        $title = $this->getTitle();
204
 
205
                        $chunked = $this->chunkedNotation(true);
206
                        $content = '<h2>'.$chunked.'</h2>';
922 daniel-mar 207
 
924 daniel-mar 208
                        $tmp = decode_aid($this->aid,true);
209
                        $tmp = htmlentities($tmp);
210
                        $tmp = str_replace(' ','&nbsp;',$tmp);
211
                        $tmp = nl2br($tmp);
1401 daniel-mar 212
                        $tmp = preg_replace('@(warning|invalid|error|illegal(&nbsp;usage){0,1})@i', '<span class="aid_decoder_errortext">\\1</span>', $tmp);
1420 daniel-mar 213
 
214
                        # TODO: am besten farbmarkierung innerhalb c_literal_machen ? mit <abbr> und dann <abbr> irgendwie behandeln?
1401 daniel-mar 215
                        $tmp = preg_replace('@(\\\\\\d{3})@i', '<span class="aid_decoder_specialhexchar">\\1</span>', $tmp);
1420 daniel-mar 216
                        $tmp = preg_replace('@(\\\\x[0-9A-Fa-f]{2})@i', '<span class="aid_decoder_specialhexchar">\\1</span>', $tmp);
924 daniel-mar 217
 
922 daniel-mar 218
                        $content .= '<h2>'._L('Decoding').'</h2>';
219
                        $content .= '<table border="0">';
1391 daniel-mar 220
                        $content .= '<div style="overflow:auto;white-space:nowrap"><code>'.$tmp.'</code></div>';
922 daniel-mar 221
                        $content .= '</table>';
222
 
924 daniel-mar 223
                        $content .= '<h2>'._L('Description').'</h2>%%DESC%%';
919 daniel-mar 224
                        if ($this->userHasWriteRights()) {
928 daniel-mar 225
                                $content .= '<h2>'._L('Create or change subordinate objects').'</h2>';
919 daniel-mar 226
                        } else {
928 daniel-mar 227
                                $content .= '<h2>'._L('Subordinate objects').'</h2>';
919 daniel-mar 228
                        }
229
                        $content .= '%%CRUD%%';
230
                }
231
        }
232
 
233
        # ---
234
 
1116 daniel-mar 235
        /**
1130 daniel-mar 236
         * @param bool $withAbbr
1116 daniel-mar 237
         * @return string
238
         * @throws OIDplusException
239
         */
1130 daniel-mar 240
        public function chunkedNotation(bool $withAbbr=true): string {
919 daniel-mar 241
                $curid = self::root().$this->aid;
242
 
977 daniel-mar 243
                $obj = OIDplusObject::findFitting($curid);
244
                if (!$obj) return $this->aid;
919 daniel-mar 245
 
246
                $hints = array();
247
                $lengths = array(strlen($curid));
977 daniel-mar 248
                while ($obj = OIDplusObject::findFitting($curid)) {
249
                        $objParent = $obj->getParent();
250
                        if (!$objParent) break;
251
                        $curid = $objParent->nodeId();
252
                        $hints[] = $obj->getTitle();
919 daniel-mar 253
                        $lengths[] = strlen($curid);
254
                }
255
 
256
                array_shift($lengths);
257
                $chunks = array();
258
 
259
                $full = self::root().$this->aid;
260
                foreach ($lengths as $len) {
261
                        $chunks[] = substr($full, $len);
262
                        $full = substr($full, 0, $len);
263
                }
264
 
265
                $hints = array_reverse($hints);
266
                $chunks = array_reverse($chunks);
267
 
268
                $full = array();
269
                foreach ($chunks as $c) {
934 daniel-mar 270
                        $hint = array_shift($hints);
271
                        $full[] = $withAbbr && ($hint !== '') ? '<abbr title="'.htmlentities($hint).'">'.$c.'</abbr>' : $c;
919 daniel-mar 272
                }
273
                return implode(' ', $full);
274
        }
275
 
1116 daniel-mar 276
        /**
277
         * @return OIDplusAid|null
278
         */
279
        public function one_up()/*: ?OIDplusAid*/ {
280
                return self::parse($this->ns().':'.substr($this->aid,0,strlen($this->aid)-1));
919 daniel-mar 281
        }
282
 
1116 daniel-mar 283
        /**
1130 daniel-mar 284
         * @param OIDplusObject|string $to
1116 daniel-mar 285
         * @return int|null
286
         */
919 daniel-mar 287
        public function distance($to) {
288
                if (!is_object($to)) $to = OIDplusObject::parse($to);
1121 daniel-mar 289
                if (!$to) return null;
1116 daniel-mar 290
                if (!($to instanceof $this)) return null;
919 daniel-mar 291
 
292
                $a = $to->aid;
293
                $b = $this->aid;
294
 
295
                $ary = $a;
296
                $bry = $b;
297
 
298
                $min_len = min(strlen($ary), strlen($bry));
299
 
300
                for ($i=0; $i<$min_len; $i++) {
1116 daniel-mar 301
                        if ($ary[$i] != $bry[$i]) return null;
919 daniel-mar 302
                }
303
 
304
                return strlen($ary) - strlen($bry);
305
        }
306
 
1116 daniel-mar 307
        /**
308
         * @return array|OIDplusAltId[]
309
         * @throws OIDplusException
310
         */
311
        public function getAltIds(): array {
930 daniel-mar 312
                if ($this->isRoot()) return array();
313
                $ids = parent::getAltIds();
314
 
945 daniel-mar 315
                $aid = $this->nodeId(false);
316
                $aid = strtoupper($aid);
317
 
1077 daniel-mar 318
                // ViaThinkSoft proprietary AIDs
319
 
320
                // (VTS B1) Members
321
                if ($aid == 'D276000186B1') {
322
                        $oid = '1.3.6.1.4.1.37476.1';
323
                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
324
                }
325
 
326
                if (preg_match('@^D276000186B1(....)$@', $aid, $m)) {
327
                        $oid = '1.3.6.1.4.1.37476.1.'.ltrim($m[1],'0');
328
                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
329
                }
330
 
331
                // (VTS B2) Products
332
                if ($aid == 'D276000186B2') {
333
                        $oid = '1.3.6.1.4.1.37476.2';
334
                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
335
                }
336
 
337
                if (preg_match('@^D276000186B2(....)$@', $aid, $m)) {
338
                        $oid = '1.3.6.1.4.1.37476.2.'.ltrim($m[1],'0');
339
                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
340
                }
341
 
1078 daniel-mar 342
                // (VTS B2 00 05) OIDplus Information Objects AID
343
                // Attention: D276000186B20005 does NOT represent 1.3.6.1.4.1.37476.30.9
344
                //            because the mapping to OIDplus systems only applies for 00......-7F...... (31 bit hash)
345
 
346
                if (preg_match('@^D276000186B20005([0-7].......)$@', $aid, $m)) {
347
                        $oid = '1.3.6.1.4.1.37476.30.9.'.hexdec($m[1]);
348
                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
349
                }
350
 
351
                if (preg_match('@^D276000186B20005([0-7].......)([0-7].......)$@', $aid, $m)) {
352
                        $oid = '1.3.6.1.4.1.37476.30.9.'.hexdec($m[1]).'.'.hexdec($m[2]);
353
                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
354
                }
355
 
1079 daniel-mar 356
                // ViaThinkSoft "Example" AID
357
 
358
                if ($aid == 'D276000186E0') {
359
                        // Note that the OID object type plugin also maps children of 2.999 to AID,
360
                        // using a hash. But since this is not unique and cannot be reverted,
361
                        // we cannot have an reverse lookup/map.
362
                        $ids[] = new OIDplusAltId('oid', '2.999', _L('Object Identifier (OID)'), ' ('._L('Optional PIX allowed, without prefix').')');
363
                }
364
 
930 daniel-mar 365
                // ViaThinkSoft "Foreign" AIDs
366
 
945 daniel-mar 367
                // (VTS F0) IANA PEN + PIX
368
                // Resolve only if there is no PIX
369
                if (str_starts_with($aid,'D276000186F0')) {
370
                        $rest = substr($aid,strlen('D276000186F0'));
371
                        $p = strpos($rest,'F');
372
                        if ($p !== false) {
373
                                $pen = substr($rest,0,$p);
374
                                $pix = substr($rest,$p+1);
375
                        } else {
376
                                $pen = $rest;
377
                                $pix = '';
378
                        }
379
                        if (($pix === '') && preg_match('/^[0-9]+$/',$pen,$m)) {
380
                                $oid = '1.3.6.1.4.1.'.$pen;
381
                                $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
961 daniel-mar 382
                                $ids[] = new OIDplusAltId('iana-pen', $pen, _L('IANA Private Enterprise Number (PEN)'));
945 daniel-mar 383
                        }
384
                }
385
 
386
                // (VTS F1) ViaThinkSoft FreeOID + PIX
387
                // Resolve only if there is no PIX
388
                if (str_starts_with($aid,'D276000186F1')) {
389
                        $rest = substr($aid,strlen('D276000186F1'));
390
                        $p = strpos($rest,'F');
391
                        if ($p !== false) {
392
                                $number = substr($rest,0,$p);
393
                                $pix = substr($rest,$p+1);
394
                        } else {
395
                                $number = $rest;
396
                                $pix = '';
397
                        }
398
                        if (($pix === '') && preg_match('/^[0-9]+$/',$number,$m)) {
399
                                $oid = '1.3.6.1.4.1.37476.9000.'.$number;
400
                                $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
401
                        }
402
                }
403
 
1256 daniel-mar 404
                // (VTS F2) MAC address (EUI/ELI/...) + PIX
945 daniel-mar 405
                // Resolve only if there is no PIX
406
                if (str_starts_with($aid,'D276000186F2')) {
1256 daniel-mar 407
                        $size_nibble = substr($aid,strlen('D276000186F2'),1);
1257 daniel-mar 408
                        if ($size_nibble != '') {
1440 daniel-mar 409
                                $mac = substr($aid, strlen('D276000186F2'.$size_nibble), hexdec($size_nibble) + 1);
410
                                $test_aid = 'D276000186F2'.$size_nibble.$mac;
411
                                if (strlen($test_aid)%2 == 1) $test_aid .= 'F'; // padding
412
                                if ($aid == $test_aid) {
1257 daniel-mar 413
                                        $mac_type = mac_type(str_pad($mac, 12, '0', STR_PAD_RIGHT));
414
                                        $ids[] = new OIDplusAltId('mac', $mac, $mac_type);
415
                                }
945 daniel-mar 416
                        }
417
                }
418
 
1459 daniel-mar 419
                // (VTS F3 01) USB-IF VendorID + ProductID + PIX
945 daniel-mar 420
                // Resolve only if there is no PIX
1459 daniel-mar 421
                if (str_starts_with($aid,'D276000186F301')) {
422
                        $rest = substr($aid,strlen('D276000186F301'));
945 daniel-mar 423
                        if (strlen($rest) == 4) {
424
                                $vid = $rest;
425
                                $ids[] = new OIDplusAltId('usb-vendor-id', $vid, _L('USB-IF (usb.org) VendorID'));
1459 daniel-mar 426
                        } else if (strlen($rest) == 8) {
427
                                $vid_pid = substr($rest, 0, 4) . ':' . substr($rest, 4);;
428
                                $ids[] = new OIDplusAltId('usb-vendor-product-id', $vid_pid, _L('USB-IF (usb.org) VendorID/ProductID'));
945 daniel-mar 429
                        }
430
                }
431
 
1459 daniel-mar 432
                // (VTS F3 02) PCI-SIG VendorID + ProductID + PIX
433
                // Resolve only if there is no PIX
434
                if (str_starts_with($aid,'D276000186F302')) {
435
                        $rest = substr($aid,strlen('D276000186F302'));
436
                        if (strlen($rest) == 4) {
437
                                $vid = $rest;
438
                                $ids[] = new OIDplusAltId('pci-vendor-id', $vid, _L('PCI-SIG (pcisig.com) VendorID'));
439
                        } else if (strlen($rest) == 8) {
440
                                $vid_pid = substr($rest, 0, 4) . ':' . substr($rest, 4);;
441
                                $ids[] = new OIDplusAltId('pci-vendor-product-id', $vid_pid, _L('PCI-SIG (pcisig.com)VendorID/ProductID'));
442
                        }
443
                }
444
 
1466 daniel-mar 445
                // (VTS F4 01) D-U-N-S number + PIX
945 daniel-mar 446
                // Resolve only if there is no PIX
1466 daniel-mar 447
                if (str_starts_with($aid,'D276000186F401')) {
448
                        $rest = substr($aid,strlen('D276000186F401'));
945 daniel-mar 449
                        $p = strpos($rest,'F');
450
                        if ($p !== false) {
451
                                $duns = substr($rest,0,$p);
452
                                $pix = substr($rest,$p+1);
453
                        } else {
454
                                $duns = $rest;
455
                                $pix = '';
456
                        }
457
                        if (($pix === '') && preg_match('/^[0-9]+$/',$duns,$m)) {
458
                                $ids[] = new OIDplusAltId('duns', $duns, _L('Data Universal Numbering System (D-U-N-S)'));
459
                        }
460
                }
461
 
462
                // (VTS F5) GS1 number + PIX
463
                // Resolve only if there is no PIX
464
                if (str_starts_with($aid,'D276000186F5')) {
465
                        $rest = substr($aid,strlen('D276000186F5'));
466
                        $p = strpos($rest,'F');
467
                        if ($p !== false) {
468
                                $gs1 = substr($rest,0,$p);
469
                                $pix = substr($rest,$p+1);
470
                        } else {
471
                                $gs1 = $rest;
472
                                $pix = '';
473
                        }
474
                        if (($pix === '') && preg_match('/^[0-9]+$/',$gs1,$m)) {
475
                                $ids[] = new OIDplusAltId('gs1', $gs1, _L('GS1 Based IDs (GLN/GTIN/SSCC/...)'), ' ('._L('without check-digit').')');
476
                        }
477
                }
478
 
479
                // (VTS F6) OID<->AID, no PIX
930 daniel-mar 480
                if (str_starts_with($aid,'D276000186F6')) {
481
                        $der = substr($aid,strlen('D276000186F6'));
482
                        $len = strlen($der);
483
                        if ($len%2 == 0) {
484
                                $len /= 2;
485
                                $len = str_pad("$len", 2, '0', STR_PAD_LEFT);
486
                                $type = '06'; // absolute OID
487
                                $der = "$type $len $der";
1050 daniel-mar 488
                                $oid = \OidDerConverter::derToOID(\OidDerConverter::hexStrToArray($der));
930 daniel-mar 489
                                if ($oid) {
490
                                        $oid = ltrim($oid,'.');
491
                                        $ids[] = new OIDplusAltId('oid', $oid, _L('Object Identifier (OID)'));
492
                                }
493
                        }
494
                }
495
 
1466 daniel-mar 496
                // (VTS F7 01) ISNI + PIX
497
                // Resolve only if there is no PIX
498
                if (str_starts_with($aid,'D276000186F701')) {
499
                        $rest = substr($aid,strlen('D276000186F701'));
500
                        if (strlen($rest) >= 14) {
501
                                $isni_bin = substr($rest,0,14);
502
                                $pix = substr($rest,15);
503
                                if (($pix === '') && preg_match('/^[A-F0-9]+$/',$isni_bin,$m)) {
504
                                        // Example: "2386F26FC0FFFF" => "9999-9999-9999-9999"
505
                                        $isni = rtrim(chunk_split(str_pad(self::base_convert_bigint($isni_bin,16,10),16,'0',STR_PAD_LEFT),4,'-'),'-');
506
                                        $ids[] = new OIDplusAltId('isni', $isni, _L('International Standard Name Identifier (ISNI)'));
507
                                }
508
                        }
509
                }
510
 
511
 
933 daniel-mar 512
                // The case E8... (Standard OID 1.0) doesn't need to be addressed here, because it is already shown in the AID decoder (and it is ambiguous since DER and PIX are mixed)
945 daniel-mar 513
                // TODO: If it has no pix, then resolve it !!! but how do we know if there is a PIX or a part ID ?
933 daniel-mar 514
 
930 daniel-mar 515
                return $ids;
516
        }
517
 
1116 daniel-mar 518
        /**
1466 daniel-mar 519
         * @param string $numstring
520
         * @param int $frombase
521
         * @param int $tobase
1116 daniel-mar 522
         * @return string
523
         */
1466 daniel-mar 524
        protected static function base_convert_bigint(string $numstring, int $frombase, int $tobase): string {
525
                // TODO: put this (used here and in OID WeidConverter) to functions.inc.php ?
526
 
527
                $frombase_str = '';
528
                for ($i=0; $i<$frombase; $i++) {
529
                        $frombase_str .= strtoupper(base_convert((string)$i, 10, 36));
530
                }
531
 
532
                $tobase_str = '';
533
                for ($i=0; $i<$tobase; $i++) {
534
                        $tobase_str .= strtoupper(base_convert((string)$i, 10, 36));
535
                }
536
 
537
                $length = strlen($numstring);
538
                $result = '';
539
                $number = array();
540
                for ($i = 0; $i < $length; $i++) {
541
                        $number[$i] = stripos($frombase_str, $numstring[$i]);
542
                }
543
                do { // Loop until whole number is converted
544
                        $divide = 0;
545
                        $newlen = 0;
546
                        for ($i = 0; $i < $length; $i++) { // Perform division manually (which is why this works with big numbers)
547
                                $divide = $divide * $frombase + $number[$i];
548
                                if ($divide >= $tobase) {
549
                                        $number[$newlen++] = (int)($divide / $tobase);
550
                                        $divide = $divide % $tobase;
551
                                } else if ($newlen > 0) {
552
                                        $number[$newlen++] = 0;
553
                                }
554
                        }
555
                        $length = $newlen;
556
                        $result = $tobase_str[$divide] . $result; // Divide is basically $numstring % $tobase (i.e. the new character)
557
                }
558
                while ($newlen != 0);
559
 
560
                return $result;
561
        }
562
 
563
        /**
564
         * @return string
565
         */
1116 daniel-mar 566
        public function getDirectoryName(): string {
919 daniel-mar 567
                if ($this->isRoot()) return $this->ns();
568
                return $this->ns().'_'.$this->nodeId(false); // safe, because there are only AIDs
569
        }
570
 
1116 daniel-mar 571
        /**
572
         * @param string $mode
573
         * @return string
574
         */
575
        public static function treeIconFilename(string $mode): string {
919 daniel-mar 576
                return 'img/'.$mode.'_icon16.png';
577
        }
578
}