[Home]WikiPatches/WikiFarm

UseModWiki | WikiPatches | RecentChanges | Preferences

I've written a WikiFarm? patch that is in use at [KiwiWiki]. I've pasted it below. Parts of it are hackish, but it works well enough for me. No documentation yet (sorry). Also, it doesn't patch everything because I never use some features with it, like file uploads, so if you want to use those you'll have to extend the patch. It also contains some junk that doesn't actually make the patch work, but I was too lazy to make the patch file pristine.

Comments and suggestions for improvement are greatly appreciated.

-- GordonWorley

@@ -62,19 +62,115 @@
   $OpenPageName @KeptList @IndexList $IndexInit $TableMode
   $q $Now $UserID $TimeZoneOffset $ScriptName $BrowseCode $OtherCode
   $AnchoredLinkPattern @HeadingNumbers $TableOfContents $QuotedFullUrl
-  $ConfigError $UploadPattern );
+  $ConfigError $UploadPattern);
+# Wiki farm global variables:
+use vars qw($WikiName $ConfigOverrideFile $FarmDir $FarmConfigFile
+		$NamedWikisOnly $UseFarmConfig $UseOverrideConfig $WikiNotFound
+		$WikiNamesFile $DefaultWiki);
+
+#Wiki farm config defaults
+
+$FarmDir = "/path/to/wikidbs"; #no trailing slash
+$UseFarmConfig = 0;
+$FarmConfigFile = "$FarmDir/config"; #set wiki farm options
+$WikiNamesFile = "$FarmDir/names";
+
+$ConfigOverrideFile = "$FarmDir/configall"; #farm-wide config override
+$WikiNotFound = "/notfound.html"; #page if wiki not found
+$DefaultWiki = "KiwiWiki";
+
+$UseOverrideConfig = 1;
+$NamedWikisOnly = 1; #only allow wikis in $WikiNamesFile
+
+if ($UseFarmConfig && (-f $FarmConfigFile))
+{
+    $ConfigError = '';
+    if (!do $FarmConfigFile) {   # Some error occurred
+      $ConfigError = $@;
+      if ($ConfigError eq '') {
+        # Unfortunately, if the last expr returns 0, one will get a false
+        # error above.  To remain compatible with existing installs the
+        # wiki must not report an error unless there is error text in $@.
+        # (Errors in "use strict" may not have error text.)
+        # Uncomment the line below if you want to catch use strict errors.
+#       $ConfigError = T('Unknown Error (no error text)');
+      }
+    }
+}
+
+use CGI;
+use CGI::Carp qw(fatalsToBrowser);
+
+$q = new CGI;
+
+$WikiName = $q->param('keywords');
+if ($WikiName)
+	#just script?WikiName/PageName
+{
+	$WikiName =~ s/(.*?)\/.*/\1/;
+}
+elsif ($q->param("wiki"))
+	# url is something like ...?...&wiki=WikiName&...
+{
+	$WikiName = $q->param("wiki");
+}
+else
+	# if no wiki name is given
+{
+	$WikiName = $DefaultWiki;
+}
+
+unless (&WikiExists())
+{
+	# handle missing wiki by sending to $WikiNotFound
+	print "Location: $WikiNotFound";
+	error ($q, "wiki doesn't exist");
+}
+
+sub WikiExists
+	#should check if the wiki exists
+	#if not, take some action
+{
+	if (!$NamedWikisOnly)
+	{
+		#just return true
+		#wikis are created by naming them
+		return 1;
+	}
+	elsif (-e "$WikiNamesFile")
+		#check if the wiki exists
+	{
+		open (WNAMES, "<$WikiNamesFile");
+		while (my $line = <WNAMES>)
+		{
+			if ($line =~ /^$WikiName$/)
+			{
+				close(WNAMES);
+				return 1;
+			}
+		}
+		close(WNAMES);
+		return 0;
+	}
+	else
+	{
+		#some kind of error
+		#shouldn't happen, but just in case
+		return 0;
+	}
+}
 
 # == Configuration =====================================================
-$DataDir     = "/Library/WebServer/mangowikidb"; # Main wiki directory
+$DataDir     = "$FarmDir/$WikiName"; # Main wiki directory
 $UseConfig   = 1;       # 1 = use config file,    0 = do not look for config
 $ConfigFile  = "$DataDir/config";   # Configuration file
 
 # Default configuration (used if UseConfig is 0)
