You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"text": "/*\\\ntitle: $:/plugins/sq/ImportToExternalFile/server-route-upload.js\ntype: application/javascript\nmodule-type: route\n\nPOST /^\\/api\\/upload/\n\nUpload media\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"POST\";\n\nexports.path = new RegExp('^\\/api\\/upload');\nexports.bodyFormat = \"stream\";\n\n\tconst fs = require('fs')\n\tconst path = require('path')\n\tconst buffer = require('buffer')\n\nexports.handler = function(request,response,state) {\n\n\t\n\tlet body = ''\n\t\n\trequest.on('data', function(chunk){\n\t\tbody += chunk;\n\t\t// We limit the size of an upload to 10mb for now.\n\t\tif(body.length > 10e6) {\n\t\t\tresponse.writeHead(413, {'Content-Type': 'text/plain'}).end();\n\t\t\trequest.connection.destroy();\n\t\t}\n\t});\n\t\n\trequest.on('end', function() {\n\t\ttry {\n\t\t\tlet bodyData = JSON.parse(body)\n\n\t\t\tconst filesPath = path.resolve($tw.boot.wikiTiddlersPath, \"../files\");\n\n //config option overwrite existing?\n\t\n /* \n var xfilepath = $tw.utils.generateTiddlerFilepath(bodyData.tiddler.fields.title,{\n directory: filesPath\n });\n //var ext = path.extname(originalpath);\n //xfilepath = xfilepath.substring(0,xfilepath.length - ext.length);\n \n \n // 1) try to increment filename before extension.\n // 2) don't encode / in file path so can specify a subdir\n xfilepath = path.join(filesPath, bodyData.tiddler.fields.title); //with this tiddler titles like images/filename work but only if directory exists\n console.log(xfilepath);\n\t\t\t*/\n var xfilepath = generateBinaryFilePath(bodyData.tiddler.fields.title);\n\t\t\tconsole.log(xfilepath);\n\t\t\t$tw.utils.createDirectory(filesPath);\n\t\t\tconst buf = Buffer.from(bodyData.tiddler.fields.text,'base64');\n\t\t\t//const filename = path.join(filesPath, bodyData.tiddler.fields.title);\n\t\t\tconst filename = xfilepath;\n fs.writeFile(path.join(xfilepath), buf, function(error) {\n\t\t\t\tif (error) {\n\t\t\t\t\tconsole.log(error);\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\"External file saved: \" + filename);\n\t\t\t\t\tresponse.setHeader('Content-Type', 'application/json');\n\t\t\t\t\tresponse.end(JSON.stringify( {\n \"success\": \"saved \" + bodyData.tiddler.fields.title,\n \"status\": 200,\n //\"_canonical_uri\":\t \"files/\" + bodyData.tiddler.fields.title,\n \"_canonical_uri\": path.relative(path.resolve($tw.boot.wikiTiddlersPath,\"..\"),xfilepath),\n\t\t\t\t\t\t\t\"tiddler\": bodyData.tiddler.fields.title\n }));\n //state.wiki.addTiddler(bodyData.tiddler.fields,{_canonical_uri : bodyData.tiddler.fields.title, text:\"\"},state.wiki.getModificationFields());\n\t\t\t\t\t\t//return true;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tconsole.log('Error parsing or writing uploaded file', e, {'level': 2});\n\t\t\tresponse.writeHead(400);\n\t\t\tresponse.end();\n\t\t}\n\t})\n};\n\nvar generateBinaryFilePath = function(title,options) {\n const filesDirPath = path.resolve($tw.boot.wikiTiddlersPath,\"../files\");\n\t// Remove any forward or backward slashes so we don't create directories\n\tvar filepath = title.replace(/\\/|\\\\/g,\"_\");\n\t// Replace any Windows control codes\n\tfilepath = filepath.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,\"_$1_\");\n\t// Replace any leading spaces with the same number of underscores\n\tfilepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, \"_\")});\n\t//If the path does not start with \".\" or \"..\" && a path seperator, then\t\n\tif(!/^\\.{1,2}[/\\\\]/g.test(filepath)) {\n\t\t// Don't let the filename start with any dots because such files are invisible on *nix\n\t\tfilepath = filepath.replace(/^\\.+/g,function (u) { return u.replace(/\\./g, \"_\")});\n\t}\n\t// Replace any Unicode control codes\n\tfilepath = filepath.replace(/[\\x00-\\x1f\\x80-\\x9f]/g,\"_\");\n\t// Replace any characters that can't be used in cross-platform filenames\n\tfilepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\\:|\\\"|\\||\\?|\\*|\\^/g,\"_\"));\n\tvar extension = path.extname(title);\n\t//remove extension from filepath\n\tfilepath = filepath.substring(0,filepath.length - extension.length);\n\t// Replace any dots or spaces at the end of the extension with the same number of underscores\t\n\textension = extension.replace(/[\\. ]+$/, function (u) { return u.replace(/[\\. ]/g, \"_\")});\n\t// Truncate the extension if it is too long\n\tif(extension.length > 32) {\n\t\textension = extension.substr(0,32);\n\t}\n\t// Truncate the filename if it is too long\n\tif(filepath.length > 200) {\n\t\tfilepath = filepath.substr(0,200);\n\t}\n\t// If the resulting filename is blank (eg because the title is just punctuation)\n\tif(!filepath || /^_+$/g.test(filepath)) {\n\t\t// ...then just use the character codes of the title\n\t\tfilepath = \"\";\t\n\t\t$tw.utils.each(title.split(\"\"),function(char) {\n\t\t\tif(filepath) {\n\t\t\t\tfilepath += \"-\";\n\t\t\t}\n\t\t\tfilepath += char.charCodeAt(0).toString();\n\t\t});\n\t}\n\t\n\t\n\tvar overwrite = $tw.wiki.getTextReference(\"!!text\",\"yes\",\"$:/config/sq/OverwriteBinaryFiles\") === \"yes\" ? true : false;\n\tif(overwrite) {\n\t\treturn path.resolve(filesDirPath,filepath + extension);\n\t}\n\t\n\tvar fullPath,\n\t\tcount = 0;\n\tdo {\n\t\tfullPath = path.resolve(filesDirPath,filepath + (count ? \"_\" + count : \"\") + extension);\n\t\tcount++;\n\t} while(fs.existsSync(fullPath));\t\n\treturn fullPath;\n}\n\n\n}());",
"text": "/*\\\ntitle: $:/plugins/sq/ImportToExternalFile/startup.js\ntype: application/javascript\nmodule-type: startup\n\nThis adds a hook for the \"th-importing-tiddler\"\n\n\\*/\n(function () {\n\n\t/*jslint node: true, browser: true */\n\t/*global $tw: false */\n\t\"use strict\";\n\n\t// Export name and synchronous status\n\texports.name = \"sq-server-images\";\n\texports.platforms = [\"browser\"];\n\texports.after = [\"render\"];\n\texports.synchronous = true;\n\n\texports.startup = function() {\n\n\t// Add the hook to the wiki in the browser\n\t$tw.hooks.addHook(\"th-importing-tiddler\", function(tiddler) {\n\t\t\n\t\tvar saveAsExternal = $tw.wiki.getTextReference(\"!!text\",\"yes\",\"$:/config/sq/SaveAsExternalFile\") === \"yes\" ? true : false;\n\t\tif(!saveAsExternal) {\n\t\t\treturn tiddler;\n\t\t}\n\t\treturn externaliseTiddler(tiddler);\n\n\t});\n\t\n\t$tw.rootWidget.addEventListener(\"tm-externalise-tiddler\",function(event){\n\t\tvar tiddler = $tw.wiki.getTiddler(event.tiddlerTitle);\n\t\tif(tiddler) {\n\t\t\texternaliseTiddler(tiddler);\n\t\t}\n\t});\n\t\n}\n\nfunction updateProgress(e) {\n\t// TODO make this work in different browsers\n\t/*\n\tif (e.lengthComputable) {\n\tvar percentComplete = e.loaded/e.total*100;\n\t} else {\n\tvar percentComplete = -1;\n\t}\n\tconsole.log(percentComplete);\n\t*/\n}\nfunction transferComplete(e) {\n\tconsole.log('Complete!!',e);\n}\nfunction transferFailed(e) {\n\tconsole.log('Failed due to Network issues!');\n}\nfunction transferCanceled(e) {\n\tconsole.log('Cancelled!')\n}\n\n// https://github.com/Jermolene/TiddlyWiki5/blob/14a28b77796461c9167898793ab9851e029e0354/core/modules/utils/dom/http.js\n\nvar externaliseTiddler = function(tiddler) {\n\t// Figure out if the thing being imported is something that should be\n\t// saved on the server.\n\tvar mediaTypes = ['image/gif', 'image/x-icon', 'image/jpeg', 'image/jpeg', 'image/png', 'image/svg+xml', 'application/pdf', 'application/zip', 'application/font-woff', 'application/x-font-ttf', 'audio/ogg', 'video/mp4', 'audio/mp3', 'audio/mp4'];\n\tif (mediaTypes.indexOf(tiddler.fields.type) > -1 && !tiddler.fields._canonical_uri) {\n\t\t// Check if this is set up to use HTTP post or websockets to save the\n\t\t// image on the server.\n\t\tvar request = new XMLHttpRequest();\n\t\trequest.upload.addEventListener('progress', updateProgress);\n\t\trequest.upload.addEventListener('load', transferComplete);\n\t\trequest.upload.addEventListener('error', transferFailed);\n\t\trequest.upload.addEventListener('abort', transferCanceled);\n\n\t\trequest.onreadystatechange = function() {\n\t\t\tif (this.readyState == 4) {\n\t\t\t\tif(this.status == 200) {\n\t\t\t\t\tconsole.log(this.response);\n\t\t\t\t\tvar json = null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tjson = JSON.parse(this.response);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.log(\"Error/XMLHttpRequest when parsing JSON\" + \": \" + this.status);\n\t\t\t\t\t}\n\t\t\t\t\tif(json && json.tiddler) {\n\t\t\t\t\t\tconsole.log(json);\n\t\t\t\t\t\tvar tiddler = $tw.wiki.getTiddler(json.tiddler);\n\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(tiddler,{_canonical_uri: json._canonical_uri, text:\"\"}));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// if we are here the request did not return a success codePointAt\n\t\t\t\tconsole.log(\"Error/XMLHttpRequest\" + \": \" + this.status);\n\t\t\t};\n\t\t}\n\t\tvar uploadURL = '/api/upload';\n\t\trequest.open('POST', uploadURL, true);\n\n\t\tvar thing = {\n\t\t\ttiddler: tiddler\n\t\t}\n\t//\trequest.upload.addEventListener('load', transferComplete);\n\t\trequest.setRequestHeader(\"X-Requested-With\",\"TiddlyWiki\");\n\t\trequest.send(JSON.stringify(thing));\n\n\t\t// Change the tiddler fields and stuff\n\t\tvar fields = {};\n\t\tvar uri = '/files/'+tiddler.fields.title;\n\t\t//Use tw.utils.generateTiddlerFilePath //remove / etc from title\n\t\t//https://github.com/Jermolene/TiddlyWiki5/blob/master/core/modules/utils/filesystem.js#L321\n\t\tfields.title = tiddler.fields.title;\n\t\tfields.type = tiddler.fields.type;\n\t\tfields._canonical_uri = uri;\n\t\t//return new $tw.Tiddler(fields);\n\t\treturn tiddler;\n\t} else {\n\t\treturn tiddler;\n\t}\t\n}\n\n})();",
0 commit comments