Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
635 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
635 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;
635 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
 
1131 daniel-mar 26
class OIDplusPageAdminRegistration extends OIDplusPagePluginAdmin
27
        implements INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1, /* oobeRequested, oobeEntry */
28
                   INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8  /* getNotifications */
29
{
635 daniel-mar 30
 
1130 daniel-mar 31
        /**
32
         *
33
         */
635 daniel-mar 34
        /*private*/ const QUERY_REGISTER_V1 =         '1.3.6.1.4.1.37476.2.5.2.1.1.1';
1130 daniel-mar 35
 
36
        /**
37
         *
38
         */
635 daniel-mar 39
        /*private*/ const QUERY_UNREGISTER_V1 =       '1.3.6.1.4.1.37476.2.5.2.1.2.1';
1130 daniel-mar 40
 
41
        /**
42
         *
43
         */
635 daniel-mar 44
        /*private*/ const QUERY_LISTALLSYSTEMIDS_V1 = '1.3.6.1.4.1.37476.2.5.2.1.3.1';
1130 daniel-mar 45
 
46
        /**
47
         *
48
         */
635 daniel-mar 49
        /*private*/ const QUERY_LIVESTATUS_V1 =       '1.3.6.1.4.1.37476.2.5.2.1.4.1';
50
 
1116 daniel-mar 51
        /**
52
         * @param string $actionID
53
         * @return bool
54
         */
55
        public function csrfUnlock(string $actionID): bool {
635 daniel-mar 56
                if ($actionID == 'verify_pubkey') return true;
57
                return parent::csrfUnlock($actionID);
58
        }
59
 
1116 daniel-mar 60
        /**
61
         * @param string $actionID
62
         * @param array $params
63
         * @return array
64
         * @throws OIDplusException
65
         */
66
        public function action(string $actionID, array $params): array {
635 daniel-mar 67
                if ($actionID == 'verify_pubkey') {
68
                        _CheckParamExists($params, 'challenge');
69
 
70
                        $payload = 'oidplus-verify-pubkey:'.sha3_512($params['challenge']);
71
 
72
                        $signature = '';
830 daniel-mar 73
                        if (!OIDplus::getPkiStatus() || !@openssl_sign($payload, $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 74
                                throw new OIDplusException(_L('Signature failed'));
75
                        }
76
 
77
                        return array(
78
                                "status" => 0,
79
                                "response" => base64_encode($signature)
80
                        );
81
                } else {
1116 daniel-mar 82
                        return parent::action($actionID, $params);
635 daniel-mar 83
                }
84
        }
85
 
1116 daniel-mar 86
        /**
87
         * @param string $id
88
         * @param array $out
89
         * @param bool $handled
90
         * @return void
91
         * @throws OIDplusConfigInitializationException
92
         * @throws OIDplusException
93
         */
94
        public function gui(string $id, array &$out, bool &$handled) {
635 daniel-mar 95
                if ($id === 'oidplus:srv_registration') {
96
                        $handled = true;
97
                        $out['title'] = _L('System registration settings');
801 daniel-mar 98
                        $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
635 daniel-mar 99
 
100
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
800 daniel-mar 101
                                $out['icon'] = 'img/error.png';
635 daniel-mar 102
                                $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
103
                                return;
104
                        }
105
 
106
                        if (file_exists(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html')) {
107
                                $info = file_get_contents(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html');
108
                        } else {
109
                                $info = file_get_contents(__DIR__ . '/info.html');
110
                        }
111
 
112
                        list($html, $js, $css) = extractHtmlContents($info);
113
                        $info = '';
114
                        if (!empty($js))  $info .= "<script>\n$js\n</script>";
115
                        if (!empty($css)) $info .= "<style>\n$css\n</style>";
821 daniel-mar 116
                        $info .= stripHtmlComments($html);
635 daniel-mar 117
 
118
                        $out['text'] = $info;
119
 
120
                        if (!OIDplus::getPkiStatus()) {
121
                                $out['text'] .= '<p><font color="red">'._L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.').'</font></p>';
122
                        } else {
123
                                $out['text'] .= '<p><input type="button" onclick="openOidInPanel(\'oidplus:srvreg_status\');" value="'._L('Check status of the registration and collected data').'"></p>';
124
 
125
                                if (OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) {
126
                                        $out['text'] .= '<p><font color="red"><b>'._L('Attention!').'</b> '._L('<code>REGISTRATION_HIDE_SYSTEM</code> is set in the local configuration file! Therefore, this system will not register itself, despite of the settings below.').'</font></p>';
127
                                }
128
 
129
                                $out['text'] .= '<p>'._L('You can adjust your privacy level here').':</p><p><select name="reg_privacy" id="reg_privacy">';
130
 
131
                                # ---
132
 
133
                                $out['text'] .= '<option value="0"';
134
                                if (OIDplus::config()->getValue('reg_privacy') == 0) {
135
                                        $out['text'] .= ' selected';
136
                                } else {
137
                                        $out['text'] .= '';
138
                                }
139
                                $out['text'] .= '>'._L('0 = Register to directory service and automatically publish RA/OID data at oid-info.com').'</option>';
140
 
141
                                # ---
142
 
143
                                $out['text'] .= '<option value="1"';
144
                                if (OIDplus::config()->getValue('reg_privacy') == 1) {
145
                                        $out['text'] .= ' selected';
146
                                } else {
147
                                        $out['text'] .= '';
148
                                }
149
                                $out['text'] .= '>'._L('1 = Only register to directory service').'</option>';
150
 
151
                                # ---
152
 
153
                                $out['text'] .= '<option value="2"';
154
                                if (OIDplus::config()->getValue('reg_privacy') == 2) {
155
                                        $out['text'] .= ' selected';
156
                                } else {
157
                                        $out['text'] .= '';
158
                                }
159
                                $out['text'] .= '>'._L('2 = Hide system').'</option>';
160
 
161
                                # ---
162
 
163
                                $out['text'] .= '</select> <input type="button" value="'._L('Change').'" onclick="OIDplusPageAdminRegistration.crudActionRegPrivacyUpdate()"></p>';
164
 
165
                                $out['text'] .= '<p>'._L('After clicking "change", your OIDplus system will contact the ViaThinkSoft server to adjust (add or remove information) your privacy setting. This may take a few minutes.').'</p>';
166
 
167
                                $out['text'] .= '<p>'._L('<i>Privacy information:</i> Please note that removing your system from the directory does not automatically delete information about OIDs which are already published at oid-info.com. To remove already submitted OIDs at oid-info.com, please contact the <a href="mailto:admin@oid-info.com">OID Repository Webmaster</a>.').'</p>';
168
                        }
169
                }
170
                if ($id === 'oidplus:srvreg_status') {
171
                        $handled = true;
172
                        $out['title'] = _L('Registration live status');
801 daniel-mar 173
                        $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
635 daniel-mar 174
 
175
                        if (!OIDplus::authUtils()->isAdminLoggedIn()) {
800 daniel-mar 176
                                $out['icon'] = 'img/error.png';
635 daniel-mar 177
                                $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
178
                                return;
179
                        }
180
 
181
                        $query = self::QUERY_LIVESTATUS_V1;
182
 
183
                        $payload = array(
777 daniel-mar 184
                                "query" => $query, // we must include $query to the playload, because we want to sign it
635 daniel-mar 185
                                "lang" => OIDplus::getCurrentLang(),
186
                                "system_id" => OIDplus::getSystemId(false)
187
                        );
188
 
189
                        $signature = '';
830 daniel-mar 190
                        if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 191
                                throw new OIDplusException(_L('Signature failed'));
192
                        }
193
 
194
                        $data = array(
195
                                "payload" => $payload,
196
                                "signature" => base64_encode($signature)
197
                        );
198
 
199
                        if (function_exists('gzdeflate')) {
200
                                $compressed = "1";
201
                                $data2 = gzdeflate(json_encode($data));
202
                        } else {
203
                                $compressed = "0";
204
                                $data2 = json_encode($data);
205
                        }
1149 daniel-mar 206
 
207
                        $res = url_post_contents(
208
                                'https://oidplus.viathinksoft.com/reg2/query.php',
209
                                array(
210
                                        "query"      => $query,
211
                                        "compressed" => $compressed,
212
                                        "data"       => base64_encode($data2)
213
                                )
214
                        );
215
 
216
                        if ($res === false) {
217
                                throw new OIDplusException(_L('Communication with %1 server failed', 'ViaThinkSoft'));
635 daniel-mar 218
                        }
219
 
220
                        $json = @json_decode($res, true);
221
 
222
                        if (!$json) {
800 daniel-mar 223
                                $out['icon'] = 'img/error.png';
635 daniel-mar 224
                                $out['text'] = _L('JSON reply from ViaThinkSoft decoding error: %1',$res);
225
                                return;
226
                        }
227
 
228
                        if (isset($json['error']) || ($json['status'] < 0)) {
800 daniel-mar 229
                                $out['icon'] = 'img/error.png';
635 daniel-mar 230
                                if (isset($json['error'])) {
231
                                        $out['text'] = _L('Received error status code: %1',$json['error']);
232
                                } else {
233
                                        $out['text'] = _L('Received error status code: %1',$json['status']);
234
                                }
235
                                return;
236
                        }
237
 
238
                        $out['text']  = '<p><a '.OIDplus::gui()->link('oidplus:srv_registration').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to registration settings').'</a></p>' .
239
                                        $json['content'];
240
                }
241
        }
242
 
1116 daniel-mar 243
        /**
244
         * @return bool
245
         * @throws OIDplusException
246
         */
247
        protected function areWeRegistered(): bool {
635 daniel-mar 248
                // To check if we are registered. Check it "anonymously" (i.e. without revealing our system ID)
715 daniel-mar 249
                $res = url_get_contents('https://oidplus.viathinksoft.com/reg2/query.php?query='.self::QUERY_LISTALLSYSTEMIDS_V1);
1149 daniel-mar 250
                if ($res === false) return false;
635 daniel-mar 251
 
252
                $json = @json_decode($res, true);
253
 
254
                if (!$json) {
255
                        return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res));
256
                }
257
 
258
                if (isset($json['error']) || ($json['status'] < 0)) {
259
                        if (isset($json['error'])) {
260
                                return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error']));
261
                        } else {
262
                                return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status']));
263
                        }
264
                }
265
 
266
                $list = $json['list'];
267
 
268
                return in_array(OIDplus::getSystemId(false), $list);
269
        }
