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