508a509,994 >
>
//{{{
> config.options.txtTheme = "WritableTheme";
> //}}}
>
>
>
/***
> |''Name''|HTTPSavingPlugin|
> |''Description''|<...>|
> |''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''|<...>|
> !Description
> <...>
> !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("saveTest");
> 			/*if (s.hasChildNodes()) {
> 			  alert(config.messages.savedSnapshotError);
> 			  }*/
> 			s.appendChild(document.createTextNode("savetest"));
> 		};
> 
> 		// Save this TiddlyWiki with the pending changes
> 		saveChanges = function (onlyIfDirty, tiddlers) {
> 			var originalPath, localCallback, result;
> 			if (onlyIfDirty && !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("loaded remote file from ", originalPath);
> 				/*log("got callback status ", status, "\n", context: ", context, "\n",
> 				  URL: ", url, "\n", XHR: ", 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("result from loadRemoteFile: ", 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("?");
> 			if (argPos !== -1) {
> 				originalPath = originalPath.substr(0, argPos);
> 			}
> 			hashPos = originalPath.indexOf("#");
> 			if (hashPos !== -1) {
> 				originalPath = originalPath.substr(0, hashPos);
> 			}
> 			// Convert file://localhost/ to file:///
> 			if (originalPath.indexOf("file://localhost/") === 0) {
> 				originalPath = "file://" + originalPath.substr(16);
> 			}
> 			// Convert to a native file format
> 			if (originalPath.indexOf("http://") === 0) { // HTTP file
> 				resultPath = originalPath;
> 			} else if (originalPath.charAt(9) === ":") { // PC local file
> 				resultPath = unescape(originalPath.substr(8)).replace(new RegExp("/", "g"), "\\");
> 			} else if (originalPath.indexOf("file://///") === 0) { // Firefox PC network file
> 				resultPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/", "g"), "\\");
> 			} else if (originalPath.indexOf("file:///") === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(7));
> 			} else if (originalPath.indexOf("file:/") === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(5));
> 			} else { // PC local file
> 				resultPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/", "g"), "\\");
> 			}
> 			return resultPath;
> 		};
> 
> 		// override saveFile()
> 		saveFile = function (fileUrl, content, callb) {
> 			displayMessage("saving... please wait"); // XXX: belongs into command handler -- TODO: i18n
> 			//alert("whee! about to save to " + fileUrl);
> 			var localCallback = function (status, params, responseText, url, xhr) {
> 				if (!status) {
> 					displayMessage("saving failed: " + responseText);
> 				}
> 			};
> 			return httpReq("PUT", fileUrl, localCallback, null, null, content, "text/html;charset=utf-8");
> 		};
> 
> 		// override convertUnicodeToFileFormat()
> 		convertUnicodeToFileFormat = function (s)
> 		{
> 			return s;
> 		};
> 
> 	})(); //# end of wrapper
> } //# end of "install only once"
> //}}}
> 
>
>
>
<!--{{{-->
> <div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
> <div class='headerShadow'>
> <div id='accessControlExplanationDivId' macro='accessControlExplanation'></div>
> <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
> <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
> </div>
> <div class='headerForeground'>
> <div id='accessControlExplanationDivId' macro='accessControlExplanation'></div>
> <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
> <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
> </div>
> </div>
> <div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
> <div id='sidebar'>
> <div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
> <div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
> </div>
> <div id='displayArea'>
> <div id='messageArea'></div>
> <div id='tiddlerDisplay'></div>
> </div>
> <!--}}}-->
>
>
>
/***
> |''Name''|HTTPSavingPlugin|
> |''Description''|<...>|
> |''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''|<...>|
> !Description
> <...>
> !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("saveTest");
> 			/*if (s.hasChildNodes()) {
> 			  alert(config.messages.savedSnapshotError);
> 			  }*/
> 			s.appendChild(document.createTextNode("savetest"));
> 		};
> 
> 		// Save this TiddlyWiki with the pending changes
> 		saveChanges = function (onlyIfDirty, tiddlers) {
> 			var originalPath, localCallback, result;
> 			if (onlyIfDirty && !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("loaded remote file from ", originalPath);
> 				/*log("got callback status ", status, "\n", context: ", context, "\n",
> 				  URL: ", url, "\n", XHR: ", 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("result from loadRemoteFile: ", 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("?");
> 			if (argPos !== -1) {
> 				originalPath = originalPath.substr(0, argPos);
> 			}
> 			hashPos = originalPath.indexOf("#");
> 			if (hashPos !== -1) {
> 				originalPath = originalPath.substr(0, hashPos);
> 			}
> 			// Convert file://localhost/ to file:///
> 			if (originalPath.indexOf("file://localhost/") === 0) {
> 				originalPath = "file://" + originalPath.substr(16);
> 			}
> 			// Convert to a native file format
> 			if (originalPath.indexOf("http://") === 0) { // HTTP file
> 				resultPath = originalPath;
> 			} else if (originalPath.charAt(9) === ":") { // PC local file
> 				resultPath = unescape(originalPath.substr(8)).replace(new RegExp("/", "g"), "\\");
> 			} else if (originalPath.indexOf("file://///") === 0) { // Firefox PC network file
> 				resultPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/", "g"), "\\");
> 			} else if (originalPath.indexOf("file:///") === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(7));
> 			} else if (originalPath.indexOf("file:/") === 0) { // *nix local file
> 				resultPath = unescape(originalPath.substr(5));
> 			} else { // PC local file
> 				resultPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/", "g"), "\\");
> 			}
> 			return resultPath;
> 		};
> 
> 		// override saveFile()
> 		saveFile = function (fileUrl, content, callb) {
> 			displayMessage("saving... please wait"); // XXX: belongs into command handler -- TODO: i18n
> 			//alert("whee! about to save to " + fileUrl);
> 			var localCallback = function (status, params, responseText, url, xhr) {
> 				if (!status) {
> 					displayMessage("saving failed: " + responseText);
> 				}
> 			};
> 			return httpReq("PUT", fileUrl, localCallback, null, null, content, "text/html;charset=utf-8");
> 		};
> 
> 		// override convertUnicodeToFileFormat()
> 		convertUnicodeToFileFormat = function (s)
> 		{
> 			return s;
> 		};
> 
> 	})(); //# end of wrapper
> } //# end of "install only once"
> //}}}
> /***
> |''Name''|TahoePlugin|
> |''Description''|<...>|
> |''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''|<...>|
> !Description
> <...>
> !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 = "i_" + ALPHANUMERIC_STRING;
> 		TAHOE_FUTURE_READONLY_CAP_RE_STR = "r_" + ALPHANUMERIC_STRING;
> 		TAHOE_FUTURE_WRITABLE_CAP_RE_STR = "W_" + ALPHANUMERIC_STRING;
> 
> 		TAHOE_IMMUTABLE_CAP_RE_STR = "(?:URI" + SEP + "CHK" + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits + SEP + NUMBER + SEP + NUMBER + SEP + NUMBER + '|' + TAHOE_FUTURE_IMMUTABLE_CAP_RE_STR + ')';
> 		TAHOE_READONLY_FILE_CAP_RE_STR = "URI" + SEP + "SSK-RO" + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 		TAHOE_READONLY_DIR_CAP_RE_STR = "URI" + SEP + "DIR2-RO" + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 		TAHOE_WRITABLE_FILE_CAP_RE_STR = "URI" + SEP + "SSK" + SEP + BASE32STR_128bits + SEP + BASE32STR_256bits;
> 		TAHOE_WRITABLE_DIR_CAP_RE_STR = "URI" + SEP + "DIR2" + 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 "http://$HOST:$PORT/uri"), 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 > 0) && (!urlPrefix.match(new RegExp("^" + HTTPLEAD + "$")))) {
> 				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:
> 			// [
> 			// "dirnode", 
> 			// {
> 			//  "rw_uri": "URI:DIR2:ouojn4oj2fa7fphdf54hz5bfaq:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa", 
> 			//  "ro_uri": "URI:DIR2-RO:sznrgoyz7lbjorhe4ipzcnmluy:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa", 
> 			//  "children": {
> 			//   "tw_empty.html": [
> 			//    "filenode", 
> 			//    {
> 			//     "mutable": false, 
> 			//     "metadata": {
> 			//      "ctime": 1229263396.69, 
> 			//      "mtime": 1229263396.69
> 			//     }, 
> 			//     "ro_uri": "URI:CHK:cofm2lm3ywu4r4efeqwjzuzyeq:dfw7oi65smf7dhtcx6wvr4ouazswprhwkvc3uopqtmvn3e7cactq:3:10:295520", 
> 			//     "size": 295520
> 			//    }
> 			//   ]
> 			//  }, 
> 			//  "mutable": true
> 			// }
> 			//]
> 
> 			// another example:
> 			// [
> 			//  "filenode", 
> 			//  {
> 			//   "rw_uri": "URI:SSK:ouojn4oj2fa7fphdf54hz5bfaq:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa", 
> 			//   "mutable": true, 
> 			//   "ro_uri": "URI:SSK-RO:sznrgoyz7lbjorhe4ipzcnmluy:rf56nzb6klj3ctvssqghy2ugalp6wundystbysxujodttrhxbqwa", 
> 			//   "size": "?"
> 			//  }
> 			// ]
> 			var matchobj = metadata.match(new RegExp("^\\s*\\[[^\\[]*\"ro_uri\"\\s*:\\s*\"([^\"]*)\""));
> 			if (matchobj) {
> 				return matchobj[1];
> 			}
> 		};
> 
> 		diminishToReadonlyCap = function (urlPrefix, writableCap, callback) {
> 			var queryURL = [urlPrefix, writableCap, "?t=json"].join("/");
> 
> 			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 + "/" + diminishedCap + "/" + 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("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.", place);
> 				} else if (document.location.toString().match(new RegExp(HTTPLEAD + TAHOE_NONWRITABLE_THING_CAP_RE_STR))) {
> 					wikify("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.", place);
> 				} else if (document.location.toString().match(new RegExp(HTTPLEAD + TAHOE_WRITABLE_THING_CAP_RE_STR))) {
> 					getReadonlyURLToThisPage(function (readonlyCap) {
> 						wikify("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|" + readonlyCap + "]].", place);
> 					});
> 				} else {
> 					wikify("You are accessing this page not through the Tahoe-LAFS secure, distributed filesystem.", place);
> 				}
> 			}
> 		};
> 	})(); //# end of wrapper
> } //# end of "install only once"
> //}}}
> 
>
>
>
|StyleSheet|##AuthorStyles|
> |StyleSheetReadOnly|##ReaderStyles|
> 
> !AuthorStyles
> /*{{{*/
> [[StyleSheet]]
> body {
> 	background: #eee;
> }
> /*}}}*/
> 
> !ReaderStyles
> /*{{{*/
> [[StyleSheet]]
> body {
> }
> /*}}}*/
>