270
 
1116 daniel-mar 271
        /**
1130 daniel-mar 272
         * @param int|null $privacy_level
1116 daniel-mar 273
         * @return false|void
1130 daniel-mar 274
         * @throws OIDplusException|\OIDInfoException
1116 daniel-mar 275
         */
1130 daniel-mar 276
        public function sendRegistrationQuery(int $privacy_level=null) {
1029 daniel-mar 277
 
635 daniel-mar 278
                if (is_null($privacy_level)) {
279
                        $privacy_level = OIDplus::config()->getValue('reg_privacy');
280
                }
281
 
801 daniel-mar 282
                $system_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL);
635 daniel-mar 283
 
284
                // It is very important that we set the ping time NOW, because ViaThinkSoft might contact us during the ping,
285
                // and this would cause an endless loop!
286
                OIDplus::config()->setValue('reg_last_ping', time());
287
 
288
                if (!OIDplus::getPkiStatus()) return false;
289
 
290
                if ($privacy_level == 2) {
291
                        // The user wants to unregister,  but we only unregister if we are registered
292
                        if ($this->areWeRegistered()) {
293
                                $query = self::QUERY_UNREGISTER_V1;
294
 
295
                                $payload = array(
777 daniel-mar 296
                                        "query" => $query, // we must include $query to the payload, because we want to sign it
635 daniel-mar 297
                                        "system_id" => OIDplus::getSystemId(false)
298
                                );
299
 
300
                                $signature = '';
830 daniel-mar 301
                                if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 302
                                        return false; // throw new OIDplusException(_L('Signature failed'));
303
                                }
304
 
305
                                $data = array(
306
                                        "payload" => $payload,
307
                                        "signature" => base64_encode($signature)
308
                                );
309
 
310
                                if (function_exists('gzdeflate')) {
311
                                        $compressed = "1";
312
                                        $data2 = gzdeflate(json_encode($data));
313
                                } else {
314
                                        $compressed = "0";
315
                                        $data2 = json_encode($data);
316
                                }
317
 
1149 daniel-mar 318
                                $res = url_post_contents(
319
                                        'https://oidplus.viathinksoft.com/reg2/query.php',
320
                                        array(
321
                                                "query"      => $query,
322
                                                "compressed" => $compressed,
323
                                                "data"       => base64_encode($data2)
324
                                        )
325
                                );
326
 
327
                                if ($res === false) return false; // throw new OIDplusException(_L('Communication with %1 server failed', 'ViaThinkSoft'));
328
 
635 daniel-mar 329
                                $json = @json_decode($res, true);
330
 
331
                                if (!$json) {
332
                                        return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res));
