Boum TWiki Setup

Why we've laid TWiki down on the torture bench

Shorter URLs

By default, TWiki generates really long URLs. Various solutions are discussed on TWiki:Codev/ShorterURLs and TWiki:Support/ShorteningUrls ; lots of good ideas that inspired us. Here is our whole setup, ready-to-use, to get short URLs working and generated by TWiki.

%U% The upcoming Dakar TWiki release should support this without patching anything.

httpS-only authentification

We do not want any password to be transfered as clear-text. Therefore, any TWiki script requiring the user to be authentificated should be made available only via httpS.

The actual setup

This setup is based on TWiki:Codev/TWikiRelease02Sep2004.

Apache config

<VirtualHost 69.90.134.151:80>
   ServerName wiki.boum.org
   ServerAdmin wiki@boumNO.SPAMorg
   DocumentRoot /var/www/twiki
   ScriptAlias /twiki/bin/ "/var/www/twiki/bin/"
   Alias /twiki/ "/var/www/twiki/"

   <Directory "/var/www/twiki/bin">
           Options +ExecCGI
      SetHandler cgi-script
          Allow from all

      # File to return on access control error (e.g. wrong password)
      ErrorDocument 401 /twiki/bin/oops/TWiki/TWikiRegistration?template=oopsauth

      <Files ~ "[^/]*\.html$">
                SetHandler blabla
                allow from all
      </Files>

      <Files "*">
                allow from all
      </Files>

   </Directory>

   <Directory "/var/www/twiki/pub">
      Options FollowSymLinks +Includes
         AllowOverride None
          Allow from all
   </Directory>

   <Directory "/var/www/twiki/data">
      deny from all
   </Directory>

   <Directory "/var/www/twiki/templates">
      deny from all
   </Directory>

   RewriteEngine On

   # / displays homepage
   RewriteRule  ^/$ /twiki/bin/view/Main/WebHome [PT]

   # Nicer, and to prevent anyone to bypass the following redirect
   RewriteRule ^/twiki/bin/(.*) /$1 [R=permanent,L]

   # Scripts that need to be authentificated can *only* be accessed via httpS
   RewriteRule ^/(viewauth|edit|preview|save|attach|upload|rename|rdiffauth|manage|installpasswd|logon|logout)(.*) https://%{SERVER_NAME}/$1$2 [R,L]

   # if (URL begins with a caps) then
   #   rewrite /twiki/bin/view/URL and stop
   # end if
   # if (URL begins with view) then
   #   redirect to Web/Topic without view and stop
   # end if
   # if (URL begins with a script)
   #   rewrite /twiki/bin/URL
   # end if

   RewriteRule ^/(<span class="createlink">:upper:</span>.*) /twiki/bin/view/$1 [PT]
   RewriteRule ^/view/(.*) /$1 [R=permanent,L]

   RewriteCond %{DOCUMENT_ROOT}/bin/$1 -f
   RewriteRule ^/([a-z]+)(.*) /twiki/bin/$1$2 [PT]

</VirtualHost>

