create new tag
, view all tags

Feature Proposal: Read-only and mirror web support


There are cases where read-only webs are useful.

  • %SYSTEMWEB% web being a part of installation rather than a content, it may reside in read-only storage. In that case, It's better for TWiki to recognize as such and not to allow update operations rather than update operations causing errors. Even if you don't see an edit or attach link, users may enter an edit or attach URL manually. In that case, the edit and attach scripts should display "operation not allowed" kind of message.
  • You may want to run a federation of TWiki sites, in which member sites have read-only mirror of other sites' webs. Read-only mirror webs are not so useful for tight collaboration. But it's useful for a web viewed by many users geographically distributed.

Description and Documentation

A read-only web such as %SYSTEMWEB% web is displayed as such by the following setting.


A topic of a web mirrored from a site federation member has "Edit" and "Attach" enabled but they point to the master site while "More..." is disabled. The bottom toolbar gets "view master" link, which leads to the topic on the master site.

On the master site of the mirrored web, things are almost as usual but the bottom toolbar has the "mirror to all" link. The content mirroring feature is provided by an add-on.





To use this feature, $TWiki::cfg{SiteName} needs to be set, most likely in lib/LocalSite.cfg. You can see its value by %SITENAME%

This feature introduces the notion of content mode. A web is either:

  • local -- read/write and not mirrored, e.g. Sandbox, Trash. Without this feature, all webs are "local".
  • read-only (e.g. %SYSTEMWEB%, if you choose as such)
  • master -- mirrored and the current site is the master
  • slave -- mirrored and the current site is not the master