333
                                }
334
 
335
                                if (isset($json['error']) || ($json['status'] < 0)) {
1116 daniel-mar 336
                                        return false; // throw new OIDplusException(_L('Received error status code: %1',isset($json['error']) ? $json['error'] : $json['status']));
635 daniel-mar 337
                                }
338
                        }
339
                } else {
340
                        if ($privacy_level == 0) {
341
                                $adminExportPlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.3.400'); // OIDplusPageAdminOIDInfoExport
342
                                if (!is_null($adminExportPlugin)) {
941 daniel-mar 343
                                        list($oidinfo_xml, $dummy_content_type) = OIDplusPageAdminOIDInfoExport::outputXML(false); // no online check, because the query should be short (since the query is done while a visitor waits for the response)
635 daniel-mar 344
                                } else {
345
                                        $oidinfo_xml = false;
346
                                }
347
                        } else {
348
                                $oidinfo_xml = false;
349
                        }
350
 
351
                        $query = self::QUERY_REGISTER_V1;
352
 
353
                        $root_oids = array();
354
                        foreach (OIDplus::getEnabledObjectTypes() as $ot) {
355
                                if ($ot::ns() == 'oid') {
356
                                        $res = OIDplus::db()->query("select id from ###objects where " .
357
                                                                    "(parent = 'oid:' or " .
358
                                                                    // The following two cases are special cases e.g. if there are multiple PEN or UUID-OIDs, and the system owner decides to use the IANA PEN as root OID, but actually, it is not "his" root then! The OIDs inside the IANA PEN root are his root then!
359
                                                                    "parent in (select oid from ###asn1id where well_known = ?) or " .
360
                                                                    "parent in (select oid from ###iri where well_known = ?)) and " .
361
                                                                    // We assume hereby that RAs of well-known OIDs (e.g. IANA) will not use OIDplus for allocating OIDs:
362
                                                                    "id not in (select oid from ###asn1id where well_known = ?) and " .
1148 daniel-mar 363
                                                                    "id not in (select oid from ###iri where well_known = ?)", array(true, true, true, true));
364
                                        $res = new OIDplusNaturalSortedQueryResult($res, 'id');
635 daniel-mar 365
                                        while ($row = $res->fetch_array()) {
366
                                                $root_oids[] = substr($row['id'],strlen('oid:'));
367
                                        }
368
                                }
369
                        }
370
                        $payload = array(
777 daniel-mar 371
                                "query" => $query, // we must include $query to the payload, because we want to sign it
635 daniel-mar 372
                                "privacy_level" => $privacy_level,
373
                                "system_id" => OIDplus::getSystemId(false),
830 daniel-mar 374
                                "public_key" => OIDplus::getSystemPublicKey(),
635 daniel-mar 375
                                "system_url" => $system_url,
376
                                "hide_system_url" => 0,
377
                                "hide_public_key" => 0,
378
                                "admin_email" => OIDplus::config()->getValue('admin_email'),
379
                                "system_title" => OIDplus::config()->getValue('system_title'),
380
                                "oidinfo_xml" => @base64_encode($oidinfo_xml),
381
                                "root_oids" => $root_oids,
382
                                "system_version" => OIDplus::getVersion(),
383
                                "system_install_type" => OIDplus::getInstallType()
384
                        );
385
 
386
                        $signature = '';
830 daniel-mar 387
                        if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) {
635 daniel-mar 388
                                return false; // throw new OIDplusException(_L('Signature failed'));
389
                        }