-$CookieName  = "Wiki";          # Name for this wiki (for multi-wiki sites)
-$SiteName    = "Wiki";          # Name of site (used for titles)
-$HomePage    = "HomePage";      # Home page (change space to _)
+$CookieName  = "$WikiName";          # Name for this wiki (for multi-wiki sites)
+$SiteName    = "$WikiName";          # Name of site (used for titles)
+$HomePage    = "$WikiName";      # Home page (change space to _)
 $RCName      = "RecentChanges"; # Name of changes page (change space to _)
-$LogoUrl     = "/wiki.gif";     # URL for site logo ("" for no logo)
+$LogoUrl     = "";     # URL for site logo ("" for no logo)
 $ENV{PATH}   = "/usr/bin/";     # Path used to find "diff"
 $ScriptTZ    = "";              # Local time zone ("" means do not print)
 $RcDefault   = 30;              # Default number of RecentChanges days
@@ -87,7 +183,7 @@
 $EditPass    = "";              # Like AdminPass, but for editing only
 $StyleSheet  = "";              # URL for CSS stylesheet (like "/wiki.css")
 $NotFoundPg  = "";              # Page for not-found links ("" for blank pg)
-$EmailFrom   = "Wiki";          # Text for "From: " field of email notes.
+$EmailFrom   = "$WikiName";          # Text for "From: " field of email notes.
 $SendMail    = "/usr/sbin/sendmail";  # Full path to sendmail executable
 $FooterNote  = "";              # HTML for bottom of every page
 $EditNote    = "";              # HTML notice above buttons on edit page
@@ -130,19 +226,19 @@
 $ReplaceFile = 'ReplaceFile';   # 0 = disable, 'PageName' = indicator tag
 @ReplaceableFiles = ();     # List of allowed server files to replace
 $TableSyntax = 1;           # 1 = wiki syntax tables, 0 = no table syntax
-$NewFS       = 0;           # 1 = new multibyte $FS,  0 = old $FS
+$NewFS       = 1;           # 1 = new multibyte $FS,  0 = old $FS
 $UseUpload   = 0;           # 1 = allow uploads,      0 = no uploads
 
 # Minor options:
 $LogoLeft     = 0;      # 1 = logo on left,       0 = logo on right
 $RecentTop    = 1;      # 1 = recent on top,      0 = recent on bottom
-$UseDiffLog   = 1;      # 1 = save diffs to log,  0 = do not save diffs
+$UseDiffLog   = 0;      # 1 = save diffs to log,  0 = do not save diffs
 $KeepMajor    = 1;      # 1 = keep major rev,     0 = expire all revisions
 $KeepAuthor   = 1;      # 1 = keep author rev,    0 = expire all revisions
 $ShowEdits    = 0;      # 1 = show minor edits,   0 = hide edits by default
 $HtmlLinks    = 0;      # 1 = allow A HREF links, 0 = no raw HTML links
 $SimpleLinks  = 0;      # 1 = only letters,       0 = allow _ and numbers
-$NonEnglish   = 0;      # 1 = extra link chars,   0 = only A-Za-z chars
+$NonEnglish   = 1;      # 1 = extra link chars,   0 = only A-Za-z chars
 $ThinLine     = 0;      # 1 = fancy <hr> tags,    0 = classic wiki <hr>
 $BracketText  = 1;      # 1 = allow [URL text],   0 = no link descriptions
 $UseAmPm      = 1;      # 1 = use am/pm in times, 0 = use 24-hour times
@@ -203,7 +299,7 @@
 $KeepDir     = "$DataDir/keep";     # Stores kept (old) page data
 $TempDir     = "$DataDir/temp";     # Temporary files and locks
 $LockDir     = "$TempDir/lock";     # DB is locked if this exists
-$InterFile   = "$DataDir/intermap"; # Interwiki site->url map
+$InterFile   = "$FarmDir/intermap"; # Interwiki site->url map
 $RcFile      = "$DataDir/rclog";    # New RecentChanges logfile
 $RcOldFile   = "$DataDir/oldrclog"; # Old RecentChanges logfile
 $IndexFile   = "$DataDir/pageidx";  # List of all pages
@@ -229,6 +325,23 @@
       }
     }
   }
