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