390
 
391
                        $data = array(
392
                                "payload" => $payload,
393
                                "signature" => base64_encode($signature)
394
                        );
395
 
396
                        if (function_exists('gzdeflate')) {
397
                                $compressed = "1";
398
                                $data2 = gzdeflate(json_encode($data));
399
                        } else {
400
                                $compressed = "0";
401
                                $data2 = json_encode($data);
402
                        }
403
 
1149 daniel-mar 404
                        $res = url_post_contents(
405
                                'https://oidplus.viathinksoft.com/reg2/query.php',
406
                                array(
407
                                        "query"      => $query,
408
                                        "compressed" => $compressed,
409
                                        "data"       => base64_encode($data2)
410
                                )
411
                        );
412
 
413
                        if ($res === false) return false; // throw new OIDplusException(_L('Communication with %1 server failed', 'ViaThinkSoft'));
414
 
635 daniel-mar 415
                        $json = @json_decode($res, true);
416
 
417
                        if (!$json) {
418
                                return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res));
419
                        }
420
 
421
                        if (isset($json['error']) || ($json['status'] < 0)) {
422
                                if (isset($json['error'])) {
423
                                        return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error']));
424
                                } else {
425
                                        return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status']));
426
                                }
427
                        } else if ($json['status'] == 99/*Hash conflict*/) {
428
                                OIDplus::logger()->log("[WARN]A!", "Removing SystemID and key pair because there is a hash conflict with another OIDplus system!");
429
 
430
                                // Delete the system ID since we have a conflict with the 31-bit hash!
431
                                OIDplus::config()->setValue('oidplus_private_key', '');
432
                                OIDplus::config()->setValue('oidplus_public_key', '');
433
 
434
                                // Try to generate a new system ID
435
                                OIDplus::getPkiStatus(true);
436
 
437
                                // Enforce a new registration attempt at the next page visit
438
                                // We will not try again here, because that might lead to an endless loop if the VTS server would always return 'HASH_CONFLCIT'
439
                                OIDplus::config()->setValue('reg_last_ping', 0);
776 daniel-mar 440
                        } else if ($json['status'] == 0/*OK*/) {
441
                                // Note: whois.viathinksoft.de:43 uses VGWhoIs, which uses these patterns: https://github.com/danielmarschall/vgwhois/blob/master/main/pattern/oid
442
                                // If your system gets acknowledged by ViaThinkSoft, then vts_whois will be filled with that server name whois.viathinksoft.de:43
443
                                if (isset($json['vts_whois'])) OIDplus::config()->setValue('vts_whois', $json['vts_whois']);
444
 
445
                                // ViaThinkSoft certifies the system public key and other system attributes and root objects (requires human verification)
446
                                if (isset($json['vts_cert'])) OIDplus::config()->setValue('vts_cert', $json['vts_cert']);
447
                                if (isset($json['vts_ca'])) OIDplus::config()->setValue('vts_ca', $json['vts_ca']);
635 daniel-mar 448
                        }