+# override any user-set options that we want the same on all wikis
+# mostly for security purposes, but also to prevent other things
+# like if you want ads on all pages
+  if ($UseOverrideConfig && (-f $ConfigOverrideFile)) {
+    $ConfigError = '';
+    if (!do $ConfigOverrideFile) {   # Some error occurred
+      $ConfigError = $@;
+      if ($ConfigError eq '') {
+        # Unfortunately, if the last expr returns 0, one will get a false
+        # error above.  To remain compatible with existing installs the
+        # wiki must not report an error unless there is error text in $@.
+        # (Errors in "use strict" may not have error text.)
+        # Uncomment the line below if you want to catch use strict errors.
+#       $ConfigError = T('Unknown Error (no error text)');
+      }
+    }
+  }
   &InitLinkPatterns();
   if (!&DoCacheBrowse()) {
     eval $BrowseCode;
@@ -392,8 +505,6 @@
 # == Normal page-browsing and RecentChanges code =======================
 $BrowseCode = ""; # Comment next line to always compile (slower)
 #$BrowseCode = <<'#END_OF_BROWSE_CODE';
-use CGI;
-use CGI::Carp qw(fatalsToBrowser);
 
 sub InitRequest {
   my @ScriptPath = split('/', "$ENV{SCRIPT_NAME}");
@@ -459,6 +570,7 @@
   }
   $id = &GetParam('keywords', '');
   if ($id) {                    # Just script?PageName
+	$id =~ s/.*?\/(.*)/\1/;     # eat wiki name
     if ($FreeLinks && (!-f &GetPageFile($id))) {
       $id = &FreeToNormal($id);
     }
@@ -593,7 +705,7 @@
   my ($id, $oldId, $isEdit) = @_;
 
   if ($oldId ne "") {   # Target of #REDIRECT (loop breaking)
-    print &GetRedirectPage("action=browse&id=$id&oldid=$oldId",
+    print &GetRedirectPage("action=browse&wiki=$WikiName&id=$id&oldid=$oldId",
                            $id, $isEdit);
   } else {
     print &GetRedirectPage($id, $id, $isEdit);
@@ -689,13 +801,13 @@
     foreach $i (@RcDays) {
       print " | "  if $showbar;
       $showbar = 1;
-      print &ScriptLink("action=rc&days=$i",
+      print &ScriptLink("action=rc&days=$i&wiki=$WikiName",
                         Ts('%s day' . (($i != 1)?'s':''), $i));
         # Note: must have two translations (for "day" and "days")
         # Following comment line is for translation helper script
         # Ts('%s days', '');
     }
-    print "<br>" . &ScriptLink("action=rc&from=$lastTs",
+    print "<br>" . &ScriptLink("action=rc&from=$lastTs&wiki=$WikiName",
                                T('List new changes starting from'));
     print " " . &TimeToText($lastTs) . "<br>\n";
   }
@@ -763,8 +875,8 @@
   $tEdit    = T('(edit)');
   $tDiff    = T('(diff)');
   $tChanges = T('changes');
-  $diffPrefix = $QuotedFullUrl . &QuoteHtml("?action=browse\&diff=4\&id=");
-  $historyPrefix = $QuotedFullUrl . &QuoteHtml("?action=history\&id=");
+  $diffPrefix = $QuotedFullUrl . &QuoteHtml("?action=browse\&wiki=$WikiName\&diff=4\&id=");
+  $historyPrefix = $QuotedFullUrl . &QuoteHtml("?action=history\&wiki=$WikiName\&id=");
   foreach $rcline (@outrc) {
     ($ts, $pagename) = split(/$FS3/, $rcline);
     $pagecount{$pagename}++;
@@ -997,6 +1109,7 @@
           <input type='hidden' name='action' value='browse'/>
           <input type='hidden' name='diff' value='1'/>
           <input type='hidden' name='id' value='$id'/>
+		  <input type='hidden' name='wiki' value='$WikiName'/>
       <table border='0' width='100%'><tr>
 EOF
   }
@@ -1111,7 +1224,7 @@
     $id = &FreeToNormal($id);
     $name =~ s/_/ /g;
   }
-  return &ScriptLinkClass($id, $name, 'wikipagelink');
+  return &ScriptLinkClass("$WikiName/$id", $name, 'wikipagelink');
 }
 
 sub GetPageLink {
@@ -1127,7 +1240,7 @@
     $id = &FreeToNormal($id);
     $name =~ s/_/ /g;
   }
-  return &ScriptLinkClass("action=edit&id=$id", $name, 'wikipageedit');
+  return &ScriptLinkClass("action=edit&wiki=$WikiName&id=$id", $name, 'wikipageedit');
 }
 
 sub GetDeleteLink {
@@ -1137,14 +1250,14 @@
     $id = &FreeToNormal($id);
     $name =~ s/_/ /g;
   }
-  return &ScriptLink("action=delete&id=$id&confirm=$confirm", $name);
+  return &ScriptLink("action=delete&wiki=$WikiName&id=$id&confirm=$confirm", $name);
 }
 
 sub GetOldPageParameters {
   my ($kind, $id, $revision) = @_;
 
   $id = &FreeToNormal($id) if $FreeLinks;
-  return "action=$kind&id=$id&revision=$revision";
+  return "action=$kind&wiki=$WikiName&id=$id&revision=$revision";
 }
 
 sub GetOldPageLink {
@@ -1208,15 +1321,15 @@
     $name =~ s/_/ /g;  # Display with spaces
     $id =~ s/_/+/g;    # Search for url-escaped spaces
   }
-  return &ScriptLink("back=$id", $name);
+  return &ScriptLink("back=$id&wiki=$WikiName", $name);
 }
 
 sub GetPrefsLink {
-  return &ScriptLink("action=editprefs", T('Preferences'));
+  return &ScriptLink("action=editprefs&wiki=$WikiName", T('Preferences'));
 }
 
 sub GetRandomLink {
-  return &ScriptLink("action=random", T('Random Page'));
+  return &ScriptLink("action=random&wiki=$WikiName", T('Random Page'));
 }
 
 sub ScriptLinkDiff {
@@ -1224,7 +1337,7 @@
 
   $rev = "&revision=$rev"  if ($rev ne "");
   $diff = &GetParam("defaultdiff", 1)  if ($diff == 4);
-  return &ScriptLink("action=browse&diff=$diff&id=$id$rev", $text);
+  return &ScriptLink("action=browse&wiki=$WikiName&diff=$diff&id=$id$rev", $text);
 }
 
 sub ScriptLinkDiffRevision {
@@ -1232,11 +1345,11 @@
 
   $rev = "&diffrevision=$rev"  if ($rev ne "");
   $diff = &GetParam("defaultdiff", 1)  if ($diff == 4);
-  return &ScriptLink("action=browse&diff=$diff&id=$id$rev", $text);
+  return &ScriptLink("action=browse&wiki=$WikiName&diff=$diff&id=$id$rev", $text);
 }
 
 sub GetUploadLink {
-  return &ScriptLink('action=upload', T('Upload'));
+  return &ScriptLink('action=upload&wiki=$WikiName', T('Upload'));
 }
 
 sub ScriptLinkTitle {
@@ -1262,7 +1375,7 @@
     $userName = "";  # Just pretend it isn't there.
   }
   if (($uid > 0) && ($userName ne "")) {
-    $html = &ScriptLinkTitle($userName, $userNameShow,
+    $html = &ScriptLinkTitle("$WikiName/$userName", $userNameShow,
             Ts('ID %s', $uid) . ' ' . Ts('from %s', $host));
   } else {
     $html = $host;
@@ -1276,12 +1389,12 @@
   if ($FreeLinks) {
     $id =~ s/ /_/g;
   }
-  return &ScriptLink("action=history&id=$id", $text);
+  return &ScriptLink("action=history&wiki=$WikiName&id=$id", $text);
 }
 
 sub GetHeader {
   my ($id, $title, $oldId) = @_;
-  my $header = "";
+  my $header = "$WikiName:  ";
   my $logoImage = "";
   my $result = "";
   my $embed = &GetParam('embed', $EmbedWiki);
@@ -1304,7 +1417,7 @@
     if (!$LogoLeft) {
       $logoImage .= " align=\"right\"";
     }
-    $header = &ScriptLink($HomePage, "<$logoImage>");
+    $header = "$WikiName:  " . &ScriptLink($HomePage, "<$logoImage>");
   }
   if ($id ne '') {
     $result .= $q->h1($header . &GetBackLinksSearchLink($id));
@@ -1513,7 +1626,7 @@
 
   # Normally get URL from script, but allow override.
   $FullUrl = $q->url(-full=>1)  if ($FullUrl eq "");
-  $url = $FullUrl . &ScriptLinkChar() . $newid;
+  $url = $FullUrl . &ScriptLinkChar() . "$WikiName/$newid";
   $nameLink = "<a href=\"$url\">$name</a>";
   if ($RedirType < 3) {
     if ($RedirType == 1) {             # Use CGI.pm
@@ -3244,7 +3357,8 @@
   print &GetFormStart();
   print &GetHiddenValue("title", $id), "\n",
         &GetHiddenValue("oldtime", $pageTime), "\n",
-        &GetHiddenValue("oldconflict", $isConflict), "\n";
+        &GetHiddenValue("oldconflict", $isConflict), "\n",
+		&GetHiddenValue("wiki", $WikiName), "\n";
   if ($revision ne "") {
     print &GetHiddenValue("revision", $revision), "\n";
   }
@@ -3402,6 +3516,7 @@
                               T('Add "Random Page" link to link bar'));
   print '<br>' . T('StyleSheet URL:') . ' ',
         &GetFormText('stylesheet', "", 30, 150);
+  print &GetHiddenValue('wiki', $WikiName), "\n";
   print '<br>', $q->submit(-name=>'Save', -value=>T('Save')), "\n";
   print '</div>';
   print "<hr class=wikilinefooter>\n";
@@ -4089,7 +4204,7 @@
   so only do that if you mean to.
 
   To remove yourself from this list, visit
-  ${home_url}?action=editprefs .)
+  ${home_url}?action=editprefs&wiki=$WikiName .)
 END_MAIL_CONTENT
     my $subject = "The $id page at $SiteName has been changed.";
     # I'm setting the "reply-to" field to be the same as the "to:" field
@@ -4839,7 +4954,7 @@
   if ($FreeLinks) {
     $id = &FreeToNormal($id);
   }
-  return &ScriptLink("action=pagelock&set=$status&id=$id", $name);
+  return &ScriptLink("action=pagelock&set=$status&wiki=$WikiName&id=$id", $name);
 }
 
 sub GetAdminBar {
@@ -4854,13 +4969,13 @@
     $result .= &GetPageLockLink($id, 1, T('Lock page'));
   }
   $result .= " | " . &GetDeleteLink($id, T('Delete this page'), 0);
