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