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