Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
2 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
5
 * Copyright 2019 Daniel Marschall, ViaThinkSoft
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
 
112 daniel-mar 20
if (!defined('IN_OIDPLUS')) die();
21
 
227 daniel-mar 22
require_once __DIR__ . '/WeidOidConverter.class.php';
222 daniel-mar 23
 
227 daniel-mar 24
class OIDplusObjectTypePluginOid extends OIDplusObjectTypePlugin {
2 daniel-mar 25
 
222 daniel-mar 26
        public static function getPluginInformation() {
27
                $out = array();
28
                $out['name'] = 'Object Identifier (OID)';
29
                $out['author'] = 'ViaThinkSoft';
30
                $out['version'] = null;
31
                $out['descriptionHTML'] = null;
32
                return $out;
33
        }
34
 
227 daniel-mar 35
        public static function getObjectTypeClassName() {
36
                return 'OIDplusOid';
37
        }
38
 
39
}
40
 
41
class OIDplusOid extends OIDplusObject {
42
        private $oid;
43
 
2 daniel-mar 44
        public function __construct($oid) {
12 daniel-mar 45
                $bak_oid = $oid;
46
 
47
                $oid = sanitizeOID($oid, 'auto');
48
                if ($oid === false) {
49
                        throw new Exception("Invalid OID '$bak_oid'");
50
                }
51
 
52
                if (($oid != '') && (!oid_valid_dotnotation($oid, false, true, 0))) {
53
                        // avoid OIDs like 3.0
54
                        throw new Exception("Invalid OID '$bak_oid'");
55
                }
56
 
2 daniel-mar 57
                $this->oid = $oid;
58
        }
59
 
60
        public static function parse($node_id) {
61
                @list($namespace, $oid) = explode(':', $node_id, 2);
62
                if ($namespace !== 'oid') return false;
63
                return new self($oid);
64
        }
65
 
66
        public static function objectTypeTitle() {
67
                return "Object Identifier (OID)";
68
        }
69
 
70
        public static function objectTypeTitleShort() {
71
                return "OID";
72
        }
73
 
74
        public static function ns() {
75
                return 'oid';
76
        }
77
 
78
        public static function root() {
79
                return 'oid:';
80
        }
81
 
82
        public function isRoot() {
83
                return $this->oid == '';
84
        }
85
 
86
        public function nodeId() {
87
                return 'oid:'.$this->oid;
88
        }
89
 
90
        public function addString($str) {
91
                if (!$this->isRoot()) {
196 daniel-mar 92
                        if (strpos($str,'.') !== false) throw new Exception("Please only submit one arc (not an absolute OID or multiple arcs).");
2 daniel-mar 93
                }
196 daniel-mar 94
 
199 daniel-mar 95
                return $this->appendArcs($str)->nodeId();
2 daniel-mar 96
        }
97
 
98
        public function crudShowId(OIDplusObject $parent) {
99
                return $this->deltaDotNotation($parent);
100
        }
101
 
102
        public function crudInsertPrefix() {
103
                return '';
104
        }
105
 
106
        public function jsTreeNodeName(OIDplusObject $parent = null) {
107
                if ($parent == null) return $this->objectTypeTitle();
108
                return $this->viewGetArcAsn1s($parent);
109
        }
110
 
111
        public function defaultTitle() {
112
                return 'OID ' . $this->oid;
113
        }
114
 
16 daniel-mar 115
        public function isLeafNode() {
116
                return false;
117
        }
118
 
34 daniel-mar 119
        public function getContentPage(&$title, &$content, &$icon) {
55 daniel-mar 120
                $icon = file_exists(__DIR__.'/icon_big.png') ? 'plugins/objectTypes/'.basename(__DIR__).'/icon_big.png' : '';
121
 
2 daniel-mar 122
                if ($this->isRoot()) {
123
                        $title = OIDplusOid::objectTypeTitle();
124
 
150 daniel-mar 125
                        $res = OIDplus::db()->query("select id from ".OIDPLUS_TABLENAME_PREFIX."objects where parent = ?", array(self::root()));
2 daniel-mar 126
                        if (OIDplus::db()->num_rows($res) > 0) {
127
                                $content = 'Please select an OID in the tree view at the left to show its contents.';
128
                        } else {
129
                                $content = 'Currently, no OID is registered in the system.';
130
                        }
131
 
16 daniel-mar 132
                        if (!$this->isLeafNode()) {
133
                                if (OIDplus::authUtils()::isAdminLoggedIn()) {
134
                                        $content .= '<h2>Manage your root OIDs</h2>';
135
                                } else {
136
                                        $content .= '<h2>Root OIDs</h2>';
137
                                }
138
                                $content .= '%%CRUD%%';
2 daniel-mar 139
                        }
140
                } else {
192 daniel-mar 141
                        $title = $this->getTitle();
142
 
103 daniel-mar 143
                        $content = "<h2>Technical information</h2>".$this->oidInformation().
11 daniel-mar 144
                                   "<h2>Description</h2>%%DESC%%".
6 daniel-mar 145
                                   "<h2>Registration Authority</h2>%%RA_INFO%%";
2 daniel-mar 146
 
16 daniel-mar 147
                        if (!$this->isLeafNode()) {
148
                                if ($this->userHasWriteRights()) {
149
                                        $content .= '<h2>Create or change subsequent objects</h2>';
150
                                } else {
151
                                        $content .= '<h2>Subsequent objects</h2>';
152
                                }
153
                                $content .= '%%CRUD%%';
2 daniel-mar 154
                        }
155
                }
156
        }
157
 
158
        # ---
159
 
197 daniel-mar 160
        public function isWeid($allow_root) {
61 daniel-mar 161
                $weid = WeidOidConverter::oid2weid($this->getDotNotation());
197 daniel-mar 162
                if (!$allow_root && ($weid === 'weid:4')) return false;
196 daniel-mar 163
                return $weid !== false;
2 daniel-mar 164
        }
165
 
196 daniel-mar 166
        public function weidArc() {
167
                $weid = WeidOidConverter::oid2weid($this->getDotNotation());
168
                if ($weid === false) return false;
197 daniel-mar 169
                list($ns,$weid) = explode(':', $weid, 2);
196 daniel-mar 170
                $x = explode('-', $weid);
197 daniel-mar 171
                if (count($x) < 2) return ''; // WEID root arc. Has no name
196 daniel-mar 172
                return $x[count($x)-2];
173
        }
174
 
175
        public function getWeidNotation($withAbbr=true) {
176
                $weid = WeidOidConverter::oid2weid($this->getDotNotation());
177
                if ($withAbbr) {
178
                        list($ns,$weid) = explode(':', $weid);
179
                        $weid_arcs = explode('-', $weid);
180
                        foreach ($weid_arcs as $i => &$weid) {
181
                                if ($i == count($weid_arcs)-1) {
182
                                        $weid = '<abbr title="weLuhn check digit">'.$weid.'</abbr>';
183
                                } else {
184
                                        $oid_arcs = explode('.',$this->oid);
185
                                        $weid_num = $oid_arcs[(count($oid_arcs)-1)-(count($weid_arcs)-1)+($i+1)];
186
                                        if ($weid_num != $weid) {
187
                                                $weid = '<abbr title="Numeric value: '.$weid_num.'">'.$weid.'</abbr>';
188
                                        }
189
                                }
190
                        }
191
                        $weid = '<abbr title="Root arc: 1.3.6.1.4.1.37553.8">' . $ns . '</abbr>:' . implode('-',$weid_arcs);
192
                }
193
                return $weid;
194
        }
195
 
196
        private function oidInformation() {
197
                $out = array();
198
                $out[] = "Dot notation: <code>" . $this->getDotNotation() . "</code>";
199
                $out[] = "ASN.1 notation: <code>{ " . $this->getAsn1Notation() . " }</code>";
200
                $out[] = "OID-IRI notation: <code>" . $this->getIriNotation() . "</code>";
197 daniel-mar 201
                if ($this->isWeid(true)) {
196 daniel-mar 202
                        $out[] = "WEID notation: <code>" . $this->getWeidNotation() . "</code>";
203
                }
204
                return '<p>'.implode('<br>',$out).'</p>';
205
        }
206
 
2 daniel-mar 207
        public function __clone() {
208
                return new self($this->oid);
209
        }
210
 
211
        public function appendArcs(String $arcs) {
212
                $out = clone $this;
5 daniel-mar 213
 
2 daniel-mar 214
                if ($out->isRoot()) {
215
                        $out->oid .= $arcs;
216
                } else {
217
                        $out->oid .= '.' . $arcs;
218
                }
5 daniel-mar 219
 
13 daniel-mar 220
                $bak_oid = $out->oid;
5 daniel-mar 221
                $out->oid = sanitizeOID($out->oid);
13 daniel-mar 222
                if ($out->oid === false) throw new Exception("$bak_oid is not a valid OID!");
5 daniel-mar 223
 
2 daniel-mar 224
                return $out;
225
        }
226
 
227
        public function deltaDotNotation(OIDplusOid $parent) {
228
                if (!$parent->isRoot()) {
229
                        if (substr($this->oid, 0, strlen($parent->oid)+1) == $parent->oid.'.') {
230
                                return substr($this->oid, strlen($parent->oid)+1);
231
                        } else {
232
                                return false;
233
                        }
234
                } else {
235
                        return $this->oid;
236
                }
237
        }
238
 
239
        public function viewGetArcAsn1s(OIDplusOid $parent=null, $separator = ' | ') {
240
                $asn_ids = array();
241
 
242
                if (is_null($parent)) $parent = OIDplusOid::parse('oid:');
243
 
244
                $part = $this->deltaDotNotation($parent);
245
 
246
                if (strpos($part, '.') === false) {
150 daniel-mar 247
                        $res2 = OIDplus::db()->query("select name from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = ? order by lfd", array("oid:".$this->oid));
2 daniel-mar 248
                        while ($row2 = OIDplus::db()->fetch_array($res2)) {
249
                                $asn_ids[] = $row2['name'].'('.$part.')';
250
                        }
251
                }
252
 
253
                if (count($asn_ids) == 0) $asn_ids = array($part);
254
                return implode($asn_ids, $separator);
255
        }
256
 
257
        public function getAsn1Notation($withAbbr=true) {
258
                $asn1_notation = '';
259
                $arcs = explode('.', $this->oid);
260
 
261
                foreach ($arcs as $arc) {
150 daniel-mar 262
                        $res = OIDplus::db()->query("select name, standardized from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = ? order by lfd", array('oid:'.implode('.',$arcs)));
2 daniel-mar 263
 
264
                        $names = array();
265
                        while ($row = OIDplus::db()->fetch_array($res)) {
51 daniel-mar 266
                                $names[] = $row['name']."(".end($arcs).")";
267
                                if ($row['standardized']) {
268
                                        $names[] = $row['name'];
269
                                }
2 daniel-mar 270
                        }
271
 
52 daniel-mar 272
                        $numeric = array_pop($arcs);
2 daniel-mar 273
                        if (count($names) > 1) {
274
                                $first_name = array_shift($names);
52 daniel-mar 275
                                $abbr = 'Other identifiers:&#10;      '.implode('&#10;      ',$names);
2 daniel-mar 276
                                if ($withAbbr) {
51 daniel-mar 277
                                        $asn1_notation = '<abbr title="'.$abbr.'">'.$first_name.'</abbr> '.$asn1_notation;
2 daniel-mar 278
                                } else {
51 daniel-mar 279
                                        $asn1_notation = $first_name.' '.$asn1_notation;
2 daniel-mar 280
                                }
281
                        } else if (count($names) == 1) {
51 daniel-mar 282
                                $asn1_notation = array_shift($names).' '.$asn1_notation;
2 daniel-mar 283
                        } else {
52 daniel-mar 284
                                $asn1_notation = $numeric.' '.$asn1_notation;
2 daniel-mar 285
                        }
286
                }
287
 
288
                return $asn1_notation;
289
        }
290
 
291
        public function getIriNotation($withAbbr=true) {
292
                $iri_notation = '';
293
                $arcs = explode('.', $this->oid);
294
 
295
                foreach ($arcs as $arc) {
150 daniel-mar 296
                        $res = OIDplus::db()->query("select name, longarc from ".OIDPLUS_TABLENAME_PREFIX."iri where oid = ? order by lfd", array('oid:'.implode('.',$arcs)));
2 daniel-mar 297
 
298
                        $is_longarc = false;
299
                        $names = array();
300
                        while ($row = OIDplus::db()->fetch_array($res)) {
301
                                $is_longarc = $row['longarc'];
302
                                $names[] = $row['name'];
51 daniel-mar 303
 
304
                                if ($is_longarc) {
305
                                        $names[] = 'Joint-ISO-ITU-T/'.$row['name']; // Long arcs can only be inside root OID 2
306
                                }
2 daniel-mar 307
                        }
308
 
309
                        $names[] = array_pop($arcs);
310
                        if (count($names) > 2) {
311
                                $first_name = array_shift($names);
52 daniel-mar 312
                                $numeric = array_pop($names);
313
                                $abbr = 'Other identifiers:&#10;      '.implode('&#10;      ',$names).'&#10;Numeric value: '.$numeric;
2 daniel-mar 314
                                $iri_notation = $withAbbr ? '<abbr title="'.$abbr.'">'.$first_name.'</abbr>/'.$iri_notation : $first_name.'/'.$iri_notation;
315
                        } else if (count($names) > 1) {
316
                                $first_name = array_shift($names);
317
                                $abbr = 'Numeric value: '.array_shift($names);
318
                                $iri_notation = $withAbbr ? '<abbr title="'.$abbr.'">'.$first_name.'</abbr>/'.$iri_notation : $first_name.'/'.$iri_notation;
319
                        } else if (count($names) == 1) {
320
                                $iri_notation = array_shift($names) . '/' . $iri_notation;
321
                        }
322
 
51 daniel-mar 323
                        if ($is_longarc) break; // we don't write /ITU-T/ at the beginning, when /ITU-T/xxx is a long arc
2 daniel-mar 324
                }
325
                $iri_notation = '/' . substr($iri_notation, 0, strlen($iri_notation)-1);
326
 
327
                return $iri_notation;
328
        }
329
 
330
        public function getDotNotation() {
331
                return $this->oid;
332
        }
333
 
13 daniel-mar 334
        public function isWellKnown() {
150 daniel-mar 335
                $res = OIDplus::db()->query("select oid from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = ? and well_known = 1", array("oid:".$this->oid));
13 daniel-mar 336
                if (OIDplus::db()->num_rows($res) > 0) return true;
337
 
150 daniel-mar 338
                $res = OIDplus::db()->query("select oid from ".OIDPLUS_TABLENAME_PREFIX."iri where oid = ? and well_known = 1", array("oid:".$this->oid));
13 daniel-mar 339
                if (OIDplus::db()->num_rows($res) > 0) return true;
340
 
341
                return false;
342
        }
343
 
147 daniel-mar 344
        public function replaceAsn1Ids($demandedASN1s=array(), $simulate=false) {
13 daniel-mar 345
                if ($this->isWellKnown()) {
346
                        throw new Exception("OID ".$this->oid." is a 'well-known' OID. Its identifiers cannot be changed.");
347
                }
348
 
2 daniel-mar 349
                // First do a few checks
350
                foreach ($demandedASN1s as &$asn1) {
351
                        $asn1 = trim($asn1);
352
 
13 daniel-mar 353
                        // Validate identifier
354
                        if (!oid_id_is_valid($asn1)) throw new Exception("'$asn1' is not a valid ASN.1 identifier!");
355
 
2 daniel-mar 356
                        // Check if the (real) parent has any conflict
201 daniel-mar 357
                        // Unlike IRI identifiers, ASN.1 identifiers may be used multiple times (not recommended), except if one of them is standardized
358
                        $res = OIDplus::db()->query("select oid from ".OIDPLUS_TABLENAME_PREFIX."asn1id where name = ? and standardized = 1", array($asn1));
2 daniel-mar 359
                        while ($row = OIDplus::db()->fetch_array($res)) {
360
                                $check_oid = OIDplusOid::parse($row['oid'])->oid;
361
                                if ((oid_up($check_oid) === oid_up($this->oid)) && // same parent
362
                                   ($check_oid !== $this->oid))                    // different OID
363
                                {
201 daniel-mar 364
                                        throw new Exception("ASN.1 identifier '$asn1' is a standardized identifier belonging to OID ($check_oid)");
2 daniel-mar 365
                                }
366
                        }
367
                }
368
 
369
                // Now do the real replacement
147 daniel-mar 370
                if (!$simulate) {
150 daniel-mar 371
                        OIDplus::db()->query("delete from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = ?", array("oid:".$this->oid));
147 daniel-mar 372
                        foreach ($demandedASN1s as &$asn1) {
150 daniel-mar 373
                                if (!OIDplus::db()->query("insert into ".OIDPLUS_TABLENAME_PREFIX."asn1id (oid, name) values (?, ?)", array("oid:".$this->oid, $asn1))) {
147 daniel-mar 374
                                        throw new Exception("Insertion of ASN.1 ID $asn1 to OID ".$this->oid." failed!");
375
                                }
2 daniel-mar 376
                        }
377
                }
378
        }
379
 
147 daniel-mar 380
        public function replaceIris($demandedIris=array(), $simulate=false) {
13 daniel-mar 381
                if ($this->isWellKnown()) {
382
                        throw new Exception("OID ".$this->oid." is a 'well-known' OID. Its identifiers cannot be changed.");
383
                }
384
 
2 daniel-mar 385
                // First do a few checks
386
                foreach ($demandedIris as &$iri) {
387
                        $iri = trim($iri);
388
 
13 daniel-mar 389
                        // Validate identifier
390
                        if (!iri_arc_valid($iri, false)) throw new Exception("'$iri' is not a valid IRI!");
391
 
2 daniel-mar 392
                        // Check if the (real) parent has any conflict
150 daniel-mar 393
                        $res = OIDplus::db()->query("select oid from ".OIDPLUS_TABLENAME_PREFIX."iri where name = ?", array($iri));
2 daniel-mar 394
                        while ($row = OIDplus::db()->fetch_array($res)) {
395
                                $check_oid = OIDplusOid::parse($row['oid'])->oid;
396
                                if ((oid_up($check_oid) === oid_up($this->oid)) && // same parent
397
                                   ($check_oid !== $this->oid))                    // different OID
398
                                {
399
                                        throw new Exception("IRI '$iri' is already used by another OID ($check_oid)");
400
                                }
401
                        }
402
                }
403
 
404
                // Now do the real replacement
147 daniel-mar 405
                if (!$simulate) {
150 daniel-mar 406
                        OIDplus::db()->query("delete from ".OIDPLUS_TABLENAME_PREFIX."iri where oid = ?", array("oid:".$this->oid));
147 daniel-mar 407
                        foreach ($demandedIris as &$iri) {
150 daniel-mar 408
                                if (!OIDplus::db()->query("insert into ".OIDPLUS_TABLENAME_PREFIX."iri (oid, name) values (?, ?)", array("oid:".$this->oid, $iri))) {
147 daniel-mar 409
                                        throw new Exception("Insertion of IRI $iri to OID ".$this->oid." failed!");
410
                                }
2 daniel-mar 411
                        }
412
                }
413
        }
12 daniel-mar 414
 
20 daniel-mar 415
        public function one_up() {
416
                return self::parse(self::ns().':'.oid_up($this->oid));
12 daniel-mar 417
        }
418
 
419
        public function distance($to) {
420
                if (!is_object($to)) $to = OIDplusObject::parse($to);
28 daniel-mar 421
                if (!($to instanceof $this)) return false;
12 daniel-mar 422
                return oid_distance($to->oid, $this->oid);
423
        }
192 daniel-mar 424
 
193 daniel-mar 425
        public function getAltIds() {
426
                if ($this->isRoot()) return array();
427
                $ids = parent::getAltIds();
428
                if ($uuid = oid_to_uuid($this->oid)) {
429
                        $ids[] = array('guid', $uuid, 'GUID representation of this OID');
430
                }
431
                $ids[] = array('guid', gen_uuid_md5_namebased(UUID_NAMEBASED_NS_OID, $this->oid), 'Namebased version 3 / MD5 UUID with namespace UUID_NAMEBASED_NS_OID');
432
                $ids[] = array('guid', gen_uuid_sha1_namebased(UUID_NAMEBASED_NS_OID, $this->oid), 'Namebased version 5 / SHA1 UUID with namespace UUID_NAMEBASED_NS_OID');
433
                return $ids;
192 daniel-mar 434
        }
2 daniel-mar 435
}