Subversion Repositories oidplus

Rev

Rev 4 | Go to most recent revision | Details | 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
 
20
class OIDplusGui {
21
 
22
        private static $crudCounter = 0;
23
 
24
        protected static function objDescription($html) {
25
                // We allow HTML, but no hacking
26
                // TODO: disallow more html tags https://www.experts-exchange.com/questions/22664900/Extensive-list-of-all-dangerous-HTML-tags-and-attributes-anti-XSS.html
27
                $forbidden_tags = array('script');
28
                $html = str_ireplace('<script', '<xxx', $html);
29
                $html = str_ireplace('</script>', '</xxx>', $html);
30
                return $html;
31
        }
32
 
33
        protected static function showRAInfo($email) {
34
                $out = '';
35
 
36
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."ra where email = '".OIDplus::db()->real_escape_string($email)."'");
37
                if (OIDplus::db()->num_rows($res) === 0) {
38
                        $out = '<p>The RA <a href="mailto:'.htmlentities($email).'">'.htmlentities($email).'</a> is not registered in the database.</p>';
39
 
40
                } else {
41
                        $row = OIDplus::db()->fetch_array($res);
42
                        $out = '<b>'.htmlentities($row['ra_name']).'</b><br>';
43
                        $out .= 'E-Mail: <a href="mailto:'.htmlentities($email).'">'.htmlentities($email).'</a><br>';
44
                        if (trim($row['personal_name']) !== '') $out .= htmlentities($row['personal_name']).'<br>';
45
                        if (trim($row['organization']) !== '') $out .= htmlentities($row['organization']).'<br>';
46
                        if (trim($row['office']) !== '') $out .= htmlentities($row['office']).'<br>';
47
                        if ($row['privacy']) {
48
                                // TODO: meldung nur anzeigen, wenn benutzer überhaupt straße, adresse etc hat
49
                                // TODO: aber der admin soll es sehen, und der user selbst (mit anmerkung, dass es privat ist)
50
                                $out .= '<p>The RA does not want to publish their personal information.</p>';
51
                        } else {
52
                                if (trim($row['street']) !== '') $out .= htmlentities($row['street']).'<br>';
53
                                if (trim($row['zip_town']) !== '') $out .= htmlentities($row['zip_town']).'<br>';
54
                                if (trim($row['country']) !== '') $out .= htmlentities($row['country']).'<br>';
55
                                $out .= '<br>';
56
                                if (trim($row['phone']) !== '') $out .= htmlentities($row['phone']).'<br>';
57
                                if (trim($row['fax']) !== '') $out .= htmlentities($row['fax']).'<br>';
58
                                if (trim($row['mobile']) !== '') $out .= htmlentities($row['mobile']).'<br>';
59
                                $out .= '<br>';
60
                        }
61
                }
62
 
63
                return $out;
64
        }
65
 
