]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - configurator.php
Remove obsolete comment
[SourceForge/phpwiki.git] / configurator.php
1 <?php
2 /*
3  * Copyright 2002,2003,2005,2008-2010 $ThePhpWikiProgrammingTeam
4  * Copyright 2002 Martin Geisler <gimpster@gimpster.com>
5  * Copyright 2008-2009 Marc-Etienne Vargenau, Alcatel-Lucent
6  *
7  * This file is part of PhpWiki.
8  * Parts of this file were based on PHPWeather's configurator.php file.
9  *   http://sourceforge.net/projects/phpweather/
10  *
11  * PhpWiki is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * PhpWiki is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 /**
27  * Starts automatically the first time by IniConfig("config/config.ini")
28  * if it doesn't exist.
29  *
30  * DONE:
31  * o Initial expand ?show=_part1 (the part id)
32  * o read config-default.ini and use this as default_values
33  * o commented / optional: non-default values should not be commented!
34  *                         default values if optional can be omitted.
35  * o validate input (fix javascript, add POST checks)
36  * o start this automatically the first time
37  * o fix include_path
38  *
39  * 1.3.11 TODO: (or 1.3.12?)
40  * o parse_ini_file("config-dist.ini") for the commented vars
41  * o check automatically for commented and optional vars
42  * o fix _optional, to ignore existing config.ini and only use config-default.ini values
43  * o mixin class for commented
44  * o fix SQL quotes, AUTH_ORDER quotes and file forward slashes
45  * o posted values validation, extend js validation for sane DB values
46  * o read config-dist.ini into sections, comments, and optional/required settings
47  *
48  * A file config/config.ini will be automatically generated, if writable.
49  *
50  * NOTE: If you have a starterscript outside PHPWIKI_DIR but no
51  * config/config.ini yet (very unlikely!), you must define DATA_PATH in the
52  * starterscript, otherwise the webpath to configurator is unknown, and
53  * subsequent requests will fail. (POST to save the INI)
54  */
55
56 global $HTTP_POST_VARS, $tdwidth;
57 if (empty($_SERVER)) $_SERVER =& $GLOBALS['HTTP_SERVER_VARS'];
58 if (empty($_GET)) $_GET =& $GLOBALS['HTTP_GET_VARS'];
59 if (empty($_ENV)) $_ENV =& $GLOBALS['HTTP_ENV_VARS'];
60 if (empty($_POST)) $_POST =& $GLOBALS['HTTP_POST_VARS'];
61
62 if (empty($configurator))
63     $configurator = "configurator.php";
64 if (!strstr($_SERVER["SCRIPT_NAME"], $configurator) and defined('DATA_PATH'))
65     $configurator = DATA_PATH . "/" . $configurator;
66 $scriptname = str_replace('configurator.php', 'index.php', $_SERVER["SCRIPT_NAME"]);
67 if (strstr($_SERVER["SCRIPT_NAME"], "/php")) { // cgi got this different
68     if (defined('DATA_PATH'))
69         $scriptname = DATA_PATH . "/index.php";
70     else
71         $scriptname = str_replace('configurator.php', 'index.php', $_SERVER["PHP_SELF"]);
72 }
73
74 $tdwidth = 700;
75 $config_file = (substr(PHP_OS, 0, 3) == 'WIN') ? 'config\\config.ini' : 'config/config.ini';
76 $fs_config_file = dirname(__FILE__) . (substr(PHP_OS, 0, 3) == 'WIN' ? '\\' : '/') . $config_file;
77 if (isset($_POST['create'])) header('Location: ' . $configurator . '?show=_part1&create=1#create');
78
79 // helpers from lib/WikiUser/HttpAuth.php
80 if (!function_exists('_http_user')) {
81     function _http_user()
82     {
83         if (!isset($_SERVER))
84             $_SERVER = $GLOBALS['HTTP_SERVER_VARS'];
85         if (!empty($_SERVER['PHP_AUTH_USER']))
86             return array($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
87         if (!empty($_SERVER['REMOTE_USER']))
88             return array($_SERVER['REMOTE_USER'], $_SERVER['PHP_AUTH_PW']);
89         if (!empty($GLOBALS['HTTP_ENV_VARS']['REMOTE_USER']))
90             return array($GLOBALS['HTTP_ENV_VARS']['REMOTE_USER'],
91                 $GLOBALS['HTTP_ENV_VARS']['PHP_AUTH_PW']);
92         if (!empty($GLOBALS['REMOTE_USER']))
93             return array($GLOBALS['REMOTE_USER'], $GLOBALS['PHP_AUTH_PW']);
94
95         // MsWindows IIS:
96         if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
97             list($userid, $passwd) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
98             return array($userid, $passwd);
99         }
100         return array('', '');
101     }
102
103     function _http_logout()
104     {
105         if (!isset($_SERVER))
106             $_SERVER =& $GLOBALS['HTTP_SERVER_VARS'];
107         // maybe we should random the realm to really force a logout. but the next login will fail.
108         header('WWW-Authenticate: Basic realm="' . WIKI_NAME . '"');
109         if (strstr(php_sapi_name(), 'apache'))
110             header('HTTP/1.0 401 Unauthorized');
111         else
112             header("Status: 401 Access Denied"); //IIS and CGI need that
113         unset($GLOBALS['REMOTE_USER']);
114         unset($_SERVER['PHP_AUTH_USER']);
115         unset($_SERVER['PHP_AUTH_PW']);
116
117         trigger_error("Permission denied. Require ADMIN_USER.", E_USER_ERROR);
118         exit();
119     }
120 }
121
122 // If config.ini exists, we require ADMIN_USER access by faking HttpAuth.
123 // So nobody can see or reset the password(s).
124 if (file_exists($fs_config_file)) {
125     // Require admin user
126     if (!defined('ADMIN_USER') or !defined('ADMIN_PASSWD')) {
127         if (!function_exists("IniConfig")) {
128             include_once 'lib/prepend.php';
129             include_once 'lib/IniConfig.php';
130         }
131         IniConfig($fs_config_file);
132     }
133     if (!defined('ADMIN_USER') or ADMIN_USER == '') {
134         trigger_error("Configuration problem:\nADMIN_USER not defined in \"$fs_config_file\".\n"
135             . "Cannot continue: You have to fix that manually.", E_USER_ERROR);
136         exit();
137     }
138
139     list($admin_user, $admin_pw) = _http_user();
140     //$required_user = ADMIN_USER;
141     if (empty($admin_user) or $admin_user != ADMIN_USER) {
142         _http_logout();
143     }
144     // check password
145     if (ENCRYPTED_PASSWD) {
146         if (crypt($admin_pw, ADMIN_PASSWD) != ADMIN_PASSWD)
147             _http_logout();
148     } elseif ($admin_pw != ADMIN_PASSWD) {
149         _http_logout();
150     }
151 } else {
152     if (!function_exists("IniConfig")) {
153         include_once 'lib/prepend.php';
154         include_once 'lib/IniConfig.php';
155     }
156     $def_file = (substr(PHP_OS, 0, 3) == 'WIN') ? 'config\\config-default.ini' : 'config/config-default.ini';
157     $fs_def_file = dirname(__FILE__) . (substr(PHP_OS, 0, 3) == 'WIN' ? '\\' : '/') . $def_file;
158     IniConfig($fs_def_file);
159 }
160
161 ?>
162 <!DOCTYPE html>
163 <html>
164 <head>
165     <meta charset="UTF-8" />
166     <title>Configuration tool for PhpWiki <?php echo $config_file ?></title>
167     <style type="text/css" media="screen">
168         <!--
169             /* TABLE { border: thin solid black } */
170         body {
171             font-family: Verdana, Arial, Helvetica, sans-serif;
172             font-size: 80%;
173         }
174
175         pre {
176             font-size: 120%;
177         }
178
179         td {
180             border: thin solid black
181         }
182
183         tr {
184             border: none
185         }
186
187         div.hint {
188             background-color: #eeeeee;
189         }
190
191         tr.hidden {
192             border: none;
193             display: none;
194         }
195
196         td.part {
197             background-color: #eeeeee;
198             color: inherit;
199         }
200
201         td.instructions {
202             background-color: #ffffee;
203             width: <?php echo $tdwidth ?>px;
204             color: inherit;
205         }
206
207         td.unchangeable-variable-top {
208             border-bottom: none;
209             background-color: #ffffee;
210             color: inherit;
211         }
212
213         td.unchangeable-variable-left {
214             border-top: none;
215             background-color: #ffffee;
216             color: inherit;
217         }
218
219         -->
220     </style>
221     <script type="text/javascript">
222         <!--
223                 function update(accepted, error, value, output) {
224                     var msg = document.getElementById(output);
225                     if (accepted) {
226                         /* MSIE 5.0 fails here */
227                         if (msg && msg.innerHTML) {
228                             msg.innerHTML = "<span color=\"green\">Input accepted.</span>";
229                         }
230                     } else {
231                         var index;
232                         while ((index = error.indexOf("%s")) > -1) {
233                             error = error.substring(0, index) + value + error.substring(index + 2);
234                         }
235                         if (msg) {
236                             msg.innerHTML = "<span color=\"red\">" + error + "</span>";
237                         }
238                     }
239                     var submit;
240                     if (submit = document.getElementById('submit')) submit.disabled = accepted ? false : true;
241                 }
242
243         function validate(error, value, output, field) {
244             update(field.value == value, error, field.value, output);
245         }
246
247         function validate_ereg(error, ereg, output, field) {
248             var regex = new RegExp(ereg);
249             update(regex.test(field.value), error, field.value, output);
250         }
251
252         function validate_range(error, low, high, empty_ok, output, field) {
253             update((empty_ok == 1 && field.value == "") ||
254                     (field.value >= low && field.value <= high),
255                     error, field.value, output);
256         }
257
258         function toggle_group(id) {
259             var text = document.getElementById(id + "_text");
260             var do_hide = false;
261             if (text.innerHTML == "Hide options.") {
262                 do_hide = true;
263                 text.innerHTML = "Show options.";
264             } else {
265                 text.innerHTML = "Hide options.";
266             }
267
268             var rows = document.getElementsByTagName('tr');
269             var i;
270             var tr;
271             for (i = 0; i < rows.length; i++) {
272                 tr = rows[i];
273                 if (tr.className == 'header' && tr.id == id) {
274                     i++;
275                     break;
276                 }
277             }
278             for (; i < rows.length; i++) {
279                 tr = rows[i];
280                 if (tr.className == 'header')
281                     break;
282                 tr.className = do_hide ? 'hidden' : 'nonhidden';
283             }
284         }
285
286         function do_init() {
287             // Hide all groups.  We do this via JavaScript to avoid
288             // hiding the groups if JavaScript is not supported...
289             var rows = document.getElementsByTagName('tr');
290             var show = '<?php echo $_GET["show"] ?>';
291             for (var i = 0; i < rows.length; i++) {
292                 var tr = rows[i];
293                 if (tr.className == 'header')
294                     if (!show || tr.id != show)
295                         toggle_group(tr.id);
296             }
297
298             // Select text in textarea upon focus
299             var area = document.getElementById('config-output');
300             if (area) {
301                 var listener = { handleEvent:function (e) {
302                     area.select();
303                 } };
304                 area.addEventListener('focus', listener, false);
305             }
306         }
307
308         // -->
309     </script>
310 </head>
311 <body onload="do_init();">
312
313 <h1>Configuration for PhpWiki <?php echo $config_file ?></h1>
314
315 <div class="hint">
316     Using this configurator.php is experimental!<br/>
317     On any configuration problems, please edit the resulting config.ini manually.
318 </div>
319
320 <?php
321 define('DEBUG', 0);
322 //define('DEBUG', 1);
323 /**
324  * The Configurator is a php script to aid in the configuration of PhpWiki.
325  * Parts of this file were based on PHPWeather's configurator.php file.
326  *   http://sourceforge.net/projects/phpweather/
327  *
328  * TO CHANGE THE CONFIGURATION OF YOUR PHPWIKI, DO *NOT* MODIFY THIS FILE!
329  * more instructions go here
330  *
331  * Todo:
332  *   * fix include_path
333  *   * eval config.ini to get the actual settings.
334  */
335
336 //////////////////////////////
337 // begin configuration options
338
339 /**
340  * Notes for the description parameter of $property:
341  *
342  * - Descriptive text will be changed into comments (preceeded by ; )
343  *   for the final output to config.ini.
344  *
345  * - Only a limited set of html is allowed: pre, dl dt dd; it will be
346  *   stripped from the final output.
347  *
348  * - Line breaks and spacing will be preserved for the final output.
349  *
350  * - Double line breaks are automatically converted to paragraphs
351  *   for the html version of the descriptive text.
352  *
353  * - Double-quotes and dollar signs in the descriptive text must be
354  *   escaped: \" and \$. Instead of escaping double-quotes you can use
355  *   single (') quotes for the enclosing quotes.
356  *
357  * - Special characters like < and > must use html entities,
358  *   they will be converted back to characters for the final output.
359  */
360
361 $SEPARATOR = ";=========================================================================";
362
363 $preamble = "
364 ; This is the main configuration file for PhpWiki in INI-style format.
365 ; Note that certain characters are used as comment char and therefore
366 ; these entries must be in double-quotes. Such as \":\", \";\", \",\" and \"|\"
367 ; Take special care for DBAUTH_ sql statements. (Part 3a)
368 ;
369 ; This file is divided into several parts: Each one has different configuration
370 ; settings you can change; in all cases the default should work on your system,
371 ; however, we recommend you tailor things to your particular setting.
372 ; Here undefined definitions get defined by config-default.ini settings.
373 ";
374
375 // Detect not here listed configs:
376 // for x in `perl -ne 'print $1,"\n" if /^;(\w+) =/' config/config-dist.ini`; do \
377 //   grep \'$x\' configurator.php >/dev/null || echo $x ; done
378
379 $properties["Part Zero"] =
380     new part('_part0', $SEPARATOR . "\n", "
381 Part Zero: (optional)
382 Latest Development and Tricky Options");
383
384 if (defined('INCLUDE_PATH'))
385     $include_path = INCLUDE_PATH;
386 else {
387     if (substr(PHP_OS, 0, 3) == 'WIN') {
388         $include_path = dirname(__FILE__) . ';' . ini_get('include_path');
389         if (strchr(ini_get('include_path'), '/'))
390             $include_path = strtr($include_path, '\\', '/');
391     } else {
392         $include_path = dirname(__FILE__) . ':' . ini_get('include_path');
393     }
394 }
395
396 $properties["PHP include_path"] =
397     new _define('INCLUDE_PATH', $include_path);
398
399 // TODO: Convert this to a checkbox row as in tests/unit/test.php
400 $properties["DEBUG"] =
401     new numeric_define_optional('DEBUG', DEBUG);
402
403 $properties["ENABLE_EDIT_TOOLBAR"] =
404     new boolean_define_commented_optional('ENABLE_EDIT_TOOLBAR');
405
406 $properties["JS_SEARCHREPLACE"] =
407     new boolean_define_commented_optional('JS_SEARCHREPLACE');
408
409 // TESTME: use config-default:  = false
410 $properties["ENABLE_DOUBLECLICKEDIT"] =
411     new boolean_define_commented_optional('ENABLE_DOUBLECLICKEDIT');
412
413 $properties["ENABLE_WYSIWYG"] =
414     new boolean_define_commented_optional('ENABLE_WYSIWYG');
415
416 $properties["WYSIWYG_BACKEND"] =
417     new _define_selection(
418         'WYSIWYG_BACKEND',
419         array('Wikiwyg' => 'Wikiwyg',
420             'tinymce' => 'tinymce',
421             'CKeditor' => 'CKeditor',
422             'spaw' => 'spaw',
423             'htmlarea3' => 'htmlarea3',
424             'htmlarea2' => 'htmlarea2',
425         ));
426
427 $properties["WYSIWYG_DEFAULT_PAGETYPE_HTML"] =
428     new boolean_define_commented_optional('WYSIWYG_DEFAULT_PAGETYPE_HTML');
429
430 $properties["UPLOAD_USERDIR"] =
431     new boolean_define_commented_optional('UPLOAD_USERDIR');
432
433 $properties["DISABLE_UNITS"] =
434     new boolean_define_commented_optional('DISABLE_UNITS');
435
436 $properties["UNITS_EXE"] =
437     new _define_commented_optional('UNITS_EXE');
438
439 $properties["ENABLE_XHTML_XML"] =
440     new boolean_define_commented_optional('ENABLE_XHTML_XML');
441
442 $properties["ENABLE_OPEN_GRAPH"] =
443     new boolean_define_commented_optional('ENABLE_OPEN_GRAPH');
444
445 $properties["ENABLE_SPAMASSASSIN"] =
446     new boolean_define_commented_optional('ENABLE_SPAMASSASSIN');
447
448 $properties["ENABLE_SPAMBLOCKLIST"] =
449     new boolean_define_optional('ENABLE_SPAMBLOCKLIST');
450
451 $properties["NUM_SPAM_LINKS"] =
452     new numeric_define_optional('NUM_SPAM_LINKS');
453
454 $properties["GOOGLE_LINKS_NOFOLLOW"] =
455     new boolean_define_commented_optional('GOOGLE_LINKS_NOFOLLOW');
456
457 $properties["ENABLE_DISCUSSION_LINK"] =
458     new boolean_define_commented_optional('ENABLE_DISCUSSION_LINK');
459
460 $properties["ENABLE_CAPTCHA"] =
461     new boolean_define_commented_optional('ENABLE_CAPTCHA');
462
463 $properties["USE_CAPTCHA_RANDOM_WORD"] =
464     new boolean_define_commented_optional('USE_CAPTCHA_RANDOM_WORD');
465
466 $properties["USE_SAFE_DBSESSION"] =
467     new boolean_define_commented_optional('USE_SAFE_DBSESSION');
468
469 $properties["BLOG_DEFAULT_EMPTY_PREFIX"] =
470     new boolean_define_commented_optional('BLOG_DEFAULT_EMPTY_PREFIX');
471
472 $properties["ENABLE_SEARCHHIGHLIGHT"] =
473     new boolean_define_commented_optional('ENABLE_SEARCHHIGHLIGHT');
474
475 $properties["Part One"] =
476     new part('_part1', $SEPARATOR . "\n", "
477 Part One: Authentication and security settings. See Part Three for more.");
478
479 $properties["Wiki Name"] =
480     new _define_optional('WIKI_NAME', WIKI_NAME);
481
482 $properties["Admin Username"] =
483     new _define_notempty('ADMIN_USER', ADMIN_USER, "
484 You must set this! Username and password of the administrator.",
485         "onchange=\"validate_ereg('Sorry, ADMIN_USER cannot be empty.', '^.+$', 'ADMIN_USER', this);\"");
486
487 $properties["Admin Password"] =
488     new _define_password('ADMIN_PASSWD', ADMIN_PASSWD, "
489 You must set this!
490 For heaven's sake pick a good password.
491
492 If your version of PHP supports encrypted passwords, your password will be
493 automatically encrypted within the generated config file.
494 Use the \"Create Random Password\" button to create a good (random) password.
495
496 ADMIN_PASSWD is ignored on HttpAuth",
497         "onchange=\"validate_ereg('Sorry, ADMIN_PASSWD must be at least 4 chars long.', '^....+$', 'ADMIN_PASSWD', this);\"");
498
499 $properties["Encrypted Passwords"] =
500     new boolean_define
501     ('ENCRYPTED_PASSWD',
502         array('true' => "true.  use crypt for all passwords",
503             'false' => "false. use plaintest passwords (not recommended)"));
504
505 $properties["Reverse DNS"] =
506     new boolean_define_optional
507     ('ENABLE_REVERSE_DNS',
508         array('true' => "true. perform additional reverse dns lookups",
509             'false' => "false. just record the address as given by the httpd server"));
510
511 $properties["ZIP Dump Authentication"] =
512     new boolean_define_optional('ZIPDUMP_AUTH',
513         array('false' => "false. Everyone may download zip dumps",
514             'true' => "true. Only admin may download zip dumps"));
515
516 $properties["Enable RawHtml Plugin"] =
517     new boolean_define_commented_optional('ENABLE_RAW_HTML');
518
519 $properties["Allow RawHtml Plugin only on locked pages"] =
520     new boolean_define_commented_optional('ENABLE_RAW_HTML_LOCKEDONLY');
521
522 $properties["Allow RawHtml Plugin if safe HTML code"] =
523     new boolean_define_commented_optional('ENABLE_RAW_HTML_SAFE', '', "
524 If this is set, all unsafe html code is stripped automatically (experimental!)
525 See <a href=\"http://chxo.com/scripts/safe_html-test.php\" target=\"_new\">chxo.com/scripts/safe_html-test.php</a>
526 ");
527
528 $properties["Maximum Upload Size"] =
529     new numeric_define_optional('MAX_UPLOAD_SIZE', MAX_UPLOAD_SIZE);
530
531 $properties["Minor Edit Timeout"] =
532     new numeric_define_optional('MINOR_EDIT_TIMEOUT', MINOR_EDIT_TIMEOUT);
533
534 $properties["Disabled Actions"] =
535     new array_define('DISABLED_ACTIONS', DISABLED_ACTIONS /*array()*/);
536
537 $properties["Moderate all Pagechanges"] =
538     new boolean_define_commented_optional('ENABLE_MODERATEDPAGE_ALL');
539
540 $properties["Access Log File"] =
541     new _define_commented_optional('ACCESS_LOG', ACCESS_LOG);
542
543 $properties["Access Log SQL"] =
544     new _define_selection(
545         'ACCESS_LOG_SQL',
546         array('0' => 'disabled',
547             '1' => 'read only',
548             '2' => 'read + write'));
549
550 $properties["Compress Output"] =
551     new boolean_define_commented_optional
552     ('COMPRESS_OUTPUT',
553         array('' => 'undefined - GZIP compress when appropriate.',
554             'false' => 'Never compress output.',
555             'true' => 'Always try to compress output.'));
556
557 $properties["HTTP Cache Control"] =
558     new _define_selection_optional
559     ('CACHE_CONTROL',
560         array('LOOSE' => 'LOOSE',
561             'STRICT' => 'STRICT',
562             'NO_CACHE' => 'NO_CACHE',
563             'ALLOW_STALE' => 'ALLOW_STALE'),
564         "
565 HTTP CACHE_CONTROL
566
567 This controls how PhpWiki sets the HTTP cache control
568 headers (Expires: and Cache-Control:)
569
570 Choose one of:
571 <dl>
572 <dt>NO_CACHE</dt>
573 <dd>This is roughly the old (pre 1.3.4) behaviour.  PhpWiki will
574     instruct proxies and browsers never to cache PhpWiki output.</dd>
575 <dt>STRICT</dt>
576 <dd>Cached pages will be invalidated whenever the database global
577     timestamp changes.  This should behave just like NONE (modulo
578     bugs in PhpWiki and your proxies and browsers), except that
579     things will be slightly more efficient.</dd>
580 <dt>LOOSE</dt>
581 <dd>Cached pages will be invalidated whenever they are edited,
582     or, if the pages include plugins, when the plugin output could
583     conceivably have changed.
584     <p>Behavior should be much like STRICT, except that sometimes
585        wikilinks will show up as undefined (with the question mark)
586        when in fact they refer to (recently) created pages.
587        (Hitting your browsers reload or perhaps shift-reload button
588        should fix the problem.)</p></dd>
589 <dt>ALLOW_STALE</dt>
590 <dd>Proxies and browsers will be allowed to used stale pages.
591     (The timeout for stale pages is controlled by CACHE_CONTROL_MAX_AGE.)
592     <p>This setting will result in quirky behavior.  When you edit a
593        page your changes may not show up until you shift-reload the
594        page, etc...</p>
595     <p>This setting is generally not advisable, however it may be useful
596        in certain cases (e.g. if your wiki gets lots of page views,
597        and few edits by knowledgeable people who won't freak over the quirks.)</p>
598 </dd>
599 </dl>
600 The default is currently LOOSE.");
601
602 $properties["HTTP Cache Control Max Age"] =
603     new numeric_define_optional('CACHE_CONTROL_MAX_AGE', CACHE_CONTROL_MAX_AGE);
604
605 $properties["Markup Caching"] =
606     new boolean_define_commented_optional
607     ('WIKIDB_NOCACHE_MARKUP',
608         array('false' => 'Enable markup cache',
609             'true' => 'Disable markup cache'));
610
611 $properties["COOKIE_EXPIRATION_DAYS"] =
612     new numeric_define_optional('COOKIE_EXPIRATION_DAYS', COOKIE_EXPIRATION_DAYS);
613
614 $properties["COOKIE_DOMAIN"] =
615     new _define_commented_optional('COOKIE_DOMAIN', COOKIE_DOMAIN);
616
617 $properties["Path for PHP Session Support"] =
618     new _define_optional('SESSION_SAVE_PATH', defined('SESSION_SAVE_PATH') ? SESSION_SAVE_PATH : ini_get('session.save_path'));
619
620 $properties["Force PHP Database Sessions"] =
621     new boolean_define_commented_optional
622     ('USE_DB_SESSION',
623         array('false' => 'Disable database sessions, use files',
624             'true' => 'Enable database sessions'));
625
626 ///////// database selection
627
628 $properties["Part Two"] =
629     new part('_part2', $SEPARATOR . "\n", "
630
631 Part Two:
632 Database Configuration
633 ");
634
635 $properties["Database Type"] =
636     new _define_selection("DATABASE_TYPE",
637         array('dba' => "dba",
638             'SQL' => "SQL PEAR",
639             'ADODB' => "SQL ADODB",
640             'PDO' => "PDO (php5 only)",
641             'file' => "flatfile")/*, "
642 Select the database backend type:
643 Choose dba (default) to use one of the standard UNIX dba libraries. This is the fastest.
644 Choose ADODB or SQL to use an SQL database with ADODB or PEAR.
645 Choose PDO on php5 to use an SQL database. (experimental, no paging yet)
646 flatfile is simple and slow.
647 Recommended is dba or SQL: PEAR or ADODB."*/);
648
649 $properties["SQL DSN Setup"] =
650     new unchangeable_variable('_sqldsnstuff', "", "
651 For SQL based backends, specify the database as a DSN
652 The most general form of a DSN looks like:
653 <pre>
654   phptype(dbsyntax)://username:password@protocol+hostspec/database?option=value
655 </pre>
656 For a MySQL database, the following should work:
657 <pre>
658    mysql://user:password@host/databasename
659 </pre>
660 To connect over a unix socket, use something like
661 <pre>
662    mysql://user:password@unix(/path/to/socket)/databasename
663 </pre>
664 <pre>
665   DATABASE_DSN = mysql://guest@:/var/lib/mysql/mysql.sock/phpwiki
666   DATABASE_DSN = mysql://guest@localhost/phpwiki
667   DATABASE_DSN = pgsql://localhost/user_phpwiki
668 </pre>");
669
670 // Choose ADODB or SQL to use an SQL database with ADODB or PEAR.
671 // Choose dba to use one of the standard UNIX dbm libraries.
672
673 $properties["SQL Type"] =
674     new _variable_selection('_dsn_sqltype',
675         array('mysql' => "MySQL",
676             'pgsql' => "PostgreSQL",
677             'mssql' => "Microsoft SQL Server",
678             'mssqlnative' => "Microsoft SQL Server (native)",
679             'oci8' => "Oracle 8",
680             'mysqli' => "mysqli (only ADODB)",
681             'mysqlt' => "mysqlt (only ADODB)",
682             'ODBC' => "ODBC (only ADODB or PDO)",
683             'firebird' => "Firebird (only PDO)",
684             'oracle' => "Oracle (only PDO)",
685         ), "
686 SQL DB types. The DSN hosttype.");
687
688 $properties["SQL User"] =
689     new _variable('_dsn_sqluser', "wikiuser", "
690 SQL User Id:");
691
692 $properties["SQL Password"] =
693     new _variable('_dsn_sqlpass', "", "
694 SQL Password:");
695
696 $properties["SQL Database Host"] =
697     new _variable('_dsn_sqlhostorsock', "localhost", "
698 SQL Database Hostname:
699
700 To connect over a local named socket, use something like
701 <pre>
702   unix(/var/lib/mysql/mysql.sock)
703 </pre>
704 here.
705 mysql on Windows via named pipes might need 127.0.0.1");
706
707 $properties["SQL Database Name"] =
708     new _variable('_dsn_sqldbname', "phpwiki", "
709 SQL Database Name:");
710
711 $dsn_sqltype = $properties["SQL Type"]->value();
712 $dsn_sqluser = $properties["SQL User"]->value();
713 $dsn_sqlpass = $properties["SQL Password"]->value();
714 $dsn_sqlhostorsock = $properties["SQL Database Host"]->value();
715 $dsn_sqldbname = $properties["SQL Database Name"]->value();
716 $dsn_sqlstring = $dsn_sqltype . "://{$dsn_sqluser}:{$dsn_sqlpass}@{$dsn_sqlhostorsock}/{$dsn_sqldbname}";
717
718 $properties["SQL dsn"] =
719     new unchangeable_define("DATABASE_DSN",
720         $dsn_sqlstring, "
721 Calculated from the settings above:");
722
723 $properties["Filename / Table name Prefix"] =
724     new _define_commented('DATABASE_PREFIX', DATABASE_PREFIX, "
725 Used by all DB types:
726
727 Prefix for filenames or table names, e.g. \"phpwiki_\"
728
729 Currently <b>you MUST EDIT THE SQL file too!</b> (in the schemas/
730 directory because we aren't doing on the fly sql generation
731 during the installation.
732
733 Note: This prefix is NOT prepended to the default DBAUTH_
734       tables user, pref and member!
735 ");
736
737 $properties["DATABASE_PERSISTENT"] =
738     new boolean_define_commented_optional
739     ('DATABASE_PERSISTENT',
740         array('false' => "Disabled",
741             'true' => "Enabled"));
742
743 $properties["DB Session table"] =
744     new _define_optional("DATABASE_SESSION_TABLE", DATABASE_SESSION_TABLE, "
745 Tablename to store session information. Only supported by SQL backends.
746
747 A word of warning - any prefix defined above will be prepended to whatever is given here.
748 ");
749
750 //TODO: $TEMP
751 $temp = !empty($_ENV['TEMP']) ? $_ENV['TEMP'] : "/tmp";
752 $properties["dba directory"] =
753     new _define("DATABASE_DIRECTORY", $temp);
754
755 // TODO: list the available methods
756 $properties["dba handler"] =
757     new _define_selection('DATABASE_DBA_HANDLER',
758         array('gdbm' => "gdbm - GNU database manager (not recommended anymore)",
759             'dbm' => "DBM - Redhat default. On sf.net there's dbm and not gdbm anymore",
760             'db2' => "DB2 - BerkeleyDB (Sleepycat) DB2",
761             'db3' => "DB3 - BerkeleyDB (Sleepycat) DB3. Default on Windows but not on every Linux",
762             'db4' => "DB4 - BerkeleyDB (Sleepycat) DB4."), "
763 Use 'gdbm', 'dbm', 'db2', 'db3' or 'db4' depending on your DBA handler methods supported: <br />  "
764             . join(", ", dba_handlers())
765             . "\n\nBetter not use other hacks such as inifile, flatfile or cdb");
766
767 $properties["dba timeout"] =
768     new numeric_define("DATABASE_TIMEOUT", DATABASE_TIMEOUT, "
769 Recommended values are 10-20 seconds. The more load the server has, the higher the timeout.");
770
771 $properties["DATABASE_OPTIMISE_FREQUENCY"] =
772     new numeric_define_optional('DATABASE_OPTIMISE_FREQUENCY', DATABASE_OPTIMISE_FREQUENCY);
773
774 $properties["DBADMIN_USER"] =
775     new _define_optional('DBADMIN_USER', DBADMIN_USER);
776
777 $properties["DBADMIN_PASSWD"] =
778     new _define_password_optional('DBADMIN_PASSWD', DBADMIN_PASSWD);
779
780 $properties["USECACHE"] =
781     new boolean_define_commented_optional('USECACHE');
782
783 ///////////////////
784
785 $properties["Page Revisions"] =
786     new unchangeable_variable('_parttworevisions', "", "
787
788 Section 2a: Archive Cleanup
789 The next section controls how many old revisions of each page are kept in the database.
790
791 There are two basic classes of revisions: major and minor. Which
792 class a revision belongs in is determined by whether the author
793 checked the \"this is a minor revision\" checkbox when they saved the
794 page.
795
796 There is, additionally, a third class of revisions: author
797 revisions. The most recent non-mergable revision from each distinct
798 author is and author revision.
799
800 The expiry parameters for each of those three classes of revisions
801 can be adjusted separately. For each class there are five
802 parameters (usually, only two or three of the five are actually
803 set) which control how long those revisions are kept in the
804 database.
805 <dl>
806    <dt>max_keep:</dt> <dd>If set, this specifies an absolute maximum for the
807             number of archived revisions of that class. This is
808             meant to be used as a safety cap when a non-zero
809             min_age is specified. It should be set relatively high,
810             and it's purpose is to prevent malicious or accidental
811             database overflow due to someone causing an
812             unreasonable number of edits in a short period of time.</dd>
813
814   <dt>min_age:</dt>  <dd>Revisions younger than this (based upon the supplanted
815             date) will be kept unless max_keep is exceeded. The age
816             should be specified in days. It should be a
817             non-negative, real number,</dd>
818
819   <dt>min_keep:</dt> <dd>At least this many revisions will be kept.</dd>
820
821   <dt>keep:</dt>     <dd>No more than this many revisions will be kept.</dd>
822
823   <dt>max_age:</dt>  <dd>No revision older than this age will be kept.</dd>
824 </dl>
825 Supplanted date: Revisions are timestamped at the instant that they
826 cease being the current revision. Revision age is computed using
827 this timestamp, not the edit time of the page.
828
829 Merging: When a minor revision is deleted, if the preceding
830 revision is by the same author, the minor revision is merged with
831 the preceding revision before it is deleted. Essentially: this
832 replaces the content (and supplanted timestamp) of the previous
833 revision with the content after the merged minor edit, the rest of
834 the page metadata for the preceding version (summary, mtime, ...)
835 is not changed.
836 ");
837
838 // For now the expiration parameters are statically inserted as
839 // an unchangeable property. You'll have to edit the resulting
840 // config file if you really want to change these from the default.
841
842 $properties["Major Edits: keep minimum days"] =
843     new numeric_define('MAJOR_MIN_KEEP', MAJOR_MIN_KEEP, "
844 Default: Keep for unlimited time.
845 Set to 0 to enable archive cleanup");
846 $properties["Minor Edits: keep minumum days"] =
847     new numeric_define('MINOR_MIN_KEEP', MINOR_MIN_KEEP, "
848 Default: Keep for unlimited time.
849 Set to 0 to enable archive cleanup");
850
851 $properties["Major Edits: how many"] =
852     new numeric_define('MAJOR_KEEP', MAJOR_KEEP, "
853 Keep up to 8 major edits");
854 $properties["Major Edits: how many days"] =
855     new numeric_define('MAJOR_MAX_AGE', MAJOR_MAX_AGE, "
856 keep them no longer than a month");
857
858 $properties["Minor Edits: how many"] =
859     new numeric_define("MINOR_KEEP", MINOR_KEEP, "
860 Keep up to 4 minor edits");
861 $properties["Minor Edits: how many days"] =
862     new numeric_define("MINOR_MAX_AGE", "7", "
863 keep them no longer than a week");
864
865 $properties["per Author: how many"] =
866     new numeric_define("AUTHOR_KEEP", "8", "
867 Keep the latest contributions of the last 8 authors,");
868 $properties["per Author: how many days"] =
869     new numeric_define("AUTHOR_MAX_AGE", "365", "
870 up to a year.");
871 $properties["per Author: keep minumum days"] =
872     new numeric_define("AUTHOR_MIN_AGE", "7", "
873 Additionally, (in the case of a particularly active page) try to
874 keep the latest contributions of all authors in the last week (even if there are more than eight of them,)");
875 $properties["per Author: max revisions"] =
876     new numeric_define("AUTHOR_MAX_KEEP", "20", "
877 but in no case keep more than twenty unique author revisions.");
878
879 /////////////////////////////////////////////////////////////////////
880
881 $properties["Part Three"] =
882     new part('_part3', $SEPARATOR . "\n", "
883
884 Part Three: (optional)
885 Basic User Authentication Setup
886 ");
887
888 $properties["Publicly viewable"] =
889     new boolean_define_optional('ALLOW_ANON_USER',
890         array('true' => "true. Permit anonymous view. (Default)",
891             'false' => "false. Force login even on view (strictly private)"), "
892 If ALLOW_ANON_USER is false, you have to login before viewing any page or doing any other action on a page.");
893
894 $properties["Allow anonymous edit"] =
895     new boolean_define_optional('ALLOW_ANON_EDIT',
896         array('true' => "true. Permit anonymous users to edit. (Default)",
897             'false' => "false. Force login on edit (moderately locked)"), "
898 If ALLOW_ANON_EDIT is false, you have to login before editing or changing any page. See below.");
899
900 $properties["Allow Bogo Login"] =
901     new boolean_define_optional('ALLOW_BOGO_LOGIN',
902         array('true' => "true. Users may Sign In with any WikiWord, without password. (Default)",
903             'false' => "false. Require stricter authentication."), "
904 If ALLOW_BOGO_LOGIN is false, you may not login with any wikiword username and empty password.
905 If true, users are allowed to create themselves with any WikiWord username. See below.");
906
907 $properties["Allow User Passwords"] =
908     new boolean_define_optional('ALLOW_USER_PASSWORDS',
909         array('true' => "True user authentication with password checking. (Default)",
910             'false' => "false. Ignore authentication settings below."), "
911 If ALLOW_USER_PASSWORDS is true, the authentication settings below define where and how to
912 check against given username/passwords. For completely security disable BOGO_LOGIN and ANON_EDIT above.");
913
914 $properties["User Authentication Methods"] =
915     new array_define('USER_AUTH_ORDER', array("PersonalPage", "Db"), "
916 Many different methods can be used to check user's passwords.
917 Try any of these in the given order:
918 <dl>
919 <dt>BogoLogin</dt>
920         <dd>WikiWord username, with no *actual* password checking,
921         although the user will still have to enter one.</dd>
922 <dt>PersonalPage</dt>
923         <dd>Store passwords in the users homepage metadata (simple)</dd>
924 <dt>Db</dt>
925         <dd>Use DBAUTH_AUTH_* (see below) with PearDB or ADODB only.</dd>
926 <dt>LDAP</dt>
927         <dd>Authenticate against LDAP_AUTH_HOST with LDAP_BASE_DN.</dd>
928 <dt>IMAP</dt>
929         <dd>Authenticate against IMAP_AUTH_HOST (email account)</dd>
930 <dt>POP3</dt>
931         <dd>Authenticate against POP3_AUTH_HOST (email account)</dd>
932 <dt>Session</dt>
933         <dd>Get username and level from a PHP session variable. (e.g. for FusionForge)</dd>
934 <dt>File</dt>
935         <dd>Store username:crypted-passwords in .htaccess like files.
936          Use Apache's htpasswd to manage this file.</dd>
937 <dt>HttpAuth</dt>
938         <dd>Use the protection by the webserver (.htaccess/.htpasswd) (experimental)
939         Enforcing HTTP Auth not yet. Note that the ADMIN_USER should exist also.
940         Using HttpAuth disables all other methods and no userauth sessions are used.</dd>
941 </dl>
942
943 Several of these methods can be used together, in the manner specified by
944 USER_AUTH_POLICY, below.  To specify multiple authentication methods,
945 separate the name of each one with colons.
946 <pre>
947   USER_AUTH_ORDER = 'PersonalPage : Db'
948   USER_AUTH_ORDER = 'BogoLogin : PersonalPage'
949 </pre>");
950
951 $properties["ENABLE_AUTH_OPENID"] =
952     new boolean_define('ENABLE_AUTH_OPENID');
953
954 $properties["PASSWORD_LENGTH_MINIMUM"] =
955     new numeric_define('PASSWORD_LENGTH_MINIMUM', PASSWORD_LENGTH_MINIMUM);
956
957 $properties["USER_AUTH_POLICY"] =
958     new _define_selection('USER_AUTH_POLICY',
959         array('first-only' => "first-only - use only the first method in USER_AUTH_ORDER",
960             'old' => "old - ignore USER_AUTH_ORDER (legacy)",
961             'strict' => "strict - check all methods for userid + password (recommended)",
962             'stacked' => "stacked - check all methods for userid, and if found for password"), "
963 The following policies are available for user authentication:
964 <dl>
965 <dt>first-only</dt>
966         <dd>use only the first method in USER_AUTH_ORDER</dd>
967 <dt>old</dt>
968         <dd>ignore USER_AUTH_ORDER and try to use all available
969         methods as in the previous PhpWiki releases (slow)</dd>
970 <dt>strict</dt>
971         <dd>check if the user exists for all methods:
972         on the first existing user, try the password.
973         dont try the other methods on failure then</dd>
974 <dt>stacked</dt>
975         <dd>check the given user - password combination for all
976         methods and return true on the first success.</dd></dl>");
977
978 $properties["ENABLE_PAGEPERM"] =
979     new boolean_define_commented_optional('ENABLE_PAGEPERM');
980
981 ///////////////////
982
983 $properties["Part Three A"] =
984     new part('_part3a', $SEPARATOR . "\n", "
985
986 Part Three A: (optional)
987 Group Membership");
988
989 $properties["Group membership"] =
990     new _define_selection("GROUP_METHOD",
991         array('WIKIPAGE' => "WIKIPAGE - List at \"CategoryGroup\". (Slowest, but easiest to maintain)",
992             'NONE' => "NONE - Disable group membership (Fastest)",
993             'DB' => "DB - SQL Database, Optionally external. See USERS/GROUPS queries",
994             'FILE' => "Flatfile. See AUTH_GROUP_FILE below.",
995             'LDAP' => "LDAP - See \"LDAP authentication options\" above. (Experimental)"), "
996 Group membership.  PhpWiki supports defining permissions for a group as
997 well as for individual users.  This defines how group membership information
998 is obtained.  Supported values are:
999 <dl>
1000 <dt>\"NONE\"</dt>
1001           <dd>Disable group membership (Fastest). Note the required quoting.</dd>
1002 <dt>WIKIPAGE</dt>
1003           <dd>Define groups as list at \"CategoryGroup\". (Slowest, but easiest to maintain)</dd>
1004 <dt>DB</dt>
1005           <dd>Stored in an SQL database. Optionally external. See USERS/GROUPS queries</dd>
1006 <dt>FILE</dt>
1007           <dd>Flatfile. See AUTH_GROUP_FILE below.</dd>
1008 <dt>LDAP</dt>
1009           <dd>LDAP groups. See \"LDAP authentication options\" above and
1010           lib/WikiGroup.php. (experimental)</dd></dl>");
1011
1012 $properties["CATEGORY_GROUP_PAGE"] =
1013     new _define_optional('CATEGORY_GROUP_PAGE', _("CategoryGroup"), "
1014 If GROUP_METHOD = WIKIPAGE:
1015
1016 Page where all groups are listed.");
1017
1018 $properties["AUTH_GROUP_FILE"] =
1019     new _define_optional('AUTH_GROUP_FILE', "/etc/groups", "
1020 For GROUP_METHOD = FILE, the file given below is referenced to obtain
1021 group membership information.  It should be in the same format as the
1022 standard unix /etc/groups(5) file.");
1023
1024 $properties["Part Three B"] =
1025     new part('_part3b', $SEPARATOR . "\n", "
1026
1027 Part Three B: (optional)
1028 External database authentication and authorization.
1029
1030 If USER_AUTH_ORDER includes Db, or GROUP_METHOD = DB, the options listed
1031 below define the SQL queries used to obtain the information out of the
1032 database, and (optionally) store the information back to the DB.");
1033
1034 $properties["DBAUTH_AUTH_DSN"] =
1035     new _define_optional('DBAUTH_AUTH_DSN', $dsn_sqlstring, "
1036 A database DSN to connect to.  Defaults to the DSN specified for the Wiki as a whole.");
1037
1038 $properties["User Exists Query"] =
1039     new _define('DBAUTH_AUTH_USER_EXISTS', "SELECT userid FROM user WHERE userid='\$userid'", "
1040 USER/PASSWORD queries:
1041
1042 For USER_AUTH_POLICY=strict and the Db method is required");
1043
1044 $properties["Check Query"] =
1045     new _define_optional('DBAUTH_AUTH_CHECK', "SELECT IF(passwd='\$password',1,0) AS ok FROM user WHERE userid='\$userid'", "
1046
1047 Check to see if the supplied username/password pair is OK
1048
1049 Plaintext passwords: (DBAUTH_AUTH_CRYPT_METHOD = plain)<br />
1050 ; DBAUTH_AUTH_CHECK = \"SELECT IF(passwd='\$password',1,0) AS ok FROM user WHERE userid='\$userid'\"
1051
1052 database-hashed passwords (more secure):<br />
1053 ; DBAUTH_AUTH_CHECK = \"SELECT IF(passwd=PASSWORD('\$password'),1,0) AS ok FROM user WHERE userid='\$userid'\"");
1054
1055 $properties["Crypt Method"] =
1056     new _define_selection_optional
1057     ('DBAUTH_AUTH_CRYPT_METHOD',
1058         array('plain' => 'plain',
1059             'crypt' => 'crypt'), "
1060 If you want to use Unix crypt()ed passwords, you can use DBAUTH_AUTH_CHECK
1061 to get the password out of the database with a simple SELECT query, and
1062 specify DBAUTH_AUTH_USER_EXISTS and DBAUTH_AUTH_CRYPT_METHOD:
1063
1064 ; DBAUTH_AUTH_CHECK = \"SELECT passwd FROM user where userid='\$userid'\" <br />
1065 ; DBAUTH_AUTH_CRYPT_METHOD = crypt");
1066
1067 $properties["Update the user's authentication credential"] =
1068     new _define('DBAUTH_AUTH_UPDATE', "UPDATE user SET passwd='\$password' WHERE userid='\$userid'", "
1069 If this is not defined but DBAUTH_AUTH_CHECK is, then the user will be unable to update their
1070 password.
1071
1072 Plaintext passwords:<br />
1073   DBAUTH_AUTH_UPDATE = \"UPDATE user SET passwd='\$password' WHERE userid='\$userid'\"<br />
1074 Database-hashed passwords:<br />
1075   DBAUTH_AUTH_UPDATE = \"UPDATE user SET passwd=PASSWORD('\$password') WHERE userid='\$userid'\"");
1076
1077 $properties["Allow the user to create their own account"] =
1078     new _define_optional('DBAUTH_AUTH_CREATE', "INSERT INTO user SET passwd=PASSWORD('\$password'),userid='\$userid'", "
1079 If this is empty, Db users cannot subscribe by their own.");
1080
1081 $properties["USER/PREFERENCE queries"] =
1082     new _define_optional('DBAUTH_PREF_SELECT', "SELECT prefs FROM user WHERE userid='\$userid'", "
1083 If you choose to store your preferences in an external database, enable
1084 the following queries.  Note that if you choose to store user preferences
1085 in the 'user' table, only registered users get their prefs from the database,
1086 self-created users do not.  Better to use the special 'pref' table.
1087
1088 The prefs field stores the serialized form of the user's preferences array,
1089 to ease the complication of storage.
1090 <pre>
1091   DBAUTH_PREF_SELECT = \"SELECT prefs FROM user WHERE userid='\$userid'\"
1092   DBAUTH_PREF_SELECT = \"SELECT prefs FROM pref WHERE userid='\$userid'\"
1093 </pre>");
1094
1095 $properties["Update the user's preferences"] =
1096     new _define_optional('DBAUTH_PREF_UPDATE', "UPDATE user SET prefs='\$pref_blob' WHERE userid='\$userid'", "
1097 Note that REPLACE works only with mysql and destroy all other columns!
1098
1099 Mysql: DBAUTH_PREF_UPDATE = \"REPLACE INTO pref SET prefs='\$pref_blob',userid='\$userid'\"");
1100
1101 $properties["Create new user's preferences"] =
1102     new _define_optional('DBAUTH_PREF_INSERT', "INSERT INTO pref (userid,prefs) VALUES ('\$userid','\$pref_blob')", "
1103 Define this if new user can be create by themselves.
1104 ");
1105
1106 $properties["USERS/GROUPS queries"] =
1107     new _define_optional('DBAUTH_IS_MEMBER', "SELECT user FROM user WHERE user='\$userid' AND group='\$groupname'", "
1108 You can define 1:n or n:m user<=>group relations, as you wish.
1109
1110 Sample configurations:
1111
1112 only one group per user (1:n):<br />
1113    DBAUTH_IS_MEMBER = \"SELECT user FROM user WHERE user='\$userid' AND group='\$groupname'\"<br />
1114    DBAUTH_GROUP_MEMBERS = \"SELECT user FROM user WHERE group='\$groupname'\"<br />
1115    DBAUTH_USER_GROUPS = \"SELECT group FROM user WHERE user='\$userid'\"<br />
1116 multiple groups per user (n:m):<br />
1117    DBAUTH_IS_MEMBER = \"SELECT userid FROM member WHERE userid='\$userid' AND groupname='\$groupname'\"<br />
1118    DBAUTH_GROUP_MEMBERS = \"SELECT DISTINCT userid FROM member WHERE groupname='\$groupname'\"<br />
1119    DBAUTH_USER_GROUPS = \"SELECT groupname FROM member WHERE userid='\$userid'\"<br />");
1120 $properties["DBAUTH_GROUP_MEMBERS"] =
1121     new _define_optional('DBAUTH_GROUP_MEMBERS', "SELECT user FROM user WHERE group='\$groupname'", "");
1122 $properties["DBAUTH_USER_GROUPS"] =
1123     new _define_optional('DBAUTH_USER_GROUPS', "SELECT group FROM user WHERE user='\$userid'", "");
1124
1125 $properties["LDAP AUTH Host"] =
1126     new _define_optional('LDAP_AUTH_HOST', "ldap://localhost:389", "
1127 If USER_AUTH_ORDER contains Ldap:
1128
1129 The LDAP server to connect to.  Can either be a hostname, or a complete
1130 URL to the server (useful if you want to use ldaps or specify a different
1131 port number).");
1132
1133 $properties["LDAP BASE DN"] =
1134     new _define_optional('LDAP_BASE_DN', "ou=mycompany.com,o=My Company", "
1135 The organizational or domain BASE DN: e.g. \"dc=mydomain,dc=com\".
1136
1137 Note: ou=Users and ou=Groups are used for GroupLdap Membership
1138 Better use LDAP_OU_USERS and LDAP_OU_GROUP with GROUP_METHOD=LDAP.");
1139
1140 $properties["LDAP SET OPTION"] =
1141     new _define_optional('LDAP_SET_OPTION', "LDAP_OPT_PROTOCOL_VERSION=3:LDAP_OPT_REFERRALS=0", "
1142 Some LDAP servers need some more options, such as the Windows Active
1143 Directory Server.  Specify the options (as allowed by the PHP LDAP module)
1144 and their values as NAME=value pairs separated by colons.");
1145
1146 $properties["LDAP AUTH USER"] =
1147     new _define_optional('LDAP_AUTH_USER', "CN=ldapuser,ou=Users,o=Development,dc=mycompany.com", "
1148 DN to initially bind to the LDAP server as. This is needed if the server doesn't
1149 allow anonymous queries. (Windows Active Directory Server)");
1150
1151 $properties["LDAP AUTH PASSWORD"] =
1152     new _define_optional('LDAP_AUTH_PASSWORD', "secret", "
1153 Password to use to initially bind to the LDAP server, as the DN
1154 specified in the LDAP_AUTH_USER option (above).");
1155
1156 $properties["LDAP SEARCH FIELD"] =
1157     new _define_optional('LDAP_SEARCH_FIELD', "uid", "
1158 If you want to match usernames against an attribute other than uid,
1159 specify it here. Default: uid
1160
1161 e.g.: LDAP_SEARCH_FIELD = sAMAccountName");
1162
1163 $properties["LDAP OU USERS"] =
1164     new _define_optional('LDAP_OU_USERS', "ou=Users", "
1165 If you have an organizational unit for all users, define it here.
1166 This narrows the search, and is needed for LDAP group membership (if GROUP_METHOD=LDAP)
1167 Default: ou=Users");
1168
1169 $properties["LDAP OU GROUP"] =
1170     new _define_optional('LDAP_OU_GROUP', "ou=Groups", "
1171 If you have an organizational unit for all groups, define it here.
1172 This narrows the search, and is needed for LDAP group membership (if GROUP_METHOD=LDAP)
1173 The entries in this ou must have a gidNumber and cn attribute.
1174 Default: ou=Groups");
1175
1176 $properties["IMAP Auth Host"] =
1177     new _define_optional('IMAP_AUTH_HOST', 'localhost:143/imap/notls', "
1178 If USER_AUTH_ORDER contains IMAP:
1179
1180 The IMAP server to check usernames from. Defaults to localhost.
1181
1182 Some IMAP_AUTH_HOST samples:
1183   localhost, localhost:143/imap/notls,
1184   localhost:993/imap/ssl/novalidate-cert (SuSE refuses non-SSL conections)");
1185
1186 $properties["POP3 Authentication"] =
1187     new _define_optional('POP3_AUTH_HOST', 'localhost:110', "
1188 If USER_AUTH_ORDER contains POP3:
1189
1190 The POP3 mail server to check usernames and passwords against.");
1191 $properties["File Authentication"] =
1192     new _define_optional('AUTH_USER_FILE', '/etc/shadow', "
1193 If USER_AUTH_ORDER contains File:
1194
1195 File to read for authentication information.
1196 Popular choices are /etc/shadow and /etc/httpd/.htpasswd");
1197
1198 $properties["File Storable?"] =
1199     new boolean_define_commented_optional('AUTH_USER_FILE_STORABLE');
1200
1201 $properties["Session Auth USER"] =
1202     new _define_optional('AUTH_SESS_USER', 'userid', "
1203 If USER_AUTH_ORDER contains Session:
1204
1205 Name of the session variable which holds the already authenticated username.
1206 Sample: 'userid', 'user[username]', 'user->username'");
1207
1208 $properties["Session Auth LEVEL"] =
1209     new numeric_define('AUTH_SESS_LEVEL', '2', "
1210 Which level will the user be? 1 = Bogo or 2 = Pass");
1211
1212 /////////////////////////////////////////////////////////////////////
1213
1214 $properties["Part Four"] =
1215     new part('_part4', $SEPARATOR . "\n", "
1216
1217 Part Four:
1218 Page appearance and layout");
1219
1220 $properties["Theme"] =
1221     new _define_selection_optional('THEME',
1222         array('default' => "default",
1223             'MacOSX' => "MacOSX",
1224             'smaller' => 'smaller',
1225             'Wordpress' => 'Wordpress',
1226             'Portland' => "Portland",
1227             'Sidebar' => "Sidebar",
1228             'Crao' => 'Crao',
1229             'wikilens' => 'wikilens (Ratings)',
1230             'shamino_com' => 'shamino_com',
1231             'SpaceWiki' => "SpaceWiki",
1232             'Hawaiian' => "Hawaiian",
1233             'MonoBook' => 'MonoBook [experimental]',
1234             'blog' => 'blog [experimental]',
1235         ), "
1236 THEME
1237
1238 Most of the page appearance is controlled by files in the theme
1239 subdirectory.
1240
1241 There are a number of pre-defined themes shipped with PhpWiki.
1242 Or you may create your own, deriving from existing ones.
1243 <pre>
1244   THEME = Sidebar (default)
1245   THEME = default
1246   THEME = MacOSX
1247   THEME = MonoBook (WikiPedia)
1248   THEME = smaller
1249   THEME = Wordpress
1250   THEME = Portland
1251   THEME = Crao
1252   THEME = wikilens (with Ratings)
1253   THEME = Hawaiian
1254   THEME = SpaceWiki
1255   THEME = Hawaiian
1256   THEME = blog     (Kubrick)   [experimental]
1257 </pre>");
1258
1259 $properties["Language"] =
1260     new _define_selection_optional('DEFAULT_LANGUAGE',
1261         array('en' => "English",
1262             '' => "&lt;empty&gt; (user-specific)",
1263             'fr' => "Français",
1264             'de' => "Deutsch",
1265             'nl' => "Nederlands",
1266             'es' => "Español",
1267             'sv' => "Svenska",
1268             'it' => "Italiano",
1269             'ja' => "Japanese",
1270             'zh' => "Chinese"), "
1271 Select your language/locale - default language is \"en\" for English.
1272 Other languages available:<pre>
1273 English  \"en\" (English    - HomePage)
1274 German   \"de\" (Deutsch    - StartSeite)
1275 French   \"fr\" (Français   - PageAccueil)
1276 Dutch    \"nl\" (Nederlands - ThuisPagina)
1277 Spanish  \"es\" (Español    - PáginaPrincipal)
1278 Swedish  \"sv\" (Svenska    - Framsida)
1279 Italian  \"it\" (Italiano   - PaginaPrincipale)
1280 Japanese \"ja\" (Japanese   - ホームページ)
1281 Chinese  \"zh\" (Chinese    - 首頁)
1282 </pre>
1283 If you set DEFAULT_LANGUAGE to the empty string, your systems default language
1284 (as determined by the applicable environment variables) will be
1285 used.");
1286
1287 $properties["Wiki Page Source"] =
1288     new _define_optional('WIKI_PGSRC', 'pgsrc', "
1289 WIKI_PGSRC -- specifies the source for the initial page contents of
1290 the Wiki. The setting of WIKI_PGSRC only has effect when the wiki is
1291 accessed for the first time (or after clearing the database.)
1292 WIKI_PGSRC can either name a directory or a zip file. In either case
1293 WIKI_PGSRC is scanned for files -- one file per page.
1294 <pre>
1295 // Default (old) behavior:
1296 define('WIKI_PGSRC', 'pgsrc');
1297 // New style:
1298 define('WIKI_PGSRC', 'wiki.zip');
1299 define('WIKI_PGSRC',
1300        '../Logs/Hamwiki/hamwiki-20010830.zip');
1301 </pre>");
1302
1303 $properties["Default Wiki Page Source"] =
1304     new _define('DEFAULT_WIKI_PGSRC', 'pgsrc', "
1305 DEFAULT_WIKI_PGSRC is only used when the language is *not* the
1306 default (English) and when reading from a directory: in that case
1307 some English pages are inserted into the wiki as well.
1308 DEFAULT_WIKI_PGSRC defines where the English pages reside.
1309 ");
1310
1311 $properties["Generic Pages"] =
1312     new array_variable('DEFAULT_WIKI_PAGES', array('ReleaseNotes', 'TestPage'), "
1313 These are ':'-separated pages which will get loaded untranslated from DEFAULT_WIKI_PGSRC.
1314 ");
1315
1316 ///////////////////
1317
1318 $properties["Part Five"] =
1319     new part('_part5', $SEPARATOR . "\n", "
1320
1321 Part Five:
1322 Mark-up options");
1323
1324 $properties["Allowed Protocols"] =
1325     new list_define('ALLOWED_PROTOCOLS', 'http|https|mailto|ftp|news|nntp|ssh|gopher', "
1326 Allowed protocols for links - be careful not to allow \"javascript:\"
1327 URL of these types will be automatically linked.
1328 within a named link [name|uri] one more protocol is defined: phpwiki");
1329
1330 $properties["Inline Images"] =
1331     new list_define('INLINE_IMAGES', 'png|jpg|jpeg|gif|swf');
1332
1333 $properties["WikiName Regexp"] =
1334     new _define('WIKI_NAME_REGEXP', "(?<![[:alnum:]])(?:[[:upper:]][[:lower:]]+){2,}(?![[:alnum:]])", "
1335 Perl regexp for WikiNames (\"bumpy words\")
1336 (?&lt;!..) &amp; (?!...) used instead of '\b' because \b matches '_' as well");
1337
1338 $properties["InterWiki Map File"] =
1339     new _define('INTERWIKI_MAP_FILE', 'lib/interwiki.map', "
1340 InterWiki linking -- wiki-style links to other wikis on the web
1341
1342 The map will be taken from a page name InterWikiMap.
1343 If that page is not found (or is not locked), or map
1344 data can not be found in it, then the file specified
1345 by INTERWIKI_MAP_FILE (if any) will be used.");
1346
1347 $properties["WARN_NONPUBLIC_INTERWIKIMAP"] =
1348     new boolean_define('WARN_NONPUBLIC_INTERWIKIMAP');
1349
1350 $properties["Keyword Link Regexp"] =
1351     new _define_optional('KEYWORDS', '\"Category* OR Topic*\"', "
1352 Search term used for automatic page classification by keyword extraction.
1353
1354 Any links on a page to pages whose names match this search
1355 will be used keywords in the keywords html meta tag. This is an aid to
1356 classification by search engines. The value of the match is
1357 used as the keyword.
1358
1359 The default behavior is to match Category* or Topic* links.");
1360
1361 $properties["Author and Copyright Site Navigation Links"] =
1362     new _define_commented_optional('COPYRIGHTPAGE_TITLE', "GNU General Public License", "
1363
1364 These will be inserted as &lt;link rel&gt; tags in the html header of
1365 every page, for search engines and for browsers like Mozilla which
1366 take advantage of link rel site navigation.
1367
1368 If you have your own copyright and contact information pages change
1369 these as appropriate.");
1370
1371 $properties["COPYRIGHTPAGE URL"] =
1372     new _define_commented_optional('COPYRIGHTPAGE_URL', "http://www.gnu.org/copyleft/gpl.html#SEC1", "
1373
1374 Other useful alternatives to consider:
1375 <pre>
1376  COPYRIGHTPAGE_TITLE = \"GNU Free Documentation License\"
1377  COPYRIGHTPAGE_URL = \"http://www.gnu.org/copyleft/fdl.html\"
1378  COPYRIGHTPAGE_TITLE = \"Creative Commons License 2.0\"
1379  COPYRIGHTPAGE_URL = \"http://creativecommons.org/licenses/by/2.0/\"</pre>
1380 See http://creativecommons.org/learn/licenses/ for variations");
1381
1382 $properties["AUTHORPAGE_TITLE"] =
1383     new _define_commented_optional('AUTHORPAGE_TITLE', "The PhpWiki Programming Team", "
1384 Default Author Names");
1385 $properties["AUTHORPAGE_URL"] =
1386     new _define_commented_optional('AUTHORPAGE_URL', "http://phpwiki.fr/The%20PhpWiki%20programming%20team", "
1387 Default Author URL");
1388
1389 $properties["TOC_FULL_SYNTAX"] =
1390     new boolean_define_optional('TOC_FULL_SYNTAX');
1391
1392 $properties["ENABLE_MARKUP_COLOR"] =
1393     new boolean_define_optional('ENABLE_MARKUP_COLOR');
1394
1395 $properties["DISABLE_MARKUP_WIKIWORD"] =
1396     new boolean_define_optional('DISABLE_MARKUP_WIKIWORD');
1397
1398 $properties["ENABLE_MARKUP_DIVSPAN"] =
1399     new boolean_define_optional('ENABLE_MARKUP_DIVSPAN');
1400
1401 ///////////////////
1402
1403 $properties["Part Six"] =
1404     new part('_part6', $SEPARATOR . "\n", "
1405
1406 Part Six (optional):
1407 URL options -- you can probably skip this section.
1408
1409 For a pretty wiki (no index.php in the url) set a separate DATA_PATH.");
1410
1411 $properties["Server Name"] =
1412     new _define_commented_optional('SERVER_NAME', $_SERVER['SERVER_NAME'], "
1413 Canonical name of the server on which this PhpWiki resides.");
1414
1415 $properties["Server Port"] =
1416     new numeric_define_commented('SERVER_PORT', $_SERVER['SERVER_PORT'], "
1417 Canonical httpd port of the server on which this PhpWiki resides.",
1418         "onchange=\"validate_ereg('Sorry, \'%s\' is no valid port number.', '^[0-9]+$', 'SERVER_PORT', this);\"");
1419
1420 $properties["Server Protocol"] =
1421     new _define_selection_optional_commented('SERVER_PROTOCOL',
1422         array('http' => 'http',
1423             'https' => 'https'));
1424
1425 $properties["Script Name"] =
1426     new _define_commented_optional('SCRIPT_NAME', $scriptname);
1427
1428 $properties["Data Path"] =
1429     new _define_commented_optional('DATA_PATH', dirname($scriptname));
1430
1431 $properties["PhpWiki Install Directory"] =
1432     new _define_commented_optional('PHPWIKI_DIR', dirname(__FILE__));
1433
1434 $properties["Use PATH_INFO"] =
1435     new _define_selection_optional_commented('USE_PATH_INFO',
1436         array('' => 'automatic',
1437             'true' => 'use PATH_INFO',
1438             'false' => 'do not use PATH_INFO'), "
1439 PhpWiki will try to use short urls to pages, eg
1440 http://www.example.com/index.php/HomePage
1441 If you want to use urls like
1442 http://www.example.com/index.php?pagename=HomePage
1443 then define 'USE_PATH_INFO' as false by uncommenting the line below.
1444 NB:  If you are using Apache >= 2.0.30, then you may need to to use
1445 the directive \"AcceptPathInfo On\" in your Apache configuration file
1446 (or in an appropriate <.htaccess> file) for the short urls to work:
1447 See http://httpd.apache.org/docs-2.0/mod/core.html#acceptpathinfo
1448
1449 See also http://phpwiki.sourceforge.net/phpwiki/PrettyWiki for more ideas
1450 on prettifying your urls.
1451
1452 Default: PhpWiki will try to divine whether use of PATH_INFO
1453 is supported in by your webserver/PHP configuration, and will
1454 use PATH_INFO if it thinks that is possible.");
1455
1456 $properties["Virtual Path"] =
1457     new _define_commented_optional('VIRTUAL_PATH', '/SomeWiki', "
1458 VIRTUAL_PATH is the canonical URL path under which your your wiki
1459 appears. Normally this is the same as dirname(SCRIPT_NAME), however
1460 using e.g. separate starter scripts, apaches mod_actions (or mod_rewrite),
1461 you can make it something different.
1462
1463 If you do this, you should set VIRTUAL_PATH here or in the starter scripts.
1464
1465 E.g. your phpwiki might be installed at at /scripts/phpwiki/index.php,
1466 but you've made it accessible through eg. /wiki/HomePage.
1467
1468 One way to do this is to create a directory named 'wiki' in your
1469 server root. The directory contains only one file: an .htaccess
1470 file which reads something like:
1471 <pre>
1472     Action x-phpwiki-page /scripts/phpwiki/index.php
1473     SetHandler x-phpwiki-page
1474     DirectoryIndex /scripts/phpwiki/index.php
1475 </pre>
1476 In that case you should set VIRTUAL_PATH to '/wiki'.
1477
1478 (VIRTUAL_PATH is only used if USE_PATH_INFO is true.)
1479 ");
1480
1481 $upload_file_path = defined('UPLOAD_FILE_PATH') ? UPLOAD_FILE_PATH : getUploadFilePath();
1482 new _define_optional('UPLOAD_FILE_PATH', $temp);
1483
1484 $upload_data_path = defined('UPLOAD_DATA_PATH') ? UPLOAD_DATA_PATH : getUploadDataPath();
1485 new _define_optional('UPLOAD_DATA_PATH', $temp);
1486
1487 $temp = !empty($_ENV['TEMP']) ? $_ENV['TEMP'] : "/tmp";
1488 $properties["TEMP_DIR"] =
1489     new _define_optional('TEMP_DIR', $temp);
1490
1491 ///////////////////
1492
1493 $properties["Part Seven"] =
1494     new part('_part7', $SEPARATOR . "\n", "
1495
1496 Part Seven:
1497
1498 Miscellaneous settings
1499 ");
1500
1501 $properties["Strict Mailable Pagedumps"] =
1502     new boolean_define_optional('STRICT_MAILABLE_PAGEDUMPS',
1503         array('false' => "binary",
1504             'true' => "quoted-printable"));
1505
1506 $properties["Default local Dump Directory"] =
1507     new _define_optional('DEFAULT_DUMP_DIR');
1508
1509 $properties["Default local HTML Dump Directory"] =
1510     new _define_optional('HTML_DUMP_DIR');
1511
1512 $properties["HTML Dump Filename Suffix"] =
1513     new _define_optional('HTML_DUMP_SUFFIX');
1514
1515 $properties["Pagename of Recent Changes"] =
1516     new _define_optional('RECENT_CHANGES',
1517         "RecentChanges");
1518
1519 $properties["Disable HTTP Redirects"] =
1520     new boolean_define_commented_optional('DISABLE_HTTP_REDIRECT');
1521
1522 $properties["Disable GETIMAGESIZE"] =
1523     new boolean_define_commented_optional('DISABLE_GETIMAGESIZE');
1524
1525 $properties["EDITING_POLICY"] =
1526     new _define_optional('EDITING_POLICY');
1527
1528 $properties["TOOLBAR_PAGELINK_PULLDOWN"] =
1529     new _define_commented_optional('TOOLBAR_PAGELINK_PULLDOWN');
1530 $properties["TOOLBAR_TEMPLATE_PULLDOWN"] =
1531     new _define_commented_optional('TOOLBAR_TEMPLATE_PULLDOWN');
1532 $properties["TOOLBAR_IMAGE_PULLDOWN"] =
1533     new _define_commented_optional('TOOLBAR_IMAGE_PULLDOWN');
1534 $properties["FULLTEXTSEARCH_STOPLIST"] =
1535     new _define_commented_optional('FULLTEXTSEARCH_STOPLIST');
1536
1537 $properties["Part Seven A"] =
1538     new part('_part7a', $SEPARATOR . "\n", "
1539
1540 Part Seven A:
1541
1542 Optional Plugin Settings and external executables
1543 ");
1544
1545 $properties["FORTUNE_DIR"] =
1546     new _define_commented_optional('FORTUNE_DIR', "/usr/share/fortune");
1547 $properties["USE_EXTERNAL_HTML2PDF"] =
1548     new _define_commented_optional('USE_EXTERNAL_HTML2PDF', "htmldoc --quiet --format pdf14 --no-toc --no-title %s");
1549 $properties["EXTERNAL_HTML2PDF_PAGELIST"] =
1550     new _define_commented_optional('EXTERNAL_HTML2PDF_PAGELIST');
1551 $properties["BABYCART_PATH"] =
1552     new _define_commented_optional('BABYCART_PATH', "/usr/local/bin/babycart");
1553 $properties["GOOGLE_LICENSE_KEY"] =
1554     new _define_commented_optional('GOOGLE_LICENSE_KEY');
1555 $properties["RATEIT_IMGPREFIX"] =
1556     new _define_commented_optional('RATEIT_IMGPREFIX'); //BStar
1557 $properties["GRAPHVIZ_EXE"] =
1558     new _define_commented_optional('GRAPHVIZ_EXE', "/usr/bin/dot");
1559
1560 if (PHP_OS == "Darwin") // Mac OS X
1561     $ttfont = "/System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Home/lib/fonts/LucidaSansRegular.ttf";
1562 elseif (isWindows()) {
1563     $ttfont = $_ENV['windir'] . '\Fonts\Arial.ttf';
1564 } else {
1565     $ttfont = 'luximr'; // This is the only what sourceforge offered.
1566     //$ttfont = 'Helvetica';
1567 }
1568 $properties["TTFONT"] =
1569     new _define_commented_optional('TTFONT', $ttfont);
1570 $properties["VISUALWIKIFONT"] =
1571     new _define_commented_optional('VISUALWIKIFONT'); // Arial
1572 $properties["VISUALWIKI_ALLOWOPTIONS"] =
1573     new boolean_define_commented_optional('VISUALWIKI_ALLOWOPTIONS'); // false
1574 $properties["PLOTICUS_EXE"] =
1575     new _define_commented_optional('PLOTICUS_EXE'); // /usr/local/bin/pl
1576 $properties["PLOTICUS_PREFABS"] =
1577     new _define_commented_optional('PLOTICUS_PREFABS'); // /usr/share/ploticus
1578 $properties["MY_JABBER_ID"] =
1579     new _define_commented_optional('MY_JABBER_ID'); //
1580 $properties["PHPWEATHER_BASE_DIR"] =
1581     new _define_commented_optional('PHPWEATHER_BASE_DIR'); //
1582
1583 $properties["Part Eight"] =
1584     new part('_part8', $SEPARATOR . "\n", "
1585
1586 Part Eight:
1587
1588 Cached Plugin Settings. (pear Cache)
1589 ");
1590
1591 $properties["pear Cache USECACHE"] =
1592     new boolean_define_optional('PLUGIN_CACHED_USECACHE',
1593         array('true' => 'Enabled',
1594             'false' => 'Disabled'), "
1595 Enable or disable pear caching of plugins.");
1596 $properties["pear Cache Database Container"] =
1597     new _define_selection_optional('PLUGIN_CACHED_DATABASE',
1598         array('file' => 'file'), "
1599 Curently only file is supported.
1600 db, trifile and imgfile might be supported, but you must hack that by yourself.");
1601
1602 $properties["pear Cache cache directory"] =
1603     new _define_commented_optional('PLUGIN_CACHED_CACHE_DIR', "/tmp/cache", "
1604 Should be writable to the webserver.");
1605 $properties["pear Cache Filename Prefix"] =
1606     new _define_optional('PLUGIN_CACHED_FILENAME_PREFIX', "phpwiki", "");
1607 $properties["pear Cache HIGHWATER"] =
1608     new numeric_define_optional('PLUGIN_CACHED_HIGHWATER', "4194304", "
1609 Garbage collection parameter.");
1610 $properties["pear Cache LOWWATER"] =
1611     new numeric_define_optional('PLUGIN_CACHED_LOWWATER', "3145728", "
1612 Garbage collection parameter.");
1613 $properties["pear Cache MAXLIFETIME"] =
1614     new numeric_define_optional('PLUGIN_CACHED_MAXLIFETIME', "2592000", "
1615 Garbage collection parameter.");
1616 $properties["pear Cache MAXARGLEN"] =
1617     new numeric_define_optional('PLUGIN_CACHED_MAXARGLEN', "1000", "
1618 max. generated url length.");
1619 $properties["pear Cache FORCE_SYNCMAP"] =
1620     new boolean_define_optional('PLUGIN_CACHED_FORCE_SYNCMAP',
1621         array('true' => 'Enabled',
1622             'false' => 'Disabled'), "");
1623 $properties["pear Cache IMGTYPES"] =
1624     new list_define('PLUGIN_CACHED_IMGTYPES', "png|gif|gd|gd2|jpeg|wbmp|xbm|xpm", "
1625 Handle those image types via GD handles. Check your GD supported image types.");
1626
1627 $end = "\n" . $SEPARATOR . "\n";
1628
1629 // performance hack
1630 text_from_dist("_MAGIC_CLOSE_FILE");
1631
1632 // end of configuration options
1633 ///////////////////////////////
1634 // begin class definitions
1635
1636 /**
1637  * A basic config-dist.ini configuration line in the form of a variable.
1638  * (not needed anymore, we have only defines)
1639  *
1640  * Produces a string in the form "$name = value;"
1641  * e.g.:
1642  * $WikiNameRegexp = "value";
1643  */
1644 class _variable
1645 {
1646
1647     var $config_item_name;
1648     var $default_value;
1649     var $description;
1650     var $prefix;
1651     var $jscheck;
1652
1653     function _variable($config_item_name, $default_value = '', $description = '', $jscheck = '')
1654     {
1655         $this->config_item_name = $config_item_name;
1656         if (!$description)
1657             $description = text_from_dist($config_item_name);
1658         $this->description = $description;
1659         if (defined($config_item_name)
1660             and !preg_match("/(selection|boolean)/", get_class($this))
1661                 and !preg_match("/^(SCRIPT_NAME|VIRTUAL_PATH|TEMP_DIR)$/", $config_item_name)
1662         )
1663             $this->default_value = constant($config_item_name); // ignore given default value
1664         elseif ($config_item_name == $default_value)
1665             $this->default_value = ''; else
1666             $this->default_value = $default_value;
1667         $this->jscheck = $jscheck;
1668         if (preg_match("/variable/i", get_class($this)))
1669             $this->prefix = "\$";
1670         elseif (preg_match("/ini_set/i", get_class($this)))
1671             $this->prefix = "ini_get: "; else
1672             $this->prefix = "";
1673     }
1674
1675     function _define($config_item_name, $default_value = '', $description = '', $jscheck = '')
1676     {
1677         $this->_variable($config_item_name, $default_value, $description, $jscheck);
1678     }
1679
1680     function value()
1681     {
1682         global $HTTP_POST_VARS;
1683         if (isset($HTTP_POST_VARS[$this->config_item_name]))
1684             return $HTTP_POST_VARS[$this->config_item_name];
1685         else
1686             return $this->default_value;
1687     }
1688
1689     function _config_format($value)
1690     {
1691         return '';
1692         /*
1693         $v = $this->get_config_item_name();
1694         // handle arrays: a|b --> a['b']
1695         if (strpos($v, '|')) {
1696             list($a, $b) = explode('|', $v);
1697             $v = sprintf("%s['%s']", $a, $b);
1698         }
1699         if (preg_match("/[\"']/", $value))
1700             $value = '"' . $value . '"';
1701         return sprintf("%s = \"%s\"", $v, $value);
1702         */
1703     }
1704
1705     function get_config_item_name()
1706     {
1707         return $this->config_item_name;
1708     }
1709
1710     function get_config_item_id()
1711     {
1712         return str_replace('|', '-', $this->config_item_name);
1713     }
1714
1715     function get_config_item_header()
1716     {
1717         if (strchr($this->config_item_name, '|')) {
1718             list($var, $param) = explode('|', $this->config_item_name);
1719             return "<b>" . $this->prefix . $var . "['" . $param . "']</b><br />";
1720         } elseif ($this->config_item_name[0] != '_')
1721             return "<b>" . $this->prefix . $this->config_item_name . "</b><br />"; else
1722             return '';
1723     }
1724
1725     function _get_description()
1726     {
1727         return $this->description;
1728     }
1729
1730     function _get_config_line($posted_value)
1731     {
1732         return "\n" . $this->_config_format($posted_value);
1733     }
1734
1735     function get_config($posted_value)
1736     {
1737         $d = stripHtml($this->_get_description());
1738         $d = str_replace("\n", "\n; ", $d) . $this->_get_config_line($posted_value) . "\n";
1739         return $d;
1740     }
1741
1742     function get_instructions($title)
1743     {
1744         global $tdwidth;
1745         $i = "<h3>" . $title . "</h3>\n    " . nl2p($this->_get_description()) . "\n";
1746         return "<tr>\n<td width=\"$tdwidth\" class=\"instructions\">\n" . $i . "</td>\n";
1747     }
1748
1749     function get_html()
1750     {
1751         $size = strlen($this->default_value) > 45 ? 90 : 50;
1752         return $this->get_config_item_header() .
1753             "<input type=\"text\" size=\"$50\" name=\"" . $this->get_config_item_name() . "\" value=\"" . htmlspecialchars($this->default_value) . "\" " .
1754             $this->jscheck . " />" . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1755     }
1756 }
1757
1758 class unchangeable_variable
1759     extends _variable
1760 {
1761     function _config_format($value)
1762     {
1763         return "";
1764     }
1765
1766     // function get_html() { return false; }
1767     function get_html()
1768     {
1769         return $this->get_config_item_header() .
1770             "<em>Not editable.</em>" .
1771             "<pre>" . $this->default_value . "</pre>";
1772     }
1773
1774     function _get_config_line($posted_value)
1775     {
1776         if ($this->description)
1777             $n = "\n";
1778         return "${n}" . $this->default_value;
1779     }
1780
1781     function get_instructions($title)
1782     {
1783         global $tdwidth;
1784         $i = "<h3>" . $title . "</h3>\n    " . nl2p($this->_get_description()) . "\n";
1785         // $i .= "<em>Not editable.</em><br />\n<pre>" . $this->default_value."</pre>";
1786         return '<tr><td style="width:100%" class="unchangeable-variable-top" colspan="2">' . "\n" . $i . "</td></tr>\n"
1787             . '<tr style="border-top: none;"><td class="unchangeable-variable-left" width="' . $tdwidth . '">&nbsp;</td>';
1788     }
1789 }
1790
1791 class unchangeable_define
1792     extends unchangeable_variable
1793 {
1794     function _get_config_line($posted_value)
1795     {
1796         if ($this->description)
1797             $n = "\n";
1798         if (!$posted_value)
1799             $posted_value = $this->default_value;
1800         return "${n}" . $this->_config_format($posted_value);
1801     }
1802
1803     function _config_format($value)
1804     {
1805         return sprintf("%s = \"%s\"", $this->get_config_item_name(), $value);
1806     }
1807 }
1808 class unchangeable_ini_set
1809     extends unchangeable_variable
1810 {
1811     function _config_format($value)
1812     {
1813         return "";
1814     }
1815 }
1816
1817 class _variable_selection
1818     extends _variable
1819 {
1820     function value()
1821     {
1822         global $HTTP_POST_VARS;
1823         if (!empty($HTTP_POST_VARS[$this->config_item_name]))
1824             return $HTTP_POST_VARS[$this->config_item_name];
1825         else {
1826             list($option, $label) = each($this->default_value);
1827             return $option;
1828         }
1829     }
1830
1831     function get_html()
1832     {
1833         $output = $this->get_config_item_header();
1834         $output .= '<select name="' . $this->get_config_item_name() . "\">\n";
1835         /* The first option is the default */
1836         $values = $this->default_value;
1837         if (defined($this->get_config_item_name()))
1838             $this->default_value = constant($this->get_config_item_name());
1839         else
1840             $this->default_value = null;
1841
1842         foreach ($values as $option => $label) {
1843             if (!is_null($this->default_value) && $this->default_value === $option)
1844                 $output .= "  <option value=\"$option\" selected=\"selected\">$label</option>\n";
1845             else
1846                 $output .= "  <option value=\"$option\">$label</option>\n";
1847         }
1848         $output .= "</select>\n";
1849         return $output;
1850     }
1851 }
1852
1853 class _define
1854     extends _variable
1855 {
1856     function _config_format($value)
1857     {
1858         return sprintf("%s = \"%s\"", $this->get_config_item_name(), $value);
1859     }
1860
1861     function _get_config_line($posted_value)
1862     {
1863         if ($this->description)
1864             $n = "\n";
1865         if ($posted_value == '')
1866             return "${n};" . $this->_config_format("");
1867         else
1868             return "${n}" . $this->_config_format($posted_value);
1869     }
1870
1871     function get_html()
1872     {
1873         $size = strlen($this->default_value) > 45 ? 90 : 50;
1874         return $this->get_config_item_header()
1875             . "<input type=\"text\" size=\"$size\" name=\"" . htmlentities($this->get_config_item_name())
1876             . "\" value=\"" . htmlentities($this->default_value) . "\" {$this->jscheck} />"
1877             . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1878     }
1879 }
1880
1881 class _define_commented
1882     extends _define
1883 {
1884     function _get_config_line($posted_value)
1885     {
1886         if ($this->description)
1887             $n = "\n";
1888         if ($posted_value == $this->default_value)
1889             return "${n};" . $this->_config_format($posted_value);
1890         elseif ($posted_value == '')
1891             return "${n};" . $this->_config_format(""); else
1892             return "${n}" . $this->_config_format($posted_value);
1893     }
1894 }
1895
1896 /**
1897  * We don't use _optional anymore, because INI-style config's don't need that.
1898  * IniConfig.php does the optional logic now.
1899  * But we use _optional for config-default.ini options
1900  */
1901 class _define_commented_optional
1902     extends _define_commented
1903 {
1904 }
1905
1906 class _define_optional
1907     extends _define
1908 {
1909 }
1910
1911 class _define_notempty
1912     extends _define
1913 {
1914     function get_html()
1915     {
1916         $s = $this->get_config_item_header()
1917             . "<input type=\"text\" size=\"50\" name=\"" . $this->get_config_item_name()
1918             . "\" value=\"" . $this->default_value . "\" {$this->jscheck} />";
1919         if (empty($this->default_value))
1920             return $s . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Cannot be empty.</p>";
1921         else
1922             return $s . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1923     }
1924 }
1925
1926 class _variable_commented
1927     extends _variable
1928 {
1929     function _get_config_line($posted_value)
1930     {
1931         if ($this->description)
1932             $n = "\n";
1933         if ($posted_value == $this->default_value)
1934             return "${n};" . $this->_config_format($posted_value);
1935         elseif ($posted_value == '')
1936             return "${n};" . $this->_config_format(""); else
1937             return "${n}" . $this->_config_format($posted_value);
1938     }
1939 }
1940
1941 class numeric_define
1942     extends _define
1943 {
1944
1945     function numeric_define($config_item_name, $default_value = '', $description = '', $jscheck = '')
1946     {
1947         $this->_define($config_item_name, $default_value, $description, $jscheck);
1948         if (!$jscheck)
1949             $this->jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' is not an integer.', '^[-+]?[0-9]+$', '" . $this->get_config_item_name() . "', this);\"";
1950     }
1951
1952     function _config_format($value)
1953     {
1954         //return sprintf("define('%s', %s);", $this->get_config_item_name(), $value);
1955         return sprintf("%s = %s", $this->get_config_item_name(), $value);
1956     }
1957
1958     function _get_config_line($posted_value)
1959     {
1960         if ($this->description)
1961             $n = "\n";
1962         if ($posted_value == '')
1963             return "${n};" . $this->_config_format('0');
1964         else
1965             return "${n}" . $this->_config_format($posted_value);
1966     }
1967 }
1968
1969 class numeric_define_optional
1970     extends numeric_define
1971 {
1972 }
1973
1974 class numeric_define_commented
1975     extends numeric_define
1976 {
1977     function _get_config_line($posted_value)
1978     {
1979         if ($this->description)
1980             $n = "\n";
1981         if ($posted_value == $this->default_value)
1982             return "${n};" . $this->_config_format($posted_value);
1983         elseif ($posted_value == '')
1984             return "${n};" . $this->_config_format('0'); else
1985             return "${n}" . $this->_config_format($posted_value);
1986     }
1987 }
1988
1989 class _define_selection
1990     extends _variable_selection
1991 {
1992     function _config_format($value)
1993     {
1994         return sprintf("%s = %s", $this->get_config_item_name(), $value);
1995     }
1996
1997     function _get_config_line($posted_value)
1998     {
1999         return _define::_get_config_line($posted_value);
2000     }
2001
2002     function get_html()
2003     {
2004         return _variable_selection::get_html();
2005     }
2006 }
2007
2008 class _define_selection_optional
2009     extends _define_selection
2010 {
2011 }
2012
2013 class _variable_selection_optional
2014     extends _variable_selection
2015 {
2016 }
2017
2018 class _define_selection_optional_commented
2019     extends _define_selection_optional
2020 {
2021     function _get_config_line($posted_value)
2022     {
2023         if ($this->description)
2024             $n = "\n";
2025         if ($posted_value == $this->default_value)
2026             return "${n};" . $this->_config_format($posted_value);
2027         elseif ($posted_value == '')
2028             return "${n};" . $this->_config_format(""); else
2029             return "${n}" . $this->_config_format($posted_value);
2030     }
2031 }
2032
2033 class _define_password
2034     extends _define
2035 {
2036
2037     function _define_password($config_item_name, $default_value = '', $description = '', $jscheck = '')
2038     {
2039         if ($config_item_name == $default_value) $default_value = '';
2040         $this->_define($config_item_name, $default_value, $description, $jscheck);
2041         if (!$jscheck)
2042             $this->jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' cannot be empty.', '^.+$', '"
2043                 . $this->get_config_item_name() . "', this);\"";
2044     }
2045
2046     function _get_config_line($posted_value)
2047     {
2048         if ($this->description)
2049             $n = "\n";
2050         if ($posted_value == '') {
2051             $p = "${n};" . $this->_config_format("");
2052             $p .= "\n; If you used the passencrypt.php utility to encode the password";
2053             $p .= "\n; then uncomment this line:";
2054             $p .= "\n;ENCRYPTED_PASSWD = true";
2055             return $p;
2056         } else {
2057             $salt_length = max(CRYPT_SALT_LENGTH,
2058                 2 * CRYPT_STD_DES,
2059                 9 * CRYPT_EXT_DES,
2060                 12 * CRYPT_MD5,
2061                 16 * CRYPT_BLOWFISH);
2062             // generate an encrypted password
2063             $crypt_pass = crypt($posted_value, rand_ascii($salt_length));
2064             $p = "${n}" . $this->_config_format($crypt_pass);
2065             return $p . "\nENCRYPTED_PASSWD = true";
2066         }
2067     }
2068
2069     function get_html()
2070     {
2071         return _variable_password::get_html();
2072     }
2073 }
2074
2075 class _define_password_optional
2076     extends _define_password
2077 {
2078
2079     function _define_password_optional($config_item_name, $default_value = '', $description = '', $jscheck = '')
2080     {
2081         if ($config_item_name == $default_value) $default_value = '';
2082         if (!$jscheck) $this->jscheck = " ";
2083         $this->_define($config_item_name, $default_value, $description, $jscheck);
2084     }
2085
2086     function _get_config_line($posted_value)
2087     {
2088         if ($this->description)
2089             $n = "\n";
2090         if ($posted_value == '') {
2091             return "${n};" . $this->_config_format("");
2092         } else {
2093             return "${n}" . $this->_config_format($posted_value);
2094         }
2095     }
2096
2097     function get_html()
2098     {
2099         $s = $this->get_config_item_header();
2100         // dont re-encrypt already encrypted passwords
2101         $value = $this->value();
2102         $encrypted = !empty($GLOBALS['properties']["Encrypted Passwords"]) and
2103             $GLOBALS['properties']["Encrypted Passwords"]->value();
2104         if (empty($value))
2105             $encrypted = false;
2106         $s .= "<input type=\"" . ($encrypted ? "text" : "password") . "\" name=\"" . $this->get_config_item_name()
2107             . "\" value=\"" . $value . "\" {$this->jscheck} />";
2108         return $s;
2109     }
2110 }
2111
2112 class _define_password_commented_optional
2113     extends _define_password_optional
2114 {
2115 }
2116
2117 class _variable_password
2118     extends _variable
2119 {
2120     function _variable_password($config_item_name, $default_value = '', $description = '', $jscheck = '')
2121     {
2122         if ($config_item_name == $default_value) $default_value = '';
2123         $this->_define($config_item_name, $default_value, $description, $jscheck);
2124         if (!$jscheck)
2125             $this->jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' cannot be empty.', '^.+$', '" . $this->get_config_item_name() . "', this);\"";
2126     }
2127
2128     function get_html()
2129     {
2130         global $HTTP_POST_VARS, $HTTP_GET_VARS;
2131         $s = $this->get_config_item_header();
2132         if (isset($HTTP_POST_VARS['create']) or isset($HTTP_GET_VARS['create'])) {
2133             $new_password = random_good_password();
2134             $this->default_value = $new_password;
2135             $s .= "Created password: <strong>$new_password</strong><br />&nbsp;<br />";
2136         }
2137         // dont re-encrypt already encrypted passwords
2138         $value = $this->value();
2139         $encrypted = !empty($GLOBALS['properties']["Encrypted Passwords"]) and
2140             $GLOBALS['properties']["Encrypted Passwords"]->value();
2141         if (empty($value))
2142             $encrypted = false;
2143         $s .= "<input type=\"" . ($encrypted ? "text" : "password") . "\" name=\"" . $this->get_config_item_name()
2144             . "\" value=\"" . $value . "\" {$this->jscheck} />"
2145             . "&nbsp;&nbsp;<input type=\"submit\" name=\"create\" value=\"Create Random Password\" />";
2146         if (empty($value))
2147             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Cannot be empty.</p>";
2148         elseif (strlen($this->default_value) < 4)
2149             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Must be longer than 4 chars.</p>"; else
2150             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2151         return $s;
2152     }
2153 }
2154
2155 class list_variable
2156     extends _variable
2157 {
2158     function _get_config_line($posted_value)
2159     {
2160         // split the phrase by any number of commas or space characters,
2161         // which include " ", \r, \t, \n and \f
2162         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2163         if ($list_values)
2164             $list_values = join("|", $list_values);
2165         return _variable::_get_config_line($list_values);
2166     }
2167
2168     function get_html()
2169     {
2170         $list_values = explode("|", $this->default_value);
2171         $rows = max(3, count($list_values) + 1);
2172         $list_values = join("\n", $list_values);
2173         $ta = $this->get_config_item_header();
2174         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2175         $ta .= $list_values . "</textarea>";
2176         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2177         return $ta;
2178     }
2179 }
2180
2181 class list_define
2182     extends _define
2183 {
2184     function _get_config_line($posted_value)
2185     {
2186         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2187         if ($list_values)
2188             $list_values = join("|", $list_values);
2189         return _variable::_get_config_line($list_values);
2190     }
2191
2192     function get_html()
2193     {
2194         $list_values = explode("|", $this->default_value);
2195         $rows = max(3, count($list_values) + 1);
2196         if ($list_values)
2197             $list_values = join("\n", $list_values);
2198         $ta = $this->get_config_item_header();
2199         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2200         $ta .= $list_values . "</textarea>";
2201         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2202         return $ta;
2203     }
2204 }
2205
2206 class array_variable
2207     extends _variable
2208 {
2209     function _config_format($value)
2210     {
2211         return sprintf("%s = \"%s\"", $this->get_config_item_name(),
2212             is_array($value) ? join(':', $value) : $value);
2213     }
2214
2215     function _get_config_line($posted_value)
2216     {
2217         // split the phrase by any number of commas or space characters,
2218         // which include " ", \r, \t, \n and \f
2219         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2220         if (!empty($list_values)) {
2221             $list_values = "'" . join("', '", $list_values) . "'";
2222             return "\n" . $this->_config_format($list_values);
2223         } else
2224             return "\n;" . $this->_config_format('');
2225     }
2226
2227     function get_html()
2228     {
2229         if (is_array($this->default_value))
2230             $list_values = join("\n", $this->default_value);
2231         else
2232             $list_values = $this->default_value;
2233         $rows = max(3, count($this->default_value) + 1);
2234         $ta = $this->get_config_item_header();
2235         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2236         $ta .= $list_values . "</textarea>";
2237         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2238         return $ta;
2239     }
2240 }
2241
2242 class array_define
2243     extends _define
2244 {
2245     function _config_format($value)
2246     {
2247         return sprintf("%s = \"%s\"", $this->get_config_item_name(),
2248             is_array($value) ? join(' : ', $value) : $value);
2249     }
2250
2251     function _get_config_line($posted_value)
2252     {
2253         // split the phrase by any number of commas or space characters,
2254         // which include " ", \r, \t, \n and \f
2255         $list_values = preg_split("/[\s,:]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2256         if (!empty($list_values)) {
2257             $list_values = join(" : ", $list_values);
2258             return "\n" . $this->_config_format($list_values);
2259         } else
2260             return "\n;" . $this->_config_format('');
2261     }
2262
2263     function get_html()
2264     {
2265         if (!$this->default_value)
2266             $this->default_value = array();
2267         elseif (is_string($this->default_value))
2268             $this->default_value = preg_split("/[\s,:]+/", $this->default_value, -1, PREG_SPLIT_NO_EMPTY);
2269         $list_values = join(" : \n", $this->default_value);
2270         $rows = max(3, count($this->default_value) + 1);
2271         $ta = $this->get_config_item_header();
2272         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2273         $ta .= $list_values . "</textarea>";
2274         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2275         return $ta;
2276     }
2277 }
2278
2279 /*
2280 class _ini_set
2281 extends _variable {
2282     function value() {
2283         global $HTTP_POST_VARS;
2284         if ($v = $HTTP_POST_VARS[$this->config_item_name])
2285             return $v;
2286         else {
2287             return ini_get($this->get_config_item_name);
2288         }
2289     }
2290     function _config_format($value) {
2291         return sprintf("ini_set('%s', '%s');", $this->get_config_item_name(), $value);
2292     }
2293     function _get_config_line($posted_value) {
2294         if ($posted_value && ! $posted_value == $this->default_value)
2295             return "\n" . $this->_config_format($posted_value);
2296         else
2297             return "\n;" . $this->_config_format($this->default_value);
2298     }
2299 }
2300 */
2301
2302 class boolean_define
2303     extends _define
2304 {
2305
2306     // adds ->values property, instead of ->default_value
2307     function boolean_define($config_item_name, $values = false, $description = '', $jscheck = '')
2308     {
2309         $this->config_item_name = $config_item_name;
2310         if (!$description)
2311             $description = text_from_dist($config_item_name);
2312         $this->description = $description;
2313         // TESTME: get boolean default value from config-default.ini
2314         if (defined($config_item_name))
2315             $this->default_value = constant($config_item_name); // ignore given default value
2316         elseif (is_array($values))
2317             list($this->default_value, $dummy) = $values[0];
2318         if (!$values)
2319             $values = array('false' => "Disabled",
2320                 'true' => "Enabled");
2321         $this->values = $values;
2322         $this->jscheck = $jscheck;
2323         $this->prefix = "";
2324     }
2325
2326     function _get_config_line($posted_value)
2327     {
2328         if ($this->description)
2329             $n = "\n";
2330         return "${n}" . $this->_config_format($posted_value);
2331     }
2332
2333     function _config_format($value)
2334     {
2335         if (strtolower(trim($value)) == 'false')
2336             $value = false;
2337         return sprintf("%s = %s", $this->get_config_item_name(),
2338             (bool)$value ? 'true' : 'false');
2339     }
2340
2341     //TODO: radiobuttons, no list
2342     function get_html()
2343     {
2344         $output = $this->get_config_item_header();
2345         $name = $this->get_config_item_name();
2346         $output .= '<select name="' . $name . "\" {$this->jscheck}>\n";
2347         $values = $this->values;
2348         $default_value = $this->default_value ? 'true' : 'false';
2349         /* There can usually only be two options, there can be
2350          * three options in the case of a boolean_define_commented_optional */
2351         while (list($option, $label) = each($values)) {
2352             if (!is_null($this->default_value) and $option === $default_value)
2353                 $output .= "  <option value=\"$option\" selected=\"selected\">$label</option>\n";
2354             else
2355                 $output .= "  <option value=\"$option\">$label</option>\n";
2356         }
2357         $output .= "</select>\n";
2358         return $output;
2359     }
2360 }
2361
2362 class boolean_define_optional
2363     extends boolean_define
2364 {
2365 }
2366
2367 class boolean_define_commented
2368     extends boolean_define
2369 {
2370     function _get_config_line($posted_value)
2371     {
2372         if ($this->description)
2373             $n = "\n";
2374         list($default_value, $label) = each($this->default_value);
2375         if ($posted_value == $default_value)
2376             return "${n};" . $this->_config_format($posted_value);
2377         elseif ($posted_value == '')
2378             return "${n};" . $this->_config_format('false'); else
2379             return "${n}" . $this->_config_format($posted_value);
2380     }
2381 }
2382
2383 class boolean_define_commented_optional
2384     extends boolean_define_commented
2385 {
2386 }
2387
2388 class part
2389     extends _variable
2390 {
2391     function value()
2392     {
2393         return;
2394     }
2395
2396     function get_config($posted_value)
2397     {
2398         $d = stripHtml($this->_get_description());
2399         global $SEPARATOR;
2400         return "\n" . $SEPARATOR . str_replace("\n", "\n; ", $d) . "\n" . $this->default_value;
2401     }
2402
2403     function get_instructions($title)
2404     {
2405         $id = preg_replace("/\W/", "", $this->config_item_name);
2406         $group_name = preg_replace("/\W/", "", $title);
2407         $i = '<tr class="header" id="'.$id.'">'."\n";
2408         $i .= '<td class="part" style="width:100%;background-color:#eee" colspan="2">'."\n";
2409         $i .= "<h2>" . $title . "</h2>\n    " . nl2p($this->_get_description()) . "\n";
2410         $i .= "<p><a href=\"javascript:toggle_group('$id')\" id=\"{$id}_text\">Hide options.</a></p>";
2411         return $i . "</td>\n";
2412     }
2413
2414     function get_html()
2415     {
2416         return "";
2417     }
2418 }
2419
2420 // html utility functions
2421 function nl2p($text)
2422 {
2423     preg_match_all("@\s*(<pre>.*?</pre>|<dl>.*?</dl>|.*?(?=\n\n|<pre>|<dl>|$))@s",
2424         $text, $m, PREG_PATTERN_ORDER);
2425
2426     $text = '';
2427     foreach ($m[1] as $par) {
2428         if (!($par = trim($par)))
2429             continue;
2430         if (!preg_match('/^<(pre|dl)>/', $par))
2431             $par = "<p>$par</p>";
2432         $text .= $par;
2433     }
2434     return $text;
2435 }
2436
2437 function text_from_dist($var)
2438 {
2439     static $distfile = 0;
2440     static $f;
2441
2442     if (!$distfile) {
2443         $sep = (substr(PHP_OS, 0, 3) == 'WIN' ? '\\' : '/');
2444         $distfile = dirname(__FILE__) . $sep . "config" . $sep . "config-dist.ini";
2445         $f = fopen($distfile, "r");
2446     }
2447     if ($var == '_MAGIC_CLOSE_FILE') {
2448         fclose($f);
2449         return '';
2450     }
2451     // if all vars would be in natural order as in the config-dist this would not be needed.
2452     fseek($f, 0);
2453     $par = "\n";
2454     while (!feof($f)) {
2455         $s = fgets($f);
2456         if (preg_match("/^; \w/", $s)) {
2457             $par .= (substr($s, 2) . " ");
2458         } elseif (preg_match("/^;\s*$/", $s)) {
2459             $par .= "\n\n";
2460         }
2461         if (preg_match("/^;?" . preg_quote($var) . "\s*=/", $s))
2462             return $par;
2463         if (preg_match("/^\s*$/", $s)) // new paragraph
2464             $par = "\n";
2465     }
2466     return '';
2467 }
2468
2469 function stripHtml($text)
2470 {
2471     $d = str_replace("<pre>", "", $text);
2472     $d = str_replace("</pre>", "", $d);
2473     $d = str_replace("<dl>", "", $d);
2474     $d = str_replace("</dl>", "", $d);
2475     $d = str_replace("<dt>", "", $d);
2476     $d = str_replace("</dt>", "", $d);
2477     $d = str_replace("<dd>", "", $d);
2478     $d = str_replace("</dd>", "", $d);
2479     $d = str_replace("<p>", "", $d);
2480     $d = str_replace("</p>", "", $d);
2481     //restore html entities into characters
2482     // http://www.php.net/manual/en/function.htmlentities.php
2483     $trans = get_html_translation_table(HTML_ENTITIES);
2484     $trans = array_flip($trans);
2485     $d = strtr($d, $trans);
2486     return $d;
2487 }
2488
2489 include_once(dirname(__FILE__) . "/lib/stdlib.php");
2490
2491 ////
2492 // Function to create better user passwords (much larger keyspace),
2493 // suitable for user passwords.
2494 // Sequence of random ASCII numbers, letters and some special chars.
2495 // Note: There exist other algorithms for easy-to-remember passwords.
2496 function random_good_password($minlength = 5, $maxlength = 8)
2497 {
2498     $newpass = '';
2499     // assume ASCII ordering (not valid on EBCDIC systems!)
2500     $valid_chars = "!#%&+-.0123456789=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
2501     $start = ord($valid_chars);
2502     $end = ord(substr($valid_chars, -1));
2503     $length = mt_rand($minlength, $maxlength);
2504     while ($length > 0) {
2505         $newchar = mt_rand($start, $end);
2506         if (!strrpos($valid_chars, $newchar)) continue; // skip holes
2507         $newpass .= sprintf("%c", $newchar);
2508         $length--;
2509     }
2510     return ($newpass);
2511 }
2512
2513 // debugging
2514 function printArray($a)
2515 {
2516     echo "<hr />\n<pre>\n";
2517     print_r($a);
2518     echo "\n</pre>\n<hr />\n";
2519 }
2520
2521 // end of class definitions
2522 /////////////////////////////
2523 // begin auto generation code
2524
2525 if (!empty($HTTP_POST_VARS['action'])
2526     and $HTTP_POST_VARS['action'] == 'make_config'
2527         and !empty($HTTP_POST_VARS['ADMIN_USER'])
2528             and !empty($HTTP_POST_VARS['ADMIN_PASSWD'])
2529 ) {
2530
2531     $timestamp = date('dS \of F, Y H:i:s');
2532
2533     $config = "
2534 ; This is a local configuration file for PhpWiki.
2535 ; It was automatically generated by the configurator script
2536 ; on the $timestamp.
2537 ;
2538 ; $preamble
2539 ";
2540
2541     $posted = $GLOBALS['HTTP_POST_VARS'];
2542     /*if (defined('DEBUG'))
2543      printArray($GLOBALS['HTTP_POST_VARS']);*/
2544
2545     foreach ($properties as $option_name => $a) {
2546         $posted_value = stripslashes($posted[$a->config_item_name]);
2547         $config .= $properties[$option_name]->get_config($posted_value);
2548     }
2549
2550     $config .= $end;
2551
2552     if (is_writable($fs_config_file)) {
2553         // We first check if the config-file exists.
2554         if (file_exists($fs_config_file)) {
2555             // We make a backup copy of the file
2556             $new_filename = preg_replace('/\.ini$/', '-' . time() . '.ini', $fs_config_file);
2557             if (@copy($fs_config_file, $new_filename)) {
2558                 $fp = @fopen($fs_config_file, 'w');
2559             }
2560         } else {
2561             $fp = @fopen($fs_config_file, 'w');
2562         }
2563     } else {
2564         $fp = false;
2565     }
2566
2567     if ($fp) {
2568         fputs($fp, utf8_encode($config));
2569         fclose($fp);
2570         echo "<p>The configuration was written to <code><b>$config_file</b></code>.</p>\n";
2571         if ($new_filename) {
2572             echo "<p>A backup was made to <code><b>$new_filename</b></code>.</p>\n";
2573         } else {
2574             ; //echo "<p><strong>You must rename or copy this</strong> <code><b>$config_file</b></code> <strong>file to</strong> <code><b>config/config.ini</b></code>.</p>\n";
2575         }
2576     } else {
2577         echo "<p>The configuration file could <b>not</b> be written.<br />\n",
2578         " You should copy the above configuration to a file, ",
2579         "and manually save it as <code><b>config/config.ini</b></code>.</p>\n";
2580     }
2581
2582     echo "<hr />\n<p>Here's the configuration file based on your answers:</p>\n";
2583     echo "<form method=\"get\" action=\"", $configurator, "\">\n";
2584     echo "<textarea id='config-output' readonly='readonly' style='width:100%;' rows='30' cols='100'>\n";
2585     echo htmlentities($config, ENT_COMPAT, "UTF-8");
2586     echo "</textarea></form>\n";
2587     echo "<hr />\n";
2588
2589     echo "<p>To make any corrections, <a href=\"configurator.php\">edit the settings again</a>.</p>\n";
2590
2591 } else { // first time or create password
2592     $posted = $GLOBALS['HTTP_POST_VARS'];
2593     // No action has been specified - we make a form.
2594
2595     if (!empty($GLOBALS['HTTP_GET_VARS']['start_debug']))
2596         $configurator .= ("?start_debug=" . $GLOBALS['HTTP_GET_VARS']['start_debug']);
2597     echo '
2598 <form action="', $configurator, '" method="post">
2599 <input type="hidden" name="action" value="make_config" />
2600 <table cellpadding="4" cellspacing="0">
2601 ';
2602
2603     while (list($property, $obj) = each($properties)) {
2604         echo $obj->get_instructions($property);
2605         if ($h = $obj->get_html()) {
2606             if (defined('DEBUG') and DEBUG) $h = get_class($obj) . "<br />\n" . $h;
2607             echo "<td>" . $h . "</td>\n";
2608         }
2609         echo '</tr>';
2610     }
2611
2612     echo '
2613 </table>
2614 <p><input type="submit" id="submit" value="Save ', $config_file, '" /> <input type="reset" value="Clear" /></p>
2615 </form>
2616 ';
2617 }
2618 ?>
2619 </body>
2620 </html>