<VirtualHost 69.90.134.151:443>
   SSLEngine On
   SSLSessionCacheTimeout 15
   SSLVerifyDepth 10
   SSLCACertificateFile /etc/ssl/wiki.boum.org/CAcert.crt
   SSLCertificateFile /etc/ssl/wiki.boum.org/wiki.boum.org.crt
   SSLCertificateKeyFile /etc/ssl/wiki.boum.org/wiki.boum.org.key
   ServerName wiki.boum.org
   ServerAdmin wiki@boumNO.SPAMorg
   DocumentRoot /var/www/twiki
   ScriptAlias /twiki/bin/ "/var/www/twiki/bin/"
   Alias /twiki/ "/var/www/twiki/"

   <Directory "/var/www/twiki/bin">
       Options +ExecCGI
       SetHandler cgi-script
       Allow from all

      # Authentication type (htpasswd file)
      AuthUserFile /var/www/twiki/data/.htpasswd
      AuthName 'wiki.boum.org'
      AuthType Basic

      # File to return on access control error (e.g. wrong password)
      ErrorDocument 401 /twiki/bin/oops/TWiki/TWikiRegistration?template=oopsauth

      <Files ~ "[^/]*\.html$">
                SetHandler blabla
                allow from all
      </Files>

      <Files "viewauth">
                require valid-user
      </Files>

      <Files "edit">
                require valid-user
      </Files>

      <Files "preview">
                require valid-user
      </Files>

      <Files "save">
                require valid-user
      </Files>

      <Files "attach">
                require valid-user
      </Files>

      <Files "upload">
                require valid-user
      </Files>

      <Files "rename">
         require valid-user
      </Files>

      <Files "rdiffauth">
                require valid-user
      </Files>

      <Files "manage">
                require valid-user
      </Files>

      <Files "installpasswd">
                require valid-user
      </Files>

      <Files "logon">
                require valid-user
      </Files>

      <Files "*">
                allow from all
      </Files>

   </Directory>

   <Directory "/var/www/twiki/pub">
      Options FollowSymLinks +Includes
          AllowOverride None
          Allow from all
   </Directory>

   <Directory "/var/www/twiki/data">
      deny from all
   </Directory>

   <Directory "/var/www/twiki/templates">
      deny from all
   </Directory>

   RewriteEngine On

   # / displays WebHome
   RewriteRule  ^/$ /twiki/bin/view/Main/WebHome [PT]

   # if (URL begins with a caps) then
   #   rewrite /twiki/bin/view/URL and stop
   # end if
   # if (URL begins with view) then
   #   redirect to Web/Topic without view and stop
   # end if
   # if (URL begins with a script)
   #   rewrite /twiki/bin/URL
   # end if

   RewriteRule ^/(<span class="createlink">:upper:</span>.*) /twiki/bin/view/$1 [PT]

   RewriteRule ^/view/(.*) /$1 [R=permanent,L]

   RewriteCond %{DOCUMENT_ROOT}/bin/$1 -f
   RewriteRule ^/([a-z]+)(.*) /twiki/bin/$1$2 [PT]

</VirtualHost>

TWiki configuration & patches

TWiki.cfg

TWiki is supposed to use $dispScriptUrlPath and $dispViewPath to build the URLs it writes in the generated pages. They have to be set to empty values.

$dispScriptUrlPath = "";
$dispViewPath     = "";

Perl is your friend

Actually, it's not sufficient : /view is harcoded in TWiki:Codev/PatternSkin templates (templates/*.pattern.tmpl) and at various locations in TWiki code. This can be cured easily :

find templates -name '*.tmpl' -exec perl -pi -e 's,/view%SCRIPTSUFFIX%,%VIEWPATH%,g' {} \;
find lib -name '*.pm' -exec perl -pi -e 's,/view%SCRIPTSUFFIX%,%VIEWPATH%,g' {} \;
find bin -type f -exec perl -pi -e 's,/view\$scriptSuffix,\$dispViewPath,g' {} \;
find data -name '*.txt' -exec perl -pi -e 's,/view%SCRIPTSUFFIX%,%VIEWPATH%,g' {} \;

Patches

Here are the patches :

... that contain exactly this :

Perl substitutions cleanup

Perl is your friend... but you need to clean after him, sometimes : it allows to replace a variable with another automatically, but does not guess he has to initialize them.

--- bin/mailnotify-20040901.orig   2004-12-23 07:28:20.000000000 -0800
+++ bin/mailnotify   2004-12-23 07:28:50.000000000 -0800
@@ -109,6 +109,7 @@
     my $scriptSuffix = $TWiki::scriptSuffix;
     my $scriptUrlPath = $TWiki::scriptUrlPath;
     my $scriptUrl = "$TWiki::urlHost$scriptUrlPath";