66
        protected static function showCrud($parent='oid:') {
67
                $items_total = 0;
68
                $items_hidden = 0;
69
 
70
                $objParent = OIDplusObject::parse($parent);
71
 
72
                $output = '';
73
                if (!$objParent->userHasWriteRights()) {
74
                        // TODO: wir sollten eigentlich bei noscript die buttons und edits ausblenden
75
                        $output .= '<noscript><b>Please enable JavaScript to edit the subsequent OIDs.</b></noscript>';
76
                }
77
                $output .= '<div class="container box"><div id="suboid_table" class="table-responsive">';
78
                $output .= '<table class="table table-bordered table-striped">';
79
                $output .= '    <tr>';
80
                $output .= '         <th>ID'.(($objParent::ns() == 'gs1') ? ' (without check digit)' : '').'</th>';
81
                if ($objParent::ns() == 'oid') $output .= '          <th>ASN.1 IDs (comma sep.)</th>';
82
                if ($objParent::ns() == 'oid') $output .= '          <th>IRI IDs (comma sep.)</th>';
83
                $output .= '         <th>RA</th>';
84
                if ($objParent->userHasWriteRights()) {
85
                        $output .= '         <th>Hide</th>';
86
                        $output .= '         <th>Update</th>';
87
                        $output .= '         <th>Delete</th>';
88
                }
89
                $output .= '         <th>Created</th>';
90
                $output .= '         <th>Updated</th>';
91
                $output .= '    </tr>';
92
 
93
                $result = OIDplus::db()->query("select o.*, r.ra_name from ".OIDPLUS_TABLENAME_PREFIX."objects o left join ".OIDPLUS_TABLENAME_PREFIX."ra r on r.email = o.ra_email where parent = '".OIDplus::db()->real_escape_string($parent)."' order by ".OIDplus::db()->natOrder('id'));
94
                while ($row = OIDplus::db()->fetch_object($result)) {
95
                        $obj = OIDplusObject::parse($row->id);
96
 
97
                        $items_total++;
98
                        if (!$obj->userHasReadRights()) {
99
                                $items_hidden++;
100
                                continue;
101
                        }
102
 
103
                        $show_id = $obj->crudShowId($objParent);
104
 
105
                        $asn1ids = array();
106
                        $res2 = OIDplus::db()->query("select name from ".OIDPLUS_TABLENAME_PREFIX."asn1id where oid = '".OIDplus::db()->real_escape_string($row->id)."' order by lfd");
107
                        while ($row2 = OIDplus::db()->fetch_array($res2)) {
108
                                $asn1ids[] = $row2['name'];
109
                        }
110
                        $asn1ids = implode(', ', $asn1ids);
111
 
112
                        $iris = array();
113
                        $res2 = OIDplus::db()->query("select name from ".OIDPLUS_TABLENAME_PREFIX."iri where oid = '".OIDplus::db()->real_escape_string($row->id)."' order by lfd");
114
                        while ($row2 = OIDplus::db()->fetch_array($res2)) {
115
                                $iris[] = $row2['name'];
116
                        }
117
                        $iris = implode(', ', $iris);
118
 
119
                        $output .= '<tr>';
120
// TODO: if no scripts are allowed, we cannot open this link using openAndSelectNode()
121
                        $output .= '     <td><a href="javascript:openAndSelectNode('.js_escape($row->id).', '.js_escape($parent).')">'.htmlentities($show_id).'</a></td>';
122
                        if ($objParent->userHasWriteRights()) {
123
                                if ($obj::ns() == 'oid') $output .= '     <td><input type="text" id="asn1ids_'.$row->id.'" value="'.$asn1ids.'"></td>';
124
                                if ($obj::ns() == 'oid') $output .= '     <td><input type="text" id="iris_'.$row->id.'" value="'.$iris.'"></td>';
125
                                $output .= '     <td><input type="text" id="ra_email_'.$row->id.'" value="'.$row->ra_email.'"></td>';
126
                                $output .= '     <td><input type="checkbox" id="hide_'.$row->id.'" '.($row->confidential ? 'checked' : '').'></td>';
127
                                $output .= '     <td><button type="button" name="update_'.$row->id.'" id="update_'.$row->id.'" class="btn btn-success btn-xs update" onclick="javascript:crudActionUpdate('.js_escape($row->id).', '.js_escape($parent).')">Update</button></td>';
128
                                $output .= '     <td><button type="button" name="delete_'.$row->id.'" id="delete_'.$row->id.'" class="btn btn-danger btn-xs delete" onclick="javascript:crudActionDelete('.js_escape($row->id).', '.js_escape($parent).')">Delete</button></td>';
129
                                $output .= '     <td>'.oiddb_formatdate($row->created).'</td>';
130
                                $output .= '     <td>'.oiddb_formatdate($row->updated).'</td>';
131
                        } else {
132
                                if ($asn1ids == '') $asn1ids = '<i>(none)</i>';
133
                                if ($iris == '') $iris = '<i>(none)</i>';
134
                                if ($obj::ns() == 'oid') $output .= '     <td><a href="javascript:openAndSelectNode('.js_escape($row->id).', '.js_escape($parent).')">'.$asn1ids.'</a></td>';
135
                                if ($obj::ns() == 'oid') $output .= '     <td>'.$iris.'</td>';
136
// TODO: if no scripts are allowed, we cannot open the rainfo: pages using openOidInPanel()
137
                                $output .= '     <td><a href="javascript:openOidInPanel('.js_escape('oidplus:rainfo$'.str_replace('@', "'+'@'+'", $row->ra_email)).', true)">'.htmlentities(empty($row->ra_name) ? str_replace('@','&',$row->ra_email) : $row->ra_name).'</a></td>';
138
                                $output .= '     <td>'.oiddb_formatdate($row->created).'</td>';
139
                                $output .= '     <td>'.oiddb_formatdate($row->updated).'</td>';
140
                        }
141
                        $output .= '</tr>';
142
                }
143
 
144
                $result = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($parent)."'");
145
                $parent_ra_email = OIDplus::db()->num_rows($result) > 0 ? OIDplus::db()->fetch_object($result)->ra_email : '';
146
 
147
                if ($objParent->userHasWriteRights()) {
148
                        $output .= '<tr>';
149
                        $prefix = is_null($objParent) ? '' : $objParent->crudInsertPrefix();
150
                        if ($objParent::ns() == 'oid') {
151
                                $output .= '     <td>'.$prefix.' <input type="text" id="id" value="" style="width:100%;min-width:50px"></td>'; // TODO: idee classname vergeben, z.B. "OID" und dann mit einem oid-spezifischen css die breite einstellbar machen, somit hat das plugin mehr kontrolle über das aussehen und die mindestbreiten
152
                        } else {
153
                                $output .= '     <td>'.$prefix.' <input type="text" id="id" value=""></td>';
154
                        }
155
                        if ($objParent::ns() == 'oid') $output .= '     <td><input type="text" id="asn1ids" value=""></td>';
156
                        if ($objParent::ns() == 'oid') $output .= '     <td><input type="text" id="iris" value=""></td>';
157
                        $output .= '     <td><input type="text" id="ra_email" value="'.htmlentities($parent_ra_email).'"></td>';
158
                        $output .= '     <td><input type="checkbox" id="hide"></td>';
159
                        $output .= '     <td><button type="button" name="insert" id="insert" class="btn btn-success btn-xs update" onclick="javascript:crudActionInsert('.js_escape($parent).')">Insert</button></td>';
160
                        $output .= '     <td></td>';
161
                        $output .= '     <td></td>';
162
                        $output .= '     <td></td>';
163
                        $output .= '</tr>';
164
                } else {
165
                        if ($items_total-$items_hidden == 0) {
166
                                $cols = ($objParent::ns() == 'oid') ? 7 : 5;
167
                                $output .= '<tr><td colspan="'.$cols.'">No items available</td></tr>';
168
                        }
169
                }
170
 
171
                $output .= '</table>';
172
                $output .= '</div></div>';
173
 
174
                if ($items_hidden == 1) {
175
                        $output .= '<p>'.$items_hidden.' item is hidden. Please <a href="?goto=oidplus:login">log in</a> to see it.</p>';
176
                } else if ($items_hidden > 1) {
177
                        $output .= '<p>'.$items_hidden.' items are hidden. Please <a href="?goto=oidplus:login">log in</a> to see them.</p>';
178
                }
179
 
180
                return $output;
181
        }
182
 
183
        public static $exclude_tinymce_plugins = array('fullpage', 'bbcode');
184
 
185
        protected static function showMCE($name, $content) {
186
                $mce_plugins = array();
187
                foreach (glob(__DIR__ . '/../3p/tinymce/plugins/*') as $m) { // */
188
                        $mce_plugins[] = basename($m);
189
                }
190
 
191
                foreach (self::$exclude_tinymce_plugins as $exclude) {
192
                        $index = array_search($exclude, $mce_plugins);
193
                        if ($index !== false) unset($mce_plugins[$index]);
194
                }
195
 
196
                $out = "<script>
197
                                tinymce.remove('#".$name."');
198
                                tinymce.init({
199
                                        selector: '#".$name."',
200
                                        plugins: '".implode(' ', $mce_plugins)."'
201
                                });
202
                        </script>";
203
 
204
                $out .= '<textarea name="'.htmlentities($name).'" id="'.htmlentities($name).'" rows="10">'.trim($content).'</textarea><br>';
205
 
206
                return $out;
207
        }
208
 
209
        public static function getInvitationText($email) {
210
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."ra where email = '".OIDplus::db()->real_escape_string($email)."'");
211
                if (OIDplus::db()->num_rows($res) > 0) {
212
                        throw new Exception("This RA is already registered and does not need to be invited.");
213
                }
214
 
215
                if (!OIDplus::authUtils()::isAdminLoggedIn()) {
216
                        // Check if the RA may invite the user (i.e. the they are the parent of an OID of that person)
217
                        $ok = false;
218
                        $res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where ra_email = '".OIDplus::db()->real_escape_string($email)."'");
219
                        while ($row = OIDplus::db()->fetch_array($res)) {
220
                                $objParent = OIDplusObject::parse($row['parent']);
221
                                if (is_null($objParent)) throw new Exception("Type of ".$row['parent']." unknown");
222
                                if ($objParent->userHasWriteRights()) {
223
                                        $ok = true;
224
                                }
225
                        }
226
                        if (!$ok) {
227
                                throw new Exception('You may not invite this RA. Maybe you need to log in again.');
228
                        }
229
                }
