]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - configurator.php
Better prototype
[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 $properties["Allowed Load"] =
1491     new _define_commented_optional('ALLOWED_LOAD', '/tmp',
1492         'List of directories from which it is allowed to load pages. Directories are separated with ":"');
1493
1494 ///////////////////
1495
1496 $properties["Part Seven"] =
1497     new part('_part7', $SEPARATOR . "\n", "
1498
1499 Part Seven:
1500
1501 Miscellaneous settings
1502 ");
1503
1504 $properties["Strict Mailable Pagedumps"] =
1505     new boolean_define_optional('STRICT_MAILABLE_PAGEDUMPS',
1506         array('false' => "binary",
1507             'true' => "quoted-printable"));
1508
1509 $properties["Default local Dump Directory"] =
1510     new _define_optional('DEFAULT_DUMP_DIR');
1511
1512 $properties["Default local HTML Dump Directory"] =
1513     new _define_optional('HTML_DUMP_DIR');
1514
1515 $properties["HTML Dump Filename Suffix"] =
1516     new _define_optional('HTML_DUMP_SUFFIX');
1517
1518 $properties["Pagename of Recent Changes"] =
1519     new _define_optional('RECENT_CHANGES',
1520         "RecentChanges");
1521
1522 $properties["Disable HTTP Redirects"] =
1523     new boolean_define_commented_optional('DISABLE_HTTP_REDIRECT');
1524
1525 $properties["Disable GETIMAGESIZE"] =
1526     new boolean_define_commented_optional('DISABLE_GETIMAGESIZE');
1527
1528 $properties["EDITING_POLICY"] =
1529     new _define_optional('EDITING_POLICY');
1530
1531 $properties["TOOLBAR_PAGELINK_PULLDOWN"] =
1532     new _define_commented_optional('TOOLBAR_PAGELINK_PULLDOWN');
1533 $properties["TOOLBAR_TEMPLATE_PULLDOWN"] =
1534     new _define_commented_optional('TOOLBAR_TEMPLATE_PULLDOWN');
1535 $properties["TOOLBAR_IMAGE_PULLDOWN"] =
1536     new _define_commented_optional('TOOLBAR_IMAGE_PULLDOWN');
1537 $properties["FULLTEXTSEARCH_STOPLIST"] =
1538     new _define_commented_optional('FULLTEXTSEARCH_STOPLIST');
1539
1540 $properties["Part Seven A"] =
1541     new part('_part7a', $SEPARATOR . "\n", "
1542
1543 Part Seven A:
1544
1545 Optional Plugin Settings and external executables
1546 ");
1547
1548 $properties["FORTUNE_DIR"] =
1549     new _define_commented_optional('FORTUNE_DIR', "/usr/share/fortune");
1550 $properties["USE_EXTERNAL_HTML2PDF"] =
1551     new _define_commented_optional('USE_EXTERNAL_HTML2PDF', "htmldoc --quiet --format pdf14 --no-toc --no-title %s");
1552 $properties["EXTERNAL_HTML2PDF_PAGELIST"] =
1553     new _define_commented_optional('EXTERNAL_HTML2PDF_PAGELIST');
1554 $properties["BABYCART_PATH"] =
1555     new _define_commented_optional('BABYCART_PATH', "/usr/local/bin/babycart");
1556 $properties["GOOGLE_LICENSE_KEY"] =
1557     new _define_commented_optional('GOOGLE_LICENSE_KEY');
1558 $properties["RATEIT_IMGPREFIX"] =
1559     new _define_commented_optional('RATEIT_IMGPREFIX'); //BStar
1560 $properties["GRAPHVIZ_EXE"] =
1561     new _define_commented_optional('GRAPHVIZ_EXE', "/usr/bin/dot");
1562
1563 if (PHP_OS == "Darwin") // Mac OS X
1564     $ttfont = "/System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Home/lib/fonts/LucidaSansRegular.ttf";
1565 elseif (isWindows()) {
1566     $ttfont = $_ENV['windir'] . '\Fonts\Arial.ttf';
1567 } else {
1568     $ttfont = 'luximr'; // This is the only what sourceforge offered.
1569     //$ttfont = 'Helvetica';
1570 }
1571 $properties["TTFONT"] =
1572     new _define_commented_optional('TTFONT', $ttfont);
1573 $properties["VISUALWIKIFONT"] =
1574     new _define_commented_optional('VISUALWIKIFONT'); // Arial
1575 $properties["VISUALWIKI_ALLOWOPTIONS"] =
1576     new boolean_define_commented_optional('VISUALWIKI_ALLOWOPTIONS'); // false
1577 $properties["PLOTICUS_EXE"] =
1578     new _define_commented_optional('PLOTICUS_EXE'); // /usr/local/bin/pl
1579 $properties["PLOTICUS_PREFABS"] =
1580     new _define_commented_optional('PLOTICUS_PREFABS'); // /usr/share/ploticus
1581 $properties["MY_JABBER_ID"] =
1582     new _define_commented_optional('MY_JABBER_ID'); //
1583 $properties["PHPWEATHER_BASE_DIR"] =
1584     new _define_commented_optional('PHPWEATHER_BASE_DIR'); //
1585
1586 $properties["Part Eight"] =
1587     new part('_part8', $SEPARATOR . "\n", "
1588
1589 Part Eight:
1590
1591 Cached Plugin Settings. (pear Cache)
1592 ");
1593
1594 $properties["pear Cache USECACHE"] =
1595     new boolean_define_optional('PLUGIN_CACHED_USECACHE',
1596         array('true' => 'Enabled',
1597             'false' => 'Disabled'), "
1598 Enable or disable pear caching of plugins.");
1599 $properties["pear Cache Database Container"] =
1600     new _define_selection_optional('PLUGIN_CACHED_DATABASE',
1601         array('file' => 'file'), "
1602 Curently only file is supported.
1603 db, trifile and imgfile might be supported, but you must hack that by yourself.");
1604
1605 $properties["pear Cache cache directory"] =
1606     new _define_commented_optional('PLUGIN_CACHED_CACHE_DIR', "/tmp/cache", "
1607 Should be writable to the webserver.");
1608 $properties["pear Cache Filename Prefix"] =
1609     new _define_optional('PLUGIN_CACHED_FILENAME_PREFIX', "phpwiki", "");
1610 $properties["pear Cache HIGHWATER"] =
1611     new numeric_define_optional('PLUGIN_CACHED_HIGHWATER', "4194304", "
1612 Garbage collection parameter.");
1613 $properties["pear Cache LOWWATER"] =
1614     new numeric_define_optional('PLUGIN_CACHED_LOWWATER', "3145728", "
1615 Garbage collection parameter.");
1616 $properties["pear Cache MAXLIFETIME"] =
1617     new numeric_define_optional('PLUGIN_CACHED_MAXLIFETIME', "2592000", "
1618 Garbage collection parameter.");
1619 $properties["pear Cache MAXARGLEN"] =
1620     new numeric_define_optional('PLUGIN_CACHED_MAXARGLEN', "1000", "
1621 max. generated url length.");
1622 $properties["pear Cache FORCE_SYNCMAP"] =
1623     new boolean_define_optional('PLUGIN_CACHED_FORCE_SYNCMAP',
1624         array('true' => 'Enabled',
1625             'false' => 'Disabled'), "");
1626 $properties["pear Cache IMGTYPES"] =
1627     new list_define('PLUGIN_CACHED_IMGTYPES', "png|gif|gd|gd2|jpeg|wbmp|xbm|xpm", "
1628 Handle those image types via GD handles. Check your GD supported image types.");
1629
1630 $end = "\n" . $SEPARATOR . "\n";
1631
1632 // performance hack
1633 text_from_dist("_MAGIC_CLOSE_FILE");
1634
1635 // end of configuration options
1636 ///////////////////////////////
1637 // begin class definitions
1638
1639 /**
1640  * A basic config-dist.ini configuration line in the form of a variable.
1641  * (not needed anymore, we have only defines)
1642  *
1643  * Produces a string in the form "$name = value;"
1644  * e.g.:
1645  * $WikiNameRegexp = "value";
1646  */
1647 class _variable
1648 {
1649
1650     var $config_item_name;
1651     var $default_value;
1652     var $description;
1653     var $prefix;
1654     var $jscheck;
1655
1656     function _variable($config_item_name, $default_value = '', $description = '', $jscheck = '')
1657     {
1658         $this->config_item_name = $config_item_name;
1659         if (!$description)
1660             $description = text_from_dist($config_item_name);
1661         $this->description = $description;
1662         if (defined($config_item_name)
1663             and !preg_match("/(selection|boolean)/", get_class($this))
1664                 and !preg_match("/^(SCRIPT_NAME|VIRTUAL_PATH|TEMP_DIR)$/", $config_item_name)
1665         )
1666             $this->default_value = constant($config_item_name); // ignore given default value
1667         elseif ($config_item_name == $default_value)
1668             $this->default_value = ''; else
1669             $this->default_value = $default_value;
1670         $this->jscheck = $jscheck;
1671         if (preg_match("/variable/i", get_class($this)))
1672             $this->prefix = "\$";
1673         elseif (preg_match("/ini_set/i", get_class($this)))
1674             $this->prefix = "ini_get: "; else
1675             $this->prefix = "";
1676     }
1677
1678     function _define($config_item_name, $default_value = '', $description = '', $jscheck = '')
1679     {
1680         $this->_variable($config_item_name, $default_value, $description, $jscheck);
1681     }
1682
1683     function value()
1684     {
1685         global $HTTP_POST_VARS;
1686         if (isset($HTTP_POST_VARS[$this->config_item_name]))
1687             return $HTTP_POST_VARS[$this->config_item_name];
1688         else
1689             return $this->default_value;
1690     }
1691
1692     function _config_format($value)
1693     {
1694         return '';
1695         /*
1696         $v = $this->get_config_item_name();
1697         // handle arrays: a|b --> a['b']
1698         if (strpos($v, '|')) {
1699             list($a, $b) = explode('|', $v);
1700             $v = sprintf("%s['%s']", $a, $b);
1701         }
1702         if (preg_match("/[\"']/", $value))
1703             $value = '"' . $value . '"';
1704         return sprintf("%s = \"%s\"", $v, $value);
1705         */
1706     }
1707
1708     function get_config_item_name()
1709     {
1710         return $this->config_item_name;
1711     }
1712
1713     function get_config_item_id()
1714     {
1715         return str_replace('|', '-', $this->config_item_name);
1716     }
1717
1718     function get_config_item_header()
1719     {
1720         if (strchr($this->config_item_name, '|')) {
1721             list($var, $param) = explode('|', $this->config_item_name);
1722             return "<b>" . $this->prefix . $var . "['" . $param . "']</b><br />";
1723         } elseif ($this->config_item_name[0] != '_')
1724             return "<b>" . $this->prefix . $this->config_item_name . "</b><br />"; else
1725             return '';
1726     }
1727
1728     function _get_description()
1729     {
1730         return $this->description;
1731     }
1732
1733     function _get_config_line($posted_value)
1734     {
1735         return "\n" . $this->_config_format($posted_value);
1736     }
1737
1738     function get_config($posted_value)
1739     {
1740         $d = stripHtml($this->_get_description());
1741         $d = str_replace("\n", "\n; ", $d) . $this->_get_config_line($posted_value) . "\n";
1742         return $d;
1743     }
1744
1745     function get_instructions($title)
1746     {
1747         global $tdwidth;
1748         $i = "<h3>" . $title . "</h3>\n    " . nl2p($this->_get_description()) . "\n";
1749         return "<tr>\n<td width=\"$tdwidth\" class=\"instructions\">\n" . $i . "</td>\n";
1750     }
1751
1752     function get_html()
1753     {
1754         $size = strlen($this->default_value) > 45 ? 90 : 50;
1755         return $this->get_config_item_header() .
1756             "<input type=\"text\" size=\"$50\" name=\"" . $this->get_config_item_name() . "\" value=\"" . htmlspecialchars($this->default_value) . "\" " .
1757             $this->jscheck . " />" . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1758     }
1759 }
1760
1761 class unchangeable_variable
1762     extends _variable
1763 {
1764     function _config_format($value)
1765     {
1766         return "";
1767     }
1768
1769     // function get_html() { return false; }
1770     function get_html()
1771     {
1772         return $this->get_config_item_header() .
1773             "<em>Not editable.</em>" .
1774             "<pre>" . $this->default_value . "</pre>";
1775     }
1776
1777     function _get_config_line($posted_value)
1778     {
1779         if ($this->description)
1780             $n = "\n";
1781         return "${n}" . $this->default_value;
1782     }
1783
1784     function get_instructions($title)
1785     {
1786         global $tdwidth;
1787         $i = "<h3>" . $title . "</h3>\n    " . nl2p($this->_get_description()) . "\n";
1788         // $i .= "<em>Not editable.</em><br />\n<pre>" . $this->default_value."</pre>";
1789         return '<tr><td style="width:100%;" class="unchangeable-variable-top" colspan="2">' . "\n" . $i . "</td></tr>\n"
1790             . '<tr style="border-top: none;"><td class="unchangeable-variable-left" width="' . $tdwidth . '">&nbsp;</td>';
1791     }
1792 }
1793
1794 class unchangeable_define
1795     extends unchangeable_variable
1796 {
1797     function _get_config_line($posted_value)
1798     {
1799         if ($this->description)
1800             $n = "\n";
1801         if (!$posted_value)
1802             $posted_value = $this->default_value;
1803         return "${n}" . $this->_config_format($posted_value);
1804     }
1805
1806     function _config_format($value)
1807     {
1808         return sprintf("%s = \"%s\"", $this->get_config_item_name(), $value);
1809     }
1810 }
1811 class unchangeable_ini_set
1812     extends unchangeable_variable
1813 {
1814     function _config_format($value)
1815     {
1816         return "";
1817     }
1818 }
1819
1820 class _variable_selection
1821     extends _variable
1822 {
1823     function value()
1824     {
1825         global $HTTP_POST_VARS;
1826         if (!empty($HTTP_POST_VARS[$this->config_item_name]))
1827             return $HTTP_POST_VARS[$this->config_item_name];
1828         else {
1829             list($option, $label) = each($this->default_value);
1830             return $option;
1831         }
1832     }
1833
1834     function get_html()
1835     {
1836         $output = $this->get_config_item_header();
1837         $output .= '<select name="' . $this->get_config_item_name() . "\">\n";
1838         /* The first option is the default */
1839         $values = $this->default_value;
1840         if (defined($this->get_config_item_name()))
1841             $this->default_value = constant($this->get_config_item_name());
1842         else
1843             $this->default_value = null;
1844
1845         foreach ($values as $option => $label) {
1846             if (!is_null($this->default_value) && $this->default_value === $option)
1847                 $output .= "  <option value=\"$option\" selected=\"selected\">$label</option>\n";
1848             else
1849                 $output .= "  <option value=\"$option\">$label</option>\n";
1850         }
1851         $output .= "</select>\n";
1852         return $output;
1853     }
1854 }
1855
1856 class _define
1857     extends _variable
1858 {
1859     function _config_format($value)
1860     {
1861         return sprintf("%s = \"%s\"", $this->get_config_item_name(), $value);
1862     }
1863
1864     function _get_config_line($posted_value)
1865     {
1866         if ($this->description)
1867             $n = "\n";
1868         if ($posted_value == '')
1869             return "${n};" . $this->_config_format("");
1870         else
1871             return "${n}" . $this->_config_format($posted_value);
1872     }
1873
1874     function get_html()
1875     {
1876         $size = strlen($this->default_value) > 45 ? 90 : 50;
1877         return $this->get_config_item_header()
1878             . "<input type=\"text\" size=\"$size\" name=\"" . htmlentities($this->get_config_item_name())
1879             . "\" value=\"" . htmlentities($this->default_value) . "\" {$this->jscheck} />"
1880             . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1881     }
1882 }
1883
1884 class _define_commented
1885     extends _define
1886 {
1887     function _get_config_line($posted_value)
1888     {
1889         if ($this->description)
1890             $n = "\n";
1891         if ($posted_value == $this->default_value)
1892             return "${n};" . $this->_config_format($posted_value);
1893         elseif ($posted_value == '')
1894             return "${n};" . $this->_config_format(""); else
1895             return "${n}" . $this->_config_format($posted_value);
1896     }
1897 }
1898
1899 /**
1900  * We don't use _optional anymore, because INI-style config's don't need that.
1901  * IniConfig.php does the optional logic now.
1902  * But we use _optional for config-default.ini options
1903  */
1904 class _define_commented_optional
1905     extends _define_commented
1906 {
1907 }
1908
1909 class _define_optional
1910     extends _define
1911 {
1912 }
1913
1914 class _define_notempty
1915     extends _define
1916 {
1917     function get_html()
1918     {
1919         $s = $this->get_config_item_header()
1920             . "<input type=\"text\" size=\"50\" name=\"" . $this->get_config_item_name()
1921             . "\" value=\"" . $this->default_value . "\" {$this->jscheck} />";
1922         if (empty($this->default_value))
1923             return $s . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Cannot be empty.</p>";
1924         else
1925             return $s . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1926     }
1927 }
1928
1929 class _variable_commented
1930     extends _variable
1931 {
1932     function _get_config_line($posted_value)
1933     {
1934         if ($this->description)
1935             $n = "\n";
1936         if ($posted_value == $this->default_value)
1937             return "${n};" . $this->_config_format($posted_value);
1938         elseif ($posted_value == '')
1939             return "${n};" . $this->_config_format(""); else
1940             return "${n}" . $this->_config_format($posted_value);
1941     }
1942 }
1943
1944 class numeric_define
1945     extends _define
1946 {
1947
1948     function numeric_define($config_item_name, $default_value = '', $description = '', $jscheck = '')
1949     {
1950         $this->_define($config_item_name, $default_value, $description, $jscheck);
1951         if (!$jscheck)
1952             $this->jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' is not an integer.', '^[-+]?[0-9]+$', '" . $this->get_config_item_name() . "', this);\"";
1953     }
1954
1955     function _config_format($value)
1956     {
1957         //return sprintf("define('%s', %s);", $this->get_config_item_name(), $value);
1958         return sprintf("%s = %s", $this->get_config_item_name(), $value);
1959     }
1960
1961     function _get_config_line($posted_value)
1962     {
1963         if ($this->description)
1964             $n = "\n";
1965         if ($posted_value == '')
1966             return "${n};" . $this->_config_format('0');
1967         else
1968             return "${n}" . $this->_config_format($posted_value);
1969     }
1970 }
1971
1972 class numeric_define_optional
1973     extends numeric_define
1974 {
1975 }
1976
1977 class numeric_define_commented
1978     extends numeric_define
1979 {
1980     function _get_config_line($posted_value)
1981     {
1982         if ($this->description)
1983             $n = "\n";
1984         if ($posted_value == $this->default_value)
1985             return "${n};" . $this->_config_format($posted_value);
1986         elseif ($posted_value == '')
1987             return "${n};" . $this->_config_format('0'); else
1988             return "${n}" . $this->_config_format($posted_value);
1989     }
1990 }
1991
1992 class _define_selection
1993     extends _variable_selection
1994 {
1995     function _config_format($value)
1996     {
1997         return sprintf("%s = %s", $this->get_config_item_name(), $value);
1998     }
1999
2000     function _get_config_line($posted_value)
2001     {
2002         return _define::_get_config_line($posted_value);
2003     }
2004
2005     function get_html()
2006     {
2007         return _variable_selection::get_html();
2008     }
2009 }
2010
2011 class _define_selection_optional
2012     extends _define_selection
2013 {
2014 }
2015
2016 class _variable_selection_optional
2017     extends _variable_selection
2018 {
2019 }
2020
2021 class _define_selection_optional_commented
2022     extends _define_selection_optional
2023 {
2024     function _get_config_line($posted_value)
2025     {
2026         if ($this->description)
2027             $n = "\n";
2028         if ($posted_value == $this->default_value)
2029             return "${n};" . $this->_config_format($posted_value);
2030         elseif ($posted_value == '')
2031             return "${n};" . $this->_config_format(""); else
2032             return "${n}" . $this->_config_format($posted_value);
2033     }
2034 }
2035
2036 class _define_password
2037     extends _define
2038 {
2039
2040     function _define_password($config_item_name, $default_value = '', $description = '', $jscheck = '')
2041     {
2042         if ($config_item_name == $default_value) $default_value = '';
2043         $this->_define($config_item_name, $default_value, $description, $jscheck);
2044         if (!$jscheck)
2045             $this->jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' cannot be empty.', '^.+$', '"
2046                 . $this->get_config_item_name() . "', this);\"";
2047     }
2048
2049     function _get_config_line($posted_value)
2050     {
2051         if ($this->description)
2052             $n = "\n";
2053         if ($posted_value == '') {
2054             $p = "${n};" . $this->_config_format("");
2055             $p .= "\n; If you used the passencrypt.php utility to encode the password";
2056             $p .= "\n; then uncomment this line:";
2057             $p .= "\n;ENCRYPTED_PASSWD = true";
2058             return $p;
2059         } else {
2060             $salt_length = max(CRYPT_SALT_LENGTH,
2061                 2 * CRYPT_STD_DES,
2062                 9 * CRYPT_EXT_DES,
2063                 12 * CRYPT_MD5,
2064                 16 * CRYPT_BLOWFISH);
2065             // generate an encrypted password
2066             $crypt_pass = crypt($posted_value, rand_ascii($salt_length));
2067             $p = "${n}" . $this->_config_format($crypt_pass);
2068             return $p . "\nENCRYPTED_PASSWD = true";
2069         }
2070     }
2071
2072     function get_html()
2073     {
2074         return _variable_password::get_html();
2075     }
2076 }
2077
2078 class _define_password_optional
2079     extends _define_password
2080 {
2081
2082     function _define_password_optional($config_item_name, $default_value = '', $description = '', $jscheck = '')
2083     {
2084         if ($config_item_name == $default_value) $default_value = '';
2085         if (!$jscheck) $this->jscheck = " ";
2086         $this->_define($config_item_name, $default_value, $description, $jscheck);
2087     }
2088
2089     function _get_config_line($posted_value)
2090     {
2091         if ($this->description)
2092             $n = "\n";
2093         if ($posted_value == '') {
2094             return "${n};" . $this->_config_format("");
2095         } else {
2096             return "${n}" . $this->_config_format($posted_value);
2097         }
2098     }
2099
2100     function get_html()
2101     {
2102         $s = $this->get_config_item_header();
2103         // dont re-encrypt already encrypted passwords
2104         $value = $this->value();
2105         $encrypted = !empty($GLOBALS['properties']["Encrypted Passwords"]) and
2106             $GLOBALS['properties']["Encrypted Passwords"]->value();
2107         if (empty($value))
2108             $encrypted = false;
2109         $s .= "<input type=\"" . ($encrypted ? "text" : "password") . "\" name=\"" . $this->get_config_item_name()
2110             . "\" value=\"" . $value . "\" {$this->jscheck} />";
2111         return $s;
2112     }
2113 }
2114
2115 class _define_password_commented_optional
2116     extends _define_password_optional
2117 {
2118 }
2119
2120 class _variable_password
2121     extends _variable
2122 {
2123     function _variable_password($config_item_name, $default_value = '', $description = '', $jscheck = '')
2124     {
2125         if ($config_item_name == $default_value) $default_value = '';
2126         $this->_define($config_item_name, $default_value, $description, $jscheck);
2127         if (!$jscheck)
2128             $this->jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' cannot be empty.', '^.+$', '" . $this->get_config_item_name() . "', this);\"";
2129     }
2130
2131     function get_html()
2132     {
2133         global $HTTP_POST_VARS, $HTTP_GET_VARS;
2134         $s = $this->get_config_item_header();
2135         if (isset($HTTP_POST_VARS['create']) or isset($HTTP_GET_VARS['create'])) {
2136             $new_password = random_good_password();
2137             $this->default_value = $new_password;
2138             $s .= "Created password: <strong>$new_password</strong><br />&nbsp;<br />";
2139         }
2140         // dont re-encrypt already encrypted passwords
2141         $value = $this->value();
2142         $encrypted = !empty($GLOBALS['properties']["Encrypted Passwords"]) and
2143             $GLOBALS['properties']["Encrypted Passwords"]->value();
2144         if (empty($value))
2145             $encrypted = false;
2146         $s .= "<input type=\"" . ($encrypted ? "text" : "password") . "\" name=\"" . $this->get_config_item_name()
2147             . "\" value=\"" . $value . "\" {$this->jscheck} />"
2148             . "&nbsp;&nbsp;<input type=\"submit\" name=\"create\" value=\"Create Random Password\" />";
2149         if (empty($value))
2150             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Cannot be empty.</p>";
2151         elseif (strlen($this->default_value) < 4)
2152             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Must be longer than 4 chars.</p>"; else
2153             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2154         return $s;
2155     }
2156 }
2157
2158 class list_variable
2159     extends _variable
2160 {
2161     function _get_config_line($posted_value)
2162     {
2163         // split the phrase by any number of commas or space characters,
2164         // which include " ", \r, \t, \n and \f
2165         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2166         if ($list_values)
2167             $list_values = join("|", $list_values);
2168         return _variable::_get_config_line($list_values);
2169     }
2170
2171     function get_html()
2172     {
2173         $list_values = explode("|", $this->default_value);
2174         $rows = max(3, count($list_values) + 1);
2175         $list_values = join("\n", $list_values);
2176         $ta = $this->get_config_item_header();
2177         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2178         $ta .= $list_values . "</textarea>";
2179         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2180         return $ta;
2181     }
2182 }
2183
2184 class list_define
2185     extends _define
2186 {
2187     function _get_config_line($posted_value)
2188     {
2189         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2190         if ($list_values)
2191             $list_values = join("|", $list_values);
2192         return _variable::_get_config_line($list_values);
2193     }
2194
2195     function get_html()
2196     {
2197         $list_values = explode("|", $this->default_value);
2198         $rows = max(3, count($list_values) + 1);
2199         if ($list_values)
2200             $list_values = join("\n", $list_values);
2201         $ta = $this->get_config_item_header();
2202         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2203         $ta .= $list_values . "</textarea>";
2204         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2205         return $ta;
2206     }
2207 }
2208
2209 class array_variable
2210     extends _variable
2211 {
2212     function _config_format($value)
2213     {
2214         return sprintf("%s = \"%s\"", $this->get_config_item_name(),
2215             is_array($value) ? join(':', $value) : $value);
2216     }
2217
2218     function _get_config_line($posted_value)
2219     {
2220         // split the phrase by any number of commas or space characters,
2221         // which include " ", \r, \t, \n and \f
2222         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2223         if (!empty($list_values)) {
2224             $list_values = "'" . join("', '", $list_values) . "'";
2225             return "\n" . $this->_config_format($list_values);
2226         } else
2227             return "\n;" . $this->_config_format('');
2228     }
2229
2230     function get_html()
2231     {
2232         if (is_array($this->default_value))
2233             $list_values = join("\n", $this->default_value);
2234         else
2235             $list_values = $this->default_value;
2236         $rows = max(3, count($this->default_value) + 1);
2237         $ta = $this->get_config_item_header();
2238         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2239         $ta .= $list_values . "</textarea>";
2240         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2241         return $ta;
2242     }
2243 }
2244
2245 class array_define
2246     extends _define
2247 {
2248     function _config_format($value)
2249     {
2250         return sprintf("%s = \"%s\"", $this->get_config_item_name(),
2251             is_array($value) ? join(' : ', $value) : $value);
2252     }
2253
2254     function _get_config_line($posted_value)
2255     {
2256         // split the phrase by any number of commas or space characters,
2257         // which include " ", \r, \t, \n and \f
2258         $list_values = preg_split("/[\s,:]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
2259         if (!empty($list_values)) {
2260             $list_values = join(" : ", $list_values);
2261             return "\n" . $this->_config_format($list_values);
2262         } else
2263             return "\n;" . $this->_config_format('');
2264     }
2265
2266     function get_html()
2267     {
2268         if (!$this->default_value)
2269             $this->default_value = array();
2270         elseif (is_string($this->default_value))
2271             $this->default_value = preg_split("/[\s,:]+/", $this->default_value, -1, PREG_SPLIT_NO_EMPTY);
2272         $list_values = join(" : \n", $this->default_value);
2273         $rows = max(3, count($this->default_value) + 1);
2274         $ta = $this->get_config_item_header();
2275         $ta .= "<textarea cols=\"18\" rows=\"" . $rows . "\" name=\"" . $this->get_config_item_name() . "\" {$this->jscheck}>";
2276         $ta .= $list_values . "</textarea>";
2277         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
2278         return $ta;
2279     }
2280 }
2281
2282 /*
2283 class _ini_set
2284 extends _variable {
2285     function value() {
2286         global $HTTP_POST_VARS;
2287         if ($v = $HTTP_POST_VARS[$this->config_item_name])
2288             return $v;
2289         else {
2290             return ini_get($this->get_config_item_name);
2291         }
2292     }
2293     function _config_format($value) {
2294         return sprintf("ini_set('%s', '%s');", $this->get_config_item_name(), $value);
2295     }
2296     function _get_config_line($posted_value) {
2297         if ($posted_value && ! $posted_value == $this->default_value)
2298             return "\n" . $this->_config_format($posted_value);
2299         else
2300             return "\n;" . $this->_config_format($this->default_value);
2301     }
2302 }
2303 */
2304
2305 class boolean_define
2306     extends _define
2307 {
2308
2309     // adds ->values property, instead of ->default_value
2310     function boolean_define($config_item_name, $values = false, $description = '', $jscheck = '')
2311     {
2312         $this->config_item_name = $config_item_name;
2313         if (!$description)
2314             $description = text_from_dist($config_item_name);
2315         $this->description = $description;
2316         // TESTME: get boolean default value from config-default.ini
2317         if (defined($config_item_name))
2318             $this->default_value = constant($config_item_name); // ignore given default value
2319         elseif (is_array($values))
2320             list($this->default_value, $dummy) = $values[0];
2321         if (!$values)
2322             $values = array('false' => "Disabled",
2323                 'true' => "Enabled");
2324         $this->values = $values;
2325         $this->jscheck = $jscheck;
2326         $this->prefix = "";
2327     }
2328
2329     function _get_config_line($posted_value)
2330     {
2331         if ($this->description)
2332             $n = "\n";
2333         return "${n}" . $this->_config_format($posted_value);
2334     }
2335
2336     function _config_format($value)
2337     {
2338         if (strtolower(trim($value)) == 'false')
2339             $value = false;
2340         return sprintf("%s = %s", $this->get_config_item_name(),
2341             (bool)$value ? 'true' : 'false');
2342     }
2343
2344     //TODO: radiobuttons, no list
2345     function get_html()
2346     {
2347         $output = $this->get_config_item_header();
2348         $name = $this->get_config_item_name();
2349         $output .= '<select name="' . $name . "\" {$this->jscheck}>\n";
2350         $values = $this->values;
2351         $default_value = $this->default_value ? 'true' : 'false';
2352         /* There can usually only be two options, there can be
2353          * three options in the case of a boolean_define_commented_optional */
2354         while (list($option, $label) = each($values)) {
2355             if (!is_null($this->default_value) and $option === $default_value)
2356                 $output .= "  <option value=\"$option\" selected=\"selected\">$label</option>\n";
2357             else
2358                 $output .= "  <option value=\"$option\">$label</option>\n";
2359         }
2360         $output .= "</select>\n";
2361         return $output;
2362     }
2363 }
2364
2365 class boolean_define_optional
2366     extends boolean_define
2367 {
2368 }
2369
2370 class boolean_define_commented
2371     extends boolean_define
2372 {
2373     function _get_config_line($posted_value)
2374     {
2375         if ($this->description)
2376             $n = "\n";
2377         list($default_value, $label) = each($this->default_value);
2378         if ($posted_value == $default_value)
2379             return "${n};" . $this->_config_format($posted_value);
2380         elseif ($posted_value == '')
2381             return "${n};" . $this->_config_format('false'); else
2382             return "${n}" . $this->_config_format($posted_value);
2383     }
2384 }
2385
2386 class boolean_define_commented_optional
2387     extends boolean_define_commented
2388 {
2389 }
2390
2391 class part
2392     extends _variable
2393 {
2394     function value()
2395     {
2396         return;
2397     }
2398
2399     function get_config($posted_value)
2400     {
2401         $d = stripHtml($this->_get_description());
2402         global $SEPARATOR;
2403         return "\n" . $SEPARATOR . str_replace("\n", "\n; ", $d) . "\n" . $this->default_value;
2404     }
2405
2406     function get_instructions($title)
2407     {
2408         $id = preg_replace("/\W/", "", $this->config_item_name);
2409         $group_name = preg_replace("/\W/", "", $title);
2410         $i = '<tr class="header" id="'.$id.'">'."\n";
2411         $i .= '<td class="part" style="width:100%;background-color:#eee;" colspan="2">'."\n";
2412         $i .= "<h2>" . $title . "</h2>\n    " . nl2p($this->_get_description()) . "\n";
2413         $i .= "<p><a href=\"javascript:toggle_group('$id')\" id=\"{$id}_text\">Hide options.</a></p>";
2414         return $i . "</td>\n";
2415     }
2416
2417     function get_html()
2418     {
2419         return "";
2420     }
2421 }
2422
2423 // html utility functions
2424 function nl2p($text)
2425 {
2426     preg_match_all("@\s*(<pre>.*?</pre>|<dl>.*?</dl>|.*?(?=\n\n|<pre>|<dl>|$))@s",
2427         $text, $m, PREG_PATTERN_ORDER);
2428
2429     $text = '';
2430     foreach ($m[1] as $par) {
2431         if (!($par = trim($par)))
2432             continue;
2433         if (!preg_match('/^<(pre|dl)>/', $par))
2434             $par = "<p>$par</p>";
2435         $text .= $par;
2436     }
2437     return $text;
2438 }
2439
2440 function text_from_dist($var)
2441 {
2442     static $distfile = 0;
2443     static $f;
2444
2445     if (!$distfile) {
2446         $sep = (substr(PHP_OS, 0, 3) == 'WIN' ? '\\' : '/');
2447         $distfile = dirname(__FILE__) . $sep . "config" . $sep . "config-dist.ini";
2448         $f = fopen($distfile, "r");
2449     }
2450     if ($var == '_MAGIC_CLOSE_FILE') {
2451         fclose($f);
2452         return '';
2453     }
2454     // if all vars would be in natural order as in the config-dist this would not be needed.
2455     fseek($f, 0);
2456     $par = "\n";
2457     while (!feof($f)) {
2458         $s = fgets($f);
2459         if (preg_match("/^; \w/", $s)) {
2460             $par .= (substr($s, 2) . " ");
2461         } elseif (preg_match("/^;\s*$/", $s)) {
2462             $par .= "\n\n";
2463         }
2464         if (preg_match("/^;?" . preg_quote($var) . "\s*=/", $s))
2465             return $par;
2466         if (preg_match("/^\s*$/", $s)) // new paragraph
2467             $par = "\n";
2468     }
2469     return '';
2470 }
2471
2472 function stripHtml($text)
2473 {
2474     $d = str_replace("<pre>", "", $text);
2475     $d = str_replace("</pre>", "", $d);
2476     $d = str_replace("<dl>", "", $d);
2477     $d = str_replace("</dl>", "", $d);
2478     $d = str_replace("<dt>", "", $d);
2479     $d = str_replace("</dt>", "", $d);
2480     $d = str_replace("<dd>", "", $d);
2481     $d = str_replace("</dd>", "", $d);
2482     $d = str_replace("<p>", "", $d);
2483     $d = str_replace("</p>", "", $d);
2484     //restore html entities into characters
2485     // http://www.php.net/manual/en/function.htmlentities.php
2486     $trans = get_html_translation_table(HTML_ENTITIES);
2487     $trans = array_flip($trans);
2488     $d = strtr($d, $trans);
2489     return $d;
2490 }
2491
2492 include_once(dirname(__FILE__) . "/lib/stdlib.php");
2493
2494 ////
2495 // Function to create better user passwords (much larger keyspace),
2496 // suitable for user passwords.
2497 // Sequence of random ASCII numbers, letters and some special chars.
2498 // Note: There exist other algorithms for easy-to-remember passwords.
2499 function random_good_password($minlength = 5, $maxlength = 8)
2500 {
2501     $newpass = '';
2502     // assume ASCII ordering (not valid on EBCDIC systems!)
2503     $valid_chars = "!#%&+-.0123456789=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
2504     $start = ord($valid_chars);
2505     $end = ord(substr($valid_chars, -1));
2506     $length = mt_rand($minlength, $maxlength);
2507     while ($length > 0) {
2508         $newchar = mt_rand($start, $end);
2509         if (!strrpos($valid_chars, $newchar)) continue; // skip holes
2510         $newpass .= sprintf("%c", $newchar);
2511         $length--;
2512     }
2513     return ($newpass);
2514 }
2515
2516 // debugging
2517 function printArray($a)
2518 {
2519     echo "<hr />\n<pre>\n";
2520     print_r($a);
2521     echo "\n</pre>\n<hr />\n";
2522 }
2523
2524 // end of class definitions
2525 /////////////////////////////
2526 // begin auto generation code
2527
2528 if (!empty($HTTP_POST_VARS['action'])
2529     and $HTTP_POST_VARS['action'] == 'make_config'
2530         and !empty($HTTP_POST_VARS['ADMIN_USER'])
2531             and !empty($HTTP_POST_VARS['ADMIN_PASSWD'])
2532 ) {
2533
2534     $timestamp = date('dS \of F, Y H:i:s');
2535
2536     $config = "
2537 ; This is a local configuration file for PhpWiki.
2538 ; It was automatically generated by the configurator script
2539 ; on the $timestamp.
2540 ;
2541 ; $preamble
2542 ";
2543
2544     $posted = $GLOBALS['HTTP_POST_VARS'];
2545     /*if (defined('DEBUG'))
2546      printArray($GLOBALS['HTTP_POST_VARS']);*/
2547
2548     foreach ($properties as $option_name => $a) {
2549         $posted_value = stripslashes($posted[$a->config_item_name]);
2550         $config .= $properties[$option_name]->get_config($posted_value);
2551     }
2552
2553     $config .= $end;
2554
2555     if (is_writable($fs_config_file)) {
2556         // We first check if the config-file exists.
2557         if (file_exists($fs_config_file)) {
2558             // We make a backup copy of the file
2559             $new_filename = preg_replace('/\.ini$/', '-' . time() . '.ini', $fs_config_file);
2560             if (@copy($fs_config_file, $new_filename)) {
2561                 $fp = @fopen($fs_config_file, 'w');
2562             }
2563         } else {
2564             $fp = @fopen($fs_config_file, 'w');
2565         }
2566     } else {
2567         $fp = false;
2568     }
2569
2570     if ($fp) {
2571         fputs($fp, utf8_encode($config));
2572         fclose($fp);
2573         echo "<p>The configuration was written to <code><b>$config_file</b></code>.</p>\n";
2574         if ($new_filename) {
2575             echo "<p>A backup was made to <code><b>$new_filename</b></code>.</p>\n";
2576         } else {
2577             ; //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";
2578         }
2579     } else {
2580         echo "<p>The configuration file could <b>not</b> be written.<br />\n",
2581         " You should copy the above configuration to a file, ",
2582         "and manually save it as <code><b>config/config.ini</b></code>.</p>\n";
2583     }
2584
2585     echo "<hr />\n<p>Here's the configuration file based on your answers:</p>\n";
2586     echo "<form method=\"get\" action=\"", $configurator, "\">\n";
2587     echo "<textarea id='config-output' readonly='readonly' style='width:100%;' rows='30' cols='100'>\n";
2588     echo htmlentities($config, ENT_COMPAT, "UTF-8");
2589     echo "</textarea></form>\n";
2590     echo "<hr />\n";
2591
2592     echo "<p>To make any corrections, <a href=\"configurator.php\">edit the settings again</a>.</p>\n";
2593
2594 } else { // first time or create password
2595     $posted = $GLOBALS['HTTP_POST_VARS'];
2596     // No action has been specified - we make a form.
2597
2598     if (!empty($GLOBALS['HTTP_GET_VARS']['start_debug']))
2599         $configurator .= ("?start_debug=" . $GLOBALS['HTTP_GET_VARS']['start_debug']);
2600     echo '
2601 <form action="', $configurator, '" method="post">
2602 <input type="hidden" name="action" value="make_config" />
2603 <table cellpadding="4" cellspacing="0">
2604 ';
2605
2606     while (list($property, $obj) = each($properties)) {
2607         echo $obj->get_instructions($property);
2608         if ($h = $obj->get_html()) {
2609             if (defined('DEBUG') and DEBUG) $h = get_class($obj) . "<br />\n" . $h;
2610             echo "<td>" . $h . "</td>\n";
2611         }
2612         echo '</tr>';
2613     }
2614
2615     echo '
2616 </table>
2617 <p><input type="submit" id="submit" value="Save ', $config_file, '" /> <input type="reset" value="Clear" /></p>
2618 </form>
2619 ';
2620 }
2621 ?>
2622 </body>
2623 </html>