508a509,994
> <div title="ConfigTweaks" modifier="Zooko" created="200812152209" modified="200812152226" tags="systemConfig" changecount="3">
> <pre>//{{{
> config.options.txtTheme = &quot;WritableTheme&quot;;
> //}}}</pre>
> </div>
> <div title="HTTPSavingPlugin" modifier="Zooko" created="200812152200" modified="200812152200" tags="systemConfig" changecount="4">
> <pre>/***
> |''Name''|HTTPSavingPlugin|
> |''Description''|&lt;...&gt;|
> |''Author''|Zooko|
> |''Contributors''|FND|
> |''Version''|0.2.1|
> |''Status''|@@experimental@@|
> |''Source''|http://allmydata.org/trac/tiddly_on_tahoe|
> |''CodeRepository''|http://allmydata.org/source/tiddly_on_tahoe/trunk/|
> |''License''|GPLv2+ or TGPPLv1.0+|
> |''Keywords''|&lt;...&gt;|
> !Description
> &lt;...&gt;
> !Notes
> This plugin is being developed for [[Tiddly on Tahoe|http://allmydata.org/trac/tiddly_on_tahoe]].
> ***/
> /* The following comment is to let jslint know which variables are supposed to be global. */
> /*global clearMessage, config, getPath, readOnly, saveChanges, saveTest, showBackstage, store, story, version, convertUriToUTF8, convertUnicodeToFileFormat, getLocalPath, loadRemoteFile, locateStoreArea, saveBackup, saveEmpty, saveFile, saveMain, saveRss, unescape, displayMessage, httpReq */
> //{{{
> if (!version.extensions.HTTPSavingPlugin) { //# ensure that the plugin is only installed once
> 	version.extensions.HTTPSavingPlugin = { installed: true };
> 
> 	(function () { //# wrapper
> 		readOnly = false;
> 		config.options.chkHttpReadOnly = false;
> 		showBackstage = true;
> 
> 		saveTest = function () {
> 			var s = document.getElementById(&quot;saveTest&quot;);
> 			/*if (s.hasChildNodes()) {
> 			  alert(config.messages.savedSnapshotError);
> 			  }*/
> 			s.appendChild(document.createTextNode(&quot;savetest&quot;));
> 		};
> 
> 		// Save this TiddlyWiki with the pending changes
> 		saveChanges = function (onlyIfDirty, tiddlers) {
> 			var originalPath, localCallback, result;
> 			if (onlyIfDirty &amp;&amp; !store.isDirty()) {
> 				return;
> 			}
> 			clearMessage();
> 			// Get the URL of the document
> 			originalPath = getPath(document.location.toString());
> 			// Load the original file
> 			localCallback = function (status, context, original, url, xhr) {
> 				//log(&quot;loaded remote file from &quot;, originalPath);
> 				/*log(&quot;got callback status &quot;, status, &quot;\n&quot;, context: &quot;, context, &quot;\n&quot;,
> 				  URL: &quot;, url, &quot;\n&quot;, XHR: &quot;, xhr);*/
> 				if (original === null) {
> 					alert(config.messages.cantSaveError);
> 					if (store.tiddlerExists(config.messages.saveInstructions)) {
> 						story.displayTiddler(null, config.messages.saveInstructions);
> 					}
> 					return;
> 				}
> 				// Locate the storeArea div's
> 				var posDiv = locateStoreArea(original);
> 				if (!posDiv) {
> 					alert(config.messages.invalidFileError.format([originalPath]));
> 					return;
> 				}
> 				saveRss(originalPath);
> 				saveEmpty(originalPath, original, posDiv);
> 				saveMain(originalPath, original, posDiv);
> 			};
> 			result = loadRemoteFile(originalPath, localCallback);
> 			//log(&quot;result from loadRemoteFile: &quot;, result);
> 			return true;
> 		};
> 
> 		// override and disable saveBackup()
> 		saveBackup = function (localPath, original) {};
> 
> 		// override and disable getLocalPath()
> 		getLocalPath = function (origPath) {};
> 
> 		// override getPath()
> 		getPath = function (origPath) {
> 			var originalPath, argPos, hashPos, resultPath;
> 			originalPath = convertUriToUTF8(origPath, config.options.txtFileSystemCharSet);
> 			// Remove any location or query part of the URL
> 			argPos = originalPath.indexOf(&quot;?&quot;);
> 			if (argPos !== -1) {
> 				originalPath = originalPath.substr(0, argPos);
> 			}
> 			hashPos = originalPath.indexOf(&quot;#&quot;);
> 			if (hashPos !== -1) {
> 				originalPath = originalPath.substr(0, hashPos);
> 			}
> 			// Convert file://localhost/ to file:///
> 			if (originalPath.indexOf(&quot;file://localhost/&quot;) === 0) {
> 				originalPath = &quot;file://&quot; + originalPath.substr(16);
> 			}
> 			// Convert to a native file format
> 			if (originalPath.indexOf(&quot;http://&quot;) === 0) { // HTTP file
> 				resultPath = originalPath;
> 			} else if (originalPath.charAt(9) === &quot;:&quot;) { // PC local file
> 				resultPath = unescape(originalPath.substr(8)).replace(new RegExp(&quot;/&quot;, &quot;g&quot;), &quot;\\&quot;);
> 			} else if (originalPath.indexOf(&quot;file://///&quot;) === 0) { // Firefox PC network file
> 				resultPath = &quot;\\\\&quot; + unescape(originalPath.substr(10)).replace(new RegExp(&quot;/&quot;, &quot;g&quot;), &quot;\\&quot;);
> 			} else if (originalPath.indexOf(&quot;file:///&quot;) === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(7));
> 			} else if (originalPath.indexOf(&quot;file:/&quot;) === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(5));
> 			} else { // PC local file
> 				resultPath = &quot;\\\\&quot; + unescape(originalPath.substr(7)).replace(new RegExp(&quot;/&quot;, &quot;g&quot;), &quot;\\&quot;);
> 			}
> 			return resultPath;
> 		};
> 
> 		// override saveFile()
> 		saveFile = function (fileUrl, content, callb) {
> 			displayMessage(&quot;saving... please wait&quot;); // XXX: belongs into command handler -- TODO: i18n
> 			//alert(&quot;whee! about to save to &quot; + fileUrl);
> 			var localCallback = function (status, params, responseText, url, xhr) {
> 				if (!status) {
> 					displayMessage(&quot;saving failed: &quot; + responseText);
> 				}
> 			};
> 			return httpReq(&quot;PUT&quot;, fileUrl, localCallback, null, null, content, &quot;text/html;charset=utf-8&quot;);
> 		};
> 
> 		// override convertUnicodeToFileFormat()
> 		convertUnicodeToFileFormat = function (s)
> 		{
> 			return s;
> 		};
> 
> 	})(); //# end of wrapper
> } //# end of &quot;install only once&quot;
> //}}}
> </pre>
> </div>
> <div title="PageTemplate" modifier="Zooko" created="200812152204" changecount="4">
> <pre>&lt;!--{{{--&gt;
> &lt;div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'&gt;
> &lt;div class='headerShadow'&gt;
> &lt;div id='accessControlExplanationDivId' macro='accessControlExplanation'&gt;&lt;/div&gt;
> &lt;span class='siteTitle' refresh='content' tiddler='SiteTitle'&gt;&lt;/span&gt;&amp;nbsp;
> &lt;span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'&gt;&lt;/span&gt;
> &lt;/div&gt;
> &lt;div class='headerForeground'&gt;
> &lt;div id='accessControlExplanationDivId' macro='accessControlExplanation'&gt;&lt;/div&gt;
> &lt;span class='siteTitle' refresh='content' tiddler='SiteTitle'&gt;&lt;/span&gt;&amp;nbsp;
> &lt;span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'&gt;&lt;/span&gt;
> &lt;/div&gt;
> &lt;/div&gt;
> &lt;div id='mainMenu' refresh='content' tiddler='MainMenu'&gt;&lt;/div&gt;
> &lt;div id='sidebar'&gt;
> &lt;div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'&gt;&lt;/div&gt;
> &lt;div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'&gt;&lt;/div&gt;
> &lt;/div&gt;
> &lt;div id='displayArea'&gt;
> &lt;div id='messageArea'&gt;&lt;/div&gt;
> &lt;div id='tiddlerDisplay'&gt;&lt;/div&gt;
> &lt;/div&gt;
> &lt;!--}}}--&gt;</pre>
> </div>
> <div title="TahoePlugin" modifier="Zooko" created="200812152200" modified="200812152206" tags="systemConfig" changecount="5">
> <pre>/***
> |''Name''|HTTPSavingPlugin|
> |''Description''|&lt;...&gt;|
> |''Author''|Zooko|
> |''Contributors''|FND|
> |''Version''|0.2.1|
> |''Status''|@@experimental@@|
> |''Source''|http://allmydata.org/trac/tiddly_on_tahoe|
> |''CodeRepository''|http://allmydata.org/source/tiddly_on_tahoe/trunk/|
> |''License''|GPLv2+ or TGPPLv1.0+|
> |''Keywords''|&lt;...&gt;|
> !Description
> &lt;...&gt;
> !Notes
> This plugin is being developed for [[Tiddly on Tahoe|http://allmydata.org/trac/tiddly_on_tahoe]].
> ***/
> /* The following comment is to let jslint know which variables are supposed to be global. */
> /*global clearMessage, config, getPath, readOnly, saveChanges, saveTest, showBackstage, store, story, version, convertUriToUTF8, convertUnicodeToFileFormat, getLocalPath, loadRemoteFile, locateStoreArea, saveBackup, saveEmpty, saveFile, saveMain, saveRss, unescape, displayMessage, httpReq */
> //{{{
> if (!version.extensions.HTTPSavingPlugin) { //# ensure that the plugin is only installed once
> 	version.extensions.HTTPSavingPlugin = { installed: true };
> 
> 	(function () { //# wrapper
> 		readOnly = false;
> 		config.options.chkHttpReadOnly = false;
> 		showBackstage = true;
> 
> 		saveTest = function () {
> 			var s = document.getElementById(&quot;saveTest&quot;);
> 			/*if (s.hasChildNodes()) {
> 			  alert(config.messages.savedSnapshotError);
> 			  }*/
> 			s.appendChild(document.createTextNode(&quot;savetest&quot;));
> 		};
> 
> 		// Save this TiddlyWiki with the pending changes
> 		saveChanges = function (onlyIfDirty, tiddlers) {
> 			var originalPath, localCallback, result;
> 			if (onlyIfDirty &amp;&amp; !store.isDirty()) {
> 				return;
> 			}
> 			clearMessage();
> 			// Get the URL of the document
> 			originalPath = getPath(document.location.toString());
> 			// Load the original file
> 			localCallback = function (status, context, original, url, xhr) {
> 				//log(&quot;loaded remote file from &quot;, originalPath);
> 				/*log(&quot;got callback status &quot;, status, &quot;\n&quot;, context: &quot;, context, &quot;\n&quot;,
> 				  URL: &quot;, url, &quot;\n&quot;, XHR: &quot;, xhr);*/
> 				if (original === null) {
> 					alert(config.messages.cantSaveError);
> 					if (store.tiddlerExists(config.messages.saveInstructions)) {
> 						story.displayTiddler(null, config.messages.saveInstructions);
> 					}
> 					return;
> 				}
> 				// Locate the storeArea div's
> 				var posDiv = locateStoreArea(original);
> 				if (!posDiv) {
> 					alert(config.messages.invalidFileError.format([originalPath]));
> 					return;
> 				}
> 				saveRss(originalPath);
> 				saveEmpty(originalPath, original, posDiv);
> 				saveMain(originalPath, original, posDiv);
> 			};
> 			result = loadRemoteFile(originalPath, localCallback);
> 			//log(&quot;result from loadRemoteFile: &quot;, result);
> 			return true;
> 		};
> 
> 		// override and disable saveBackup()
> 		saveBackup = function (localPath, original) {};
> 
> 		// override and disable getLocalPath()
> 		getLocalPath = function (origPath) {};
> 
> 		// override getPath()
> 		getPath = function (origPath) {
> 			var originalPath, argPos, hashPos, resultPath;
> 			originalPath = convertUriToUTF8(origPath, config.options.txtFileSystemCharSet);
> 			// Remove any location or query part of the URL
> 			argPos = originalPath.indexOf(&quot;?&quot;);
> 			if (argPos !== -1) {
> 				originalPath = originalPath.substr(0, argPos);
> 			}
> 			hashPos = originalPath.indexOf(&quot;#&quot;);
> 			if (hashPos !== -1) {
> 				originalPath = originalPath.substr(0, hashPos);
> 			}
> 			// Convert file://localhost/ to file:///
> 			if (originalPath.indexOf(&quot;file://localhost/&quot;) === 0) {
> 				originalPath = &quot;file://&quot; + originalPath.substr(16);
> 			}
> 			// Convert to a native file format
> 			if (originalPath.indexOf(&quot;http://&quot;) === 0) { // HTTP file
> 				resultPath = originalPath;
> 			} else if (originalPath.charAt(9) === &quot;:&quot;) { // PC local file
> 				resultPath = unescape(originalPath.substr(8)).replace(new RegExp(&quot;/&quot;, &quot;g&quot;), &quot;\\&quot;);
> 			} else if (originalPath.indexOf(&quot;file://///&quot;) === 0) { // Firefox PC network file
> 				resultPath = &quot;\\\\&quot; + unescape(originalPath.substr(10)).replace(new RegExp(&quot;/&quot;, &quot;g&quot;), &quot;\\&quot;);
> 			} else if (originalPath.indexOf(&quot;file:///&quot;) === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(7));
> 			} else if (originalPath.indexOf(&quot;file:/&quot;) === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(5));
> 			} else { // PC local file
> 				resultPath = &quot;\\\\&quot; + unescape(originalPath.substr(7)).replace(new RegExp(&quot;/&quot;, &quot;g&quot;), &quot;\\&quot;);
> 			}
> 			return resultPath;
> 		};
> 
> 		// override saveFile()
> 		saveFile = function (fileUrl, content, callb) {
> 			displayMessage(&quot;saving... please wait&quot;); // XXX: belongs into command handler -- TODO: i18n
> 			//alert(&quot;whee! about to save to &quot; + fileUrl);
> 			var localCallback = function (status, params, responseText, url, xhr) {
> 				if (!status) {
> 					displayMessage(&quot;saving failed: &quot; + responseText);
> 				}
> 			};
> 			return httpReq(&quot;PUT&quot;, fileUrl, localCallback, null, null, content, &quot;text/html;charset=utf-8&quot;);
> 		};
> 
> 		// override convertUnicodeToFileFormat()
> 		convertUnicodeToFileFormat = function (s)
> 		{
> 			return s;
> 		};
> 
> 	})(); //# end of wrapper
> } //# end of &quot;install only once&quot;
> //}}}
> /***
> |''Name''|TahoePlugin|
> |''Description''|&lt;...&gt;|
> |''Author''|Zooko|
> |''Contributors''|FND, EricShulman|
> |''Version''|0.2.0|
> |''Requires''|HTTPSavingPlugin| 
> |''Status''|@@experimental@@|
> |''Source''|http://allmydata.org/trac/tiddly_on_tahoe|
> |''CodeRepository''|http://allmydata.org/source/tiddly_on_tahoe/trunk/|
> |''License''|GPLv2+ or TGPPLv1.0+|
> |''Keywords''|&lt;...&gt;|
> !Description
> &lt;...&gt;
> !Notes
> This plugin is being developed for [[Tiddly on Tahoe|http://allmydata.org/trac/tiddly_on_tahoe]].
> ***/
> //{{{
> /* The following comment is to let jslint know which variables are supposed to be global. */
> /*global version, readOnly, showBackstage, config, loadRemoteFile, wikify */
> if (!version.extensions.TahoePlugin) { //# ensure that the plugin is only installed once
> 	version.extensions.TahoePlugin = { installed: true };
> 
> 	(function () { //# wrapper
> 		var BASE32CHAR, BASE32CHAR_3bits, BASE32CHAR_1bits, SEP, NUMBER, HTTPLEAD, BASE32STR_128bits, BASE32STR_256bits, ALPHANUMERIC_STRING, TAHOE_FUTURE_IMMUTABLE_CAP_RE_STR, TAHOE_FUTURE_READONLY_CAP_RE_STR, TAHOE_FUTURE_WRITABLE_CAP_RE_STR, TAHOE_IMMUTABLE_CAP_RE_STR, TAHOE_READONLY_FILE_CAP_RE_STR, TAHOE_READONLY_DIR_CAP_RE_STR, TAHOE_WRITABLE_FILE_CAP_RE_STR, TAHOE_WRITABLE_DIR_CAP_RE_STR, TAHOE_NONWRITABLE_THING_CAP_RE_STR, TAHOE_WRITABLE_THING_CAP_RE_STR, TAHOE_ANY_CAP_RE_STR, splitTahoeURL, scrapeOutReadonlyCap, diminishToReadonlyCap, getReadonlyURLToThisPage;
> 
> 		BASE32CHAR = '[abcdefghijklmnopqrstuvwxyz234567]';
> 		BASE32CHAR_3bits = '[aqiyemu4]';
> 		BASE32CHAR_1bits = '[aq]';
> 		SEP = '(?::|%3A)';
> 		NUMBER = '[0-9]+';
> 		HTTPLEAD = 'https?://(?:[^:/]+)(?::' + NUMBER + ')?/(uri|file|cap)/?';
> 
> 		BASE32STR_128bits = '(' + BASE32CHAR + '{25}' + BASE32CHAR_3bits + ')';
> 		BASE32STR_256bits = '(' + BASE32CHAR + '{51}' + BASE32CHAR_1bits + ')';
> 
> 		ALPHANUMERIC_STRING = '[A-Za-z0-9]+';
> 
> 		// This is speculative: maybe in the future there will be a version of Tahoe where caps 
> 		// start with these symbols, and if so then this JavaScript code will magically work with 
> 		// that version of Tahoe.
> 		TAHOE_FUTURE_IMMUTABLE_CAP_RE_STR = &quot;i_&quot; + ALPHANUMERIC_STRING;
> 		TAHOE_FUTURE_READONLY_CAP_RE_STR = &quot;r_&quot; + ALPHANUMERIC_STRING;
> 		TAHOE_FUTURE_WRITABLE_CAP_RE_STR = &quot;W_&quot; + ALPHANUMERIC_STRING;
> 
> 		TAHOE_IMMUTABLE_CAP_RE_STR = &quot;(?:URI&quot; + SEP + &quot;CHK&quot; + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits + SEP + NUMBER + SEP + NUMBER + SEP + NUMBER + '|' + TAHOE_FUTURE_IMMUTABLE_CAP_RE_STR + ')';
> 		TAHOE_READONLY_FILE_CAP_RE_STR = &quot;URI&quot; + SEP + &quot;SSK-RO&quot; + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 		TAHOE_READONLY_DIR_CAP_RE_STR = &quot;URI&quot; + SEP + &quot;DIR2-RO&quot; + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 		TAHOE_WRITABLE_FILE_CAP_RE_STR = &quot;URI&quot; + SEP + &quot;SSK&quot; + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 		TAHOE_WRITABLE_DIR_CAP_RE_STR = &quot;URI&quot; + SEP + &quot;DIR2&quot; + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 
> 		TAHOE_NONWRITABLE_THING_CAP_RE_STR = '(' + TAHOE_READONLY_FILE_CAP_RE_STR + '|' + TAHOE_READONLY_DIR_CAP_RE_STR + '|' + TAHOE_IMMUTABLE_CAP_RE_STR + '|' + TAHOE_FUTURE_IMMUTABLE_CAP_RE_STR + '|' + TAHOE_FUTURE_READONLY_CAP_RE_STR + ')';
> 		TAHOE_WRITABLE_THING_CAP_RE_STR = '(' + TAHOE_WRITABLE_DIR_CAP_RE_STR + '|' + TAHOE_WRITABLE_FILE_CAP_RE_STR + '|' + TAHOE_FUTURE_WRITABLE_CAP_RE_STR + ')';
> 
> 		TAHOE_ANY_CAP_RE_STR = '(' + TAHOE_NONWRITABLE_THING_CAP_RE_STR + '|' + TAHOE_WRITABLE_THING_CAP_RE_STR + ')';
> 
> 		readOnly = document.location.toString().match(new RegExp(HTTPLEAD + TAHOE_NONWRITABLE_THING_CAP_RE_STR));
> 		showBackstage = !readOnly;
> 		config.options.chkHttpReadOnly = false;
> 		
> 		/* Returns server (which is &quot;http://$HOST:$PORT/uri&quot;), cap, and suffix, which can be a 
> 		   path from the cap through the tahoe filesystem and/or trailing extra arguments. */
> 		splitTahoeURL = function (someURL) {
> 			var u, urlSuffix, candidate_cap, urlPrefix;
> 
> 			u = someURL.split('/');
> 			urlSuffix = [];
> 			candidate_cap = u.pop();
> 			urlPrefix = u.join('/');
> 			while ((u.length &gt; 0) &amp;&amp; (!urlPrefix.match(new RegExp(&quot;^&quot; + HTTPLEAD + &quot;$&quot;)))) {
> 				urlSuffix.unshift(candidate_cap);
> 				candidate_cap = u.pop();
> 				urlPrefix = u.join('/');
> 			}
> 			// Okay we've found the HTTPLEAD.  Is the following thing shaped like a Tahoe capability?
> 			if (candidate_cap.match(new RegExp(TAHOE_ANY_CAP_RE_STR))) {
> 				// Yes!
> 				return {'urlPrefix': urlPrefix, 'cap': candidate_cap, 'urlSuffix': urlSuffix};
> 			} else {
> 				// No!
> 				return;
> 			}
> 		};
> 
> 		scrapeOutReadonlyCap = function (metadata) {
> 			// example of tahoe-lafs json-encoded metadata:
> 			// [
> 			// &quot;dirnode&quot;, 
> 			// {
> 			//  &quot;rw_uri&quot;: &quot;URI:DIR2:ouojn4oj2fa7fphdf54hz5bfaq:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa&quot;, 
> 			//  &quot;ro_uri&quot;: &quot;URI:DIR2-RO:sznrgoyz7lbjorhe4ipzcnmluy:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa&quot;, 
> 			//  &quot;children&quot;: {
> 			//   &quot;tw_empty.html&quot;: [
> 			//    &quot;filenode&quot;, 
> 			//    {
> 			//     &quot;mutable&quot;: false, 
> 			//     &quot;metadata&quot;: {
> 			//      &quot;ctime&quot;: 1229263396.69, 
> 			//      &quot;mtime&quot;: 1229263396.69
> 			//     }, 
> 			//     &quot;ro_uri&quot;: &quot;URI:CHK:cofm2lm3ywu4r4efeqwjzuzyeq:dfw7oi65smf7dhtcx6wvr4ouazswprhwkvc3uopqtmvn3e7cactq:3:10:295520&quot;, 
> 			//     &quot;size&quot;: 295520
> 			//    }
> 			//   ]
> 			//  }, 
> 			//  &quot;mutable&quot;: true
> 			// }
> 			//]
> 
> 			// another example:
> 			// [
> 			//  &quot;filenode&quot;, 
> 			//  {
> 			//   &quot;rw_uri&quot;: &quot;URI:SSK:ouojn4oj2fa7fphdf54hz5bfaq:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa&quot;, 
> 			//   &quot;mutable&quot;: true, 
> 			//   &quot;ro_uri&quot;: &quot;URI:SSK-RO:sznrgoyz7lbjorhe4ipzcnmluy:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa&quot;, 
> 			//   &quot;size&quot;: &quot;?&quot;
> 			//  }
> 			// ]
> 			var matchobj = metadata.match(new RegExp(&quot;^\\s*\\[[^\\[]*\&quot;ro_uri\&quot;\\s*:\\s*\&quot;([^\&quot;]*)\&quot;&quot;));
> 			if (matchobj) {
> 				return matchobj[1];
> 			}
> 		};
> 
> 		diminishToReadonlyCap = function (urlPrefix, writableCap, callback) {
> 			var queryURL = [urlPrefix, writableCap, &quot;?t=json&quot;].join(&quot;/&quot;);
> 
> 			loadRemoteFile(queryURL, function (success, param, txt, src, xhr) {
> 				if (success) {
> 					callback(scrapeOutReadonlyCap(txt));
> 				}
> 			}); 
> 		};
>     
> 		getReadonlyURLToThisPage = function (callback) {
> 			if (document.location.tahoeDiminishedCapabilityURL) {
> 				return callback(document.location.tahoeDiminishedCapabilityURL);
> 			} else {
> 				var pieces = splitTahoeURL(document.location.toString());
> 				diminishToReadonlyCap(pieces.urlPrefix, pieces.cap, function (diminishedCap) {
> 					var diminishedURL = pieces.urlPrefix + &quot;/&quot; + diminishedCap + &quot;/&quot; + pieces.urlSuffix;
> 					document.location.tahoeDiminishedCapabilityURL = diminishedURL;
> 					callback(diminishedURL);
> 				});
> 			}
> 		};
> 
> 		config.macros.accessControlExplanation = {
> 	
> 			handler: function (place, macroName, params, wikifier, paramString, tiddler) {
> 				if (document.location.toString().match(new RegExp(HTTPLEAD + TAHOE_IMMUTABLE_CAP_RE_STR))) {
> 					wikify(&quot;This is an immutable view of this page.  Using this link will always give this exact same page, even if a newer version has been uploaded.&quot;, place);
> 				} else if (document.location.toString().match(new RegExp(HTTPLEAD + TAHOE_NONWRITABLE_THING_CAP_RE_STR))) {
> 					wikify(&quot;This is a read-only view of this page.  Using this link will give the most recent version of this page, but doesn't allow the user to change the page.&quot;, place);
> 				} else if (document.location.toString().match(new RegExp(HTTPLEAD + TAHOE_WRITABLE_THING_CAP_RE_STR))) {
> 					getReadonlyURLToThisPage(function (readonlyCap) {
> 						wikify(&quot;You are accessing this page with a writable link.  If you share this link with someone else, they will gain the ability to write to this page.  Click here for a [[read-only link to this page|&quot; + readonlyCap + &quot;]].&quot;, place);
> 					});
> 				} else {
> 					wikify(&quot;You are accessing this page not through the Tahoe-LAFS secure, distributed filesystem.&quot;, place);
> 				}
> 			}
> 		};
> 	})(); //# end of wrapper
> } //# end of &quot;install only once&quot;
> //}}}
> </pre>
> </div>
> <div title="WritableTheme" modifier="Zooko" created="200812152209" modified="200812152255" tags="systemTheme" changecount="12">
> <pre>|StyleSheet|##AuthorStyles|
> |StyleSheetReadOnly|##ReaderStyles|
> 
> !AuthorStyles
> /*{{{*/
> [[StyleSheet]]
> body {
> 	background: #eee;
> }
> /*}}}*/
> 
> !ReaderStyles
> /*{{{*/
> [[StyleSheet]]
> body {
> }
> /*}}}*/</pre>
> </div>