230
 
231
                $list_of_oids = array();
232
                $res = OIDplus::db()->query("select id from ".OIDPLUS_TABLENAME_PREFIX."objects where ra_email = '".OIDplus::db()->real_escape_string($email)."'");
233
                while ($row = OIDplus::db()->fetch_array($res)) {
234
                        $list_of_oids[] = $row['id'];
235
                }
236
 
237
                $message = file_get_contents(__DIR__ . '/../invite_msg.tpl');
238
 
239
                // Resolve stuff
240
                $message = str_replace('{{SYSTEM_URL}}', OIDplus::system_url(), $message);
241
                $message = str_replace('{{OID_LIST}}', implode("\n", $list_of_oids), $message);
242
                $message = str_replace('{{ADMIN_EMAIL}}', OIDPLUS_ADMIN_EMAIL, $message);
243
                $message = str_replace('{{PARTY}}', OIDplus::authUtils()::isAdminLoggedIn() ? 'the system administrator' : 'a superior Registration Authority', $message);
244
 
245
                // {{ACTIVATE_URL}} will be resolved in action.php
246
 
247
                return $message;
248
        }
249
 
250
        public static function getForgotPasswordText($email) {
251
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."ra where email = '".OIDplus::db()->real_escape_string($email)."'");
252
                if (OIDplus::db()->num_rows($res) == 0) {
253
                        throw new Exception("This RA does not exist.");
254
                }
255
 
256
                $message = file_get_contents(__DIR__ . '/../forgot_password.tpl');
257
 
258
                // Resolve stuff
259
                $message = str_replace('{{SYSTEM_URL}}', OIDplus::system_url(), $message);
260
                $message = str_replace('{{ADMIN_EMAIL}}', OIDPLUS_ADMIN_EMAIL, $message);
261
 
262
                // {{ACTIVATE_URL}} will be resolved in action.php
263
 
264
                return $message;
265
        }
266
 