-  $result .= " | " . &ScriptLink("action=editbanned", T("Edit Banned List"));
-  $result .= " | " . &ScriptLink("action=maintain", T("Run Maintenance"));
-  $result .= " | " . &ScriptLink("action=editlinks", T("Edit/Rename pages")); 
+  $result .= " | " . &ScriptLink("action=editbanned&wiki=$WikiName", T("Edit Banned List"));
+  $result .= " | " . &ScriptLink("action=maintain&wiki=$WikiName", T("Run Maintenance"));
+  $result .= " | " . &ScriptLink("action=editlinks&wiki=$WikiName", T("Edit/Rename pages")); 
   if (-f "$DataDir/noedit") {
-    $result .= " | " . &ScriptLink("action=editlock&set=0", T("Unlock site")); 
+    $result .= " | " . &ScriptLink("action=editlock&set=0&wiki=$WikiName", T("Unlock site")); 
   } else {
-    $result .= " | " . &ScriptLink("action=editlock&set=1", T("Lock site"));
+    $result .= " | " . &ScriptLink("action=editlock&set=1&wiki=$WikiName", T("Lock site"));
   }
   return $result;
 }
@@ -4911,6 +5026,7 @@
   print '<FORM METHOD="post" ACTION="' . $ScriptName
         . '" ENCTYPE="multipart/form-data">';
   print '<input type="hidden" name="upload" value="1" />';
+  print '<input type="hidden" name="wiki" value="' . $WikiName . '"/>';
   print 'File to Upload: <INPUT TYPE="file" NAME="file"><br><BR>';
   print '<INPUT TYPE="submit" NAME="Submit" VALUE="Upload">';
   print '</FORM>';

I am currently working on a patch to facilitate multi-wiki sites, ie /WikiFarms. Work is not complete but if you're interested in commenting on my thoughts so far please join me there -- RiVer
A slightly simpler patch compared to the above would be to make these changes to wiki.pl (version 1.0.4): (The latter isn't necessary, but makes more sense IMO if we are going to treat wiki.pl as a Perl library.)

Then load and run wiki.pl from wrapper scripts:

#!/usr/bin/perl
package UseModWiki;
$DataDir = '/path/to/wiki/data';
require '/path/to/wiki.pl';
DoWikiRequest();

This presupposes that there is a config file in the DataDir of each wiki. --GunnarH


UseModWiki | WikiPatches | RecentChanges | Preferences
Edit text of this page | View other revisions | Search MetaWiki
Last edited March 22, 2009 12:16 am by GunnarH (diff)
Search: