I recently modified my
TWikiWeb to support per-web properties files.
It started because I realized I wanted to to a fancier page heading - instead of a single block of color, I wanted a table with a colored border. However, I wanted this color to be parameterized, just like the current heading. The current mechanism stores the color in an include file, "webcolor.inc". So my initial thought was that I would have to create a second include file, "webcolor2.inc". However, I realized that if I were to expand this idea to an arbitrary number of colors, this would quickly get unwieldy, as well as inefficient having to hit this disk for all of those include files.
I realized that what I really wanted to do was replace the "webcolor.inc" mechanism with a per-web properties file. In other words, you could define a "Main/web.vars" that would store a set of properties for each web. Here's an example:
WEB_FG_COLOR => '#8888cc',
WEB_BG_COLOR => '#CCCCff'
Naturally, it would be easy to read in this file and evaluate it, producing a hashtable. Let's call this table "%webVars". So in initialize, I insert this code:
my $webCfg = &readFile( "$dataDir/$webName/web.vars" );
%webVars = eval "( $webCfg )";
Then, in the handleCommonTags, we would add a line like this:
$text=~ s/%(\w+)%/$webVars{$1}||"%$1%"/geo;
In other words, each time we see a word surrounded by percent signs, we look up that word in the %webVars hash table. If the entry is defined, then we perform the substitution, otherwise we simply substitute in the original value.
Then I looked at the rest of handleCommonTags, with all of those other
substitutions, and I realized that it might be more efficient to simply stick those values into %webVars along with everything else, and just do one big substitution. However, I'm not going to mess with that yet.
One issue that needs to be thought about is whether the use of perl "eval" function could represent a possible security hole - that is, if a user were able to somehow trick the system into modifying the proeprties file, then they could insert a perl backtick sequence which would run arbitrary shell commands as the user "nobody". Fortunately, since the current system allows only ".txt" files to be modified, there does not appear to be much danger of this.
--
TaLiN - 13 Feb 2000
That is an excellent idea to make per-web properties files. How about extending this? We could have three level of properties:
- User properties: Define user level properties.
- Web properties: Define per-web properties.
- Site level properties: Define site level settings.
The list shows the order of priority. I.e., if a value is not defined in a higher level, it will use the one from a lower level.
These properties could be defined as Wiki topics:
TWikiProperties (or
SiteProperties ?) for site level,
WebProperties for web level,
PeterThoenyProperties (or
PeterThoeny only ?) for user level. Needless to say, non existing topics would be ignored.
TWikiVariables could be defined in the properties. To name a few:
| Variable: |
Level: |
What: |
%WIKIWEBMASTER% |
site, web |
TWiki webmaster email |
%WIKITOOLNAME% |
site |
Name of TWiki tool |
%WEBCOLOR% |
web |
Background color of current web |
%EDITSIZEX% |
site, user |
Horizontal size of text edit box |
%EDITSIZEY% |
site, user |
Vertical size of text edit box |
The syntax to define a variable in a property topic could be like this: Three spaces,
'*' , variable name without % signs,
'=' , value. Example:
The variable could be used in topic templates and topics as usual, in our example as
%WEBCOLOR% .
New variables could be introduced and used without changing the TWiki source, i.e. in your case you could define:
and change your template files to use the
%WEBFGCOLOR% variable.
TWiki currently uses some
%INCLUDE{...}% to include part of the topic header and footer, like
wikiwebs.inc (list of webs in header),
weblist.inc (web topic list, second line in header)
webcopyright.inc (copyright notice in footer). They also could be replaced by properties:
| Variable: |
Level: |
What: |
%WIKIWEBLIST% |
site |
List of TWiki webs |
%WEBTOPICLIST% |
web |
List of topics of a web |
%WEBCOPYRIGHT% |
site, web |
Copyright notice |
Performance is also an issue. Sub wiki::initialize is probably the place to read the three properties topic files and extract the variables. There are probably fast ways to do that.
TaLiN, you are the Perl guru, can you shed some light on that? BTW, replacing includes by properties could even improve performance?
Security is an issue as you pointed out. I would filter any non
[a-zA-Z_] characters out of the variable name. Dangerous characters like "`" need to be filtered out of the value as well. Any other gochas?
--
PeterThoeny - 15 Feb 2000
If you wanted to change the syntax of the file to something like you suggest, this would be done by actually parsing the file (which would be slightly slower, but not much), instead of using 'eval'. On the other hand, it has the advantage of improved readability.
Backticks and non-alpha characters are not a problem as long as you aren't using 'eval' to read the properties file.
I think it would be valuable to allow the property values to be quoted, with embedded control characters ('\n' at least) for more complex properties. This wouldn't be hard.
Performance: If you are using something like Apache mod_perl or another system that allows the perl script to remain "resident", then some big performance wins can be obtained fairly easily by allowing the parsed list of properties to reside in memory inbetween invocations of the script. This could also apply to a lot of other things that the TWiki scripts are doing. However, this is somewhat difficult to accomplish in a straight
CGI-style environment (although there might be some perl modules that accomplish something similar, perhaps using shared memory.)
Replacing includes with properties would definately improve performance. The overhead of reading one properties file is about the same as reading one include file, and the cost of the actual substitution is close to nothing. So as long as you are replacing three or more include statements with the property equivalents, then it's probably a win, overall.
--
TaLiN - 16 Feb 2000
Finished implementation. See
TWikiPreferences (site-level),
WebPreferences (web-level) and
PeterThoeny (user level). The algorithm used is probably not the fastest possible.
TaLiN, could you check the latest Beta and give feedback?
--
PeterThoeny - 25 Feb 2000