From 97bb1fa8c9ce3a1417c02c880c18ad2793c8d161 Mon Sep 17 00:00:00 2001 From: Jermolene Date: Sat, 13 Oct 2018 14:50:21 +0100 Subject: [PATCH] Rename external tasks to external pipes And add support for connecting via sockets to existing processers/tasks --- core/modules/commands/exec.js | 121 ------ core/modules/commands/pipe.js | 194 +++++++++ .../dev/tiddlers/new/External Shell Tasks.tid | 131 ------ .../dev/tiddlers/new/pipes/External Pipes.tid | 121 ++++++ .../external-references/tiddlywiki.files | 32 ++ .../demo-tasks/mimic.js | 0 .../externalpipesdemo/demo-tasks/readme.md | 3 + .../externalpipesdemo/demo-tasks/reverser.js | 49 +++ .../demo-tasks/stats.js | 0 .../tiddlers/system/DefaultTiddlers.tid | 0 .../tiddlywiki.info | 71 +++- .../externaltasksdemo/demo-tasks/readme.md | 4 - .../Alice in Wonderland License.tid | 360 +++++++++++++++++ .../demonstrations/Alice in Wonderland.tid | 373 +----------------- 14 files changed, 812 insertions(+), 647 deletions(-) delete mode 100644 core/modules/commands/exec.js create mode 100644 core/modules/commands/pipe.js delete mode 100644 editions/dev/tiddlers/new/External Shell Tasks.tid create mode 100644 editions/dev/tiddlers/new/pipes/External Pipes.tid create mode 100644 editions/dev/tiddlers/new/pipes/external-references/tiddlywiki.files rename editions/{externaltasksdemo => externalpipesdemo}/demo-tasks/mimic.js (100%) create mode 100644 editions/externalpipesdemo/demo-tasks/readme.md create mode 100755 editions/externalpipesdemo/demo-tasks/reverser.js rename editions/{externaltasksdemo => externalpipesdemo}/demo-tasks/stats.js (100%) rename editions/{externaltasksdemo => externalpipesdemo}/tiddlers/system/DefaultTiddlers.tid (100%) rename editions/{externaltasksdemo => externalpipesdemo}/tiddlywiki.info (54%) delete mode 100644 editions/externaltasksdemo/demo-tasks/readme.md create mode 100644 editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland License.tid diff --git a/core/modules/commands/exec.js b/core/modules/commands/exec.js deleted file mode 100644 index f8fa87b4b..000000000 --- a/core/modules/commands/exec.js +++ /dev/null @@ -1,121 +0,0 @@ -/*\ -title: $:/core/modules/commands/exec.js -type: application/javascript -module-type: command - -Command to execute an external task - -\*/ -(function(){ - -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; - -exports.info = { - name: "exec", - synchronous: false -}; - -var Command = function(params,commander,callback) { - this.params = params; - this.commander = commander; - this.callback = callback; -}; - -Command.prototype.execute = function() { - var self = this; - if(this.params.length < 2) { - return "Missing parameters"; - } - var name = self.params[0], // External task name - filter = self.params[1], // Filter of tiddlers to pass to the task - args = self.params.slice(2); // Remaining arguments are passed to the task arguments - // Find the task information - var taskInfo = ($tw.boot.wikiInfo["external-tasks"] || {})[name]; - if(!taskInfo) { - return this.callback("External task \"" + name + "\" not found"); - } - // Execute it - var spawn = require("child_process").spawn, - path = require("path"), - childProcess = spawn(path.resolve($tw.boot.wikiPath,taskInfo.path),args,{ - stdio: ["pipe","pipe",process.stderr], - shell: true, - env: $tw.utils.extend({},process.env,taskInfo.environment) - }); - // Choose the input representation - var taskInfoInput = taskInfo.input || {}, - data; - switch(taskInfoInput.format || "json-raw-tiddlers") { - case "rendered-text": - var titles = self.commander.wiki.filterTiddlers(filter), - output = []; - $tw.utils.each(titles,function(title) { - output.push(self.commander.wiki.renderTiddler("text/plain",title)); - }); - data = output.join(""); - break; - case "json-rendered-text-tiddlers": - var titles = self.commander.wiki.filterTiddlers(filter), - tiddlers = []; - $tw.utils.each(titles,function(title) { - tiddlers.push({ - title: title, - text: self.commander.wiki.renderTiddler("text/plain",title) - }) - }); - data = JSON.stringify(tiddlers); - break; - case "json-raw-tiddlers": - // Intentional fall-through - default: - data = this.commander.wiki.getTiddlersAsJson(filter); - break; - } - if(data === undefined) { - return this.callback("No input data defined for tiddler processor"); - } - // Pass the tiddlers as JSON over stdin - childProcess.stdin.write(data); - childProcess.stdin.end(); - // Catch the output - var chunks = []; - childProcess.stdout.on("data",function(chunk) { - chunks.push(chunk.toString()); - }); - // Pick up the output when the process ends - childProcess.once("exit",function(code) { - if(code !== 0) { - return self.callback("Error executing external task: " + code); - } - var childOutput = chunks.join(""), - taskInfoOutput = taskInfo.output || {}, - data; - switch(taskInfoOutput.format || "text") { - case "json-raw-tiddlers": - try { - data = JSON.parse(childOutput); - } catch(e) { - self.callback("Error parsing returned JSON: " + e + "\n\n\n->\n" + childOutput); - } - // Add the tiddlers - self.commander.wiki.addTiddlers(data); - break; - case "text": - // Intentional fall-through - default: - self.commander.wiki.addTiddler(new $tw.Tiddler(taskInfoOutput.tiddler,{ - text: childOutput - })); - break; - } - // Exit successfully - self.callback(null); - }); - return null; -}; - -exports.Command = Command; - -})(); diff --git a/core/modules/commands/pipe.js b/core/modules/commands/pipe.js new file mode 100644 index 000000000..90f48250e --- /dev/null +++ b/core/modules/commands/pipe.js @@ -0,0 +1,194 @@ +/*\ +title: $:/core/modules/commands/pipe.js +type: application/javascript +module-type: command + +Command to execute an external task + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.info = { + name: "pipe", + synchronous: false +}; + +var Command = function(params,commander,callback) { + this.params = params; + this.commander = commander; + this.callback = callback; +}; + +Command.prototype.execute = function() { + var self = this; + if(this.params.length < 2) { + return "Missing parameters"; + } + var name = self.params[0], // External pipe name + filter = self.params[1], // Filter of tiddlers to write to the pipe + args = self.params.slice(2); // Remaining arguments are passed on as tasks arguments + // Find the pipe information + var pipeInfo = ($tw.boot.wikiInfo["external-pipes"] || {})[name]; + if(!pipeInfo) { + return this.callback("External pipe \"" + name + "\" not found"); + } + // Get the outgoing data + var data = this.composeOutgoingData(filter,pipeInfo); + // Connect to the pipe + var options = { + args: args, + data: data + }; + switch(pipeInfo.type) { + case "task": + return this.pipeExternalTask(pipeInfo,options); + case "socket": + return this.pipeSocket(pipeInfo,options); + default: + return "Invalid pipe specifier '" + name + "'" + } +}; + +Command.prototype.log = function(args) { + this.commander.log("Pipe: " + Array.prototype.slice.call(arguments,0).join(" ")); +}; + +Command.prototype.pipeExternalTask = function(pipeInfo,options) { + var self = this, + spawn = require("child_process").spawn, + path = require("path"), + childProcess = spawn(path.resolve($tw.boot.wikiPath,pipeInfo.path),options.args,{ + stdio: ["pipe","pipe",process.stderr], + shell: true, + env: $tw.utils.extend({},process.env,pipeInfo.environment) + }); + // Pass the tiddlers over the outgoing stream + childProcess.stdin.on("error",function(err) { + self.log("Task stdin error",err) + }); + childProcess.stdin.write(options.data); + childProcess.stdin.end(); + // Catch the output + var chunks = []; + childProcess.stdout.on("data",function(chunk) { + chunks.push(chunk.toString()); + }); + childProcess.stdout.on("close",function() { + self.log("Task stdout close"); + self.processIncomingData(chunks.join(""),pipeInfo); + }); + childProcess.stdout.on("error",function(err) { + self.log("Task stdout error",err) + }); + // Pick up the output when the process ends + childProcess.on("error",function(err) { + self.log("Task error",err) + }); + childProcess.on("exit",function(code,signal) { + self.log("Task exit",code,signal) + if(code !== 0) { + return self.callback("Error executing external task: " + code); + } + // Exit successfully + self.callback(null); + }); + return null; +}; + +Command.prototype.pipeSocket = function(pipeInfo,options) { + var self = this, + net = require("net"), + socket = new net.Socket({ + allowHalfOpen: true + }), + chunks = []; + socket.connect(pipeInfo.port,pipeInfo.host || 8081,function() { + self.log("Socket connection",pipeInfo.port,pipeInfo.host); + socket.write(options.data); + socket.end(); + }); + socket.on("error",function(e) { + self.log("Socket error",e) + }); + socket.on("data",function(data) { + chunks.push(data.toString()); + }); + socket.on("end",function() { + self.processIncomingData(chunks.join(""),pipeInfo); + self.log("Socket end"); + socket.destroy(); + }); + // Add a "close" event handler for the client socket + socket.on("close",function() { + self.log("Socket closed"); + return self.callback(null); + }); + return null; +}; + +Command.prototype.composeOutgoingData = function(filter,pipeInfo) { + var self = this, + pipeInfoInput = pipeInfo.input || {}, + data; + switch(pipeInfoInput.format || "json-raw-tiddlers") { + case "rendered-text": + var titles = self.commander.wiki.filterTiddlers(filter), + output = []; + $tw.utils.each(titles,function(title) { + output.push(self.commander.wiki.renderTiddler("text/plain",title)); + }); + data = output.join(""); + break; + case "json-rendered-text-tiddlers": + var titles = self.commander.wiki.filterTiddlers(filter), + tiddlers = []; + $tw.utils.each(titles,function(title) { + tiddlers.push({ + title: title, + text: self.commander.wiki.renderTiddler("text/plain",title) + }) + }); + data = JSON.stringify(tiddlers); + break; + case "json-raw-tiddlers": + // Intentional fall-through + default: + data = this.commander.wiki.getTiddlersAsJson(filter); + break; + } + return data; +}; + +Command.prototype.processIncomingData = function(data,pipeInfo) { + var self = this, + pipeInfoOutput = pipeInfo.output || {}, + jsonData; + switch(pipeInfoOutput.format || "text") { + case "json-raw-tiddlers": + try { + jsonData = JSON.parse(data); + } catch(e) { + self.log("Error parsing returned JSON: " + e + "\n\n\n->\n" + data); + } + // Add the tiddlers + if(jsonData) { + this.commander.wiki.addTiddlers(jsonData); + } + break; + case "text": + // Intentional fall-through + default: + this.commander.wiki.addTiddler(new $tw.Tiddler(pipeInfoOutput.tiddler,{ + text: data + })); + break; + } +}; + +exports.Command = Command; + +})(); diff --git a/editions/dev/tiddlers/new/External Shell Tasks.tid b/editions/dev/tiddlers/new/External Shell Tasks.tid deleted file mode 100644 index 90115a58c..000000000 --- a/editions/dev/tiddlers/new/External Shell Tasks.tid +++ /dev/null @@ -1,131 +0,0 @@ -created: 20181001171604072 -modified: 20181001184306738 -title: External Shell Tasks -type: text/vnd.tiddlywiki - -!! Introduction - -It can be difficult for experienced developers to become proficient in working with TiddlyWiki's code: besides requiring a good understanding of JavaScript, the internals are built around relatively unusual concepts and techniques that are likely to be unfamiliar to most. - -However, many software developers are very familiar with using and creating text-based command line tools that adhere to the Unix philosophy of using stdin/stdout for input and output, allowing tools to be chained together in powerful ways. - -The external task mechanism allows Unix-style tasks to be registered and executed by TiddlyWiki under Node.js. Execution can be triggered via a server command or via a message propagated from the browser. - -!! Configuration - -External tasks must be registered in the `tiddlywiki.info` file of a wiki folder. For example: - -``` -{ - "description": "Edition demonstrating external tasks", - "plugins": [ - ], - "themes": [ - "tiddlywiki/vanilla", - "tiddlywiki/snowwhite" - ], - "includeWikis": [ - "../tw5.com" - ], - "external-tasks": { - "stats": { - "path": "./demo-tasks/stats.js", - "input": { - "format": "json-raw-tiddlers" - }, - "environment": { - "MY_VARIABLE": "value" - }, - "output": { - "format": "json-raw-tiddlers" - }, - "timeout": 100 - }, - "mimic": { - "path": "./demo-tasks/mimic.js", - "arguments": ["ngram-length"], - "input": { - "format": "rendered-text" - }, - "environment": { - "MY_VARIABLE": "value" - }, - "output": { - "format": "text", - "tiddler": { - "title": "HelloThere", - "type": "text/plain" - } - }, - "timeout": 100 - } - } -} -``` - -!!! Task Configuration Properties - -TBD - -!!! Input Formats - -The available input formats are: - -* `raw-text` - concatenated raw text of the tiddlers -* `rendered-text` - concatenated rendered text of the tiddlers -* `rendered-html` - concatenated rendered html of the tiddlers -* `json-raw-tiddlers` - raw tiddlers in JSON -* `json-rendered-text-tiddlers` - rendered tiddlers in JSON - -!!! Output Formats - -The available output formats include: - -* `raw-text` - raw text -* `json-raw-tiddlers` - raw tiddlers in JSON - -!! Usage - -External tasks can be invoked via the `--exec` command, or via a widget message propagated from the browser to the server. - -!!! `--exec` Command - -The `--exec` command triggers the execution of an external task. The parameters are: - -``` -tiddlywiki --exec ... -``` - -The ''taskname'' identifies the task to be run, and must match the name defined in the `tiddlywiki.info` file. - -The ''filter'' identifies the tiddlers to be passed to the external task - -The remaining ''arguments'' are passed through to the external task. - -!!! `tm-exec-task` Message - -TBD - -!! Examples - -The edition `editions/externaltasksdemo` in the TiddlyWiki5 repo contains a demo wiki that invokes sample tasks. - -!!! Mimic - -The `mimic.js` example is a simple command line tool that accepts source text via stdin and outputs a sort of statistical parody of the input text. It is written without any knowledge of TiddlyWiki, and so serves as an example of using an existing text-based tool with TiddlyWiki. - -``` -tiddlywiki editions/externaltasksdemo/ --exec mimic '[[Alice in Wonderland]]' 5 4000 --build index -``` - -View the resulting wiki at `editions/externaltaskdemo/output/index.html`: the tiddler "HelloThere" will contain a garbled version of the "Alice in Wonderland" text. - -!!! Stats - -The `stats.js` example is a simple command line tool that accepts source text via stdin and outputs a sort of statistical parody of the input text. It is written without any knowledge of TiddlyWiki, and so serves as an example of using an existing text-based tool with TiddlyWiki. - -``` -tiddlywiki editions/externaltasksdemo/ --exec stats '[[Alice in Wonderland]]' --build index -``` - -View the resulting wiki at `editions/externaltaskdemo/output/index.html`: the tiddler "HelloThere" will contain statistics about the "Alice in Wonderland" text. diff --git a/editions/dev/tiddlers/new/pipes/External Pipes.tid b/editions/dev/tiddlers/new/pipes/External Pipes.tid new file mode 100644 index 000000000..a869400af --- /dev/null +++ b/editions/dev/tiddlers/new/pipes/External Pipes.tid @@ -0,0 +1,121 @@ +created: 20181001171604072 +modified: 20181001184306738 +title: External Pipes +type: text/vnd.tiddlywiki + +!! Introduction + +The external pipes mechanism is intended to address the fact that it can be difficult for experienced developers to quickly get started working with TiddlyWiki's code because it requires a good understanding of JavaScript, and some relatively unusual concepts and techniques that are likely to be unfamiliar to most. + +Many software developers are comfortable using and building text-based command line tools that follow the Unix philosophy of using stdin/stdout or TCP sockets for input and output, allowing tools to be chained together in powerful ways. + +External pipes support data transfer with external programs via two techniques: + +* By directly executing the program and communicating with it via stdin and stdout ([[mimic.js|External Pipes mimic.js]] and [[stats.js|External Pipes stats.js]]) +* By connecting to an existing TCP socket via a host address and port ([[reverser.js|External Pipes reverser.js]]) + +Pipes are registered and executed under Node.js. Execution can be triggered via a server command or via a message propagated from the browser. + +Pipes currently support a simple question/response model: + +* TiddlyWiki opens a connection to the host/port, or starts the external task +* TiddlyWiki sends the outgoing data through the pipe +* TiddlyWiki receives the incoming data through the pipe +* The connection is close, or the external task exits + +!! `externalpipesdemo` Edition + +The edition at `editions/externalpipesdemo` in the TiddlyWiki 5 repo contains the example tasks referenced in this documentation. + +!! Configuration + +Pipes must be registered in the `tiddlywiki.info` file of a wiki folder. For example: + +{{External Pipes tiddlywiki.info}} + +!!! Task Configuration Properties + +TBD + +!!! Input Formats + +The available input formats are: + +* `raw-text` - concatenated raw text of the tiddlers +* `rendered-text` - concatenated rendered text of the tiddlers +* `rendered-html` - concatenated rendered html of the tiddlers +* `json-raw-tiddlers` - raw tiddlers in JSON +* `json-rendered-text-tiddlers` - rendered tiddlers in JSON + +!!! Output Formats + +The available output formats include: + +* `raw-text` - raw text +* `json-raw-tiddlers` - raw tiddlers in JSON + +!! Usage + +Pipes can be invoked via the `--pipe` command, or via a widget message propagated from the browser to the server. + +!!! `--pipe` Command + +The `--pipe` command triggers the invocation of a pipe task. The parameters are: + +``` +tiddlywiki --pipe ... +``` + +The ''pipename'' identifies the pipe, and must match the name defined in the `tiddlywiki.info` file. + +The ''filter'' identifies the tiddlers to be passed to the pipe + +The remaining ''arguments'' are passed through to external task pipes, and ignored for other types of pipe. + +!!! `tm-exec-task` Message + +TBD + +!! Examples + +The edition `editions/externalpipesdemo` in the TiddlyWiki5 repo contains a demo wiki that invokes sample tasks. + +!!! Mimic + +The `mimic.js` example is a simple command line tool that accepts source text via stdin and outputs a sort of statistical parody of the input text. It is written without any knowledge of TiddlyWiki, and so serves as an example of using an existing text-based tool with TiddlyWiki. + +``` +tiddlywiki editions/externalpipesdemo/ --verbose --pipe mimic '[[Alice in Wonderland]]' 5 4000 --build index +``` + +View the resulting wiki at `editions/externaltaskdemo/output/index.html`: the tiddler "HelloThere" will contain a garbled version of the "Alice in Wonderland" text. + +!!! Stats + +The `stats.js` example is a simple command line tool that accepts source text via stdin and outputs a sort of statistical parody of the input text. It is written without any knowledge of TiddlyWiki, and so serves as an example of using an existing text-based tool with TiddlyWiki. + +``` +tiddlywiki editions/externalpipesdemo/ --verbose --pipe stats '[[Alice in Wonderland]]' --build index +``` + +View the resulting wiki at `editions/externaltaskdemo/output/index.html`: the tiddler "HelloThere" will contain statistics about the "Alice in Wonderland" text. + +!!! Reverser + +The `reverser.js` example is an simple command line tool that listens for connections on a host address and port, accepts source text and then returns the same text with the characters reversed. + +Two separate commands are needed to run the sample: one to get the server running, and the second to run TiddlyWiki and invoke the server. + +To run the server, open a command prompt in the `demo-tasks` directory and run: + +``` +../reverser.js 8081 +``` + +And then in another command prompt in the root of the repo run: + +``` +tiddlywiki editions/externalpipesdemo/ --verbose --pipe reverser '[[Alice in Wonderland]]' --build index +``` + +View the resulting wiki at `editions/externaltaskdemo/output/index.html`: the tiddler "HelloThere" will contain the reversed text of "Alice in Wonderland". diff --git a/editions/dev/tiddlers/new/pipes/external-references/tiddlywiki.files b/editions/dev/tiddlers/new/pipes/external-references/tiddlywiki.files new file mode 100644 index 000000000..c3f136509 --- /dev/null +++ b/editions/dev/tiddlers/new/pipes/external-references/tiddlywiki.files @@ -0,0 +1,32 @@ +{ + "tiddlers": [ + { + "file": "../../../../../externalpipesdemo/tiddlywiki.info", + "fields": { + "type": "text/plain", + "title": "External Pipes tiddlywiki.info" + } + }, + { + "file": "../../../../../externalpipesdemo/demo-tasks/mimic.js", + "fields": { + "type": "application/javascript", + "title": "External Pipes mimic.js" + } + }, + { + "file": "../../../../../externalpipesdemo/demo-tasks/reverser.js", + "fields": { + "type": "application/javascript", + "title": "External Pipes reverser.js" + } + }, + { + "file": "../../../../../externalpipesdemo/demo-tasks/stats.js", + "fields": { + "type": "application/javascript", + "title": "External Pipes stats.js" + } + } + ] +} diff --git a/editions/externaltasksdemo/demo-tasks/mimic.js b/editions/externalpipesdemo/demo-tasks/mimic.js similarity index 100% rename from editions/externaltasksdemo/demo-tasks/mimic.js rename to editions/externalpipesdemo/demo-tasks/mimic.js diff --git a/editions/externalpipesdemo/demo-tasks/readme.md b/editions/externalpipesdemo/demo-tasks/readme.md new file mode 100644 index 000000000..fcb092dea --- /dev/null +++ b/editions/externalpipesdemo/demo-tasks/readme.md @@ -0,0 +1,3 @@ +# Sample Processes for TiddlyWiki External Pipes + +"External Pipes" are connections enabling a wiki to communicate with an external process to perform arbitrary processing on a group of tiddlers. diff --git a/editions/externalpipesdemo/demo-tasks/reverser.js b/editions/externalpipesdemo/demo-tasks/reverser.js new file mode 100755 index 000000000..ebd660c23 --- /dev/null +++ b/editions/externalpipesdemo/demo-tasks/reverser.js @@ -0,0 +1,49 @@ +#!/usr/bin/env node + +/* +A socket server that listens on a host/port for connections and reverses the order of incoming text + + reverser.js + +This utility is provided as an example of using an external task that doesn't have any prior knowledge of +TiddlyWiki. Like many Unix utilities, it just reads and writes to a socket. + +*/ + +var net = require("net"), + port = parseInt(process.argv[2] || "",10) || 8081, // Port + host = process.argv[3] || "127.0.0.1"; // Host + +var server = net.createServer({ + allowHalfOpen: true +}); + +server.listen(port,host); + +server.on("connection", function(sock) { + console.log("CONNECTED: " + sock.remoteAddress +":"+ sock.remotePort); + // Trap errors + sock.on("error",function(e) { + console.log("ERROR: " + e); + }); + // Read data until the end + var chunks = []; + sock.on("data",function(data) { + console.log("DATA " + sock.remoteAddress + ": " + data); + chunks.push(data.toString()); + }); + sock.on("end",function() { + console.log("END") + // Write the data back to the socket + sock.write(reverse(chunks.join(""))); + sock.end(); + }); + sock.on("close", function(data) { + console.log("CLOSED: " + sock.remoteAddress +" "+ sock.remotePort); + }); +}); + +function reverse(str) { + return str.split("").reverse().join(""); +} + diff --git a/editions/externaltasksdemo/demo-tasks/stats.js b/editions/externalpipesdemo/demo-tasks/stats.js similarity index 100% rename from editions/externaltasksdemo/demo-tasks/stats.js rename to editions/externalpipesdemo/demo-tasks/stats.js diff --git a/editions/externaltasksdemo/tiddlers/system/DefaultTiddlers.tid b/editions/externalpipesdemo/tiddlers/system/DefaultTiddlers.tid similarity index 100% rename from editions/externaltasksdemo/tiddlers/system/DefaultTiddlers.tid rename to editions/externalpipesdemo/tiddlers/system/DefaultTiddlers.tid diff --git a/editions/externaltasksdemo/tiddlywiki.info b/editions/externalpipesdemo/tiddlywiki.info similarity index 54% rename from editions/externaltasksdemo/tiddlywiki.info rename to editions/externalpipesdemo/tiddlywiki.info index 7e5215b28..062dc3deb 100644 --- a/editions/externaltasksdemo/tiddlywiki.info +++ b/editions/externalpipesdemo/tiddlywiki.info @@ -1,5 +1,5 @@ { - "description": "Edition demonstrating external tasks", + "description": "Edition demonstrating external pipes", "plugins": [ ], "themes": [ @@ -9,29 +9,14 @@ "includeWikis": [ "../tw5.com" ], - "external-tasks": { - "stats": { - "path": "./demo-tasks/stats.js", - "input": { - "format": "json-raw-tiddlers" - }, - "environment": { - "MY_VARIABLE": "value" - }, - "output": { - "format": "json-raw-tiddlers" - }, - "timeout": 100 - }, - "mimic": { - "path": "./demo-tasks/mimic.js", - "arguments": ["ngram-length"], + "external-pipes": { + "reverser": { + "type": "socket", + "host": "127.0.0.1", + "port": 8081, "input": { "format": "rendered-text" }, - "environment": { - "MY_VARIABLE": "value" - }, "output": { "format": "text", "tiddler": { @@ -39,6 +24,50 @@ "type": "text/plain" } }, + "environment": { + "MY_VARIABLE": "value" + }, + "timeout": 100 + }, + "stats": { + "type": "task", + "path": "./demo-tasks/stats.js", + "input": { + "format": "json-raw-tiddlers" + }, + "output": { + "format": "json-raw-tiddlers" + }, + "error": { + "format": "text", + "tiddler": { + "title": "HelloThere", + "type": "text/plain", + "result": "error" + } + }, + "environment": { + "MY_VARIABLE": "value" + }, + "timeout": 100 + }, + "mimic": { + "type": "task", + "path": "./demo-tasks/mimic.js", + "arguments": ["ngram-length"], + "input": { + "format": "rendered-text" + }, + "output": { + "format": "text", + "tiddler": { + "title": "HelloThere", + "type": "text/plain" + } + }, + "environment": { + "MY_VARIABLE": "value" + }, "timeout": 100 } } diff --git a/editions/externaltasksdemo/demo-tasks/readme.md b/editions/externaltasksdemo/demo-tasks/readme.md deleted file mode 100644 index f236e6bc2..000000000 --- a/editions/externaltasksdemo/demo-tasks/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -# Sample External Tasks for TiddlyWiki - -"External Tasks" are external shell commands that can be triggered from within TiddlyWiki to perform arbitrary processing on a group of tiddlers. - diff --git a/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland License.tid b/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland License.tid new file mode 100644 index 000000000..1f396e48c --- /dev/null +++ b/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland License.tid @@ -0,0 +1,360 @@ +title: Alice in Wonderland License +tags: text/plain + +End of Project Gutenberg's Alice's Adventures in Wonderland, by Lewis Carroll + +*** END OF THIS PROJECT GUTENBERG EBOOK ALICE'S ADVENTURES IN WONDERLAND *** + +***** This file should be named 11.txt or 11.zip ***** +This and all associated files of various formats will be found in: + http://www.gutenberg.org/1/11/ + +Updated editions will replace the previous one--the old editions +will be renamed. + +Creating the works from public domain print editions means that no +one owns a United States copyright in these works, so the Foundation +(and you!) can copy and distribute it in the United States without +permission and without paying copyright royalties. Special rules, +set forth in the General Terms of Use part of this license, apply to +copying and distributing Project Gutenberg-tm electronic works to +protect the PROJECT GUTENBERG-tm concept and trademark. Project +Gutenberg is a registered trademark, and may not be used if you +charge for the eBooks, unless you receive specific permission. If you +do not charge anything for copies of this eBook, complying with the +rules is very easy. You may use this eBook for nearly any purpose +such as creation of derivative works, reports, performances and +research. They may be modified and printed and given away--you may do +practically ANYTHING with public domain eBooks. Redistribution is +subject to the trademark license, especially commercial +redistribution. + +*** START: FULL LICENSE *** + +THE FULL PROJECT GUTENBERG LICENSE +PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK + +To protect the Project Gutenberg-tm mission of promoting the free +distribution of electronic works, by using or distributing this work +(or any other work associated in any way with the phrase "Project +Gutenberg"), you agree to comply with all the terms of the Full Project +Gutenberg-tm License (available with this file or online at +http://gutenberg.org/license). + + +Section 1. General Terms of Use and Redistributing Project Gutenberg-tm +electronic works + +1.A. By reading or using any part of this Project Gutenberg-tm +electronic work, you indicate that you have read, understand, agree to +and accept all the terms of this license and intellectual property +(trademark/copyright) agreement. If you do not agree to abide by all +the terms of this agreement, you must cease using and return or destroy +all copies of Project Gutenberg-tm electronic works in your possession. +If you paid a fee for obtaining a copy of or access to a Project +Gutenberg-tm electronic work and you do not agree to be bound by the +terms of this agreement, you may obtain a refund from the person or +entity to whom you paid the fee as set forth in paragraph 1.E.8. + +1.B. "Project Gutenberg" is a registered trademark. It may only be +used on or associated in any way with an electronic work by people who +agree to be bound by the terms of this agreement. There are a few +things that you can do with most Project Gutenberg-tm electronic works +even without complying with the full terms of this agreement. See +paragraph 1.C below. There are a lot of things you can do with Project +Gutenberg-tm electronic works if you follow the terms of this agreement +and help preserve free future access to Project Gutenberg-tm electronic +works. See paragraph 1.E below. + +1.C. The Project Gutenberg Literary Archive Foundation ("the Foundation" +or PGLAF), owns a compilation copyright in the collection of Project +Gutenberg-tm electronic works. Nearly all the individual works in the +collection are in the public domain in the United States. If an +individual work is in the public domain in the United States and you are +located in the United States, we do not claim a right to prevent you from +copying, distributing, performing, displaying or creating derivative +works based on the work as long as all references to Project Gutenberg +are removed. Of course, we hope that you will support the Project +Gutenberg-tm mission of promoting free access to electronic works by +freely sharing Project Gutenberg-tm works in compliance with the terms of +this agreement for keeping the Project Gutenberg-tm name associated with +the work. You can easily comply with the terms of this agreement by +keeping this work in the same format with its attached full Project +Gutenberg-tm License when you share it without charge with others. + +1.D. The copyright laws of the place where you are located also govern +what you can do with this work. Copyright laws in most countries are in +a constant state of change. If you are outside the United States, check +the laws of your country in addition to the terms of this agreement +before downloading, copying, displaying, performing, distributing or +creating derivative works based on this work or any other Project +Gutenberg-tm work. The Foundation makes no representations concerning +the copyright status of any work in any country outside the United +States. + +1.E. Unless you have removed all references to Project Gutenberg: + +1.E.1. The following sentence, with active links to, or other immediate +access to, the full Project Gutenberg-tm License must appear prominently +whenever any copy of a Project Gutenberg-tm work (any work on which the +phrase "Project Gutenberg" appears, or with which the phrase "Project +Gutenberg" is associated) is accessed, displayed, performed, viewed, +copied or distributed: + +This eBook is for the use of anyone anywhere at no cost and with +almost no restrictions whatsoever. You may copy it, give it away or +re-use it under the terms of the Project Gutenberg License included +with this eBook or online at www.gutenberg.org + +1.E.2. If an individual Project Gutenberg-tm electronic work is derived +from the public domain (does not contain a notice indicating that it is +posted with permission of the copyright holder), the work can be copied +and distributed to anyone in the United States without paying any fees +or charges. If you are redistributing or providing access to a work +with the phrase "Project Gutenberg" associated with or appearing on the +work, you must comply either with the requirements of paragraphs 1.E.1 +through 1.E.7 or obtain permission for the use of the work and the +Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or +1.E.9. + +1.E.3. If an individual Project Gutenberg-tm electronic work is posted +with the permission of the copyright holder, your use and distribution +must comply with both paragraphs 1.E.1 through 1.E.7 and any additional +terms imposed by the copyright holder. Additional terms will be linked +to the Project Gutenberg-tm License for all works posted with the +permission of the copyright holder found at the beginning of this work. + +1.E.4. Do not unlink or detach or remove the full Project Gutenberg-tm +License terms from this work, or any files containing a part of this +work or any other work associated with Project Gutenberg-tm. + +1.E.5. Do not copy, display, perform, distribute or redistribute this +electronic work, or any part of this electronic work, without +prominently displaying the sentence set forth in paragraph 1.E.1 with +active links or immediate access to the full terms of the Project +Gutenberg-tm License. + +1.E.6. You may convert to and distribute this work in any binary, +compressed, marked up, nonproprietary or proprietary form, including any +word processing or hypertext form. However, if you provide access to or +distribute copies of a Project Gutenberg-tm work in a format other than +"Plain Vanilla ASCII" or other format used in the official version +posted on the official Project Gutenberg-tm web site (www.gutenberg.org), +you must, at no additional cost, fee or expense to the user, provide a +copy, a means of exporting a copy, or a means of obtaining a copy upon +request, of the work in its original "Plain Vanilla ASCII" or other +form. Any alternate format must include the full Project Gutenberg-tm +License as specified in paragraph 1.E.1. + +1.E.7. Do not charge a fee for access to, viewing, displaying, +performing, copying or distributing any Project Gutenberg-tm works +unless you comply with paragraph 1.E.8 or 1.E.9. + +1.E.8. You may charge a reasonable fee for copies of or providing +access to or distributing Project Gutenberg-tm electronic works provided +that + +- You pay a royalty fee of 20% of the gross profits you derive from + the use of Project Gutenberg-tm works calculated using the method + you already use to calculate your applicable taxes. The fee is + owed to the owner of the Project Gutenberg-tm trademark, but he + has agreed to donate royalties under this paragraph to the + Project Gutenberg Literary Archive Foundation. Royalty payments + must be paid within 60 days following each date on which you + prepare (or are legally required to prepare) your periodic tax + returns. Royalty payments should be clearly marked as such and + sent to the Project Gutenberg Literary Archive Foundation at the + address specified in Section 4, "Information about donations to + the Project Gutenberg Literary Archive Foundation." + +- You provide a full refund of any money paid by a user who notifies + you in writing (or by e-mail) within 30 days of receipt that s/he + does not agree to the terms of the full Project Gutenberg-tm + License. You must require such a user to return or + destroy all copies of the works possessed in a physical medium + and discontinue all use of and all access to other copies of + Project Gutenberg-tm works. + +- You provide, in accordance with paragraph 1.F.3, a full refund of any + money paid for a work or a replacement copy, if a defect in the + electronic work is discovered and reported to you within 90 days + of receipt of the work. + +- You comply with all other terms of this agreement for free + distribution of Project Gutenberg-tm works. + +1.E.9. If you wish to charge a fee or distribute a Project Gutenberg-tm +electronic work or group of works on different terms than are set +forth in this agreement, you must obtain permission in writing from +both the Project Gutenberg Literary Archive Foundation and Michael +Hart, the owner of the Project Gutenberg-tm trademark. Contact the +Foundation as set forth in Section 3 below. + +1.F. + +1.F.1. Project Gutenberg volunteers and employees expend considerable +effort to identify, do copyright research on, transcribe and proofread +public domain works in creating the Project Gutenberg-tm +collection. Despite these efforts, Project Gutenberg-tm electronic +works, and the medium on which they may be stored, may contain +"Defects," such as, but not limited to, incomplete, inaccurate or +corrupt data, transcription errors, a copyright or other intellectual +property infringement, a defective or damaged disk or other medium, a +computer virus, or computer codes that damage or cannot be read by +your equipment. + +1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right +of Replacement or Refund" described in paragraph 1.F.3, the Project +Gutenberg Literary Archive Foundation, the owner of the Project +Gutenberg-tm trademark, and any other party distributing a Project +Gutenberg-tm electronic work under this agreement, disclaim all +liability to you for damages, costs and expenses, including legal +fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT +LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE +PROVIDED IN PARAGRAPH F3. YOU AGREE THAT THE FOUNDATION, THE +TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE +LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR +INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH +DAMAGE. + +1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a +defect in this electronic work within 90 days of receiving it, you can +receive a refund of the money (if any) you paid for it by sending a +written explanation to the person you received the work from. If you +received the work on a physical medium, you must return the medium with +your written explanation. The person or entity that provided you with +the defective work may elect to provide a replacement copy in lieu of a +refund. If you received the work electronically, the person or entity +providing it to you may choose to give you a second opportunity to +receive the work electronically in lieu of a refund. If the second copy +is also defective, you may demand a refund in writing without further +opportunities to fix the problem. + +1.F.4. Except for the limited right of replacement or refund set forth +in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER +WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE. + +1.F.5. Some states do not allow disclaimers of certain implied +warranties or the exclusion or limitation of certain types of damages. +If any disclaimer or limitation set forth in this agreement violates the +law of the state applicable to this agreement, the agreement shall be +interpreted to make the maximum disclaimer or limitation permitted by +the applicable state law. The invalidity or unenforceability of any +provision of this agreement shall not void the remaining provisions. + +1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the +trademark owner, any agent or employee of the Foundation, anyone +providing copies of Project Gutenberg-tm electronic works in accordance +with this agreement, and any volunteers associated with the production, +promotion and distribution of Project Gutenberg-tm electronic works, +harmless from all liability, costs and expenses, including legal fees, +that arise directly or indirectly from any of the following which you do +or cause to occur: (a) distribution of this or any Project Gutenberg-tm +work, (b) alteration, modification, or additions or deletions to any +Project Gutenberg-tm work, and (c) any Defect you cause. + + +Section 2. Information about the Mission of Project Gutenberg-tm + +Project Gutenberg-tm is synonymous with the free distribution of +electronic works in formats readable by the widest variety of computers +including obsolete, old, middle-aged and new computers. It exists +because of the efforts of hundreds of volunteers and donations from +people in all walks of life. + +Volunteers and financial support to provide volunteers with the +assistance they need, is critical to reaching Project Gutenberg-tm's +goals and ensuring that the Project Gutenberg-tm collection will +remain freely available for generations to come. In 2001, the Project +Gutenberg Literary Archive Foundation was created to provide a secure +and permanent future for Project Gutenberg-tm and future generations. +To learn more about the Project Gutenberg Literary Archive Foundation +and how your efforts and donations can help, see Sections 3 and 4 +and the Foundation web page at http://www.pglaf.org. + + +Section 3. Information about the Project Gutenberg Literary Archive +Foundation + +The Project Gutenberg Literary Archive Foundation is a non profit +501(c)(3) educational corporation organized under the laws of the +state of Mississippi and granted tax exempt status by the Internal +Revenue Service. The Foundation's EIN or federal tax identification +number is 64-6221541. Its 501(c)(3) letter is posted at +http://pglaf.org/fundraising. Contributions to the Project Gutenberg +Literary Archive Foundation are tax deductible to the full extent +permitted by U.S. federal laws and your state's laws. + +The Foundation's principal office is located at 4557 Melan Dr. S. +Fairbanks, AK, 99712., but its volunteers and employees are scattered +throughout numerous locations. Its business office is located at +809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email +business@pglaf.org. Email contact links and up to date contact +information can be found at the Foundation's web site and official +page at http://pglaf.org + +For additional contact information: + Dr. Gregory B. Newby + Chief Executive and Director + gbnewby@pglaf.org + + +Section 4. Information about Donations to the Project Gutenberg +Literary Archive Foundation + +Project Gutenberg-tm depends upon and cannot survive without wide +spread public support and donations to carry out its mission of +increasing the number of public domain and licensed works that can be +freely distributed in machine readable form accessible by the widest +array of equipment including outdated equipment. Many small donations +($1 to $5,000) are particularly important to maintaining tax exempt +status with the IRS. + +The Foundation is committed to complying with the laws regulating +charities and charitable donations in all 50 states of the United +States. Compliance requirements are not uniform and it takes a +considerable effort, much paperwork and many fees to meet and keep up +with these requirements. We do not solicit donations in locations +where we have not received written confirmation of compliance. To +SEND DONATIONS or determine the status of compliance for any +particular state visit http://pglaf.org + +While we cannot and do not solicit contributions from states where we +have not met the solicitation requirements, we know of no prohibition +against accepting unsolicited donations from donors in such states who +approach us with offers to donate. + +International donations are gratefully accepted, but we cannot make +any statements concerning tax treatment of donations received from +outside the United States. U.S. laws alone swamp our small staff. + +Please check the Project Gutenberg Web pages for current donation +methods and addresses. Donations are accepted in a number of other +ways including checks, online payments and credit card donations. +To donate, please visit: http://pglaf.org/donate + + +Section 5. General Information About Project Gutenberg-tm electronic +works. + +Professor Michael S. Hart is the originator of the Project Gutenberg-tm +concept of a library of electronic works that could be freely shared +with anyone. For thirty years, he produced and distributed Project +Gutenberg-tm eBooks with only a loose network of volunteer support. + + +Project Gutenberg-tm eBooks are often created from several printed +editions, all of which are confirmed as Public Domain in the U.S. +unless a copyright notice is included. Thus, we do not necessarily +keep eBooks in compliance with any particular paper edition. + + +Most people start at our Web site which has the main PG search facility: + + http://www.gutenberg.org + +This Web site includes information about Project Gutenberg-tm, +including how to make donations to the Project Gutenberg Literary +Archive Foundation, how to help produce our new eBooks, and how to +subscribe to our email newsletter to hear about new eBooks. diff --git a/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland.tid b/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland.tid index 934c21967..13ecb7825 100644 --- a/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland.tid +++ b/editions/tw5.com/tiddlers/demonstrations/Alice in Wonderland.tid @@ -1,15 +1,14 @@ title: Alice in Wonderland tags: external-text +license: Alice in Wonderland License //Included here as a demonstration of ExternalText text support. See the bottom for the license from Project Gutenberg// --- -# ALICE'S ADVENTURES IN WONDERLAND +! ALICE'S ADVENTURES IN WONDERLAND -## Lewis Carroll - -THE MILLENNIUM FULCRUM EDITION 3.0 +!! Lewis Carroll !!! CHAPTER I. Down the Rabbit-Hole @@ -3341,369 +3340,3 @@ all their simple sorrows, and find a pleasure in all their simple joys, remembering her own child-life, and the happy summer days. THE END - - - - - -End of Project Gutenberg's Alice's Adventures in Wonderland, by Lewis Carroll - -*** END OF THIS PROJECT GUTENBERG EBOOK ALICE'S ADVENTURES IN WONDERLAND *** - -***** This file should be named 11.txt or 11.zip ***** -This and all associated files of various formats will be found in: - http://www.gutenberg.org/1/11/ - - - -Updated editions will replace the previous one--the old editions -will be renamed. - -Creating the works from public domain print editions means that no -one owns a United States copyright in these works, so the Foundation -(and you!) can copy and distribute it in the United States without -permission and without paying copyright royalties. Special rules, -set forth in the General Terms of Use part of this license, apply to -copying and distributing Project Gutenberg-tm electronic works to -protect the PROJECT GUTENBERG-tm concept and trademark. Project -Gutenberg is a registered trademark, and may not be used if you -charge for the eBooks, unless you receive specific permission. If you -do not charge anything for copies of this eBook, complying with the -rules is very easy. You may use this eBook for nearly any purpose -such as creation of derivative works, reports, performances and -research. They may be modified and printed and given away--you may do -practically ANYTHING with public domain eBooks. Redistribution is -subject to the trademark license, especially commercial -redistribution. - - - -*** START: FULL LICENSE *** - -THE FULL PROJECT GUTENBERG LICENSE -PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK - -To protect the Project Gutenberg-tm mission of promoting the free -distribution of electronic works, by using or distributing this work -(or any other work associated in any way with the phrase "Project -Gutenberg"), you agree to comply with all the terms of the Full Project -Gutenberg-tm License (available with this file or online at -http://gutenberg.org/license). - - -Section 1. General Terms of Use and Redistributing Project Gutenberg-tm -electronic works - -1.A. By reading or using any part of this Project Gutenberg-tm -electronic work, you indicate that you have read, understand, agree to -and accept all the terms of this license and intellectual property -(trademark/copyright) agreement. If you do not agree to abide by all -the terms of this agreement, you must cease using and return or destroy -all copies of Project Gutenberg-tm electronic works in your possession. -If you paid a fee for obtaining a copy of or access to a Project -Gutenberg-tm electronic work and you do not agree to be bound by the -terms of this agreement, you may obtain a refund from the person or -entity to whom you paid the fee as set forth in paragraph 1.E.8. - -1.B. "Project Gutenberg" is a registered trademark. It may only be -used on or associated in any way with an electronic work by people who -agree to be bound by the terms of this agreement. There are a few -things that you can do with most Project Gutenberg-tm electronic works -even without complying with the full terms of this agreement. See -paragraph 1.C below. There are a lot of things you can do with Project -Gutenberg-tm electronic works if you follow the terms of this agreement -and help preserve free future access to Project Gutenberg-tm electronic -works. See paragraph 1.E below. - -1.C. The Project Gutenberg Literary Archive Foundation ("the Foundation" -or PGLAF), owns a compilation copyright in the collection of Project -Gutenberg-tm electronic works. Nearly all the individual works in the -collection are in the public domain in the United States. If an -individual work is in the public domain in the United States and you are -located in the United States, we do not claim a right to prevent you from -copying, distributing, performing, displaying or creating derivative -works based on the work as long as all references to Project Gutenberg -are removed. Of course, we hope that you will support the Project -Gutenberg-tm mission of promoting free access to electronic works by -freely sharing Project Gutenberg-tm works in compliance with the terms of -this agreement for keeping the Project Gutenberg-tm name associated with -the work. You can easily comply with the terms of this agreement by -keeping this work in the same format with its attached full Project -Gutenberg-tm License when you share it without charge with others. - -1.D. The copyright laws of the place where you are located also govern -what you can do with this work. Copyright laws in most countries are in -a constant state of change. If you are outside the United States, check -the laws of your country in addition to the terms of this agreement -before downloading, copying, displaying, performing, distributing or -creating derivative works based on this work or any other Project -Gutenberg-tm work. The Foundation makes no representations concerning -the copyright status of any work in any country outside the United -States. - -1.E. Unless you have removed all references to Project Gutenberg: - -1.E.1. The following sentence, with active links to, or other immediate -access to, the full Project Gutenberg-tm License must appear prominently -whenever any copy of a Project Gutenberg-tm work (any work on which the -phrase "Project Gutenberg" appears, or with which the phrase "Project -Gutenberg" is associated) is accessed, displayed, performed, viewed, -copied or distributed: - -This eBook is for the use of anyone anywhere at no cost and with -almost no restrictions whatsoever. You may copy it, give it away or -re-use it under the terms of the Project Gutenberg License included -with this eBook or online at www.gutenberg.org - -1.E.2. If an individual Project Gutenberg-tm electronic work is derived -from the public domain (does not contain a notice indicating that it is -posted with permission of the copyright holder), the work can be copied -and distributed to anyone in the United States without paying any fees -or charges. If you are redistributing or providing access to a work -with the phrase "Project Gutenberg" associated with or appearing on the -work, you must comply either with the requirements of paragraphs 1.E.1 -through 1.E.7 or obtain permission for the use of the work and the -Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or -1.E.9. - -1.E.3. If an individual Project Gutenberg-tm electronic work is posted -with the permission of the copyright holder, your use and distribution -must comply with both paragraphs 1.E.1 through 1.E.7 and any additional -terms imposed by the copyright holder. Additional terms will be linked -to the Project Gutenberg-tm License for all works posted with the -permission of the copyright holder found at the beginning of this work. - -1.E.4. Do not unlink or detach or remove the full Project Gutenberg-tm -License terms from this work, or any files containing a part of this -work or any other work associated with Project Gutenberg-tm. - -1.E.5. Do not copy, display, perform, distribute or redistribute this -electronic work, or any part of this electronic work, without -prominently displaying the sentence set forth in paragraph 1.E.1 with -active links or immediate access to the full terms of the Project -Gutenberg-tm License. - -1.E.6. You may convert to and distribute this work in any binary, -compressed, marked up, nonproprietary or proprietary form, including any -word processing or hypertext form. However, if you provide access to or -distribute copies of a Project Gutenberg-tm work in a format other than -"Plain Vanilla ASCII" or other format used in the official version -posted on the official Project Gutenberg-tm web site (www.gutenberg.org), -you must, at no additional cost, fee or expense to the user, provide a -copy, a means of exporting a copy, or a means of obtaining a copy upon -request, of the work in its original "Plain Vanilla ASCII" or other -form. Any alternate format must include the full Project Gutenberg-tm -License as specified in paragraph 1.E.1. - -1.E.7. Do not charge a fee for access to, viewing, displaying, -performing, copying or distributing any Project Gutenberg-tm works -unless you comply with paragraph 1.E.8 or 1.E.9. - -1.E.8. You may charge a reasonable fee for copies of or providing -access to or distributing Project Gutenberg-tm electronic works provided -that - -- You pay a royalty fee of 20% of the gross profits you derive from - the use of Project Gutenberg-tm works calculated using the method - you already use to calculate your applicable taxes. The fee is - owed to the owner of the Project Gutenberg-tm trademark, but he - has agreed to donate royalties under this paragraph to the - Project Gutenberg Literary Archive Foundation. Royalty payments - must be paid within 60 days following each date on which you - prepare (or are legally required to prepare) your periodic tax - returns. Royalty payments should be clearly marked as such and - sent to the Project Gutenberg Literary Archive Foundation at the - address specified in Section 4, "Information about donations to - the Project Gutenberg Literary Archive Foundation." - -- You provide a full refund of any money paid by a user who notifies - you in writing (or by e-mail) within 30 days of receipt that s/he - does not agree to the terms of the full Project Gutenberg-tm - License. You must require such a user to return or - destroy all copies of the works possessed in a physical medium - and discontinue all use of and all access to other copies of - Project Gutenberg-tm works. - -- You provide, in accordance with paragraph 1.F.3, a full refund of any - money paid for a work or a replacement copy, if a defect in the - electronic work is discovered and reported to you within 90 days - of receipt of the work. - -- You comply with all other terms of this agreement for free - distribution of Project Gutenberg-tm works. - -1.E.9. If you wish to charge a fee or distribute a Project Gutenberg-tm -electronic work or group of works on different terms than are set -forth in this agreement, you must obtain permission in writing from -both the Project Gutenberg Literary Archive Foundation and Michael -Hart, the owner of the Project Gutenberg-tm trademark. Contact the -Foundation as set forth in Section 3 below. - -1.F. - -1.F.1. Project Gutenberg volunteers and employees expend considerable -effort to identify, do copyright research on, transcribe and proofread -public domain works in creating the Project Gutenberg-tm -collection. Despite these efforts, Project Gutenberg-tm electronic -works, and the medium on which they may be stored, may contain -"Defects," such as, but not limited to, incomplete, inaccurate or -corrupt data, transcription errors, a copyright or other intellectual -property infringement, a defective or damaged disk or other medium, a -computer virus, or computer codes that damage or cannot be read by -your equipment. - -1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right -of Replacement or Refund" described in paragraph 1.F.3, the Project -Gutenberg Literary Archive Foundation, the owner of the Project -Gutenberg-tm trademark, and any other party distributing a Project -Gutenberg-tm electronic work under this agreement, disclaim all -liability to you for damages, costs and expenses, including legal -fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT -LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE -PROVIDED IN PARAGRAPH F3. YOU AGREE THAT THE FOUNDATION, THE -TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE -LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR -INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH -DAMAGE. - -1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a -defect in this electronic work within 90 days of receiving it, you can -receive a refund of the money (if any) you paid for it by sending a -written explanation to the person you received the work from. If you -received the work on a physical medium, you must return the medium with -your written explanation. The person or entity that provided you with -the defective work may elect to provide a replacement copy in lieu of a -refund. If you received the work electronically, the person or entity -providing it to you may choose to give you a second opportunity to -receive the work electronically in lieu of a refund. If the second copy -is also defective, you may demand a refund in writing without further -opportunities to fix the problem. - -1.F.4. Except for the limited right of replacement or refund set forth -in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER -WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE. - -1.F.5. Some states do not allow disclaimers of certain implied -warranties or the exclusion or limitation of certain types of damages. -If any disclaimer or limitation set forth in this agreement violates the -law of the state applicable to this agreement, the agreement shall be -interpreted to make the maximum disclaimer or limitation permitted by -the applicable state law. The invalidity or unenforceability of any -provision of this agreement shall not void the remaining provisions. - -1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the -trademark owner, any agent or employee of the Foundation, anyone -providing copies of Project Gutenberg-tm electronic works in accordance -with this agreement, and any volunteers associated with the production, -promotion and distribution of Project Gutenberg-tm electronic works, -harmless from all liability, costs and expenses, including legal fees, -that arise directly or indirectly from any of the following which you do -or cause to occur: (a) distribution of this or any Project Gutenberg-tm -work, (b) alteration, modification, or additions or deletions to any -Project Gutenberg-tm work, and (c) any Defect you cause. - - -Section 2. Information about the Mission of Project Gutenberg-tm - -Project Gutenberg-tm is synonymous with the free distribution of -electronic works in formats readable by the widest variety of computers -including obsolete, old, middle-aged and new computers. It exists -because of the efforts of hundreds of volunteers and donations from -people in all walks of life. - -Volunteers and financial support to provide volunteers with the -assistance they need, is critical to reaching Project Gutenberg-tm's -goals and ensuring that the Project Gutenberg-tm collection will -remain freely available for generations to come. In 2001, the Project -Gutenberg Literary Archive Foundation was created to provide a secure -and permanent future for Project Gutenberg-tm and future generations. -To learn more about the Project Gutenberg Literary Archive Foundation -and how your efforts and donations can help, see Sections 3 and 4 -and the Foundation web page at http://www.pglaf.org. - - -Section 3. Information about the Project Gutenberg Literary Archive -Foundation - -The Project Gutenberg Literary Archive Foundation is a non profit -501(c)(3) educational corporation organized under the laws of the -state of Mississippi and granted tax exempt status by the Internal -Revenue Service. The Foundation's EIN or federal tax identification -number is 64-6221541. Its 501(c)(3) letter is posted at -http://pglaf.org/fundraising. Contributions to the Project Gutenberg -Literary Archive Foundation are tax deductible to the full extent -permitted by U.S. federal laws and your state's laws. - -The Foundation's principal office is located at 4557 Melan Dr. S. -Fairbanks, AK, 99712., but its volunteers and employees are scattered -throughout numerous locations. Its business office is located at -809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email -business@pglaf.org. Email contact links and up to date contact -information can be found at the Foundation's web site and official -page at http://pglaf.org - -For additional contact information: - Dr. Gregory B. Newby - Chief Executive and Director - gbnewby@pglaf.org - - -Section 4. Information about Donations to the Project Gutenberg -Literary Archive Foundation - -Project Gutenberg-tm depends upon and cannot survive without wide -spread public support and donations to carry out its mission of -increasing the number of public domain and licensed works that can be -freely distributed in machine readable form accessible by the widest -array of equipment including outdated equipment. Many small donations -($1 to $5,000) are particularly important to maintaining tax exempt -status with the IRS. - -The Foundation is committed to complying with the laws regulating -charities and charitable donations in all 50 states of the United -States. Compliance requirements are not uniform and it takes a -considerable effort, much paperwork and many fees to meet and keep up -with these requirements. We do not solicit donations in locations -where we have not received written confirmation of compliance. To -SEND DONATIONS or determine the status of compliance for any -particular state visit http://pglaf.org - -While we cannot and do not solicit contributions from states where we -have not met the solicitation requirements, we know of no prohibition -against accepting unsolicited donations from donors in such states who -approach us with offers to donate. - -International donations are gratefully accepted, but we cannot make -any statements concerning tax treatment of donations received from -outside the United States. U.S. laws alone swamp our small staff. - -Please check the Project Gutenberg Web pages for current donation -methods and addresses. Donations are accepted in a number of other -ways including checks, online payments and credit card donations. -To donate, please visit: http://pglaf.org/donate - - -Section 5. General Information About Project Gutenberg-tm electronic -works. - -Professor Michael S. Hart is the originator of the Project Gutenberg-tm -concept of a library of electronic works that could be freely shared -with anyone. For thirty years, he produced and distributed Project -Gutenberg-tm eBooks with only a loose network of volunteer support. - - -Project Gutenberg-tm eBooks are often created from several printed -editions, all of which are confirmed as Public Domain in the U.S. -unless a copyright notice is included. Thus, we do not necessarily -keep eBooks in compliance with any particular paper edition. - - -Most people start at our Web site which has the main PG search facility: - - http://www.gutenberg.org - -This Web site includes information about Project Gutenberg-tm, -including how to make donations to the Project Gutenberg Literary -Archive Foundation, how to help produce our new eBooks, and how to -subscribe to our email newsletter to hear about new eBooks.