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