449
                }
450
        }
451
 
1116 daniel-mar 452
        /**
453
         * @param bool $html
454
         * @return void
455
         * @throws OIDplusException
456
         */
457
        public function init(bool $html=true) {
699 daniel-mar 458
                if (OIDplus::getEditionInfo()['vendor'] != 'ViaThinkSoft') {
459
                        throw new OIDplusException(_L('This plugin is only available in the ViaThinkSoft edition of OIDplus'));
460
                }
461
 
635 daniel-mar 462
                // Note: It is important that the default value is '2', otherwise, systems which don't have CURL will fail
463
                OIDplus::config()->prepareConfigKey('reg_privacy', '2=Hide your system, 1=Register your system to the ViaThinkSoft directory and oid-info.com, 0=Publish your system to ViaThinkSoft directory and all public contents (RA/OID) to oid-info.com', '2', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
464
                        if (($value != '0') && ($value != '1') && ($value != '2')) {
465
                                throw new OIDplusException(_L('Please enter either 0, 1 or 2.'));
466
                        }
467
                        // Now do a recheck and notify the ViaThinkSoft server
468
                        if (($value == 2) || !OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) {
469
                                OIDplus::config()->setValue('reg_last_ping', 0);
470
                                $this->sendRegistrationQuery($value);
471
                        }
472
                });
