From d0a17d547168a0bcb8e35a7f63ba37ad2d360f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Fri, 23 Nov 2012 18:18:03 +0100 Subject: [PATCH 1/5] test import converting to html instead to txt by default --- src/node/handler/ImportHandler.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 788706ce7..b6cd5029d 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -27,17 +27,22 @@ var settings = require('../utils/Settings'); var formidable = require('formidable'); var os = require("os"); +// TESTING importing in HTML +var importHtml = require("../utils/ImportHtml"); + //load abiword only if its enabled if(settings.abiword != null) var abiword = require("../utils/Abiword"); -var tempDirectory = "/tmp/"; +//Patched in formidable since v1.0.4: +// The dafault temp directory is well detected in order to OS +//var tempDirectory = "/tmp/"; //tempDirectory changes if the operating system is windows -if(os.type().indexOf("Windows") > -1) +/*if(os.type().indexOf("Windows") > -1) { tempDirectory = process.env.TEMP; -} +}*/ /** * do a requested import @@ -58,7 +63,7 @@ exports.doImport = function(req, res, padId) { var form = new formidable.IncomingForm(); form.keepExtensions = true; - form.uploadDir = tempDirectory; + //form.uploadDir = tempDirectory; form.parse(req, function(err, fields, files) { @@ -105,6 +110,7 @@ exports.doImport = function(req, res, padId) { var oldSrcFile = srcFile; srcFile = srcFile.split(".")[0] + ".txt"; + //srcFile = srcFile.split(".")[0] + ".htm"; fs.rename(oldSrcFile, srcFile, callback); } @@ -114,8 +120,11 @@ exports.doImport = function(req, res, padId) function(callback) { var randNum = Math.floor(Math.random()*0xFFFFFFFF); - destFile = tempDirectory + "eplite_import_" + randNum + ".txt"; - abiword.convertFile(srcFile, destFile, "txt", function(err){ + //destFile = tempDirectory + "eplite_import_" + randNum + ".txt"; + //destFile = tempDirectory + "eplite_import_" + randNum + ".htm"; + destFile = os.tmpDir() + "/eplite_import_" + randNum + ".htm"; + //abiword.convertFile(srcFile, destFile, "txt", function(err){ + abiword.convertFile(srcFile, destFile, "htm", function(err){ //catch convert errors if(err){ console.warn("Converting Error:", err); @@ -164,7 +173,9 @@ exports.doImport = function(req, res, padId) //change text of the pad and broadcast the changeset function(callback) { - pad.setText(text); + //pad.setText(text); + //prueba + importHtml.setPadHTML(pad, text); padMessageHandler.updatePadClients(pad, callback); }, @@ -196,6 +207,7 @@ exports.doImport = function(req, res, padId) ERR(err); //close the connection + res.send("", 200); }); } From ef3231efd27a5fde80a6d94b559117e9a028e641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Fri, 23 Nov 2012 19:06:18 +0100 Subject: [PATCH 2/5] cleaning --- src/node/handler/ImportHandler.js | 121 ++++++++++-------------------- 1 file changed, 39 insertions(+), 82 deletions(-) diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index b6cd5029d..f6b381a71 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -18,31 +18,19 @@ * limitations under the License. */ -var ERR = require("async-stacktrace"); -var padManager = require("../db/PadManager"); -var padMessageHandler = require("./PadMessageHandler"); -var async = require("async"); -var fs = require("fs"); -var settings = require('../utils/Settings'); -var formidable = require('formidable'); -var os = require("os"); - -// TESTING importing in HTML -var importHtml = require("../utils/ImportHtml"); +var ERR = require("async-stacktrace") + , padManager = require("../db/PadManager") + , padMessageHandler = require("./PadMessageHandler") + , async = require("async") + , fs = require("fs") + , settings = require('../utils/Settings') + , formidable = require('formidable') + , os = require("os") + , importHtml = require("../utils/ImportHtml"); //load abiword only if its enabled if(settings.abiword != null) var abiword = require("../utils/Abiword"); - -//Patched in formidable since v1.0.4: -// The dafault temp directory is well detected in order to OS -//var tempDirectory = "/tmp/"; - -//tempDirectory changes if the operating system is windows -/*if(os.type().indexOf("Windows") > -1) -{ - tempDirectory = process.env.TEMP; -}*/ /** * do a requested import @@ -50,32 +38,27 @@ if(settings.abiword != null) exports.doImport = function(req, res, padId) { //pipe to a file - //convert file to text via abiword - //set text in the pad + //convert file to html via abiword + //set html in the pad - var srcFile, destFile; - var pad; - var text; + var srcFile, destFile + , pad; + , text; async.series([ //save the uploaded file to /tmp - function(callback) - { + function(callback) { var form = new formidable.IncomingForm(); form.keepExtensions = true; - //form.uploadDir = tempDirectory; - form.parse(req, function(err, fields, files) - { + form.parse(req, function(err, fields, files) { //the upload failed, stop at this point - if(err || files.file === undefined) - { + if(err || files.file === undefined) { console.warn("Uploading Error: " + err.stack); callback("uploadFailed"); } //everything ok, continue - else - { + else { //save the path of the uploaded file srcFile = files.file.path; callback(); @@ -85,48 +68,38 @@ exports.doImport = function(req, res, padId) //ensure this is a file ending we know, else we change the file ending to .txt //this allows us to accept source code files like .c or .java - function(callback) - { + function(callback) { var fileEnding = (srcFile.split(".")[1] || "").toLowerCase(); var knownFileEndings = ["txt", "doc", "docx", "pdf", "odt", "html", "htm"]; //find out if this is a known file ending var fileEndingKnown = false; - for(var i in knownFileEndings) - { - if(fileEnding == knownFileEndings[i]) - { + for(var i in knownFileEndings) { + if(fileEnding == knownFileEndings[i]){ fileEndingKnown = true; } } //if the file ending is known, continue as normal - if(fileEndingKnown) - { + if(fileEndingKnown) { callback(); } //we need to rename this file with a .txt ending - else - { + else { var oldSrcFile = srcFile; srcFile = srcFile.split(".")[0] + ".txt"; - //srcFile = srcFile.split(".")[0] + ".htm"; fs.rename(oldSrcFile, srcFile, callback); } }, //convert file to text - function(callback) - { + function(callback) { var randNum = Math.floor(Math.random()*0xFFFFFFFF); - //destFile = tempDirectory + "eplite_import_" + randNum + ".txt"; - //destFile = tempDirectory + "eplite_import_" + randNum + ".htm"; destFile = os.tmpDir() + "/eplite_import_" + randNum + ".htm"; - //abiword.convertFile(srcFile, destFile, "txt", function(err){ - abiword.convertFile(srcFile, destFile, "htm", function(err){ + abiword.convertFile(srcFile, destFile, "htm", function(err) { //catch convert errors - if(err){ + if(err) { console.warn("Converting Error:", err); return callback("convertFailed"); } else { @@ -136,10 +109,8 @@ exports.doImport = function(req, res, padId) }, //get the pad object - function(callback) - { - padManager.getPad(padId, function(err, _pad) - { + function(callback) { + padManager.getPad(padId, function(err, _pad){ if(ERR(err, callback)) return; pad = _pad; callback(); @@ -147,54 +118,40 @@ exports.doImport = function(req, res, padId) }, //read the text - function(callback) - { - fs.readFile(destFile, "utf8", function(err, _text) - { + function(callback) { + fs.readFile(destFile, "utf8", function(err, _text){ if(ERR(err, callback)) return; text = _text; //node on windows has a delay on releasing of the file lock. //We add a 100ms delay to work around this - if(os.type().indexOf("Windows") > -1) - { - setTimeout(function() - { - callback(); - }, 100); - } - else - { + if(os.type().indexOf("Windows") > -1){ + setTimeout(function(){callback();}, 100); + } else { callback(); } }); }, //change text of the pad and broadcast the changeset - function(callback) - { - //pad.setText(text); - //prueba + function(callback) { importHtml.setPadHTML(pad, text); padMessageHandler.updatePadClients(pad, callback); }, //clean up temporary files - function(callback) - { + function(callback) { async.parallel([ - function(callback) - { + function(callback){ fs.unlink(srcFile, callback); }, - function(callback) - { + function(callback){ fs.unlink(destFile, callback); } ], callback); } - ], function(err) - { + ], function(err) { + var status = "ok"; //check for known errors and replace the status From cc60b82a6ef3dda7a8c89dc8083bd5204bb99f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Fri, 23 Nov 2012 22:55:25 +0100 Subject: [PATCH 3/5] Import html by default and allow basic import/export features without abiword --- src/node/handler/ImportHandler.js | 70 ++++++++++++++------------ src/node/hooks/express/importexport.js | 6 --- src/static/js/pad_impexp.js | 4 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index f6b381a71..93fd3db5b 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -23,6 +23,7 @@ var ERR = require("async-stacktrace") , padMessageHandler = require("./PadMessageHandler") , async = require("async") , fs = require("fs") + , path = require("path") , settings = require('../utils/Settings') , formidable = require('formidable') , os = require("os") @@ -42,7 +43,7 @@ exports.doImport = function(req, res, padId) //set html in the pad var srcFile, destFile - , pad; + , pad , text; async.series([ @@ -69,16 +70,9 @@ exports.doImport = function(req, res, padId) //ensure this is a file ending we know, else we change the file ending to .txt //this allows us to accept source code files like .c or .java function(callback) { - var fileEnding = (srcFile.split(".")[1] || "").toLowerCase(); - var knownFileEndings = ["txt", "doc", "docx", "pdf", "odt", "html", "htm"]; - - //find out if this is a known file ending - var fileEndingKnown = false; - for(var i in knownFileEndings) { - if(fileEnding == knownFileEndings[i]){ - fileEndingKnown = true; - } - } + var fileEnding = path.extname(srcFile).toLowerCase() + , knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm"] + , fileEndingKnown = (knownFileEndings.indexOf(fileEnding) > -1); //if the file ending is known, continue as normal if(fileEndingKnown) { @@ -87,25 +81,31 @@ exports.doImport = function(req, res, padId) //we need to rename this file with a .txt ending else { var oldSrcFile = srcFile; - srcFile = srcFile.split(".")[0] + ".txt"; + srcFile = path.join(path.dirname(srcFile),path.basename(srcFile, fileEnding)+".txt"); fs.rename(oldSrcFile, srcFile, callback); } }, - //convert file to text + //convert file to html function(callback) { var randNum = Math.floor(Math.random()*0xFFFFFFFF); - destFile = os.tmpDir() + "/eplite_import_" + randNum + ".htm"; - abiword.convertFile(srcFile, destFile, "htm", function(err) { - //catch convert errors - if(err) { - console.warn("Converting Error:", err); - return callback("convertFailed"); - } else { - callback(); - } - }); + destFile = path.join(os.tmpDir(), "eplite_import_" + randNum + ".htm"); + + if (abiword) { + abiword.convertFile(srcFile, destFile, "htm", function(err) { + //catch convert errors + if(err) { + console.warn("Converting Error:", err); + return callback("convertFailed"); + } else { + callback(); + } + }); + } else { + // if no abiword only rename + fs.rename(srcFile, destFile, callback); + } }, //get the pad object @@ -125,28 +125,35 @@ exports.doImport = function(req, res, padId) //node on windows has a delay on releasing of the file lock. //We add a 100ms delay to work around this - if(os.type().indexOf("Windows") > -1){ - setTimeout(function(){callback();}, 100); - } else { - callback(); - } + if(os.type().indexOf("Windows") > -1){ + setTimeout(function() {callback();}, 100); + } else { + callback(); + } }); }, //change text of the pad and broadcast the changeset function(callback) { - importHtml.setPadHTML(pad, text); + var fileEnding = path.extname(srcFile).toLowerCase(); + if (abiword || fileEnding == ".htm" || fileEnding == ".html") { + importHtml.setPadHTML(pad, text); + } else { + pad.setText(text); + } padMessageHandler.updatePadClients(pad, callback); }, //clean up temporary files function(callback) { + //for node < 0.7 compatible + var fileExists = fs.exists || path.exists; async.parallel([ function(callback){ - fs.unlink(srcFile, callback); + fileExists (srcFile, function(exist) { (exist)? fs.unlink(srcFile, callback): callback(); }); }, function(callback){ - fs.unlink(destFile, callback); + fileExists (destFile, function(exist) { (exist)? fs.unlink(destFile, callback): callback(); }); } ], callback); } @@ -164,7 +171,6 @@ exports.doImport = function(req, res, padId) ERR(err); //close the connection - res.send("", 200); }); } diff --git a/src/node/hooks/express/importexport.js b/src/node/hooks/express/importexport.js index 9e78f34d7..9754ffa64 100644 --- a/src/node/hooks/express/importexport.js +++ b/src/node/hooks/express/importexport.js @@ -28,12 +28,6 @@ exports.expressCreateServer = function (hook_name, args, cb) { //handle import requests args.app.post('/p/:pad/import', function(req, res, next) { - //if abiword is disabled, skip handling this request - if(settings.abiword == null) { - next(); - return; - } - hasPadAccess(req, res, function() { importHandler.doImport(req, res, req.params.pad); }); diff --git a/src/static/js/pad_impexp.js b/src/static/js/pad_impexp.js index 08dd42934..70d27d407 100644 --- a/src/static/js/pad_impexp.js +++ b/src/static/js/pad_impexp.js @@ -225,8 +225,8 @@ var padimpexp = (function() $("#exportworda").remove(); $("#exportpdfa").remove(); $("#exportopena").remove(); - $(".importformdiv").remove(); - $("#import").html("Import is not available. To enable import please install abiword"); + + $("#importform").attr('action', pad_root_url + "/import"); } else if(clientVars.abiwordAvailable == "withoutPDF") { From d7cca602dfb2e87497e404d21083c2e8b2cf6689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Mon, 26 Nov 2012 03:18:47 +0100 Subject: [PATCH 4/5] Added message translatable about features importing without abiword --- settings.json.template | 2 +- src/locales/en.ini | 3 ++- src/locales/es.ini | 1 + src/static/css/pad.css | 19 ++++++++++++------- src/static/js/pad_impexp.js | 9 ++++----- src/templates/pad.html | 3 ++- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/settings.json.template b/settings.json.template index 4894f897d..f6f3e5b85 100644 --- a/settings.json.template +++ b/settings.json.template @@ -65,7 +65,7 @@ "maxAge" : 21600, // 60 * 60 * 6 = 6 hours /* This is the path to the Abiword executable. Setting it to null, disables abiword. - Abiword is needed to enable the import/export of pads*/ + Abiword is needed to advanced import/export features of pads*/ "abiword" : null, /* This setting is used if you require authentication of all users. diff --git a/src/locales/en.ini b/src/locales/en.ini index a110583ea..32980b51d 100644 --- a/src/locales/en.ini +++ b/src/locales/en.ini @@ -41,6 +41,7 @@ pad.importExport.exportword = Microsoft Word pad.importExport.exportpdf = PDF pad.importExport.exportopen = ODF (Open Document Format) pad.importExport.exportdokuwiki = DokuWiki +pad.importExport.abiword.innerHTML = You only can import from plain text or html formats. For more advanced import features please install abiword. pad.modals.connected = Connected. pad.modals.reconnecting = Reconnecting to your pad.. pad.modals.forcereconnect = Force reconnect @@ -74,4 +75,4 @@ timeslider.pageTitle = {{appTitle}} Timeslider timeslider.toolbar.returnbutton = Return to pad timeslider.toolbar.authors = Authors: timeslider.toolbar.authorsList = No Authors -timeslider.exportCurrent = Export current version as: \ No newline at end of file +timeslider.exportCurrent = Export current version as: diff --git a/src/locales/es.ini b/src/locales/es.ini index dd2c0d142..538d94955 100644 --- a/src/locales/es.ini +++ b/src/locales/es.ini @@ -44,6 +44,7 @@ pad.importExport.exportword = Microsoft Word pad.importExport.exportpdf = PDF pad.importExport.exportopen = ODF (Open Document Format) pad.importExport.exportdokuwiki = DokuWiki +pad.importExport.abiword.innerHTML = Sólo puede importar formatos de texto plano o html. Para funciones más avanzadas instale abiword. pad.modals.connected = Conectado. pad.modals.reconnecting = Reconectando a tu pad.. pad.modals.forcereconnect = Reconexión forzosa diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 64f9f0d44..c3deebc19 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -571,15 +571,20 @@ table#otheruserstable { #exportdokuwiki { background-position: 0px -459px } -#importstatusball { - display: none + +/* hidden element */ +#importstatusball, +#importarrow, +#importmessagesuccess, +#importmessageabiword { + display: none; } -#importarrow { - display: none -} -#importmessagesuccess { - display: none + +#importmessageabiword { + color: #900; + font-size: small; } + #importsubmitinput { height: 25px; width: 85px; diff --git a/src/static/js/pad_impexp.js b/src/static/js/pad_impexp.js index 70d27d407..4b4733a56 100644 --- a/src/static/js/pad_impexp.js +++ b/src/static/js/pad_impexp.js @@ -218,6 +218,9 @@ var padimpexp = (function() $("#exporthtmla").attr("href", pad_root_path + "/export/html"); $("#exportplaina").attr("href", pad_root_path + "/export/txt"); $("#exportdokuwikia").attr("href", pad_root_path + "/export/dokuwiki"); + + // activate action to import in the form + $("#importform").attr('action', pad_root_url + "/import"); //hide stuff thats not avaible if abiword is disabled if(clientVars.abiwordAvailable == "no") @@ -226,7 +229,7 @@ var padimpexp = (function() $("#exportpdfa").remove(); $("#exportopena").remove(); - $("#importform").attr('action', pad_root_url + "/import"); + $("#importmessageabiword").show(); } else if(clientVars.abiwordAvailable == "withoutPDF") { @@ -237,16 +240,12 @@ var padimpexp = (function() $("#importexport").css({"height":"142px"}); $("#importexportline").css({"height":"142px"}); - - $("#importform").attr('action', pad_root_url + "/import"); } else { $("#exportworda").attr("href", pad_root_path + "/export/doc"); $("#exportpdfa").attr("href", pad_root_path + "/export/pdf"); $("#exportopena").attr("href", pad_root_path + "/export/odt"); - - $("#importform").attr('action', pad_root_path + "/import"); } $("#impexp-close").click(function() diff --git a/src/templates/pad.html b/src/templates/pad.html index 3f3eee4f1..a2b153d39 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -246,7 +246,8 @@

<% e.begin_block("importColumn"); %> -


+

+

From 97d77ea089c75fc64fef94b9259674d738a930cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Tue, 27 Nov 2012 00:11:45 +0100 Subject: [PATCH 5/5] added my name in header --- src/node/handler/ImportHandler.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 93fd3db5b..815e53579 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -4,6 +4,7 @@ /* * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) + * 2012 Iván Eixarch * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.