7abcc9d10918e03f6d29d0da284d168fc3174a2d
[memberdb.git] / include / members.php
1 <?php
2
3 $SQL_CREATE_MEMBERS = sprintf('
4     CREATE TABLE IF NOT EXISTS `%1$s` (
5       `id` int(10) unsigned NOT NULL auto_increment,
6       `number` int(10) unsigned NOT NULL,
7       `firstname` varchar(255) NOT NULL,
8       `lastname` varchar(255) NOT NULL,
9       `nickname` varchar(255) NOT NULL,
10       `accountholder` blob NOT NULL,
11       `accountnumber` blob NOT NULL,
12       `bankcode` blob NOT NULL,
13       `bankname` blob NOT NULL,
14       `directdebit` tinyint(1) NOT NULL,
15       `street` varchar(255) NOT NULL,
16       `housenumber` varchar(255) NOT NULL,
17       `postcode` varchar(255) NOT NULL,
18       `city` varchar(255) NOT NULL,
19       `country` varchar(255) NOT NULL,
20       `email` varchar(255) NOT NULL,
21       `phone` varchar(255) NOT NULL,
22       `fax` varchar(255) NOT NULL,
23       `mobile` varchar(255) NOT NULL,
24       `jabber` varchar(255) NOT NULL,
25       `icq` varchar(255) NOT NULL,
26       `msn` varchar(255) NOT NULL,
27       `aim` varchar(255) NOT NULL,
28       `skype` varchar(255) NOT NULL,
29       `url` varchar(255) NOT NULL,
30       `twitter` varchar(255) NOT NULL,
31       `created_at` datetime NOT NULL,
32       `modified_at` datetime NOT NULL,
33       PRIMARY KEY  (`id`),
34       UNIQUE KEY `number` (`number`)
35     ) ENGINE=InnoDB DEFAULT CHARSET=%2$s
36     ', DB_TABLE_MEMBERS, DB_CHARSET);
37
38 /* DB functions {{{ */
39
40 function db_create_member($member) {
41     unset($member['id']);
42     $member['created_at']   = db_unixtime2datetime(time());
43     $member['modified_at']  = db_unixtime2datetime(time());
44     if (!db_insert_single(DB_TABLE_MEMBERS, $member)) return false;
45     return db_insert_id();
46 }
47
48 function db_change_member($member) {
49     $id = $member['id'];
50     unset($member['id']);
51     $member['modified_at']  = db_unixtime2datetime(time());
52     return db_update_single(DB_TABLE_MEMBERS, $member, sprintf('id=\'%1$d\'', db_escape($id)));
53 }
54
55 function db_get_members() {
56     $sql = 'SELECT * FROM %1$s ORDER BY number ASC';
57     return db_select_multi(sprintf($sql, DB_TABLE_MEMBERS));
58 }
59
60 function db_get_member_with_id($member_id) {
61     $sql = 'SELECT * FROM %1$s WHERE id=\'%2$d\' LIMIT 1';
62     return db_select_single(sprintf($sql, DB_TABLE_MEMBERS, db_escape($member_id)));
63 }
64
65 function db_get_next_free_member_number() {/*{{{*/
66     $row = db_select_single(sprintf('SELECT MAX(number) AS number FROM %1$s', DB_TABLE_MEMBERS));
67     if (!isset($row)) return 2;
68
69     $number = $row['number'] + 1;
70     // Some numbers are reserved for honorary members
71     $number = (int) $number;
72     switch ($number) {
73         case 1:
74         case 23:
75         case 42:
76         case 666:
77         case 1337:
78         case 31337:
79             return $number + 1;
80     }
81     return $number;
82 };/*}}}*/
83
84
85 function db_get_member_with_number($member_number) {
86     $sql = 'SELECT * FROM %1$s WHERE number=\'%2$d\' LIMIT 1';
87     return db_select_single(sprintf($sql, DB_TABLE_MEMBERS, db_escape($member_number)));
88 }
89
90 /* }}} */
91
92 function validate_member($userdata, &$dbdata, &$validation) {/*{{{*/
93     $fields = array(
94         'id'            => 'number',
95         'number'        => 'number',
96         'firstname'     => 'string',
97         'lastname'      => 'string',
98         'nickname'      => 'string',
99         'accountholder' => 'string',
100         'accountnumber' => 'string',
101         'bankcode'      => 'string',
102         'bankname'      => 'string',
103         'directdebit'   => 'bool',
104         'street'        => 'string',
105         'housenumber'   => 'string',
106         'postcode'      => 'string',
107         'city'          => 'string',
108         'country'       => 'string',
109         'email'         => 'string',
110         'phone'         => 'string',
111         'fax'           => 'string',
112         'mobile'        => 'string',
113         'jabber'        => 'string',
114         'icq'           => 'string',
115         'msn'           => 'string',
116         'aim'           => 'string',
117         'skype'         => 'string',
118         'url'           => 'string',
119         'twitter'       => 'string',
120     );
121     $orig = $dbdata;
122     foreach ($fields as $name => $type) {
123         if ($type == 'bool') {
124             $dbdata[$name] = !empty($userdata[$name]);
125             continue;
126         }
127         if (!isset($userdata[$name])) continue;
128         $dbdata[$name] = $userdata[$name];
129     }
130 //      ids must be equal
131 //      number must be equal. if changed - check if free and allowed
132     if (isset($orig['id'])) {
133         if ($dbdata['id'] != $orig['id']) {
134             $validation[] = 'Irgendwas ist sehr sehr komisch.';
135         }
136         if (!validate_member_number($dbdata['number'], $dbdata['id'])) {
137             $validation[] = 'Die Mitgliedsnummer ist schon vergeben.';
138         }
139         return (count($validation) == 0);
140     }
141     if (!validate_member_number($dbdata['number'])) {
142         $validation[] = 'Die Mitgliedsnummer ist schon vergeben.';
143     }
144     return (count($validation) == 0);
145 }/*}}}*/
146
147 function validate_member_number($member_number, $member_id = NULL) {/*{{{*/
148     $member = db_get_member_with_number($member_number);
149
150     // theres no member with this number
151     if (!isset($member)) return true;
152
153     // there is a member, but maybe its the one we got passed
154     if (isset($member_id) && $member_id == $member['id']) return true;
155
156     return false;
157 }/*}}}*/
158
159
160 function action_list_members() {/*{{{*/
161     $members = db_get_members();
162     ?>
163     <h2>Liste der Mitglieder</h2>
164     <?php if (isset($members)) : ?>
165         <table>
166             <tr>
167                 <th>Mitgliedsnummer</th>
168                 <th>Nickname</th>
169                 <th>Vorname</th>
170                 <th>Nachname</th>
171             </tr>
172         <?php foreach ($members as $member) : ?>
173             <tr>
174                 <td><a href="<?=html_escape(link_to('view_member', array('id'=> $member['id'])))?>"><?=html_escape($member['number'])?></a></td>
175                 <td><?=html_escape($member['nickname'])?></td>
176                 <td><?=html_escape($member['firstname'])?></td>
177                 <td><?=html_escape($member['lastname'])?></td>
178             </tr>
179         <?php endforeach ?>
180         </table>
181     <?php else : ?>
182         <p>Bisher gibt's noch keine Mitglieder.</p>
183     <?php endif ?>
184         <a href="<?=link_to('create_member')?>">Neues Mitglied</a>
185         <a href="<?=link_to('export_email')?>">E-Mail-Adressen</a>
186     <?php
187 }/*}}}*/
188
189 function action_view_member() {/*{{{*/
190     if (!isset($_REQUEST['id'])) redirect(link_to());
191     $member = db_get_member_with_id($_REQUEST['id']);
192     if (!isset($member)) redirect(link_to());
193
194     form_member($member, true);
195     action_list_events($member);
196     action_create_event($member);
197 }/*}}}*/
198
199 function action_create_member() {/*{{{*/
200     $member = array();
201     $log_messages = array();
202     if (isset($_POST['submit'])) {
203         unset($_POST['id']);
204         if (validate_member($_POST, $member, $log_messages)) {
205             if (empty($member['number'])) $member['number'] = db_get_next_free_member_number();
206             if ($member_id = db_create_member($member)) {
207                 redirect(link_to('view_member', array('id' => $member_id)) . '#events');
208             }
209             echo db_error();
210         }
211     }
212     form_member($member, false, $log_messages);
213 }/*}}}*/
214
215 function action_change_member() {/*{{{*/
216     if (!isset($_REQUEST['id'])) redirect(link_to());
217     $member = db_get_member_with_id($_REQUEST['id']);
218     if (!isset($member)) redirect(link_to());
219     $log_messages = array();
220     if (isset($_POST['submit'])) {
221         if (validate_member($_POST, $member, $log_messages)) {
222             if (empty($member['number'])) $member['number'] = db_get_next_free_member_number();
223             if (db_change_member($member)) {
224                 redirect(link_to('view_member', array('id' => $member['id'])));
225             }
226             echo db_error();
227         }
228     }
229     form_member($member, false, $log_messages);
230 }/*}}}*/
231
232
233 function action_export_email() {/*{{{*/
234     $members = db_get_members();
235     $first = true;
236     ?>
237     <h2>E-Mail-Adressen</h2>
238     <?php if (isset($members)) : ?>
239         <?php foreach ($members as $member) : ?><?php if (empty($member['email'])) continue; ?><?php if ($first) : $first = false; else :?>,<?php endif ?> <?=$member['email']?><?php endforeach ?>
240     <?php else : ?>
241         <p>Bisher gibt's noch keine Mitglieder.</p>
242     <?php endif ?>
243     <?php
244 }/*}}}*/
245
246
247 function html_member_list_box($label, $name, $selected, $readonly = false, $id = NULL, $tag_params = '') {
248     $list = array(0 => '-');
249     $members = db_get_members();
250     if (!empty($members)) {
251         foreach ($members as $member) {
252             $list[$member['id']] = $member['number'] . ' ' . $member['nickname'];
253         }
254     }
255     return html_list_box($label, $name, $list, $selected, $readonly, $id, $tag_params);
256 }
257
258 function form_member($member = array(), $readonly = false, $log_messages = array()) {/*{{{*/
259     
260     $keys = db_get_crypto_keys();
261     if (empty($keys)) {
262 ?>
263         <p class="error">
264             <strong>Achtung:</strong> Bitte zuerst <a href="<?=link_to('cryptography')?>">Kryptographie einrichten</a>.
265         </p>
266 <?php
267         return;
268     }
269
270     js_modal_windows();
271     js_get_master_key();
272
273     ?>
274     <noscript>
275         <p class="error">
276             <strong>Achtung:</strong> Ohne JavaScript geht hier gar nichts. Bitte aktivieren!
277         </p>
278     </noscript>
279     <?php if (!isset($member['id'])) : ?>
280         <h2>Neues Mitglied</h2>
281     <?php elseif ($readonly) : ?>
282         <h2>Mitgliedsdetails</h2>
283     <?php else : ?>
284         <h2>Mitglied &auml;ndern</h2>
285     <?php endif ?>
286     <?php log_messages($log_messages); ?>
287     <form action="" method="post" class="clearfix">
288         <?php if (isset($member['id']) && !$readonly) : ?><?=html_hidden_field('id', $member)?><?php endif ?>
289         <fieldset>
290             <legend>Allgemein</legend>
291             <?=html_text_field('Mitgliedsnummer', 'number', $member, $readonly)?>
292             <?php if (!$readonly) : ?><small>Wird automatisch vergeben wenn leer.</small><?php endif ?>
293             <?=html_text_field('Nickname', 'nickname', $member, $readonly)?>
294             <?=html_text_field('E-Mail', 'email', $member, $readonly)?>
295         </fieldset>
296         <fieldset id="bank_details">
297             <legend>Bankverbindung</legend>
298             <?=html_text_field('Kontoinhaber', 'accountholder', $member, true)?>
299             <?=html_text_field('Kontonummer', 'accountnumber', $member, true)?>
300             <?=html_text_field('Bankleitzahl', 'bankcode', $member, true)?>
301             <?=html_text_field('Name der Bank', 'bankname', $member, true)?>
302             <?=html_checkbox('Lastschrifteinzug', 'directdebit', $member, 1, $readonly)?>
303             <?php if (!isset($member['id'])) : ?>
304                 <input class="submit" type="button" name="btn_bank_details" value="Bankverbindung erfassen" onclick="bank_details_ask_pass()" id="btn_bank_details"/>
305             <?php elseif ($readonly) : ?>
306                 <input class="submit" type="button" name="btn_bank_details" value="Bankverbindung betrachten" onclick="bank_details_ask_pass()" id="btn_bank_details"/>
307             <?php else : ?>
308                 <input class="submit" type="button" name="btn_bank_details" value="Bankverbindung &auml;ndern" onclick="bank_details_ask_pass()" id="btn_bank_details"/>
309             <?php endif ?>
310         </fieldset>
311         <fieldset style="clear: left;">
312             <legend>Anschrift</legend>
313             <?=html_text_field('Vorname', 'firstname', $member, $readonly)?>
314             <?=html_text_field('Nachname', 'lastname', $member, $readonly)?>
315             <?=html_text_field('Straße', 'street', $member, $readonly)?>
316             <?=html_text_field('Hausnummer', 'housenumber', $member, $readonly)?>
317             <?=html_text_field('PLZ', 'postcode', $member, $readonly)?>
318             <?=html_text_field('Ort', 'city', $member, $readonly)?>
319             <?=html_text_field('Land', 'country', $member, $readonly)?>
320         </fieldset>
321         <fieldset>
322             <legend>Sonstiges</legend>
323             <?=html_text_field('Telefon', 'phone', $member, $readonly)?>
324             <?=html_text_field('Fax', 'fax', $member, $readonly)?>
325             <?=html_text_field('Handy', 'mobile', $member, $readonly)?>
326             <?=html_text_field('Jabber', 'jabber', $member, $readonly)?>
327             <?=html_text_field('ICQ', 'icq', $member, $readonly)?>
328             <?=html_text_field('MSN', 'msn', $member, $readonly)?>
329             <?=html_text_field('AIM', 'aim', $member, $readonly)?>
330             <?=html_text_field('Skype', 'skype', $member, $readonly)?>
331             <?=html_text_field('Website', 'url', $member, $readonly)?>
332             <?=html_text_field('Twitter', 'twitter', $member, $readonly)?>
333         </fieldset>
334         <?php if (!$readonly) : ?>
335             <input class="submit" type="submit" name="submit" value="Speichern"/>
336         <?php else : ?>
337             <br style="clear: left;"/>
338             <a href="<?=html_escape(link_to('change_member', array('id' => $member['id'])))?>">Mitglied &auml;ndern</a>
339         <?php endif ?>
340     </form>
341     <?php if (!isset($member['id'])) : ?>
342     <input class="submit" type="button" name="btn_import_qrcode1" value="QR-Code importieren" onclick="import_qrcode_ask_pass()" id="btn_import_qrcode1"/>
343     <div id="password_popup2" class="modal_window">
344         <fieldset>
345             <legend>Passwortabfrage</legend>
346             <?=html_password_field('Passwort', 'password2')?>
347             <input class="submit" type="button" name="btn_import_qrcode2" value="QR-Code importieren" onclick="import_qrcode()"/>
348         <input class="submit" type="button" name="btn_cancel_import_qrcode" value="Abbrechen" onclick="cancel_import_qrcode()"/>
349         </fieldset>
350     </div>
351     <div id="qrcode_popup" class="modal_window">
352         <fieldset>
353             <legend>QR-Code</legend>
354             <textarea id="qrcode_content" style="width: 100%" rows="30"></textarea>
355             <input class="submit" type="button" name="btn_qrcode_close" value="Importieren" onclick="qrcode_close()"/>
356         </fieldset>
357     </div>
358     <?php endif ?>
359     
360     <div id="password_popup" class="modal_window">
361         <fieldset>
362             <legend>Passwortabfrage</legend>
363             <?=html_password_field('Passwort', 'password1')?>
364             <input class="submit" type="button" name="btn_decrypt_bank_details" value="Bankdaten entschl&uuml;sseln" onclick="decrypt_bank_details()"/>
365         <input class="submit" type="button" name="btn_cancel" value="Abbrechen" onclick="cancel_change_bank_details()"/>
366         </fieldset>
367     </div>
368     <div id="bank_detail_popup" class="modal_window">
369         <fieldset>
370             <legend>Bankverbindung</legend>
371             <?=html_text_field('Kontoinhaber', 'tmp_accountholder', $member, $readonly)?>
372             <?=html_text_field('Kontonummer', 'tmp_accountnumber', $member, $readonly)?>
373             <?=html_text_field('Bankleitzahl', 'tmp_bankcode', $member, $readonly)?>
374             <?=html_text_field('Name der Bank', 'tmp_bankname', $member, $readonly)?>
375             <?php if (!isset($member['id'])) : ?>
376                 <input class="submit" type="button" name="btn_bank_details_save" value="&Uuml;bernehmen" onclick="bank_details_save()"/>
377                 <input class="submit" type="button" name="btn_bank_details_cancel" value="Abbrechen" onclick="bank_details_cancel()"/>
378             <?php elseif ($readonly) : ?>
379                 <input class="submit" type="button" name="btn_bank_details_cancel" value="Zur&uuml;ck" onclick="bank_details_cancel()" id="btn_bank_details_cancel"/>
380             <?php else : ?>
381                 <input class="submit" type="button" name="btn_bank_details_save" value="&Uuml;bernehmen" onclick="bank_details_save()"/>
382                 <input class="submit" type="button" name="btn_bank_details_cancel" value="Abbrechen" onclick="bank_details_cancel()"/>
383             <?php endif ?>
384         </fieldset>
385     </div>
386 <script type="text/javascript">
387
388
389 var the_masterkey;
390
391 $(document).ready(function(){  
392     $('#accountholder').focus( function() { $("#btn_bank_details").focus(); });
393 <?php if ($readonly) : ?>
394     $('#btn_bank_details_cancel').keypress( function(event) { if (event.keyCode == '13') { bank_details_cancel(); } });
395 <?php else : ?>
396     $('#tmp_bankname').keypress( function(event) { if (event.keyCode == '13') { bank_details_save(); } });
397 <?php endif ?>
398     $('#password1').keypress( function(event) { if (event.keyCode == '13') { decrypt_bank_details(); } });
399     <?php if (!isset($member['id'])) : ?>
400     $('#password2').keypress( function(event) { if (event.keyCode == '13') { import_qrcode(); } });
401 <?php endif ?>
402 });  
403
404 function bank_details_ask_pass() {/*{{{*/
405     modal_window_show($("#password_popup"));
406     $("#password1").focus();
407     return;
408 }/*}}}*/
409
410
411 function import_qrcode_ask_pass() {/*{{{*/
412     modal_window_show($("#password_popup2"));
413     $("#password2").focus();
414     return;
415 }/*}}}*/
416
417 function cancel_change_bank_details() {/*{{{*/
418     modal_window_hide();
419     $("#btn_bank_details").focus();
420     $("#password1").val('');
421     return;
422 }/*}}}*/
423
424 function cancel_import_qrcode() {/*{{{*/
425     modal_window_hide();
426     $("#password2").val('');
427     return;
428 }/*}}}*/
429
430 function decrypt_bank_details() {/*{{{*/
431
432     var password = $('#password1').val();
433     $("#password1").val('');
434
435     // We pass a closure so that get_master_key may defer execution
436     get_master_key(password, function(masterkey) {
437
438         modal_window_replace($("#bank_detail_popup"));
439 <?php if ($readonly) : ?>
440         $('#btn_bank_details_cancel').focus();
441 <?php else : ?>
442         $('#tmp_accountholder').focus();
443 <?php endif ?>
444
445         var accountholder = $('#accountholder').val();
446         var accountnumber = $('#accountnumber').val();
447         var bankcode      = $('#bankcode').val();
448         var bankname      = $('#bankname').val();
449
450         // Encrypt/Decrypt data using AES with masterkey
451         if (accountholder != "") { $('#tmp_accountholder').val(Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(accountholder, masterkey))); }
452         if (accountnumber != "") { $('#tmp_accountnumber').val(Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(accountnumber, masterkey))); }
453         if (bankcode      != "") { $('#tmp_bankcode'     ).val(Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(bankcode,      masterkey))); }
454         if (bankname      != "") { $('#tmp_bankname'     ).val(Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(bankname,      masterkey))); }
455         the_masterkey = masterkey; // cache masterkey until popup is closed
456     });
457
458 }/*}}}*/
459
460 function import_qrcode() {/*{{{*/
461
462     var password = $('#password2').val();
463     $("#password2").val('');
464
465     // We pass a closure so that get_master_key may defer execution
466     get_master_key(password, function(masterkey) {
467
468         modal_window_replace($("#qrcode_popup"));
469         the_masterkey = masterkey; // cache masterkey until popup is closed
470     });
471
472 }/*}}}*/
473
474 function qrcode_close() {/*{{{*/
475
476     modal_window_hide();
477
478     var qrcode_content = $('#qrcode_content').val();
479     $("#qrcode_content").val('');
480     var qrcode = qrcode_content.split(';');
481     if (qrcode.length >= 17) { 
482         $("#nickname").val(qrcode[0]);
483         // XXX birthdate - unused
484         $("#email").val(qrcode[2]);
485         // XXX cccmember - unused
486         $("#firstname").val(qrcode[4]);
487         $("#lastname").val(qrcode[5]);
488         $("#street").val(qrcode[6]);
489         $("#housenumber").val(qrcode[7]);
490         $("#postcode").val(qrcode[8]);
491         $("#city").val(qrcode[9]);
492         $("#country").val(qrcode[10]);
493         // XXX fee unused
494         $("#paymentinterval").val(qrcode[12]);
495         var accountholder = qrcode[13];
496         var accountnumber = qrcode[14];
497         var bankcode = qrcode[15];
498         var bankname = qrcode[16];
499         // XXX amount unused - wurde erst am 4.5. ergänzt, war vorher leer.
500     }
501
502
503     // 4.2 Encrypt/Decrypt data using AES with masterkey
504     if (accountholder != "") { $('#accountholder').val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(accountholder), the_masterkey)); } else { $('#accountholder').val(''); }
505     if (accountnumber != "") { $('#accountnumber').val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(accountnumber), the_masterkey)); } else { $('#accountnumber').val(''); }
506     if (bankcode      != "") { $('#bankcode'     ).val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(bankcode),      the_masterkey)); } else { $('#bankcode').val(''); }
507     if (bankname      != "") { $('#bankname'     ).val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(bankname),      the_masterkey)); } else { $('#bankname').val(''); }
508     the_masterkey = '';
509
510 }/*}}}*/
511
512 function bank_details_save() {/*{{{*/
513
514     modal_window_hide();
515
516     var accountholder = $('#tmp_accountholder').val();
517     var accountnumber = $('#tmp_accountnumber').val();
518     var bankcode      = $('#tmp_bankcode').val();
519     var bankname      = $('#tmp_bankname').val();
520     $("#tmp_accountholder").val('');
521     $("#tmp_accountnumber").val('');
522     $("#tmp_bankcode").val('');
523     $("#tmp_bankname").val('');
524
525     // 4.2 Encrypt/Decrypt data using AES with masterkey
526     if (accountholder != "") { $('#accountholder').val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(accountholder), the_masterkey)); } else { $('#accountholder').val(''); }
527     if (accountnumber != "") { $('#accountnumber').val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(accountnumber), the_masterkey)); } else { $('#accountnumber').val(''); }
528     if (bankcode      != "") { $('#bankcode'     ).val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(bankcode),      the_masterkey)); } else { $('#bankcode').val(''); }
529     if (bankname      != "") { $('#bankname'     ).val(Crypto.AES.encrypt(Crypto.charenc.UTF8.stringToBytes(bankname),      the_masterkey)); } else { $('#bankname').val(''); }
530     the_masterkey = '';
531
532 }/*}}}*/
533
534 function bank_details_cancel() {/*{{{*/
535
536     modal_window_hide();
537
538     $("#tmp_accountholder").val('');
539     $("#tmp_accountnumber").val('');
540     $("#tmp_bankcode").val('');
541     $("#tmp_bankname").val('');
542
543     the_masterkey = '';
544 }/*}}}*/
545
546 </script>
547     <?php
548 }/*}}}*/
549
550