\
|
| Change History: | |
-| 2006-03-13: | fixed WebLinks components; \
- fixed atom feed link at the page bottom |
| 2006-03-11: | reworked sidebar using the new WEBCOMPONET logic; \
docu restructuring - more needed; \
using messages.tmpl as far as possible |
@@ -222,7 +220,7 @@
removed absolute urls; removed EDITURL; \
fixed sidebar help for cairo and beijing; \
fixed squeezed main page; \
- added the concept of WebComponents, that is the WebSideBar and the WebButtons; \
+ added the concept of WebComponents, that is the WebSideBar and the WebButtons; \
the WebButtons are customizable the way the WebSideBar already is |
| 2005-12-01: | added transparent borders and corners to the Kubrick style; \
improved PlasticLoveVariation; \
@@ -250,7 +248,7 @@
fixed way how the oops dialogues switch off the sidebar |
| 2005-10-09: | new release NatSkin-2.51: \
reinvention of the NatSkinStyleBrowser; \
- reworked the standard WebSideBar; \
+ reworked the standard WebSideBar; \
extensive usage of the new conditional content tags \
interfacing the skin state machine, i.e. switch the \
sidebar from the left to the right etc.; \
@@ -279,7 +277,7 @@
__Related topic:__ TWiki:TWiki/TWikiSkins, TWiki:TWiki/TWikiSkinBrowser, TWiki:Plugins/NatSkinDev, NatSkinPlugin
--- TWiki:Main/MichaelDaum - 13 Mar 2006
+-- TWiki:Main/MichaelDaum - 11 Mar 2006
%META:FILEATTACHMENT{name="favicon.ico" attr="" comment="" date="1113468984" path="favicon.ico" size="4710" user="TWikiContributor" version="1.1"}%
Index: twikiplugins/NatSkin/data/TWiki/WebLinks.txt
===================================================================
--- twikiplugins/NatSkin/data/TWiki/WebLinks.txt (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/NatSkin/data/TWiki/WebLinks.txt (.../DEVELOP) (revision 9301)
@@ -1,6 +1,8 @@
%META:TOPICINFO{author="TWikiContributor" date="1132161897" format="1.1" version="1.1"}%
-%STARTINCLUDE%
- * [[%TWIKIWEB%.InstalledPlugins][Plugins]]
-%WEBCOMPONENT{"TWikiWebLinks"}%
- * [[%TWIKIWEB%.TWikiPreferences][SitePreferences]]
+
Index: twikiplugins/NatSkin/templates/defaultbody.nat.tmpl
===================================================================
--- twikiplugins/NatSkin/templates/defaultbody.nat.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/NatSkin/templates/defaultbody.nat.tmpl (.../DEVELOP) (revision 9301)
@@ -49,7 +49,7 @@
%WEBSYNDICATION%
%ELSEDEFINED%
Syndicate this site
- RSSATOM
+ RSSATOM
%FIDEFINED%
Index: twikiplugins/LatexModePlugin/lib/TWiki/Plugins/LatexModePlugin.pm
===================================================================
--- twikiplugins/LatexModePlugin/lib/TWiki/Plugins/LatexModePlugin.pm (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/LatexModePlugin/lib/TWiki/Plugins/LatexModePlugin.pm (.../DEVELOP) (revision 9301)
@@ -65,11 +65,12 @@
use vars qw( $web $topic $user $installWeb $VERSION $RELEASE $debug
$default_density $default_gamma $default_scale $preamble
$eqn $fig $tbl $use_color @norender $tweakinline @EXPORT_OK
+ $rerender
);
# number the release version of this plugin
$VERSION = '$Rev$';
-$RELEASE = '2.4';
+$RELEASE = '2.5';
require Exporter;
*import = \&Exporter::import;
@@ -156,6 +157,8 @@
### between the two.
my $latexout = 0 ;
+my $rerender = 0 ; # flag to rerender all images
+
# =========================
sub initPlugin
{
@@ -202,6 +205,12 @@
$latexout = 1 if ($script =~ m/genpdflatex/);
+ my $query = &TWiki::Func::getCgiQuery();
+ $rerender = &TWiki::Func::getPreferencesValue( "RERENDER" ) || 0;
+ if ($query->param( 'latex' )) {
+ $rerender = ($query->param( 'latex' ) eq 'rerender');
+ }
+
# Plugin correctly initialized
&TWiki::Func::writeDebug( "- TWiki::Plugins::LatexModePlugin::initPlugin( $web.$topic ) is OK" ) if $debug;
@@ -396,7 +405,7 @@
(my $a = $k) =~ s/^\s*|\s*$//;
# scrub the inputs, since this gets passed to 'convert' (in
- # particular, sheild against 'density=166|cat%20/etc/passwd'
+ # particular, shield against 'density=166|cat%20/etc/passwd'
# type inputs). alpha-numeric OK. slash, space, and brackets
# are valid in preamble. need semi-colon in eqn lables!
# allow '-' and '_' in eqn labels too.
@@ -502,9 +511,15 @@
### store the declared options for the rendering later...
$markup_opts{$hash_code} = \%opts;
- #remove any quotes in the string, so the alt tag doesn't break
+
+ # replace troublesome characters in the string, so the alt tag
+ # doesn't break:
$escaped =~ s/\"/"/gso;
$escaped =~ s/\n/ /gso;
+ $escaped =~ s!\&!\&\;!g;
+ $escaped =~ s!\>!\>\;!g;
+ $escaped =~ s!\$1!g;
my $image_name = "$pubUrlPath/latex$hash_code.$EXT";
@@ -555,7 +570,6 @@
$txt = "";
}
} # end 'if !$latexout';
-
return($txt);
}
@@ -616,7 +630,8 @@
#is the image still used in the document?
if( exists( $hashed_math_strings{$hash_code} ) ) {
#if the image is already there, we don't need to re-render
- delete( $hashed_math_strings{$hash_code} );
+ delete( $hashed_math_strings{$hash_code} )
+ unless ($rerender);
next;
}
Index: twikiplugins/LatexModePlugin/data/TWiki/LatexModePlugin.txt
===================================================================
--- twikiplugins/LatexModePlugin/data/TWiki/LatexModePlugin.txt (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/LatexModePlugin/data/TWiki/LatexModePlugin.txt (.../DEVELOP) (revision 9301)
@@ -1,7 +1,7 @@
%META:TOPICINFO{author="ScottHoge" date="1125954924" format="1.0" version="1.4"}%
---+!! %TOPIC%
-This LaTeX Mode TWiki Plugin allows you to include LaTeX mark up commands within a TWiki page. It uses external programs (specifically latex, dvips, and convert) to generate =png= images from the mark up. These images are then included in the rendered TWiki page. The first time a particular image is generated, there may be a significant lag in page rendering as the images are generated on the server. Once rendered, the image is saved as an attached file for the page, so subsequent viewings will not require re-renders. When you remove a math expression from a page, its image is deleted.
+This LaTeX Mode TWiki Plugin allows you to include LaTeX mark up commands within a TWiki page. It uses external programs (specifically latex, dvipng, or dvips-and-convert) to generate =png= images from the mark up. These images are then included in the rendered TWiki page. The first time a particular image is generated, there may be a significant lag in page rendering as the images are generated on the server. Once rendered, the image is saved as an attached file for the page, so subsequent viewings will not require re-renders. When you remove a math expression from a page, its image is deleted.
This plugin expands the functionality provided by the (older) TWiki:Plugins.MathModePlugin.
@@ -83,16 +83,6 @@
| =yellow=| cmyk | 0,0,1,0 |
-To use additional colors, they need to be defined in (what is known as) the
-Latex preamble. The preamble can be set as either a web or topic preference
-variable
-
- * #Set PREAMBLE = \usepackage{color} \definecolor{Aqua}{rgb}{0,1,1}
-
-
-or as a multi-line declaration, using the tags:
-%BEGINLATEXPREAMBLE% and %ENDLATEXPREAMBLE%
-
For convenience, the following TWiki colors are pre-defined in the LatexModePlugin
\definecolor{Red}{rgb}{1,0,0}
@@ -114,8 +104,30 @@
\definecolor{Silver}{gray}{0.75}
\definecolor{White}{gray}{1}
-One does not need to declare a preamble to use these colors.
+To use additional colors, they need to be defined in the Latex preamble, as described in the next section.
+
+---+++ Defining the LaTeX preamble
+
+In LaTeX, the preamble is used to customize the latex processing,
+allowing one to add custom styles and declare new commands.
+
+In TWiki, the preamble can be set as either a web or topic preference variable
+
+ * #Set PREAMBLE = \usepackage{color} \definecolor{Aqua}{rgb}{0,1,1}
+
+or as a multi-line declaration, using the tags:
+
+ %BEGINLATEXPREAMBLE% ... %ENDLATEXPREAMBLE%
+
+
+One critical difference between the two exists. With the exception of the
+color declarations above, the TWiki preference setting will _override_ the
+default settings, and is intended to provide site administrators a central
+point to set preamble settings globally. In contrast, the tag declaration
+will _add_ to the preamble defined by either the default settings or the
+preference setting, allowing TWiki users to amend the preamble.
+
---++ Examples
@@ -176,15 +188,21 @@
First, confirm that the external software needed by the plugin is installed on the TWiki server. This includes:
* The =Digest::MD5= and =Image::Info= perl modules.
* A working LaTeX implementation ([[http://www.tug.org/tetex/][tetex]] and [[http://www.miktex.org/][MikTeX]] are two popular choices)
+ * [[http://sourceforge.net/projects/dvipng/][dvipng]], a fast dvi to png converter
* the [[http://www.cs.wisc.edu/~ghost/][Ghostscript]] package
* the 'convert' executable from either [[http://www.imagemagick.org/][ImageMagick]] or [[http://www.graphicsmagick.org/][GraphicsMagick]]
+Rendering can be performed by _either_ (=dvipng=) or (=dvips= and =convert=).
+=dvipng= is significantly faster. However, the =tweakinline= processing
+currently (v 2.5) uses =convert=. Installation requires at least one, and best results will be seen if all are installed.
+
Second,
* Download the ==%TOPIC%.zip== file from the Plugin web
* Unzip ZIP file in your twiki installation directory. Content:
| *File:* | *Description:* |
| ==lib/TWiki/Plugins/LatexModePlugin.pm== | Plugin Perl module |
| ==data/TWiki/LatexModePlugin.txt== | Plugin topic and documentation |
+ | ==data/TWiki/LatexIntro.txt== | a basic description of LaTeX markup conventions |
| ==data/TWiki/LatexSymbolList.txt== | Comprehensive list of available LaTeX symbols |
| ==pub/TWiki/LatexModePlugin/expl-v1.4.png== | example image of rendered latex |
@@ -192,10 +210,10 @@
* Set the local paths of =latex=, =dvips= and =convert=. This can be done by adding the following lines to =lib/LocalSite.cfg= or =lib/TWiki.cfg=.
* $TWiki::cfg{Plugins}{LatexModePlugin}{latex} = '/usr/bin/latex';
* $TWiki::cfg{Plugins}{LatexModePlugin}{dvips} = '/usr/bin/dvips';
+ * $TWiki::cfg{Plugins}{LatexModePlugin}{dvipng} = '/usr/bin/dvipng';
* $TWiki::cfg{Plugins}{LatexModePlugin}{convert} = '/usr/X11R6/bin/convert';
* Modify the following if needed. %BR% (These variables were introduced in version 2.4)
- * $TWiki::cfg{Plugins}{LatexModePlugin}{donotrenderlist} %BR% declare a comma-separated list of LaTeX commands that _will not be rendered_. Default = ='input,include'=.
-
+ * $TWiki::cfg{Plugins}{LatexModePlugin}{donotrenderlist} %BR% declare a comma-separated list of LaTeX commands that _will not be rendered_. %BR% Default = ='input,include'=.
* $TWiki::cfg{Plugins}{LatexModePlugin}{tweakinline} %BR% Turned off by default, setting this boolean variable to =1= will enable more complex in-line rendering. See the TWiki:Plugins.LatexModePluginDev topic for more details.
@@ -205,20 +223,22 @@
This plugin is an enhanced version of the TWiki:Plugins.MathModePlugin created by TWiki:Main.GraemeLufkin. There are a number of significant differences:
- * latex-dvips-convert is used in place of =latex2html=, consequently
+ * =dvipng= or =latex-dvips-convert= is used in place of =latex2html=, consequently
* hash table mismatching between twiki and images generated by =latex2html= is eliminated, which was a source of many problems in the TWiki:Plugins.MathModePlugin.
* greater flexibility in markup rendering is available.
* the rendering is done image-by-image, so the cost of total page rendering time should be linear. (that is, ten images will take ten times as long to render as one image.)
* multi-line latex markup is now possible. Consequently, this now means that a <nop> must be included to disable rendering in documentation, as opposed to spliting the math markup over multiple lines as before.
* equations can be numbered, with automatic cross-links available
* if errors occur during the latex markup processing, they are reported during the editing =preview= screen, but not during the standard =view=. The motivation for this is that, in general, _authors_ care about the error but _readers_ do not.
+ * as of version 2.5, one can force the recreation of all latex images in a topic. To do this, add the following text (similar to raw text rendering) to the end of the URL: =?latex=rerender=. E.g. changing =http://localhost/twiki/bin/view/TWiki/LatexModePlugin= to =http://localhost/twiki/bin/view/TWiki/LatexModePlugin?latex=rerender= will force all of the images to be redrawn.
---++ Plugin Info
| Plugin Author: | TWiki:Main.ScottHoge |
-| Plugin Version: | 21 Feb 2006 (v 2.4) |
+| Plugin Version: | 14 Mar 2006 (v 2.5) |
| Change History: | |
+| 14 Feb 2006 (v 2.5) | added =rerender= hook, fixed '> in =alt= field' bug. |
| 21 Feb 2006 (v 2.4) | introduced =donotrenderlist= to patch a critical security hole. Bug fixes include: disabling WikiWord link rendering in =alt= fields of =img= tags; improved in-line rendering alignment available; |
| 1 Feb 2006 (v 2.3) | minor bug fixes: $pathSep changes, now uses &TWiki::Func::extractParameters() |
| 11 Nov 2005 (v 2.2) | more mods for TWiki:Plugins.GenPDFLatexAddOn: protect newlines, moved float handler, moved float label checker |
@@ -230,7 +250,7 @@
| 22 Aug 2005 (v 1.2) | Forked from the TWiki:Plugins.MathModePlugin by TWiki:Main.GraemeLufkin |
| TWiki Dependency: | $TWiki::Plugins::VERSION 1.025 |
| CPAN Dependencies: | CPAN:Digest::MD5, CPAN:File::Basename, CPAN:Image::Info |
-| Other Dependencies: | A working installation of =latex= and =convert= |
+| Other Dependencies: | A working installation of =latex=. A working installation of =convert= or =dvipng=. |
| Perl Version: | 5.8.0 |
| License: | GPL ([[http://www.gnu.org/copyleft/gpl.html][GNU General Public License]]) |
| TWiki:Plugins/Benchmark: | %TWIKIWEB%.GoodStyle 100%, %TWIKIWEB%.FormattedSearch 100%, %TOPIC% 100% |
Index: twikiplugins/LatexModePlugin/data/TWiki/LatexIntro.txt
===================================================================
--- twikiplugins/LatexModePlugin/data/TWiki/LatexIntro.txt (.../TWikiRelease04x00) (revision 0)
+++ twikiplugins/LatexModePlugin/data/TWiki/LatexIntro.txt (.../DEVELOP) (revision 9301)
@@ -0,0 +1,62 @@
+%META:TOPICINFO{author="ScottHoge" date="1140536586" format="1.0" version="1.0"}%
+
+%BEGINLATEXPREAMBLE%
+ \usepackage{amsfonts}
+ \definecolor{Lightmaroon}{rgb}{0.6667,0,0}
+ \definecolor{Cornflowerblue}{rgb}{0,0.4,0.8}
+%ENDLATEXPREAMBLE%
+
+
+---++ Introduction to %BEGINLATEX{inline="1" color="Lightmaroon"}%\Large\LaTeX%ENDLATEX%
+
+%BEGINLATEX{inline="1"}%\LaTeX%ENDLATEX% is a complete typesetting language developed by Leslie Lamport on top of Donald Knuth's %BEGINLATEX{inline="1"}%\TeX%ENDLATEX%. Most of it is implemented using TWiki.LatexModePlugin, but the main use is producing mathematics, since most other formatting is more conveniently accomplished using Wiki constructs. To produce mathematics _in-line_, the %BEGINLATEX{inline="1"}%\LaTeX%ENDLATEX% text must be surrounded by %BROWN%%$%ENDCOLOR%
+and %BROWN%$%%ENDCOLOR%. Thus, %$\Gamma \vdash Rx_1\cdots x_n$% looks like this
+%$\Gamma \vdash Rx_1\cdots x_n$%
+in the middle of some text. To _display_ mathematics, it must be surrounded by %BROWN%%\[%ENDCOLOR%
+and %BROWN%\]%%ENDCOLOR%. Thus, %BROWN%%\[\mathcal{N}=\langle \mathbb{N},0,1+,\cdot \rangle \subseteq \langle \mathbb{R},0,1+,\cdot \rangle\]%%ENDCOLOR% produces this centered display %\[\mathcal{N}=\langle \mathbb{N},0,1+,\cdot \rangle \subseteq \langle \mathbb{R},0,1+,\cdot \rangle\]% in the middle of a paragraph, which is preferable for long formulas or ones requiring emphasis.
+
+%BEGINLATEX{inline="1"}%\LaTeX%ENDLATEX% is used by most mathematicians, physicists, and engineers for mathematics, and articles and books are typically submitted for publication in %BEGINLATEX{inline="1"}%\LaTeX%ENDLATEX%. There are therefore many helpful web sites, newsgroups, and books about %BEGINLATEX{inline="1"}%\LaTeX%ENDLATEX%. The standard complete reference is Lamport's [[http://www.amazon.com/exec/obidos/tg/detail/-/0201529831/102-6948132-3441705?v=glance][LaTeX: A Document Preparation System (2nd Edition)]]. The place to start on the web is the [[http://www.tug.org/][%BEGINLATEX{color="Cornflowerblue" inline="1"}%\TeX%ENDLATEX% Users Group]].
+
+---+++Brief Tutorial on %BEGINLATEX{inline="1" color="Lightmaroon"}%\bf\LaTeX%ENDLATEX%
+
+All %BEGINLATEX{inline="1"}%\TeX%ENDLATEX% codes begin with a backslash (\). Curly braces ({ }) are used to delimit groupings, except in a few cases where optional arguments must be enclosed in square brackets ([ ]). Many symbols have mnemonic names, like =\Alpha=, =\alpha=, =\forall=, =\exists=, =\lor=, =\land=.
+
+A list of some common symbols is given in the LatexSymbolList topic. Other off-site lists include: [[http://www.math.union.edu/~dpvc/jsMath/symbols/welcome.html][Some Symbols]] and [[http://www.iam.ubc.ca/~newbury/tex/symbols.html][Some Little-Known Symbols]], [[http://www.ctan.org/tex-archive/info/symbols/comprehensive/symbols-a4.pdf][All the Symbols]]. Not all the symbols work in the Wiki, but most of them do.
+
+A subscript is indicated with an underline (_). If the subscript consists of more than one symbol, it must be enclosed in braces. Similarly, a superscript is indicated with a caret (^). Thus, %BROWN%%$ \alpha _{ \beta _1^2}^{ \gamma ^{ \delta ^ \epsilon }}
+$%%ENDCOLOR% yields %$ \alpha _{ \beta _1^2}^{ \gamma ^{ \delta^ \epsilon }}$%,
+
+---+++Document Structure
+
+In standard
+%BEGINLATEX{inline="1"}%\LaTeX%ENDLATEX%
+2e documents, the main file has the following
+structure:
+
+
+Any text that normally goes in the _preamble_ or _text_ sections of the
+template above can be rendered in TWiki. The _preamble_ is typically used
+to define new commands, or use !LaTeX style-files to extend !LaTeX's
+functionality. The _text_ area contains the actual text to be rendered.
+One does not need to use the =\documentclass= or =document= environment to
+use !LaTeX in TWiki.
+
+The ability to render a complete !LaTeX document, say from an existing file,
+within TWiki is currently under consideration. See
+TWiki:Codev.IncludeExistingLatexDocsInTWiki for details and current status.
+
+---+++Pitfalls
+
+Unlike standard %BEGINLATEX{inline="1"}%\TeX%ENDLATEX%, TWiki.LatexModePlugin is (often) finicky about requiring spaces around the name of each symbol: %BROWN%'%$ \Gamma \vdash $%'%ENDCOLOR% (with spaces around =\Gamma= and =\vdash=) yields, correctly, '%$ \Gamma \vdash $%,' but %BROWN%'%$\Gamma\vdash$%'%ENDCOLOR% (no spaces) yields '%$\Gamma\vdash$%'.
+
+-- courtesy of TWiki:Main.ShaughanLavine ([[http://zillion.philosophy.arizona.edu/twiki/bin/view/Courses/LaTeX][see also]])
Index: twikiplugins/WysiwygPlugin/pub/TWiki/WysiwygPlugin/kupustart.js
===================================================================
--- twikiplugins/WysiwygPlugin/pub/TWiki/WysiwygPlugin/kupustart.js (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/WysiwygPlugin/pub/TWiki/WysiwygPlugin/kupustart.js (.../DEVELOP) (revision 9301)
@@ -48,7 +48,13 @@
kupu.registerContentChanger(getFromSelector('kupu-editor-textarea'));
var navigatingAway = function () {
- TWikiVetoIfChanged(kupu, true);
+ if (kupu.content_changed &&
+ confirm('You have unsaved changes.\nAre you sure you want to navigate away from this page?\nCancel will DISCARD your changes (forever!). OK will SAVE your changes.')) {
+ kupu.config.reload_src = 0;
+ // Call the submit handler, as it's not called by the submit() method
+ var form = TWikiHandleSubmit(kupu);
+ form.submit();
+ };
}
if (kupu.getBrowserName() == 'IE') {
@@ -69,5 +75,7 @@
// and now we can initialize...
kupu.initialize();
+ TWikiCleanForm();
+
return kupu;
};
Index: twikiplugins/WysiwygPlugin/pub/TWiki/WysiwygPlugin/twikitools.js
===================================================================
--- twikiplugins/WysiwygPlugin/pub/TWiki/WysiwygPlugin/twikitools.js (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/WysiwygPlugin/pub/TWiki/WysiwygPlugin/twikitools.js (.../DEVELOP) (revision 9301)
@@ -597,7 +597,28 @@
TWikiWikiWordTool.prototype = new LinkTool;
+/*
+ * A submit can come from several places; from links inside the form
+ * (replace form and add form) and from the Kupu save button, which is
+ * redirected to the form. We need to create the 'text'
+ * field for all these operations. The Kupu save button is handled by
+ * the 'submitForm' function declared in kupuinit.js, but the links
+ * have to be handled through the following onSubmit handler.
+ *
+ * This function can be called in a number of different ways:
+ * 1. As the onSubmit handler for the form, when triggered by a click
+ * on a type="submit" input in the form (e.g. replace form)
+ * 2. Just before a form.submit() call, such as the one done for the
+ * save button
+
+ */
function TWikiHandleSubmit(kupu) {
+
+ if (!kupu) {
+ // nasty hack, but I don;t know how else to do it
+ kupu = window.drawertool.editor;
+ }
+
//alert("Fixing spans");
FixBoldItalic(kupu);
@@ -633,54 +654,50 @@
}
//alert("Submitting");
- // we *do not* submit here
- return form;
-}
+ /*
+ // 'submit' should do this for us, but IE refuses
+ // to submit a form after a beforeunload handler has been fired, so we
+ // have to do the upload this horrible way.
+ var xmlhttp = HttpRequestObject();
+ if (!xmlhttp) {
+ alert("Failed to save text to server; could not create request object");
+ return;
+ }
-/*
- * A submit can come from several places; from links inside the form
- * (replace form and add form) and from the Kupu save button, which is
- * redirected to the form. We need to create the 'text'
- * field for all these operations.
- *
- * This function can be called in a number of different ways:
- * 1. As the onSubmit handler for the form, when triggered by a click
- * on a type="submit" input in the form (e.g. replace form)
- * 2. Just before a form.submit() call, such as the one done for the
- * save button
- */
-function TWikiVetoIfChanged(kupu, isSave) {
- if (!kupu) {
- // nasty hack, but I don't know how else to do it
- kupu = window.drawertool.editor;
- }
- var ok;
- var msg = 'You have unsaved changes.\n'+
- 'Are you sure you want to navigate away from this page?\n';
- if( isSave ) {
- kupu.config.reload_src = 0;
- ok = false;
- if( kupu.content_changed ) {
- // Form submission will *save* the topic
- msg += 'Cancel will DISCARD your changes (forever!).\n'+
- 'OK will SAVE your changes.';
- ok = confirm(msg);
+ xmlhttp.open("POST", form.action, true);
+ xmlhttp.onreadystatechange = function () {
+ // handle the response.
+ if (xmlhttp.readyState != 4) {
+ return;
}
- } else {
- // Form submission will *discard* the changes
- ok = true;
- if( kupu.content_changed ) {
- msg += 'OK will DISCARD your changes.';
- ok = confirm(msg);
+ alert("Status: "+xmlhttp.status+" "+xmlhttp.statusText+"\n"+
+ "Response: "+xmlhttp.responseText);
+ // The response contains the text of the target page
+ window.location =
+ };
+
+ var boundary = "Boundary_" + new Date().getMilliseconds() + ";";
+ xmlhttp.setRequestHeader("Content-Type",
+ "multipart/form-data; boundary=" +
+ boundary+"; charset=UTF-8");
+
+ // Set various flags
+ body += MIMEset('wysiwyg_edit', 1, boundary);
+ // Now iterate over the main form fields and include them
+ for (var i = 0; i < form.childNodes.length; i++) {
+ var item = form.childNodes[i];
+ if (item.tagName == 'input' && item.type == 'hidden' ||
+ item.tagName == 'textarea' ) {
+ body += MIMEset(item.name, item.value, boundary);
}
}
- if (ok) {
- // Call the submit handler, as it's not called by the submit() method
- var form = TWikiHandleSubmit(kupu);
- form.submit();
- }
- // always return false to veto the submit, if it came from a form button
- return false;
+ body += "--" + boundary;
+
+ // Send the request
+ xmlhttp.send(body);
+ */
+ // we *do not* submit here
+ return form;
}
function MIMEset(name, value, boundary) {
@@ -723,6 +740,18 @@
return str + ''+nn+'>';
}
+/* Hack bad buttons off the form on startup */
+function TWikiCleanForm() {
+ var elems = document.getElementsByName('submitChangeForm');
+ for (var i = 0; i < elems.length; i++) {
+ if (elems[i].nodeName.toLowerCase() == 'input' &&
+ elems[i].type.toLowerCase() == 'submit' ) {
+ elems[i].parentNode.removeChild(elems[i]);
+ // should replace with _nice_ button?
+ }
+ }
+}
+
function TWikiColorChooserTool(fgcolorbuttonid, colorchooserid) {
/* the colorchooser */
@@ -778,12 +807,10 @@
this.createColorchooser = function(table) {
/* create the colorchooser table */
- var cols = new Array(
- "black", "red", "orange", "yellow", "greenyellow", "lime", "aquamarine", "cyan", "blue", "blueviolet", "fuchsia", "hotpink",
- "dimgray", "firebrick", "darkorange", "gold", "yellowgreen", "green", "turquoise", "deepskyblue", "mediumblue", "darkviolet", "violetred", "deeppink",
- "darkgray", "lightcoral", "goldenrod", "lightyellow", "olivedrab", "limegreen", "mediumturquoise", "lightskyblue", "darkslateblue", "thistle", "orchid", "palevioletred",
- "silver", "rosybrown", "darkkhaki", "khaki", "olive", "darkgreen", "lightseagreen", "steelblue", "navy", "indigo", "purple", "crimson"
- );
+ var cols = new Array( "black", "gray", "silver", "white",
+ "maroon", "purple", "red", "fuschia",
+ "green", "olive", "lime", "yellow",
+ "navy", "teal", "blue", "aqua" );
table.setAttribute('id', 'kupu-colorchooser-table');
table.style.borderWidth = '2px';
table.style.borderStyle = 'solid';
@@ -795,8 +822,8 @@
for (var i=0; i < 4; i++) {
var tr = document.createElement('tr');
- for (var j = 0; j < 12; j++) {
- var color = cols[i * 12 + j];;
+ for (var j = 0; j < 4; j++) {
+ var color = cols[i * 4 + j];;
var td = document.createElement('td');
td.setAttribute('bgColor', color);
td.style.borderWidth = '1px';
Index: twikiplugins/WysiwygPlugin/templates/edit.kupu.tmpl
===================================================================
--- twikiplugins/WysiwygPlugin/templates/edit.kupu.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ twikiplugins/WysiwygPlugin/templates/edit.kupu.tmpl (.../DEVELOP) (revision 9301)
@@ -375,13 +375,11 @@
-
-
+
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ %TMPL:P{"BODY:TopBar:longaction"}% %TOPIC%
+| | *Web:* | *Topic:* |
+| *From:* | %WEB% | %TOPIC% |
+| *To:* | | |
Allow non WikiWord for the new topic name.
__Note:__ It's usually best to choose a
WikiWord
for the new topic name, otherwise automatic linking may not work. Characters not
-allowed in topic names, such as spaces will automatically be removed.%TMPL:END%
-%TMPL:DEF{"topicaction"}%
-
- %TMPL:P{"sep"}% [[%WEB%.%TOPIC%][Cancel]] %TMPL:END%
-%TMPL:P{"rename"}%
\ No newline at end of file
+allowed in topic names, such as spaces will automatically be removed.
+
+---++ Change links in topics that refer to %TOPIC% in the %WEB% Web:
+%LOCAL_SEARCH%
+
+---++ Change links in topics that refer to %WEB%.%TOPIC% in any Web:
+%GLOBAL_SEARCH%
+
+
+ checkboxes of referenced topics
+
+__Note:__
+ * Get help on
+ Renaming and moving topics.
+ * Select the %TRASHWEB% Web to delete the topic.
+ * The checkmarked topics will be updated (another form will appear which will _eventually_ allow you to rename any topics that were locked)
+%TMPL:P{"BODY:BottomBar"}%
+
%TMPL:END%
@@ -210,7 +210,7 @@
%MAKETEXT{"Alternatively hit back to go back to TWiki.TWikiRegistration and choose a different username."}%
-%MAKETEXT{"Please contact [_1] if you have any questions." args="%WIKIWEBMASTER%"}%
+%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
%TMPL:END%
%TMPL:DEF{"bad_wikiname"}%
---+++ %MAKETEXT{"Incorrect [_1]" args="%TWIKIWEB%.WikiName"}%
@@ -240,11 +240,11 @@
-
-
+
+
-%MAKETEXT{"Please contact [_1] if you have any questions." args="%WIKIWEBMASTER%"}%
+%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
%TMPL:END%
%TMPL:DEF{"mandatory_field"}%
---+++ %MAKETEXT{"Topic Save Error"}%
@@ -327,7 +327,8 @@
%PARAM4%
-%MAKETEXT{"Continue and try to rename web?"}%
+
+
%TMPL:END%
@@ -376,7 +377,7 @@
Messages for oopsalerts
}%
%TMPL:DEF{"access_denied"}% %MAKETEXT{"No permission to view [_1]" args="%PARAM1%"}% %TMPL:END%
-%TMPL:DEF{"bad_attachment"}% %MAKETEXT{"Error: File attachment at [_1],[_2] does not exist" args="%PARAM1%, %PARAM2%"}% %TMPL:END%
+%TMPL:DEF{"attachment_missing"}% %MAKETEXT{"Error: File attachment at [_1],[_2] does not exist" args="%PARAM1%, %PARAM2%"}% %TMPL:END%
%TMPL:DEF{"bad_protocol"}% %MAKETEXT{"Error: Unsupported protocol. (Must be 'http://domain/...')"}% %TMPL:END%
%TMPL:DEF{"bad_content"}% %MAKETEXT{"Error: Unsupported content type: [_1] (Must be =text/html=, =text/plain= or =text/css=)" args="%PARAM1%"}% %TMPL:END%
%TMPL:DEF{"topic_not_found"}% %MAKETEXT{"Warning: Can't find topic [_1]" args="%PARAM1%"}% %TMPL:END%
@@ -395,14 +396,14 @@
%MAKETEXT{"Access check on [_1] failed" args="%WEB%.%TOPIC%"}%.
%MAKETEXT{"Action [_1]: [_2]." args="\"%PARAM1%\", %PARAM2%"}%
-%MAKETEXT{"Contact [_1] if you have any questions." args="%WIKIWEBMASTER%"}%
+%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
__%MAKETEXT{"Related topics:"}%__ %MAINWEB%.TWikiGroups, %TWIKIWEB%.TWikiAccessControl %TMPL:END%
%TMPL:DEF{"only_group"}%
%MAKETEXT{"Only members of the [_1] are allowed to perform this action." args="%PARAM1%"}%
-%MAKETEXT{"Contact [_1] if you have any questions." args="%WIKIWEBMASTER%"}%
+%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
__%MAKETEXT{"Related topics:"}%__ %MAINWEB%.TWikiGroups, %TWIKIWEB%.TWikiAccessControl
@@ -411,12 +412,12 @@
---++ %MAKETEXT{"The [_1] web does not exist" args="\"%WEB%\""}%
%MAKETEXT{"A [_1] is divided into webs; each one represents one subject, one area of collaboration. You are trying to [_2] in a web that does not exist." args="%TWIKIWEB%.TWikiSite, '%PARAM1%'"}%
----+++ %MAKETEXT{"If you came here by clicking on a question mark link"}%
+---+++ %ICON{arrowright}% %MAKETEXT{"If you came here by clicking on a question mark link"}%
%MAKETEXT{"A link to a topic located in another web is written like [_1]. Make sure that the name of the web is not spelt wrongly on the previous page; fix the link if necessary." args="*Otherweb.TopicName*"}%
----+++ %MAKETEXT{"If you would like to create this web"}%
+---+++ %ICON{newtopic}% %MAKETEXT{"If you would like to create this web"}%
%MAKETEXT{"You can ~[~[[_1]~]~[create a new web~]~] if you have permission. Contact [_2] if you have any questions." args="%SCRIPTURLPATH{"view"}%/%TWIKIWEB%/ManagingWebs?newweb=%WEB%;newtopic=%TOPIC%#CreateNewWeb, %WIKIWEBMASTER%"}%
%TMPL:END%
%TMPL:DEF{"no_such_topic"}%
@@ -426,12 +427,11 @@
---++ %MAKETEXT{"If you want to create the topic"}%
[[%SCRIPTURLPATH{"edit"}%/%WEB%/%TOPIC%?t=%SERVERTIME{"$year$mo$day$min$sec"}%][%MAKETEXT{"Click here"}%]].
-%MAKETEXT{"Contact [_1] if you have any questions." args="%WIKIWEBMASTER%"}%
+%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
%TMPL:END%
%TMPL:DEF{"no_such_attachment"}%
---++ %MAKETEXT{"Attachment '[_1]' does not exist" args="%PARAM2%"}%
%MAKETEXT{"You are trying to [_1] an attachment that does not exist." args="%PARAM1%"}%
-%MAKETEXT{"Contact [_1] if you have any questions." args="%WIKIWEBMASTER%"}%
+%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
%TMPL:END%
-
Index: templates/oopssaveerr.tmpl
===================================================================
--- templates/oopssaveerr.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/oopssaveerr.tmpl (.../DEVELOP) (revision 9301)
@@ -1,17 +1,25 @@
-%{
+%TMPL:INCLUDE{"twiki.tmpl"}%
+%TMPL:DEF{"HEAD:Title:action"}%%MAKETEXT{"(oops)"}% %TMPL:END%
+%TMPL:DEF{"BODY:TopBar:shortaction"}%%MAKETEXT{"(oops)"}% %TMPL:END%
+%TMPL:DEF{"BODY:TopBar:longaction"}% *%MAKETEXT{"Attention"}%* %TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:action"}% [[%WEB%.%TOPIC%][%MAKETEXT{"OK"}%]] %TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:footernote"}% %TMPL:END%
- NOTE: not used by TWiki, but retained for compatibility with some plugins
- that use it.
-}%
-%TMPL:INCLUDE{"twiki"}%
-%TMPL:DEF{"titleaction"}%%MAKETEXT{"(oops)"}% %TMPL:END%
-%TMPL:DEF{"webaction"}% *%MAKETEXT{"Attention"}%* %TMPL:END%
-%TMPL:DEF{"heading"}%%MAKETEXT{"Topic save error"}%%TMPL:END%
-%TMPL:DEF{"message"}%
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:Start"}%
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ %MAKETEXT{"Topic save error"}%
%MAKETEXT{"During save of file [_1] an error was found by the version control system. Please notify your [_2] administrator." args="%WEB%.%TOPIC%, %WIKITOOLNAME%"}%
=%PARAM1%=
-%MAKETEXT{"Go back in your browser and save your changes locally."}% %TMPL:END%
-%TMPL:DEF{"topicaction"}% [[%WEB%.%TOPIC%][%MAKETEXT{"OK"}%]] %TMPL:END%
-%TMPL:P{"oops"}%
+%MAKETEXT{"Go back in your browser and save your changes locally."}%
+%TMPL:P{"BODY:BottomBar"}%
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
Index: templates/changes.tmpl
===================================================================
--- templates/changes.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/changes.tmpl (.../DEVELOP) (revision 9301)
@@ -1,11 +1,41 @@
-%TMPL:INCLUDE{"twiki"}%
-%TMPL:INCLUDE{"search"}%
-%TMPL:DEF{"titleaction"}%(changes) %TMPL:END%
-%TMPL:DEF{"searchbody"}% %TMPL:P{"repeatedsearchblock"}%%TMPL:END%
+%TMPL:INCLUDE{"twiki.tmpl"}%
+%TMPL:DEF{"HEAD:Title:action"}%(changes) %TMPL:END%
+%TMPL:DEF{"BODY:TopBar:shortaction"}%(changes)%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:longaction"}%%WEBTOPICLIST%%TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:action"}%Subscribe or unsubscribe in %NOTIFYTOPIC%%TMPL:END%
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:Start"}%
+
+---++ Existing attachments for %TOPIC%
+%META{"attachments" all="on"}%
+---++ Attach new file
+
+ %TMPL:P{"previous"}%
+
+
+ Local file:
+
+
+
+
+
+
+
+ Comment:
+
+
+
+
+
+
+ Link:
+
+ Create a link to the attached file at the end of the topic.
+
+
+
+
+ Hide file:
+
+ Hide attachment in normal topic view.
+
+
+
+__Notes:__
+ * *Help:* Please see FileAttachment for more information about attaching files.
+ * *File size:* %IF{"$ATTACHFILESIZELIMIT > 0" then="You can upload files up to %ATTACHFILESIZELIMIT% KB in size." else="There is no size limit for uploaded files."}%
+ * *Link checkbox:* If the attached file is a JPG, GIF or PNG image and you check the box,
+ it will create an inline image (e.g. show the image) at the end of the topic. For other
+ file types a simple link will be created.
+ * *Bug:* Internet Explorer 4.0 or earlier: If you get an "Internal Server Error"
+ message when you upload a file, you need to try again. It should work the second time.
+%TMPL:P{"BODY:BottomBar"}%
+
---+ Move or Delete File %FILENAME%
-
| | *Web:* | * Topic:* |
| *From:* | %WEB%. | %TOPIC% |
| *To:* | . | |
@@ -28,4 +34,7 @@
* An error page will be shown if either of the topics are locked by another user.
* The new topic chosen must already exist.
* Note that any URLs that refer to the attachment will be broken after this move.
-%TMPL:P{"topicinfo"}%
%TMPL:END%
\ No newline at end of file
+%TMPL:P{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
Index: templates/preview.tmpl
===================================================================
--- templates/preview.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/preview.tmpl (.../DEVELOP) (revision 9301)
@@ -1,37 +1,25 @@
-%TMPL:INCLUDE{"twiki"}%
-%TMPL:DEF{"footernote"}%
-
-
-
-
+%TMPL:INCLUDE{"twiki.tmpl"}%
+%TMPL:DEF{"HEAD:Title:action"}%(preview) %TMPL:END%
+%TMPL:DEF{"BODY:TopBar:shortaction"}%(preview)%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:longaction"}%Note: This is a preview. Do not forget to save your changes.%TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:action"}% %FORMFIELDS%%TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:footernote"}%
Minor changes, don't notify
Force new revision
(help)
- %TMPL:END%
+%TMPL:END%
-%TMPL:DEF{"bodystart"}%
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+ %TMPL:P{"HEAD:Style"}%
+
#PageTop
-%TMPL:END%
-
-%TMPL:DEF{"titleaction"}%(preview) %TMPL:END%
-%TMPL:DEF{"headerhelp"}%
-
-
To save changes: Press the [Save Changes] button.
-
To make more changes: Go back in your browser.
-
To cancel: Go back twice.
-
- %TMPL:END%
-%TMPL:DEF{"webaction"}%
- Note:
- This is a preview. Do not forget to save your changes. %TMPL:END%
-
-%TMPL:DEF{"topicaction"}% %FORMFIELDS% %TMPL:END%
-
-%TMPL:DEF{"content"}%
-%TMPL:P{"simpleheader"}%
-
+%TMPL:P{"BODY:SimpleTopBar"}%
%TEXT%
%META{"form"}%
%META{"attachments"}%
@@ -41,10 +29,7 @@
-%TMPL:P{"topicinfo"}%%TMPL:END%
-
-%TMPL:P{"htmldoctype"}%
-%TMPL:P{"head"}%
-%TMPL:P{"bodystart"}%
-%TMPL:P{"main"}%
-%TMPL:P{"bodyend"}%
\ No newline at end of file
+%TMPL:P{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
Index: templates/edit.tmpl
===================================================================
--- templates/edit.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/edit.tmpl (.../DEVELOP) (revision 9301)
@@ -1,20 +1,13 @@
%TMPL:INCLUDE{"twiki"}%
-%TMPL:DEF{"focus"}%
-try { document.main.text.focus(); } catch (er) {}
-%TMPL:END%
-%TMPL:DEF{"templatescript"}%
-
-%TMPL:END%
-%TMPL:DEF{"bodystart"}%
-
-#PageTop
-%TMPL:END%
-
-%TMPL:DEF{"footernote"}%
-
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ %TMPL:P{"BODY:TopBar:longaction"}% %TOPIC%
+| | *Web:* | *Topic:* |
+| *From:* | %WEB% | %TOPIC% |
+| *To:* | %NEW_WEB% | %NEW_TOPIC% |
+
+
+
+
+Allow non WikiWord for the new topic name.
+__Note:__ It's usually best to choose a
+WikiWord
+for the new topic name, otherwise automatic linking may not work. Characters not
+allowed in topic names, such as spaces will automatically be removed.
+
+---++ Change links in topics that refer to %TOPIC% in the %WEB% Web:
+%LOCAL_SEARCH%
+
+---++ Change links in topics that refer to %WEB%.%TOPIC% in any Web:
+%GLOBAL_SEARCH%
+
+
+ checkboxes of referenced topics
+
+__Note:__
+ * Get help on
+ Renaming and moving topics.
+ * Select the %TRASHWEB% Web to delete the topic.
+ * The checkmarked topics will be updated (another form will appear which will _eventually_ allow you to rename any topics that were locked)
+%TMPL:P{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
Index: templates/twiki.tmpl
===================================================================
--- templates/twiki.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/twiki.tmpl (.../DEVELOP) (revision 9301)
@@ -1,23 +1,45 @@
-%{ Internationalisable Messages/constructs }%
-%TMPL:DEF{"sep"}%|%TMPL:END%
-%TMPL:DEF{"titlesep"}%<%TMPL:END%
-%TMPL:DEF{"LOG_IN"}%Log In%TMPL:END%
-%TMPL:DEF{"LOG_OUT"}%Log Out%TMPL:END%
+%{
+ Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
+
+ Copyright (C) 2005-2006 TWiki Contributors. All Rights Reserved.
+ TWiki Contributors
+ are listed in the AUTHORS file in the root of this distribution.
+ NOTE: Please extend that file, not this notice.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version. For
+ more details read LICENSE in the root of this distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ As per the GPL, removal of this notice is prohibited.
-%TMPL:DEF{"htmldoctype"}%
-
- %TMPL:END%
+ This file defines a set of standard templates that are included by other
+ template files.
+ The templates are named depending on whether they are used in the HEAD or BODY of
+ the HTML page. The second part of the name is descriptive of the function. If there
+ is a third part to the name, then the template is a "variable" i.e. something that
+ may be set by a calling template to parameterise one of the definitions here.
+ Note that this file should be included in templates *before* any HTML, and any local
+ definitions in files should be defined at the top. This is because these definitions
+ expand to a bunch of whitespace that is trimmed off when the HTML is generated. If you
+ embed definitions in real HTML, you may get unexpected results!
+}%
-%TMPL:DEF{"templatescript"}%%TMPL:END%
+%{ Standard DOCTYPE tag }%
+%TMPL:DEF{"Standard:DocType"}%
+%TMPL:END%
-
-
-%TMPL:DEF{"script"}%
-
+%{ SCRIPT tag in standard page head }%
+%TMPL:DEF{"HEAD:Script"}%
-%TMPL:P{"templatescript"}%
%TMPL:END%
+%{ TITLE tag
+ Requires
+ HEAD:Title:action
+}%
+%TMPL:DEF{"HEAD:Title"}%%TMPL:P{"HEAD:Title:action"}% %WIKITOOLNAME%:%WEB%.%TOPIC%%TMPL:END%
+%{ Common META and LINK tags }%
+%TMPL:DEF{"HEAD:Meta"}%
+
+
+
+ %TMPL:END%
-%TMPL:DEF{"windowtitle"}%%TMPL:P{"titleaction"}%%TOPIC% < %WEB% < %WIKITOOLNAME%%TMPL:END%
+%{ STYLE tag }%
+%TMPL:DEF{"HEAD:Style"}%
+%TMPL:END%
-
-
-%TMPL:DEF{"twikistyle"}%
-%TMPL:INCLUDE{"css.tmpl"}%
+%{ Start of the body }%
+%TMPL:DEF{"BODY:Start"}%
+#PageTop
%TMPL:END%
-
-
-%TMPL:DEF{"head"}%
-
- %TMPL:P{"windowtitle"}%
- %HTTP_EQUIV_ON_VIEW%
-
-
- %TMPL:P{"script"}%
- %TMPL:P{"twikistyle"}%
-%TMPL:END%
-
-
-
-%TMPL:DEF{"titleaction"}% %TMPL:END%
-
-
-
-%TMPL:DEF{"webaction"}%%TMPL:END%
-
-
-
-%TMPL:DEF{"bodystart"}%
-
+%{ Alternative to BODY:Start, has javascript to initialise a form }%
+%TMPL:DEF{"BODY:StartForm"}%
#PageTop
%TMPL:END%
+%{ This template uses two global variables to help in composition. These must be set by any
+ template file instantiating this definition.
+ BODY:TopBar:shortaction - short name for the template file's action e.g. "(edit)"
+ BODY:TopBar:longaction - long name e.g "Change topic"
+}%
+%TMPL:DEF{"BODY:TopBar"}%
+
+%TMPL:END%
+%{
+ Simpler version of BODY:TopBar. Shares the same configuration variables i.e.
+ BODY:TopBar:shortaction - short name for the template file's action e.g. "(edit)"
+ BODY:TopBar:longaction - long name e.g "Change topic"
+}%
+%TMPL:DEF{"BODY:SimpleTopBar"}%
+
+%TMPL:END%
-%TMPL:DEF{"attachments"}%%TMPL:END%
+%{ Revisions, for use in bottom bar (or top bar, if you prefer }%
+%TMPL:DEF{"BODY:Revisions"}%%MAKETEXT{"&History"}%: %REVISIONS%%TMPL:END%
+%{ The action bar at the bottom of the page
+ Requires
+ BODY:BottomBar:action
+ BODY:BottomBar:footernote
+}%
+%TMPL:DEF{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:BottomBar:action"}%
+
+%TMPL:P{"BODY:BottomBar:footernote"}%
+
+%TMPL:P{"BODY:Copyright"}%
+%TMPL:END%
+%{ TWiki anchor at the bottom of the page }%
+%TMPL:DEF{"BODY:PageBottom"}%
+#PageBottom
+%TMPL:END%
-%TMPL:DEF{"standardheader"}%
-
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ Delete %TOPIC%
+| | *Web:* | * Topic:* |
+| *From:* | %WEB%. | %TOPIC% |
+| *To:* | | |
Allow non WikiWord for deleted topic name.
-__Note:__ This name has been chosen so it doesn't conflict with any other topics already in the %NEW_WEB% web. %TMPL:END%
-%TMPL:DEF{"topicaction"}%
-
- %TMPL:P{"sep"}% [[%WEB%.%TOPIC%][Cancel]] %TMPL:END%
-%TMPL:P{"rename"}%
+__Note:__ This name has been chosen so it doesn't conflict with any other topics already in the %NEW_WEB% web.
+---++ Change links in topics that refer to %TOPIC% in the %WEB% Web:
+%LOCAL_SEARCH%
+---++ Change links in topics that refer to %WEB%.%TOPIC% in any Web:
+%GLOBAL_SEARCH%
+ checkboxes of referenced topics
+
+__Note:__
+ * Get help on
+ Renaming and moving topics.
+ * Select the %TRASHWEB% Web to delete the topic.
+ * The checkmarked topics will be updated (another form will appear which will _eventually_ allow you to rename any topics that were locked)
+%TMPL:P{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
+
Index: templates/formtables.tmpl
===================================================================
--- templates/formtables.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/formtables.tmpl (.../DEVELOP) (revision 9301)
@@ -1,21 +1,18 @@
%{ These templates define the form attached at the bottom of viewed page. }%
%{ Header definition for topic attachments and top table in attach screen }%
-%TMPL:DEF{FORM:display:header}%
-
+%TMPL:DEF{FORM:display:header}%
[[%A_TITLE%]]
%TMPL:END%
%{ Each row }%
-%TMPL:DEF{FORM:display:row}%
-
-
-*Note:*
- * Get help on
- Setting topic preferences.
- * Each preference has the syntax [multiple of 3 spaces] * [space] Set [space] VARIABLENAME [space] = [space] [value]
-
- %TMPL:END%
-
-
-
-
-%TMPL:DEF{"content"}%
-
+ Create a link to the attached file at the end of the topic.
+
+
+
+
+ Hide file:
+
+ Hide attachment in normal topic view.
+
+
+
+__Notes:__
+
+ * *Help:* Please see FileAttachment for more information about attaching files.
+ * *File size:* %IF{"$ATTACHFILESIZELIMIT > 0" then="You can upload files up to %ATTACHFILESIZELIMIT% KB in size." else="There is no size limit for uploaded files."}%
+ * *Link checkbox:* If the attached file is a JPG, GIF or PNG image and you check the box,
+ it will create an inline image (e.g. show the image) at the end of the topic. For other
+ file types a simple link will be created.
+ * *Bug:* Internet Explorer 4.0 or earlier: If you get an "Internal Server Error"
+ message when you upload a file, you need to try again. It should work the second time.
* *Properties:* The comment and visibility (i.e. is attachment hidden) can be changed without
uploading a file by pressing "Change Properties"; see
HiddenAttachment
@@ -22,11 +78,7 @@
comment when the file was uploaded.
* *Local file:* If you select a different file in _Local file:_, it is this that will be
updated or added.
-%TMPL:END%
-%TMPL:DEF{"topicaction"}%
- %TMPL:P{"sep"}%
- %TMPL:P{"sep"}%
- Move or delete attachment %TMPL:P{"sep"}%
- [[%WEB%.%TOPIC%][Cancel]] %TMPL:END%
-%TMPL:DEF{"fileuser"}%(%FILEUSER%)%TMPL:END%
-%TMPL:P{"attach"}%
\ No newline at end of file
+%TMPL:P{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
Index: templates/renameweb.tmpl
===================================================================
--- templates/renameweb.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/renameweb.tmpl (.../DEVELOP) (revision 9301)
@@ -1,15 +1,61 @@
-%TMPL:INCLUDE{"renamewebbase"}%
-%TMPL:DEF{"titleaction"}%(rename) %TMPL:END%
-%TMPL:DEF{"webaction"}%Rename%TMPL:END%
-%TMPL:DEF{"newsubweb"}%%TMPL:END%
-%TMPL:DEF{"newparentweb"}%%TMPL:END%
-%TMPL:DEF{"notes"}%
+%TMPL:INCLUDE{"twiki.tmpl"}%
+%TMPL:DEF{"HEAD:Title:action"}%(rename)%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:shortaction"}%(rename)%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:longaction"}%Rename web%TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:action"}% [[%WEB%.%TOPIC%][Cancel]] %TMPL:END%
+
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+
+
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:Start"}%
+
+
+
+ %TMPL:P{"BODY:SimpleTopBar"}%
+---+ Rename %WEB%
+
+| | *Web:* ||
+| *From:* | %NEW_PARENTWEB%. |%NEW_SUBWEB% |
+| *To:* | | |
__Notes:__
* It's usually best to choose a WikiWord for the new web name, otherwise automatic linking may not work. Characters not allowed in topic names, such as spaces will automatically be removed.
* %MAKETEXT{"To delete this web: move this web to the Trash web by renaming it to [_1]." args="%TRASHWEB%/%WEB%"}%
-%TMPL:END%
-%TMPL:DEF{"topicaction"}%
-
- %TMPL:P{"sep"}% [[%WEB%.%TOPIC%][Cancel]] %TMPL:END%
-%TMPL:P{"renameweb"}%
\ No newline at end of file
+---++ Notices
+*Topics which are currently being edited by other users in the %WEB% Web:*
+%MOVE_LOCKED%
+
+*Topics which refer to this web and are are currently being edited by other users:* %REF_LOCKED%
+
+*Topics which refer to this web that you do not have permission to change:*
+%REF_DENIED%
+
+---++ Change links in topics that refer to %WEB%.Topicname in the %WEB% Web:
+
+%LOCAL_SEARCH%
+
+---++ Change links in topics that refer to %WEB% in any Web:
+
+%GLOBAL_SEARCH%
+
+ checkboxes of referenced topics
+
+__Note:__
+ * Get help on
+ Renaming and moving webs.
+ * Select the %TRASHWEB% Web to delete the topic.
+ * The checkmarked topics will be updated.
+%TMPL:P{"BODY:BottomBar"}%
+
-
-%TEXTHEAD%
-
-
-%REPEAT% %TMPL:END
\ No newline at end of file
+
Index: templates/oopsleaseconflict.tmpl
===================================================================
--- templates/oopsleaseconflict.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/oopsleaseconflict.tmpl (.../DEVELOP) (revision 9301)
@@ -1,27 +1,30 @@
-%{ Templates for lease conflict messages. One DEF is selected and inserted at %INSTANTIATE }%
-%TMPL:INCLUDE{"twiki"}%
-%TMPL:DEF{"titleaction"}%%MAKETEXT{"(oops)"}% %TMPL:END%
-%TMPL:DEF{"webaction"}% *%MAKETEXT{"Attention"}%* %TMPL:END%
-%TMPL:DEF{"heading"}%%MAKETEXT{"Conflict"}%%TMPL:END%
-%TMPL:DEF{"topicaction"}%%TMPL:END%
+%TMPL:INCLUDE{"twiki.tmpl"}%
%TMPL:INCLUDE{"messages"}%
-%TMPL:DEF{"message"}%
+%TMPL:DEF{"HEAD:Title:action"}%%MAKETEXT{"(oops)"}%%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:shortaction"}%%MAKETEXT{"(oops)"}% %TMPL:END%
+%TMPL:DEF{"BODY:TopBar:longaction"}% *%MAKETEXT{"Attention"}%* %TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:action"}%[[%WEB%.%TOPIC%][%MAKETEXT{"View topic"}%]] | View raw text without formatting%TMPL:END%
-%{ Instantiate either lease_active or lease_old }%
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:Start"}%
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ %MAKETEXT{"Conflict"}%
%INSTANTIATE%
%QUERYPARAMS%
-%MAKETEXT{"To see if [_1] has finished editing yet, click " args="%PARAM1%}%
-
+ %MAKETEXT{"to see if [_1] has finished editing yet." args="%PARAM1%}%
-%MAKETEXT{"To edit the topic anyway, click "}%
-%QUERYPARAMS%
+%QUERYPARAMS% %MAKETEXT{"to edit the topic anyway."}%
+
+
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ Confirm rename or move %WEB%
+| | *Web:* ||
+| *From:* | %NEW_PARENTWEB%. |%NEW_SUBWEB% |
+| *To:* | %TMPL:P{"newparentweb"}%. |%TMPL:P{"newsubweb"}% |
+%TMPL:P{"notes"}%
+
+---++ Notices
+*Topics which are currently being edited by other users in the %WEB% Web:*
+%MOVE_LOCKED%
+
+*Topics which refer to this web and are are currently being edited by other users:* %REF_LOCKED%
+
+*Topics which refer to this web that you do not have permission to change:*
+%REF_DENIED%
+
+---++ Change links in topics that refer to %WEB%.Topicname in the %WEB% Web:
+
+%LOCAL_SEARCH%
+
+---++ Change links in topics that refer to %WEB% in any Web:
+
+%GLOBAL_SEARCH%
+
+ checkboxes of referenced topics
+
+__Note:__
+ * Get help on
+ Renaming and moving webs.
+ * Select the %TRASHWEB% Web to delete the topic.
+ * The checkmarked topics will be updated.
+%TMPL:P{"BODY:BottomBar"}%
+
+
+
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ Delete %WEB%
+
+| | *Web:* ||
+| *From:* | %NEW_PARENTWEB%. |%NEW_SUBWEB% |
+| *To:* | | |
Allow non WikiWord for deleted topic name.
-__Note:__ This name has been chosen so it doesn't conflict with any other topics already in the %NEW_PARENTWEB% web. %TMPL:END%
-%TMPL:DEF{"topicaction"}%
-
- %TMPL:P{"sep"}% [[%WEB%.%TOPIC%][Cancel]] %TMPL:END%
-%TMPL:P{"renameweb"}%
+__Note:__ This name has been chosen so it doesn't conflict with any other topics already in the %NEW_PARENTWEB% web.
+---++ Notices
+*Topics which are currently being edited by other users in the %WEB% Web:*
+%MOVE_LOCKED%
+
+*Topics which refer to this web and are are currently being edited by other users:* %REF_LOCKED%
+
+*Topics which refer to this web that you do not have permission to change:*
+%REF_DENIED%
+
+---++ Change links in topics that refer to %WEB%.Topicname in the %WEB% Web:
+
+%LOCAL_SEARCH%
+
+---++ Change links in topics that refer to %WEB% in any Web:
+
+%GLOBAL_SEARCH%
+
+ checkboxes of referenced topics
+
+__Note:__
+ * Get help on
+ Renaming and moving webs.
+ * Select the %TRASHWEB% Web to delete the topic.
+ * The checkmarked topics will be updated.
+%TMPL:P{"BODY:BottomBar"}%
+
%TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:footernote"}%%TMPL:END%
-%TMPL:DEF{"languagenotes"}%
-%ICON{info}% %MAKETEXT{"You can set your favorite language permanently by setting the [_1] variable in your user topic." args="*LANGUAGE*"}%
-%TMPL:END%
-
-%TMPL:DEF{"message"}%
-
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:Start"}%
+%TMPL:P{"BODY:SimpleHeader"}%
+---+ %MAKETEXT{"Change language"}%
%MAKETEXT{"TWiki's user interface is available in several languages. If you want to change the language for this session, choose one of the following and hit \"Change language\". Otherwise, follow the \"Cancel\" link on the bottom of the page to return to the previous topic."}%
@@ -22,6 +27,8 @@
-%TMPL:P{"languagenotes"}%
-%TMPL:END%
-%TMPL:P{"oops"}%
\ No newline at end of file
+%ICON{info}% %MAKETEXT{"You can set your favorite language permanently by setting the [_1] variable in your user topic." args="*LANGUAGE*"}%
+%TMPL:P{"BODY:BottomBar"}%
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
+
Index: templates/edittext.tmpl
===================================================================
--- templates/edittext.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/edittext.tmpl (.../DEVELOP) (revision 9301)
@@ -1,9 +1,33 @@
-%TMPL:INCLUDE{"edit"}%
+%TMPL:INCLUDE{"twiki"}%
+%TMPL:DEF{"HEAD:Title:action"}%(edit text)%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:shortaction"}%(edit text)%TMPL:END%
+%TMPL:DEF{"BODY:TopBar:longaction"}%Change topic%TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:action"}%
+ |
+
+
+ |
+ %TMPL:END%
+%TMPL:DEF{"BODY:BottomBar:footernote"}%
+ Minor changes, don't notify
+
+ Force new revision
+(help)
+
+%INCLUDE{"%TWIKIWEB%.WikiSyntaxSummary"}%
+
+ %TMPL:END%
-%TMPL:DEF{"titleaction"}%(edit text)%TMPL:END%
-
-%TMPL:DEF{"content"}%
-%TMPL:P{"simpleheader"}%
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:StartForm"}%
+%TMPL:P{"BODY:SimpleTopBar"}%
%FORMFIELDS%
-%TMPL:P{"topicinfo"}%
%TMPL:END%
\ No newline at end of file
+%TMPL:P{"BODY:BottomBar"}%
+
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
+
+
Index: templates/oopslanguagechanged.tmpl
===================================================================
--- templates/oopslanguagechanged.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/oopslanguagechanged.tmpl (.../DEVELOP) (revision 9301)
@@ -1,11 +1,19 @@
-%TMPL:INCLUDE{"twiki"}%
-%TMPL:DEF{"titleaction"}% %MAKETEXT{"(change language)"}% %TMPL:END%
-%TMPL:DEF{"webaction"}%%TMPL:END%
-%TMPL:DEF{"heading"}%%MAKETEXT{"Change language"}%%TMPL:END%
-%TMPL:DEF{"topicaction"}%
%TMPL:END%
-%TMPL:DEF{"message"}%
-
+%TMPL:P{"Standard:DocType"}%
+
+ %TMPL:P{"HEAD:Meta"}%
+ %HTTP_EQUIV_ON_VIEW%
+ %TMPL:P{"HEAD:Script"}%
+ %TMPL:P{"HEAD:Style"}%
+
+%TMPL:P{"BODY:Start"}%
+%TMPL:P{"BODY:SimpleTopBar"}%
+---+ %MAKETEXT{"Change language"}%
%SESSION_VARIABLE{"LANGUAGE" set="%URLPARAM{language}%"}%
%MAKETEXT{"Your language will be changed to [_1] from the next screen. You will be redirected to there right now. If you aren't, ~[~[[_2]~]~[click here~]~] to proceed." args="*%SESSION_VARIABLE{LANGUAGE}%*, %SCRIPTURLPATH{"view"}%/%WEB%/%TOPIC%"}%
@@ -13,6 +21,7 @@
+%TMPL:P{"BODY:BottomBar"}%
+%TMPL:P{"BODY:PageBottom"}%
+%TMPL:P{"BODY:End"}%
-%TMPL:END%
-%TMPL:P{"oops"}%
\ No newline at end of file
Index: templates/attachtables.tmpl
===================================================================
--- templates/attachtables.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/attachtables.tmpl (.../DEVELOP) (revision 9301)
@@ -1,54 +1,43 @@
%{ These templates define the tables used to display attachments. }%
%{ Header definition for topic attachments and top table in attach screen }%
-%TMPL:DEF{ATTACH:files:header(basic)}%
-
%TMPL:END%
%{ Header for table at top of attach screen }%
-%TMPL:DEF{ATTACH:files:header:A}%
-%TMPL:P{ATTACH:files:header(basic)}% *[[%TWIKIWEB%.FileAttribute][Attribute]]* |
+%TMPL:DEF{ATTACH:files:header:A}%%TMPL:P{ATTACH:files:header(basic)}%
[[%TWIKIWEB%.FileAttribute][Attribute]]
%TMPL:END%
%{ Row for table at top of attach screen }%
-%TMPL:DEF{ATTACH:files:row:A}%
-%TMPL:P{ATTACH:files:row(basic)}% %A_ATTRS% |
+%TMPL:DEF{ATTACH:files:row:A}%%TMPL:P{ATTACH:files:row(basic)}%
%A_ATTRS%
%TMPL:END%
%{ Footer for table at top of attach screen }%
-%TMPL:DEF{ATTACH:files:footer:A}%
-
%TMPL:END%
%{ Footer for versions table in attach screen }%
-%TMPL:DEF{ATTACH:versions:footer}%
-%TMPL:END%
\ No newline at end of file
+%TMPL:DEF{ATTACH:versions:footer}%
-
-
-%TMPL:P{"simpleheader"}%
----+ %TMPL:P{"webaction"}% %WEB%
-
-| | *Web:* ||
-| *From:* | %NEW_PARENTWEB%. |%NEW_SUBWEB% |
-| *To:* | %TMPL:P{"newparentweb"}%. |%TMPL:P{"newsubweb"}% |
-%TMPL:P{"notes"}%
-
----++ Notices
-*Topics which are currently being edited by other users in the %WEB% Web:*
-%MOVE_LOCKED%
-
-*Topics which refer to this web and are are currently being edited by other users:* %REF_LOCKED%
-
-*Topics which refer to this web that you do not have permission to change:*
-%REF_DENIED%
-
----++ Change links in topics that refer to %WEB%.Topicname in the %WEB% Web:
-
-%LOCAL_SEARCH%
-
----++ Change links in topics that refer to %WEB% in any Web:
-
-%GLOBAL_SEARCH%
-
- checkboxes of referenced topics
-
-__Note:__
- * Get help on
- Renaming and moving webs.
- * Select the %TRASHWEB% Web to delete the topic.
- * The checkmarked topics will be updated.
-%TMPL:P{"topicinfo"}%
-
%TMPL:END%
-
-%TMPL:DEF{"renameweb"}%
-%TMPL:P{"htmldoctype"}%
-%TMPL:P{"head"}%
-%TMPL:P{"bodystart"}%
-%TMPL:P{"main"}%
-%TMPL:P{"bodyend"}%
-%TMPL:END%
\ No newline at end of file
Index: templates/attach.tmpl
===================================================================
--- templates/attach.tmpl (.../TWikiRelease04x00) (revision 9301)
+++ templates/attach.tmpl (.../DEVELOP) (revision 9301)
@@ -1,80 +0,0 @@
-%TMPL:INCLUDE{"twiki"}%
-
-
-
-%TMPL:DEF{"templatescript"}%
-
-%TMPL:END%
-
-
-
-%TMPL:DEF{"bodystart"}%
-
-#PageTop
-%TMPL:END%
-
-%TMPL:DEF{"notes"}%
-__Notes:__
-
- * *Help:* Please see FileAttachment for more information about attaching files.
- * *File size:* %IF{"$ATTACHFILESIZELIMIT > 0" then="You can upload files up to %ATTACHFILESIZELIMIT% KB in size." else="There is no size limit for uploaded files."}%
- * *Link checkbox:* If the attached file is a JPG, GIF or PNG image and you check the box,
- it will create an inline image (e.g. show the image) at the end of the topic. For other
- file types a simple link will be created.
- * *Bug:* Internet Explorer 4.0 or earlier: If you get an "Internal Server Error"
- message when you upload a file, you need to try again. It should work the second time.
-%TMPL:END%
-
-%TMPL:DEF{"existingattachments"}%
----++ Existing attachments for %TOPIC%
-%META{"attachments" all="on"}%
-%TMPL:END%
-
-%TMPL:DEF{"content"}%
-%TMPL:P{"simpleheader"}%
-
-%TMPL:P{"simpleheader"}%
----+ %TMPL:P{"webaction"}% %TOPIC%
-
-| | *Web:* | * Topic:* |
-| *From:* | %WEB%. | %TOPIC% |
-| *To:* | %TMPL:P{"newweb"}%. | %TMPL:P{"newtopic"}% |
-%TMPL:P{"notes"}%
-
----++ Change links in topics that refer to %TOPIC% in the %WEB% Web:
-
-%LOCAL_SEARCH%
-
----++ Change links in topics that refer to %WEB%.%TOPIC% in any Web:
-
-%GLOBAL_SEARCH%
-
- checkboxes of referenced topics
-
-__Note:__
- * Get help on
- Renaming and moving topics.
- * Select the %TRASHWEB% Web to delete the topic.
- * The checkmarked topics will be updated (another form will appear which will _eventually_ allow you to rename any topics that were locked)
-%TMPL:P{"topicinfo"}%
-
RcsLite uses a 100% Perl simplified implementation of RCS.
# RcsLite is useful if you don't have, and can't install, RCS - for
# example, on a hosted platform. It will work, and is compatible with
-# RCS, but is not quite as fast.
-#
Subversive is a thin layer over the Subversion version control system.
-# It is designed for use by developers in a subversion checkout area,
-# and is probably not useful to anyone else.
+# RCS, but is not quite as fast.
+# EXPERT You can manually add options to LocalSite.cfg to select a
+# different store for each web. If $TWiki::cfg{Store}{Fred} is defined, it will
+# be taken as the name of a perl class (which must implement the methods of
+# TWiki::Store::RcsFile).
+# The TWiki::Store::Subversive class is an example implementation using the
+# Subversion version control system as a data store.
$cfg{StoreImpl} = 'RcsWrap';
# The quote used for command arguments is normally ' for
@@ -679,21 +691,6 @@
$cfg{RCS}{ExtOption} = "-x,v" if $OS eq "WINDOWS";
}
-# **BOOLEAN**
-# Some file-based Store implementations (RcsWrap and RcsLite for
-# example) store attachment meta-data separately from the actual attachments.
-# This means that it is possible to have a file in an attachment directory
-# that is not seen as an attachment by TWiki. Sometimes it is desirable to
-# be able to simply copy files into a directory and have them appear as
-# attachments, and that's what this feature allows you to do.
-# Considered experimental.
-$cfg{AutoAttachPubFiles} = $TRUE;
-
-# **REGEX**
-# Perl regular expression matching suffixes valid on plain text files
-# Defines which attachments will be treated as ASCII in RCS
-$cfg{RCS}{asciiFileSuffixes} = '.(txt|html|xml|pl)$';
-
# **OCTAL**
# File security for new directories. You may have to adjust these
# permissions to allow (or deny) users other than the webserver user access
@@ -709,12 +706,27 @@
$cfg{RCS}{filePermission}= 0644;
# **BOOLEAN**
-# Set this if you want to use RCS subdirectories instead of storing
+# EXPERT Some file-based Store implementations (RcsWrap and RcsLite for
+# example) store attachment meta-data separately from the actual attachments.
+# This means that it is possible to have a file in an attachment directory
+# that is not seen as an attachment by TWiki. Sometimes it is desirable to
+# be able to simply copy files into a directory and have them appear as
+# attachments, and that's what this feature allows you to do.
+# Considered experimental.
+$cfg{AutoAttachPubFiles} = $TRUE;
+
+# **REGEX**
+# EXPERT Perl regular expression matching suffixes valid on plain text files
+# Defines which attachments will be treated as ASCII in RCS
+$cfg{RCS}{asciiFileSuffixes} = '.(txt|html|xml|pl)$';
+
+# **BOOLEAN**
+# EXPERT Set this if you want to use RCS subdirectories instead of storing
# ,v files alongside the topics. Not recommended.
$cfg{RCS}{useSubDir} = $FALSE;
# **BOOLEAN**
-# Set this if your RCS cannot check out using the -p option.
+# EXPERT Set this if your RCS cannot check out using the -p option.
# May be needed in some windows installations (not required for cygwin)
$cfg{RCS}{coMustCopy} = $FALSE;
@@ -733,29 +745,29 @@
# **COMMAND**
# RcsWrap initialise a file as binary.
# %FILENAME|F% will be expanded to the filename.
-$cfg{RCS}{initBinaryCmd} = "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -q -i -t-none -kb %FILENAME|F%";
+$cfg{RCS}{initBinaryCmd} = "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -i -t-none -kb %FILENAME|F%";
# **COMMAND**
# RcsWrap initialise a topic file.
-$cfg{RCS}{initTextCmd} = "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -q -i -t-none -ko %FILENAME|F%";
+$cfg{RCS}{initTextCmd} = "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -i -t-none -ko %FILENAME|F%";
# **COMMAND**
# RcsWrap uses this on Windows to create temporary binary files during upload.
-$cfg{RCS}{tmpBinaryCmd} = "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -q -kb %FILENAME|F%";
+$cfg{RCS}{tmpBinaryCmd} = "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -kb %FILENAME|F%";
# **COMMAND**
# RcsWrap check-in.
# %USERNAME|S% will be expanded to the username.
# %COMMENT|U% will be expanded to the comment.
$cfg{RCS}{ciCmd} =
- "$cfg{RCS}{BinDir}/ci $cfg{RCS}{ExtOption} -q -m%COMMENT|U% -t-none -w%USERNAME|S% -u %FILENAME|F%";
+ "$cfg{RCS}{BinDir}/ci $cfg{RCS}{ExtOption} -m%COMMENT|U% -t-none -w%USERNAME|S% -u %FILENAME|F%";
# **COMMAND**
# RcsWrap check in, forcing the date.
# %DATE|D% will be expanded to the date.
$cfg{RCS}{ciDateCmd} =
- "$cfg{RCS}{BinDir}/ci $cfg{RCS}{ExtOption} -q -m%COMMENT|U% -t-none -d%DATE|D% -u -w%USERNAME|S% %FILENAME|F%",
+ "$cfg{RCS}{BinDir}/ci $cfg{RCS}{ExtOption} -m%COMMENT|U% -t-none -d%DATE|D% -u -w%USERNAME|S% %FILENAME|F%",
# **COMMAND**
# RcsWrap check out.
# %REVISION|N% will be expanded to the revision number
$cfg{RCS}{coCmd} =
- "$cfg{RCS}{BinDir}/co $cfg{RCS}{ExtOption} -q -p%REVISION|N% -ko %FILENAME|F%";
+ "$cfg{RCS}{BinDir}/co $cfg{RCS}{ExtOption} -p%REVISION|N% -ko %FILENAME|F%";
# **COMMAND**
# RcsWrap file history.
$cfg{RCS}{histCmd} =
@@ -773,19 +785,19 @@
# **COMMAND**
# RcsWrap differences between two revisions.
$cfg{RCS}{diffCmd} =
- "$cfg{RCS}{BinDir}/rcsdiff $cfg{RCS}{ExtOption} -q -w -B -r%REVISION1|N% -r%REVISION2|N% -ko --unified=%CONTEXT|N% %FILENAME|F%";
+ "$cfg{RCS}{BinDir}/rcsdiff $cfg{RCS}{ExtOption} -w -B -r%REVISION1|N% -r%REVISION2|N% -ko --unified=%CONTEXT|N% %FILENAME|F%";
# **COMMAND**
# RcsWrap lock a file.
$cfg{RCS}{lockCmd} =
- "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -q -l %FILENAME|F%";
+ "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -l %FILENAME|F%";
# **COMMAND**
# RcsWrap unlock a file.
$cfg{RCS}{unlockCmd} =
- "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -q -u %FILENAME|F%";
+ "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -u %FILENAME|F%";
# **COMMAND**
# RcsWrap delete a specific revision.
$cfg{RCS}{delRevCmd} =
- "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -q -o%REVISION|N% %FILENAME|F%";
+ "$cfg{RCS}{BinDir}/rcs $cfg{RCS}{ExtOption} -o%REVISION|N% %FILENAME|F%";
# **PATH**
# Path to the directory where the RCS store implementation will create
@@ -802,19 +814,19 @@
$cfg{EnableHierarchicalWebs} = 1;
# **STRING 20**
-# Name of the web where documentation and default preferences are held. If you
+# EXPERT Name of the web where documentation and default preferences are held. If you
# change this setting, you must make sure the web exists and contains
# appropriate content, and upgrade scripts may no longer work (i.e. don't
# change it unless you are certain that you know what you are doing!)
$cfg{SystemWebName} = 'TWiki';
# **STRING 20**
-# Name of the web used as a trashcan (where deleted topics are moved)
+# EXPERT Name of the web used as a trashcan (where deleted topics are moved)
# If you change this setting, you must make sure the web exists.
$cfg{TrashWebName} = 'Trash';
# **STRING 20**
-# Name of the web where usertopics are stored. If you
+# EXPERT Name of the web where usertopics are stored. If you
# change this setting, you must make sure the web exists and contains
# appropriate content, and upgrade scripts may no longer work
# (i.e. don't change it unless you are certain that you know what
@@ -823,7 +835,7 @@
#---+ Mail and Proxies
# **STRING 20**
-# Name of topic in each web that has notification registrations.
+# EXPERT Name of topic in each web that has notification registrations.
# If you change this setting you will have to
# use TWiki to manually rename the topic in all existing webs
$cfg{NotifyTopicName} = 'WebNotify';
@@ -856,7 +868,7 @@
$cfg{SMTP}{SENDERHOST} = '';
# **STRING 30**
-# Some environments require outbound HTTP traffic to go through a proxy
+# EXPERT Some environments require outbound HTTP traffic to go through a proxy
# server. (e.g. proxy.your.company).
# CAUTION This setting can be overridden by a PROXYHOST setting
# in TWikiPreferences. Make sure you delete the setting from there if
@@ -864,24 +876,38 @@
$cfg{PROXY}{HOST} = '';
# **STRING 30**
-# Some environments require outbound HTTP traffic to go through a proxy
+# EXPERT Some environments require outbound HTTP traffic to go through a proxy
# server. Set the port number here (e.g: 8080).
# CAUTION This setting can be overridden by a PROXYPORT setting
# in TWikiPreferences. Make sure you delete the setting from there if you
# are using a TWikiPreferences topic from a previous release of TWiki.
$cfg{PROXY}{PORT} = '';
+#---+ Statistics
+
+# **NUMBER**
+# Number of top viewed topics to show in statistics topic
+$cfg{Stats}{TopViews} = 10;
+
+# **NUMBER**
+# Number of top contributors to show in statistics topic
+$cfg{Stats}{TopContrib} = 10;
+
+# **STRING 20**
+# EXPERT Name of statistics topic
+$cfg{Stats}{TopicName} = 'WebStatistics';
+
#---+ Miscellaneous settings
# **STRING 50**
-# Set to enable experimental mirror-site support. If this name is
+# EXPERT Set to enable experimental mirror-site support. If this name is
# different to MIRRORSITENAME, then this TWiki is assumed to be a
# mirror of another. You are highly recommended not
# to dabble with this experimental, undocumented, untested feature!
$cfg{SiteWebTopicName} = '';
# **STRING 20**
-# Name of site-level preferences topic in the {SystemWebName} web.
+# EXPERT Name of site-level preferences topic in the {SystemWebName} web.
# If you change this setting you will have to
# use TWiki and *manually* rename the existing topic.
# (i.e. don't change it unless you are certain that you know what
@@ -889,7 +915,7 @@
$cfg{SitePrefsTopicName} = 'TWikiPreferences';
# **STRING 40**
-# Web.TopicName of the site-level local preferences topic. If this topic
+# EXPERT Web.TopicName of the site-level local preferences topic. If this topic
# exists, any settings in it will override settings in
# {SitePrefsTopicName}.
# You are strongly recommended to keep all your local changes in
@@ -898,7 +924,7 @@
$cfg{LocalSitePreferences} = 'Main.TWikiPreferences';
# **STRING 20**
-# Name of main topic in a web.
+# EXPERT Name of main topic in a web.
# If you change this setting you will have to
# use TWiki to manually rename the topic in all existing webs
# (i.e. don't change it unless you are certain that you know what
@@ -906,31 +932,19 @@
$cfg{HomeTopicName} = 'WebHome';
# **STRING 20**
-# Name of preferences topic in a web.
+# EXPERT Name of preferences topic in a web.
# If you change this setting you will have to
# use TWiki to manually rename the topic in all existing webs
# (i.e. don't change it unless you are certain that you know what
# you are doing!)
$cfg{WebPrefsTopicName} = 'WebPreferences';
-# **STRING 20**
-# Name of statistics topic
-$cfg{Stats}{TopicName} = 'WebStatistics';
-
# **NUMBER**
-# Number of top viewed topics to show in statistics topic
-$cfg{Stats}{TopViews} = 10;
-
-# **NUMBER**
-# Number of top contributors to show in statistics topic
-$cfg{Stats}{TopContrib} = 10;
-
-# **NUMBER**
-# How many links to other revisions to show in the bottom bar. 0 for all
+# EXPERT How many links to other revisions to show in the bottom bar. 0 for all
$cfg{NumberOfRevisions} = 4;
# **NUMBER**
-# If this is set to a > 0 value, and the revision control system
+# EXPERT If this is set to a > 0 value, and the revision control system
# supports it (RCS does), then if a second edit of the same topic
# is done by the same user within this number of seconds, a new
# revision of the topic will NOT be created (the top revision will
@@ -939,7 +953,7 @@
$cfg{ReplaceIfEditedAgainWithin} = 3600;
# **NUMBER**
-# When a topic is edited, the user takes a "lease" on that topic.
+# EXPERT When a topic is edited, the user takes a "lease" on that topic.
# If another user tries to also edit the topic while the lease
# is still active, they will get a warning. Leases are released
# automatically when the topic is saved; otherwise they remain active
@@ -951,7 +965,7 @@
$cfg{LeaseLength} = 3600;
# **NUMBER**
-# Even if the other users' lease has expired, then you can specify that
+# EXPERT Even if the other users' lease has expired, then you can specify that
# they should still get a (less forceful) warning about the old lease for
# some additional time after the lease expired. You can set this to 0 to
# suppress these extra warnings completely, or to -1 so they are always
@@ -959,19 +973,19 @@
$cfg{LeaseLengthLessForceful} = 3600;
# **PATH**
-# Pathname to file that maps file suffixes to MIME types :
+# EXPERT Pathname to file that maps file suffixes to MIME types :
# For Apache server set this to Apache's mime.types file pathname,
# for example /etc/httpd/mime.types, or use the default shipped in
# the TWiki data directory.
$cfg{MimeTypesFileName} = "$dataDir/mime.types";
# **PATH**
-# Directory where registration approvals are held. Should be somewhere
+# EXPERT Directory where registration approvals are held. Should be somewhere
# that is not browsable from the web.
$cfg{RegistrationApprovals} = "$dataDir/RegistrationApprovals";
# **BOOLEAN**
-# If set, this will cause TWiki to treat warnings as errors that will
+# EXPERT If set, this will cause TWiki to treat warnings as errors that will
# cause TWiki to die. Provided for use by Plugin and Skin developers,
# who should develop with it switched on.
$cfg{WarningsAreErrors} = $FALSE;
Index: lib/TWiki/Attach.pm
===================================================================
--- lib/TWiki/Attach.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Attach.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::Attach
@@ -39,6 +39,7 @@
use TWiki::Attrs;
use TWiki::Store;
+use TWiki::Users;
use TWiki::User;
use TWiki::Prefs;
use TWiki::Meta;
@@ -89,7 +90,11 @@
my $rows = '';
my $row = $templates->expandTemplate('ATTACH:files:row'.$A);
- foreach my $attachment ( sort { $a->{date} <=> $b->{date} } @attachments ) {
+ # note: ($a->{date}||0) in case date field is not set. undef <=> undef
+ # seems to cause infinite looping in the sort Perl 5.6 uses :-(
+ foreach my $attachment (
+ sort { ($a->{date} || 0) <=> ($b->{date} || 0) }
+ @attachments ) {
my $attrAttr = $attachment->{attr};
if( ! $attrAttr || ( $showAttr && $attrAttr =~ /^[$showAttr]*$/ )) {
@@ -223,9 +228,12 @@
return TWiki::Time::formatTime( $info->{date} );
}
elsif ( $attr eq 'USER' ) {
- my( $w, $t ) = $this->{session}->normalizeWebTopicName(
- $TWiki::cfg{UsersWebName}, $info->{user} );
- return $w.'.'.$t;
+ my $user = $this->{session}->{users}->findUser($info->{user});
+ if (defined($user)) {
+ return $user->webDotWikiName();
+ } else {
+ return $info->{user};
+ }
}
else {
return "\0A_$attr\0";
Index: lib/TWiki/Upgrade/UpgradeToDakar.pm
===================================================================
--- lib/TWiki/Upgrade/UpgradeToDakar.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Upgrade/UpgradeToDakar.pm (.../DEVELOP) (revision 9301)
@@ -27,7 +27,7 @@
package TWiki::Upgrade::UpgradeToDakar;
-=begin twiki
+=pod
---+ UpgradeTwiki
Index: lib/TWiki/Client.pm
===================================================================
--- lib/TWiki/Client.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Client.pm (.../DEVELOP) (revision 9301)
@@ -181,19 +181,19 @@
if( $TWiki::cfg{Sessions}{MapIP2SID} ) {
# map the end user IP address to SID
my $sid = _IP2SID();
- if( $sid ) {
- $cgisession = CGI::Session->new(
- undef, $sid, { Directory => $TWiki::cfg{Sessions}{Dir} } );
- } else {
- $cgisession = CGI::Session->new(
- undef, undef,
- { Directory => $TWiki::cfg{Sessions}{Dir} } );
+ $cgisession = CGI::Session->new(
+ undef, $sid,
+ { Directory => $TWiki::cfg{Sessions}{Dir} } ) ||
+ die $CGI::Session::errstr;
+ unless( $sid ) {
+ # register the new IP->SID mapping
_IP2SID( $cgisession->id() );
}
} else {
$cgisession = CGI::Session->new(
undef, $query,
- { Directory => $TWiki::cfg{Sessions}{Dir} } );
+ { Directory => $TWiki::cfg{Sessions}{Dir} } ) ||
+ die $CGI::Session::errstr;;
}
$authUser ||= TWiki::Sandbox::untaintUnchecked(
Index: lib/TWiki/User.pm
===================================================================
--- lib/TWiki/User.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/User.pm (.../DEVELOP) (revision 9301)
@@ -22,6 +22,7 @@
use strict;
use Assert;
use TWiki;
+use Error qw( :try );
=pod
@@ -74,6 +75,7 @@
$this->{session} = $session;
$this->{login} = $name;
+# $this->{wikiname} = $wikiname;
my( $web, $topic ) =
$session->normalizeWebTopicName( $TWiki::cfg{UsersWebName}, $wikiname );
$this->{web} = $web;
@@ -101,13 +103,14 @@
---++ ObjectMethod webDotWikiName() -> $webDotWiki
Return the fully qualified wikiname of the user
+TODO: create a DisplayName function to allow the disablement of WikiWord user names
=cut
sub webDotWikiName {
my $this = shift;
ASSERT($this->isa( 'TWiki::User')) if DEBUG;
- return "$this->{web}.$this->{wikiname}";
+ return $this->web().'.'.$this->wikiName();
}
=pod
@@ -358,15 +361,16 @@
sub isAdmin {
my $this = shift;
ASSERT($this->isa( 'TWiki::User')) if DEBUG;
-
unless( $this->{isKnownAdmin} ) {
$this->{isKnownAdmin} =
$TWiki::cfg{SuperAdminGroup} =~ /\b$this->{wikiname}$/;
unless( $this->{isKnownAdmin} ) {
my $sag = $this->{session}->{users}->findUser(
- $TWiki::cfg{SuperAdminGroup} );
- ASSERT($sag->isa( 'TWiki::User')) if DEBUG;
- $this->{isKnownAdmin} = $this->isInList( $sag->groupMembers() );
+ $TWiki::cfg{SuperAdminGroup}, undef, 0 ); #we don't load the Admin group, users won't be
+ #recognized as being members of it,
+ #causing creating new webs and renaming
+ #old ones to fail
+ $this->{isKnownAdmin} = $this->isInList( $sag->groupMembers() ) if (defined($sag));
}
}
return $this->{isKnownAdmin};
@@ -386,11 +390,13 @@
#because we lazy load the groups, we can't make this conditional on
# the existance of some groups in the array.
- my @groupList = $this->{session}->{users}->_getListOfGroups();
+ my @groupList = $this->{session}->{users}->{usermappingmanager}->getListOfGroups();
foreach my $g (@groupList) {
my $groupObject = $this->{session}->{users}->findUser($g);
#simply calling isInList() will make sure the group added to $this->{groups}
- $this->isInList( $groupObject->groupMembers() );
+
+ ASSERT($groupObject->isGroup());
+ $groupObject->groupMembers();
}
return @{$this->{groups}};
@@ -446,6 +452,7 @@
return $this->wikiName() =~ /Group$/;
}
+
=pod
---++ ObjectMethod groupMembers() -> @members
@@ -458,31 +465,8 @@
sub groupMembers {
my $this = shift;
ASSERT($this->isa( 'TWiki::User')) if DEBUG;
- ASSERT( $this->isGroup()) if DEBUG;
- my $store = $this->{session}->{store};
-
- if( !defined $this->{members} &&
- $store->topicExists( $this->{web}, $this->{wikiname} )) {
- my $text =
- $store->readTopicRaw( undef,
- $this->{web}, $this->{wikiname},
- undef );
- foreach( split( /\r?\n/, $text ) ) {
- if( /$TWiki::regex{setRegex}GROUP\s*=\s*(.+)$/ ) {
- next unless( $1 eq 'Set' );
- # Note: if there are multiple GROUP assignments in the
- # topic, only the last will be taken.
- $this->{members} =
- $this->{session}->{users}->expandUserList( $2 );
- }
- }
- # backlink the user to the group
- foreach my $user ( @{$this->{members}} ) {
- push( @{$user->{groups}}, $this );
- }
- }
-
- return $this->{members};
+
+ return $this->{session}->{users}->{usermappingmanager}->groupMembers($this);
}
1;
Index: lib/TWiki/Render.pm
===================================================================
--- lib/TWiki/Render.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Render.pm (.../DEVELOP) (revision 9301)
@@ -761,6 +761,7 @@
$opt = ' target="_top"';
}
$text ||= $url;
+
# SMELL: Can't use CGI::a here, because it encodes ampersands in
# the link, and those have already been encoded once in the
# rendering loop (they are identified as "stand-alone"). One
@@ -793,6 +794,7 @@
my $formTopic = $params->{topic};
my $altText = $params->{alttext};
my $default = $params->{default};
+ my $rev = $params->{rev};
my $format = $params->{'format'};
unless ( $format ) {
@@ -824,7 +826,7 @@
unless ( $meta ) {
my $dummyText;
( $meta, $dummyText ) =
- $store->readTopic( $this->{session}->{user}, $formWeb, $formTopic, undef );
+ $store->readTopic( $this->{session}->{user}, $formWeb, $formTopic, $rev );
$this->{ffCache}{$formWeb.'.'.$formTopic} = $meta;
}
@@ -1566,11 +1568,11 @@
$un = $user->login();
}
- my $value = $format || 'r$rev - $time - $wikiusername';
+ my $value = $format || 'r$rev - $date - $time - $wikiusername';
$value =~ s/\$web/$web/gi;
$value =~ s/\$topic/$topic/gi;
$value =~ s/\$rev/$rev/gi;
- $value =~ s/\$time/TWiki::Time::formatTime($date)/gei;
+ $value =~ s/\$time/TWiki::Time::formatTime($date, '$hour:$min:$sec')/gei;
$value =~ s/\$date/TWiki::Time::formatTime($date, '$day $mon $year')/gei;
$value =~ s/\$comment/$comment/gi;
$value =~ s/\$username/$un/gi;
Index: lib/TWiki/Meta.pm
===================================================================
--- lib/TWiki/Meta.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Meta.pm (.../DEVELOP) (revision 9301)
@@ -499,11 +499,18 @@
my $s = '';
$types ||= qr/^[A-Z]+$/;
- foreach my $type ( grep { /$types/ } keys %$this ) {
+ foreach my $type ( grep { /$types/ } sort keys %$this ) {
foreach my $item ( @{$this->{$type}} ) {
- $s .= "$type: " .
- join(' ', map{ "$_='$item->{$_}'" } sort keys %$item ) .
- "\n";
+ $s .= $type.': ';
+ if( scalar(keys %$item )) {
+ my @vals;
+ foreach my $i ( sort keys %$item ) {
+ my $v = $item->{$i} || 'undefined';
+ push( @vals, $i.'="'.$v.'"' );
+ }
+ $s .= join(' ', @vals );
+ }
+ $s .= "\n";
}
}
return $s;
Index: lib/TWiki/Form.pm
===================================================================
--- lib/TWiki/Form.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Form.pm (.../DEVELOP) (revision 9301)
@@ -180,6 +180,8 @@
$vals =~ s/\s*$//go;
# SMELL: WTF is this??? This looks like a really bad hack!
+ #TODO: and slow too - compared to using the cache in TWiki::Users!
+ #TODO: this suggestes the need for a TWiki->{users}->getAllUsers()
if( $vals eq '$users' ) {
$vals = $TWiki::cfg{UsersWebName} . '.' .
join( ", ${TWiki::cfg{UsersWebName}}.",
@@ -439,12 +441,7 @@
-value => $value );
} elsif( $type eq 'label' ) {
- # Interesting question: if something is defined as "label",
- # could it be changed by applications or is the value
- # necessarily identical to what is in the form? If we can
- # take it from the text, we must be sure it cannot be
- # changed through the URL?
- # Pth: Changed labels through the URL is a feature for TWiki applications
+ # Changed labels through the URL is a feature for TWiki applications
my $renderedValue = $session->{renderer}->getRenderedVersion
( $session->handleCommonTags( $value, $web, $topic ));
$value = CGI::hidden( -name => $name,
Index: lib/TWiki/Net.pm
===================================================================
--- lib/TWiki/Net.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Net.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::Net
@@ -63,7 +63,6 @@
if( $port < 1 ) {
$port = 80;
}
- my $base64;
my $result = '';
$url = "/" unless( $url );
my $req = "GET $url HTTP/1.0\r\n";
@@ -74,7 +73,7 @@
# authentication
require MIME::Base64;
import MIME::Base64 ();
- $base64 = encode_base64( "$user:$pass", "\r\n" );
+ my $base64 = encode_base64( "$user:$pass", "\r\n" );
$req .= "Authorization: Basic $base64";
}
Index: lib/TWiki/Users/HtPasswdUser.pm
===================================================================
--- lib/TWiki/Users/HtPasswdUser.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Users/HtPasswdUser.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::Users::HtPasswdUser
Index: lib/TWiki/Users/Password.pm
===================================================================
--- lib/TWiki/Users/Password.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Users/Password.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::Users::Password
Index: lib/TWiki/Users/TWikiUserMapping.pm
===================================================================
--- lib/TWiki/Users/TWikiUserMapping.pm (.../TWikiRelease04x00) (revision 0)
+++ lib/TWiki/Users/TWikiUserMapping.pm (.../DEVELOP) (revision 9301)
@@ -0,0 +1,255 @@
+# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
+#
+# Copyright (C) 2006 Sven Dowideit, SvenDowideit@home.org.au
+# and TWiki Contributors. All Rights Reserved. TWiki Contributors
+# are listed in the AUTHORS file in the root of this distribution.
+# NOTE: Please extend that file, not this notice.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. For
+# more details read LICENSE in the root of this distribution.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# As per the GPL, removal of this notice is prohibited.
+
+=begin twiki
+
+---+ package TWiki::Users::TWikiUserMapping
+
+Base class of all user handlers. Default behaviour is to use TWiki Topics for user and group info
+
+The methods of this class should be overridded by subclasses that want
+to implement other user mapping handling methods.
+
+=cut
+
+package TWiki::Users::TWikiUserMapping;
+
+use strict;
+use strict;
+use Assert;
+use TWiki::User;
+use TWiki::Time;
+use Error qw( :try );
+
+=pod
+
+---++ ClassMethod new( $session ) -> $object
+
+Constructs a new password handler of this type, referring to $session
+for any required TWiki services.
+
+=cut
+
+sub new {
+ my( $class, $session ) = @_;
+
+ my $this = bless( {}, $class );
+ $this->{session} = $session;
+ return $this;
+}
+
+
+# callback for search function to collate results
+sub _collateGroups {
+ my $ref = shift;
+ my $group = shift;
+ push( @$ref, $group ) if $group;
+}
+
+# get a list of groups defined in this TWiki
+# TODO: i'm guessing a list of strings, Web.Topic even?
+sub getListOfGroups {
+ my $this = shift;
+ ASSERT($this->isa( 'TWiki::Users::TWikiUserMapping')) if DEBUG;
+
+ my @list;
+
+ $this->{session}->{search}->searchWeb
+ (
+ _callback => \&_collateGroups,
+ _cbdata => \@list,
+ inline => 1,
+ search => "Set GROUP =",
+ web => 'all',
+ topic => "*Group",
+ type => 'regex',
+ nosummary => 'on',
+ nosearch => 'on',
+ noheader => 'on',
+ nototal => 'on',
+ noempty => 'on',
+ format => "\$web.\$topic",
+ separator => '',
+ );
+
+ return @list;
+}
+
+=pod
+
+---++ ObjectMethod addUserToTWikiUsersTopic( $user ) -> $topicName
+
+Add a user to the TWikiUsers topic. This is a topic that
+maps from usernames to wikinames. It is maintained by
+Register.pm, or manually outside TWiki.
+
+=cut
+
+sub addUserToTWikiUsersTopic {
+ my ( $this, $user, $me ) = @_;
+
+ ASSERT($this->isa( 'TWiki::Users::TWikiUserMapping')) if DEBUG;
+ ASSERT($user->isa( 'TWiki::User')) if DEBUG;
+ ASSERT($me->isa( 'TWiki::User')) if DEBUG;
+
+ my $store = $this->{session}->{store};
+ my( $meta, $text ) =
+ $store->readTopic( undef, $TWiki::cfg{UsersWebName},
+ $TWiki::cfg{UsersTopicName}, undef );
+ my $result = '';
+ my $entry = "\t* ";
+ $entry .= $user->web()."."
+ unless $user->web() eq $TWiki::cfg{UsersWebName};
+ $entry .= $user->wikiName()." - ";
+ $entry .= $user->login() . " - " if $user->login();
+ my $today = TWiki::Time::formatTime(time(), '$day $mon $year', 'gmtime');
+
+ # add to the cache
+ $this->{session}->{users}->{U2W}{$user->login()} = $user->{web} . "." . $user->wikiName();
+
+ # add name alphabetically to list
+ foreach my $line ( split( /\r?\n/, $text) ) {
+ # TODO: I18N fix here once basic auth problem with 8-bit user names is
+ # solved
+ if ( $entry ) {
+ my ( $web, $name, $odate ) = ( '', '', '' );
+ if ( $line =~ /^\s+\*\s($TWiki::regex{webNameRegex}\.)?($TWiki::regex{wikiWordRegex})\s*(?:-\s*\w+\s*)?-\s*(.*)/ ) {
+ $web = $1 || $TWiki::cfg{UsersWebName};
+ $name = $2;
+ $odate = $3;
+ } elsif ( $line =~ /^\s+\*\s([A-Z]) - / ) {
+ # * A - - - - -^M
+ $name = $1;
+ }
+ if( $name && ( $user->wikiName() le $name ) ) {
+ # found alphabetical position
+ if( $user->wikiName() eq $name ) {
+ # adjusting existing user - keep original registration date
+ $entry .= $odate;
+ } else {
+ $entry .= $today."\n".$line;
+ }
+ # don't adjust if unchanged
+ return $TWiki::cfg{UsersTopicName} if( $entry eq $line );
+ $line = $entry;
+ $entry = '';
+ }
+ }
+
+ $result .= $line."\n";
+ }
+ if( $entry ) {
+ # brand new file - add to end
+ $result .= "$entry$today\n";
+ }
+ $store->saveTopic( $me, $TWiki::cfg{UsersWebName},
+ $TWiki::cfg{UsersTopicName},
+ $result, $meta );
+
+ return $TWiki::cfg{UsersTopicName};
+}
+
+# Build hash to translate between username (e.g. jsmith)
+# and WikiName (e.g. Main.JaneSmith). Only used for sites where
+# authentication is managed by external Apache configuration, instead of
+# via TWiki's .htpasswd mechanism.
+sub cacheTWikiUsersTopic {
+ my $this = shift;
+ ASSERT($this->isa( 'TWiki::Users::TWikiUserMapping')) if DEBUG;
+
+ return if $this->{session}->{users}->{CACHED};
+ $this->{session}->{users}->{CACHED} = 1;
+
+ %{$this->{session}->{users}->{U2W}} = ();
+ %{$this->{session}->{users}->{W2U}} = ();
+
+ my $text;
+ my $store = $this->{session}->{store};
+ if( $TWiki::cfg{MapUserToWikiName} &&
+ $store->topicExists($TWiki::cfg{UsersWebName},
+ $TWiki::cfg{UsersTopicName} )) {
+ $text = $store->readTopicRaw( undef,
+ $TWiki::cfg{UsersWebName},
+ $TWiki::cfg{UsersTopicName},
+ undef );
+ } else {
+ # fix for Codev.SecurityAlertGainAdminRightWithTWikiUsersMapping
+ # map only guest to TWikiGuest. CODE_SMELL on localization
+ $text = "\t* $TWiki::cfg{DefaultUserWikiName} - $TWiki::cfg{DefaultUserLogin} - 01 Apr 1970";
+ }
+
+ my $wUser;
+ my $lUser;
+ # Get the WikiName and userid, and build hashes in both directions
+ # This matches:
+ # * TWikiGuest - guest - 10 Mar 2005
+ # * TWikiGuest - 10 Mar 2005
+ while( $text =~ s/^\s*\* ($TWiki::regex{webNameRegex}\.)?(\w+)\s*(?:-\s*(\S+)\s*)?-\s*\d+ \w+ \d+\s*$//om ) {
+ my $web = $1 || $TWiki::cfg{UsersWebName};
+ $wUser = $2; # WikiName
+ $lUser = $3 || $wUser; # userid
+ $lUser =~ s/$TWiki::cfg{NameFilter}//go; # FIXME: Should filter in for security...
+ my $wwn = $web.'.'.$wUser;
+ $this->{session}->{users}->{U2W}{$lUser} = $wwn;
+ $this->{session}->{users}->{W2U}{$wwn} = $lUser;
+ }
+}
+
+=pod
+
+---++ ObjectMethod groupMembers($group) -> @members
+
+Return a list of user objects that are members of this group. Should only be
+called on groups.
+
+=cut
+
+sub groupMembers {
+ my $this = shift;
+ my $group = shift;
+ ASSERT($this->isa( 'TWiki::Users::TWikiUserMapping')) if DEBUG;
+ ASSERT($group->isa( 'TWiki::User')) if DEBUG;
+ ASSERT( $group->isGroup()) if DEBUG;
+ my $store = $this->{session}->{store};
+
+ if( !defined $group->{members} &&
+ $store->topicExists( $group->{web}, $group->{wikiname} )) {
+ my $text =
+ $store->readTopicRaw( undef,
+ $group->{web}, $group->{wikiname},
+ undef );
+ foreach( split( /\r?\n/, $text ) ) {
+ if( /$TWiki::regex{setRegex}GROUP\s*=\s*(.+)$/ ) {
+ next unless( $1 eq 'Set' );
+ # Note: if there are multiple GROUP assignments in the
+ # topic, only the last will be taken.
+ $group->{members} =
+ $this->{session}->{users}->expandUserList( $2 );
+ }
+ }
+ # backlink the user to the group
+ foreach my $user ( @{$group->{members}} ) {
+ push( @{$user->{groups}}, $group );
+ }
+ }
+
+ return $group->{members};
+}
+
+1;
Index: lib/TWiki/Store.pm
===================================================================
--- lib/TWiki/Store.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Store.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::Store
@@ -76,12 +76,6 @@
$this->{session} = $session;
- $this->{IMPL} = 'TWiki::Store::'.$TWiki::cfg{StoreImpl};
- eval 'use '.$this->{IMPL};
- if( $@ ) {
- die "$this->{IMPL} compile failed $@";
- }
-
return $this;
}
@@ -91,7 +85,13 @@
sub _getHandler {
my( $this, $web, $topic, $attachment ) = @_;
- return $this->{IMPL}->new( $this->{session}, $web, $topic, $attachment );
+ my $impl = $TWiki::cfg{Store}{$web};
+ $impl = 'TWiki::Store::'.$TWiki::cfg{StoreImpl} unless( $impl );
+ # Note: can't just 'require' because @INC isn't right at compilation time
+ eval "require $impl";
+ die $@ if $@;
+
+ return $impl->new( $this->{session}, $web, $topic, $attachment );
}
=pod
@@ -102,9 +102,6 @@
is undef, then read the most recent version. The version number must be
an integer, or undef for the latest version.
-Earlier argument syntax for $version; 1.x (Cairo and earlier)
-is also supported, but is to be deprecated.
-
if $user is defined, view permission will be required for the topic
read to be successful. Access control violations are flagged by a
TWiki::AccessControlException. Permissions are checked for the user
@@ -123,9 +120,8 @@
ASSERT($this->isa('TWiki::Store')) if DEBUG;
$web =~ s#\.#/#go;
- # Cairo compatibility for rev="1.x"-style arguments in %INCLUDEs
if (defined $version) {
- $version =~ s/^1\.//go;
+ $version = $this->cleanUpRevID( $version );
}
my $text = $this->readTopicRaw( $user, $web, $topic, $version );
Index: lib/TWiki/Templates.pm
===================================================================
--- lib/TWiki/Templates.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Templates.pm (.../DEVELOP) (revision 9301)
@@ -208,7 +208,6 @@
sub readTemplate {
my( $this, $name, $skins, $web ) = @_;
ASSERT($this->isa( 'TWiki::Templates')) if DEBUG;
-
$this->{files} = ();
# recursively read template file(s)
@@ -221,46 +220,41 @@
# Kill comments, marked by %{ ... }%
$text =~ s/%{.*?}%//sg;
- if( ! ( $text =~ /%TMPL\:/s ) ) {
- # no template processing
- $text =~ s|^(( {3})+)|"\t" x (length($1)/3)|geom; # leading spaces to tabs
- return $text;
- }
-
my $result = '';
- my $key = '';
- my $val = '';
- my $delim = '';
- foreach( split( /(%TMPL\:)/, $text ) ) {
- if( /^(%TMPL\:)$/ ) {
- $delim = $1;
- } elsif( ( /^DEF{[\s\"]*(.*?)[\"\s]*}%[\n\r]*(.*)/s ) && ( $1 ) ) {
- # handle %TMPL:DEF{key}%
- if( $key ) {
+ if( $text =~ /%TMPL\:/s ) {
+ my $key = '';
+ my $val = '';
+ my $delim = '';
+ foreach( split( /(%TMPL\:)/, $text ) ) {
+ if( /^(%TMPL\:)$/ ) {
+ $delim = $1;
+ } elsif( ( /^DEF{[\s\"]*(.*?)[\"\s]*}%(.*)/s ) && ( $1 ) ) {
+ # handle %TMPL:DEF{key}%
+ if( $key ) {
+ $this->{VARS}->{$key} = $val;
+ }
+ $key = $1;
+ $val = $2;
+ } elsif( /^END%[\n\r]*(.*)/s ) {
+ die "Encountered TMPL:END with no corresponding TMPL:DEF near\n$result\nin$text\n"
+ unless ($key);
+ # handle %TMPL:END%
$this->{VARS}->{$key} = $val;
+ $key = undef;
+ $val = '';
+ $result .= $1;
+ } elsif( $key ) {
+ $val .= $delim.$_;
+ } else {
+ $result .= $delim.$_;
}
- $key = $1;
- $val = $2;
-
- } elsif( /^END%[\n\r]*(.*)/s ) {
- # handle %TMPL:END%
- $this->{VARS}->{$key} = $val;
- $key = '';
- $val = '';
- $result .= $1;
-
- } elsif( $key ) {
- $val .= "$delim$_";
-
- } else {
- $result .= "$delim$_";
}
+ # handle %TMPL:P{"..."}% recursively
+ $result =~ s/(%TMPL\:P{.*?}%)/$this->_expandTrivialTemplate($1)/geo;
+ } else {
+ # no template processing
+ $result = $text;
}
-
- # handle %TMPL:P{"..."}% recursively
- $result =~ s/(%TMPL\:P{.*?}%)/$this->_expandTrivialTemplate($1)/geo;
-
- $result =~ s|^(( {3})+)|"\t" x (length($1)/3)|geom; # leading spaces to tabs
return $result;
}
@@ -283,7 +277,7 @@
# if the name ends in .tmpl, then this is an explicit include from
# the templates directory. No further searching required.
if( $name =~ /\.tmpl$/ ) {
- return TWiki::readFile( $TWiki::cfg{TemplateDir}.'/'.$name );
+ return _retrieveFile( $TWiki::cfg{TemplateDir}.'/'.$name );
}
my @skinList = split( /\,\s*/, $skins );
@@ -294,11 +288,11 @@
foreach my $skin ( @skinList ) {
foreach my $tmplDir ( "$TWiki::cfg{TemplateDir}/$web",
$TWiki::cfg{TemplateDir} ) {
- my $file=$tmplDir."/$name.$skin.tmpl";
+ my $file = $tmplDir."/$name.$skin.tmpl";
my $candidate;
- $candidate->{name}=$file;
- $candidate->{validate} = \&validateFile;
- $candidate->{retrieve} = \&TWiki::readFile;
+ $candidate->{name} = $file;
+ $candidate->{validate} = \&_validateFile;
+ $candidate->{retrieve} = \&_retrieveFile;
push @candidates, $candidate;
}
@@ -307,11 +301,11 @@
# now search the web dir and the root dir for the unskinned version
foreach my $tmplDir ( "$TWiki::cfg{TemplateDir}/$web",
$TWiki::cfg{TemplateDir} ) {
- my $file=$tmplDir."/$name.tmpl";
+ my $file = $tmplDir."/$name.tmpl";
my $candidate;
- $candidate->{name}=$file;
- $candidate->{validate} = \&validateFile;
- $candidate->{retrieve} = \&TWiki::readFile;
+ $candidate->{name} = $file;
+ $candidate->{validate} = \&_validateFile;
+ $candidate->{retrieve} = \&_retrieveFile;
push @candidates, $candidate;
}
@@ -324,13 +318,13 @@
$candidate->{name} = $web.'.'.$topic;
$candidate->{validate} =
sub {
- return validateTopic(
+ return _validateTopic(
$session, $store,
$session->{user}, $topic, $web)
};
$candidate->{retrieve} =
sub {
- return retrieveTopic($store, $web, $topic)
+ return _retrieveTopic($store, $web, $topic)
};
push @candidates, $candidate;
@@ -350,7 +344,7 @@
$candidate->{name} = $lookWeb.'.'.$skintopic;
$candidate->{validate} =
sub {
- return validateTopic($session,
+ return _validateTopic($session,
$store,
$session->{user},
$skintopic,
@@ -358,16 +352,16 @@
};
$candidate->{retrieve} =
sub {
- return retrieveTopic( $store, $lookWeb, $skintopic)
+ return _retrieveTopic( $store, $lookWeb, $skintopic)
};
push @candidates, $candidate;
}
my $candidate;
- $candidate->{name}=$lookWeb.'.'.$ttopic;
+ $candidate->{name} = $lookWeb.'.'.$ttopic;
$candidate->{validate} =
sub {
- return validateTopic($session,
+ return _validateTopic($session,
$store,
$session->{user},
$ttopic,
@@ -375,7 +369,7 @@
};
$candidate->{retrieve} =
sub {
- return retrieveTopic( $store, $lookWeb, $ttopic )
+ return _retrieveTopic( $store, $lookWeb, $ttopic )
};
push @candidates, $candidate;
@@ -390,29 +384,32 @@
}
}
- # SMELL: should really
+ # Uncomment this to debug templates
#throw Error::Simple( 'Template '.$name.' was not found' );
- # instead of
- #print STDERR "Template $name could not be found anywhere\n";
- #Is Failing Silently the best option here?
+
return '';
}
-sub validateFile {
+sub _validateFile {
my $file = shift;
return -e $file;
}
-sub validateTopic {
+sub _validateTopic {
my( $session, $store, $user, $topic, $web ) = @_;
return $store->topicExists( $web, $topic ) &&
$session->{security}->checkAccessPermission ('view', $user, undef, $topic, $web );
}
-sub retrieveTopic {
+sub _retrieveTopic {
my( $store, $web, $topic ) = @_;
my ( $meta, $text ) = $store->readTopic( undef, $web, $topic, undef );
return $text;
}
+sub _retrieveFile {
+ my $name = shift;
+ return TWiki::readFile( $name );
+}
+
1;
Index: lib/TWiki/Sandbox.pm
===================================================================
--- lib/TWiki/Sandbox.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Sandbox.pm (.../DEVELOP) (revision 9301)
@@ -378,8 +378,6 @@
open( STDERR, '>&OLDERR' ) || die "Can't restore STDERR: $!";
close(OLDERR);
$exit = ( $? >> 8 );
- # Do *not* return the error message; it contains sensitive path info.
- print STDERR "$cmd failed: $!" if $exit;
}
if( $this->{TRACE} ) {
Index: lib/TWiki/Users.pm
===================================================================
--- lib/TWiki/Users.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/Users.pm (.../DEVELOP) (revision 9301)
@@ -31,6 +31,7 @@
use Assert;
use TWiki::User;
use TWiki::Time;
+use Error qw( :try );
BEGIN {
# Do a dynamic 'use locale' for this module
@@ -54,12 +55,21 @@
$this->{session} = $session;
- my $impl = $TWiki::cfg{PasswordManager};
- $impl = 'TWiki::Users::Password' if( $impl eq 'none' );
- eval "use $impl";
+ my $implPasswordManager = $TWiki::cfg{PasswordManager};
+ $implPasswordManager = 'TWiki::Users::Password' if( $implPasswordManager eq 'none' );
+ eval "use $implPasswordManager";
die "Password Manager: $@" if $@;
- $this->{passwords} = $impl->new( $session );
+ $this->{passwords} = $implPasswordManager->new( $session );
+ my $implUserMappingManager = $TWiki::cfg{UserMappingManager};
+ $implUserMappingManager = 'TWiki::Users::TWikiUserMapping' if( $implUserMappingManager eq 'none' );
+ eval "use $implUserMappingManager";
+ die "User Mapping Manager: $@" if $@;
+ $this->{usermappingmanager} = $implUserMappingManager->new( $session );
+
+ $this->{login} = {};
+ $this->{wikiname} = {};
+
$this->{CACHED} = 0;
# create the guest user
@@ -69,39 +79,23 @@
return $this;
}
-# get a list of groups defined in this TWiki
-sub _getListOfGroups {
+#returns a ref to an array of all group objects found.
+sub getAllGroups() {
my $this = shift;
ASSERT($this->isa( 'TWiki::Users')) if DEBUG;
-
- my @list;
- $this->{session}->{search}->searchWeb
- (
- _callback => \&_collateGroups,
- _cbdata => \@list,
- inline => 1,
- search => "Set GROUP =",
- web => 'all',
- topic => "*Group",
- type => 'regex',
- nosummary => 'on',
- nosearch => 'on',
- noheader => 'on',
- nototal => 'on',
- noempty => 'on',
- format => "\$web.\$topic",
- separator => '',
- );
-
- return @list;
+
+ unless (defined($this->{grouplist})) {
+ $this->{grouplist} = [];
+ my @groupList = $this->{usermappingmanager}->getListOfGroups();
+ foreach my $g (@groupList) {
+ my $groupObject = $this->findUser($g);
+ push (@{$this->{grouplist}}, $groupObject);
+ }
+ }
+
+ return @{$this->{grouplist}};
}
-# callback for search function to collate results
-sub _collateGroups {
- my $ref = shift;
- my $group = shift;
- push( @$ref, $group ) if $group;
-}
# Get a list of user objects from a text string containing a
# list of user names. Used by User.pm
@@ -225,131 +219,19 @@
my( $this, $name, $wikiname ) = @_;
my $object = new TWiki::User( $this->{session}, $name, $wikiname );
- $this->{login}{$name} = $object;
- $this->{wikiname}{$object->webDotWikiName()} = $object;
+ if ( defined ($object) ) {
+ $this->{login}{$object->login()} = $object;
+ $this->{wikiname}{$object->webDotWikiName()} = $object;
+ }
return $object;
}
-=pod
-
----++ ObjectMethod addUserToTWikiUsersTopic( $user ) -> $topicName
-
-Add a user to the TWikiUsers topic. This is a topic that
-maps from usernames to wikinames. It is maintained by
-Register.pm, or manually outside TWiki.
-
-=cut
-
sub addUserToTWikiUsersTopic {
my ( $this, $user, $me ) = @_;
-
- ASSERT($this->isa( 'TWiki::Users')) if DEBUG;
- ASSERT($user->isa( 'TWiki::User')) if DEBUG;
- ASSERT($me->isa( 'TWiki::User')) if DEBUG;
-
- my $store = $this->{session}->{store};
- my( $meta, $text ) =
- $store->readTopic( undef, $TWiki::cfg{UsersWebName},
- $TWiki::cfg{UsersTopicName}, undef );
- my $result = '';
- my $entry = "\t* ";
- $entry .= $user->web()."."
- unless $user->web() eq $TWiki::cfg{UsersWebName};
- $entry .= $user->wikiName()." - ";
- $entry .= $user->login() . " - " if $user->login();
- my $today = TWiki::Time::formatTime(time(), '$day $mon $year', 'gmtime');
-
- # add to the cache
- $this->{U2W}{$user->login()} = $user->{web} . "." . $user->wikiName();
-
- # add name alphabetically to list
- foreach my $line ( split( /\r?\n/, $text) ) {
- # TODO: I18N fix here once basic auth problem with 8-bit user names is
- # solved
- if ( $entry ) {
- my ( $web, $name, $odate ) = ( '', '', '' );
- if ( $line =~ /^\s+\*\s($TWiki::regex{webNameRegex}\.)?($TWiki::regex{wikiWordRegex})\s*(?:-\s*\w+\s*)?-\s*(.*)/ ) {
- $web = $1 || $TWiki::cfg{UsersWebName};
- $name = $2;
- $odate = $3;
- } elsif ( $line =~ /^\s+\*\s([A-Z]) - / ) {
- # * A - - - - -^M
- $name = $1;
- }
- if( $name && ( $user->wikiName() le $name ) ) {
- # found alphabetical position
- if( $user->wikiName() eq $name ) {
- # adjusting existing user - keep original registration date
- $entry .= $odate;
- } else {
- $entry .= $today."\n".$line;
- }
- # don't adjust if unchanged
- return $TWiki::cfg{UsersTopicName} if( $entry eq $line );
- $line = $entry;
- $entry = '';
- }
- }
-
- $result .= $line."\n";
- }
- if( $entry ) {
- # brand new file - add to end
- $result .= "$entry$today\n";
- }
- $store->saveTopic( $me, $TWiki::cfg{UsersWebName},
- $TWiki::cfg{UsersTopicName},
- $result, $meta );
-
- return $TWiki::cfg{UsersTopicName};
+ return $this->{usermappingmanager}->addUserToTWikiUsersTopic($user, $me);
}
-# Build hash to translate between username (e.g. jsmith)
-# and WikiName (e.g. Main.JaneSmith). Only used for sites where
-# authentication is managed by external Apache configuration, instead of
-# via TWiki's .htpasswd mechanism.
-sub _cacheTWikiUsersTopic {
- my $this = shift;
- ASSERT($this->isa( 'TWiki::Users')) if DEBUG;
-
- return if $this->{CACHED};
- $this->{CACHED} = 1;
-
- %{$this->{U2W}} = ();
- %{$this->{W2U}} = ();
- my $text;
- my $store = $this->{session}->{store};
- if( $TWiki::cfg{MapUserToWikiName} &&
- $store->topicExists($TWiki::cfg{UsersWebName},
- $TWiki::cfg{UsersTopicName} )) {
- $text = $store->readTopicRaw( undef,
- $TWiki::cfg{UsersWebName},
- $TWiki::cfg{UsersTopicName},
- undef );
- } else {
- # fix for Codev.SecurityAlertGainAdminRightWithTWikiUsersMapping
- # map only guest to TWikiGuest. CODE_SMELL on localization
- $text = "\t* $TWiki::cfg{DefaultUserWikiName} - $TWiki::cfg{DefaultUserLogin} - 01 Apr 1970";
- }
-
- my $wUser;
- my $lUser;
- # Get the WikiName and userid, and build hashes in both directions
- # This matches:
- # * TWikiGuest - guest - 10 Mar 2005
- # * TWikiGuest - 10 Mar 2005
- while( $text =~ s/^\s*\* ($TWiki::regex{webNameRegex}\.)?(\w+)\s*(?:-\s*(\S+)\s*)?-\s*\d+ \w+ \d+\s*$//om ) {
- my $web = $1 || $TWiki::cfg{UsersWebName};
- $wUser = $2; # WikiName
- $lUser = $3 || $wUser; # userid
- $lUser =~ s/$TWiki::cfg{NameFilter}//go; # FIXME: Should filter in for security...
- my $wwn = $web.'.'.$wUser;
- $this->{U2W}{$lUser} = $wwn;
- $this->{W2U}{$wwn} = $lUser;
- }
-}
-
=pod
---++ ObjectMethod initializeRemoteUser( $remoteUser ) -> $loginName
@@ -387,7 +269,7 @@
return undef unless $loginUser;
- $this->_cacheTWikiUsersTopic();
+ $this->{usermappingmanager}->cacheTWikiUsersTopic();
$loginUser =~ s/$TWiki::cfg{NameFilter}//go;
return $this->{U2W}{$loginUser};
@@ -400,7 +282,7 @@
return undef unless $wikiName;
- $this->_cacheTWikiUsersTopic();
+ $this->{usermappingmanager}->cacheTWikiUsersTopic();
$wikiName =~ s/$TWiki::cfg{NameFilter}//go;
$wikiName = "$TWiki::cfg{UsersWebName}.$wikiName"
@@ -409,4 +291,16 @@
return $this->{W2U}{$wikiName};
}
+sub getAllLoadedUsers {
+ my( $this ) = @_;
+
+ my @list = ();
+ foreach my $key (keys(%{$this->{wikiname}})) {
+ my $u = $this->{wikiname}{$key};
+ push(@list, $u);
+ }
+
+ return sort(@list);
+}
+
1;
Index: lib/TWiki/UI/Register.pm
===================================================================
--- lib/TWiki/UI/Register.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Register.pm (.../DEVELOP) (revision 9301)
@@ -79,24 +79,24 @@
my $action = $session->{cgiQuery}->param('action') || '';
if ($action eq 'register') {
- registerAndNext($session, $tempUserDir);
+ _registerAndNext($session, $tempUserDir);
}
elsif ($action eq 'verify') {
- verifyEmailAddress( $session, $tempUserDir );
+ _verifyEmailAddress( $session, $tempUserDir );
if ($needApproval) {
throw Error::Simple('Approval code has not been written!');
}
- finish( $session, $tempUserDir);
+ _finish( $session, $tempUserDir);
}
elsif ($action eq 'resetPassword') {
#SMELL - is this still called here, or only by passwd?
- resetPassword( $session );
+ _resetPassword( $session );
}
elsif ($action eq 'approve') {
- finish($session, $tempUserDir );
+ _finish($session, $tempUserDir );
}
else {
- registerAndNext($session, $tempUserDir);
+ _registerAndNext($session, $tempUserDir);
}
$session->leaveContext('absolute_urls');
@@ -135,7 +135,7 @@
changePassword( $session );
}
elsif ( $action eq 'resetPassword' ) {
- resetPassword( $session );
+ _resetPassword( $session );
}
else {
throw TWiki::OopsException( 'attention',
@@ -271,6 +271,7 @@
my $doOverwriteTopics = defined $settings->{doOverwriteTopics} ||
throw Error::Simple( 'No doOverwriteTopics' );
my $log;
+
#-- call to the registrationHandler (to amend fields) should
# really happen in here.
@@ -281,6 +282,9 @@
$row->{LoginName}."\n";
}
+ my $template = $row->{Template};
+ $template ||= 'NewUserTemplate';
+
#-- Ensure every required field exists
# NB. LoginName is OPTIONAL
my @requiredFields = qw(WikiName FirstName LastName);
@@ -303,7 +307,7 @@
$row->{Email}, $row->{WikiName} );
if( $doOverwriteTopics or !$session->{store}->topicExists( $row->{webName}, $row->{WikiName} ) ) {
- $log .= _newUserFromTemplate($session, 'NewUserTemplate', $row);
+ $log .= _newUserFromTemplate($session, $template, $row);
} else {
$log .= $b.' Not writing topic '.$row->{WikiName}."\n";
}
@@ -352,40 +356,25 @@
return @form;
}
-=pod
+# This is called when action = register or action = ""
+# It calls register and either Verify or Finish.
+# Hopefully we will get workflow integrated and rewrite this to be table driven
----++ StaticMethod registerAndNext($session, $tempUserDir)
-
-This is called when action = register or action = ""
-
-It calls register and either Verify or Finish.
-
-Hopefully we will get workflow integrated and rewrite this to be table driven
-
-=cut
-
-sub registerAndNext {
- my ($session, $tempUserDir) = @_;
- register( $session );
- if ($TWiki::cfg{Register}{NeedVerification}) {
- _requireVerification($session, $tempUserDir);
- } else {
- finish($session);
- }
+sub _registerAndNext {
+ my ($session, $tempUserDir) = @_;
+ _register( $session );
+ if ($TWiki::cfg{Register}{NeedVerification}) {
+ _requireVerification($session, $tempUserDir);
+ } else {
+ _finish($session);
+ }
}
-=pod
+# This is called through: TWikiRegistration -> RegisterCgiScript -> here
+# 1 gets rows and fields from the query
+# 2 calls _validateRegistration() to ensure required fields correct, else OopsException
----++ StaticMethod register($session)
-
-This is called through: TWikiRegistration -> RegisterCgiScript -> here
-
- 1 gets rows and fields from the query
- 2 calls _validateRegistration() to ensure required fields correct, else OopsException
-
-=cut
-
-sub register {
+sub _register {
my( $session ) = @_;
my $query = $session->{cgiQuery};
@@ -437,16 +426,10 @@
params => $data->{Email} );
}
-=pod
+# Generates a password. Mails it to them and asks them to change it. Entry
+# point intended to be called from TWiki::UI::run
----++ StaticMethod resetPassword($session)
-
-Generates a password. Mails it to them and asks them to change it. Entry
-point intended to be called from TWiki::UI::run
-
-=cut
-
-sub resetPassword {
+sub _resetPassword {
my $session = shift;
my $query = $session->{cgiQuery};
my $topic = $session->{topicName};
@@ -511,7 +494,7 @@
sub _resetUsersPassword {
my( $session, $userName, $introduction, $pMess ) = @_;
- my $user = $session->{users}->findUser( $userName, undef);
+ my $user = $session->{users}->findUser( $userName, undef, 1 );
unless( $user ) {
# couldn't work out who they are, its neither loginName nor
# wikiName.
@@ -522,7 +505,7 @@
my $email = $em[0];
unless ($email) {
$$pMess .= $session->inlineAlert( 'alerts', 'no_email_for',
- $user->stringify());
+ $user->wikiName());
return 0;
}
@@ -530,7 +513,7 @@
unless( $user->passwordExists() ) {
# Not an error.
$$pMess .= $session->inlineAlert( 'alerts', 'missing_user',
- $user->stringify());
+ $user->wikiName());
}
my $password = $user->resetPassword();
@@ -678,19 +661,13 @@
}
-=pod
+# This is called: on receipt of the activation password -> RegisterCgiScript -> here
+# 1 calls _reloadUserContext(activation password)
+# 2 throws oops if appropriate
+# 3 calls emailRegistrationConfirmations
+# 4 still calls 'oopssendmailerr' if a problem, but this is not done uniformly
----++ StaticMethod verifyEmailAddress($session, $tempUserDir)
-
-This is called: on receipt of the activation password -> RegisterCgiScript -> here
- 1 calls _reloadUserContext(activation password)
- 2 throws oops if appropriate
- 3 calls emailRegistrationConfirmations
- 4 still calls 'oopssendmailerr' if a problem, but this is not done uniformly
-
-=cut
-
-sub verifyEmailAddress {
+sub _verifyEmailAddress {
my( $session, $tempUserDir ) = @_;
my $code = $session->{cgiQuery}->param('code');
@@ -710,25 +687,19 @@
}
-=pod
+# Presently this is called in RegisterCgiScript directly after a call to verify. The separation is intended for the RegistrationApprovals functionality
+# 1 calls _reloadUserContext (throws oops if appropriate)
+# 3 calls newUserFromTemplate()
+# 4 if using the htpasswdFormatFamily, calls _addUserToPasswordSystem
+# 5 calls the misnamed RegistrationHandler to set cookies
+# 6 calls addUserToTWikiUsersTopic
+# 7 writes the logEntry (if wanted :/)
+# 8 redirects browser to 'oopsregthanks'
+#
+# reloads the context by code
+# these two are separate in here to ease the implementation of administrator approval
----++ StaticMethod finish
-
-Presently this is called in RegisterCgiScript directly after a call to verify. The separation is intended for the RegistrationApprovals functionality
- 1 calls _reloadUserContext (throws oops if appropriate)
- 3 calls newUserFromTemplate()
- 4 if using the htpasswdFormatFamily, calls _addUserToPasswordSystem
- 5 calls the misnamed RegistrationHandler to set cookies
- 6 calls addUserToTWikiUsersTopic
- 7 writes the logEntry (if wanted :/)
- 8 redirects browser to 'oopsregthanks'
-
-reloads the context by code
-these two are separate in here to ease the implementation of administrator approval
-
-=cut
-
-sub finish {
+sub _finish {
my( $session, $tempUserDir) = @_;
my $topic = $session->{topicName};
@@ -833,8 +804,8 @@
# TODO - there should be some way of overwriting meta without
# blatting the content.
-
my( $before, $repeat, $after ) = split( /%SPLIT%/, $text, 3 );
+
$before = '' unless defined( $before );
$repeat = "\n".' * %KEY%: %VALUE%' unless defined( $repeat );
$after = "\n".' * Set ALLOWTOPICCHANGE = %WIKIUSERNAME%'."\n" unless defined( $after );
@@ -880,8 +851,19 @@
sub _getKeyValuePairsAsTopicForm {
my ($meta, @fieldArray) = @_; # SMELL - why is this an array? surely a hash is better?
my $leftoverText = '';
+
+ my $usesCustomTemplate;
+
foreach my $fd (@fieldArray) {
my $name = $fd->{name};
+
+ if ($usesCustomTemplate = ($name eq 'Template')) {
+ last;
+ }
+ }
+
+ foreach my $fd (@fieldArray) {
+ my $name = $fd->{name};
my $value = $fd->{value};
my $title = $name;
$title =~ s/([a-z0-9])([A-Z0-9])/$1 $2/go; # Spaced
@@ -899,9 +881,11 @@
if ( $name eq 'Email' ) {
# Don't paste the e-mail address in the user topic (prevent e-mail harvesting)
# $leftoverText .= "\t* E-mail: $value\n";
- } else {
- $meta->putKeyed( 'FIELD',
+ } elsif ($value || !$usesCustomTemplate) {
+ if ($name ne 'Template') {
+ $meta->putKeyed( 'FIELD',
{ name => $name, value => $value, title => $title } );
+ }
}
#### end workaround SMELL
}
Index: lib/TWiki/UI/Upload.pm
===================================================================
--- lib/TWiki/UI/Upload.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Upload.pm (.../DEVELOP) (revision 9301)
@@ -110,11 +110,11 @@
}
$tmpl =~ s/%ATTACHTABLE%/$atext/go;
$tmpl =~ s/%FILEUSER%/$fileWikiUser/go;
+ $tmpl =~ s/%FILENAME%/$fileName/go;
$session->enterContext( 'can_render_meta', $meta );
$tmpl = $session->handleCommonTags( $tmpl, $webName, $topic );
$tmpl = $session->{renderer}->getRenderedVersion( $tmpl, $webName, $topic );
$tmpl =~ s/%HIDEFILE%/$isHideChecked/go;
- $tmpl =~ s/%FILENAME%/$fileName/go;
$tmpl =~ s/%FILEPATH%/$args->{path}/go;
$args->{comment} = TWiki::entityEncode( $args->{comment} );
$tmpl =~ s/%FILECOMMENT%/$args->{comment}/go;
@@ -262,4 +262,3 @@
}
1;
-
Index: lib/TWiki/UI/Edit.pm
===================================================================
--- lib/TWiki/UI/Edit.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Edit.pm (.../DEVELOP) (revision 9301)
@@ -23,7 +23,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::UI::Edit
Edit command handler
Index: lib/TWiki/UI/Search.pm
===================================================================
--- lib/TWiki/UI/Search.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Search.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::UI::Search
Index: lib/TWiki/UI/Manage.pm
===================================================================
--- lib/TWiki/UI/Manage.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Manage.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::UI::Manage
@@ -109,7 +109,7 @@
@groups ) ] );
}
- unless( $user->checkPassword( $password ) ) {
+ unless( $user->checkPasswd( $password ) ) {
throw TWiki::OopsException( 'attention',
web => $webName,
topic => $topic,
Index: lib/TWiki/UI/ChangeForm.pm
===================================================================
--- lib/TWiki/UI/ChangeForm.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/ChangeForm.pm (.../DEVELOP) (revision 9301)
@@ -103,4 +103,5 @@
return $page;
}
+
1;
Index: lib/TWiki/UI/RDiff.pm
===================================================================
--- lib/TWiki/UI/RDiff.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/RDiff.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::UI::RDiff
Index: lib/TWiki/UI/Statistics.pm
===================================================================
--- lib/TWiki/UI/Statistics.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Statistics.pm (.../DEVELOP) (revision 9301)
@@ -21,7 +21,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::UI::Statistics
Statistics extraction and presentation
Index: lib/TWiki/UI/Oops.pm
===================================================================
--- lib/TWiki/UI/Oops.pm (.../TWikiRelease04x00) (revision 9301)
+++ lib/TWiki/UI/Oops.pm (.../DEVELOP) (revision 9301)
@@ -17,7 +17,7 @@
#
# As per the GPL, removal of this notice is prohibited.
-=begin twiki
+=pod
---+ package TWiki::UI::Oops
Index: bin/setlib.cfg
===================================================================
--- bin/setlib.cfg (.../TWikiRelease04x00) (revision 9301)
+++ bin/setlib.cfg (.../DEVELOP) (revision 9301)
@@ -20,7 +20,7 @@
# there. They will override any settings in this file. #
###########################################################################
-use vars qw( $twikiLibPath @localPerlLibPath );
+use vars qw( $twikiLibPath @localPerlLibPath $twikiConfPath);
eval 'require "LocalLib.cfg"';
@@ -28,6 +28,12 @@
use Cwd qw( abs_path );
( $twikiLibPath ) = ($twikiLibPath = Cwd::abs_path( "../lib" )) =~ /(.*)/;
}
+
+unless (( defined ($twikiConfPath) ) and (-e $twikiConfPath)) {
+ use Cwd qw( abs_path );
+ ( $twikiConfPath ) = ($twikiConfPath = Cwd::abs_path( "../conf" )) =~ /(.*)/;
+}
+
if ($twikiLibPath eq "") {
$twikiLibPath = "../lib";
warn "using relative path for libs - some plugins may break";
@@ -44,6 +50,7 @@
# Prepend to @INC, the Perl search path for modules
unshift @INC, $twikiLibPath;
+unshift @INC, $twikiConfPath;
unshift @INC, @localPerlLibPath if defined @localPerlLibPath;
1; # Return success for module loading
Index: bin/configure
===================================================================
--- bin/configure (.../TWikiRelease04x00) (revision 9301)
+++ bin/configure (.../DEVELOP) (revision 9301)
@@ -1,4045 +1,4048 @@
-#!/usr/bin/perl -w
-#
-# TWiki Enterprise Collaboration Platform, http://TWiki.org/
-#
-# Copyright (C) 2000-2006 TWiki Contributors.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version. For
-# more details read LICENSE in the root of this distribution.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# As per the GPL, removal of this notice is prohibited.
-#
-# Configuration script for TWiki. Once you have a basic webserver
-# configuration that lets you access this script, the rest of the
-# configuration process is done from here. This script replaces
-# the old "testenv" script.
-#
-# The script works by accepting values into a CGI form, and then
-# submitting those values back to itself with a parameter (update)
-# set to 1. This causes it to write config changes to LocalSite.cfg.
-# Note that changes are only written if there is a real change in the
-# value.
-#
-# The values available to configuration are determined by parsing
-# TWiki.cfg. Special full-line comments guide the parse:
-# Any comment of the form
-#---+ Some text
-# is taken as a foldable block, and following comments are dragged in too.
-# ---++ is H3, ---+++ is H4 etc
-# Comments of the form
-# **TYPE opts**
-# where TYPE is one of URL, PATH, URLPATH, BOOLEAN, STRING, REGEX, SELECT
-# are used to indicate that a following cfg var is configurable through
-# the interface. All intermediate comments are taken as documentation for
-# the value.
-#
-package TWiki;
-
-# BASIC checks. Without these, nothing works.
-
-use strict;
-
-$SIG{__DIE__} = sub { Carp::confess( $_[0] || '' ) };
-$SIG{'__WARN__'} = sub { die @_ };
-
-use vars qw( %cfg
- $perlver
- $perlvernum
- $perlverRequired
- $perlverRequiredString
- $perlverRecommended
- $perlVerPreferred
- $ActivePerlRecommendedBuild
- $GUESSED
- $cgiModVerRecommended
- $modPerlVersionRecommended
- $rcsverRequired
- );
-
-# Constants
-$perlvernum = $];
-$perlverRequired = 5.00503; # Oldest supported version of Perl
-$perlverRequiredString = '5.005_03';
-$perlverRecommended = '5.6.1';
-$perlVerPreferred = 5.006; # 5.6 or higher has [:lower:] etc
-$ActivePerlRecommendedBuild = 631; # Fixes PERL5SHELL bugs
-$GUESSED = <<'HERE';
-I guessed this setting. You are advised to confirm this setting (and any other guessed settings) and hit 'Next' to save before changing any other settings.
-HERE
-
-# CGI.pm version, on some platforms - actually need CGI 2.93 for mod_perl
-# 2.0 and CGI 2.90 for Cygwin Perl 5.8.0. See
-# http://perl.apache.org/products/apache-modules.html#Porting_CPAN_modules_to_mod_perl_2_0_Status
-$cgiModVerRecommended = '2.93';
-
-# Recommended mod_perl version if using mod_perl 2.0
-# (see Support.RegistryCookerBadFileDescriptor)
-$modPerlVersionRecommended = '1.99_12';
-
-$rcsverRequired = 5.7;
-
-# constants used in TWiki.cfg
-use vars qw($TRUE $FALSE );
-use vars qw( $basicMods $requiredMods $requiredModsNonUnix $optionalMods
- $I18Mods $I18Mods_perl56 $I18Mods_perl58 );
-
-BEGIN {
- $TRUE = 1;
- $FALSE = 0;
- # Set default current working directory
- if( $ENV{SCRIPT_FILENAME} && $ENV{SCRIPT_FILENAME} =~ /^(.+)\/[^\/]+$/ ) {
- chdir $1;
- }
- # Get Perl version
- if (defined $^V) {
- $perlver = $^V; # New in Perl 5.6.1, one byte per part
- $perlver = ord(substr($perlver,0)) . "." . ord(substr($perlver,1))
- . "." . ord(substr($perlver,2));
- } else {
- $perlver = $perlvernum
- }
-
- # Required for configure to work
- $basicMods =
- {
- 'CGI' => "basic TWiki",
- 'CGI::Carp' => "basic TWiki",
- 'Error' => 'basic TWiki',
- };
- $requiredMods =
- {
- 'File::Copy' => 'basic TWiki',
- 'File::Spec' => 'basic TWiki',
- 'FileHandle' => 'basic TWiki',
- 'Algorithm::Diff' => 'basic TWiki',
- };
-
- # Required on non-Unix platforms (mainly Windows)
- $requiredModsNonUnix =
- {
- 'MIME::Base64' => "SHA1 password encoding",
- 'Net::SMTP' => "registration emails and mailnotify",
- };
- # Optional modules on all platforms
- $optionalMods =
- {
- 'Digest::SHA1' => "SHA1 password encoding",
- 'MIME::Base64' => "HTTP Authentication to proxies, and SHA1 password encoding",
- 'POSIX' => "I18N (core module) and Security",
- 'Digest::MD5' => "MD5 encoded passwords",
- 'Text::Diff' => 'UpgradeTWiki',
- 'CGI::Cookie' => "sessions",
- 'CGI::Session' => "sessions",
- };
-
- $I18Mods =
- {
- 'Locale::Maketext::Lexicon' => "I18N translations",
- };
-
- $I18Mods_perl56 =
- {
- 'Unicode::String' => 'I18N conversions',
- 'Unicode::MapUTF8' => "I18N conversions",
- 'Unicode::Map' => "I18N conversions",
- 'Unicode::Map8' => "I18N conversions",
- 'Jcode' => "I18N conversions",
- };
-
- $I18Mods_perl58 =
- {
- 'Encode' => "I18N conversions (core module in Perl 5.8)",
- };
-};
-
-########################################################################
-##################### GLOBAL VARIABLES #################################
-########################################################################
-
-use CGI qw( :any );
-
-use vars qw( $cygwinRcsVerNum $perltype $query $action );
-
-$query = new CGI;
-$action = $query->param('action') || '';
-
-if( $action eq 'image' ) {
- _serveImage( $query->param('type'), $query->param('image' ));
- exit 0;
-}
-
-use vars qw( $errors $toterrors $warnings $totwarnings $url $nextid );
-
-$errors = 0; # reset for each block
-$toterrors = 0;
-$warnings = 0; # reset for each block
-$totwarnings = 0;
-$url = $query->url();
-$nextid = 0;
-
-########################################################################
-########################## FORMATTING ##################################
-########################################################################
-
-# a note
-sub NOTE {
- return CGI::p({class=>"info"}, join("\n",@_));
-}
-
-# a warning
-sub WARN {
- $warnings++;
- $totwarnings++;
- return CGI::div(CGI::span({class=>'warn'}, CGI::strong('Warning: ').join("\n",@_)));
-}
-
-# an error
-sub ERROR {
- $errors++;
- $toterrors++;
- return CGI::div(CGI::span({class=>'error'}, CGI::strong('Error: ').join("\n",@_)));
-}
-
-# Generate a foldable block (twisty). This is a DIV with a table in it
-# that contains the settings and doc rows.
-sub _foldableBlock {
- my( $head, $attr, $body ) = @_;
- my $headText = $head . CGI::span({ class => 'blockLinkAttribute' }, $attr);
- $body = CGI::start_table({width => '100%', -border => 0, -cellspacing => 0, -cellpadding => 0}).$body.CGI::end_table();
- my $mess = '';
- my $errorsMess = ($errors > 1) ? ' errors' : ' error';
- my $warningsMess = ($warnings > 1) ? ' warnings' : ' warning';
- $mess .= CGI::span({class=>'error'}, $errors . $errorsMess) if $errors;
- if ($errors && $warnings) {
- $mess .= ' ';
- }
- $mess .= CGI::span({class=>'warn'}, $warnings . $warningsMess) if $warnings;
- $errors = $warnings = 0;
-
- my $anchor = _makeAnchor( $head );
- my $id = $anchor;
- my $blockId = $id;
- my $linkId = 'blockLink'.$id;
- my $linkAnchor = $anchor.'link';
- return CGI::a({ name => $linkAnchor }).
- CGI::a( {id => $linkId,
- class => 'blockLink blockLinkOff',
- href => '#'.$linkAnchor,
- rel => 'nofollow',
- onclick => 'foldBlock(\'' . $id . '\'); return false;'}, $headText.$mess).
- CGI::div( { id => $blockId,
- class=> 'foldableBlock foldableBlockClosed' }, $body ).
- "\n";
-}
-
-# Generate an ordinary inline headedblock
-sub _ordinaryBlock {
- my( $depth, $head, $attr, $body ) = @_;
- $head .= CGI::span({ class => 'blockLinkAttribute' }, $attr) if $attr;
- if( $depth == 2 ) { $head = CGI::h2( $head ); }
- elsif( $depth == 3 ) { $head = CGI::h3( $head ); }
- elsif( $depth == 4 ) { $head = CGI::h4( $head ); }
- elsif( $depth == 5 ) { $head = CGI::h5( $head ); }
- elsif( $depth == 6 ) { $head = CGI::h6( $head ); }
- else { $head = CGI::h6( $head ); }
- return CGI::Tr(CGI::td( { colspan => 2 } , $head)).
- $body;
-}
-
-# Generate a sub-heading table row
-sub _subHead {
- my $text = shift;
- return CGI::Tr(CGI::Td({class=>'subHead', colspan=>2}, $text)).
- "\n";
-}
-
-# Generate a variable - prompt row
-sub _setting {
- my $key = shift;
- return CGI::Tr(CGI::td({class=>'firstCol'}, $key).
- CGI::td({class=>'secondCol'}, join(' ', @_)));
-}
-
-# generate a documentation table row
-sub _docBlock {
- my $desc = shift || '';
- my $hidden = shift;
- if (length($desc) == 0 || $desc =~ /\A\s\Z/) {
- return '';
- }
- if ($hidden) {
- return CGI::Tr( {class => 'hiddenRow' }, CGI::td( { colspan => 2, class=>'docdata info' }, $desc )).
- "\n";
- }
- return CGI::Tr( CGI::td( { colspan => 2, class=>'docdata info' }, $desc )).
- "\n";
-}
-
-# encode a string to make an HTML anchor
-sub _makeAnchor {
- my $str = shift;
-
- $str =~ s/\s(\w)/uc($1)/ge;
- $str =~ s/\W//g;
- return $str;
-}
-
-########################################################################
-################### CHECKING SUPPORT ###################################
-########################################################################
-
-# Since Windows (without Cygwin) makes it hard to capture stderr
-# ('2>&1' works only on Win2000 or higher), and Windows will usually have
-# GNU tools in any case (installed for TWiki since there's no built-in
-# diff, grep, patch, etc), we only check for these tools on Unix/Linux
-# and Cygwin.
-sub _checkGnuProgram {
- my $prog = shift;
- my $n = '';
-
- if( $TWiki::cfg{OS} eq 'UNIX' ||
- $TWiki::cfg{OS} eq 'WINDOWS' && $perltype eq 'Cygwin' ) {
- $prog =~ s/^\s*(\S+)\s.*$/$1/;
- $prog =~ /^(.*)$/;
- $prog = $1;
- # check for taintedness
- die "$prog is tainted" unless eval { $n = $prog, kill 0; 1 };
- my $diffOut = ( `$prog --version 2>&1` || "");
- my $notFound = ( $? == -1 );
- if( $notFound ) {
- $n = WARN("'$prog' program was not found on the",
- "current PATH.");
- } elsif ( $diffOut !~ /\bGNU\b/ ) {
- # Program found on path, complain if no GNU in version output
- $n = WARN("'$prog' program was found on the PATH",
- "but is not GNU $prog - this may cause",
- "problems. $diffOut");
- } else {
- $diffOut =~ /(\d+(\.\d+)+)/;
- $n = "($prog is version $1).";
- }
- }
-
- return $n;
-}
-
-sub _checkRCSProgram {
- my $key = shift;
-
- return 'Not used in this configuration.'
- unless $TWiki::cfg{StoreImpl} eq 'RcsWrap';
- my $mess = '';
- my $err = '';
- my $prog = $TWiki::cfg{RCS}{$key} || '';
- $prog =~ s/^\s*(\S+)\s.*$/$1/;
- $prog =~ /^(.*)$/; $prog = $1;
- if( !$prog ) {
- $err .= $key.' is not set';
- } else {
- my $version = `$prog -V` || '';
- if( $@ ) {
- $err .= ERROR($prog.' returned an error: '.$@ );
- } elsif ( $version ne '' ) {
- $version =~ /(\d+(\.\d+)+)/;
- $version = $1;
- $mess .= " ($prog is version $version)";
- } else {
- $err .= ERROR($prog.' did not return a version number (or might not exist..)');
- }
- if( defined( $cygwinRcsVerNum )) {
- $mess .= " (Cygwin package rcs-$cygwinRcsVerNum)";
- }
- if( $version && $version < $rcsverRequired ) {
- # RCS too old
- $err .= $prog.' is too old, upgrade to version '.
- $rcsverRequired.' or higher.';
- }
- }
- if( $err ) {
- $mess .= ERROR( $err .<$name" ) ||
- return 'Could not create test file '. $name;
- print FILE $txt1;
- close( FILE);
- open( IN_FILE, "<$name" ) ||
- return 'Could not read test file '. $name;
- my $txt2 = ;
- close( IN_FILE );
- unlink $name if( -e $name );
- unless ( $txt2 eq $txt1 ) {
- return 'Could not write and then read '.$name;
- }
- return '';
-}
-
-sub _checkTreePerms {
- my( $path, $perms, $filter ) = @_;
-
- return '' if( defined($filter) && $path !~ $filter && !-d $path);
-
- #lets ignore Subversion directories
- return '' if( $path !~ /_svn/ );
- return '' if( $path !~ /.svn/ );
-
- my $errs = '';
-
- return $path. ' cannot be found'.CGI::br() unless( -e $path );
-
- if( $perms =~ /r/ && !-r $path) {
- $errs .= ' readable';
- }
-
- if( $perms =~ /w/ && !-d $path && !-w $path) {
- $errs .= ' writable';
- }
-
- if( $perms =~ /x/ && !-x $path) {
- $errs .= ' executable';
- }
-
- return $path.' is not '.$errs.CGI::br() if $errs;
-
- return '' unless -d $path;
-
- opendir(D, $path) ||
- return 'Directory '.$path.' is not readable.'.CGI::br();
-
- foreach my $e ( grep { !/^\./ } readdir( D )) {
- my $p = $path.'/'.$e;
- $errs .= _checkTreePerms( $p, $perms, $filter );
- }
- closedir(D);
- return $errs;
-}
-
-sub _findFileOnPath {
- my $file = shift;
- $file =~ s(::)(/)g;
-
- foreach my $dir ( @INC ) {
- if ( -e "$dir/$file" ) {
- return "$dir/$file";
- }
- }
- return undef;
-}
-
-# Try and locate a required directory
-sub _findMajorDir {
- my( $cfg, $dir ) = @_;
- return '' if( $TWiki::cfg{$cfg} && $TWiki::cfg{$cfg} ne 'NOT SET');
- my $guess = $ENV{SCRIPT_FILENAME};
- unless( $guess ) {
- return WARN("This web server does not set SCRIPT_FILENAME so I can't guess a value for this");
- }
- $guess =~ s(bin/*configure$)();
- $guess .= $dir;
- $TWiki::cfg{$cfg} = $guess;
- return WARN($GUESSED);
-}
-
-sub _warnAboutWindowsBackSlashes {
- my ( $path ) = @_;
- if ( $path =~ /\\/ ) {
- return WARN('You should use c:/path style slashes, not c:\path in "'.$path.'"');
- }
-}
-
-########################################################################
-##################### PROMPT GENERATORS ################################
-########################################################################
-
-# generate an input field for string types
-sub _PROMPT_FOR_STRING {
- my( $id, $opts, $value, $keys ) = @_;
- my $size = "55%";
- if( $opts =~ /\s(\d+)\s/ ) {
- $size = $1;
- # These numbers are somewhat arbitrary..
- if($size>25) { $size="55%"; }
- }
-
- # support upgrade from old configuration, where LowerNational and UpperNational
- # were stored as REGEX'es (now they are STRING's):
- if ( $id eq "LowerNational" || $id eq "UpperNational" ) {
- if ($value =~ /^\(\?-xism:(.*)\)$/) {
- $value = $1;
- }
- }
-
- return CGI::textfield( -name => $id, -size=>$size, -default=>$value );
-}
-
-# generate an input field for URL types
-# This has its own type in case someone wants to add javascript validation
-sub _PROMPT_FOR_URL {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
-}
-
-# generate an input field for URLPATH types
-# This has its own type in case someone wants to add javascript validation
-sub _PROMPT_FOR_URLPATH {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
-}
-
-# generate an input field for PATH types
-# This has its own type in case someone wants to add javascript validation
-sub _PROMPT_FOR_PATH {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
-}
-
-# generate an input field for BOOLEAN types
-sub _PROMPT_FOR_BOOLEAN {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::checkbox( -name => $id, -checked => ( $value ? 1 : 0),
- -value => 1, -label => '' );
-}
-
-# generate an input field for REGEX types
-# This has its own type in case someone wants to add javascript validation
-sub _PROMPT_FOR_REGEX {
- my( $id, $opts, $value, $keys ) = @_;
- $value =~ s/[[\x01-\x09\x0b\x0c\x0e-\x1f"%&'*<=>@[_\|]/''.ord($&).';'/ge;
- return '';
-}
-
-# generate an input field for COMMAND types
-# This has its own type in case someone wants to add javascript validation
-sub _PROMPT_FOR_COMMAND {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
-}
-
-# generate an input field for NUMBER types
-# This has its own type in case someone wants to add javascript validation
-sub _PROMPT_FOR_NUMBER {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::textfield( -name => $id, -size=>20, -default=>$value );
-}
-
-# generate an input field for OCTAL number types (protections)
-sub _PROMPT_FOR_OCTAL {
- my( $id, $opts, $value, $keys ) = @_;
- return CGI::textfield( -name => $id, -size=>20,
- -default=>sprintf('0%o',$value) );
-}
-
-# generate an input field for SELECT types
-sub _PROMPT_FOR_SELECT {
- my( $id, $opts, $value, $keys ) = @_;
- $opts =~ s/^\s+//;
- $opts =~ s/\s.*$//;
- my $sopts = '';
- if ( defined($value) ) {
- $sopts .= '';
- }
- foreach my $opt (split( /\s*,\s*/, $opts)) {
- if( $opt ne $value ) {
- $sopts .= '';
- }
- }
- return CGI::Select({ name => $id, size=>1 }, $sopts);
-}
-
-########################################################################
-###################### VARIABLE CHECKERS ###############################
-########################################################################
-
-sub _CHECKVAR_DefaultUrlHost {
- my $keys = shift;
-
- if( $TWiki::cfg{DefaultUrlHost} &&
- $TWiki::cfg{DefaultUrlHost} ne 'NOT SET' ) {
- my $host = $ENV{HTTP_HOST};
- if( $host && $TWiki::cfg{DefaultUrlHost} !~ /$host/ ) {
- return WARN('Current setting does not match HTTP_HOST ',
- $ENV{HTTP_HOST});
- }
- } else {
- my $protocol = $url || 'http://'.$ENV{HTTP_HOST};
- $protocol =~ s(^(.*?://.*?)/.*$)($1);
- $TWiki::cfg{DefaultUrlHost} = $protocol;
- return ERROR($GUESSED);
- }
- return '';
-}
-
-sub _CHECKVAR_ScriptUrlPath {
- # Check Script URL Path against REQUEST_URI
- my $n;
- my $val = $TWiki::cfg{ScriptUrlPath};
- my $guess = $ENV{REQUEST_URI} || $ENV{SCRIPT_NAME} || '';
- $guess =~ s(/+configure\b.*$)();
-
- if( $val && $val ne 'NOT SET' ) {
- unless( $guess ) {
- return WARN(<Go to "pub" directory';
-}
-
-sub _CHECKVAR_PubDir {
- my $e = _findMajorDir('PubDir', 'pub');
- $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{PubDir});
- my $e2 = _checkTreePerms( $TWiki::cfg{PubDir}, 'rw' );
- $e .= WARN($e2) if $e2;
- return $e;
-}
-
-sub _CHECKVAR_TemplateDir {
- my $e = _findMajorDir('TemplateDir', 'templates');
- $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{TemplateDir});
- my $e2 = _checkTreePerms( $TWiki::cfg{TemplateDir}, 'r' );
- $e .= ERROR($e2) if $e2;
- return $e;
-}
-
-sub _CHECKVAR_DataDir {
- my $e = _findMajorDir('DataDir', 'data');
- my $e2 = _checkTreePerms( $TWiki::cfg{DataDir}, "r" );
- $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{DataDir});
- $e2 = _checkTreePerms( $TWiki::cfg{DataDir}, "w", qr/\.txt$/ )
- unless $e2;
- $e .= WARN($e2) if $e2;
- return $e;
-}
-
-sub _CHECKVAR_LocalesDir {
- my $e = _findMajorDir('LocalesDir', 'locale');
- my $e2 = _checkTreePerms( $TWiki::cfg{LocalesDir}, "r" );
- $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{LocalesDir});
- $e .= ERROR($e2) if $e2;
- return $e;
-}
-
-sub _CHECKVAR_MailProgram {
- eval "use Net::SMTP";
- my $n;
- if ($@) {
- $n = "Net::SMTP is not installed in this environment. ";
- my $val = $TWiki::cfg{MailProgram} || '';
- $val =~ s/\s.*$//g;
- if( ! ( -e $val ) ) {
- return WARN("$val was not found. Check the path.");
- }
- } else {
- $n = 'Net::SMTP is installed in this environment, so this setting will not be used.';
- }
- return $n;
-}
-
-sub _CHECKVAR_LogFileName {
- my $logFile = $TWiki::cfg{LogFileName} || "";
- $logFile =~ s/%DATE%/DATE/;
- my $e = _checkCanCreateFile( $logFile );
- $e = ERROR($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_ConfigurationLogName {
- my $logFile = $TWiki::cfg{ConfigurationLogName} || "";
- $logFile =~ s/%DATE%/DATE/;
- my $e = _checkCanCreateFile( $logFile );
- $e = ERROR($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_WarningFileName {
- my $logFile = $TWiki::cfg{WarningFileName} || "";
- $logFile =~ s/%DATE%/DATE/;
- my $e = _checkCanCreateFile( $logFile );
- $e = ERROR($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_DebugFileName {
- my $logFile = $TWiki::cfg{DebugFileName} || "";
- $logFile =~ s/%DATE%/DATE/;
- my $e = _checkCanCreateFile( $logFile );
- $e = ERROR($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_MimeTypesFileName {
- my $e = _checkTreePerms($TWiki::cfg{MimeTypesFileName}, 'r');
- $e = ERROR($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_Htpasswd_FileName {
- my $e = _checkTreePerms($TWiki::cfg{Htpasswd}{FileName}, 'r');
- $e = ERROR($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_RegistrationApprovals {
- my $file = $TWiki::cfg{RegistrationApprovals};
- my $e = _checkTreePerms( $file, 'rw' );
- $e = WARN($e) if $e;
- return $e;
-}
-
-sub _CHECKVAR_UseLocale {
- my $on = $TWiki::cfg{UseLocale};
-
- my $n = '';
- if( $TWiki::cfg{OS} eq 'WINDOWS' ) {
- # Warn re known broken locale setup
- $n .= WARN(<= 5.008 and
- not ( exists $Config::Config{useperlio} and
- $Config::Config{useperlio} eq 'define' ) ) {
- $n .= WARN(<Perl's Unicode Model in 'perldoc
-perluniintro') - re-compilation of Perl will be required before it can be
-used to enable TWiki's experimental UTF-8 support.
-HERE
- );
- }
-
- # Check for d_setlocale in Config (same as 'perl -V:d_setlocale')
- eval "use Config";
- if ( !( exists $Config::Config{d_setlocale} &&
- $Config::Config{d_setlocale} eq 'define' ) ) {
- $n .= WARN(<$forUpperNat
-HERE
- );
- }
- }
- return '';
-}
-
-sub _CHECKVAR_LowerNational {
- if( $perlvernum < $perlVerPreferred || 1) {
- # Locales are off/broken, or using pre-5.6 Perl, so have to
- # explicitly list the accented characters (but not if using UTF-8)
- my $forLowerNat = join '', grep { uc($_) ne $_ and m/[^a-z]/ } map { chr($_) } 1..255;
-
- if ($forLowerNat) {
- return WARN( <$forLowerNat
-HERE
- );
- }
- }
- return '';
-}
-
-sub _CHECKVAR_Site_Locale {
- my $e = '';
- my $locale = $TWiki::cfg{Site}{Locale};
- setlocale(&LC_CTYPE, $locale);
- my $currentLocale = setlocale(&LC_CTYPE);
- if ( $currentLocale ne $locale ) {
- $e .= WARN(<C, which should always work.
-HERE
- );
- }
- if( $locale !~ /[a-z]/i && $TWiki::cfg{UseLocale} ) {
- $e = WARN(<path_info() =~ /$TWiki::cfg{ScriptSuffix}$/ ) {
- return ERROR('this script ('.$query->pather_info().') called with different ScriptSuffix setting'.$TWiki::cfg{ScriptSuffix});
- }
- }
- return '';
-}
-
-sub _CHECKVAR_RCS_EgrepCmd { return _checkGnuProgram($TWiki::cfg{RCS}{EgrepCmd}); }
-sub _CHECKVAR_RCS_FgrepCmd { return _checkGnuProgram($TWiki::cfg{RCS}{FgrepCmd}); }
-sub _CHECKVAR_RCS_initTextCmd { return _checkRCSProgram('initTextCmd'); }
-sub _CHECKVAR_RCS_initBinaryCmd { return _checkRCSProgram('initBinaryCmd'); }
-sub _CHECKVAR_RCS_tmpBinaryCmd { return _checkRCSProgram('tmpBinaryCmd'); }
-sub _CHECKVAR_RCS_ciCmd { return _checkRCSProgram('ciCmd'); }
-sub _CHECKVAR_RCS_ciDateCmd { return _checkRCSProgram('ciDateCmd'); }
-sub _CHECKVAR_RCS_coCmd { return _checkRCSProgram('coCmd'); }
-sub _CHECKVAR_RCS_histCmd { return _checkRCSProgram('histCmd'); }
-sub _CHECKVAR_RCS_infoCmd { return _checkRCSProgram('infoCmd'); }
-sub _CHECKVAR_RCS_rlogDateCmd { return _checkRCSProgram('rlogDateCmd'); }
-sub _CHECKVAR_RCS_diffCmd { return _checkRCSProgram('diffCmd'); }
-sub _CHECKVAR_RCS_lockCmd { return _checkRCSProgram('lockCmd'); }
-sub _CHECKVAR_RCS_unlockCmd { return _checkRCSProgram('unlockCmd'); }
-sub _CHECKVAR_RCS_delRevCmd { return _checkRCSProgram('delRevCmd'); }
-
-sub _CHECKVAR_StoreImpl {
- my $mess = '';
- if( $TWiki::cfg{StoreImpl} eq 'RcsWrap') {
- # Check that GNU diff is found in PATH; used by rcsdiff
- $mess .= NOTE( "Note: The 'diff' program found on the path is used by RcsWrap to compare revisions ".
- _checkGnuProgram( "diff"));
- }
-
- return $mess;
-};
-
-sub _CHECKVAR_UseClientSessions {
- my $mess = '';
- if (!eval "use CGI::Cookie; 1") {
- $mess .= <$class}, $prompter) if $mandatory;
- use strict 'refs';
-
- $keys = CGI::span({class=>'mandatory'}, $keys) if $mandatory;
- my $hidden = 0;
- if (length($desc) == 0 || $desc =~ /\A\s\Z/) {
- $hidden = 1;
- }
- return _docBlock( $output.$desc, $hidden )._setting( $keys, $prompter );
-}
-
-sub _showPlugins {
- my %modules;
- foreach my $libDir ( @INC ) {
- if( opendir( DIR, "$libDir/TWiki/Plugins" ) ) {
- foreach my $file ( grep { /^[A-Za-z0-9_]+Plugin\.pm$/ }
- readdir DIR ) {
- my $module = $file;
- $module =~ s/\.pm$//;
- $TWiki::cfg{Plugins}{$module}{Enabled} ||= 0;
- $module =~ /^(.*)$/; # untaint
- $module = $1;
- # only add the first instance of any plugin, as only
- # the first can get loaded from @INC.
- unless( $modules{$module} ) {
- $modules{$module} = $libDir;
- }
- closedir( DIR );
- }
- }
- }
- my $block = '';
- foreach my $m ( sort keys %modules ) {
- $block .= _checkAndBuildValueGrabber
- ( 'BOOLEAN', '',
-#SMELL - i'm assuming that the Plugin topic is in the SystemWeb :(
-"$m",
- '{Plugins}{'.$m.'}{Enabled}'
- );
- }
- return $block;
-}
-
-sub _showLanguages {
- opendir( DIR, $TWiki::cfg{LocalesDir}) or
- return 'Couldn\'t read TWiki {LocalesDir}!';
- my $block = '';
- foreach my $file ( grep { /^.*\.po$/ } readdir DIR ) {
- $file =~ m/^(.*)\.po$/;
- my $lang = $1;
- $lang = "'$lang'" if $lang =~ /\W/;
- $block .= _checkAndBuildValueGrabber ( 'BOOLEAN', '', 'Enable the language ' . $lang . '', '{Languages}{' . $lang . '}{Enabled}' );
- }
- closedir( DIR );
- return $block;
-}
-
-########################################################################
-##################### WRITING NEW VALUES ###############################
-########################################################################
-
-sub setConfig {
- my ($path, $updates) = @_;
- my $txt = '';
- if( open(F, "<$path")) {
- undef $/;
- $txt = ;
- close(F);
- }
-
- $txt =~ s/^\s*1;\s*$//gm;
-
- open(F, ">$path") ||
- die "Failed to open $path for write";
-
- foreach my $config ( keys %$updates ) {
- # kill the old settings if any are there
- $txt =~ s/\$TWiki::cfg$config\s*=.*?;\s*\n//s;
- $txt .= '$TWiki::cfg'.$config.' = '.$updates->{$config}.";\n";
- }
- print F $txt,"1;\n";
- close(F);
-
- if( defined( $TWiki::cfg{ConfigurationLogName} ) &&
- open(F, '>>'.$TWiki::cfg{ConfigurationLogName} )) {
- my $date = gmtime();
- my $user = $query->remote_user() || 'guest';
- foreach my $config ( keys %$updates ) {
- print F '| ',$date,' | ',$user,' | ',$config,' | ',
- $updates->{$config}," |\n";
- }
- close(F);
- }
-}
-
-# Convert value to a canonical perl representation suitable for writing
-# to LocalSite.cfg
-sub _perlifyType {
- my ($val,$type) = @_;
-
- if ($type eq 'BOOLEAN') {
- return ($val ? 1 : 0);
- } elsif ($type eq 'NUMBER') {
- $val ||= 0;
- return 0+$val;
- } elsif ($type eq 'OCTAL') {
- $val ||= 0;
- $val = '0'.$val unless $val =~ /^0/;
- return $val;
- } else {
- $val ||= '';
- $val =~ s/'/\\'/g;
- return "'".$val."'";
- }
-}
-
-sub _perlModulesCheck {
- my $mods = shift;
- my $e = '';
- foreach my $mod (keys %$mods) {
- my $n = '';
- eval "use $mod";
- if ($@) {
- $n = WARN('not installed. May be required for ',
- $mods->{$mod});
- } else {
- my $mod_version;
- no strict 'refs';
- eval '$mod_version = ${'.$mod.'::VERSION}';
- use strict 'refs';
- $n = $mod_version || 'unknown';
- }
- $e .= _setting($mod, $n);
- }
- return $e;
-}
-
-########################################################################
-#################### MAIN ACTION ENTRY POINTS ##########################
-########################################################################
-
-sub _serveImage {
- my($type, $image )= @_;
-
- print "Content-type: $type\n\n";
- if( open(F, "logos/$image")) {
- local $/ = undef;
- print ;
- close(F);
- }
-}
-
-sub handleUpdate {
- my $path = shift;
- my $pass = $query->param( 'cfgAccess' );
- my $param;
- my $output = '';
- unless( defined( $pass )) {
- $output .= CGI::start_form({ action=>$ENV{SCRIPT_NAME}, method=>"post" });
- # Pass all URL params through
- foreach $param ( $query->param ) {
- $output .= CGI::hidden( $param, $query->param( $param ));
- $output .= "\n";
- }
-
- my $changed = calculateChanges();
- my $itemText = ($changed == 1) ? 'item' : 'items';
- $output .= CGI::div({ class => 'explanation'},
- CGI::strong( 'Changing ' . $changed.
- ' configuration ' . $itemText.
- '.').
- (($changed == 0) ? CGI::br() .
- CGI::a( { href=>$url.'?t='.time(),
- rel => 'nofollow' },
- 'Return to configuration') : CGI::br() .
- 'Proceed with the steps below to save your changes.'));
-
- # and add a few more
- $output .= CGI::h2('Enter the configuration password');
- if ($TWiki::cfg{Password} ne '') {
- $output .= CGI::p(CGI::strong("Your Password:").CGI::br());
- $output .= CGI::password_field( 'cfgAccess', '', 20, 80 );
- $output .= ' ' . CGI::submit(-class=>'twikiSubmit', -value=>'Save changes');
- $output .= CGI::br();
- } else {
- $output .= CGI::hidden( 'cfgAccess', '' );
- }
- my $forgotPassword = '';
- if ($TWiki::cfg{Password} ne '') {
- $forgotPassword = CGI::strong("Forgot your password?"). CGI::br(). 'To reset the password, log in to the server and delete the $TWiki::cfg{Password} = \'...\'; line in lib/LocalSite.cfg';
- }
- $output .= CGI::div({ class => 'explanation'},
- CGI::span( $forgotPassword . CGI::img({src=>$ENV{SCRIPT_NAME}.'?action=image;image=warning.gif;type=image/gif', alt=>''}) . ' ' . <<'HERE'
-Notes on Security:
-
-
If you don't set a password, or the password is cracked, then configure could be used to do very nasty things to your server.
-
If you are running TWiki on a public website, you are strongly advised to disable saving from configure by making lib/LocalSite.cfg readonly once you are happy with your configuration.
-
-HERE
- ));
- if ($TWiki::cfg{Password} ne '') {
- $output .= CGI::p( "You may change your password here:" );
- }
-
- $output .= CGI::div({ class => 'formElem'},
-
- CGI::strong("New Password:").
- CGI::br().
- CGI::password_field( 'newCfgP', '', 20, 80 ).
- CGI::br().
- CGI::strong("Confirm Password:").CGI::br().
- CGI::password_field( 'confCfgP', '', 20, 80 ).
- CGI::br().
- CGI::submit(-class=>'twikiSubmit', -value=>'Set Password and Save changes'));
- $output .= CGI::end_form();
- $output .= CGI::end_html();
- return $output;
- }
-
- unless( crypt( $pass, $TWiki::cfg{Password}) eq
- $TWiki::cfg{Password} || $TWiki::cfg{Password} eq '') {
- $output .= CGI::span( {class => 'error' }, "Incorrect password" ).
- CGI::end_html();
- return $output;
- }
-
- my $changed = 0;
- my %updates;
-
- if( $query->param( 'newCfgP' )) {
- if( $query->param( 'newCfgP' ) eq
- $query->param( 'confCfgP' )) {
- my @saltchars = ( 'a'..'z', 'A'..'Z', '0'..'9', '.', '/' );
- my $salt = $saltchars[int(rand($#saltchars+1))] .
- $saltchars[int(rand($#saltchars+1)) ];
- $updates{'{Password}'} =
- _perlifyType(
- crypt( $query->param( 'newCfgP' ), $salt ),
- 'STRING' );
- $changed++;
- $output .= "Password changed";
- } else {
- $output .= "New password and confirmation do not match";
- return $output;
- }
- }
-
- $output .= CGI::h2('Updating configuration');
- foreach $param ( $query->param ) {
- next unless $param =~ /^^TYPEOF:(.*)/;
- my $type = $query->param( $param );
- $param =~ s/^TYPEOF:(.*)$/$1/;
- my $basevar = $1;
- my $var = '$TWiki::cfg'.$basevar;
- my $val = $query->param( $param );
- my $def;
- eval "\$def = defined( $var );";
- if( $type ) {
- eval "\$def = $var;" if $def;
- next if( $type eq 'OCTAL' && sprintf('0%o', $def) =~ /^0*$val$/ );
- next if( $type eq 'NUMBER' && $val + 1 == $def + 1 );
- next if( $type eq 'BOOLEAN' && ($val && $def || !$val && !$def));
- next if( $val eq $def );
- $output .= CGI::h3($var).
- CGI::b('old ').
- CGI::code($def||' ').
- CGI::br().
- CGI::b('new ').
- CGI::code($val||' ');
- $updates{$basevar} = _perlifyType($val, $type);
- $changed++;
- }
- }
- $output .= CGI::p();
- setConfig($path, \%updates);
- my $itemText = ($changed == 1) ? 'item' : 'items';
- $output .= CGI::hr();
- $output .= CGI::p(CGI::strong($changed.' configuration ' . $itemText . ' changed. '));
- $output .= CGI::p(CGI::a({ rel => 'nofollow',
- href=>$url.'?t='.time() },
- 'Return to configuration'));
- return $output;
-}
-
-sub calculateChanges {
- my $param;
- my $changed = 0;
- foreach $param ( $query->param ) {
- next unless $param =~ /^^TYPEOF:(.*)/;
- my $type = $query->param( $param );
- $param =~ s/^TYPEOF:(.*$)/$1/;
- my $var = '$TWiki::cfg'.$1;
- my $val = $query->param( $param );
- my $def;
- eval "\$def = defined( $var );";
- if( $type ) {
- eval "\$def = $var;" if $def;
- next if( $type eq 'OCTAL' && sprintf('0%o', $def) =~ /^0*$val$/ );
- next if( $type eq 'NUMBER' && $val + 1 == $def + 1 );
- next if( $type eq 'BOOLEAN' && ($val && $def || !$val && !$def));
- next if( $val eq $def );
- $changed++;
- }
- }
- return $changed;
-}
-
-sub performSanityChecks {
- my( $brokenTWikiCfgError, $brokenLocalSiteError ) = @_;
- my $output = '';
-
- if ($brokenTWikiCfgError) {
- $output .= CGI::h2('WARNING:').
- CGI::p('TWiki.cfg is unreadable or has a configuration problem that is causing a Perl error - the following message(s) should help locate the problem.');
- $output .= $brokenTWikiCfgError;
-
- # EARLY EXIT
- $output .= CGI::end_html();
- return $output;
- }
-
- if ($brokenLocalSiteError) {
- $output .= CGI::h2('WARNING:').
- ERROR('LocalSite.cfg is unreadable or has a configuration problem that is causing a Perl error - the following message(s) was generated:').
- CGI::pre($brokenLocalSiteError).
- 'The @INC path is '.
- CGI::pre(join(":", @INC)).
- NOTE('This may be because this is the first time you have run configure. In this case you can simply ignore this error until you have filled in your General path settings. Otherwise, check that the file exists, and the webserver user is allowed to read it.');
- }
-
- # Check whether basic CGI modules exist (some broken installations of
- # Perl don't have this, even though they are standard modules), and warn user
- my $modMissing = 0;
- foreach my $mod (keys %$basicMods) {
- eval "use $mod";
- if ($@) {
- unless ($modMissing) {
- $output .= ERROR( 'Perl Module(s) missing');
- }
- $modMissing = 1;
- $output .= ERROR( 'Essential Perl Module \'',$mod,
- '\' not installed - please check the setting ',
- 'of @INC.' );
- }
- }
-
- # If any critical modules missing, display @INC and give up
- if ($modMissing) {
- $output .= NOTE( '@INC = ', join( ' ', @INC ));
- return $output;
- }
-
- return $output;
-}
-
-sub presentReadOnlyInfo {
- # use strict; # Recommended for mod_perl, enable for Perl 5.6.1 only
- # Doesn't work well here, due to 'do "TWiki.cfg"'
- # use diagnostics; # Debug only
-
- # Load CGI modules (run-time, after checking they are accessible)
- require CGI;
- import CGI qw( -any );
- require CGI::Carp;
- import CGI::Carp qw( fatalsToBrowser );
-
- $errors = 0;
- $warnings = 0;
-
- my $output = '';
- my $block = '';
- for my $key ( sort keys %ENV ) {
- $block .= _setting($key, $ENV{$key});
- }
- $output .= _foldableBlock(CGI::em( 'Environment variables' ),
- '(read only) ', $block);
-
- $block = '';
-
- # Make %ENV safer for CGI (should reflect TWiki.pm)
- my $originalPath = $ENV{PATH} || '';
- if( $TWiki::cfg{SafeEnvPath} ) {
- # SMELL: this untaint probably isn't needed
- my $ut = $TWiki::cfg{SafeEnvPath};
- $ut =~ /^(.*)$/;
- $ENV{PATH} = $1;
- }
- delete @ENV{ qw( IFS CDPATH ENV BASH_ENV ) };
- my $perlverMsg = $perlver; # Default version message
-
- # Load Config module - used here and elsewhere
- require Config;
-
- # Set $TWiki::cfg{DetailedOS} if not using later versions of TWiki.cfg for BeijingRelease
- # - this code enables the latest testenv to be used with Dec 2001 and
- # earlier releases.
- if ( !defined $TWiki::cfg{DetailedOS} ) {
- $TWiki::cfg{DetailedOS} = $Config::Config{'osname'};
- }
-
- # Detect Perl flavour on Windows, and Cygwin Perl/RCS package versions
-
- if ($TWiki::cfg{DetailedOS} eq 'cygwin') {
- $perltype = 'Cygwin'; # Cygwin Perl only
- my ($pkg, $pkgName);
-
- # Get Cygwin perl's package version number
- $pkgName = 'perl';
- $pkg = `/bin/cygcheck -c $pkgName | /bin/grep $pkgName 2>/dev/null`;
- if ($?) {
- $pkg = " [Cannot identify package - cygcheck or grep not installed]";
- $perlverMsg = $perlver . $pkg
- } else {
- $pkg = (split ' ', $pkg)[1]; # Package version
- $perlverMsg = $pkg;
- }
-
- # Get Cygwin RCS's package version number
- $pkgName = 'rcs';
- $pkg = `/bin/cygcheck -c $pkgName | /bin/grep $pkgName 2>/dev/null`;
- if ($?) {
- $pkg = " [Cannot identify package - cygcheck or grep not installed]";
- $cygwinRcsVerNum = $pkg;
- } else {
- $pkg = (split ' ', $pkg)[1]; # Package version
- $cygwinRcsVerNum = $pkg;
- }
- } elsif ($TWiki::cfg{DetailedOS} =~ /win/i && $TWiki::cfg{DetailedOS} !~ /darwin/i ) {
- # Windows Perl - try ActivePerl-only function: returns number if
- # successful, otherwise treated as a literal (bareword).
- my $isActivePerl= eval 'Win32::BuildNumber !~ /Win32/';
- if( $isActivePerl ) {
- $perltype = 'ActiveState';
- $perlverMsg = $perlver . ", build " . Win32::BuildNumber();
- } else {
- # Could be SiePerl or some other Win32 port of Perl
- $perltype = 'SiePerl or other Windows Perl';
- }
- } else {
- $perltype = 'generic';
- }
-
- # Detect executable name suffix, e.g. .exe on Windows or '' on Unix
- # Avoid testing for .exe suffixes on Cygwin, since the built-in
- # grep and ls don't end in '.exe', even though Perl's '_exe' setting
- # indicates they should.
- my $exeSuffix='';
- if ( $Config::Config{'_exe'} and ($TWiki::cfg{OS} eq 'WINDOWS' and $perltype ne 'Cygwin') ) {
- if ( ! $ENV{INTERIX_ROOT} ) { #this is set is we are using UnixServicesForWindows (or INTERIX funnily enough) and they don't use .exe either
- $exeSuffix = $Config::Config{'_exe'};
- }
- }
-
- # Detect whether mod_perl was loaded into Apache
- my $modPerlLoaded = ( exists $ENV{SERVER_SOFTWARE} &&
- ( $ENV{SERVER_SOFTWARE} =~ /mod_perl/ ));
- # Detect whether we are actually running under mod_perl
- # - test for MOD_PERL alone, which is enough.
- my $usingModPerl = ( exists $ENV{MOD_PERL} );
- my $modPerlVersion;
-
- # Get the version of mod_perl if it's being used
- if ( $usingModPerl ) {
- $modPerlVersion = eval 'use mod_perl; return $mod_perl::VERSION';
- $block .= _setting('',
- WARN(<configure with mod_perl. This
-is risky because mod_perl will remember old values of configuration
-variables. You are *highly* recommended not to run configure under
-mod_perl (though the rest of TWiki can be run with mod_perl, of course)
-HERE
- ));
- }
-
- my $n = ucfirst(lc($TWiki::cfg{OS}));
- $n .= " ($TWiki::cfg{DetailedOS})" if ( $TWiki::cfg{DetailedOS} ne '' );
- # OS
- $block .= _setting("Operating system", $n);
-
- # Perl version and type
- $perlverMsg .= " ($perltype)" if $perltype ne 'generic';
- $block .= _setting("Perl version", $perlverMsg);
-
- if ( $perlvernum < $perlverRequired ) {
- $block .= _setting('',
- WARN(<twiki/lib and check that LocalSite.cfg is present and readable");
- } else {
- $twikiFound = 1;
- my $mod_version = eval '$TWiki::wikiversion || $TWiki::VERSION';
- $mod_version ||= 'unknown';
- $mess = 'OK, TWiki.pm found (Version: '.$mod_version.')';
- }
- $block .= _setting('TWiki module in @INC path', $mess);
-
- #add in the basic Modules so that we list their versions in the UI
- map { $requiredMods->{$_} = $basicMods->{$_} }
- keys %$basicMods;
-
- if ( defined $TWiki::cfg{DetailedOS} and ($TWiki::cfg{DetailedOS} =~ /darwin/i or $TWiki::cfg{OS} ne 'UNIX') ) {
- map { $requiredMods->{$_} = $requiredModsNonUnix->{$_} }
- keys %$requiredModsNonUnix;
- } else {
- # these are optional on Unix
- map { $optionalMods->{$_} = $requiredModsNonUnix->{$_} }
- keys %$requiredModsNonUnix;
- }
-
- # Check that each of the required Perl modules can be loaded, and
- # print its version number.
- my $set = '';
- foreach my $mod (keys %$requiredMods) {
- eval "use $mod";
- if ($@) {
- $set .= _setting($mod, ERROR("not installed. Required for ",
- $requiredMods->{$mod}));
- } else {
- my $mod_version;
- no strict 'refs';
- eval '$mod_version = ${'.$mod.'::VERSION}';
- use strict 'refs';
- $n = $mod_version || 'unknown';
- # Check for potential CGI.pm module upgrade
- if( $mod eq 'CGI' and $mod_version < $cgiModVerRecommended ) {
- if ( $perltype eq 'Cygwin' and $perlver eq '5.8.0' ) {
- # Recommend CGI.pm upgrade if using Cygwin Perl 5.8.0
- $n .= WARN( "CGI.pm version $cgiModVerRecommended or higher",
- "is recommended to avoid problems with attachment",
- "uploads on Cygwin Perl $perlver.");
- } elsif ( $usingModPerl and $modPerlVersion >= 1.99 ) {
- # Recommend CGI.pm upgrade if using mod_perl 2.0, which
- # is reported as version 1.99 and implies Apache 2.0
- $n .= WARN("CGI.pm version $cgiModVerRecommended or higher is",
- "recommended to avoid problems with mod_perl version",
- "$modPerlVersion on Apache 2.0 or higher.");
- }
- }
- $set .= _setting( $mod, $n );
- }
- }
- $block .= _setting("Required Perl modules",
- CGI::start_table({width=>'100%'}).
- $set.CGI::end_table());
-
- # Check that each of the optional Perl modules can be loaded, and
- # print its version number.
- $set = _perlModulesCheck( $optionalMods );
- $set .= _perlModulesCheck( $I18Mods );
- $set .= _perlModulesCheck( $] >= 5.008 ? $I18Mods_perl58 : $I18Mods_perl56 );
- $block .= _setting("Optional Perl Modules",
- CGI::start_table({width=>'100%'}).
- $set.CGI::end_table());
-
- # All module checks done, OK to enable fatalsToBrowser
- import CGI::Carp qw( fatalsToBrowser );
-
- # PATH_INFO
- $block .= _setting(CGI::a({name=>'PATH_INFO'},'PATH_INFO'), $query->path_info().
- NOTE(<$url/foo/bar,
-the correct PATH_INFO is /foo/bar, without any prefixed path
-components.
-Click here to test this
-- particularly if you are using mod_perl, Apache or IIS, or are using
-a web hosting provider.
-Look at the new path info here. It should be /foo/bar.
-HERE
- ));
-
- # mod_perl
- if( $usingModPerl ) {
- $n = "Used for this script";
- } else {
- $n = "Not used for this script";
- }
- $n .= NOTE( 'mod_perl is ', $modPerlLoaded ? '' : 'not',
- ' loaded into Apache' );
- if ( $modPerlVersion ) {
- $n .= NOTE( 'mod_perl version ', $modPerlVersion );
- }
-
- # Check for a broken version of mod_perl 2.0
- if ( $usingModPerl && $modPerlVersion =~ /1\.99_?11/ ) {
- # Recommend mod_perl upgrade if using a mod_perl 2.0 version
- # with PATH_INFO bug (see Support.RegistryCookerBadFileDescriptor
- # and Bugs:Item82)
- $n .= ERROR(<) ); # Unix/Cygwin Perl - effective UID
- $grp = join(',', map { lc(getgrgid( $_ )) } split( " ", $( ) );
- } else { # ActiveState or other Win32 Perl
- $usr = lc( getlogin );
- # Try to use Cygwin's 'id' command - may be on the path, since Cygwin
- # is probably installed to supply ls, egrep, etc - if it isn't, give up.
- # Run command without stderr output, to avoid CGI giving error.
- # Get names of primary and other groups.
- $grp = lc(qx(sh -c '( id -un ; id -gn) 2>/dev/null' 2>nul ));
- if ($?) {
- $grp = "[Cannot identify groups - no Cygwin 'id' or 'sh' command on path]";
- }
- }
-
- $block .= _setting('CGI user', 'userid = '.$usr.' groups = '.
- $grp.''.
- NOTE('Your CGI scripts are executing as this user.'));
-
- $block .= _setting("Original PATH", $originalPath.
- NOTE(<recommended if Cygwin is installed).
-
Use this page to set the configuration options for TWiki. Fill in the settings, and then press 'Next'.
";
- $body .= "
";
- $body .= CGI::img({src=>$ENV{SCRIPT_NAME}.'?action=image;image=info.gif;type=image/gif', alt=>''}) . ' ';
- $TWiki::cfg{ScriptUrlPath} ||= '';
- $TWiki::cfg{ScriptSuffix} ||= '';
- $TWiki::cfg{SystemWebName} ||= '';
- $body .= <If you are installing TWiki for the first time If you just want to get up and running, the only section you need to worry about below is
-General path settings. You can always come
-back and configure other settings later.
You will now need to consider how you are going to manage authentication and access control. See the reference manual sections on authentication and access control, and the Security Setup section below.
If you get stuck there is a lot of support available on TWikiIRC (irc.freenode.net, channel #twiki) and at TWiki:Support.
-
-
-
Explanation of color codes:
-
-
Settings marked like this are required (they must
-have a value).
-
Any errors in your configuration will be highlighted.
-
Warnings are non-fatal, but are often a good indicator that something that is wrong.
-
-HERE
-
- $body .= performSanityChecks( $brokenTWikiCfgError, $brokenLocalSiteError );
-
- my $options = '';
- unless( $update_disabled ) {
- $body .= CGI::start_form({ action=>$ENV{SCRIPT_NAME},method=>"post" });
- # use time to make sure we never allow cacheing
- $options .= CGI::hidden( 'action', 'update' );
- $options .= CGI::hidden( 'time', time() );
- }
- $options .= CGI::div({ class => 'optionHeader'},
- CGI::span({ class => 'twikiLeft' }, 'Settings' .
- CGI::span({ class => 'twikiSmall' },
- 'Click the buttons below to open each section')).
- CGI::span({ class => 'twikiSmall twikiRight' },
- CGI::a({ href => '#', rel => 'nofollow',
- onclick => 'toggleAllOptions(true); return false;'}, 'Open all options')).
- CGI::br());
-
- $options .= presentReadOnlyInfo();
-
- $options .= presentEditableInfo();
-
- $body .= CGI::div({class=>'options', id=>'options'}, $options);
- my $totwarningsMess = ($totwarnings > 1) ? ' warnings' : ' warning';
- $body .= CGI::div('Total: '.CGI::span(
- {class=>'warn'}, $totwarnings . $totwarningsMess)) if $totwarnings;
- my $toterrorsMess = ($toterrors > 1) ? ' errors' : ' error';
- $body .= CGI::div('Total: ' . CGI::span(
- {class=>'error'}, $toterrors . $toterrorsMess)) if $toterrors;
-
- if( $update_disabled) {
- $body .= CGI::em("Update is disabled - $update_disabled");
- } else {
- $body .= CGI::p(CGI::submit(-class=>'twikiSubmit', -value=>'Next', -accesskey=>'N'));
- $body .= CGI::end_form();
- }
-
-}
-print CGI::div({class => 'patternMain'}, $body);
-print CGI::end_html();
-
-1;
+#!/usr/bin/perl -w
+#
+# TWiki Enterprise Collaboration Platform, http://TWiki.org/
+#
+# Copyright (C) 2000-2006 TWiki Contributors.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. For
+# more details read LICENSE in the root of this distribution.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# As per the GPL, removal of this notice is prohibited.
+#
+# Configuration script for TWiki. Once you have a basic webserver
+# configuration that lets you access this script, the rest of the
+# configuration process is done from here. This script replaces
+# the old "testenv" script.
+#
+# The script works by accepting values into a CGI form, and then
+# submitting those values back to itself with a parameter (update)
+# set to 1. This causes it to write config changes to LocalSite.cfg.
+# Note that changes are only written if there is a real change in the
+# value.
+#
+# The values available to configuration are determined by parsing
+# TWiki.cfg. Special full-line comments guide the parse:
+# Any comment of the form
+#---+ Some text
+# is taken as a foldable block, and following comments are dragged in too.
+# ---++ is H3, ---+++ is H4 etc
+# Comments of the form
+# **TYPE opts**
+# where TYPE is one of URL, PATH, URLPATH, BOOLEAN, STRING, REGEX, SELECT
+# are used to indicate that a following cfg var is configurable through
+# the interface. All intermediate comments are taken as documentation for
+# the value.
+#
+package TWiki;
+
+# BASIC checks. Without these, nothing works.
+
+use strict;
+
+$SIG{__DIE__} = sub { Carp::confess( $_[0] || '' ) };
+$SIG{'__WARN__'} = sub { die @_ };
+
+use vars qw( %cfg
+ $perlver
+ $perlvernum
+ $perlverRequired
+ $perlverRequiredString
+ $perlverRecommended
+ $perlVerPreferred
+ $ActivePerlRecommendedBuild
+ $GUESSED
+ $cgiModVerRecommended
+ $modPerlVersionRecommended
+ $rcsverRequired
+ );
+
+# Constants
+$perlvernum = $];
+$perlverRequired = 5.00503; # Oldest supported version of Perl
+$perlverRequiredString = '5.005_03';
+$perlverRecommended = '5.6.1';
+$perlVerPreferred = 5.006; # 5.6 or higher has [:lower:] etc
+$ActivePerlRecommendedBuild = 631; # Fixes PERL5SHELL bugs
+$GUESSED = <<'HERE';
+I guessed this setting. You are advised to confirm this setting (and any other guessed settings) and hit 'Next' to save before changing any other settings.
+HERE
+
+# CGI.pm version, on some platforms - actually need CGI 2.93 for mod_perl
+# 2.0 and CGI 2.90 for Cygwin Perl 5.8.0. See
+# http://perl.apache.org/products/apache-modules.html#Porting_CPAN_modules_to_mod_perl_2_0_Status
+$cgiModVerRecommended = '2.93';
+
+# Recommended mod_perl version if using mod_perl 2.0
+# (see Support.RegistryCookerBadFileDescriptor)
+$modPerlVersionRecommended = '1.99_12';
+
+$rcsverRequired = 5.7;
+
+# constants used in TWiki.cfg
+use vars qw($TRUE $FALSE );
+use vars qw( $basicMods $requiredMods $requiredModsNonUnix $optionalMods
+ $I18Mods $I18Mods_perl56 $I18Mods_perl58 );
+
+BEGIN {
+ $TRUE = 1;
+ $FALSE = 0;
+ # Set default current working directory
+ if( $ENV{SCRIPT_FILENAME} && $ENV{SCRIPT_FILENAME} =~ /^(.+)\/[^\/]+$/ ) {
+ chdir $1;
+ }
+ # Get Perl version
+ if (defined $^V) {
+ $perlver = $^V; # New in Perl 5.6.1, one byte per part
+ $perlver = ord(substr($perlver,0)) . "." . ord(substr($perlver,1))
+ . "." . ord(substr($perlver,2));
+ } else {
+ $perlver = $perlvernum
+ }
+
+ # Required for configure to work
+ $basicMods =
+ {
+ 'CGI' => "basic TWiki",
+ 'CGI::Carp' => "basic TWiki",
+ 'Error' => 'basic TWiki',
+ };
+ $requiredMods =
+ {
+ 'File::Copy' => 'basic TWiki',
+ 'File::Spec' => 'basic TWiki',
+ 'FileHandle' => 'basic TWiki',
+ 'Algorithm::Diff' => 'basic TWiki',
+ };
+
+ # Required on non-Unix platforms (mainly Windows)
+ $requiredModsNonUnix =
+ {
+ 'MIME::Base64' => "SHA1 password encoding",
+ 'Net::SMTP' => "registration emails and mailnotify",
+ };
+ # Optional modules on all platforms
+ $optionalMods =
+ {
+ 'Digest::SHA1' => "SHA1 password encoding",
+ 'MIME::Base64' => "HTTP Authentication to proxies, and SHA1 password encoding",
+ 'POSIX' => "I18N (core module) and Security",
+ 'Digest::MD5' => "MD5 encoded passwords",
+ 'Text::Diff' => 'UpgradeTWiki',
+ 'CGI::Cookie' => "sessions",
+ 'CGI::Session' => "sessions",
+ };
+
+ $I18Mods =
+ {
+ 'Locale::Maketext::Lexicon' => "I18N translations",
+ };
+
+ $I18Mods_perl56 =
+ {
+ 'Unicode::String' => 'I18N conversions',
+ 'Unicode::MapUTF8' => "I18N conversions",
+ 'Unicode::Map' => "I18N conversions",
+ 'Unicode::Map8' => "I18N conversions",
+ 'Jcode' => "I18N conversions",
+ };
+
+ $I18Mods_perl58 =
+ {
+ 'Encode' => "I18N conversions (core module in Perl 5.8)",
+ };
+};
+
+########################################################################
+##################### GLOBAL VARIABLES #################################
+########################################################################
+
+use CGI qw( :any );
+
+use vars qw( $cygwinRcsVerNum $perltype $query $action );
+
+$query = new CGI;
+$action = $query->param('action') || '';
+
+if( $action eq 'image' ) {
+ _serveImage( $query->param('type'), $query->param('image' ));
+ exit 0;
+}
+
+use vars qw( $errors $toterrors $warnings $totwarnings $url $nextid );
+
+$errors = 0; # reset for each block
+$toterrors = 0;
+$warnings = 0; # reset for each block
+$totwarnings = 0;
+$url = $query->url();
+$nextid = 0;
+
+########################################################################
+########################## FORMATTING ##################################
+########################################################################
+
+# a note
+sub NOTE {
+ return CGI::p({class=>"info"}, join("\n",@_));
+}
+
+# a warning
+sub WARN {
+ $warnings++;
+ $totwarnings++;
+ return CGI::div(CGI::span({class=>'warn'}, CGI::strong('Warning: ').join("\n",@_)));
+}
+
+# an error
+sub ERROR {
+ $errors++;
+ $toterrors++;
+ return CGI::div(CGI::span({class=>'error'}, CGI::strong('Error: ').join("\n",@_)));
+}
+
+# Generate a foldable block (twisty). This is a DIV with a table in it
+# that contains the settings and doc rows.
+sub _foldableBlock {
+ my( $head, $attr, $body ) = @_;
+ my $headText = $head . CGI::span({ class => 'blockLinkAttribute' }, $attr);
+ $body = CGI::start_table({width => '100%', -border => 0, -cellspacing => 0, -cellpadding => 0}).$body.CGI::end_table();
+ my $mess = '';
+ my $errorsMess = ($errors > 1) ? ' errors' : ' error';
+ my $warningsMess = ($warnings > 1) ? ' warnings' : ' warning';
+ $mess .= CGI::span({class=>'error'}, $errors . $errorsMess) if $errors;
+ if ($errors && $warnings) {
+ $mess .= ' ';
+ }
+ $mess .= CGI::span({class=>'warn'}, $warnings . $warningsMess) if $warnings;
+ $errors = $warnings = 0;
+
+ my $anchor = _makeAnchor( $head );
+ my $id = $anchor;
+ my $blockId = $id;
+ my $linkId = 'blockLink'.$id;
+ my $linkAnchor = $anchor.'link';
+ return CGI::a({ name => $linkAnchor }).
+ CGI::a( {id => $linkId,
+ class => 'blockLink blockLinkOff',
+ href => '#'.$linkAnchor,
+ rel => 'nofollow',
+ onclick => 'foldBlock(\'' . $id . '\'); return false;'}, $headText.$mess).
+ CGI::div( { id => $blockId,
+ class=> 'foldableBlock foldableBlockClosed' }, $body ).
+ "\n";
+}
+
+# Generate an ordinary inline headedblock
+sub _ordinaryBlock {
+ my( $depth, $head, $attr, $body ) = @_;
+ $head .= CGI::span({ class => 'blockLinkAttribute' }, $attr) if $attr;
+ if( $depth == 2 ) { $head = CGI::h2( $head ); }
+ elsif( $depth == 3 ) { $head = CGI::h3( $head ); }
+ elsif( $depth == 4 ) { $head = CGI::h4( $head ); }
+ elsif( $depth == 5 ) { $head = CGI::h5( $head ); }
+ elsif( $depth == 6 ) { $head = CGI::h6( $head ); }
+ else { $head = CGI::h6( $head ); }
+ return CGI::Tr(CGI::td( { colspan => 2 } , $head)).
+ $body;
+}
+
+# Generate a sub-heading table row
+sub _subHead {
+ my $text = shift;
+ return CGI::Tr(CGI::Td({class=>'subHead', colspan=>2}, $text)).
+ "\n";
+}
+
+# Generate a variable - prompt row
+sub _setting {
+ my $key = shift;
+ return CGI::Tr(CGI::td({class=>'firstCol'}, $key).
+ CGI::td({class=>'secondCol'}, join(' ', @_)));
+}
+
+# generate a documentation table row
+sub _docBlock {
+ my $desc = shift || '';
+ my $hidden = shift;
+ if (length($desc) == 0 || $desc =~ /\A\s\Z/) {
+ return '';
+ }
+ if ($hidden) {
+ return CGI::Tr( {class => 'hiddenRow' }, CGI::td( { colspan => 2, class=>'docdata info' }, $desc )).
+ "\n";
+ }
+ return CGI::Tr( CGI::td( { colspan => 2, class=>'docdata info' }, $desc )).
+ "\n";
+}
+
+# encode a string to make an HTML anchor
+sub _makeAnchor {
+ my $str = shift;
+
+ $str =~ s/\s(\w)/uc($1)/ge;
+ $str =~ s/\W//g;
+ return $str;
+}
+
+########################################################################
+################### CHECKING SUPPORT ###################################
+########################################################################
+
+# Since Windows (without Cygwin) makes it hard to capture stderr
+# ('2>&1' works only on Win2000 or higher), and Windows will usually have
+# GNU tools in any case (installed for TWiki since there's no built-in
+# diff, grep, patch, etc), we only check for these tools on Unix/Linux
+# and Cygwin.
+sub _checkGnuProgram {
+ my $prog = shift;
+ my $n = '';
+
+ if( $TWiki::cfg{OS} eq 'UNIX' ||
+ $TWiki::cfg{OS} eq 'WINDOWS' && $perltype eq 'Cygwin' ) {
+ $prog =~ s/^\s*(\S+)\s.*$/$1/;
+ $prog =~ /^(.*)$/;
+ $prog = $1;
+ # check for taintedness
+ die "$prog is tainted" unless eval { $n = $prog, kill 0; 1 };
+ my $diffOut = ( `$prog --version 2>&1` || "");
+ my $notFound = ( $? == -1 );
+ if( $notFound ) {
+ $n = WARN("'$prog' program was not found on the",
+ "current PATH.");
+ } elsif ( $diffOut !~ /\bGNU\b/ ) {
+ # Program found on path, complain if no GNU in version output
+ $n = WARN("'$prog' program was found on the PATH",
+ "but is not GNU $prog - this may cause",
+ "problems. $diffOut");
+ } else {
+ $diffOut =~ /(\d+(\.\d+)+)/;
+ $n = "($prog is version $1).";
+ }
+ }
+
+ return $n;
+}
+
+sub _checkRCSProgram {
+ my $key = shift;
+
+ return 'Not used in this configuration.'
+ unless $TWiki::cfg{StoreImpl} eq 'RcsWrap';
+ my $mess = '';
+ my $err = '';
+ my $prog = $TWiki::cfg{RCS}{$key} || '';
+ $prog =~ s/^\s*(\S+)\s.*$/$1/;
+ $prog =~ /^(.*)$/; $prog = $1;
+ if( !$prog ) {
+ $err .= $key.' is not set';
+ } else {
+ my $version = `$prog -V` || '';
+ if( $@ ) {
+ $err .= ERROR($prog.' returned an error: '.$@ );
+ } elsif ( $version ne '' ) {
+ $version =~ /(\d+(\.\d+)+)/;
+ $version = $1;
+ $mess .= " ($prog is version $version)";
+ } else {
+ $err .= ERROR($prog.' did not return a version number (or might not exist..)');
+ }
+ if( defined( $cygwinRcsVerNum )) {
+ $mess .= " (Cygwin package rcs-$cygwinRcsVerNum)";
+ }
+ if( $version && $version < $rcsverRequired ) {
+ # RCS too old
+ $err .= $prog.' is too old, upgrade to version '.
+ $rcsverRequired.' or higher.';
+ }
+ }
+ if( $err ) {
+ $mess .= ERROR( $err .<$name" ) ||
+ return 'Could not create test file '. $name;
+ print FILE $txt1;
+ close( FILE);
+ open( IN_FILE, "<$name" ) ||
+ return 'Could not read test file '. $name;
+ my $txt2 = ;
+ close( IN_FILE );
+ unlink $name if( -e $name );
+ unless ( $txt2 eq $txt1 ) {
+ return 'Could not write and then read '.$name;
+ }
+ return '';
+}
+
+sub _checkTreePerms {
+ my( $path, $perms, $filter ) = @_;
+
+ return '' if( defined($filter) && $path !~ $filter && !-d $path);
+
+ #lets ignore Subversion directories
+ return '' if( $path !~ /_svn/ );
+ return '' if( $path !~ /.svn/ );
+
+ my $errs = '';
+
+ return $path. ' cannot be found'.CGI::br() unless( -e $path );
+
+ if( $perms =~ /r/ && !-r $path) {
+ $errs .= ' readable';
+ }
+
+ if( $perms =~ /w/ && !-d $path && !-w $path) {
+ $errs .= ' writable';
+ }
+
+ if( $perms =~ /x/ && !-x $path) {
+ $errs .= ' executable';
+ }
+
+ return $path.' is not '.$errs.CGI::br() if $errs;
+
+ return '' unless -d $path;
+
+ opendir(D, $path) ||
+ return 'Directory '.$path.' is not readable.'.CGI::br();
+
+ foreach my $e ( grep { !/^\./ } readdir( D )) {
+ my $p = $path.'/'.$e;
+ $errs .= _checkTreePerms( $p, $perms, $filter );
+ }
+ closedir(D);
+ return $errs;
+}
+
+sub _findFileOnPath {
+ my $file = shift;
+ $file =~ s(::)(/)g;
+
+ foreach my $dir ( @INC ) {
+ if ( -e "$dir/$file" ) {
+ return "$dir/$file";
+ }
+ }
+ return undef;
+}
+
+# Try and locate a required directory
+sub _findMajorDir {
+ my( $cfg, $dir ) = @_;
+ return '' if( $TWiki::cfg{$cfg} && $TWiki::cfg{$cfg} ne 'NOT SET');
+ my $guess = $ENV{SCRIPT_FILENAME};
+ unless( $guess ) {
+ return WARN("This web server does not set SCRIPT_FILENAME so I can't guess a value for this");
+ }
+ $guess =~ s(bin/*configure$)();
+ $guess .= $dir;
+ $TWiki::cfg{$cfg} = $guess;
+ return WARN($GUESSED);
+}
+
+sub _warnAboutWindowsBackSlashes {
+ my ( $path ) = @_;
+ if ( $path =~ /\\/ ) {
+ return WARN('You should use c:/path style slashes, not c:\path in "'.$path.'"');
+ }
+}
+
+########################################################################
+##################### PROMPT GENERATORS ################################
+########################################################################
+
+# generate an input field for string types
+sub _PROMPT_FOR_STRING {
+ my( $id, $opts, $value, $keys ) = @_;
+ my $size = "55%";
+ if( $opts =~ /\s(\d+)\s/ ) {
+ $size = $1;
+ # These numbers are somewhat arbitrary..
+ if($size>25) { $size="55%"; }
+ }
+
+ # support upgrade from old configuration, where LowerNational and UpperNational
+ # were stored as REGEX'es (now they are STRING's):
+ if ( $id eq "LowerNational" || $id eq "UpperNational" ) {
+ if ($value =~ /^\(\?-xism:(.*)\)$/) {
+ $value = $1;
+ }
+ }
+
+ return CGI::textfield( -name => $id, -size=>$size, -default=>$value );
+}
+
+# generate an input field for URL types
+# This has its own type in case someone wants to add javascript validation
+sub _PROMPT_FOR_URL {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
+}
+
+# generate an input field for URLPATH types
+# This has its own type in case someone wants to add javascript validation
+sub _PROMPT_FOR_URLPATH {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
+}
+
+# generate an input field for PATH types
+# This has its own type in case someone wants to add javascript validation
+sub _PROMPT_FOR_PATH {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
+}
+
+# generate an input field for BOOLEAN types
+sub _PROMPT_FOR_BOOLEAN {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::checkbox( -name => $id, -checked => ( $value ? 1 : 0),
+ -value => 1, -label => '' );
+}
+
+# generate an input field for REGEX types
+# This has its own type in case someone wants to add javascript validation
+sub _PROMPT_FOR_REGEX {
+ my( $id, $opts, $value, $keys ) = @_;
+ $value =~ s/[[\x01-\x09\x0b\x0c\x0e-\x1f"%&'*<=>@[_\|]/''.ord($&).';'/ge;
+ return '';
+}
+
+# generate an input field for COMMAND types
+# This has its own type in case someone wants to add javascript validation
+sub _PROMPT_FOR_COMMAND {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::textfield( -name => $id, -size=>"55%", -default=>$value );
+}
+
+# generate an input field for NUMBER types
+# This has its own type in case someone wants to add javascript validation
+sub _PROMPT_FOR_NUMBER {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::textfield( -name => $id, -size=>20, -default=>$value );
+}
+
+# generate an input field for OCTAL number types (protections)
+sub _PROMPT_FOR_OCTAL {
+ my( $id, $opts, $value, $keys ) = @_;
+ return CGI::textfield( -name => $id, -size=>20,
+ -default=>sprintf('0%o',$value) );
+}
+
+# generate an input field for SELECT types
+sub _PROMPT_FOR_SELECT {
+ my( $id, $opts, $value, $keys ) = @_;
+ $opts =~ s/^\s+//;
+ $opts =~ s/\s.*$//;
+ my $sopts = '';
+ if ( defined($value) ) {
+ $sopts .= '';
+ }
+ foreach my $opt (split( /\s*,\s*/, $opts)) {
+ if( $opt ne $value ) {
+ $sopts .= '';
+ }
+ }
+ return CGI::Select({ name => $id, size=>1 }, $sopts);
+}
+
+########################################################################
+###################### VARIABLE CHECKERS ###############################
+########################################################################
+
+sub _CHECKVAR_DefaultUrlHost {
+ my $keys = shift;
+
+ if( $TWiki::cfg{DefaultUrlHost} &&
+ $TWiki::cfg{DefaultUrlHost} ne 'NOT SET' ) {
+ my $host = $ENV{HTTP_HOST};
+ if( $host && $TWiki::cfg{DefaultUrlHost} !~ /$host/ ) {
+ return WARN('Current setting does not match HTTP_HOST ',
+ $ENV{HTTP_HOST});
+ }
+ } else {
+ my $protocol = $url || 'http://'.$ENV{HTTP_HOST};
+ $protocol =~ s(^(.*?://.*?)/.*$)($1);
+ $TWiki::cfg{DefaultUrlHost} = $protocol;
+ return ERROR($GUESSED);
+ }
+ return '';
+}
+
+sub _CHECKVAR_ScriptUrlPath {
+ # Check Script URL Path against REQUEST_URI
+ my $n;
+ my $val = $TWiki::cfg{ScriptUrlPath};
+ my $guess = $ENV{REQUEST_URI} || $ENV{SCRIPT_NAME} || '';
+ $guess =~ s(/+configure\b.*$)();
+
+ if( $val && $val ne 'NOT SET' ) {
+ unless( $guess ) {
+ return WARN(<Go to "pub" directory';
+}
+
+sub _CHECKVAR_PubDir {
+ my $e = _findMajorDir('PubDir', 'pub');
+ $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{PubDir});
+ my $e2 = _checkTreePerms( $TWiki::cfg{PubDir}, 'rw' );
+ $e .= WARN($e2) if $e2;
+ return $e;
+}
+
+sub _CHECKVAR_TemplateDir {
+ my $e = _findMajorDir('TemplateDir', 'templates');
+ $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{TemplateDir});
+ my $e2 = _checkTreePerms( $TWiki::cfg{TemplateDir}, 'r' );
+ $e .= ERROR($e2) if $e2;
+ return $e;
+}
+
+sub _CHECKVAR_DataDir {
+ my $e = _findMajorDir('DataDir', 'data');
+ my $e2 = _checkTreePerms( $TWiki::cfg{DataDir}, "r" );
+ $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{DataDir});
+ $e2 = _checkTreePerms( $TWiki::cfg{DataDir}, "w", qr/\.txt$/ )
+ unless $e2;
+ $e .= WARN($e2) if $e2;
+ return $e;
+}
+
+sub _CHECKVAR_LocalesDir {
+ my $e = _findMajorDir('LocalesDir', 'locale');
+ my $e2 = _checkTreePerms( $TWiki::cfg{LocalesDir}, "r" );
+ $e .= _warnAboutWindowsBackSlashes($TWiki::cfg{LocalesDir});
+ $e .= ERROR($e2) if $e2;
+ return $e;
+}
+
+sub _CHECKVAR_MailProgram {
+ eval "use Net::SMTP";
+ my $n;
+ if ($@) {
+ $n = "Net::SMTP is not installed in this environment. ";
+ my $val = $TWiki::cfg{MailProgram} || '';
+ $val =~ s/\s.*$//g;
+ if( ! ( -e $val ) ) {
+ return WARN("$val was not found. Check the path.");
+ }
+ } else {
+ $n = 'Net::SMTP is installed in this environment, so this setting will not be used.';
+ }
+ return $n;
+}
+
+sub _CHECKVAR_LogFileName {
+ my $logFile = $TWiki::cfg{LogFileName} || "";
+ $logFile =~ s/%DATE%/DATE/;
+ my $e = _checkCanCreateFile( $logFile );
+ $e = ERROR($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_ConfigurationLogName {
+ my $logFile = $TWiki::cfg{ConfigurationLogName} || "";
+ $logFile =~ s/%DATE%/DATE/;
+ my $e = _checkCanCreateFile( $logFile );
+ $e = ERROR($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_WarningFileName {
+ my $logFile = $TWiki::cfg{WarningFileName} || "";
+ $logFile =~ s/%DATE%/DATE/;
+ my $e = _checkCanCreateFile( $logFile );
+ $e = ERROR($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_DebugFileName {
+ my $logFile = $TWiki::cfg{DebugFileName} || "";
+ $logFile =~ s/%DATE%/DATE/;
+ my $e = _checkCanCreateFile( $logFile );
+ $e = ERROR($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_MimeTypesFileName {
+ my $e = _checkTreePerms($TWiki::cfg{MimeTypesFileName}, 'r');
+ $e = ERROR($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_Htpasswd_FileName {
+ my $e = _checkTreePerms($TWiki::cfg{Htpasswd}{FileName}, 'r');
+ $e = ERROR($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_RegistrationApprovals {
+ my $file = $TWiki::cfg{RegistrationApprovals};
+ my $e = _checkTreePerms( $file, 'rw' );
+ $e = WARN($e) if $e;
+ return $e;
+}
+
+sub _CHECKVAR_UseLocale {
+ my $on = $TWiki::cfg{UseLocale};
+
+ my $n = '';
+ if( $TWiki::cfg{OS} eq 'WINDOWS' ) {
+ # Warn re known broken locale setup
+ $n .= WARN(<= 5.008 and
+ not ( exists $Config::Config{useperlio} and
+ $Config::Config{useperlio} eq 'define' ) ) {
+ $n .= WARN(<Perl's Unicode Model in 'perldoc
+perluniintro') - re-compilation of Perl will be required before it can be
+used to enable TWiki's experimental UTF-8 support.
+HERE
+ );
+ }
+
+ # Check for d_setlocale in Config (same as 'perl -V:d_setlocale')
+ eval "use Config";
+ if ( !( exists $Config::Config{d_setlocale} &&
+ $Config::Config{d_setlocale} eq 'define' ) ) {
+ $n .= WARN(<$forUpperNat
+HERE
+ );
+ }
+ }
+ return '';
+}
+
+sub _CHECKVAR_LowerNational {
+ if( $perlvernum < $perlVerPreferred || 1) {
+ # Locales are off/broken, or using pre-5.6 Perl, so have to
+ # explicitly list the accented characters (but not if using UTF-8)
+ my $forLowerNat = join '', grep { uc($_) ne $_ and m/[^a-z]/ } map { chr($_) } 1..255;
+
+ if ($forLowerNat) {
+ return WARN( <$forLowerNat
+HERE
+ );
+ }
+ }
+ return '';
+}
+
+sub _CHECKVAR_Site_Locale {
+ my $e = '';
+ my $locale = $TWiki::cfg{Site}{Locale};
+ setlocale(&LC_CTYPE, $locale);
+ my $currentLocale = setlocale(&LC_CTYPE);
+ if ( $currentLocale ne $locale ) {
+ $e .= WARN(<C, which should always work.
+HERE
+ );
+ }
+ if( $locale !~ /[a-z]/i && $TWiki::cfg{UseLocale} ) {
+ $e = WARN(<path_info() =~ /$TWiki::cfg{ScriptSuffix}$/ ) {
+ return ERROR('this script ('.$query->pather_info().') called with different ScriptSuffix setting'.$TWiki::cfg{ScriptSuffix});
+ }
+ }
+ return '';
+}
+
+sub _CHECKVAR_RCS_EgrepCmd { return _checkGnuProgram($TWiki::cfg{RCS}{EgrepCmd}); }
+sub _CHECKVAR_RCS_FgrepCmd { return _checkGnuProgram($TWiki::cfg{RCS}{FgrepCmd}); }
+sub _CHECKVAR_RCS_initTextCmd { return _checkRCSProgram('initTextCmd'); }
+sub _CHECKVAR_RCS_initBinaryCmd { return _checkRCSProgram('initBinaryCmd'); }
+sub _CHECKVAR_RCS_tmpBinaryCmd { return _checkRCSProgram('tmpBinaryCmd'); }
+sub _CHECKVAR_RCS_ciCmd { return _checkRCSProgram('ciCmd'); }
+sub _CHECKVAR_RCS_ciDateCmd { return _checkRCSProgram('ciDateCmd'); }
+sub _CHECKVAR_RCS_coCmd { return _checkRCSProgram('coCmd'); }
+sub _CHECKVAR_RCS_histCmd { return _checkRCSProgram('histCmd'); }
+sub _CHECKVAR_RCS_infoCmd { return _checkRCSProgram('infoCmd'); }
+sub _CHECKVAR_RCS_rlogDateCmd { return _checkRCSProgram('rlogDateCmd'); }
+sub _CHECKVAR_RCS_diffCmd { return _checkRCSProgram('diffCmd'); }
+sub _CHECKVAR_RCS_lockCmd { return _checkRCSProgram('lockCmd'); }
+sub _CHECKVAR_RCS_unlockCmd { return _checkRCSProgram('unlockCmd'); }
+sub _CHECKVAR_RCS_delRevCmd { return _checkRCSProgram('delRevCmd'); }
+
+sub _CHECKVAR_StoreImpl {
+ my $mess = '';
+ if( $TWiki::cfg{StoreImpl} eq 'RcsWrap') {
+ # Check that GNU diff is found in PATH; used by rcsdiff
+ $mess .= NOTE( "Note: The 'diff' program found on the path is used by RcsWrap to compare revisions ".
+ _checkGnuProgram( "diff"));
+ }
+
+ return $mess;
+};
+
+sub _CHECKVAR_UseClientSessions {
+ my $mess = '';
+ if (!eval "use CGI::Cookie; 1") {
+ $mess .= <$class}, $prompter) if $mandatory;
+ use strict 'refs';
+
+ $keys = CGI::span({class=>'mandatory'}, $keys) if $mandatory;
+ my $hidden = 0;
+ if (length($desc) == 0 || $desc =~ /\A\s\Z/) {
+ $hidden = 1;
+ }
+ return _docBlock( $output.$desc, $hidden )._setting( $keys, $prompter );
+}
+
+sub _showPlugins {
+ my %modules;
+ foreach my $libDir ( @INC ) {
+ if( opendir( DIR, "$libDir/TWiki/Plugins" ) ) {
+ foreach my $file ( grep { /^[A-Za-z0-9_]+Plugin\.pm$/ }
+ readdir DIR ) {
+ my $module = $file;
+ $module =~ s/\.pm$//;
+ $TWiki::cfg{Plugins}{$module}{Enabled} ||= 0;
+ $module =~ /^(.*)$/; # untaint
+ $module = $1;
+ # only add the first instance of any plugin, as only
+ # the first can get loaded from @INC.
+ unless( $modules{$module} ) {
+ $modules{$module} = $libDir;
+ }
+ closedir( DIR );
+ }
+ }
+ }
+ my $block = '';
+ foreach my $m ( sort keys %modules ) {
+ $block .= _checkAndBuildValueGrabber
+ ( 'BOOLEAN', '',
+#SMELL - i'm assuming that the Plugin topic is in the SystemWeb :(
+"$m",
+ '{Plugins}{'.$m.'}{Enabled}'
+ );
+ }
+ return $block;
+}
+
+sub _showLanguages {
+ opendir( DIR, $TWiki::cfg{LocalesDir}) or
+ return 'Couldn\'t read TWiki {LocalesDir}!';
+ my $block = '';
+ foreach my $file ( grep { /^.*\.po$/ } readdir DIR ) {
+ $file =~ m/^(.*)\.po$/;
+ my $lang = $1;
+ $lang = "'$lang'" if $lang =~ /\W/;
+ $block .= _checkAndBuildValueGrabber ( 'BOOLEAN', '', 'Enable the language ' . $lang . '', '{Languages}{' . $lang . '}{Enabled}' );
+ }
+ closedir( DIR );
+ return $block;
+}
+
+########################################################################
+##################### WRITING NEW VALUES ###############################
+########################################################################
+
+sub setConfig {
+ my ($path, $updates) = @_;
+ my $txt = '';
+ if( open(F, "<$path")) {
+ undef $/;
+ $txt = ;
+ close(F);
+ }
+
+ $txt =~ s/^\s*1;\s*$//gm;
+
+ open(F, ">$path") ||
+ die "Failed to open $path for write";
+
+ foreach my $config ( keys %$updates ) {
+ # kill the old settings if any are there
+ $txt =~ s/\$TWiki::cfg$config\s*=.*?;\s*\n//s;
+ $txt .= '$TWiki::cfg'.$config.' = '.$updates->{$config}.";\n";
+ }
+ print F $txt,"1;\n";
+ close(F);
+
+ if( defined( $TWiki::cfg{ConfigurationLogName} ) &&
+ open(F, '>>'.$TWiki::cfg{ConfigurationLogName} )) {
+ my $date = gmtime();
+ my $user = $query->remote_user() || 'guest';
+ foreach my $config ( keys %$updates ) {
+ print F '| ',$date,' | ',$user,' | ',$config,' | ',
+ $updates->{$config}," |\n";
+ }
+ close(F);
+ }
+}
+
+# Convert value to a canonical perl representation suitable for writing
+# to LocalSite.cfg
+sub _perlifyType {
+ my ($val,$type) = @_;
+
+ if ($type eq 'BOOLEAN') {
+ return ($val ? 1 : 0);
+ } elsif ($type eq 'NUMBER') {
+ $val ||= 0;
+ return 0+$val;
+ } elsif ($type eq 'OCTAL') {
+ $val ||= 0;
+ $val = '0'.$val unless $val =~ /^0/;
+ return $val;
+ } else {
+ $val ||= '';
+ $val =~ s/'/\\'/g;
+ return "'".$val."'";
+ }
+}
+
+sub _perlModulesCheck {
+ my $mods = shift;
+ my $e = '';
+ foreach my $mod (keys %$mods) {
+ my $n = '';
+ eval "use $mod";
+ if ($@) {
+ $n = WARN('not installed. May be required for ',
+ $mods->{$mod});
+ } else {
+ my $mod_version;
+ no strict 'refs';
+ eval '$mod_version = ${'.$mod.'::VERSION}';
+ use strict 'refs';
+ $n = $mod_version || 'unknown';
+ }
+ $e .= _setting($mod, $n);
+ }
+ return $e;
+}
+
+########################################################################
+#################### MAIN ACTION ENTRY POINTS ##########################
+########################################################################
+
+sub _serveImage {
+ my($type, $image )= @_;
+
+ print "Content-type: $type\n\n";
+ if( open(F, "logos/$image")) {
+ local $/ = undef;
+ print ;
+ close(F);
+ }
+}
+
+sub handleUpdate {
+ my $path = shift;
+ my $pass = $query->param( 'cfgAccess' );
+ my $param;
+ my $output = '';
+ unless( defined( $pass )) {
+ $output .= CGI::start_form({ action=>$ENV{SCRIPT_NAME}, method=>"post" });
+ # Pass all URL params through
+ foreach $param ( $query->param ) {
+ $output .= CGI::hidden( $param, $query->param( $param ));
+ $output .= "\n";
+ }
+
+ my $changed = calculateChanges();
+ my $itemText = ($changed == 1) ? 'item' : 'items';
+ $output .= CGI::div({ class => 'explanation'},
+ CGI::strong( 'Changing ' . $changed.
+ ' configuration ' . $itemText.
+ '.').
+ (($changed == 0) ? CGI::br() .
+ CGI::a( { href=>$url.'?t='.time(),
+ rel => 'nofollow' },
+ 'Return to configuration') : CGI::br() .
+ 'Proceed with the steps below to save your changes.'));
+
+ # and add a few more
+ $output .= CGI::h2('Enter the configuration password');
+ if ($TWiki::cfg{Password} ne '') {
+ $output .= CGI::p(CGI::strong("Your Password:").CGI::br());
+ $output .= CGI::password_field( 'cfgAccess', '', 20, 80 );
+ $output .= ' ' . CGI::submit(-class=>'twikiSubmit', -value=>'Save changes');
+ $output .= CGI::br();
+ } else {
+ $output .= CGI::hidden( 'cfgAccess', '' );
+ }
+ my $forgotPassword = '';
+ if ($TWiki::cfg{Password} ne '') {
+ $forgotPassword = CGI::strong("Forgot your password?"). CGI::br(). 'To reset the password, log in to the server and delete the $TWiki::cfg{Password} = \'...\'; line in lib/LocalSite.cfg';
+ }
+ $output .= CGI::div({ class => 'explanation'},
+ CGI::span( $forgotPassword . CGI::img({src=>$ENV{SCRIPT_NAME}.'?action=image;image=warning.gif;type=image/gif', alt=>''}) . ' ' . <<'HERE'
+Notes on Security:
+
+
If you don't set a password, or the password is cracked, then configure could be used to do very nasty things to your server.
+
If you are running TWiki on a public website, you are strongly advised to disable saving from configure by making lib/LocalSite.cfg readonly once you are happy with your configuration.
+
+HERE
+ ));
+ if ($TWiki::cfg{Password} ne '') {
+ $output .= CGI::p( "You may change your password here:" );
+ }
+
+ $output .= CGI::div({ class => 'formElem'},
+
+ CGI::strong("New Password:").
+ CGI::br().
+ CGI::password_field( 'newCfgP', '', 20, 80 ).
+ CGI::br().
+ CGI::strong("Confirm Password:").CGI::br().
+ CGI::password_field( 'confCfgP', '', 20, 80 ).
+ CGI::br().
+ CGI::submit(-class=>'twikiSubmit', -value=>'Set Password and Save changes'));
+ $output .= CGI::end_form();
+ $output .= CGI::end_html();
+ return $output;
+ }
+
+ unless( crypt( $pass, $TWiki::cfg{Password}) eq
+ $TWiki::cfg{Password} || $TWiki::cfg{Password} eq '') {
+ $output .= CGI::span( {class => 'error' }, "Incorrect password" ).
+ CGI::end_html();
+ return $output;
+ }
+
+ my $changed = 0;
+ my %updates;
+
+ if( $query->param( 'newCfgP' )) {
+ if( $query->param( 'newCfgP' ) eq
+ $query->param( 'confCfgP' )) {
+ my @saltchars = ( 'a'..'z', 'A'..'Z', '0'..'9', '.', '/' );
+ my $salt = $saltchars[int(rand($#saltchars+1))] .
+ $saltchars[int(rand($#saltchars+1)) ];
+ $updates{'{Password}'} =
+ _perlifyType(
+ crypt( $query->param( 'newCfgP' ), $salt ),
+ 'STRING' );
+ $changed++;
+ $output .= "Password changed";
+ } else {
+ $output .= "New password and confirmation do not match";
+ return $output;
+ }
+ }
+
+ $output .= CGI::h2('Updating configuration');
+ foreach $param ( $query->param ) {
+ next unless $param =~ /^^TYPEOF:(.*)/;
+ my $type = $query->param( $param );
+ $param =~ s/^TYPEOF:(.*)$/$1/;
+ my $basevar = $1;
+ my $var = '$TWiki::cfg'.$basevar;
+ my $val = $query->param( $param );
+ my $def;
+ eval "\$def = defined( $var );";
+ if( $type ) {
+ eval "\$def = $var;" if $def;
+ next if( $type eq 'OCTAL' && sprintf('0%o', $def) =~ /^0*$val$/ );
+ next if( $type eq 'NUMBER' && $val + 1 == $def + 1 );
+ next if( $type eq 'BOOLEAN' && ($val && $def || !$val && !$def));
+ next if( $val eq $def );
+ $output .= CGI::h3($var).
+ CGI::b('old ').
+ CGI::code($def||' ').
+ CGI::br().
+ CGI::b('new ').
+ CGI::code($val||' ');
+ $updates{$basevar} = _perlifyType($val, $type);
+ $changed++;
+ }
+ }
+ $output .= CGI::p();
+ setConfig($path, \%updates);
+ my $itemText = ($changed == 1) ? 'item' : 'items';
+ $output .= CGI::hr();
+ $output .= CGI::p(CGI::strong($changed.' configuration ' . $itemText . ' changed. '));
+ $output .= CGI::p(CGI::a({ rel => 'nofollow',
+ href=>$url.'?t='.time() },
+ 'Return to configuration'));
+ return $output;
+}
+
+sub calculateChanges {
+ my $param;
+ my $changed = 0;
+ foreach $param ( $query->param ) {
+ next unless $param =~ /^^TYPEOF:(.*)/;
+ my $type = $query->param( $param );
+ $param =~ s/^TYPEOF:(.*$)/$1/;
+ my $var = '$TWiki::cfg'.$1;
+ my $val = $query->param( $param );
+ my $def;
+ eval "\$def = defined( $var );";
+ if( $type ) {
+ eval "\$def = $var;" if $def;
+ next if( $type eq 'OCTAL' && sprintf('0%o', $def) =~ /^0*$val$/ );
+ next if( $type eq 'NUMBER' && $val + 1 == $def + 1 );
+ next if( $type eq 'BOOLEAN' && ($val && $def || !$val && !$def));
+ next if( $val eq $def );
+ $changed++;
+ }
+ }
+ return $changed;
+}
+
+sub performSanityChecks {
+ my( $brokenTWikiCfgError, $brokenLocalSiteError ) = @_;
+ my $output = '';
+
+ if ($brokenTWikiCfgError) {
+ $output .= CGI::h2('WARNING:').
+ CGI::p('TWiki.cfg is unreadable or has a configuration problem that is causing a Perl error - the following message(s) should help locate the problem.');
+ $output .= $brokenTWikiCfgError;
+
+ # EARLY EXIT
+ $output .= CGI::end_html();
+ return $output;
+ }
+
+ if ($brokenLocalSiteError) {
+ $output .= CGI::h2('WARNING:').
+ ERROR('LocalSite.cfg is unreadable or has a configuration problem that is causing a Perl error - the following message(s) was generated:').
+ CGI::pre($brokenLocalSiteError).
+ 'The @INC path is '.
+ CGI::pre(join(":", @INC)).
+ NOTE('This may be because this is the first time you have run configure. In this case you can simply ignore this error until you have filled in your General path settings. Otherwise, check that the file exists, and the webserver user is allowed to read it.');
+ }
+
+ # Check whether basic CGI modules exist (some broken installations of
+ # Perl don't have this, even though they are standard modules), and warn user
+ my $modMissing = 0;
+ foreach my $mod (keys %$basicMods) {
+ eval "use $mod";
+ if ($@) {
+ unless ($modMissing) {
+ $output .= ERROR( 'Perl Module(s) missing');
+ }
+ $modMissing = 1;
+ $output .= ERROR( 'Essential Perl Module \'',$mod,
+ '\' not installed - please check the setting ',
+ 'of @INC.' );
+ }
+ }
+
+ # If any critical modules missing, display @INC and give up
+ if ($modMissing) {
+ $output .= NOTE( '@INC = ', join( ' ', @INC ));
+ return $output;
+ }
+
+ return $output;
+}
+
+sub presentReadOnlyInfo {
+ # use strict; # Recommended for mod_perl, enable for Perl 5.6.1 only
+ # Doesn't work well here, due to 'do "TWiki.cfg"'
+ # use diagnostics; # Debug only
+
+ # Load CGI modules (run-time, after checking they are accessible)
+ require CGI;
+ import CGI qw( -any );
+ require CGI::Carp;
+ import CGI::Carp qw( fatalsToBrowser );
+
+ $errors = 0;
+ $warnings = 0;
+
+ my $output = '';
+ my $block = '';
+ for my $key ( sort keys %ENV ) {
+ $block .= _setting($key, $ENV{$key});
+ }
+ $output .= _foldableBlock(CGI::em( 'Environment variables' ),
+ '(read only) ', $block);
+
+ $block = '';
+
+ # Make %ENV safer for CGI (should reflect TWiki.pm)
+ my $originalPath = $ENV{PATH} || '';
+ if( $TWiki::cfg{SafeEnvPath} ) {
+ # SMELL: this untaint probably isn't needed
+ my $ut = $TWiki::cfg{SafeEnvPath};
+ $ut =~ /^(.*)$/;
+ $ENV{PATH} = $1;
+ }
+ delete @ENV{ qw( IFS CDPATH ENV BASH_ENV ) };
+ my $perlverMsg = $perlver; # Default version message
+
+ # Load Config module - used here and elsewhere
+ require Config;
+
+ # Set $TWiki::cfg{DetailedOS} if not using later versions of TWiki.cfg for BeijingRelease
+ # - this code enables the latest testenv to be used with Dec 2001 and
+ # earlier releases.
+ if ( !defined $TWiki::cfg{DetailedOS} ) {
+ $TWiki::cfg{DetailedOS} = $Config::Config{'osname'};
+ }
+
+ # Detect Perl flavour on Windows, and Cygwin Perl/RCS package versions
+
+ if ($TWiki::cfg{DetailedOS} eq 'cygwin') {
+ $perltype = 'Cygwin'; # Cygwin Perl only
+ my ($pkg, $pkgName);
+
+ # Get Cygwin perl's package version number
+ $pkgName = 'perl';
+ $pkg = `/bin/cygcheck -c $pkgName | /bin/grep $pkgName 2>/dev/null`;
+ if ($?) {
+ $pkg = " [Cannot identify package - cygcheck or grep not installed]";
+ $perlverMsg = $perlver . $pkg
+ } else {
+ $pkg = (split ' ', $pkg)[1]; # Package version
+ $perlverMsg = $pkg;
+ }
+
+ # Get Cygwin RCS's package version number
+ $pkgName = 'rcs';
+ $pkg = `/bin/cygcheck -c $pkgName | /bin/grep $pkgName 2>/dev/null`;
+ if ($?) {
+ $pkg = " [Cannot identify package - cygcheck or grep not installed]";
+ $cygwinRcsVerNum = $pkg;
+ } else {
+ $pkg = (split ' ', $pkg)[1]; # Package version
+ $cygwinRcsVerNum = $pkg;
+ }
+ } elsif ($TWiki::cfg{DetailedOS} =~ /win/i && $TWiki::cfg{DetailedOS} !~ /darwin/i ) {
+ # Windows Perl - try ActivePerl-only function: returns number if
+ # successful, otherwise treated as a literal (bareword).
+ my $isActivePerl= eval 'Win32::BuildNumber !~ /Win32/';
+ if( $isActivePerl ) {
+ $perltype = 'ActiveState';
+ $perlverMsg = $perlver . ", build " . Win32::BuildNumber();
+ } else {
+ # Could be SiePerl or some other Win32 port of Perl
+ $perltype = 'SiePerl or other Windows Perl';
+ }
+ } else {
+ $perltype = 'generic';
+ }
+
+ # Detect executable name suffix, e.g. .exe on Windows or '' on Unix
+ # Avoid testing for .exe suffixes on Cygwin, since the built-in
+ # grep and ls don't end in '.exe', even though Perl's '_exe' setting
+ # indicates they should.
+ my $exeSuffix='';
+ if ( $Config::Config{'_exe'} and ($TWiki::cfg{OS} eq 'WINDOWS' and $perltype ne 'Cygwin') ) {
+ if ( ! $ENV{INTERIX_ROOT} ) { #this is set is we are using UnixServicesForWindows (or INTERIX funnily enough) and they don't use .exe either
+ $exeSuffix = $Config::Config{'_exe'};
+ }
+ }
+
+ # Detect whether mod_perl was loaded into Apache
+ my $modPerlLoaded = ( exists $ENV{SERVER_SOFTWARE} &&
+ ( $ENV{SERVER_SOFTWARE} =~ /mod_perl/ ));
+ # Detect whether we are actually running under mod_perl
+ # - test for MOD_PERL alone, which is enough.
+ my $usingModPerl = ( exists $ENV{MOD_PERL} );
+ my $modPerlVersion;
+
+ # Get the version of mod_perl if it's being used
+ if ( $usingModPerl ) {
+ $modPerlVersion = eval 'use mod_perl; return $mod_perl::VERSION';
+ $block .= _setting('',
+ WARN(<configure with mod_perl. This
+is risky because mod_perl will remember old values of configuration
+variables. You are *highly* recommended not to run configure under
+mod_perl (though the rest of TWiki can be run with mod_perl, of course)
+HERE
+ ));
+ }
+
+ my $n = ucfirst(lc($TWiki::cfg{OS}));
+ $n .= " ($TWiki::cfg{DetailedOS})" if ( $TWiki::cfg{DetailedOS} ne '' );
+ # OS
+ $block .= _setting("Operating system", $n);
+
+ # Perl version and type
+ $perlverMsg .= " ($perltype)" if $perltype ne 'generic';
+ $block .= _setting("Perl version", $perlverMsg);
+
+ if ( $perlvernum < $perlverRequired ) {
+ $block .= _setting('',
+ WARN(<twiki/lib and check that LocalSite.cfg is present and readable");
+ } else {
+ $twikiFound = 1;
+ my $mod_version = eval '$TWiki::wikiversion || $TWiki::VERSION';
+ $mod_version ||= 'unknown';
+ $mess = 'OK, TWiki.pm found (Version: '.$mod_version.')';
+ }
+ $block .= _setting('TWiki module in @INC path', $mess);
+
+ #add in the basic Modules so that we list their versions in the UI
+ map { $requiredMods->{$_} = $basicMods->{$_} }
+ keys %$basicMods;
+
+ if ( defined $TWiki::cfg{DetailedOS} and ($TWiki::cfg{DetailedOS} =~ /darwin/i or $TWiki::cfg{OS} ne 'UNIX') ) {
+ map { $requiredMods->{$_} = $requiredModsNonUnix->{$_} }
+ keys %$requiredModsNonUnix;
+ } else {
+ # these are optional on Unix
+ map { $optionalMods->{$_} = $requiredModsNonUnix->{$_} }
+ keys %$requiredModsNonUnix;
+ }
+
+ # Check that each of the required Perl modules can be loaded, and
+ # print its version number.
+ my $set = '';
+ foreach my $mod (keys %$requiredMods) {
+ eval "use $mod";
+ if ($@) {
+ $set .= _setting($mod, ERROR("not installed. Required for ",
+ $requiredMods->{$mod}));
+ } else {
+ my $mod_version;
+ no strict 'refs';
+ eval '$mod_version = ${'.$mod.'::VERSION}';
+ use strict 'refs';
+ $n = $mod_version || 'unknown';
+ # Check for potential CGI.pm module upgrade
+ if( $mod eq 'CGI' and $mod_version < $cgiModVerRecommended ) {
+ if ( $perltype eq 'Cygwin' and $perlver eq '5.8.0' ) {
+ # Recommend CGI.pm upgrade if using Cygwin Perl 5.8.0
+ $n .= WARN( "CGI.pm version $cgiModVerRecommended or higher",
+ "is recommended to avoid problems with attachment",
+ "uploads on Cygwin Perl $perlver.");
+ } elsif ( $usingModPerl and $modPerlVersion >= 1.99 ) {
+ # Recommend CGI.pm upgrade if using mod_perl 2.0, which
+ # is reported as version 1.99 and implies Apache 2.0
+ $n .= WARN("CGI.pm version $cgiModVerRecommended or higher is",
+ "recommended to avoid problems with mod_perl version",
+ "$modPerlVersion on Apache 2.0 or higher.");
+ }
+ }
+ $set .= _setting( $mod, $n );
+ }
+ }
+ $block .= _setting("Required Perl modules",
+ CGI::start_table({width=>'100%'}).
+ $set.CGI::end_table());
+
+ # Check that each of the optional Perl modules can be loaded, and
+ # print its version number.
+ $set = _perlModulesCheck( $optionalMods );
+ $set .= _perlModulesCheck( $I18Mods );
+ $set .= _perlModulesCheck( $] >= 5.008 ? $I18Mods_perl58 : $I18Mods_perl56 );
+ $block .= _setting("Optional Perl Modules",
+ CGI::start_table({width=>'100%'}).
+ $set.CGI::end_table());
+
+ # All module checks done, OK to enable fatalsToBrowser
+ import CGI::Carp qw( fatalsToBrowser );
+
+ # PATH_INFO
+ $block .= _setting(CGI::a({name=>'PATH_INFO'},'PATH_INFO'), $query->path_info().
+ NOTE(<$url/foo/bar,
+the correct PATH_INFO is /foo/bar, without any prefixed path
+components.
+Click here to test this
+- particularly if you are using mod_perl, Apache or IIS, or are using
+a web hosting provider.
+Look at the new path info here. It should be /foo/bar.
+HERE
+ ));
+
+ # mod_perl
+ if( $usingModPerl ) {
+ $n = "Used for this script";
+ } else {
+ $n = "Not used for this script";
+ }
+ $n .= NOTE( 'mod_perl is ', $modPerlLoaded ? '' : 'not',
+ ' loaded into Apache' );
+ if ( $modPerlVersion ) {
+ $n .= NOTE( 'mod_perl version ', $modPerlVersion );
+ }
+
+ # Check for a broken version of mod_perl 2.0
+ if ( $usingModPerl && $modPerlVersion =~ /1\.99_?11/ ) {
+ # Recommend mod_perl upgrade if using a mod_perl 2.0 version
+ # with PATH_INFO bug (see Support.RegistryCookerBadFileDescriptor
+ # and Bugs:Item82)
+ $n .= ERROR(<) ); # Unix/Cygwin Perl - effective UID
+ $grp = join(',', map { lc(getgrgid( $_ )) } split( " ", $( ) );
+ } else { # ActiveState or other Win32 Perl
+ $usr = lc( getlogin );
+ # Try to use Cygwin's 'id' command - may be on the path, since Cygwin
+ # is probably installed to supply ls, egrep, etc - if it isn't, give up.
+ # Run command without stderr output, to avoid CGI giving error.
+ # Get names of primary and other groups.
+ $grp = lc(qx(sh -c '( id -un ; id -gn) 2>/dev/null' 2>nul ));
+ if ($?) {
+ $grp = "[Cannot identify groups - no Cygwin 'id' or 'sh' command on path]";
+ }
+ }
+
+ $block .= _setting('CGI user', 'userid = '.$usr.' groups = '.
+ $grp.''.
+ NOTE('Your CGI scripts are executing as this user.'));
+
+ $block .= _setting("Original PATH", $originalPath.
+ NOTE(<recommended if Cygwin is installed).
+
Use this page to set the configuration options for TWiki. Fill in the settings, and then press 'Next'.
";
+ $body .= "
";
+ $body .= CGI::img({src=>$ENV{SCRIPT_NAME}.'?action=image;image=info.gif;type=image/gif', alt=>''}) . ' ';
+ $TWiki::cfg{ScriptUrlPath} ||= '';
+ $TWiki::cfg{ScriptSuffix} ||= '';
+ $TWiki::cfg{SystemWebName} ||= '';
+ $body .= <If you are installing TWiki for the first time If you just want to get up and running, the only section you need to worry about below is
+General path settings. You can always come
+back and configure other settings later.
You will now need to consider how you are going to manage authentication and access control. See the reference manual sections on authentication and access control, and the Security Setup section below.
If you get stuck there is a lot of support available on TWikiIRC (irc.freenode.net, channel #twiki) and at TWiki:Support.
+
+
+
Explanation of color codes:
+
+
Settings marked like this are required (they must
+have a value).
+
Any errors in your configuration will be highlighted.
+
Warnings are non-fatal, but are often a good indicator that something that is wrong.
+
+HERE
+
+ $body .= performSanityChecks( $brokenTWikiCfgError, $brokenLocalSiteError );
+
+ my $options = '';
+ unless( $update_disabled ) {
+ $body .= CGI::start_form({ action=>$ENV{SCRIPT_NAME},method=>"post" });
+ # use time to make sure we never allow cacheing
+ $options .= CGI::hidden( 'action', 'update' );
+ $options .= CGI::hidden( 'time', time() );
+ }
+ $options .= CGI::div({ class => 'optionHeader'},
+ CGI::span({ class => 'twikiLeft' }, 'Settings' .
+ CGI::span({ class => 'twikiSmall' },
+ 'Click the buttons below to open each section')).
+ CGI::span({ class => 'twikiSmall twikiRight' },
+ CGI::a({ href => '#', rel => 'nofollow',
+ onclick => 'toggleAllOptions(true); return false;'}, 'Open all options')).
+ CGI::br());
+
+ $options .= presentReadOnlyInfo();
+
+ $options .= presentEditableInfo();
+
+ $body .= CGI::div({class=>'options', id=>'options'}, $options);
+ my $totwarningsMess = ($totwarnings > 1) ? ' warnings' : ' warning';
+ $body .= CGI::div('Total: '.CGI::span(
+ {class=>'warn'}, $totwarnings . $totwarningsMess)) if $totwarnings;
+ my $toterrorsMess = ($toterrors > 1) ? ' errors' : ' error';
+ $body .= CGI::div('Total: ' . CGI::span(
+ {class=>'error'}, $toterrors . $toterrorsMess)) if $toterrors;
+
+ if( $update_disabled) {
+ $body .= CGI::em("Update is disabled - $update_disabled");
+ } else {
+ $body .= CGI::p(CGI::submit(-class=>'twikiSubmit', -value=>'Next', -accesskey=>'N'));
+ $body .= CGI::end_form();
+ }
+
+}
+print CGI::div({class => 'patternMain'}, $body);
+print CGI::end_html();
+
+1;
Index: bin/.htaccess.txt
===================================================================
--- bin/.htaccess.txt (.../TWikiRelease04x00) (revision 9301)
+++ bin/.htaccess.txt (.../DEVELOP) (revision 9301)
@@ -1,17 +1,19 @@
# bin/.htaccess.txt
#
# Controls access to TWiki scripts - to make Apache use it, rename this
-# file to '.htaccess' and REPLACE THE FOLLOWING STRINGS WHEREVER YOU SEE
-# THEM IN THIS FILE WITH PATHS SPECIFIC TO YOUR INSTALLATION.
-# Most required values can be seen in the Path Settings section of
-# =configure=.
+# file to '.htaccess' and REPLACE THE FOLLOWING STRINGS WITH PATHS
+# SPECIFIC TO YOUR INSTALLATION. Most required values can be seen in the
+# Path Settings section of =configure=.
#
-# Replace {DataDir} with the value from =configure=
-# Replace {DefaultUrlHost} with the value from =configure=
-# Replace {ScriptUrlPath} with the value from =configure=
-# Replace {Administrators} with a space-separated list of the login
-# name(s) of the person(s) allowed to run the configure script
-# e.g. admin root superhero
+# {DataDir}
+# Get the value from =configure=
+# {DefaultUrlHost}
+# Get the value from =configure=
+# {ScriptUrlPath}
+# Get the value from =configure=
+# {Administrators}
+# Space-separated list of the login name(s) of the person(s) allowed
+# to run the configure script
# Use CGI & Perl to handle all files in 'bin' directory, i.e. run as scripts
# - this should remove the need to rename files to end in '.pl' etc,
Index: bin/update-develop-links
===================================================================
--- bin/update-develop-links (.../TWikiRelease04x00) (revision 9301)
+++ bin/update-develop-links (.../DEVELOP) (revision 9301)
@@ -1,5 +1,11 @@
#!/bin/sh
+# Temporary script for supporting access to commands as the apache user
+# for people with shell access on develop.twiki.org.
+# Must not be released!
+# Remove the hack script when you are done!
+# Be very, very careful!
echo "Content-type: text/plain"
echo ""
cd /home/virtual/site2/fst/home/develop/twikisvn
-perl pseudo-install.pl -link all 2>&1
+. hack 2>&1
+
Index: data/Main/UserViewTemplate.txt
===================================================================
--- data/Main/UserViewTemplate.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/Main/UserViewTemplate.txt (.../DEVELOP) (revision 9301)
@@ -7,41 +7,12 @@
%TMPL:DEF{"create_topic"}%Create%TMPL:END%
%TMPL:DEF{"edit_topic"}%Edit text%TMPL:END%
%TMPL:DEF{"active_edit"}%%TMPL:P{context="new_topic" then="create_topic" else="edit_topic"}%%TMPL:END%
-%TMPL:DEF{"helptext"}%
-----
-----
----++ Help Text
- * %MAKETEXT{"[_1] - view a short introductory presentation on TWiki for beginners" args="%TWIKIWEB%.ATasteOfTWiki"}%
- * %MAKETEXT{"[_1] - starting points on TWiki" args="%TWIKIWEB%.WelcomeGuest"}%
- * %MAKETEXT{"[_1] - complete TWiki documentation, Quick Start to Reference" args="%TWIKIWEB%.TWikiUsersGuide"}%
- * %MAKETEXT{"[_1] - try out TWiki on your own" args="Sandbox.%HOMETOPIC%"}%
- * %MAKETEXT{"[_1] - just for me" args="Sandbox.%TOPIC%Sandbox"}%
-
----++ Settings
-%MAKETEXT{"Uncomment preferences variables to activate them (remove the #-sign). Help and details on preferences variables are available in [_1]." args="%TWIKIWEB%.%WIKIPREFSTOPIC%"}%
-
- * LINKTOOLTIPINFO - %MAKETEXT{"Show tool-tip topic info on mouse-over of [_1] links, on or off:" args="%TWIKIWEB%.WikiWord"}%
- * EDITBOXWIDTH - %MAKETEXT{"Horizontal size of text edit box:"}%
- * EDITBOXHEIGHT - %MAKETEXT{"Vertical size of text edit box:"}%
- * EDITBOXSTYLE - %MAKETEXT{"Style of text edit box. =width: 99%= for full window width (default), =width: auto= to disable."}%
- * ALLOWTOPICCHANGE - %MAKETEXT{"Write protect your home page: (set it to your [_1])" args="%TWIKIWEB%.WikiName"}%
-
----++ %MAKETEXT{"Related Topics"}%
-
- * %MAKETEXT{"[_1] for changing your password" args="%TWIKIWEB%.ChangePassword"}%
- * %MAKETEXT{"[_1] for changing your email address" args="%TWIKIWEB%.ChangeEmailAddress"}%
- * %MAKETEXT{"[_1] has a list of other TWiki users" args="%MAINWEB%.%WIKIUSERSTOPIC%"}%
- * %MAKETEXT{"[_1] is a list of TWiki user documentation" args="%TWIKIWEB%.UserDocumentationCategory"}%
- * %MAKETEXT{"[_1] lists all TWiki user tools" args="%TWIKIWEB%.UserToolsCategory"}%
-%TMPL:END%
-
%TMPL:DEF{"content"}%
%TMPL:P{"form"}%
%TMPL:P{context="inactive" then="inactive_form" else="active_form"}%
%BR%
%TEXT%
-%TMPL:P{"helptext"}%
#TopicEnd
%TMPL:P{"attachments"}%
%TMPL:P{"topicinfo"}%%TMPL:END%
Index: data/Main/TWikiUsers.txt
===================================================================
--- data/Main/TWikiUsers.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/Main/TWikiUsers.txt (.../DEVELOP) (revision 9301)
@@ -1,4 +1,4 @@
-%META:TOPICINFO{author="TWikiRegistrationAgent" date="1137835126" format="1.1" version="1.2"}%
+%META:TOPICINFO{author="TWikiRegistrationAgent" date="1140723227" format="1.1" version="1.1"}%
---+ List of %WIKITOOLNAME% users
Below is a list of users with accounts. If you want to edit topics or see protected areas of the site then you can get added to the list by registering: fill out the form in %TWIKIWEB%.TWikiRegistration.
@@ -50,4 +50,3 @@
__Access Control:__
* Set ALLOWTOPICCHANGE = TWikiAdminGroup, TWikiRegistrationAgent
-
Index: data/Main/TWikiGuest.txt
===================================================================
--- data/Main/TWikiGuest.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/Main/TWikiGuest.txt (.../DEVELOP) (revision 9301)
@@ -6,3 +6,4 @@
__Related topics:__ %WIKIUSERSTOPIC%, %TWIKIWEB%.TWikiRegistration
%META:PREFERENCE{name="ALLOWTOPICCHANGE" title="ALLOWTOPICCHANGE" type="Set" value="TWikiAdminGroup"}%
+
Index: data/TWiki/ResetPassword.txt
===================================================================
--- data/TWiki/ResetPassword.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/ResetPassword.txt (.../DEVELOP) (revision 9301)
@@ -10,7 +10,6 @@
%X% __%MAKETEXT{"Note:"}%__ %MAKETEXT{"you *must* have at least one valid registered e-mail to be able to reset your password. If none of your registered e-mail addresses is valid, and you have forgotten your password, contact [_1]." args="%WIKIWEBMASTER%"}%
---+++ %MAKETEXT{"Your [_1].LoginName" args="%TWIKIWEB%"}%
Index: data/TWiki/TWikiTemplates.txt
===================================================================
--- data/TWiki/TWikiTemplates.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/TWikiTemplates.txt (.../DEVELOP) (revision 9301)
@@ -24,7 +24,7 @@
* Directives are of the form ==%TMPL:<key>%== and ==%TMPL:<key>{"attr"}%==.
* Directives:
* ==%TMPL:INCLUDE{"file"}%==: Includes a template file. The file is found as described [[#FindingTemplates][below]].
- * ==%TMPL:DEF{"block"}%==: Define a block. Text between this and the =%TMPL:END%= directive is not used in-place, but is saved for later use with =%TMPL:P=. Leading and trailing whitespace is ignored.
+ * ==%TMPL:DEF{"block"}%==: Define a block. *All* text between this and the next =%TMPL:END%= directive is removed and saved for later use with =%TMPL:P=.
* ==%TMPL:END%==: Ends a block definition.
* ==%TMPL:P{"var"}%==: Includes a previously defined block.
* ==%{...}%==: is a comment.
Index: data/TWiki/ChangePassword.txt
===================================================================
--- data/TWiki/ChangePassword.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/ChangePassword.txt (.../DEVELOP) (revision 9301)
@@ -7,16 +7,14 @@
%MAKETEXT{"[_1] has a list of other TWiki users" args="%MAINWEB%.%WIKIUSERSTOPIC%"}%
@@ -32,5 +30,6 @@
%MAKETEXT{"If you have any questions, please contact [_1]." args="%WIKIWEBMASTER%"}%
+__Related Topics:__ ChangeEmailAddress, AdminToolsCategory, UserToolsCategory
__%MAKETEXT{"Note to administrator"}%:__ %MAKETEXT{"This form applies only if TWiki uses a {PasswordManager} that supports changing passwords. Otherwise replace this topic with a note describing how to change the password in your organization."}% %MAKETEXT{"See [_1] for more information." args="TWikiUserAuthentication"}%
__%MAKETEXT{"Related topics:"}%__ ChangeEmailAddress, ResetPassword, AdminToolsCategory, UserToolsCategory
Index: data/TWiki/TWikiRegistration.txt
===================================================================
--- data/TWiki/TWikiRegistration.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/TWikiRegistration.txt (.../DEVELOP) (revision 9301)
@@ -82,6 +82,7 @@
+
@@ -215,7 +216,7 @@
%MAKETEXT{"Fields marked [_1] are required" args="=**="}%
-
+
Index: data/TWiki/NewUserTemplate.txt
===================================================================
--- data/TWiki/NewUserTemplate.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/NewUserTemplate.txt (.../DEVELOP) (revision 9301)
@@ -2,9 +2,15 @@
%SPLIT%
* %KEY%: %VALUE%%SPLIT%
----++ About me
+---++ My Links
- * Replace this text with an introduction about yourself
+ * %TWIKIWEB%.ATasteOfTWiki - view a short introductory presentation on TWiki for beginners
+ * %TWIKIWEB%.WelcomeGuest - starting points on TWiki
+ * %TWIKIWEB%.TWikiUsersGuide - complete TWiki documentation, Quick Start to Reference
+ * Sandbox.%HOMETOPIC% - try out TWiki on your own
+ * Sandbox.%TOPIC%Sandbox - just for me
+ *
+ *
---++ Personal Preferences
@@ -21,6 +27,68 @@
* Write protect your home page: (set it to your %TWIKIWEB%.WikiName)
* #Set ALLOWTOPICCHANGE = %WIKIUSERNAME%
+---++ Related Topics
+
+ * %TWIKIWEB%.ChangePassword for changing your password
+ * %TWIKIWEB%.ChangeEmailAddress for changing your email address
+ * %MAINWEB%.%WIKIUSERSTOPIC% has a list of other TWiki users
+ * %TWIKIWEB%.UserDocumentationCategory is a list of TWiki user documentation
+ * %TWIKIWEB%.UserToolsCategory lists all TWiki user tools
+%STARTSECTION{type="templateonly"}%
+Note to TWiki Administrator:
+
+Above text is for English speaking users. If you have a multilingual wiki community you can replace the "My Links", "Personal Preferences" and "Related Topics" sections above with the localized text below. Text enclosed in %MAKETEXT will be shown in the language selected by the user. Please note that the %MAKETEXT can be quite intimidating to new users. Consider translating above text to your own language if your community uses a non-English language. (Remove all text from =%STARTSECTION{type="templateonly"}%= to =%ENDSECTION{type="templateonly"}%= when you are done)
+
+Text for multilingual wiki community, copy from here to %ENDSECTION{type="templateonly"}%
+
+
+---++ %MAKETEXT{"My Links"}%
+
+ * %MAKETEXT{"[_1] - view a short introductory presentation on TWiki for beginners" args="%TWIKIWEB%.ATasteOfTWiki"}%
+ * %MAKETEXT{"[_1] - starting points on TWiki" args="%TWIKIWEB%.WelcomeGuest"}%
+ * %MAKETEXT{"[_1] - complete TWiki documentation, Quick Start to Reference" args="%TWIKIWEB%.TWikiUsersGuide"}%
+ * %MAKETEXT{"[_1] - try out TWiki on your own" args="Sandbox.%HOMETOPIC%"}%
+ * %MAKETEXT{"[_1] - just for me" args="Sandbox.%TOPIC%Sandbox"}%
+ *
+ *
+
+---++ %MAKETEXT{"Personal Preferences"}%
+
+%MAKETEXT{"Uncomment preferences variables to activate them (remove the #-sign). Help and details on preferences variables are available in [_1]." args="%TWIKIWEB%.%WIKIPREFSTOPIC%"}%
+
+ * %MAKETEXT{"Show tool-tip topic info on mouse-over of [_1] links, on or off:" args="%TWIKIWEB%.WikiWord"}%
+ * #Set LINKTOOLTIPINFO = off
+ * %MAKETEXT{"Horizontal size of text edit box:"}%
+ * #Set EDITBOXWIDTH = 70
+ * %MAKETEXT{"Vertical size of text edit box:"}%
+ * #Set EDITBOXHEIGHT = 22
+ * %MAKETEXT{"Style of text edit box. =width: 99%= for full window width (default), =width: auto= to disable."}%
+ * #Set EDITBOXSTYLE = width: 99%
+ * %MAKETEXT{"Write protect your home page: (set it to your [_1])" args="%TWIKIWEB%.WikiName"}%
+ * Set ALLOWTOPICCHANGE = %WIKIUSERNAME%
+
+---++ %MAKETEXT{"Related Topics"}%
+
+ * %MAKETEXT{"[_1] for changing your password" args="%TWIKIWEB%.ChangePassword"}%
+ * %MAKETEXT{"[_1] for changing your email address" args="%TWIKIWEB%.ChangeEmailAddress"}%
+ * %MAKETEXT{"[_1] has a list of other TWiki users" args="%MAINWEB%.%WIKIUSERSTOPIC%"}%
+ * %MAKETEXT{"[_1] is a list of TWiki user documentation" args="%TWIKIWEB%.UserDocumentationCategory"}%
+ * %MAKETEXT{"[_1] lists all TWiki user tools" args="%TWIKIWEB%.UserToolsCategory"}%
+
+%ENDSECTION{type="templateonly"}%
%META:FORM{name="%MAINWEB%.UserForm"}%
%META:FIELD{name="FirstName" attributes="" title="FirstName" value=""}%
%META:FIELD{name="LastName" attributes="" title="LastName" value=""}%
Index: data/TWiki/ManagingUsers.txt
===================================================================
--- data/TWiki/ManagingUsers.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/ManagingUsers.txt (.../DEVELOP) (revision 9301)
@@ -1,4 +1,4 @@
-%META:TOPICINFO{author="TWikiContributor" date="1111929255" format="1.0" version="$Rev:$"}%
+%META:TOPICINFO{author="TWikiContributor" date="1111929255" format="1.0" version="$Rev$"}%
%TOC%
%STARTINCLUDE%
---# Manage Users
Index: data/TWiki/AdminSkillsAssumptions.txt
===================================================================
--- data/TWiki/AdminSkillsAssumptions.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/AdminSkillsAssumptions.txt (.../DEVELOP) (revision 9301)
@@ -1,4 +1,4 @@
-%META:TOPICINFO{author="TWikiContributor" date="1111929255" format="1.0" version="$Rev:$"}%
+%META:TOPICINFO{author="TWikiContributor" date="1111929255" format="1.0" version="$Rev$"}%
%META:TOPICPARENT{name="TWikiInstallationGuide"}%
---+ Administrator Skills Assumptions
Index: data/TWiki/CascadingStyleSheets.txt
===================================================================
--- data/TWiki/CascadingStyleSheets.txt (.../TWikiRelease04x00) (revision 0)
+++ data/TWiki/CascadingStyleSheets.txt (.../DEVELOP) (revision 9301)
@@ -0,0 +1,4 @@
+%META:TOPICINFO{author="TWikiContributor" date="1111929255" format="1.0" version="$Rev: 8906 $"}%
+%META:TOPICPARENT{name="WebHome"}%
+
+This topic is a placeholder where stylesheets are attached.
Index: data/TWiki/TWikiReleaseNotes04x00x00.txt
===================================================================
--- data/TWiki/TWikiReleaseNotes04x00x00.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/TWikiReleaseNotes04x00x00.txt (.../DEVELOP) (revision 9301)
@@ -220,8 +220,9 @@
New optional features include {AutoAttachPubFiles} and {EnableHierarchicalWebs}. Both are switched off by default but can be enabled in =configure=.
---++++ Improved support for shorter URLs
-See TWiki:TWiki.ShorterURLCookbook
+See TWiki:TWiki.ShorterUrlCookbook
+
---+++ Preferences
There have been some significant changes to the handling of preferences, aimed at making them more logical, consistent and easy to use.
Index: data/TWiki/TWikiUserAuthentication.txt
===================================================================
--- data/TWiki/TWikiUserAuthentication.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/TWikiUserAuthentication.txt (.../DEVELOP) (revision 9301)
@@ -145,7 +145,7 @@
#ChangingPasswords
---++ Changing Passwords
-If your {PasswordManager} supports password changing, you can change and reset passwords using forms on regular pages.
+If your {PasswordManager} supports password changing (e.g. TWiki::Users::HtPasswdUser), you can change and reset passwords using forms on regular pages.
* The ChangePassword form ( ==TWiki/ChangePassword== )
* The ResetPassword form ( ==TWiki/ResetPassword== )
Index: data/TWiki/TWikiScripts.txt
===================================================================
--- data/TWiki/TWikiScripts.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/TWikiScripts.txt (.../DEVELOP) (revision 9301)
@@ -154,7 +154,7 @@
| rev1 | the higher revision | |
| rev2 | the lower revision | |
| render | the rendering style {sequential, sidebyside, raw, debug} | DIFFRENDERSTYLE, =sequential= |
-| type | history, diff, last} history diff, version to version, last version to previous | =diff= |
+| type | {history, diff, last} history diff, version to version, last version to previous | =diff= |
| context | number of lines of context | |
TODO:
* add a {word} render style
Index: data/TWiki/TWikiVariablesQuickStart.txt
===================================================================
--- data/TWiki/TWikiVariablesQuickStart.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/TWiki/TWikiVariablesQuickStart.txt (.../DEVELOP) (revision 9301)
@@ -1,29 +0,0 @@
-%META:TOPICINFO{author="MeredithLesly" date="1142354264" format="1.1" version="1.2"}%
----++ TWiki Variables Quickstart
-
-%STARTINCLUDE%
-
-TWiki Variables are names that are enclosed in percent signs =%= that are expanded on the fly. Some variables take arguments, such as =%INCLUDE%=. For those variables, the arguments are included in curly braces ({ and }).
-
-| *Variable* | *In brief* | *Full documentation* |
-| =%TOC%= | Automatically generates a table of contents based on headings in a topic - see the top of this page for an example. |VarTOC |
-| =%WEB%= | The current web, is %WEB%. | VarWEB |
-| =%TOPIC%= | The current topic name, is %TOPIC%. | VarTOPIC |
-| =%ATTACHURL%= | The attachment URL of the current topic. Example usage: If you attach a file to a topic you can refer to it as =%ATTACHURL%/image.gif= to show the URL of the file or the image in your text. | VarATTACHURL |
-| =%INCLUDE{"SomeTopic"}%= | Server side include, includes another topic. The current web is the default web. Example: =%INCLUDE{"%TWIKIWEB%.SiteMap"}%= | VarINCLUDE |
-| =%SEARCH{"sushi"}%= | Inline search showing the search result embedded in a topic. FormattedSearch gives you control over formatting, useful for creating web-based applications. | VarSEARCH |
-
-TWikiPreferences defines some site-wide variables. Among them are:
- * *Line break:* Write =%BR%= to start a new line.
- * *Colored text:* Write: =%RED% Red %ENDCOLOR% and %BLUE% blue %ENDCOLOR% colors= to get: %RED% Red %ENDCOLOR% and %BLUE% blue %ENDCOLOR% colors.
-
-There are many more variables. To see them all, go to *[[TWikiVariables]]*.
-
-*Documentation Graphics:* There are many graphics available to use in your topics. Use =%ICON{"help"}%=, =%ICON{"tip"|%=, and =%icon{"warning"}%= to get: %H%, %T%, and %X%. To see all of the graphics available, see TWikiDocGraphics.
-
-
-%ICON{"tip"}% To "escape" a variable, prefix it with an exclamation mark. Write: =!%SOMEVARIABLE%= to get: !%SOMEVARIABLE%.
-%STOPINCLUDE%
-
-
-%META:TOPICMOVED{by="MeredithLesly" date="1142354264" from="TWiki.TWikiVariableQuickStart" to="TWiki.TWikiVariablesQuickStart"}%
Index: data/Sandbox/WebPreferences.txt
===================================================================
--- data/Sandbox/WebPreferences.txt (.../TWikiRelease04x00) (revision 9301)
+++ data/Sandbox/WebPreferences.txt (.../DEVELOP) (revision 9301)
@@ -20,7 +20,7 @@
* [[%TWIKIWEB%.WebTopicEditTemplate]]: Site-level default topic template
* Comma separated list of *forms* that can be attached to topics in this web. See %TWIKIWEB%.TWikiForms for more information.
- * Set WEBFORMS = %MAINWEB%.UserForm
+ * Set WEBFORMS =
* Users or groups who __are not__ / __are__ allowed to __view__ / __change__ / __rename__ topics in the %WEB% web: (See %TWIKIWEB%.TWikiAccessControl). Remove the # to enable any of these settings. Remember that an empty setting is a valid setting; setting DENYWEBVIEW to nothing means that anyone can view the web.
* #Set DENYWEBVIEW =
Index: index.html
===================================================================
--- index.html (.../TWikiRelease04x00) (revision 9301)
+++ index.html (.../DEVELOP) (revision 9301)
@@ -153,9 +153,9 @@
Note: These pages do not need to be accessible by browsers. Preventing access will increase security and will not affect TWiki in any way.
Index: pseudo-install.pl
===================================================================
--- pseudo-install.pl (.../TWikiRelease04x00) (revision 9301)
+++ pseudo-install.pl (.../DEVELOP) (revision 9301)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!perl
use strict;
use File::Path;
@@ -36,7 +36,7 @@
my $module = shift;
print "Processing $module\n";
my $subdir = 'Plugins';
- $subdir = 'Contrib' if $module =~ /(Contrib|Skin)$/;
+ $subdir = 'Contrib' if $module =~ /(Contrib|Skin|AddOn)$/;
my $moduleDir = "twikiplugins/$module/";
unless (-d $moduleDir) {
@@ -58,7 +58,7 @@
}
close(F);
} else {
- print STDERR "---> No MANIFEST in $module\n";
+ print STDERR "---> No MANIFEST in $module (at $manifest)\n";
}
}
Index: mklinks.sh
===================================================================
--- mklinks.sh (.../TWikiRelease04x00) (revision 9301)
+++ mklinks.sh (.../DEVELOP) (revision 9301)
@@ -1,115 +0,0 @@
-#!/bin/sh
-# Usage:
-# mklinks.sh [-cp|-echo] ...
-# Make links from the core into twikiplugins, to pseudo-install these
-# components into a subversion checkout area. Default is to process
-# all plugins and contribs, or you can do just a subset. Default behaviour
-# is to skip a link if there is an existing file in the way. You can also
-# request a cp instead of ln -s, which will stomp existing files.
-# -cp - copy files from the twikiplugins area instead of linking them.
-# DESTROYS THE EXISTING INSTALL OF THE PLUGIN EVEN IF FILES HAVE CHANGED
-# -echo - just print the names of files that would be linked/copied
-# ... list of plugins and contribs to link into the core.
-# Example: CommentPlugin RenderListPlugin JSCalendarContrib
-# Optional, defaults to all plugins and contribs.
-shopt -s nullglob
-
-function mklink () {
- link=`echo $1 | sed -e 's#twikiplugins/[A-Za-z0-9]*/##'`
- if [ -L $link ]; then
- # Always kill links
- $destroy $link
- fi
- if [ x$wipeout = x -a -e $link ]; then
- # If we are linking, and there's a file in the way, check
- # if it is different
- x=`diff -q $1 $link`
- if [ "$x" = "" ]; then
- $destroy $link
- else
- echo "diff $1 $link different - Keeping $link intact"
- fi
- else
- target=`dirname $link | sed -e 's/[^\/][^\/]*/../g'`
- # if wipeout is 1, will simply overwrite whatever is already there
- $build $target/$1 $link
- fi
-}
-
-# Main program
-if [ "$1" = "-cp" ]; then
- shift;
- # must be -r to catch dirs
- build="cp -rf"
- destroy="rm -rf"
- # set wipeout to always overwrite existing installed files
- wipeout=1
-elif [ "$1" = "-echo" ]; then
- shift;
- build="echo"
- destroy="echo"
-else
- build="ln -s"
- destroy="rm"
-wipeout=1
-fi
-
-# examine remaining params
-params=""
-for param in $* ; do
- params="$params twikiplugins/$param"
-done
-
-# default is to do all plugins and contribs
-if [ "$params" = "" ]; then
- for param in twikiplugins/*Contrib ; do
- params="$params $param"
- done
- for param in twikiplugins/*Plugin ; do
- params="$params $param"
- done
-fi
-
-for dir in $params; do
- module=`basename $dir`
-
- # pub dir
- if [ -d $dir/pub/TWiki/$module ]; then
- mklink $dir/pub/TWiki/$module
- fi
- for pubdir in $dir/pub/*; do
- if [ ! -e pub/`basename $pubdir` ]; then
- mklink $pubdir
- fi
- done
-
- # lib dir
- for type in Plugins Contrib; do
- if [ -d $dir/lib/TWiki/$type/$module ]; then
- mklink $dir/lib/TWiki/$type/$module
- fi
- for pm in $dir/lib/TWiki/$type/*.pm; do
- mklink $dir/lib/TWiki/$type/*.pm
- done
- done
-
- # data dir
- if [ -d $dir/data/TWiki ]; then
- for txt in $dir/data/TWiki/*.txt; do
- mklink $txt
- done
- fi
-
- # templates dir
- if [ -d $dir/templates ]; then
- for tmpl in $dir/templates/*.tmpl; do
- mklink $tmpl
- done
- fi
-
- # unit tests dir
- if [ -d $dir/test/unit/$module ]; then
- mklink $dir/test/unit/$module
- fi
-done
-