473
                OIDplus::config()->prepareConfigKey('reg_ping_interval', 'Registration ping interval (in seconds)', '3600', OIDplusConfig::PROTECTION_HIDDEN, function($value) {
474
 
475
                });
476
                OIDplus::config()->prepareConfigKey('reg_last_ping', 'Last ping to ViaThinkSoft directory services', '0', OIDplusConfig::PROTECTION_HIDDEN, function($value) {
477
 
478
                });
776 daniel-mar 479
                OIDplus::config()->prepareConfigKey('vts_whois', 'ViaThinkSoft Whois Server (if this system is recognized)', '', OIDplusConfig::PROTECTION_READONLY, function($value) {
480
 
481
                });
482
                OIDplus::config()->prepareConfigKey('vts_cert', 'ViaThinkSoft certificate (requires registration)', '', OIDplusConfig::PROTECTION_HIDDEN, function($value) {
483
 
484
                });
485
                OIDplus::config()->prepareConfigKey('vts_ca', 'ViaThinkSoft certificate root (requires registration)', '', OIDplusConfig::PROTECTION_HIDDEN, function($value) {
486
 
487
                });
635 daniel-mar 488
                OIDplus::config()->prepareConfigKey('oobe_registration_done', '"Out Of Box Experience" wizard for OIDplusPageAdminRegistration done once?', '0', OIDplusConfig::PROTECTION_HIDDEN, function($value) {});
489
 
490
                // Is it time to register / renew the directory entry?
491
                // Note: REGISTRATION_HIDE_SYSTEM is an undocumented constant that can be put in the userdata/baseconfig/config.inc.php files of a test system accessing the same database as the productive system that is registered.
492
                // This avoids that the URL of a productive system is overridden with the URL of a cloned test system (since they use the same database, they also have the same system ID)
493
 
494
                if (OIDplus::config()->getValue('oobe_registration_done') == '1') {
495
                        if (!OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) {
496
                                $privacy_level = OIDplus::config()->getValue('reg_privacy');
497
 
498
                                if (PHP_SAPI !== 'cli') { // don't register when called from CLI, otherwise the oidinfo XML can't convert relative links into absolute links
786 daniel-mar 499
                                        $last_ping = OIDplus::config()->getValue('reg_last_ping');
500
                                        if (!is_numeric($last_ping)) $last_ping = 0;
501
                                        $last_ping_interval = OIDplus::config()->getValue('reg_ping_interval');
502
                                        if (!is_numeric($last_ping_interval)) $last_ping_interval = 3600;
852 daniel-mar 503
 
504
                                        // Cronjobs get half ping interval, to make sure that a web visitor won't get any delay
505
                                        if (OIDplus::isCronjob()) $last_ping_interval /= 2;
506
 
786 daniel-mar 507
                                        if ((time()-$last_ping >= $last_ping_interval)) {
635 daniel-mar 508
                                                $this->sendRegistrationQuery();
509
                                        }
510
                                }
511
                        }
512
                }