267
        public static function generateContentPage($id) {
268
                $out = array();
269
 
270
                $handled = false;
271
                $out['title'] = '';
272
                $out['text'] = '';
273
 
274
                // === System ===
275
 
276
                if ($id === 'oidplus:system') {
277
                        $handled = true;
278
 
279
                        $out['title'] = 'Object Database of ' . $_SERVER['SERVER_NAME'];
280
                        $out['text'] = file_get_contents('welcome.html');
281
                        return $out;
282
 
283
                // === Generic stuff ===
284
 
285
                } else if (explode('$',$id)[0] == 'oidplus:rainfo') {
286
                        $handled = true;
287
 
288
                        $ra_email = explode('$',$id)[1];
289
 
290
                        $out['title'] = 'Registration Authority Information'; // TODO: email addresse reinschreiben? aber wie vor anti spam schützen?
291
 
292
                        if (empty($ra_email)) {
293
                                $out['text'] = '<p>Following object roots have an undefined Registration Authority:</p>';
294
                        } else {
295
                                $out['text'] = self::showRAInfo($ra_email);
296
                        }
297
 
298
                        foreach (OIDplusObject::getRaRoots($ra_email) as $loc_root) {
299
                                $icon = file_exists('plugins/objectTypes/'.$loc_root::ns().'/img/treeicon_link.png') ? 'plugins/objectTypes/'.$loc_root::ns().'/img/treeicon_link.png' : 'img/link.png';
300
                                $out['text'] .= '<p><a href="?goto='.$loc_root->nodeId().'"><img src="'.$icon.'"> Jump to RA root '.$loc_root->objectTypeTitleShort().' '.$loc_root->crudShowId(OIDplusObject::parse($loc_root::root())).'</a></p>';
301
                        }
302
 
303
 
304
                        if (OIDplus::authUtils()::isAdminLoggedIn()) {
305
                                $out['text'] .= '<p><a href="javascript:deleteRa('.js_escape($ra_email).',null)">Delete this RA</a></p>';
306
                        }
307
 
308
                // === Forgot password ===
309
 
310
                } else if (explode('$',$id)[0] == 'oidplus:forgot_password') {
311
                        $handled = true;
312
 
313
                        $out['title'] = 'Forgot password';
314
 
315
                        try {
316
                                $out['text'] .= '<p>Please enter the email address of your account, and information about the password reset will be sent to you.</p>
317
                                  <form id="forgotPasswordForm" onsubmit="return forgotPasswordFormOnSubmit();">
318
                                    E-Mail: <input type="text" id="email" value=""/><br><br>'.
319
                                 (RECAPTCHA_ENABLED ? '<script> grecaptcha.render(document.getElementById("g-recaptcha"), { "sitekey" : "'.RECAPTCHA_PUBLIC.'" }); </script>'.
320
                                                   '<div id="g-recaptcha" class="g-recaptcha" data-sitekey="'.RECAPTCHA_PUBLIC.'"></div>' : '').
321
                                ' <br>
322
                                    <input type="submit" value="Send recovery information">
323
                                  </form>';
324
 
325
                        } catch (Exception $e) {
326
 
327
                                $out['text'] = "Error: ".$e->getMessage();
328
 
329
                        }
330
                } else if (explode('$',$id)[0] == 'oidplus:reset_password') {
331
                        $handled = true;
332
 
333
                        $email = explode('$',$id)[1];
334
                        $timestamp = explode('$',$id)[2];
335
                        $auth = explode('$',$id)[3];
336
 
337
                        $out['title'] = 'Reset password';
338
 
339
                        if (!OIDplus::authUtils()::validateAuthKey('reset_password;'.$email.';'.$timestamp, $auth)) {
340
                                $out['text'] = 'Invalid authorization. Is the URL OK?';
341
                        } else {
342
                                $out['text'] = '<p>E-Mail-Adress: <b>'.$email.'</b></p>
343
 
344
                                  <form id="resetPasswordForm" onsubmit="return resetPasswordFormOnSubmit();">
345
                                    <input type="hidden" id="email" value="'.htmlentities($email).'"/>
346
                                    <input type="hidden" id="timestamp" value="'.htmlentities($timestamp).'"/>
347
                                    <input type="hidden" id="auth" value="'.htmlentities($auth).'"/>
348
                                    New password: <input type="password" id="password1" value=""/><br><br>
349
                                    Again: <input type="password" id="password2" value=""/><br><br>
350
                                    <input type="submit" value="Change password">
351
                                  </form>';
352
                        }
353
 
354
 
355
                // === Invite ===
356
 
357
                } else if (explode('$',$id)[0] == 'oidplus:invite_ra') {
358
                        $handled = true;
359
 
360
                        $email = explode('$',$id)[1];
361
                        $origin = explode('$',$id)[2];
362
 
363
                        $out['title'] = 'Invite a Registration Authority';
364
 
365
                        try {
366
                                $cont = self::getInvitationText($email);
367
 
368
                                $out['text'] .= '<p>You have chosen to invite <b>'.$email.'</b> as an Registration Authority. If you click "Send", the following email will be sent to '.$email.':</p><p><i>'.nl2br(htmlentities($cont)).'</i></p>
369
                                  <form id="inviteForm" onsubmit="return inviteFormOnSubmit();">
370
                                    <input type="hidden" id="email" value="'.htmlentities($email).'"/>
371
                                    <input type="hidden" id="origin" value="'.htmlentities($origin).'"/>'.
372
                                 (RECAPTCHA_ENABLED ? '<script> grecaptcha.render(document.getElementById("g-recaptcha"), { "sitekey" : "'.RECAPTCHA_PUBLIC.'" }); </script>'.
373
                                                   '<div id="g-recaptcha" class="g-recaptcha" data-sitekey="'.RECAPTCHA_PUBLIC.'"></div>' : '').
374
                                ' <br>
375
                                    <input type="submit" value="Send invitation">
376
                                  </form>';
377
 
378
                        } catch (Exception $e) {
379
 
380
                                $out['text'] = "Error: ".$e->getMessage();
381
 
382
                        }
383
                } else if (explode('$',$id)[0] == 'oidplus:activate_ra') {
384
                        $handled = true;
385
 
386
                        $email = explode('$',$id)[1];
387
                        $timestamp = explode('$',$id)[2];
388
                        $auth = explode('$',$id)[3];
389
 
390
                        $out['title'] = 'Register as Registration Authority';
391
 
392
                        $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."ra where email = '".OIDplus::db()->real_escape_string($email)."'");
393
                        if (OIDplus::db()->num_rows($res) > 0) {
394
                                $out['text'] = 'This RA is already registered and does not need to be invited.';
395
                        } else {
396
                                if (!OIDplus::authUtils()::validateAuthKey('activate_ra;'.$email.';'.$timestamp, $auth)) {
397
                                        $out['text'] = 'Invalid authorization. Is the URL OK?';
398
                                } else {
399
                                        // TODO: like in the FreeOID plugin, we could ask here at least for a name for the RA
400
                                        $out['text'] = '<p>E-Mail-Adress: <b>'.$email.'</b></p>
401
 
402
                                          <form id="activateRaForm" onsubmit="return activateRaFormOnSubmit();">
403
                                            <input type="hidden" id="email" value="'.htmlentities($email).'"/>
404
                                            <input type="hidden" id="timestamp" value="'.htmlentities($timestamp).'"/>
405
                                            <input type="hidden" id="auth" value="'.htmlentities($auth).'"/>
406
                                            New password: <input type="password" id="password1" value=""/><br><br>
407
                                            Again: <input type="password" id="password2" value=""/><br><br>
408
                                            <input type="submit" value="Register">
409
                                          </form>';
410
                                }
411
                        }
412
 
413
                // === Login ===
414
 
415
                } else if ($id === 'oidplus:login') {
416
                        $handled = true;
417
                        $out['title'] = 'Login';
418
 
419
                        $out['text'] = 'Here you can login and register as RA.';
420
 
421
                        $out['text'] .= '<script>function raLoginOnSubmit() {';
422
                        $out['text'] .= '       raLogin(document.getElementById("raLoginEMail").value, document.getElementById("raLoginPassword").value);';
423
                        $out['text'] .= '       return false;';
424
                        $out['text'] .= '}</script>';
425
 
426
                        $out['text'] .= (RECAPTCHA_ENABLED ? '<script> grecaptcha.render(document.getElementById("g-recaptcha"), { "sitekey" : "'.RECAPTCHA_PUBLIC.'" }); </script>'.
427
                                                          '<div id="g-recaptcha" class="g-recaptcha" data-sitekey="'.RECAPTCHA_PUBLIC.'"></div>' : '');
428
 
429
                        $out['text'] .= '<h2>Login as RA</h2>';
430
                        $out['text'] .= '<form action="action.php" method="POST" onsubmit="return raLoginOnSubmit(this);">';
431
                        $out['text'] .= '<input type="hidden" name="action" value="ra_login">';
432
                        $out['text'] .= 'E-Mail: <input type="text" name="email" value="" id="raLoginEMail"><br>';
433
                        $out['text'] .= 'Password: <input type="password" name="password" value="" id="raLoginPassword"><br>';
434
                        $out['text'] .= '<input type="submit" value="Login">';
435
                        $out['text'] .= '</form>';
436
                        $out['text'] .= '<p><a href="?goto=oidplus:forgot_password">Forgot password?</a><br>';
437
                        $out['text'] .= '<abbr title="To receive login data, the superior RA needs to send you an invitation. After creating or updating your OID, the system will ask them if they want to send you an invitation. If they accept, you will receive an email with an activation link.">How to register?</abbr></p>';
438
 
439
                        $out['text'] .= '<script>function adminLoginOnSubmit() {';
440
                        $out['text'] .= '       adminLogin(document.getElementById("adminLoginPassword").value);';
441
                        $out['text'] .= '       return false;';
442
                        $out['text'] .= '}</script>';
443
 
444
                        if (OIDplus::authUtils()::isAdminLoggedIn()) {
445
                                $out['text'] .= '<h2>Admin login</h2>';
446
                                $out['text'] .= '<p>You are logged in as administrator.</p>';
447
                                $out['text'] .= '<a href="javascript:adminLogout();">Logout</a>';
448
                        } else {
449
                                $out['text'] .= '<h2>Login as admin</h2>';
450
                                $out['text'] .= '<form action="action.php" method="POST" onsubmit="return adminLoginOnSubmit(this);">';
451
                                $out['text'] .= '<input type="hidden" name="action" value="admin_login">';
452
                                $out['text'] .= 'Password: <input type="password" name="password" value="" id="adminLoginPassword"><br>';
453
                                $out['text'] .= '<input type="submit" value="Login">';
454
                                $out['text'] .= '</form>';
455
                                $out['text'] .= '<p><abbr title="Delete the file includes/config.inc.php and reload the page to start Setup again">Forgot password?</abbr></p>';
456
                        }
457
                }
