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