513
        }
514
 
1116 daniel-mar 515
        /**
516
         * @param array $json
517
         * @param string|null $ra_email
518
         * @param bool $nonjs
519
         * @param string $req_goto
520
         * @return bool
521
         * @throws OIDplusException
522
         */
523
        public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool {
635 daniel-mar 524
                if (!OIDplus::authUtils()->isAdminLoggedIn()) return false;
525
 
800 daniel-mar 526
                if (file_exists(__DIR__.'/img/main_icon16.png')) {
801 daniel-mar 527
                        $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png';
635 daniel-mar 528
                } else {
529
                        $tree_icon = null; // default icon (folder)
530
                }
531
 
532
                $json[] = array(
533
                        'id' => 'oidplus:srv_registration',
534
                        'icon' => $tree_icon,
535
                        'text' => _L('System registration')
536
                );
537
 
538
                return true;
539
        }
540
 
1116 daniel-mar 541
        /**
542
         * @param string $request
543
         * @return array|false
544
         */
545
        public function tree_search(string $request) {
635 daniel-mar 546
                return false;
547
        }
548
 
1116 daniel-mar 549
        /**
1131 daniel-mar 550
         * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1
1116 daniel-mar 551
         * @return bool
552
         * @throws OIDplusException
553
         */
635 daniel-mar 554
        public function oobeRequested(): bool {
555
                return OIDplus::config()->getValue('oobe_registration_done') == '0';
556
        }
557
 
1116 daniel-mar 558
        /**
1131 daniel-mar 559
         * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1
1125 daniel-mar 560
         * @param int $step
561
         * @param bool $do_edits
562
         * @param bool $errors_happened
1116 daniel-mar 563
         * @return void
564
         * @throws OIDplusConfigInitializationException
565
         * @throws OIDplusException
566
         */