458
 
459
                // === Plugins ===
460
 
461
                $ary = glob(__DIR__ . '/../../plugins/publicPages/'.'*'.'/gui.inc.php');
462
                sort($ary);
463
                foreach ($ary as $a) include $a;
464
 
465
                $ary = glob(__DIR__ . '/../../plugins/adminPages/'.'*'.'/gui.inc.php');
466
                sort($ary);
467
                foreach ($ary as $a) include $a;
468
 
469
                $ary = glob(__DIR__ . '/../../plugins/raPages/'.'*'.'/gui.inc.php');
470
                sort($ary);
471
                foreach ($ary as $a) include $a;
472
 
473
                // === Everything else (objects) ===
474
 
475
                if (!$handled) {
476
                        $obj = OIDplusObject::parse($id);
477
 
478
                        if ((!is_null($obj)) && (!$obj->userHasReadRights())) {
479
                                $out['title'] = 'Access denied';
480
                                $out['text'] = '<p>Please <a href="?goto=oidplus:login">log in</a> to receive information about this object.</p>';
481
                                return $out;
482
                        }
483
 
484
                        $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($id)."'");
485
                        $row = OIDplus::db()->fetch_array($res);
486
 
487
                        if (empty($row['title'])) {
488
                                $out['title'] = is_null($obj) ? $id : $obj->defaultTitle();
489
                        } else {
490
                                $out['title'] = $row['title'];
491
                        }
