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