TWiki::modeAndMaster($web) called from TWiki::new() and other places plays a key role.

  • It returns the web's content mode and master site data by "return ($mode, \%master);"
    • \%master is returned only if the web is a slave. Otherwise, it's undef.
  • If $TWiki::cfg{SiteName} is not defined, it returns ('local', undef).
  • Otherwise, the content mode is determined by the master site name of the web and $TWiki::cfg{SiteName}.
    • If the master site name equals to $TWiki::cfg{SiteName}, then 'master'
    • Otherwise
      • If the URL of the web on the master site is specified directly or indirectly, 'slave'
      • Otherwise, 'read-only'
  • %master has the following keys:
    $TWiki::cfg{SiteName} value of the master site of the specified web
    "%SCRIPTURL%//%WEB%" on the master site. Inserting a script name (e.g. view, edit) followed by the masterScriptExt value (e.g. ".cgi") between the two slashes (//) and then adding "/TOPIC_NAME" to the value makes the URL to execute the specified script with the page on the master site. If this cannot be determined, the web is regarded as read-only - no way to update a topic by a web browser.
    %SCRIPTSUFFIX% value on the master site. Optional.
    There are cases where the view URL format is different from the other scripts, e.g. http://twiki.example.com/Web/Topic. In that case, this attribute has http://twiki.example.com/Web. Adding "/TOPIC_NAME" to this value makes the URL to view the page on the master site. Optional.
  • If the metadata repository (RepositoryForSiteAndWebMetadata) is in use:
    • The web's metadata record is retrieved from the 'webs' file of the metadata repository.
    • The 'master' field of the metadata record is regarded as the master site name.
    • Then, the master site's metadata record is retrieved from the 'sites' file of the metadata repository.
    • The record's scripturl, scriptsuffix, and viewurl attributes are used to make the webScriptUrlTmpl, scriptSuffix, and webViewUrl attributes of %master.
  • If the metadata repository is not in use, the $mode and %master values come from the values of %MASTERSITENAME%, %MASTERWEBSCRIPTURLTMPL%, %MASTERSCRIPTSUFFIX%, %MASTERWEBVIEWURL%

core/lib/TWiki.pm other than modeAndMaster()

new() calls modeAndMaster() and then put the return value to the 'contentMode' attribute of the TWiki object and 'master' attribute (if defined).

To provide URLs on the master site rather than the local site, %SCRIPTURL{...}% is enhanced. The following behavior kicks in if the web="WEB" or topic="WEB.TOPIC" parameter is provided.

  • With scripts only valid on the master site, such as "edit", "save", "attach", and "upload", the URLs on the master site are returned.
  • With other scripts, you can get the URLs on the master site by specifying master="on" parameter.

%CONTENTMODE% is expanded to the content mode of the current web.

%WEBLIST{...}%'s webs parameter gets a new filter "canmoveto", which eliminates read-only and slave webs. Rename templates need to have the canmoveto filter in %WEBLIST{...}%. This is to avoid a topic or a web being tried to be moved to unwritable web. You may think the filter name should be something else such as "writable". The reason why "writable" is not taken is that under UsingMultipleDisks, not all writable webs can be move destinations.

TWiki::readOnlyMirrorWeb() becomes no use and gets removed.


checkWritable($session, [$web]) is introduced and replaces checkMirror($session, $web, $topic). It throws TWiki::OopsException('accessdenied' def => 'not_writable') if the web is not writable. core/templates/messages.tmpl is enhanced accordingly.


It's enhanced to accommodate content mode. Depending on the mode, an additional context is added as follows.

Content mode Context
read-only inactive (existing)
master content_master (new)
slave content_slave (new)

core/lib/TWiki/UI/Edit.pm, Save.pm, Upload.pm

They call checkWritable($session) instead of checkMirror($sessin, $web, $topic).


saveTopicText() was calling $session->readOnlyMirrorWeb($web) and then threw exception if needed, which is replaced by TWiki::UI::checkWritable($session, $web).


The topicactionbuttons block gets %TMPL:P{"action_mirror"}% inserted between %TMPL:P{"action_raw_or_view"}% and %TMPL:P{"action_activatable_raw_edit"}%. Natually the definition of the block action_mirror is added. The action_mirror block assumes %MIRRORTOALLURL% is defined, which is used on a master web topic.

The following block definitions are modified using enhanced %SCRIPTURL{...}%.

Block Using
%TMPL:DEF{"create_topic_link"}% ... %TMPL:END% %SCRIPTURL{"edit" web="%WEB%"}%
%TMPL:DEF{"edit_topic_link"}% ... %TMPL:END% %SCRIPTURL{"edit" web="%WEB%"}%
%TMPL:DEF{"raw_edit_link"}% ... %TMPL:END% %SCRIPTURL{"edit" web="%WEB%"}%
%TMPL:DEF{"attach_link"}% ... %TMPL:END% %SCRIPTURL{"attach" web="%WEB%"}%

The activatable_more block is modified so that it's displayed in the inactive mode not only in inactive context but also in comment_slave context.

core/templates/moveattachment.tmpl, rename.tmpl, renameweb.tmpl

These templates have %WEBLIST{... webs="...,public" ...}%, which needs to be changed to %WEBLIST{... webs="...,canmoveto" ...}%.


You should not update WebStatistics of a mirror slave or read-only web. WebStatistics of a mirror slave web will be overridden when the web is mirrored. WebStatistics of a read-only web may reside in a read-only storage and cannot be updated.

With federated sites, you should combine statistics of a web among all the sites. For that, all the sites need to have all the sites' access logs and the statistics script reads log files of all sites.

The statistics script takes topic renaming into account. To reduce the number of incorrect counts, all the sites in a federation should use GMT for logging.


TWiki having web content as files, web content mirroring can be done by rsync.

If you have a federation of TWiki sites, you need a systematic mirroring among the participating sites. The details of that would be installation dependent and is not part of the TWiki core enhancement.

Other consideration

For web mirroring to work, each web needs to be self-contained.
  • Group definition by group topics needs to be de-centralized. In other words, the user mapping handler needs to read the topic SomethingGroup in the current web when SomethingGroup appears in access control setting. The default behavior is that group definition needs to be in the Main web.
  • If a plug-in leaves data files, those files must be in $TWiki::cfg{PubDir}/WEB.
  • Some plug-ins need to be aware of the inactive and content_slave contexts. In those context, "edit" button or feature of the following plug-ins (not a comprehensive list) needs to be suppressed.
    • EditTablePlugin
    • MultiEditPlugin - The master topic may be changed when a user seeing a slave topic edits it. Since sections are identified by sequential numbers, the section the user tries to edit may no longer be there or have changed its sequence number. In that case, the user encounters unexpected behavior.
    • VotePlugin - voting information stored on files, which is a part of the web's content, must not be updated on a slave. It would be overwritten next time it's mirrored anyway.
    • TagMePlugin - same as VotePlugin.

Rationale of the design

You may want to try this feature with a small amount of effort, without introducing RepositoryForSiteAndWebMetadata. That's why this is designed to work well with out without RepositoryForSiteAndWebMetadata.

The name of a mirrored web may differ on the local site and a remote site. So we use %MASTERWEBVIEWURL% and %MASTERWEBSCRIPTURL{...}% instead of %MASTERVIEWURL% and %MASTERSCRIPTURL{...}%

On a mirror web, typically links to the view, edit and attach operations on the master web are provided. But there are cases where the save and rename operations are conducted. As such, instead of providing %MASTERWEBEDITURL%, %MASTERWEBATTACHURL%, etc., %MASTERWEBSCRIPTURL{...}% is provided.

Canonical topic view URLs (e.g. http://server/web/topic) may have a different structure from other script URLs (e.g. http://server/cgi-bin/edit/web/topic). To cope with such situations, %MASTERWEBVIEWURL% is provided.

-- Contributors: HideyoImazu - 2012-07-05


TWiki-5.1 already supports read-only skin mode, see TopMenuSkin#Read_Only_Skin_Mode - is that sufficient, or do you need also access controlled?

-- PeterThoeny - 2012-07-05

Thank you for pointing it out. I updated the proposal accordingly.

-- HideyoImazu - 2012-07-05

This looks like a sensible feature request. I do not have suggestions, but wondering if it can be simplified a bit.

-- PeterThoeny - 2012-07-11

I agree it ended up being complicated than I originally thought. The good news is, I know it really works in production.

-- HideyoImazu - 2012-07-13

As per discussion in JerusalemReleaseMeeting2012x07x20,

  • $TWiki::cfg{SiteName} being defined in LocalSite.cfg is mentioned
  • %WEBLIST{...}% behavior is revised.

-- HideyoImazu - 2012-07-20

Accepted in JerusalemReleaseMeeting2012x07x20 with two changes:

  • To remain compatible, better keep TWiki.TWikiPreferences and TWiki.TWikiPreferences (in addition to new meta data preferences)
  • Better to keep spec of WEBLIST, and to add a new webs="local"

-- PeterThoeny - 2012-07-21

  • You mean TWiki.TWikiPreferences and Main.TWikiPreferences, right? I have no intention to get rid of them. The site name is defined by $TWiki::cfg{SiteName}. That's OK, right?
  • The new filter would be "canmoveto" rather than "local" because "local" is confusing (see #Nitty_gritty). "local" is even less appropriate under UsingMultipleDisks because only a subset of read/write webs can be move destination. Above all, the filter's purpose is to get the list of move target webs, "canmoveto" is accurate and straightforward.

-- HideyoImazu - 2012-07-23

On using GMT for statistics, I think this is a safe change to do in all cases, not just if mirror web is enabled. I don't think we need to worry about compatibility here.

-- PeterThoeny - 2012-08-29

Edit | Attach | Watch | Print version | History: r32 < r31 < r30 < r29 < r28 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r32 - 2013-08-15 - HideyoImazu
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by Perl Hosted by OICcam.com Ideas, requests, problems regarding TWiki? Send feedback. Ask community in the support forum.
Copyright © 1999-2016 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.