492
 
493
                        if (isset($row['description'])) {
494
                                $desc = empty($row['description']) ? '<p><i>No description for this object available</i></p>' : OIDplusGui::objDescription($row['description']);
495
                                if ($obj->userHasWriteRights()) {
496
                                        $rand = ++self::$crudCounter;
497
                                        $desc = '<noscript><p><b>You need to enable JavaScript to edit title or description of this object.</b></p>'.$desc.'</noscript>';
498
                                        $desc .= '<div class="container box" style="display:none" id="descbox_'.$rand.'">';
499
                                        $desc .= 'Title: <input type="text" name="title" id="titleedit" value="'.htmlentities($row['title']).'"><br><br>Description:<br>';
500
                                        $desc .= self::showMCE('description', $row['description']);
501
                                        $desc .= '<button type="button" name="update_desc" id="update_desc" class="btn btn-success btn-xs update" onclick="javascript:updateDesc()">Update description</button>';
502
                                        $desc .= '</div>';
503
                                        $desc .= '<script>document.getElementById("descbox_'.$rand.'").style.display = "block";</script>';
504
                                }
505
                        } else {
506
                                $desc = '';
507
                        }
508
 
509
                        $matches_any_registered_type = false;
510
                        foreach (OIDplusObject::$registeredObjectTypes as $ot) {
511
                                if ($obj = $ot::parse($id)) {
512
                                        $matches_any_registered_type = true;
513
                                        if ((OIDplus::db()->num_rows($res) == 0) && !$obj->isRoot()){
514
                                                http_response_code(404);
515
                                                $out['title'] = 'Object not found';
516
                                                $out['text'] = 'The object <code>'.htmlentities($id).'</code> was not found in this database.';
517
                                                return $out;
518
                                        } else {
519
                                                $obj->getContentPage($out['title'], $out['text']);
520
                                        }
521
                                }
522
                        }
523
                        if (!$matches_any_registered_type) {
524
                                http_response_code(404);
525
                                $out['title'] = 'Object not found';
526
                                $out['text'] = 'The object <code>'.htmlentities($id).'</code> was not found in this database.';
527
                                return $out;
528
                        }
529
 
530
                        if (strpos($out['text'], '%%DESC%%') !== false)
531
                                $out['text'] = str_replace('%%DESC%%',    $desc,                              $out['text']);
532
                        if (strpos($out['text'], '%%CRUD%%') !== false)
533
                                $out['text'] = str_replace('%%CRUD%%',    self::showCrud($id),                $out['text']);
534
                        if (strpos($out['text'], '%%RA_INFO%%') !== false)
535
                                $out['text'] = str_replace('%%RA_INFO%%', self::showRaInfo($row['ra_email']), $out['text']);
536
                }
537
 
538
                return $out;
539
        }
540
 
541
}