Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
990 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2022 - 2023 Daniel Marschall, ViaThinkSoft / Till Wehowski, Frdlweb
990 daniel-mar 6
 *
7
 * Licensed under the MIT License.
8
 */
9
 
1050 daniel-mar 10
namespace Frdlweb\OIDplus;
990 daniel-mar 11
 
1131 daniel-mar 12
use ViaThinkSoft\OIDplus\INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_4;
13
use ViaThinkSoft\OIDplus\INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_7;
1050 daniel-mar 14
use ViaThinkSoft\OIDplus\OIDplus;
15
use ViaThinkSoft\OIDplus\OIDplusObject;
16
use ViaThinkSoft\OIDplus\OIDplusPagePluginPublic;
17
 
1086 daniel-mar 18
// phpcs:disable PSR1.Files.SideEffects
19
\defined('INSIDE_OIDPLUS') or die;
20
// phpcs:enable PSR1.Files.SideEffects
21
 
1131 daniel-mar 22
class OIDplusPagePublicAltIds extends OIDplusPagePluginPublic
23
        implements INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_4, /* whois*Attributes */
24
                   INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_7  /* getAlternativesForQuery */
25
{
990 daniel-mar 26
 
1116 daniel-mar 27
        /**
28
         * @param string $actionID
29
         * @param array $params
30
         * @return array
31
         * @throws \ViaThinkSoft\OIDplus\OIDplusException
32
         */
33
        public function action(string $actionID, array $params): array {
34
                return parent::action($actionID, $params);
990 daniel-mar 35
        }
36
 
1116 daniel-mar 37
        /**
38
         * @param string $id
39
         * @param array $out
40
         * @param bool $handled
41
         * @return void
42
         */
43
        public function gui(string $id, array &$out, bool &$handled) {
990 daniel-mar 44
 
45
        }
46
 
1116 daniel-mar 47
        /**
48
         * @param array $out
49
         * @return void
50
         */
51
        public function publicSitemap(array &$out) {
990 daniel-mar 52
 
53
        }
54
 
1116 daniel-mar 55
        /**
56
         * @param array $json
57
         * @param string|null $ra_email
58
         * @param bool $nonjs
59
         * @param string $req_goto
60
         * @return bool
61
         */
62
        public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool {
990 daniel-mar 63
                return false;
64
        }
65
 
1116 daniel-mar 66
        /**
67
         * @return string|null
68
         * @throws \ViaThinkSoft\OIDplus\OIDplusException
69
         */
990 daniel-mar 70
        private function cache_id() {
71
                static $cache_id = null;
72
                if (!is_null($cache_id)) return $cache_id;
73
                $cache_id  =  'Create='.OIDplus::db()->getScalar("select max(created) as ts from ###objects where created is not null;");
74
                $cache_id .= '/Update='.OIDplus::db()->getScalar("select max(updated) as ts from ###objects where updated is not null;");
75
                $cache_id .= '/Count='.OIDplus::db()->getScalar("select count(id) as cnt from ###objects;");
76
                $plugin_versions = array();
77
                foreach (OIDplus::getObjectTypePluginsEnabled() as $otp) {
78
                        $plugin_versions[] = '/'.$otp->getManifest()->getOid().'='.$otp->getManifest()->getVersion();
79
                }
80
                sort($plugin_versions);
81
                $cache_id .= implode('',$plugin_versions);
82
                return $cache_id;
83
        }
84
 
1116 daniel-mar 85
        /**
1130 daniel-mar 86
         * @param bool $noCache
1116 daniel-mar 87
         * @return array[]|mixed|null
88
         * @throws \ViaThinkSoft\OIDplus\OIDplusException
89
         */
1130 daniel-mar 90
        public function readAll(bool $noCache = false) {
990 daniel-mar 91
                static $local_cache = null;
92
 
93
                $cache_file = OIDplus::localpath().'/userdata/cache/frdl_alt_id.ser';
94
                if ($noCache === false) {
95
                        // Local cache (to save time for multiple calls during the same HTTP request)
96
                        if (!is_null($local_cache)) return $local_cache;
97
 
98
                        // File cache (to save time between HTTP requests)
99
                        if (file_exists($cache_file)) {
100
                                $cache_data = unserialize(file_get_contents($cache_file));
101
                                $cache_id = $cache_data[0];
102
                                if ($cache_id == $this->cache_id()) {
103
                                        return $cache_data[1];
104
                                }
105
                        }
106
                }
107
 
108
                $alt_ids = array();
109
                $rev_lookup = array();
110
 
1445 daniel-mar 111
                $res = OIDplus::db()->query("select id from ###objects ".
112
                                            "where parent <> 'oid:1.3.6.1.4.1.37476.1.2.3.1'");  // TODO FIXME! readAll() is TOOOOO slow if a system has more than 50.000 OIDs!!! DEADLOCK!!!
990 daniel-mar 113
                while ($row = $res->fetch_array()) {
114
                        $obj = OIDplusObject::parse($row['id']);
115
                        if (!$obj) continue; // e.g. if plugin is disabled
116
                        $ary = $obj->getAltIds();
117
                        foreach ($ary as $a) {
118
                                $origin = $obj->nodeId(true);
119
                                $alternative = $a->getNamespace() . ':' . $a->getId();
120
 
121
                                if (!isset($alt_ids[$origin])) $alt_ids[$origin] = array();
122
                                $alt_ids[$origin][] = $alternative;
123
 
124
                                if (!isset($rev_lookup[$alternative])) $rev_lookup[$alternative] = array();
125
                                $rev_lookup[$alternative][] = $origin;
126
                        }
127
                }
128
 
129
                $data = array($alt_ids, $rev_lookup);
130
 
131
                // File cache (to save time between HTTP requests)
132
                $cache_data = array($this->cache_id(), $data);
133
                @file_put_contents($cache_file, serialize($cache_data));
134
 
135
                // Local cache (to save time for multiple calls during the same HTTP request)
136
                $local_cache = $data;
137
 
138
                return $data;
139
        }
140
 
1116 daniel-mar 141
        /**
1449 daniel-mar 142
         * Acts like in_array(), but allows includes prefilterQuery, e.g. `mac:AA-BB-CC-DD-EE-FF` can be found in an array containing `mac:AABBCCDDEEFF`.
143
         * @param string $needle
144
         * @param array $haystack
145
         * @return bool
146
         */
147
        private static function special_in_array(string $needle, array $haystack) {
148
                $needle_prefiltered = OIDplus::prefilterQuery($needle,false);
149
                foreach ($haystack as $straw) {
150
                        $straw_prefiltered = OIDplus::prefilterQuery($straw, false);
151
                        if ($needle == $straw) return true;
152
                        else if ($needle == $straw_prefiltered) return true;
153
                        else if ($needle_prefiltered == $straw) return true;
154
                        else if ($needle_prefiltered == $straw_prefiltered) return true;
155
                }
156
                return false;
157
        }
158
 
159
        /**
1130 daniel-mar 160
         * @param string $id
1131 daniel-mar 161
         * @return string[]
1116 daniel-mar 162
         * @throws \ViaThinkSoft\OIDplus\OIDplusException
163
         */
1131 daniel-mar 164
        public function getAlternativesForQuery(string $id/* INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_7 signature takes just 1 param!? , $noCache = false*/): array {
990 daniel-mar 165
 
166
                static $caches = array();
167
 
168
                if(/*$noCache === false && */isset($caches[$id]) ){
169
                        return $caches[$id];
170
                }
171
 
1008 daniel-mar 172
                if (strpos($id,':') !== false) {
173
                        list($ns, $altIdRaw) = explode(':', $id, 2);
174
                        if($ns === 'weid'){
1050 daniel-mar 175
                                $id='oid:'.\Frdl\Weid\WeidOidConverter::weid2oid($id);
1008 daniel-mar 176
                        }
990 daniel-mar 177
                }
178
 
179
                list($alt_ids, $rev_lookup) = $this->readAll(false);
180
 
181
                $res = [
182
                        $id,
183
                ];
184
                if(isset($rev_lookup[$id])){
185
                        $res = array_merge($res, $rev_lookup[$id]);
186
                }
187
                foreach($alt_ids as $original => $altIds){
1449 daniel-mar 188
                        // Why self::special_in_array() instead of in_array()? Consider the following testcase:
189
                        // "oid:1.3.6.1.4.1.37553.8.8.2" defines alt ID "mac:63-CF-E4-AE-C5-66" which is NOT canonized!
190
                        // You must be able to enter "mac:63-CF-E4-AE-C5-66" in the search box, which gets canonized
191
                        // to mac:63CFE4AEC566 and must be solved to "oid:1.3.6.1.4.1.37553.8.8.2" by this plugin.
192
                        // Therefore we use self::special_in_array().
193
                        // However, it is mandatory, that previously saveAltIdsForQuery("oid:1.3.6.1.4.1.37553.8.8.2") was called once!
194
                        // Please also note that the "weid:" to "oid:" converting is handled by prefilterQuery(), but only if the OID plugin is installed.
195
                        if($id === $original || self::special_in_array($id, $altIds) ){
990 daniel-mar 196
                                 $res = array_merge($res, $altIds);
197
                                 $res = array_merge($res, [$original]);
198
                        }
199
                }
200
 
201
                $weid = false;
202
                foreach($res as $alt){
1008 daniel-mar 203
                        if (strpos($alt,':') !== false) {
204
                                list($ns, $altIdRaw) = explode(':', $alt, 2);
205
                                if($ns === 'oid'){
1050 daniel-mar 206
                                        $weid=\Frdl\Weid\WeidOidConverter::oid2weid($altIdRaw);
1008 daniel-mar 207
                                        break;
208
                                }
990 daniel-mar 209
                        }
210
                }
211
 
212
                if ($weid !== false) {
213
                        $res[]=$weid;
214
                }
215
                $res = array_unique($res);
216
 
217
                $caches[$id] = $res;
218
 
219
                return $res;
220
        }
221
 
1116 daniel-mar 222
        /**
223
         * @param string $request
224
         * @return array|false
225
         */
226
        public function tree_search(string $request) {
990 daniel-mar 227
                return false;
228
        }
229
 
1116 daniel-mar 230
        /**
1130 daniel-mar 231
         * @param string $id
1116 daniel-mar 232
         * @return false|mixed|string
233
         * @throws \ViaThinkSoft\OIDplus\OIDplusException
234
         */
1130 daniel-mar 235
        public function getCanonical(string $id){
990 daniel-mar 236
                foreach($this->getAlternativesForQuery($id) as $alt){
1008 daniel-mar 237
                        if (strpos($alt,':') !== false) {
238
                                list($ns, $altIdRaw) = explode(':', $alt, 2);
239
                                if($ns === 'oid'){
240
                                        return $alt;
241
                                }
990 daniel-mar 242
                        }
243
                }
244
 
245
                return false;
246
        }
247
 
1116 daniel-mar 248
        /**
1131 daniel-mar 249
         * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_4
1130 daniel-mar 250
         * @param string $id
251
         * @param array $out
1116 daniel-mar 252
         * @return void
253
         * @throws \ViaThinkSoft\OIDplus\OIDplusException
254
         */
1130 daniel-mar 255
        public function whoisObjectAttributes(string $id, array &$out) {
990 daniel-mar 256
                $xmlns = 'oidplus-frdlweb-altids-plugin';
257
                $xmlschema = 'urn:oid:1.3.6.1.4.1.37553.8.1.8.8.53354196964.641310544.1714020422';
1375 daniel-mar 258
                $xmlschemauri = OIDplus::webpath(__DIR__.'/altids.xsd',OIDplus::PATH_ABSOLUTE_CANONICAL);
990 daniel-mar 259
 
260
                $handleShown = false;
261
                $canonicalShown = false;
262
 
1135 daniel-mar 263
                $out1 = array();
264
                $out2 = array();
990 daniel-mar 265
 
1135 daniel-mar 266
                $tmp = $this->getAlternativesForQuery($id);
267
                sort($tmp); // DM 26.03.2023 : Added sorting (intended to sort "alternate-identifier")
1445 daniel-mar 268
 
1135 daniel-mar 269
                foreach($tmp as $alt) {
1040 daniel-mar 270
                        if (strpos($alt,':') === false) continue;
1008 daniel-mar 271
 
990 daniel-mar 272
                        list($ns, $altIdRaw) = explode(':', $alt, 2);
273
 
1445 daniel-mar 274
                        if (($canonicalShown === false) && ($ns === 'oid')) {
990 daniel-mar 275
                                $canonicalShown=true;
276
 
1135 daniel-mar 277
                                $out1[] = [
990 daniel-mar 278
                                        'xmlns' => $xmlns,
279
                                        'xmlschema' => $xmlschema,
280
                                        'xmlschemauri' => $xmlschemauri,
281
                                        'name' => 'canonical-identifier',
282
                                        'value' => $ns.':'.$altIdRaw,
283
                                ];
284
 
285
                        }
286
 
287
                        if (($handleShown === false) && ($alt === $id)) {
288
                                $handleShown=true;
289
 
1135 daniel-mar 290
                                $out1[] = [
990 daniel-mar 291
                                        'xmlns' => $xmlns,
292
                                        'xmlschema' => $xmlschema,
293
                                        'xmlschemauri' => $xmlschemauri,
294
                                        'name' => 'handle-identifier',
295
                                        'value' => $alt,
296
                                ];
297
 
298
                        }
299
 
1135 daniel-mar 300
                        if ($alt !== $id) { // DM 26.03.2023 : Added condition that alternate must not be the id itself
301
                                $out2[] = [
302
                                        'xmlns' => $xmlns,
303
                                        'xmlschema' => $xmlschema,
304
                                        'xmlschemauri' => $xmlschemauri,
305
                                        'name' => 'alternate-identifier',
306
                                        'value' => $ns.':'.$altIdRaw,
307
                                ];
308
                        }
990 daniel-mar 309
 
310
                }
1135 daniel-mar 311
 
312
                // DM 26.03.2023 : Added this
313
                $out = array_merge($out, $out1); // handle-identifier and canonical-identifier
314
                $out = array_merge($out, $out2); // alternate-identifier
315
 
990 daniel-mar 316
        }
317
 
1116 daniel-mar 318
        /**
1131 daniel-mar 319
         * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_4
1130 daniel-mar 320
         * @param string $email
321
         * @param array $out
1116 daniel-mar 322
         * @return void
323
         */
1130 daniel-mar 324
        public function whoisRaAttributes(string $email, array &$out) {
1116 daniel-mar 325
 
990 daniel-mar 326
        }
327
 
328
 }