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