+    my $dispViewPath = "$TWiki::dispViewPath";
     my $frev = "";

     foreach( reverse split( /\n/, $changes ) ) {

UI :: View.pm

diff -Naur /root/politburo/twiki/backup/lib-20041222/TWiki/UI/View.pm lib/TWiki/UI/View.pm
--- /root/politburo/twiki/backup/lib-20041222/TWiki/UI/View.pm   2004-08-24 23:36:15.000000000 -0700
+++ lib/TWiki/UI/View.pm   2004-12-22 19:32:44.000000000 -0800
@@ -247,6 +247,9 @@
   # check access permission
   my $viewAccessOK = &TWiki::Access::checkAccessPermission( "view", $wikiUserName, $text, $topic, $webName );

+  # we will remember if the next if... block has redirected, in order to prevent the next one to oops and block the redirect
+  my $boumWasRedirected = 0;
+
   if( (!$topicExists) || $TWiki::readTopicPermissionFailed ) {
     # Can't read requested topic and/or included (or other accessed topics
     # user could not be authenticated, may be not logged in yet?
@@ -270,22 +273,15 @@
         my $script      = $ENV{'SCRIPT_NAME'};
         my $pathInfo    = $ENV{'PATH_INFO'};
         my $queryString = $ENV{'QUERY_STRING'};
-        $pathInfo    = '/' . $pathInfo    if ($pathInfo);
         $queryString = '?' . $queryString if ($queryString);
-        if ($script && $script =~ m|/view| ) {
-          $script =~ s|/view|/viewauth|o;
-          $url = "$TWiki::urlHost$script$pathInfo$queryString";
-        } else {
-          # If SCRIPT_NAME does not contain the name "view"
-          # the last hope is to try the SCRIPT_FILENAME ...
           $viewauthFile =~ s|^.*/viewauth|/viewauth|o;  # strip off $Twiki::scriptUrlPath
-         $url = "$TWiki::urlHost$TWiki::scriptUrlPath/$viewauthFile$pathInfo$queryString";
-         }
+         $url = "$TWiki::urlHost$TWiki::dispScriptUrlPath$viewauthFile$pathInfo$queryString";
       }
       TWiki::UI::redirect( $url );
+      $boumWasRedirected = 1;
     }
   }
-  if( ! $viewAccessOK ) {
+  if( (! $viewAccessOK) && (! $boumWasRedirected) ) {
     TWiki::UI::oops( $webName, $topic, "accessview" );
   }

TWiki.pm

diff -Naur /root/politburo/twiki/backup/lib-20041222/TWiki.pm lib/TWiki.pm
--- /root/politburo/twiki/backup/lib-20041222/TWiki.pm   2004-08-29 23:46:11.000000000 -0700
+++ lib/TWiki.pm   2004-12-22 19:29:04.000000000 -0800
@@ -424,7 +424,7 @@
     $includingWebName = $webName;

     # initialize $urlHost and $scriptUrlPath
-    if( ( $theUrl ) && ( $theUrl =~ m!^([^:]*://[^/]*)(.*)/.*$! ) && ( $2 ) ) {
+    if( ( $theUrl ) && ( $theUrl =~ m!^([^:]*://[^/]*).*$! )  ) {
         if( $doGetScriptUrlFromCgi ) {
             $scriptUrlPath = $2;
         }
@@ -2945,6 +2945,7 @@
     $_[0] =~ s/%WIKIHOMEURL%/$wikiHomeUrl/g;
     $_[0] =~ s/%SCRIPTURL%/$urlHost$dispScriptUrlPath/g;
     $_[0] =~ s/%SCRIPTURLPATH%/$dispScriptUrlPath/g;
+    $_[0] =~ s/%VIEWPATH%/$dispViewPath/g;
     $_[0] =~ s/%SCRIPTSUFFIX%/$scriptSuffix/g;
     $_[0] =~ s/%PUBURL%/$urlHost$pubUrlPath/g;
     $_[0] =~ s/%PUBURLPATH%/$pubUrlPath/g;

Integration to Dakar

The following bugs have been filled in order to make Dakar more easily adaptable to this setup :