]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - configurator.php
New feature: Automatic extraction of keywords (for the meta keywords tag)
[SourceForge/phpwiki.git] / configurator.php
1 <?php 
2 /*
3  * Todo: 
4  *   * validate input (fix javascript, add POST checks)
5  *   * start this automatically the first time
6  *   * fix include_path
7  *   * eval index-user.php or index.php to get the actual settings.
8  *   * ask to store it in index.php or index-user.php
9  * 
10  * The file index-user.php will be generated which you can use as your index.php.
11  */
12
13 $tdwidth = 700;
14 $config_file = 'index-user.php';
15 $fs_config_file = dirname(__FILE__) . (substr(PHP_OS,0,3) == 'WIN' ? '\\' : "/") . $config_file;
16 if (isset($HTTP_POST_VARS['create']))  header('Location: configurator.php?create=1#create');
17 printf("<?xml version=\"1.0\" encoding=\"%s\"?>\n", 'iso-8859-1'); 
18 ?>
19 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
20   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
21 <html xmlns="http://www.w3.org/1999/xhtml">
22 <head>
23 <!-- $Id: configurator.php,v 1.15 2003-03-07 20:51:49 dairiki Exp $ -->
24 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
25 <title>Configuration tool for PhpWiki 1.3.x</title>
26 <style type="text/css" media="screen">
27 <!--
28 /* TABLE { border: thin solid black } */
29 body { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 80%; }
30 pre { font-size: 120%; }
31 td { border: thin solid black }
32 tr { border: none }
33 tr.hidden { border: none; display: none; }
34 td.part { background-color: #eeaaaa; color: inherit; }
35 td.instructions { background-color: #ffffee; width: <?php echo $tdwidth ?>px; color: inherit; }
36 td.unchangeable-variable-top   { border-bottom: none; background-color: #eeeeee; color:inherit; }
37 td.unchangeable-variable-left  { border-top: none; background-color: #eeeeee; color:inherit; }
38 -->
39 </style>
40 <script language="JavaScript" type="text/javascript">
41 <!--
42 function update(accepted, error, value, output) {
43   if (accepted) {
44     document.getElementById(output).innerHTML = "<font color=\"green\">Input accepted.</font>";
45   } else {
46     while ((index = error.indexOf("%s")) > -1) {
47       error = error.substring(0, index) + value + error.substring(index+2);
48     }
49     document.getElementById(output).innerHTML = "<font color=\"red\">" + error + "</font>";
50   }
51 }
52
53 function validate(error, value, output, field) {
54   update(field.value == value, error, field.value, output);
55 }
56
57 function validate_ereg(error, ereg, output, field) {
58   regex = new RegExp(ereg);
59   update(regex.test(field.value), error, field.value, output);
60 }
61
62 function validate_range(error, low, high, empty_ok, output, field) {
63   update((empty_ok == 1 && field.value == "") ||
64          (field.value >= low && field.value <= high),
65          error, field.value, output);
66 }
67
68 function toggle_group(id) {
69   var text = document.getElementById(id + "_text");
70   var do_hide = false;
71   if (text.innerHTML == "Hide options.") {
72     do_hide = true;
73     text.innerHTML = "Show options.";
74   } else {
75     text.innerHTML = "Hide options.";
76   }
77
78   var rows = document.getElementsByTagName('tr');
79   var i = 0;
80   for (i = 0; i < rows.length; i++) {
81     var tr = rows[i];
82     if (tr.className == 'header' && tr.id == id) {
83       i++;
84       break;
85     }
86   }
87   for (; i < rows.length; i++) {
88     var tr = rows[i];
89     if (tr.className == 'header')
90       break;
91     tr.className = do_hide ? 'hidden': 'nonhidden';
92   }
93 }
94
95 function do_init() {
96   // Hide all groups.  We do this via JavaScript to avoid
97   // hiding the groups if JavaScript is not supported...
98   var rows = document.getElementsByTagName('tr');
99   for (var i = 0; i < rows.length; i++) {
100     var tr = rows[i];
101     if (tr.className == 'header')
102       toggle_group(tr.id);
103   }
104
105   // Select text in textarea upon focus
106   var area = document.getElementById('config-output');
107   if (area) {
108     listener = { handleEvent: function (e) { area.select(); } };
109     area.addEventListener('focus', listener, false);
110   }
111 }
112   
113 -->
114 </script>
115 </head>
116 <body onload="do_init();">
117
118 <h1>Configuration tool for PhpWiki 1.3.x</h1>
119
120 <?php
121 //define('DEBUG', 1);
122 /**
123  * The Configurator is a php script to aid in the configuration of PhpWiki.
124  * Parts of this file are based on PHPWeather's configurator.php file.
125  * http://sourceforge.net/projects/phpweather/
126  *
127  *
128  * TO CHANGE THE CONFIGURATION OF YOUR PHPWIKI, DO *NOT* MODIFY THIS FILE!
129  * more instructions go here
130  *
131  * Todo: 
132  *   * start this automatically the first time
133  *   * fix include_path
134  *   * eval index.php to get the actual settings.
135  *   * ask to store it in index.php or settings.php
136  * 
137  * The file settings.php will be generated which you can use as your index.php.
138  */
139
140
141 //////////////////////////////
142 // begin configuration options
143
144
145 /**
146  * Notes for the description parameter of $property:
147  *
148  * - Descriptive text will be changed into comments (preceeded by //)
149  *   for the final output to index.php.
150  *
151  * - Only a limited set of html is allowed: pre, dl dt dd; it will be
152  *   stripped from the final output.
153  *
154  * - Line breaks and spacing will be preserved for the final output.
155  *
156  * - Double line breaks are automatically converted to paragraphs
157  *   for the html version of the descriptive text.
158  *
159  * - Double-quotes and dollar signs in the descriptive text must be
160  *   escaped: \" and \$. Instead of escaping double-quotes you can use 
161  *   single (') quotes for the enclosing quotes. 
162  *
163  * - Special characters like < and > must use html entities,
164  *   they will be converted back to characters for the final output.
165  */
166
167 $SEPARATOR = "///////////////////////////////////////////////////////////////////";
168
169 $copyright = '
170 Copyright 1999, 2000, 2001, 2002 $ThePhpWikiProgrammingTeam = array(
171 "Steve Wainstead", "Clifford A. Adams", "Lawrence Akka", 
172 "Scott R. Anderson", "Jon Åslund", "Neil Brown", "Jeff Dairiki",
173 "Stéphane Gourichon", "Jan Hidders", "Arno Hollosi", "John Jorgensen",
174 "Antti Kaihola", "Jeremie Kass", "Carsten Klapp", "Marco Milanesi",
175 "Grant Morgan", "Jan Nieuwenhuizen", "Aredridel Niothke", 
176 "Pablo Roca Rozas", "Sandino Araico Sánchez", "Joel Uckelman", 
177 "Reini Urban", "Tim Voght", "Jochen Kalmbach");
178
179 This file is part of PhpWiki.
180
181 PhpWiki is free software; you can redistribute it and/or modify
182 it under the terms of the GNU General Public License as published by
183 the Free Software Foundation; either version 2 of the License, or
184 (at your option) any later version.
185
186 PhpWiki is distributed in the hope that it will be useful,
187 but WITHOUT ANY WARRANTY; without even the implied warranty of
188 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
189 GNU General Public License for more details.
190
191 You should have received a copy of the GNU General Public License
192 along with PhpWiki; if not, write to the Free Software
193 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
194 ';
195
196
197
198 $preamble = "
199   This is the starting file for PhpWiki. All this file does is set
200   configuration options, and at the end of the file it includes() the
201   file lib/main.php, where the real action begins.
202
203   If you include this file to override the default settings here, 
204   you must also include lib/main.php.
205
206   This file is divided into seven parts: Parts Zero, One, Two, Three,
207   Four, Five and Six. Each one has different configuration settings you can
208   change; in all cases the default should work on your system,
209   however, we recommend you tailor things to your particular setting.
210 ";
211
212
213
214 $properties["Part Zero"] =
215 new part('_part0', false, "
216 Part Zero: If PHP needs help in finding where you installed the
217 rest of the PhpWiki code, you can set the include_path here.");
218
219 if (substr(PHP_OS,0,3) == 'WIN') {
220     $include_path = ini_get('include_path') . ';' . dirname(__FILE__);
221     if (strchr(ini_get('include_path'),'/'))
222         $include_path = strtr($include_path,'\\','/');
223 } else {
224     $include_path = ini_get('include_path') . ':' . dirname(__FILE__);
225 }
226
227 $properties["PHP include_path"] =
228 new _ini_set('include_path', $include_path, "
229 NOTE: phpwiki uses the PEAR library of php code for SQL database
230 access. Your PHP is probably already configured to set
231 include_path so that PHP can find the pear code. If not (or if you
232 change include_path here) make sure you include the path to the
233 PEAR code in include_path. (To find the PEAR code on your system,
234 search for a file named 'PEAR.php'. Some common locations are:
235 <pre>
236   Unixish systems:
237     /usr/share/php
238     /usr/local/share/php
239   Mac OS X:
240     /System/Library/PHP
241 </pre>
242 The above examples are already included by PhpWiki. You shouldn't
243 have to change this unless you see a WikiFatalError:
244 <pre>
245     lib/FileFinder.php:82: Fatal[256]: 
246     DB.php: file not found
247 </pre>
248 Define the include path for this wiki: pear plus the phpwiki path
249 <pre>
250 \$include_path = '.:/Apache/php/pear:/prog/php/phpwiki';
251 </pre>
252 Windows needs ';' as path delimiter. cygwin, mac and unix ':'
253 <pre>
254 if (substr(PHP_OS,0,3) == 'WIN') {
255   \$include_path = implode(';',explode(':',\$include_path));
256 } elseif (substr(PHP_OS,0,6) == 'CYGWIN') {
257   \$include_path = '.:/usr/local/lib/php/pear'.
258                      ':/usr/src/php/phpwiki';
259 } else {
260   ;
261 }</pre>");
262
263 $properties["Part Null"] =
264 new part('_partnullheader', "", "
265 Part Null: Don't touch this!");
266
267
268
269 $properties["Part Null Settings"] =
270 new unchangeable_variable('_partnullsettings', "
271 define ('PHPWIKI_VERSION', '1.3.5pre');
272 require \"lib/prepend.php\";
273 rcs_id('\$Id: configurator.php,v 1.15 2003-03-07 20:51:49 dairiki Exp $');", "");
274
275
276 $properties["Part One"] =
277 new part('_partone', $SEPARATOR."\n", "
278
279 Part One:
280 Authentication and security settings. See Part Three for more.
281 ");
282
283
284
285 $properties["Wiki Name"] =
286 new _define_optional('WIKI_NAME', 'PhpWiki', "
287 The name of your wiki.
288 This is used to generate a keywords meta tag in the HTML templates,
289 in bookmark titles for any bookmarks made to pages in your wiki,
290 and during RSS generation for the title of the RSS channel.");
291
292
293 $properties["Reverse DNS"] =
294 new boolean_define('ENABLE_REVERSE_DNS',
295                     array('true'  => "true. perform additional reverse dns lookups",
296                           'false' => "false. just record the address as given by the httpd server"), "
297 If set, we will perform reverse dns lookups to try to convert the
298 users IP number to a host name, even if the http server didn't do it for us.");
299
300 $properties["Admin Username"] =
301 new _define_optional_notempty('ADMIN_USER', "", "
302 <a name=\"create\">You must set this! Username and password of the administrator.</a>",
303 "onchange=\"validate_ereg('Sorry, ADMIN_USER cannot be empty.', '^.+$', 'ADMIN_USER', this);\"");
304
305 $properties["Admin Password"] =
306 new _define_password_optional('ADMIN_PASSWD', "", "
307 For heaven's sake pick a good password.
308 You can also use our <a target=\"_new\" href=\"passencrypt.php\">passwordencrypter</a> to encrypt an existing password or 
309 the \"Create Password\" button to create a good password.",
310 "onchange=\"validate_ereg('Sorry, ADMIN_PASSWD must be at least 4 chars long.', '^....+$', 'ADMIN_PASSWD', this);\"");
311
312 $properties["Encrypted Password"] = 
313 new boolean_define_optional('ENCRYPTED_PASSWD',
314                     array('true'  => "true. ADMIN_PASSWD is encrypted",
315                           'false' => "false. ADMIN_PASSWD is plaintext. Not recommended!"), "
316 If you used the passencrypt.php utility to encode the password or use an existing unix-crypt password,
317 then set this to true. Recommended!");
318
319 $properties["ZIPdump Authentication"] =
320 new boolean_define_optional('ZIPDUMP_AUTH', 
321                     array('false' => "false. Everyone may download zip dumps",
322                           'true'  => "true. Only admin may download zip dumps"), "
323 If true, only the admin user can make zip dumps, else zip dumps
324 require no authentication.");
325
326 $properties["Enable Plugin RawHtml"] =
327 new boolean_define_optional('ENABLE_RAW_HTML', 
328                     array('false' => "Disabled. Recommended on public sites.",
329                           'true'  => "Enabled"), "
330 Allow &lt; ?plugin RawHtml ...&gt;. Don't do this on a publicly accessable wiki for now.");
331
332 $properties["Strict Mailable Pagedumps"] =
333 new boolean_define('STRICT_MAILABLE_PAGEDUMPS', 
334                     array('false' => "binary",
335                           'true'  => "quoted-printable"), "
336 If you define this to true, (MIME-type) page-dumps (either zip dumps,
337 or \"dumps to directory\" will be encoded using the quoted-printable
338 encoding.  If you're actually thinking of mailing the raw page dumps,
339 then this might be useful, since (among other things,) it ensures
340 that all lines in the message body are under 80 characters in length.
341
342 Also, setting this will cause a few additional mail headers
343 to be generated, so that the resulting dumps are valid
344 RFC 2822 e-mail messages.
345
346 Probably, you can just leave this set to false, in which case you get
347 raw ('binary' content-encoding) page dumps.");
348
349
350
351 $properties["HTML Dump Filename Suffix"] =
352 new _variable('HTML_DUMP_SUFFIX', ".html", "
353 Here you can change the filename suffix used for XHTML page dumps.
354 If you don't want any suffix just comment this out.");
355
356
357
358 $properties["Maximum Upload Size"] =
359 new numeric_define('MAX_UPLOAD_SIZE', "16 * 1024 * 1024", "
360 The maximum file upload size.");
361
362
363
364 $properties["Minor Edit Timeout"] =
365 new numeric_define('MINOR_EDIT_TIMEOUT', "7 * 24 * 3600", "
366 If the last edit is older than MINOR_EDIT_TIMEOUT seconds, the
367 default state for the \"minor edit\" checkbox on the edit page form
368 will be off.");
369
370
371
372 $properties["Disabled Actions"] =
373 new array_variable('DisabledActions', array(), "
374 Actions listed in this array will not be allowed. Actions are:
375 browse, create, diff, dumphtml, dumpserial, edit, loadfile, lock, remove, 
376 unlock, upload, viewsource, zip, ziphtml");
377
378 $properties["Access Log"] =
379 new _define_commented('ACCESS_LOG', "/var/logs/wiki_access.log", "
380 PhpWiki can generate an access_log (in \"NCSA combined log\" format)
381 for you. If you want one, define this to the name of the log file,
382 such as /tmp/wiki_access_log.");
383
384 $properties["Compress Output"] =
385 new boolean_define_commented_optional
386 ( 'COMPRESS_OUTPUT', 
387   array(''  => 'Compress when PhpWiki thinks approriate.',
388         'false' => 'Never compress output.',
389         'true' => 'Always try to compress output.'),
390   "
391 By default PhpWiki will try to have PHP compress it's output
392 before sending it to the browser (if you have a recent enough
393 version of PHP and the browser supports it.
394
395 Define COMPRESS_OUTPUT to false to prevent output compression.
396
397 Define COMPRESS_OUTPUT to true to force output compression,
398 even if we think your version of PHP does this in a buggy
399 fashion.
400
401 Leave it undefined to leave the choice up to PhpWiki.");
402
403 $properties["HTTP Cache Control"] =
404 new _define_selection_optional
405 ('CACHE_CONTROL',
406  array('LOOSE' => 'LOOSE',
407        'STRICT' => 'STRICT',
408        'NONE' => 'NONE',
409        'ALLOW_STALE' => 'ALLOW_STALE'),
410  "
411 HTTP CACHE_CONTROL
412
413 This controls how PhpWiki sets the HTTP cache control
414 headers (Expires: and Cache-Control:) 
415
416 Choose one of:
417
418 <dl>
419 <dt>NONE</dt>
420 <dd>This is roughly the old (pre 1.3.4) behavior.  PhpWiki will
421     instruct proxies and browsers never to cache PhpWiki output.</dd>
422
423 <dt>STRICT</dt>
424 <dd>Cached pages will be invalidated whenever the database global
425     timestamp changes.  This should behave just like NONE (modulo
426     bugs in PhpWiki and your proxies and browsers), except that
427     things will be slightly more efficient.</dd>
428
429 <dt>LOOSE</dt>
430 <dd>Cached pages will be invalidated whenever they are edited,
431     or, if the pages include plugins, when the plugin output could
432     concievably have changed.
433
434     <p>Behavior should be much like STRICT, except that sometimes
435        wikilinks will show up as undefined (with the question mark)
436        when in fact they refer to (recently) created pages.
437        (Hitting your browsers reload or perhaps shift-reload button
438        should fix the problem.)</p></dd>
439
440 <dt>ALLOW_STALE</dt>
441 <dd>Proxies and browsers will be allowed to used stale pages.
442     (The timeout for stale pages is controlled by CACHE_CONTROL_MAX_AGE.)
443
444     <p>This setting will result in quirky behavior.  When you edit a
445        page your changes may not show up until you shift-reload the
446        page, etc...</p>
447
448     <p>This setting is generally not advisable, however it may be useful
449        in certain cases (e.g. if your wiki gets lots of page views,
450        and few edits by knowledgable people who won't freak over the quirks.)</p>
451 </dd>
452
453 The default is currently LOOSE.");
454
455 $properties["HTTP Cache Control Max Age"] =
456 new numeric_define('CACHE_CONTROL_MAX_AGE', 600,
457             "
458 Maximum page staleness, in seconds.");
459
460 $properties["Markup Caching"] =
461 new boolean_define_commented_optional
462 ('WIKIDB_NOCACHE_MARKUP',
463  array('false' => 'Enable markup cache',
464        'true' => 'Disable markup cache'),
465  "
466 MARKUP CACHING
467
468 PhpWiki normally caches a preparsed version (i.e. mostly
469 converted to HTML) of the most recent version of each page.
470 (Parsing the wiki-markup takes a fair amount of CPU.)
471
472 Define WIKIDB_NOCACHE_MARKUP to true to disable the
473 caching of marked-up page content.
474
475 Note that you can also disable markup caching on a per-page
476 temporary basis by addinging a query arg of '?nocache=1'
477 to the URL to the page.  (Use '?nocache=purge' to completely
478 discard the cached version of the page.)
479
480 You can also purge the cached markup globally by using the
481 \"Purge Markup Cache\" button on the PhpWikiAdministration page.");
482
483
484 $properties["Path for PHP Session Support"] =
485 new _ini_set('session.save_path', '/tmp', "
486 The login code now uses PHP's session support. Usually, the default
487 configuration of PHP is to store the session state information in
488 /tmp. That probably will work fine, but fails e.g. on clustered
489 servers where each server has their own distinct /tmp (this is the
490 case on SourceForge's project web server.) You can specify an
491 alternate directory in which to store state information like so
492 (whatever user your httpd runs as must have read/write permission
493 in this directory):");
494
495
496
497 $properties["Disable PHP Transparent Session ID"] =
498 new unchangeable_ini_set('session.use_trans_sid', "@ini_set('session.use_trans_sid', 0);", "
499 If your php was compiled with --enable-trans-sid it tries to
500 add a PHPSESSID query argument to all URL strings when cookie
501 support isn't detected in the client browser.  For reasons
502 which aren't entirely clear (PHP bug) this screws up the URLs
503 generated by PhpWiki.  Therefore, transparent session ids
504 should be disabled.  This next line does that.
505
506 (At the present time, you will not be able to log-in to PhpWiki,
507 or set any user preferences, unless your browser supports cookies.)");
508
509
510
511 ///////// database selection
512
513
514 $properties["Part Two"] =
515 new part('_parttwo', $SEPARATOR."\n", "
516
517 Part Two:
518 Database Selection
519 ");
520
521
522 $properties["Database Type"] =
523 new _variable_selection("DBParams|dbtype",
524               array('dba'   => "dba DBM",
525                     'SQL'   => "SQL PEAR",
526                     'ADODB' => "SQL ADODB",
527                     'cvs'   => "CVS File handler"), "
528 Select the database backend type:
529 Choose ADODB or SQL to use an SQL database with ADODB or PEAR.
530 Choose dba to use one of the standard UNIX dbm libraries.
531 CVS is not yet tested nor supported.
532 Recommended is SQL PEAR.");
533
534 $properties["Filename / Table name Prefix"] =
535 new _variable_commented("DBParams|prefix", "phpwiki_", "
536 Used by all DB types:
537
538 Prefix for filenames or table names
539
540 Currently you MUST EDIT THE SQL file too (in the schemas/
541 directory because we aren't doing on the fly sql generation
542 during the installation.");
543
544
545 $properties["SQL dsn Setup"] =
546 new unchangeable_variable('_sqldsnstuff', "", "
547 For SQL based backends, specify the database as a DSN
548 The most general form of a DSN looks like:
549 <pre>
550   phptype(dbsyntax)://username:password@protocol+hostspec/database
551 </pre>
552 For a MySQL database, the following should work:
553 <pre>
554    mysql://user:password@host/databasename
555 </pre>
556 To connect over a unix socket, use something like
557 <pre>
558    mysql://user:password@unix(/path/to/socket)/databasename
559 </pre>
560 <pre>'dsn' => 'mysql://guest@:/var/lib/mysql/mysql.sock/test',
561 'dsn' => 'mysql://guest@localhost/test',
562 'dsn' => 'pgsql://localhost/test',</pre>");
563
564 // Choose ADODB or SQL to use an SQL database with ADODB or PEAR.
565 // Choose dba to use one of the standard UNIX dbm libraries.
566
567 $properties["SQL Type"] =
568 new _variable_selection('_dsn_sqltype',
569               array('mysql' => "MySQL",
570                     'pgsql' => "PostgreSQL"), "
571 SQL DB types");
572
573
574
575 $properties["SQL User"] =
576 new _variable('_dsn_sqluser', "wikiuser", "
577 SQL User Id:");
578
579
580
581 $properties["SQL Password"] =
582 new _variable('_dsn_sqlpass', "", "
583 SQL Password:");
584
585
586
587 $properties["SQL Database Host"] =
588 new _variable('_dsn_sqlhostorsock', "localhost", "
589 SQL Database Hostname:
590
591 To connect over a local named socket, use something like
592 <pre>
593   unix(/var/lib/mysql/mysql.sock)
594 </pre>
595 here.");
596
597
598
599 $properties["SQL Database Name"] =
600 new _variable('_dsn_sqldbname', "phpwiki", "
601 SQL Database Name:");
602
603 list($dsn_sqltype,) = $properties["SQL Type"]->value();
604 $dsn_sqluser = $properties["SQL User"]->value();
605 $dsn_sqlpass = $properties["SQL Password"]->value();
606 $dsn_sqlhostorsock = $properties["SQL Database Host"]->value();
607 $dsn_sqldbname = $properties["SQL Database Name"]->value();
608
609 $properties["SQL dsn"] =
610 new unchangeable_variable("DBParams['dsn']", 
611   "\$DBParams['dsn'] = \"\$_dsn_sqltype://{$dsn_sqluser}:{$dsn_sqlpass}@{$dsn_sqlhostorsock}/{$dsn_sqldbname}\";", "");
612
613 $properties["dba directory"] =
614 new _variable("DBParams|directory", "/tmp", "
615 dba directory:");
616
617
618 $properties["dba handler"] =
619 new _variable_selection('DBParams|dba_handler',
620               array('gdbm' => "Gdbm - GNU database manager",
621                     'dbm'  => "DBM - Redhat default. On sf.net there's dbm and gdbm",
622                     'db2'  => "DB2 - Sleepycat Software's DB2",
623                     'db3'  => "DB3 - Sleepycat Software's DB3. Fine on Windows but not on every Linux"), "
624 Use 'gdbm', 'dbm', 'db2' or 'db3' depending on your DBA handler methods supported:");
625
626 $properties["dba timeout"] =
627 new _variable("DBParams|timeout", "20", "
628 Recommended values are 20 or 5.");
629
630
631
632 ///////////////////
633
634
635
636 $properties["Page Revisions"] =
637 new unchangeable_variable('_parttworevisions', "", "
638
639 The next section controls how many old revisions of each page are
640 kept in the database.
641
642 There are two basic classes of revisions: major and minor. Which
643 class a revision belongs in is determined by whether the author
644 checked the \"this is a minor revision\" checkbox when they saved the
645 page.
646  
647 There is, additionally, a third class of revisions: author
648 revisions. The most recent non-mergable revision from each distinct
649 author is and author revision.
650
651 The expiry parameters for each of those three classes of revisions
652 can be adjusted seperately. For each class there are five
653 parameters (usually, only two or three of the five are actually
654 set) which control how long those revisions are kept in the
655 database.
656 <dl>
657    <dt>max_keep:</dt> <dd>If set, this specifies an absolute maximum for the
658             number of archived revisions of that class. This is
659             meant to be used as a safety cap when a non-zero
660             min_age is specified. It should be set relatively high,
661             and it's purpose is to prevent malicious or accidental
662             database overflow due to someone causing an
663             unreasonable number of edits in a short period of time.</dd>
664
665   <dt>min_age:</dt>  <dd>Revisions younger than this (based upon the supplanted
666             date) will be kept unless max_keep is exceeded. The age
667             should be specified in days. It should be a
668             non-negative, real number,</dd>
669
670   <dt>min_keep:</dt> <dd>At least this many revisions will be kept.</dd>
671
672   <dt>keep:</dt>     <dd>No more than this many revisions will be kept.</dd>
673
674   <dt>max_age:</dt>  <dd>No revision older than this age will be kept.</dd>
675 </dl>
676 Supplanted date: Revisions are timestamped at the instant that they
677 cease being the current revision. Revision age is computed using
678 this timestamp, not the edit time of the page.
679
680 Merging: When a minor revision is deleted, if the preceding
681 revision is by the same author, the minor revision is merged with
682 the preceding revision before it is deleted. Essentially: this
683 replaces the content (and supplanted timestamp) of the previous
684 revision with the content after the merged minor edit, the rest of
685 the page metadata for the preceding version (summary, mtime, ...)
686 is not changed.
687 ");
688
689
690 // For now the expiration parameters are statically inserted as
691 // an unchangeable property. You'll have to edit the resulting
692 // config file if you really want to change these from the default.
693
694 $properties["Expiration Parameters for Major Edits"] =
695 new unchangeable_variable('ExpireParams|major',
696 "\$ExpireParams['major'] = array('max_age' => 32,
697                                'keep'    => 8);", "
698 Keep up to 8 major edits, but keep them no longer than a month.");
699
700 $properties["Expiration Parameters for Minor Edits"] =
701 new unchangeable_variable('ExpireParams|minor',
702 "\$ExpireParams['minor'] = array('max_age' => 7,
703                                'keep'    => 4);", "
704 Keep up to 4 minor edits, but keep them no longer than a week.");
705
706
707
708 $properties["Expiration Parameters by Author"] =
709 new unchangeable_variable('ExpireParams|author',
710 "\$ExpireParams['author'] = array('max_age'  => 365,
711                                 'keep'     => 8,
712                                 'min_age'  => 7,
713                                 'max_keep' => 20);", "
714 Keep the latest contributions of the last 8 authors up to a year.
715 Additionally, (in the case of a particularly active page) try to
716 keep the latest contributions of all authors in the last week (even
717 if there are more than eight of them,) but in no case keep more
718 than twenty unique author revisions.");
719
720 /////////////////////////////////////////////////////////////////////
721
722 $properties["Part Three"] =
723 new part('_partthree', $SEPARATOR."\n", "
724
725 Part Three: (optional)
726 User Authentication
727 ");
728
729 $properties["User Authentication"] =
730 new boolean_define_optional('ALLOW_USER_LOGIN',
731                     array('true'  => "true. Check any defined passwords. (Default)",
732                           'false' => "false. Don't check passwords. Legacy &lt; 1.3.4"), "
733 If ALLOW_USER_LOGIN is true, any defined internal and external
734 authentication method is tried. 
735 If not, we don't care about passwords, but check the next two constants.");
736
737 $properties["HTTP Authentication"] =
738 new boolean_define_optional('ALLOW_HTTP_AUTH_LOGIN',
739                     array('false' => "false. Ignore HTTP Authentication. (Default)",
740                           'true'  => "true. Allow .htpasswd users login automatically."), "
741 The wiki can be optionally be protected by HTTP Auth. Use the username and password 
742 from there, and if this fails, try the other methods also.");
743
744 $properties["Strict Login"] =
745 new boolean_define_optional('ALLOW_BOGO_LOGIN',
746                     array('true'  => "Users may Sign In with any WikiWord",
747                           'false' => "Only admin may Sign In"), "
748 If ALLOW_BOGO_LOGIN is true, users are allowed to login (with
749 any/no password) using any userid which: 1) is not the ADMIN_USER,
750 2) is a valid WikiWord (matches \$WikiNameRegexp.)
751 If true, users may be created by themselves. Otherwise we need seperate auth. 
752 This might be renamed to ALLOW_SELF_REGISTRATION");
753
754 $properties["Require Sign In Before Editing"] =
755 new boolean_define_optional('REQUIRE_SIGNIN_BEFORE_EDIT',
756                     array('false' => "Do not require Sign In",
757                           'true'  => "Require Sign In"), "
758 If set, then if an anonymous user attempts to edit a page he will
759 be required to sign in.  (If ALLOW_BOGO_LOGIN is true, of course,
760 no password is required, but the user must still sign in under
761 some sort of BogoUserId.)");
762
763 if (function_exists('ldap_connect')) {
764 $properties["LDAP Authentication"] =
765   new boolean_define_optional('ALLOW_LDAP_LOGIN',
766                     array('true'  => "Allow LDAP Authentication",
767                           'false' => "Ignore LDAP"), "
768 LDAP Authentication
769 ");
770 $properties["LDAP Host"] =
771   new _define_optional('LDAP_AUTH_HOST', "localhost", "");
772 $properties["LDAP Root Search"] =
773   new _define_optional('LDAP_AUTH_SEARCH', "ou=mycompany.com,o=My Company", "
774 Give the right LDAP root search information in the next statement.");
775
776 } else {
777
778 $properties["LDAP Authentication"] =
779 new unchangeable_define('ALLOW_LDAP_LOGIN', "
780 if (!defined('ALLOW_LDAP_LOGIN')) define('ALLOW_LDAP_LOGIN', true and function_exists('ldap_connect'));
781 if (!defined('LDAP_AUTH_HOST'))   define('LDAP_AUTH_HOST', 'localhost');
782 // Give the right LDAP root search information in the next statement. 
783 if (!defined('LDAP_AUTH_SEARCH')) define('LDAP_AUTH_SEARCH', 'ou=mycompany.com,o=My Company');
784 ", "
785 Ignored. No LDAP support in this php. configure --with-ldap");
786 }
787
788 if (function_exists('imap_open')) {
789 $properties["IMAP Authentication"] =
790   new boolean_define_optional('ALLOW_IMAP_LOGIN',
791                     array('true'  => "Allow IMAP Authentication",
792                           'false' => "Ignore IMAP"), "
793 IMAP Authentication
794 ");
795 $properties["IMAP Host"] =
796   new _define_optional('IMAP_AUTH_HOST', 'localhost', '');
797 } else {
798 $properties["IMAP Authentication"] =
799   new unchangeable_define('ALLOW_IMAP_LOGIN',"
800 // IMAP auth: check userid/passwords from a imap server, defaults to localhost
801 if (!defined('ALLOW_IMAP_LOGIN')) define('ALLOW_IMAP_LOGIN', true and function_exists('imap_open'));
802 if (!defined('IMAP_AUTH_HOST'))   define('IMAP_AUTH_HOST', 'localhost');
803 ", "Ignored. No IMAP support in this php. configure --with-imap");
804 }
805
806
807 /////////////////////////////////////////////////////////////////////
808
809 $properties["Part Four"] =
810 new part('_partfour', $SEPARATOR."\n", "
811
812 Part Four:
813 Page appearance and layout
814 ");
815
816
817
818 $properties["Theme"] =
819 new _define_selection_optional('THEME',
820               array('default'  => "default",
821                     'Hawaiian' => "Hawaiian",
822                     'MacOSX'   => "MacOSX",
823                     'Portland' => "Portland",
824                     'Sidebar'  => "Sidebar",
825                     'SpaceWiki' => "SpaceWiki"), "
826 THEME
827
828 Most of the page appearance is controlled by files in the theme
829 subdirectory.
830
831 There are a number of pre-defined themes shipped with PhpWiki.
832 Or you may create your own (e.g. by copying and then modifying one of
833 stock themes.)
834
835 Pick one.
836 <pre>
837 define('THEME', 'default');
838 define('THEME', 'Hawaiian');
839 define('THEME', 'MacOSX');
840 define('THEME', 'Portland');
841 define('THEME', 'Sidebar');
842 define('THEME', 'SpaceWiki');</pre>");
843
844
845
846 $properties["Character Set"] =
847 new _define_optional('CHARSET', 'iso-8859-1', "
848 Select a valid charset name to be inserted into the xml/html pages, 
849 and to reference links to the stylesheets (css). For more info see: 
850 http://www.iana.org/assignments/character-sets. Note that PhpWiki 
851 has been extensively tested only with the latin1 (iso-8859-1) 
852 character set.
853
854 If you change the default from iso-8859-1 PhpWiki may not work 
855 properly and it will require code modifications. However, character 
856 sets similar to iso-8859-1 may work with little or no modification 
857 depending on your setup. The database must also support the same 
858 charset, and of course the same is true for the web browser. (Some 
859 work is in progress hopefully to allow more flexibility in this 
860 area in the future).");
861
862
863
864 $properties["Language"] =
865 new _variable_selection_optional('LANG',
866               array('en' => "English",
867                     'nl' => "Nederlands",
868                     'es' => "Español",
869                     'fr' => "Français",
870                     'de' => "Deutsch",
871                     'sv' => "Svenska",
872                     'it' => "Italiano",
873                     ''   => "none"), "
874 Select your language/locale - default language is \"en\" for English.
875 Other languages available:<pre>
876 English \"en\"  (English    - HomePage)
877 Dutch   \"nl\" (Nederlands - ThuisPagina)
878 Spanish \"es\" (Español    - PáginaPrincipal)
879 French  \"fr\" (Français   - Accueil)
880 German  \"de\" (Deutsch    - StartSeite)
881 Swedish \"sv\" (Svenska    - Framsida)
882 Italian \"it\" (Italiano   - PaginaPrincipale)
883 </pre>
884 If you set \$LANG to the empty string, your systems default language
885 (as determined by the applicable environment variables) will be
886 used.");
887
888 $properties["Language Locales"] =
889 new unchangeable_variable('language_locales',
890 "\$language_locales = array('en' => 'C',
891                             'de' => 'de_DE',
892                             'es' => 'es_MX',
893                             'nl' => 'nl_NL',
894                             'fr' => 'fr_FR',
895                             'it' => 'it_IT',
896                             'sv' => 'sv_SV'
897                             );
898 if (empty(\$LC_ALL)) {
899   if (empty(\$language_locales[\$LANG]))
900      \$LC_ALL = \$LANG;
901   else
902      \$LC_ALL = \$language_locales[\$LANG];
903 }
904 putenv(\"LC_TIME=\$LC_ALL\");
905 ", "
906 Setting the LANG environment variable (accomplished above) may or
907 may not be sufficient to cause PhpWiki to produce dates in your
908 native language. (It depends on the configuration of the operating
909 system on your http server.)  The problem is that, e.g. 'de' is
910 often not a valid locale.
911
912 A standard locale name is typically of  the  form
913 language[_territory][.codeset][@modifier],  where  language is
914 an ISO 639 language code, territory is an ISO 3166 country code,
915 and codeset  is  a  character  set or encoding identifier like
916 ISO-8859-1 or UTF-8.
917
918 You can tailor the locale used for time and date formatting by
919 setting the LC_TIME environment variable. You'll have to experiment
920 to find the correct setting.
921 gettext() fix: With setlocale() we must use the long form, 
922 like 'de_DE','nl_NL', 'es_MX', 'es_AR', 'fr_FR'. 
923 For Windows maybe even 'german'. You might fix this accordingly.");
924
925 $properties["Wiki Page Source"] =
926 new _define_optional('WIKI_PGSRC', 'pgsrc', "
927 WIKI_PGSRC -- specifies the source for the initial page contents of
928 the Wiki. The setting of WIKI_PGSRC only has effect when the wiki is
929 accessed for the first time (or after clearing the database.)
930 WIKI_PGSRC can either name a directory or a zip file. In either case
931 WIKI_PGSRC is scanned for files -- one file per page.
932 <pre>
933 // Default (old) behavior:
934 define('WIKI_PGSRC', 'pgsrc'); 
935 // New style:
936 define('WIKI_PGSRC', 'wiki.zip'); 
937 define('WIKI_PGSRC', 
938        '../Logs/Hamwiki/hamwiki-20010830.zip'); 
939 </pre>");
940
941
942
943 $properties["Default Wiki Page Source"] =
944 new _define('DEFAULT_WIKI_PGSRC', 'pgsrc', "
945 DEFAULT_WIKI_PGSRC is only used when the language is *not* the
946 default (English) and when reading from a directory: in that case
947 some English pages are inserted into the wiki as well.
948 DEFAULT_WIKI_PGSRC defines where the English pages reside.
949
950 FIXME: is this really needed?
951 ");
952
953
954
955 $properties["Generic Pages"] =
956 new array_variable('GenericPages', array('ReleaseNotes', 'SteveWainstead', 'TestPage'), "
957 These are the pages which will get loaded from DEFAULT_WIKI_PGSRC.      
958
959 FIXME: is this really needed?  Can't we just copy these pages into
960 the localized pgsrc?
961 ");
962
963
964
965
966 $properties["Part Five"] =
967 new part('_partfive', $SEPARATOR."\n", "
968
969 Part Five:
970 Mark-up options.
971 ");
972
973
974
975 $properties["Allowed Protocols"] =
976 new list_variable('AllowedProtocols', 'http|https|mailto|ftp|news|nntp|ssh|gopher', "
977 allowed protocols for links - be careful not to allow \"javascript:\"
978 URL of these types will be automatically linked.
979 within a named link [name|uri] one more protocol is defined: phpwiki");
980
981
982
983 $properties["Inline Images"] =
984 new list_variable('InlineImages', 'png|jpg|gif', "
985 URLs ending with the following extension should be inlined as images");
986
987
988
989 $properties["WikiName Regexp"] =
990 new _variable('WikiNameRegexp', "(?<![[:alnum:]])(?:[[:upper:]][[:lower:]]+){2,}(?![[:alnum:]])", "
991 Perl regexp for WikiNames (\"bumpy words\")
992 (?&lt;!..) &amp; (?!...) used instead of '\b' because \b matches '_' as well");
993
994 $properties["Subpage Separator"] =
995 new _define_optional('SUBPAGE_SEPARATOR', '/', "
996 One character which seperates pages from subpages. Defaults to '/', but '.' or ':' were also used.",
997 "onchange=\"validate_ereg('Sorry, \'%s\' must be a single character. Currently only :, / or .', '^[/:.]$', 'SUBPAGE_SEPARATOR', this);\""
998 );
999
1000 $properties["InterWiki Map File"] =
1001 new _define('INTERWIKI_MAP_FILE', 'lib/interwiki.map', "
1002 InterWiki linking -- wiki-style links to other wikis on the web
1003
1004 The map will be taken from a page name InterWikiMap.
1005 If that page is not found (or is not locked), or map
1006 data can not be found in it, then the file specified
1007 by INTERWIKI_MAP_FILE (if any) will be used.");
1008
1009 $properties["WARN_NONPUBLIC_INTERWIKIMAP"] =
1010 new boolean_define('WARN_NONPUBLIC_INTERWIKIMAP',   
1011         array('true'  => "true",
1012                           'false' => "false"), "
1013 Display a warning if the internal lib/interwiki.map is used, and 
1014 not the public InterWikiMap page. This map is not readable from outside.");
1015
1016 $properties["Keyword Link Regexp"] =
1017 new _variable('KeywordLinkRegexp',
1018               '(?<=^Category|^Topic)[[:upper:]].*$',
1019               "
1020 Regexp used for automatic keyword extraction.
1021
1022 Any links on a page to pages whose names match this regexp will
1023 be used keywords in the keywords meta tag.  (This is an aid to
1024 classification by search engines.)  The value of the match is
1025 used as the keyword.
1026
1027 The default behavior is to match Category* and Topic* links.");
1028
1029 $properties["Part Six"] =
1030 new part('_partsix', $SEPARATOR."\n", "
1031
1032 Part Six (optional):
1033 URL options -- you can probably skip this section.
1034 ");
1035
1036 $properties["Server Name"] =
1037 new _define_commented_optional('SERVER_NAME', $HTTP_SERVER_VARS['SERVER_NAME'], "
1038 Canonical name and httpd port of the server on which this PhpWiki
1039 resides.");
1040
1041
1042
1043 $properties["Server Port"] =
1044 new numeric_define_commented('SERVER_PORT', $HTTP_SERVER_VARS['SERVER_PORT'], "",
1045 "onchange=\"validate_ereg('Sorry, \'%s\' is no valid port number.', '^[0-9]+$', 'SERVER_PORT', this);\"");
1046
1047 $scriptname = preg_replace('/configurator.php/','index.php',$HTTP_SERVER_VARS["SCRIPT_NAME"]);
1048
1049 $properties["Script Name"] =
1050 new _define_commented_optional('SCRIPT_NAME', $scriptname, "
1051 Relative URL (from the server root) of the PhpWiki script.");
1052
1053 $properties["Data Path"] =
1054 new _define_commented_optional('DATA_PATH', dirname($scriptname), "
1055 URL of the PhpWiki install directory.  (You only need to set this
1056 if you've moved index.php out of the install directory.)  This can
1057 be either a relative URL (from the directory where the top-level
1058 PhpWiki script is) or an absolute one.");
1059
1060
1061
1062 $properties["PhpWiki Install Directory"] =
1063 new _define_commented_optional('PHPWIKI_DIR', dirname(__FILE__), "
1064 Path to the PhpWiki install directory.  This is the local
1065 filesystem counterpart to DATA_PATH.  (If you have to set
1066 DATA_PATH, your probably have to set this as well.)  This can be
1067 either an absolute path, or a relative path interpreted from the
1068 directory where the top-level PhpWiki script (normally index.php)
1069 resides.");
1070
1071
1072
1073 $properties["Use PATH_INFO"] =
1074 new boolean_define_commented_optional('USE_PATH_INFO', 
1075                     array('true'  => 'use PATH_INFO',
1076                           'false' => 'do not use PATH_INFO'), "
1077 Define to 'true' to use PATH_INFO to pass the pagenames.
1078 e.g. http://www.some.where/index.php/HomePage instead
1079 of http://www.some.where/index.php?pagename=HomePage
1080 FIXME: more docs (maybe in README). Default: true");
1081
1082
1083
1084 $properties["Virtual Path"] =
1085 new _define_commented_optional('VIRTUAL_PATH', '/SomeWiki', "
1086 VIRTUAL_PATH is the canonical URL path under which your your wiki
1087 appears. Normally this is the same as dirname(SCRIPT_NAME), however
1088 using, e.g. apaches mod_actions (or mod_rewrite), you can make it
1089 something different.
1090
1091 If you do this, you should set VIRTUAL_PATH here.
1092
1093 E.g. your phpwiki might be installed at at /scripts/phpwiki/index.php,
1094 but you've made it accessible through eg. /wiki/HomePage.
1095
1096 One way to do this is to create a directory named 'wiki' in your
1097 server root. The directory contains only one file: an .htaccess
1098 file which reads something like:
1099 <pre>
1100     Action x-phpwiki-page /scripts/phpwiki/index.php
1101     SetHandler x-phpwiki-page
1102     DirectoryIndex /scripts/phpwiki/index.php
1103 </pre>
1104 In that case you should set VIRTUAL_PATH to '/wiki'.
1105
1106 (VIRTUAL_PATH is only used if USE_PATH_INFO is true.)
1107 ");
1108
1109
1110 $properties["Part Seven"] =
1111 new part('_partseven', $SEPARATOR."\n", "
1112
1113 Part Seven:
1114
1115 Miscellaneous settings
1116 ");
1117
1118 $properties["Pagename of Recent Changes"] =
1119 new _define_optional('RECENT_CHANGES', 'RecentChanges', "
1120 Page name of RecentChanges page.  Used for RSS Auto-discovery.");
1121
1122 $properties["Disable HTTP Redirects"] =
1123 new boolean_define_commented_optional
1124 ('DISABLE_HTTP_REDIRECT',
1125  array('false' => 'Enable HTTP Redirects',
1126        'true' => 'Disable HTTP Redirects'),
1127 "
1128 (You probably don't need to touch this.)
1129
1130 PhpWiki uses HTTP redirects for some of it's functionality.
1131 (e.g. after saving changes, PhpWiki redirects your browser to
1132 view the page you just saved.)
1133
1134 Some web service providers (notably free European Lycos) don't seem to
1135 allow these redirects.  (On Lycos the result in an \"Internal Server Error\"
1136 report.)  In that case you can set DISABLE_HTTP_REDIRECT to true.
1137 (In which case, PhpWiki will revert to sneakier tricks to try to
1138 redirect the browser...)");
1139
1140 $end = "
1141
1142 $SEPARATOR
1143 // Check if we were included by some other wiki version (getimg, en, ...) 
1144 // or not. 
1145 // If the server requested this index.php fire up the code by loading lib/main.php.
1146 // Parallel wiki scripts can now simply include /index.php for the 
1147 // main configuration, extend or redefine some settings and 
1148 // load lib/main.php by themselves. 
1149 // This overcomes the index as config problem.
1150 $SEPARATOR
1151
1152 // This doesn't work with php as CGI yet!
1153 if (defined('VIRTUAL_PATH') and defined('USE_PATH_INFO')) {
1154     if (\$HTTP_SERVER_VARS['SCRIPT_NAME'] == VIRTUAL_PATH) {
1155         include \"lib/main.php\";
1156     }
1157 } else {
1158     if (defined('SCRIPT_NAME') and 
1159         (\$HTTP_SERVER_VARS['SCRIPT_NAME'] == SCRIPT_NAME)) {
1160         include \"lib/main.php\";
1161     } elseif (strstr(\$HTTP_SERVER_VARS['PHP_SELF'],'index.php')) {
1162         include \"lib/main.php\";
1163     }
1164 }
1165
1166 // (c-file-style: \"gnu\")
1167 // Local Variables:
1168 // mode: php
1169 // tab-width: 8
1170 // c-basic-offset: 4
1171 // c-hanging-comment-ender-p: nil
1172 // indent-tabs-mode: nil
1173 // End:   
1174 ?>
1175 ";
1176
1177
1178
1179 // end of configuration options
1180 ///////////////////////////////
1181 // begin class definitions
1182
1183 /**
1184  * A basic index.php configuration line in the form of a variable.
1185  *
1186  * Produces a string in the form "$name = value;"
1187  * e.g.:
1188  * $WikiNameRegexp = "value";
1189  */
1190 class _variable {
1191
1192     var $config_item_name;
1193     var $default_value;
1194     var $description;
1195     var $prefix;
1196     var $jscheck;
1197
1198     function _variable($config_item_name, $default_value, $description, $jscheck = '') {
1199         $this->config_item_name = $config_item_name;
1200         $this->description = $description;
1201         $this->default_value = $default_value;
1202         $this->jscheck = $jscheck;
1203         if (preg_match("/variable/i",get_class($this)))
1204             $this->prefix = "\$";
1205         elseif (preg_match("/ini_set/i",get_class($this)))
1206             $this->prefix = "ini_get: ";
1207         else
1208             $this->prefix = "";
1209     }
1210
1211     function value() {
1212       global $HTTP_POST_VARS;
1213       if (isset($HTTP_POST_VARS[$this->config_item_name]))
1214           return $HTTP_POST_VARS[$this->config_item_name];
1215       else 
1216           return $this->default_value;
1217     }
1218
1219     function _config_format($value) {
1220         $v = $this->get_config_item_name();
1221         // handle arrays: a|b --> a['b']
1222         if (strpos($v, '|')) {
1223             list($a, $b) = explode('|', $v);
1224             $v = sprintf("%s['%s']", $a, $b);
1225         }
1226         return sprintf("\$%s = \"%s\";", $v, $value);
1227     }
1228
1229     function get_config_item_name() {
1230         return $this->config_item_name;
1231     }
1232
1233     function get_config_item_id() {
1234         return str_replace('|', '-', $this->config_item_name);
1235     }
1236
1237     function get_config_item_header() {
1238        if (strchr($this->config_item_name,'|')) {
1239           list($var,$param) = explode('|',$this->config_item_name);
1240           return "<b>" . $this->prefix . $var . "['" . $param . "']</b><br />";
1241        }
1242        elseif ($this->config_item_name[0] != '_')
1243           return "<b>" . $this->prefix . $this->config_item_name . "</b><br />";
1244        else 
1245           return '';
1246     }
1247
1248     function _get_description() {
1249         return $this->description;
1250     }
1251
1252     function _get_config_line($posted_value) {
1253         return "\n" . $this->_config_format($posted_value);
1254     }
1255
1256     function get_config($posted_value) {
1257         $d = stripHtml($this->_get_description());
1258         $d = str_replace("\n", "\n// ", $d) . $this->_get_config_line($posted_value) ."\n";
1259         return $d;
1260     }
1261
1262     function get_instructions($title) {
1263         global $tdwidth;
1264         $i = "<h3>" . $title . "</h3>\n    " . nl2p($this->_get_description()) . "\n";
1265         return "<tr>\n<td width=\"$tdwidth\" class=\"instructions\">\n" . $i . "</td>\n";
1266     }
1267
1268     function get_html() {
1269         return $this->get_config_item_header() . 
1270             "<input type=\"text\" size=\"50\" name=\"" . $this->get_config_item_name() . "\" value=\"" . htmlspecialchars($this->default_value) . "\" " . 
1271             $this->jscheck . " />" . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1272     }
1273 }
1274
1275 class unchangeable_variable
1276 extends _variable {
1277     function _config_format($value) {
1278         return "";
1279     }
1280     // function get_html() { return false; }
1281     function get_html() {
1282         return $this->get_config_item_header() . 
1283         "<em>Not editable.</em>" . 
1284         "<pre>" . $this->default_value."</pre>";
1285     }
1286     function _get_config_line($posted_value) {
1287         if ($this->description)
1288             $n = "\n";
1289         return "${n}".$this->default_value;
1290     }
1291     function get_instructions($title) {
1292         global $tdwidth;
1293         $i = "<h3>" . $title . "</h3>\n    " . nl2p($this->_get_description()) . "\n";
1294         // $i = $i ."<em>Not editable.</em><br />\n<pre>" . $this->default_value."</pre>";
1295         return "<tr><td width=\"100%\" class=\"unchangeable-variable-top\" colspan=\"2\">\n".$i ."</td></tr>\n".
1296         "<tr style=\"border-top: none;\"><td class=\"unchangeable-variable-left\" width=\"$tdwidth\" bgcolor=\"#eeeeee\">&nbsp;</td>";
1297     }
1298 }
1299
1300 class unchangeable_define
1301 extends unchangeable_variable {
1302     function _config_format($value) {
1303         return "";
1304     }
1305 }
1306 class unchangeable_ini_set
1307 extends unchangeable_variable {
1308     function _config_format($value) {
1309         return "";
1310     }
1311 }
1312
1313
1314 class _variable_selection
1315 extends _variable {
1316     function value() {
1317         global $HTTP_POST_VARS;
1318         if (!empty($HTTP_POST_VARS[$this->config_item_name]))
1319             return $HTTP_POST_VARS[$this->config_item_name];
1320         else {
1321             list($option, $label) = current($this->default_value);
1322             return $this->$option;
1323         }
1324     }
1325     function get_html() {
1326         $output = $this->get_config_item_header();
1327         $output .= '<select name="' . $this->get_config_item_name() . "\">\n";
1328         /* The first option is the default */
1329         while(list($option, $label) = each($this->default_value)) {
1330             $output .= "  <option value=\"$option\">$label</option>\n";
1331         }
1332         $output .= "</select>\n";
1333         return $output;
1334     }
1335 }
1336
1337
1338 class _define
1339 extends _variable {
1340     function _config_format($value) {
1341         return sprintf("define('%s', '%s');", $this->get_config_item_name(), $value);
1342     }
1343     function _get_config_line($posted_value) {
1344         if ($this->description)
1345             $n = "\n";
1346         if ($posted_value == '')
1347             return "${n}//" . $this->_config_format("");
1348         else
1349             return "${n}" . $this->_config_format($posted_value);
1350     }
1351     function get_html() {
1352         return $this->get_config_item_header() . 
1353             "<input type=\"text\" size=\"50\" name=\"" . $this->get_config_item_name() . "\" value=\"" . $this->default_value . "\" {$this->jscheck} />" .
1354             "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1355     }
1356 }
1357
1358 class _define_commented
1359 extends _define {
1360     function _get_config_line($posted_value) {
1361         if ($this->description)
1362             $n = "\n";
1363         if ($posted_value == $this->default_value)
1364             return "${n}//" . $this->_config_format($posted_value);
1365         else if ($posted_value == '')
1366             return "${n}//" . $this->_config_format("");
1367         else
1368             return "${n}" . $this->_config_format($posted_value);
1369     }
1370 }
1371
1372 class _define_commented_optional
1373 extends _define_commented {
1374     function _config_format($value) {
1375         $name = $this->get_config_item_name();
1376         return sprintf("if (!defined('%s')) define('%s', '%s');", $name, $name, $value);
1377     }
1378 }
1379
1380 class _define_optional
1381 extends _define {
1382     function _config_format($value) {
1383         $name = $this->get_config_item_name();
1384         return sprintf("if (!defined('%s')) define('%s', '%s');", $name, $name, $value);
1385     }
1386 }
1387
1388 class _define_optional_notempty
1389 extends _define_optional {
1390     function get_html() {
1391         $s = $this->get_config_item_header() . 
1392             "<input type=\"text\" size=\"50\" name=\"" . $this->get_config_item_name() . "\" value=\"" . $this->default_value . "\" {$this->jscheck} />";
1393         if (empty($this->default_value))
1394             return $s . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Cannot be empty.</p>";
1395         else
1396             return $s . "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1397     }
1398 }
1399
1400 class _variable_commented
1401 extends _variable {
1402     function _get_config_line($posted_value) {
1403         if ($this->description)
1404             $n = "\n";
1405         if ($posted_value == $this->default_value)
1406             return "${n}//" . $this->_config_format($posted_value);
1407         else if ($posted_value == '')
1408             return "${n}//" . $this->_config_format("");
1409         else
1410             return "${n}" . $this->_config_format($posted_value);
1411     }
1412 }
1413
1414 class numeric_define_commented
1415 extends _define {
1416     //    var $jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' is not an integer.', '^[-+]?[0-9]+$', '" . $this->get_config_item_name() . "', this);\"";
1417
1418     function get_html() {
1419         return numeric_define::get_html();
1420     }
1421     function _get_config_line($posted_value) {
1422         if ($this->description)
1423             $n = "\n";
1424         if ($posted_value == $this->default_value)
1425             return "${n}//" . $this->_config_format($posted_value);
1426         else if ($posted_value == '')
1427             return "${n}//" . $this->_config_format('0');
1428         else
1429             return "${n}" . $this->_config_format($posted_value);
1430     }
1431 }
1432
1433 class _define_selection
1434 extends _variable_selection {
1435     function _config_format($value) {
1436         return sprintf("define('%s', '%s');", $this->get_config_item_name(), $value);
1437     }
1438     function _get_config_line($posted_value) {
1439         return _define::_get_config_line($posted_value);
1440     }
1441     function get_html() {
1442         return _variable_selection::get_html();
1443     }
1444 }
1445
1446 class _define_selection_optional
1447 extends _define_selection {
1448     function _config_format($value) {
1449         $name = $this->get_config_item_name();
1450         return sprintf("if (!defined('%s')) define('%s', '%s');", $name, $name, $value);
1451     }
1452 }
1453
1454 class _variable_selection_optional
1455 extends _variable_selection {
1456     function _config_format($value) {
1457         $v = $this->get_config_item_name();
1458         // handle arrays: a|b --> a['b']
1459         if (strpos($v, '|')) {
1460             list($a, $b) = explode('|', $v);
1461             $v = sprintf("%s['%s']", $a, $b);
1462         }
1463         return sprintf("if (!isset(\$%s)) { \$%s = \"%s\"; }", $v, $v, $value);
1464     }
1465 }
1466
1467 class _define_password
1468 extends _define {
1469     //    var $jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' cannot be empty.', '^.+$', '" . $this->get_config_item_name() . "', this);\"";
1470
1471     function _get_config_line($posted_value) {
1472         if ($this->description)
1473             $n = "\n";
1474         if ($posted_value == '') {
1475             $p = "${n}//" . $this->_config_format("");
1476             $p = $p . "\n// If you used the passencrypt.php utility to encode the password";
1477             $p = $p . "\n// then uncomment this line:";
1478             $p = $p . "\n//if (!defined('ENCRYPTED_PASSWD')) define('ENCRYPTED_PASSWD', true);";
1479             return $p;
1480         } else {
1481             if (function_exists('crypt')) {
1482                 $salt_length = max(CRYPT_SALT_LENGTH,
1483                                     2 * CRYPT_STD_DES,
1484                                     9 * CRYPT_EXT_DES,
1485                                    12 * CRYPT_MD5,
1486                                    16 * CRYPT_BLOWFISH);
1487                 // generate an encrypted password
1488                 $crypt_pass = crypt($posted_value, rand_ascii($salt_length));
1489                 $p = "${n}" . $this->_config_format($crypt_pass);
1490                 return $p . "\ndefine('ENCRYPTED_PASSWD', true);";
1491             } else {
1492                 $p = "${n}" . $this->_config_format($posted_value);
1493                 $p = $p . "\n// If you used the passencrypt.php utility to encode the password";
1494                 $p = $p . "\n// then uncomment this line:";
1495                 $p = $p . "\n//define('ENCRYPTED_PASSWD', false);";
1496                 $p = $p . "\n// Encrypted passwords cannot be used:";
1497                 $p = $p . "\n// 'function crypt()' not available in this version of php";
1498                 return $p;
1499             }
1500         }
1501     }
1502     function get_html() {
1503         return _variable_password::get_html();
1504     }
1505 }
1506
1507 class _define_password_optional
1508 extends _define_password {
1509     function _config_format($value) {
1510         $name = $this->get_config_item_name();
1511         return sprintf("if (!defined('%s')) define('%s', '%s');", $name, $name, $value);
1512     }
1513 }
1514
1515
1516 class _variable_password
1517 extends _variable {
1518     //    var $jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' cannot be empty.', '^.+$', '" . $this->get_config_item_name() . "', this);\"";
1519
1520     function get_html() {
1521         global $HTTP_POST_VARS, $HTTP_GET_VARS;
1522         $s = $this->get_config_item_header();
1523         $s .= "<input type=\"password\" name=\"" . $this->get_config_item_name() . "\" value=\"" . $this->default_value . "\" {$this->jscheck} />" . 
1524 "&nbsp;&nbsp;<input type=\"submit\" name=\"create\" value=\"Create Password\" />";
1525         if (isset($HTTP_POST_VARS['create']) or isset($HTTP_GET_VARS['create'])) {
1526             $new_password = random_good_password();
1527             $this->default_value = $new_password;
1528             $s .= "<br />&nbsp;<br />Created password: <strong>$new_password</strong>";
1529         }
1530         if (empty($this->default_value))
1531             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Cannot be empty.</p>";
1532         elseif (strlen($this->default_value) < 4)
1533             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: red\">Must be longer than 4 chars.</p>";
1534         else
1535             $s .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1536         return $s;
1537     }
1538 }
1539
1540 class numeric_define
1541 extends _define {
1542     //    var $jscheck = "onchange=\"validate_ereg('Sorry, \'%s\' is not an integer.', '^[-+]?[0-9]+$', '" . $this->get_config_item_name() . "', this);\"";
1543
1544     function _config_format($value) {
1545         return sprintf("define('%s', %s);", $this->get_config_item_name(), $value);
1546     }
1547     function _get_config_line($posted_value) {
1548         if ($this->description)
1549             $n = "\n";
1550         if ($posted_value == '')
1551             return "${n}//" . $this->_config_format('0');
1552         else
1553             return "${n}" . $this->_config_format($posted_value);
1554     }
1555 }
1556
1557 class list_variable
1558 extends _variable {
1559     function _get_config_line($posted_value) {
1560         // split the phrase by any number of commas or space characters,
1561         // which include " ", \r, \t, \n and \f
1562         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
1563         $list_values = join("|", $list_values);
1564         return _variable::_get_config_line($list_values);
1565     }
1566     function get_html() {
1567         $list_values = explode("|", $this->default_value);
1568         $rows = max(3, count($list_values) +1);
1569         $list_values = join("\n", $list_values);
1570         $ta = $this->get_config_item_header();
1571         $ta .= "<textarea cols=\"18\" rows=\"". $rows ."\" name=\"".$this->get_config_item_name()."\" {$this->jscheck}>";
1572         $ta .= $list_values . "</textarea>";
1573         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1574         return $ta;
1575     }
1576 }
1577
1578 class array_variable
1579 extends _variable {
1580     function _config_format($value) {
1581         return sprintf("\$%s = array(%s);", $this->get_config_item_name(), $value);
1582     }
1583     function _get_config_line($posted_value) {
1584         // split the phrase by any number of commas or space characters,
1585         // which include " ", \r, \t, \n and \f
1586         $list_values = preg_split("/[\s,]+/", $posted_value, -1, PREG_SPLIT_NO_EMPTY);
1587         if (!empty($list_values)) {
1588             $list_values = "'".join("', '", $list_values)."'";
1589             return "\n" . $this->_config_format($list_values);
1590         } else
1591             return "\n//" . $this->_config_format('');
1592     }
1593     function get_html() {
1594         $list_values = join("\n", $this->default_value);
1595         $rows = max(3, count($this->default_value) +1);
1596         $ta = $this->get_config_item_header();
1597         $ta .= "<textarea cols=\"18\" rows=\"". $rows ."\" name=\"".$this->get_config_item_name()."\" {$this->jscheck}>";
1598         $ta .= $list_values . "</textarea>";
1599         $ta .= "<p id=\"" . $this->get_config_item_id() . "\" style=\"color: green\">Input accepted.</p>";
1600         return $ta;
1601     }
1602
1603 }
1604
1605 class _ini_set
1606 extends _variable {
1607     function value() {
1608         global $HTTP_POST_VARS;
1609         if ($v = $HTTP_POST_VARS[$this->config_item_name])
1610             return $v;
1611         else {
1612             return ini_get($this->get_config_item_name);
1613         }
1614     }
1615     function _config_format($value) {
1616         return sprintf("ini_set('%s', '%s');", $this->get_config_item_name(), $value);
1617     }
1618     function _get_config_line($posted_value) {
1619         if ($posted_value && ! $posted_value == $this->default_value)
1620             return "\n" . $this->_config_format($posted_value);
1621         else
1622             return "\n//" . $this->_config_format($this->default_value);
1623     }
1624 }
1625
1626 class boolean_define
1627 extends _define {
1628     function _get_config_line($posted_value) {
1629         if ($this->description)
1630             $n = "\n";
1631         return "${n}" . $this->_config_format($posted_value);
1632     }
1633     function _config_format($value) {
1634         if (strtolower(trim($value)) == 'false')
1635             $value = false;
1636         return sprintf("define('%s', %s);", $this->get_config_item_name(),
1637                        (bool)$value ? 'true' : 'false');
1638     }
1639     function get_html() {
1640         $output = $this->get_config_item_header();
1641         $output .= '<select name="' . $this->get_config_item_name() . "\" {$this->jscheck}>\n";
1642         /* The first option is the default */
1643         list($option, $label) = each($this->default_value);
1644         $output .= "  <option value=\"$option\" selected='selected'>$label</option>\n";
1645         /* There can usually, only be two options, there can be
1646          * three options in the case of a boolean_define_commented_optional */
1647         while (list($option, $label) = each($this->default_value)) 
1648           $output .= "  <option value=\"$option\">$label</option>\n";
1649         $output .= "</select>\n";
1650         return $output;
1651     }
1652 }
1653
1654 class boolean_define_optional
1655 extends boolean_define {
1656     function _config_format($value) {
1657         $name = $this->get_config_item_name();
1658         return "if (!defined('$name')) " . boolean_define::_config_format($value);
1659     }
1660 }
1661
1662 class boolean_define_commented
1663 extends boolean_define {
1664     function _get_config_line($posted_value) {
1665         if ($this->description)
1666             $n = "\n";
1667         list($default_value, $label) = each($this->default_value);
1668         if ($posted_value == $default_value)
1669             return "${n}//" . $this->_config_format($posted_value);
1670         else if ($posted_value == '')
1671             return "${n}//" . $this->_config_format('false');
1672         else
1673             return "${n}" . $this->_config_format($posted_value);
1674     }
1675 }
1676
1677 class boolean_define_commented_optional
1678 extends boolean_define_commented {
1679     function _config_format($value) {
1680         $name = $this->get_config_item_name();
1681         return "if (!defined('$name')) " . boolean_define_commented::_config_format($value);
1682     }
1683 }
1684
1685 class part
1686 extends _variable {
1687     function value () { return; }
1688     function get_config($posted_value) {
1689         $d = stripHtml($this->_get_description());
1690         global $SEPARATOR;
1691         return "\n".$SEPARATOR . str_replace("\n", "\n// ", $d) ."\n$this->default_value";
1692     }
1693     function get_instructions($title) {
1694         $group_name = preg_replace("/\W/","",$title);
1695         $i = "<tr class='header' id='$group_name'>\n<td class=\"part\" width=\"100%\" colspan=\"2\" bgcolor=\"#eeaaaa\">\n";
1696         $i .= "<h2>" . $title . "</h2>\n    " . nl2p($this->_get_description()) ."\n";
1697         $i .= "<p><a href=\"javascript:toggle_group('$group_name')\" id=\"{$group_name}_text\">Hide options.</a></p>";
1698         return  $i ."</td>\n";
1699     }
1700     function get_html() {
1701         return "";
1702     }
1703 }
1704
1705 // html utility functions
1706 function nl2p($text) {
1707   preg_match_all("@\s*(<pre>.*?</pre>|<dl>.*?</dl>|.*?(?=\n\n|<pre>|<dl>|$))@s",
1708                  $text, $m, PREG_PATTERN_ORDER);
1709
1710   $text = '';
1711   foreach ($m[1] as $par) {
1712     if (!($par = trim($par)))
1713       continue;
1714     if (!preg_match('/^<(pre|dl)>/', $par))
1715       $par = "<p>$par</p>";
1716     $text .= $par;
1717   }
1718   return $text;
1719 }
1720
1721 function stripHtml($text) {
1722         $d = str_replace("<pre>", "", $text);
1723         $d = str_replace("</pre>", "", $d);
1724         $d = str_replace("<dl>", "", $d);
1725         $d = str_replace("</dl>", "", $d);
1726         $d = str_replace("<dt>", "", $d);
1727         $d = str_replace("</dt>", "", $d);
1728         $d = str_replace("<dd>", "", $d);
1729         $d = str_replace("</dd>", "", $d);
1730         $d = str_replace("<p>", "", $d);
1731         $d = str_replace("</p>", "", $d);
1732         //restore html entities into characters
1733         // http://www.php.net/manual/en/function.htmlentities.php
1734         $trans = get_html_translation_table (HTML_ENTITIES);
1735         $trans = array_flip ($trans);
1736         $d = strtr($d, $trans);
1737         return $d;
1738 }
1739
1740 /**
1741  * Seed the random number generator.
1742  *
1743  * better_srand() ensures the randomizer is seeded only once.
1744  * 
1745  * How random do you want it? See:
1746  * http://www.php.net/manual/en/function.srand.php
1747  * http://www.php.net/manual/en/function.mt-srand.php
1748  */
1749 function better_srand($seed = '') {
1750     static $wascalled = FALSE;
1751     if (!$wascalled) {
1752         if ($seed === '') {
1753             list($usec,$sec)=explode(" ",microtime());
1754             if ($usec > 0.1) 
1755                 $seed = (double) $usec * $sec;
1756             else // once in a while use the combined LCG entropy
1757                 $seed = (double) 1000000 * substr(uniqid("",true),13);
1758         }
1759         if (function_exists('mt_srand')) {
1760             mt_srand($seed); // mersenne twister
1761         } else {
1762             srand($seed);    
1763         }
1764         $wascalled = TRUE;
1765     }
1766 }
1767
1768 function rand_ascii($length = 1) {
1769     better_srand();
1770     $s = "";
1771     for ($i = 1; $i <= $length; $i++) {
1772         // return only typeable 7 bit ascii, avoid quotes
1773         if (function_exists('mt_rand'))
1774             // the usually bad glibc srand()
1775             $s .= chr(mt_rand(40, 126)); 
1776         else
1777             $s .= chr(rand(40, 126));
1778     }
1779     return $s;
1780 }
1781
1782 ////
1783 // Function to create better user passwords (much larger keyspace),
1784 // suitable for user passwords.
1785 // Sequence of random ASCII numbers, letters and some special chars.
1786 // Note: There exist other algorithms for easy-to-remember passwords.
1787 function random_good_password ($minlength = 5, $maxlength = 8) {
1788   $newpass = '';
1789   // assume ASCII ordering (not valid on EBCDIC systems!)
1790   $valid_chars = "!#%&+-.0123456789=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
1791   $start = ord($valid_chars);
1792   $end   = ord(substr($valid_chars,-1));
1793   better_srand();
1794   if (function_exists('mt_rand')) // mersenne twister
1795       $length = mt_rand($minlength, $maxlength);
1796   else  // the usually bad glibc rand()
1797       $length = rand($minlength, $maxlength);
1798   while ($length > 0) {
1799       if (function_exists('mt_rand'))
1800           $newchar = mt_rand($start, $end);
1801       else
1802           $newchar = rand($start, $end);
1803       if (! strrpos($valid_chars,$newchar) ) continue; // skip holes
1804       $newpass .= sprintf("%c",$newchar);
1805       $length--;
1806   }
1807   return($newpass);
1808 }
1809
1810 // debugging
1811 function printArray($a) {
1812     echo "<hr />\n<pre>\n";
1813     print_r($a);
1814     echo "\n</pre>\n<hr />\n";
1815 }
1816
1817 // end of class definitions
1818 /////////////////////////////
1819 // begin auto generation code
1820
1821 if (!function_exists('is_a'))
1822 {
1823   function is_a($object, $class)
1824   {
1825     $class = strtolower($class);
1826     return (get_class($object) == $class) or is_subclass_of($object, $class);
1827   }
1828 }
1829
1830
1831 if (@$HTTP_POST_VARS['action'] == 'make_config') {
1832
1833     $timestamp = date ('dS of F, Y H:i:s');
1834
1835     $config = "<?php
1836 /* This is a local configuration file for PhpWiki.
1837  * It was automatically generated by the configurator script
1838  * on the $timestamp.
1839  */
1840
1841 /*$copyright*/
1842
1843 /////////////////////////////////////////////////////////////////////
1844 /*$preamble*/
1845 ";
1846
1847     $posted = $GLOBALS['HTTP_POST_VARS'];
1848
1849     if (defined('DEBUG'))
1850         printArray($GLOBALS['HTTP_POST_VARS']);
1851
1852     foreach($properties as $option_name => $a) {
1853         $posted_value = $posted[$a->config_item_name];
1854         $config .= $properties[$option_name]->get_config($posted_value);
1855     }
1856
1857     if (defined('DEBUG')) {
1858         $diemsg = "The configurator.php is provided for testing purposes only.
1859 You can't use this file with your PhpWiki server yet!!";
1860         $config .= "\ndie(\"$diemsg\");\n";
1861     }
1862     $config .= $end;
1863
1864     // I think writing this config file is a big security hole.
1865     // If this is installed in such a way that it can write an index-user.php,
1866     // then anyone can create a working index-user.php with, e.g. any
1867     // admin user and pw of their choosing...
1868     //
1869     // So I'm disabling it...
1870
1871     if (defined(ENABLE_FILE_OUTPUT) and ENABLE_FILE_OUPUT) {
1872       /* We first check if the config-file exists. */
1873       if (file_exists($fs_config_file)) {
1874         /* We make a backup copy of the file */
1875         // $config_file = 'index-user.php';
1876         $new_filename = preg_replace('/\.php$/', time() . '.php', $fs_config_file);
1877         if (@copy($fs_config_file, $new_filename)) {
1878             $fp = @fopen($fs_config_file, 'w');
1879         }
1880       } else {
1881         $fp = @fopen($fs_config_file, 'w');
1882       }
1883     }
1884     else {
1885       $fp = false;
1886     }
1887     
1888
1889     if ($fp) {
1890         fputs($fp, $config);
1891         fclose($fp);
1892         echo "<p>The configuration was written to <code><b>$config_file</b></code>.</p>\n";
1893         if ($new_filename) {
1894             echo "<p>A backup was made to <code><b>$new_filename</b></code>.</p>\n";
1895         }
1896         echo "<p><strong>You must rename or copy this</strong> <code><b>$config_file</b></code> <strong>file to</strong> <code><b>index.php</b></code>.</p>\n";
1897     } else {
1898         echo "<p>A configuration file could <b>not</b> be written. You should copy the above configuration to a file, and manually save it as <code><b>index.php</b></code>.</p>\n";
1899     }
1900
1901     echo "<hr />\n<p>Here's the configuration file based on your answers:</p>\n";
1902     echo "<form method='get' action='$PHP_SELF'>\n";
1903     echo "<textarea id='config-output' readonly='readonly' style='width:100%;' rows='30' cols='100'>\n";
1904     echo htmlentities($config);
1905     echo "</textarea></form>\n";
1906     echo "<hr />\n";
1907
1908     echo "<p>To make any corrections, <a href=\"configurator.php\">edit the settings again</a>.</p>\n";
1909
1910 } else { // first time or create password
1911     $posted = $GLOBALS['HTTP_POST_VARS'];
1912     /* No action has been specified - we make a form. */
1913
1914     echo '
1915 <form action="configurator.php" method="post">
1916 <input type="hidden" name="action" value="make_config" />
1917 <table cellpadding="4" cellspacing="0">
1918 ';
1919
1920     while(list($property, $obj) = each($properties)) {
1921         echo $obj->get_instructions($property);
1922         if ($h = $obj->get_html()) {
1923             if (defined('DEBUG'))  $h = get_class($obj) . "<br />\n" . $h;
1924             echo "<td>".$h."</td>\n";
1925         }
1926         echo '</tr>';
1927     }
1928
1929     echo '
1930 </table>
1931 <p><input type="submit" value="Save ',$config_file,'" /> <input type="reset" value="Clear" /></p>
1932 </form>
1933 ';
1934 }
1935 ?>
1936 </body>
1937 </html>