1125 daniel-mar 567
        public function oobeEntry(int $step, bool $do_edits, bool &$errors_happened)/*: void*/ {
1055 daniel-mar 568
                echo '<h2>'._L('Step %1: System registration and automatic publishing (optional)',$step).'</h2>';
635 daniel-mar 569
 
570
                if (file_exists(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html')) {
571
                        $info = file_get_contents(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html');
572
                } else {
573
                        $info = file_get_contents(__DIR__ . '/info.html');
574
                }
575
 
576
                // make sure the program works even if the user provided HTML is not UTF-8
721 daniel-mar 577
                $info = convert_to_utf8_no_bom($info);
635 daniel-mar 578
 
579
                echo $info;
580
 
1149 daniel-mar 581
                if (!url_post_contents_available()) {
635 daniel-mar 582
                        echo '<p><font color="red">';
583
                        echo _L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl').' ';
584
                        echo _L('Therefore, you <b>cannot</b> register your OIDplus instance now.');
585
                        echo '</font></p>';
586
                        if ($do_edits) {
587
                                OIDplus::config()->setValue('oobe_registration_done', '1');
588
                        }
589
                        return;
590
                }
591
 
592
                $pki_status = OIDplus::getPkiStatus();
593
 
594
                if (!$pki_status) {
595
                        echo '<p><font color="red">';
596
                        echo _L('Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system).').' ';
597
                        echo _L('Therefore, you <b>cannot</b> register your OIDplus instance now.');
598
                        echo '</font></p>';
599
                        if ($do_edits) {
600
                                OIDplus::config()->setValue('oobe_registration_done', '1');
601
                        }
602
                        return;
603
                }
604
 
605
                echo '<p>'._L('Privacy level').':</p><select name="reg_privacy" id="reg_privacy">';
606
 
607
                # ---
608
 
609
                echo '<option value="0"';
1033 daniel-mar 610
                if (isset($_POST['sent'])) {
611
                        if (isset($_POST['reg_privacy']) && ($_POST['reg_privacy'] == 0)) echo ' selected';
635 daniel-mar 612
                } else {
613
                        if ((OIDplus::config()->getValue('reg_privacy') == 0) || !OIDplus::config()->getValue('oobe_registration_done')) {
614
                                echo ' selected';
615
                        } else {
616
                                echo '';
617
                        }
618
                }
619
                echo '>'._L('0 = Register to directory service and automatically publish RA/OID data at oid-info.com').'</option>';
620
 
621
                # ---
622
 
623
                echo '<option value="1"';
1033 daniel-mar 624
                if (isset($_POST['sent'])) {
625
                        if (isset($_POST['reg_privacy']) && ($_POST['reg_privacy'] == 1)) echo ' selected';
635 daniel-mar 626
                } else {
627
                        if ((OIDplus::config()->getValue('reg_privacy') == 1)) {
628
                                echo ' selected';
629
                        } else {
630
                                echo '';
631
                        }
632
                }
633
                echo '>'._L('1 = Only register to directory service').'</option>';
634
 
635
                # ---
636
 
637
                echo '<option value="2"';
1033 daniel-mar 638
                if (isset($_POST['sent'])) {
639
                        if (isset($_POST['reg_privacy']) && ($_POST['reg_privacy'] == 2)) echo ' selected';
635 daniel-mar 640
                } else {
641
                        if ((OIDplus::config()->getValue('reg_privacy') == 2)) {
642
                                echo ' selected';
643
                        } else {
644
                                echo '';
645
                        }
646
                }
647
                echo '>'._L('2 = Hide system').'</option>';
648
 
649
                # ---
650
 
651
                echo '</select>';
652
 
653
                $msg = '';
654
                if ($do_edits) {
655
                        try {
1130 daniel-mar 656
                                OIDplus::config()->setValue('reg_privacy', $_POST['reg_privacy'] ?? 1);
635 daniel-mar 657
                                OIDplus::config()->setValue('oobe_registration_done', '1');
1050 daniel-mar 658
                        } catch (\Exception $e) {
635 daniel-mar 659
                                $msg = $e->getMessage();
660
                                $errors_happened = true;
661
                        }
662
                }
1029 daniel-mar 663
                if (!empty($msg)) echo ' <font color="red"><b>'.$msg.'</b></font>';
635 daniel-mar 664
 
665
                echo '<p>'._L('<i>Privacy information:</i> This setting can always be changed in the administrator login / control panel.').'<br>';
666
                echo _L('<a %1>Click here</a> for more information about privacy related topics.','href="../../../../res/OIDplus/privacy_documentation.html" target="_blank"');
667
                echo '</p>';
668
        }
669
 
1116 daniel-mar 670
        /**
1131 daniel-mar 671
         * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8
1125 daniel-mar 672
         * @param string|null $user
1116 daniel-mar 673
         * @return array
674
         * @throws OIDplusException
675
         */
1125 daniel-mar 676
        public function getNotifications(string $user=null): array {
1000 daniel-mar 677
                $notifications = array();
678
                if ((!$user || ($user == 'admin')) && OIDplus::authUtils()->isAdminLoggedIn()) {
1149 daniel-mar 679
                        if (!url_post_contents_available()) {
1000 daniel-mar 680
                                $title = _L('System registration');
1008 daniel-mar 681
                                $notifications[] = array('ERR', _L('OIDplus plugin "%1" is enabled, but the required PHP extension "%2" is not installed.', '<a '.OIDplus::gui()->link('oidplus:srv_registration').'>'.htmlentities($title).'</a>', 'php_curl'));
1000 daniel-mar 682
                        }
683
                }
684
                return $notifications;
685
        }
686
 
635 daniel-mar 687
}