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