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 01/37] 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 02/37] 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 03/37] 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 ef7590fb7367ee87a444ef8a99c25b622bc3741b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Sat, 24 Nov 2012 00:26:48 +0100 Subject: [PATCH 04/37] Fix 1203: non-escaped html in plugins info --- src/templates/admin/plugins-info.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/templates/admin/plugins-info.html b/src/templates/admin/plugins-info.html index 22f87073e..b361e9cf2 100644 --- a/src/templates/admin/plugins-info.html +++ b/src/templates/admin/plugins-info.html @@ -14,17 +14,17 @@

Installed plugins

-
<%= plugins.formatPlugins() %>
+
<%- plugins.formatPlugins() %>

Installed parts

-
<%= plugins.formatParts() %>
+
<%- plugins.formatParts() %>

Installed hooks

Server side hooks

-
<%= plugins.formatHooks() %>
+
<%- plugins.formatHooks() %>

Client side hooks

-
<%= plugins.formatHooks("client_hooks") %>
+
<%- plugins.formatHooks("client_hooks") %>
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 05/37] 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 fddca354b33eb2f855178657b775a4008e8da8d5 Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 26 Nov 2012 20:52:10 +0000 Subject: [PATCH 06/37] proper fix for focus and some styling of the form and allows for pressing enter on form so generally a better fix --- src/static/js/pad.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 34f2a2877..936298abc 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -305,14 +305,22 @@ function handshake() else if(obj.accessStatus == "needPassword") { $("#editorloadingbox").html("You need a password to access this pad
" + - ""+ - ""); + ""+ + "
"); + $("#passwordinput").focus(); + $(".passForm").submit(function(){ + $('.passForm button').click(); + }); } else if(obj.accessStatus == "wrongPassword") { $("#editorloadingbox").html("Your password was wrong
" + - ""+ - ""); + ""+ + "
"); + $("#passwordinput").focus(); + $(".passForm").submit(function(){ + $('.passForm button').click(); + }); } } From f880473360e26f683df73700366f36b7dc757bdb Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 26 Nov 2012 20:54:28 +0000 Subject: [PATCH 07/37] remember the styling for the pasword prompt --- src/static/css/pad.css | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 64f9f0d44..01a195144 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -190,6 +190,19 @@ a img { height: 30px; z-index: 100; } + +#editorloadingbox passForm{ + padding:10px; +} + +#editorloadingbox input{ + padding:10px; +} + +#editorloadingbox button{ + padding:10px; +} + #editorcontainerbox { position: absolute; bottom: 0; From 6fe61036325c86ed6e572d0676f1272d67ae1bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Mon, 26 Nov 2012 23:40:31 +0100 Subject: [PATCH 08/37] added languages for translatewiki --- src/locales/zh-hant.ini | 78 ----------------------------------------- src/node/hooks/i18n.js | 4 +-- src/package.json | 52 +++++++++++++-------------- 3 files changed, 28 insertions(+), 106 deletions(-) delete mode 100644 src/locales/zh-hant.ini diff --git a/src/locales/zh-hant.ini b/src/locales/zh-hant.ini deleted file mode 100644 index b76ae1805..000000000 --- a/src/locales/zh-hant.ini +++ /dev/null @@ -1,78 +0,0 @@ -; Exported from translatewiki.net -; Author: Simon Shek -[zh-hant] -index.newPad = 新Pad -index.createOpenPad = 或創建/開啟以下名稱的pad: -pad.toolbar.bold.title = 粗體(Ctrl-B) -pad.toolbar.italic.title = 斜體(Ctrl-I) -pad.toolbar.underline.title = 底線(Ctrl-U) -pad.toolbar.strikethrough.title = 刪除線 -pad.toolbar.ol.title = 有序清單 -pad.toolbar.ul.title = 無序清單 -pad.toolbar.indent.title = 縮排 -pad.toolbar.unindent.title = 凸排 -pad.toolbar.undo.title = 撤銷(Ctrl-Z) -pad.toolbar.redo.title = 重做(Ctrl-Y) -pad.toolbar.clearAuthorship.title = 清除作名顏色 -pad.toolbar.import_export.title = 以其他檔案格式導入/匯出 -pad.toolbar.timeslider.title = 時間軸 -pad.toolbar.savedRevision.title = 已儲存的修訂 -pad.toolbar.settings.title = 設定 -pad.toolbar.embed.title = 嵌入此pad -pad.toolbar.showusers.title = 顯示此pad的用戶 -pad.colorpicker.save = 儲存 -pad.colorpicker.cancel = 取消 -pad.loading = 載入中... -pad.settings.padSettings = Pad設定 -pad.settings.myView = 我的視窗 -pad.settings.stickychat = 永遠在屏幕上顯示聊天 -pad.settings.colorcheck = 作者顏色 -pad.settings.linenocheck = 行號 -pad.settings.fontType = 字體類型: -pad.settings.fontType.normal = 正常 -pad.settings.fontType.monospaced = 等寬 -pad.settings.globalView = 所有人的視窗 -pad.settings.language = 語言: -pad.importExport.import_export = 導入/匯出 -pad.importExport.import = 上載任何文字檔或文檔 -pad.importExport.successful = 完成! -pad.importExport.export = 匯出當前pad為: -pad.importExport.exporthtml = HTML -pad.importExport.exportplain = 純文字 -pad.importExport.exportword = Microsoft Word -pad.importExport.exportpdf = PDF -pad.importExport.exportopen = ODF(開放文件格式) -pad.importExport.exportdokuwiki = DokuWiki -pad.modals.connected = 已連線。 -pad.modals.reconnecting = 重新連接到您的pad... -pad.modals.forcereconnect = 強制重新連線 -pad.modals.uderdup = 在另一個視窗中開啟 -pad.modals.userdup.explanation = 此pad似乎在此電腦上的多個瀏覽器視窗中開啟。 -pad.modals.userdup.advice = 重新連接到此視窗。 -pad.modals.unauth = 未授權 -pad.modals.unauth.explanation = 您的權限在查看此頁時發生更改。請嘗試重新連接。 -pad.modals.looping = 已離線。 -pad.modals.looping.explanation = 與同步伺服器間有通信問題。 -pad.modals.looping.cause = 也許您通過一個不相容的防火牆或代理伺服器連接。 -pad.modals.initsocketfail = 無法訪問伺服器。 -pad.modals.initsocketfail.explanation = 無法連接到同步伺服器。 -pad.modals.initsocketfail.cause = 可能是由於您的瀏覽器或您的互聯網連接的問題。 -pad.modals.slowcommit = 已離線。 -pad.modals.slowcommit.explanation = 伺服器沒有回應。 -pad.modals.slowcommit.cause = 可能是由於網路連接問題。 -pad.modals.deleted = 已刪除。 -pad.modals.deleted.explanation = 此pad已被移除。 -pad.modals.disconnected = 您已中斷連線。 -pad.modals.disconnected.explanation = 伺服器連接曾中斷 -pad.modals.disconnected.cause = 伺服器可能無法使用。若此情況持續發生,請通知我們。 -pad.share = 分享此pad -pad.share.readonly = 唯讀 -pad.share.link = 連結 -pad.share.emebdcode = 嵌入網址 -pad.chat = 聊天 -pad.chat.title = 打開此pad的聊天。 -timeslider.pageTitle = {{appTitle}}時間軸 -timeslider.toolbar.returnbutton = 返回到pad -timeslider.toolbar.authors = 作者: -timeslider.toolbar.authorsList = 無作者 -timeslider.exportCurrent = 匯出當前版本為: diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index 4d42de048..f6f0f8c8d 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -1,4 +1,4 @@ -var languages = require('languages') +var languages = require('languages4translatewiki') , fs = require('fs') , path = require('path') , express = require('express') @@ -9,7 +9,7 @@ var localesPath = __dirname+"/../../locales"; var localeIndex = fs.readFileSync(localesPath+'/en.ini')+'\r\n'; // add language base 'en' to availableLangs -exports.availableLangs = {en: languages.getLanguageInfo('en')} +exports.availableLangs = {en: {name:'English',nativeName:'English',direction:'ltr'}}; fs.readdir(localesPath, function(er, files) { files.forEach(function(locale) { diff --git a/src/package.json b/src/package.json index 8f7620773..24bcdd84c 100644 --- a/src/package.json +++ b/src/package.json @@ -11,32 +11,32 @@ { "name": "Marcel Klehr" } ], "dependencies" : { - "yajsml" : "1.1.6", - "request" : "2.9.100", - "require-kernel" : "1.0.5", - "resolve" : "0.2.x", - "socket.io" : "0.9.x", - "ueberDB" : "0.1.8", - "async" : "0.1.x", - "express" : "3.x", - "connect" : "2.4.x", - "clean-css" : "0.3.2", - "uglify-js" : "1.2.5", - "formidable" : "1.0.9", - "log4js" : "0.5.x", - "jsdom-nocontextifiy" : "0.2.10", - "async-stacktrace" : "0.0.2", - "npm" : "1.1.x", - "npm-registry-client" : "0.2.10", - "ejs" : "0.6.1", - "graceful-fs" : "1.1.5", - "slide" : "1.1.3", - "semver" : "1.0.13", - "security" : "1.0.0", - "tinycon" : "0.0.1", - "underscore" : "1.3.1", - "unorm" : "1.0.0", - "languages" : "0.1.1" + "yajsml" : "1.1.6", + "request" : "2.9.100", + "require-kernel" : "1.0.5", + "resolve" : "0.2.x", + "socket.io" : "0.9.x", + "ueberDB" : "0.1.8", + "async" : "0.1.x", + "express" : "3.x", + "connect" : "2.4.x", + "clean-css" : "0.3.2", + "uglify-js" : "1.2.5", + "formidable" : "1.0.9", + "log4js" : "0.5.x", + "jsdom-nocontextifiy" : "0.2.10", + "async-stacktrace" : "0.0.2", + "npm" : "1.1.x", + "npm-registry-client" : "0.2.10", + "ejs" : "0.6.1", + "graceful-fs" : "1.1.5", + "slide" : "1.1.3", + "semver" : "1.0.13", + "security" : "1.0.0", + "tinycon" : "0.0.1", + "underscore" : "1.3.1", + "unorm" : "1.0.0", + "languages4translatewiki" : "0.1.2" }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": { 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 09/37] 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. From c445197e7fc03572aa31511e35f9193a47332c20 Mon Sep 17 00:00:00 2001 From: John McLear Date: Tue, 27 Nov 2012 15:10:36 +0000 Subject: [PATCH 10/37] Update src/static/css/pad.css --- src/static/css/pad.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 01a195144..a25406144 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -191,7 +191,7 @@ a img { z-index: 100; } -#editorloadingbox passForm{ +#editorloadingbox .passForm{ padding:10px; } From 1cc0e8cbf0d38b4a34674623e329cf9e2379c209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Wed, 28 Nov 2012 03:27:09 +0100 Subject: [PATCH 11/37] Restore original ini file --- src/locales/zh-hant.ini | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/locales/zh-hant.ini diff --git a/src/locales/zh-hant.ini b/src/locales/zh-hant.ini new file mode 100644 index 000000000..b76ae1805 --- /dev/null +++ b/src/locales/zh-hant.ini @@ -0,0 +1,78 @@ +; Exported from translatewiki.net +; Author: Simon Shek +[zh-hant] +index.newPad = 新Pad +index.createOpenPad = 或創建/開啟以下名稱的pad: +pad.toolbar.bold.title = 粗體(Ctrl-B) +pad.toolbar.italic.title = 斜體(Ctrl-I) +pad.toolbar.underline.title = 底線(Ctrl-U) +pad.toolbar.strikethrough.title = 刪除線 +pad.toolbar.ol.title = 有序清單 +pad.toolbar.ul.title = 無序清單 +pad.toolbar.indent.title = 縮排 +pad.toolbar.unindent.title = 凸排 +pad.toolbar.undo.title = 撤銷(Ctrl-Z) +pad.toolbar.redo.title = 重做(Ctrl-Y) +pad.toolbar.clearAuthorship.title = 清除作名顏色 +pad.toolbar.import_export.title = 以其他檔案格式導入/匯出 +pad.toolbar.timeslider.title = 時間軸 +pad.toolbar.savedRevision.title = 已儲存的修訂 +pad.toolbar.settings.title = 設定 +pad.toolbar.embed.title = 嵌入此pad +pad.toolbar.showusers.title = 顯示此pad的用戶 +pad.colorpicker.save = 儲存 +pad.colorpicker.cancel = 取消 +pad.loading = 載入中... +pad.settings.padSettings = Pad設定 +pad.settings.myView = 我的視窗 +pad.settings.stickychat = 永遠在屏幕上顯示聊天 +pad.settings.colorcheck = 作者顏色 +pad.settings.linenocheck = 行號 +pad.settings.fontType = 字體類型: +pad.settings.fontType.normal = 正常 +pad.settings.fontType.monospaced = 等寬 +pad.settings.globalView = 所有人的視窗 +pad.settings.language = 語言: +pad.importExport.import_export = 導入/匯出 +pad.importExport.import = 上載任何文字檔或文檔 +pad.importExport.successful = 完成! +pad.importExport.export = 匯出當前pad為: +pad.importExport.exporthtml = HTML +pad.importExport.exportplain = 純文字 +pad.importExport.exportword = Microsoft Word +pad.importExport.exportpdf = PDF +pad.importExport.exportopen = ODF(開放文件格式) +pad.importExport.exportdokuwiki = DokuWiki +pad.modals.connected = 已連線。 +pad.modals.reconnecting = 重新連接到您的pad... +pad.modals.forcereconnect = 強制重新連線 +pad.modals.uderdup = 在另一個視窗中開啟 +pad.modals.userdup.explanation = 此pad似乎在此電腦上的多個瀏覽器視窗中開啟。 +pad.modals.userdup.advice = 重新連接到此視窗。 +pad.modals.unauth = 未授權 +pad.modals.unauth.explanation = 您的權限在查看此頁時發生更改。請嘗試重新連接。 +pad.modals.looping = 已離線。 +pad.modals.looping.explanation = 與同步伺服器間有通信問題。 +pad.modals.looping.cause = 也許您通過一個不相容的防火牆或代理伺服器連接。 +pad.modals.initsocketfail = 無法訪問伺服器。 +pad.modals.initsocketfail.explanation = 無法連接到同步伺服器。 +pad.modals.initsocketfail.cause = 可能是由於您的瀏覽器或您的互聯網連接的問題。 +pad.modals.slowcommit = 已離線。 +pad.modals.slowcommit.explanation = 伺服器沒有回應。 +pad.modals.slowcommit.cause = 可能是由於網路連接問題。 +pad.modals.deleted = 已刪除。 +pad.modals.deleted.explanation = 此pad已被移除。 +pad.modals.disconnected = 您已中斷連線。 +pad.modals.disconnected.explanation = 伺服器連接曾中斷 +pad.modals.disconnected.cause = 伺服器可能無法使用。若此情況持續發生,請通知我們。 +pad.share = 分享此pad +pad.share.readonly = 唯讀 +pad.share.link = 連結 +pad.share.emebdcode = 嵌入網址 +pad.chat = 聊天 +pad.chat.title = 打開此pad的聊天。 +timeslider.pageTitle = {{appTitle}}時間軸 +timeslider.toolbar.returnbutton = 返回到pad +timeslider.toolbar.authors = 作者: +timeslider.toolbar.authorsList = 無作者 +timeslider.exportCurrent = 匯出當前版本為: From 9ec8a6e3d38bde94a3bc52daa16bb1588157f67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Wed, 28 Nov 2012 04:02:55 +0100 Subject: [PATCH 12/37] back to globalize... don't work :S --- src/node/hooks/i18n.js | 11 +++++++---- src/package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index f6f0f8c8d..147ef5335 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -1,4 +1,4 @@ -var languages = require('languages4translatewiki') +var Globalize = require('globalize') , fs = require('fs') , path = require('path') , express = require('express') @@ -9,7 +9,8 @@ var localesPath = __dirname+"/../../locales"; var localeIndex = fs.readFileSync(localesPath+'/en.ini')+'\r\n'; // add language base 'en' to availableLangs -exports.availableLangs = {en: {name:'English',nativeName:'English',direction:'ltr'}}; +exports.availableLangs = {}; +exports.availableLangs['en'] = Globalize.cultures['en']; fs.readdir(localesPath, function(er, files) { files.forEach(function(locale) { @@ -19,11 +20,13 @@ fs.readdir(localesPath, function(er, files) { // build locale index localeIndex += '['+locale+']\r\n@import url(locales/'+locale+'.ini)\r\n' - // add info language {name, nativeName, direction} to availableLangs - exports.availableLangs[locale]=languages.getLanguageInfo(locale); + require('globalize/lib/cultures/globalize.culture.'+locale+'.js') + exports.availableLangs[locale]=Globalize.cultures[locale]; }) }) +console.log(exports.availableLangs); + exports.expressCreateServer = function(n, args) { args.app.use('/locales', express.static(localesPath)); diff --git a/src/package.json b/src/package.json index 24bcdd84c..2bc5ac22e 100644 --- a/src/package.json +++ b/src/package.json @@ -36,7 +36,7 @@ "tinycon" : "0.0.1", "underscore" : "1.3.1", "unorm" : "1.0.0", - "languages4translatewiki" : "0.1.2" + "globalize" : "0.1.1" }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": { From 795a20b3f24b122acc356e6ecd29b76a6cd09bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Wed, 28 Nov 2012 23:54:23 +0100 Subject: [PATCH 13/37] get languages availables through translatewiki API --- src/node/hooks/i18n.js | 47 ++++++++++++++++++++++++++++-------------- src/package.json | 3 +-- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index 147ef5335..3589dfb29 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -1,4 +1,4 @@ -var Globalize = require('globalize') +var http = require ('http') , fs = require('fs') , path = require('path') , express = require('express') @@ -8,24 +8,39 @@ var localesPath = __dirname+"/../../locales"; // Serve English strings directly with /locales.ini var localeIndex = fs.readFileSync(localesPath+'/en.ini')+'\r\n'; -// add language base 'en' to availableLangs -exports.availableLangs = {}; -exports.availableLangs['en'] = Globalize.cultures['en']; +exports.availableLangs = {'en': {'nativeName': 'English'}}; -fs.readdir(localesPath, function(er, files) { - files.forEach(function(locale) { - locale = locale.split('.')[0] - if(locale.toLowerCase() == 'en') return; +// build availableLangs with translatewiki web API +var request = http.request ('http://translatewiki.net/w/api.php?action=query&meta=siteinfo&siprop=languages&format=json', + function (res) { + var twLangs = ''; + res.setEncoding ('utf8'); + res.on ('data', function (chunk) { twLangs += chunk; }); + res.on ('end', function () { + // twLangs = [{code: 'en', '*': 'English'}...] + twLangs = JSON.parse(twLangs)['query']['languages']; - // build locale index - localeIndex += '['+locale+']\r\n@import url(locales/'+locale+'.ini)\r\n' + fs.readdir(localesPath, function(er, files) { + files.forEach(function(locale) { + locale = locale.split('.')[0]; + if(locale.toLowerCase() == 'en') return; + + // build locale index + localeIndex += '['+locale+']\r\n@import url(locales/'+locale+'.ini)\r\n'; - require('globalize/lib/cultures/globalize.culture.'+locale+'.js') - exports.availableLangs[locale]=Globalize.cultures[locale]; - }) -}) - -console.log(exports.availableLangs); + for (var l = 0; l < twLangs.length; l++) { + var code = twLangs[l]['code']; + if (locale == code) { + var nativeName = twLangs[l]['*']; + exports.availableLangs[code] = {'nativeName': nativeName}; + } + } + }); + }); + }); + }).on ('error', function(e) { + console.error('While query translatewiki API: '+e.message); + }).end(); exports.expressCreateServer = function(n, args) { diff --git a/src/package.json b/src/package.json index 2bc5ac22e..e68053534 100644 --- a/src/package.json +++ b/src/package.json @@ -35,8 +35,7 @@ "security" : "1.0.0", "tinycon" : "0.0.1", "underscore" : "1.3.1", - "unorm" : "1.0.0", - "globalize" : "0.1.1" + "unorm" : "1.0.0" }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": { From 3cdf66c2f77d6aa57f38635492464ecc4a2059f7 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 2 Dec 2012 17:03:56 +0000 Subject: [PATCH 14/37] first effort to move into templates but javascript is broken so dont pull --- src/static/css/pad.css | 13 +++++++++++++ src/static/js/pad.js | 25 +++++++++++++++++-------- src/templates/pad.html | 14 +++++++++++++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 01a195144..6f96b92d6 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -22,6 +22,7 @@ iframe { .readonly .acl-write { display: none; } + #users { background: #f7f7f7; background: -webkit-linear-gradient( #F7F7F7,#EEE); @@ -891,3 +892,15 @@ input[type=checkbox] { line-height: 24px } } + +#passwordRequired{ + display:none; +} + +#permissionDenied{ + display:none; +} + +#wrongPassword{ + display:none; +} diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 936298abc..bfe8bf8c1 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -298,30 +298,39 @@ function handshake() //the access was not granted, give the user a message if(!receivedClientVars && obj.accessStatus) { + $('.passForm').submit(function(){ + // THIS BIT DOESNT WORK + alert("I AM BROKEN"); + padutils.escapeHtml('require('+JSON.stringify(module.id)).savePassword(); + }); + if(obj.accessStatus == "deny") { - $("#editorloadingbox").html("You do not have permission to access this pad"); + $('#loading').hide(); + $("#permissionDenied").show()); } else if(obj.accessStatus == "needPassword") { - $("#editorloadingbox").html("You need a password to access this pad
" + +/* $("#editorloadingbox").html("You need a password to access this pad
" + ""+ ""); $("#passwordinput").focus(); $(".passForm").submit(function(){ $('.passForm button').click(); }); +*/ + $('#loading').hide(); + $('#passwordRequired').show(); + $("#passwordinput").focus(); } else if(obj.accessStatus == "wrongPassword") { - $("#editorloadingbox").html("Your password was wrong
" + - ""+ - ""); + $('#loading').hide(); + $('#wrongPassword').show(); $("#passwordinput").focus(); - $(".passForm").submit(function(){ - $('.passForm button').click(); - }); + } + } //if we haven't recieved the clientVars yet, then this message should it be diff --git a/src/templates/pad.html b/src/templates/pad.html index 3f3eee4f1..402d90034 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -184,7 +184,19 @@
-

Loading...

+
+

You need a password to access this pad

+ + + +
+
+

You do not have permission to access this pad

+
+
+

Your password was wrong

+
+

Loading...

From 8a9045b3358ea6b60cdb7d9d8e19ed0cb545d950 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 2 Dec 2012 18:33:31 +0000 Subject: [PATCH 15/37] remove ssl not enabled message --- src/node/hooks/express.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index 2bbb5eec8..033bd5e36 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -66,8 +66,6 @@ exports.restartServer = function () { } else { - console.log( "SSL -- not enabled!" ); - var http = require('http'); server = http.createServer(app); } From b5c263dd37829afc63c0e1ea572954094c4be062 Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 01:41:01 +0000 Subject: [PATCH 16/37] improve search to use description too, bit more cpu heavy for thats okay --- src/static/js/pluginfw/installer.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/static/js/pluginfw/installer.js b/src/static/js/pluginfw/installer.js index d668e549e..e491f0771 100644 --- a/src/static/js/pluginfw/installer.js +++ b/src/static/js/pluginfw/installer.js @@ -91,9 +91,12 @@ exports.search = function(query, cache, cb) { if (er) return cb(er); var res = {}; var i = 0; - for (key in data) { + for (key in data) { // for every plugin in the data from npm if ( key.indexOf(plugins.prefix) == 0 - && key.indexOf(query.pattern) != -1) { + && key.indexOf(query.pattern) != -1 + || key.indexOf(plugins.prefix) == 0 + && data[key].description.indexOf(query.pattern) != -1 + ) { // If the name contains ep_ and the search string is in the name or description i++; if (i > query.offset && i <= query.offset + query.limit) { From 84d154b168f792bd6c95aa9c78df8ddc0d867805 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 3 Dec 2012 11:35:06 +0000 Subject: [PATCH 17/37] Update strings, add UK strings, fix JS --- src/locales/en.ini | 3 +++ src/static/js/pad.js | 12 +----------- src/templates/pad.html | 6 +++--- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/locales/en.ini b/src/locales/en.ini index e542594da..225b16cf3 100644 --- a/src/locales/en.ini +++ b/src/locales/en.ini @@ -21,6 +21,9 @@ pad.toolbar.showusers.title = Show the users on this pad pad.colorpicker.save = Save pad.colorpicker.cancel = Cancel pad.loading = Loading... +pad.passwordRequired = You need a password to access this pad +pad.permissionDenied = You do not have permission to access this pad +pad.wrongPassword = Your password was wrong pad.settings.padSettings = Pad Settings pad.settings.myView = My View pad.settings.stickychat = Chat always on screen diff --git a/src/static/js/pad.js b/src/static/js/pad.js index bfe8bf8c1..aef06eff9 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -299,9 +299,7 @@ function handshake() if(!receivedClientVars && obj.accessStatus) { $('.passForm').submit(function(){ - // THIS BIT DOESNT WORK - alert("I AM BROKEN"); - padutils.escapeHtml('require('+JSON.stringify(module.id)).savePassword(); + require(module.id).savePassword(); }); if(obj.accessStatus == "deny") @@ -311,14 +309,6 @@ function handshake() } else if(obj.accessStatus == "needPassword") { -/* $("#editorloadingbox").html("You need a password to access this pad
" + - "
"+ - ""); - $("#passwordinput").focus(); - $(".passForm").submit(function(){ - $('.passForm button').click(); - }); -*/ $('#loading').hide(); $('#passwordRequired').show(); $("#passwordinput").focus(); diff --git a/src/templates/pad.html b/src/templates/pad.html index e37163e19..d9c6be466 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -185,16 +185,16 @@
-

You need a password to access this pad

+

You need a password to access this pad

-

You do not have permission to access this pad

+

You do not have permission to access this pad

-

Your password was wrong

+

Your password was wrong

Loading...

From b0463bd7d5c64b25cff95718e9b529320a10586e Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 11:41:51 +0000 Subject: [PATCH 18/37] whoopsi --- src/static/js/pad.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index aef06eff9..54d442787 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -298,14 +298,12 @@ function handshake() //the access was not granted, give the user a message if(!receivedClientVars && obj.accessStatus) { - $('.passForm').submit(function(){ - require(module.id).savePassword(); - }); + $('.passForm').submit(pad.savePassword); if(obj.accessStatus == "deny") { $('#loading').hide(); - $("#permissionDenied").show()); + $("#permissionDenied").show(); } else if(obj.accessStatus == "needPassword") { @@ -318,9 +316,7 @@ function handshake() $('#loading').hide(); $('#wrongPassword').show(); $("#passwordinput").focus(); - } - } //if we haven't recieved the clientVars yet, then this message should it be From 4843840d72095229e022b81629fb6639ef201946 Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 11:44:30 +0000 Subject: [PATCH 19/37] last JS fix --- src/static/js/pad.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 54d442787..316802bf3 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -298,7 +298,7 @@ function handshake() //the access was not granted, give the user a message if(!receivedClientVars && obj.accessStatus) { - $('.passForm').submit(pad.savePassword); + $('.passForm').submit(require(module.id).savePassword); if(obj.accessStatus == "deny") { From d09894ce779e1b55970514d1318119dd2485da44 Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 12:05:11 +0000 Subject: [PATCH 20/37] make it show password dialog on wrong password --- src/static/js/pad.js | 1 + src/static/js/pad_utils.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 316802bf3..d380a8dcf 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -315,6 +315,7 @@ function handshake() { $('#loading').hide(); $('#wrongPassword').show(); + $('#passwordRequired').show(); $("#passwordinput").focus(); } } diff --git a/src/static/js/pad_utils.js b/src/static/js/pad_utils.js index 83ee9aae8..f752722f3 100644 --- a/src/static/js/pad_utils.js +++ b/src/static/js/pad_utils.js @@ -52,7 +52,17 @@ function createCookie(name, value, days, path) if(!path) path = "/"; - document.cookie = name + "=" + value + expires + "; path=" + path; + if(!path) + path = "/"; + + //Check if the browser is IE and if so make sure the full path is set in the cookie + if(navigator.appName=='Microsoft Internet Explorer'){ + document.cookie = name + "=" + value + expires + "; path="+document.location; + } + else{ + document.cookie = name + "=" + value + expires + "; path=" + path; + } + } function readCookie(name) From 0b92fdfc628656f9d7b562d62733778f144e65d9 Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 12:47:11 +0000 Subject: [PATCH 21/37] fix IE auth but only a temp fix --- src/static/js/pad_utils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/static/js/pad_utils.js b/src/static/js/pad_utils.js index f752722f3..59c3d4190 100644 --- a/src/static/js/pad_utils.js +++ b/src/static/js/pad_utils.js @@ -52,8 +52,9 @@ function createCookie(name, value, days, path) if(!path) path = "/"; - if(!path) - path = "/"; + // This fixes an issue with IE not wanting to store cookies for Auth #1234. It's a temp fix because + // Really we should be storing the cookie on teh document.location path and not modifying the fsking URL to contain a password! + document.cookie = name + "=" + value + expires + "; path=" + "/"; //Check if the browser is IE and if so make sure the full path is set in the cookie if(navigator.appName=='Microsoft Internet Explorer'){ From b3e55f64a86951ddd25243c4b593cf61ec109c4c Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 13:10:32 +0000 Subject: [PATCH 22/37] stop password being clearly visible --- src/static/js/pad.js | 1 + src/static/js/pad_utils.js | 2 +- src/templates/pad.html | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index d380a8dcf..cace9bf76 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -202,6 +202,7 @@ function savePassword() createCookie("password",$("#passwordinput").val(),null,document.location.pathname); //reload document.location=document.location; + return false; } function handshake() diff --git a/src/static/js/pad_utils.js b/src/static/js/pad_utils.js index 59c3d4190..7c97b035a 100644 --- a/src/static/js/pad_utils.js +++ b/src/static/js/pad_utils.js @@ -54,7 +54,7 @@ function createCookie(name, value, days, path) // This fixes an issue with IE not wanting to store cookies for Auth #1234. It's a temp fix because // Really we should be storing the cookie on teh document.location path and not modifying the fsking URL to contain a password! - document.cookie = name + "=" + value + expires + "; path=" + "/"; + // document.cookie = name + "=" + value + expires + "; path=" + "/"; //Check if the browser is IE and if so make sure the full path is set in the cookie if(navigator.appName=='Microsoft Internet Explorer'){ diff --git a/src/templates/pad.html b/src/templates/pad.html index 896a62f67..a392980a6 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -186,7 +186,7 @@

You need a password to access this pad

-
+
From 1e8d954560bc7e475d73ce9e4df82ffeb2492c80 Mon Sep 17 00:00:00 2001 From: John McLear Date: Mon, 3 Dec 2012 14:28:25 +0000 Subject: [PATCH 23/37] best I can do with this temporary fix for IE --- src/static/js/pad.js | 10 ++++++---- src/static/js/pad_utils.js | 16 +++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index cace9bf76..9ad701b38 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -51,18 +51,20 @@ var randomString = require('./pad_utils').randomString; var hooks = require('./pluginfw/hooks'); -function createCookie(name, value, days, path) -{ +function createCookie(name, value, days, path){ /* Warning Internet Explorer doesn't use this it uses the one from pad_utils.js */ if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); var expires = "; expires=" + date.toGMTString(); } - else var expires = ""; + else{ + var expires = ""; + } - if(!path) + if(!path){ // If the path isn't set then just whack the cookie on the root path path = "/"; + } //Check if the browser is IE and if so make sure the full path is set in the cookie if(navigator.appName=='Microsoft Internet Explorer'){ diff --git a/src/static/js/pad_utils.js b/src/static/js/pad_utils.js index 7c97b035a..82f7fcada 100644 --- a/src/static/js/pad_utils.js +++ b/src/static/js/pad_utils.js @@ -39,26 +39,24 @@ function randomString(len) return randomstring; } -function createCookie(name, value, days, path) -{ +function createCookie(name, value, days, path){ /* Used by IE */ if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); var expires = "; expires=" + date.toGMTString(); } - else var expires = ""; + else{ + var expires = ""; + } - if(!path) + if(!path){ // IF the Path of the cookie isn't set then just create it on root path = "/"; - - // This fixes an issue with IE not wanting to store cookies for Auth #1234. It's a temp fix because - // Really we should be storing the cookie on teh document.location path and not modifying the fsking URL to contain a password! - // document.cookie = name + "=" + value + expires + "; path=" + "/"; + } //Check if the browser is IE and if so make sure the full path is set in the cookie if(navigator.appName=='Microsoft Internet Explorer'){ - document.cookie = name + "=" + value + expires + "; path="+document.location; + document.cookie = name + "=" + value + expires + "; path=/"; /* Note this bodge fix for IE is temporary until auth is rewritten */ } else{ document.cookie = name + "=" + value + expires + "; path=" + path; From 5f949b8457154d5b75a79765565977e8cbdf1e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Tue, 4 Dec 2012 12:12:58 +0100 Subject: [PATCH 24/37] Update language4translatewiki 0.1.3 --- src/node/hooks/i18n.js | 43 +++++++++++++----------------------------- src/package.json | 3 ++- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index 3589dfb29..882e51569 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -1,4 +1,4 @@ -var http = require ('http') +var languages = require('languages4translatewiki') , fs = require('fs') , path = require('path') , express = require('express') @@ -10,37 +10,20 @@ var localeIndex = fs.readFileSync(localesPath+'/en.ini')+'\r\n'; exports.availableLangs = {'en': {'nativeName': 'English'}}; -// build availableLangs with translatewiki web API -var request = http.request ('http://translatewiki.net/w/api.php?action=query&meta=siteinfo&siprop=languages&format=json', - function (res) { - var twLangs = ''; - res.setEncoding ('utf8'); - res.on ('data', function (chunk) { twLangs += chunk; }); - res.on ('end', function () { - // twLangs = [{code: 'en', '*': 'English'}...] - twLangs = JSON.parse(twLangs)['query']['languages']; +fs.readdir(localesPath, function(er, files) { + files.forEach(function(locale) { + var ext = path.extname(locale); + locale = path.basename(locale, ext).toLowerCase(); + if(locale == 'en' || ext != '.ini') return; - fs.readdir(localesPath, function(er, files) { - files.forEach(function(locale) { - locale = locale.split('.')[0]; - if(locale.toLowerCase() == 'en') return; - - // build locale index - localeIndex += '['+locale+']\r\n@import url(locales/'+locale+'.ini)\r\n'; + // build locale index + localeIndex += '['+locale+']\r\n@import url(locales/'+locale+'.ini)\r\n' - for (var l = 0; l < twLangs.length; l++) { - var code = twLangs[l]['code']; - if (locale == code) { - var nativeName = twLangs[l]['*']; - exports.availableLangs[code] = {'nativeName': nativeName}; - } - } - }); - }); - }); - }).on ('error', function(e) { - console.error('While query translatewiki API: '+e.message); - }).end(); + // add info language {nativeName, direction} to availableLangs + exports.availableLangs[locale]=languages.getLanguageInfo(locale); + }) +}) + exports.expressCreateServer = function(n, args) { diff --git a/src/package.json b/src/package.json index e68053534..d2b03a97a 100644 --- a/src/package.json +++ b/src/package.json @@ -35,7 +35,8 @@ "security" : "1.0.0", "tinycon" : "0.0.1", "underscore" : "1.3.1", - "unorm" : "1.0.0" + "unorm" : "1.0.0", + "languages4translatewiki" : "0.1.3" }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": { From a2b22652ceee934682f84bffa43d3b6d0df27fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Eixarch?= Date: Tue, 4 Dec 2012 13:02:23 +0100 Subject: [PATCH 25/37] added direction language in English --- src/node/hooks/i18n.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index 882e51569..a45d46fee 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -8,7 +8,7 @@ var localesPath = __dirname+"/../../locales"; // Serve English strings directly with /locales.ini var localeIndex = fs.readFileSync(localesPath+'/en.ini')+'\r\n'; -exports.availableLangs = {'en': {'nativeName': 'English'}}; +exports.availableLangs = {'en': {'nativeName': 'English', 'direction': 'ltr'}}; fs.readdir(localesPath, function(er, files) { files.forEach(function(locale) { From 1fc5519c86dd95136471149e0ae99a4c0c5ca4e2 Mon Sep 17 00:00:00 2001 From: 0ip Date: Tue, 4 Dec 2012 14:30:30 +0100 Subject: [PATCH 26/37] Display plugin versions --- src/static/js/admin/plugins.js | 4 ++++ src/templates/admin/plugins.html | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index 93acf6ea5..a279498f4 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -113,10 +113,14 @@ $(document).ready(function () { for (plugin_name in data.results) { var plugin = data.results[plugin_name]; var row = widget.find(".template tr").clone(); + var version = '0.0.0'; + for (version in data.results[plugin_name].versions) break; for (attr in plugin) { row.find("." + attr).html(plugin[attr]); } + row.find(".version").html(version); + widget.find(".results").append(row); } diff --git a/src/templates/admin/plugins.html b/src/templates/admin/plugins.html index 3dad3bd01..394cf0e06 100644 --- a/src/templates/admin/plugins.html +++ b/src/templates/admin/plugins.html @@ -30,6 +30,7 @@ Name Description + Version @@ -37,6 +38,7 @@ + @@ -58,6 +60,7 @@ Name Description + Version @@ -65,6 +68,7 @@ + From 20f13bc8cedb3721d64af6da9214df150959218c Mon Sep 17 00:00:00 2001 From: 0ip Date: Tue, 4 Dec 2012 19:08:25 +0100 Subject: [PATCH 27/37] Add comment to explain how the property containing the version is being read --- src/static/js/admin/plugins.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index a279498f4..618520282 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -114,6 +114,7 @@ $(document).ready(function () { var plugin = data.results[plugin_name]; var row = widget.find(".template tr").clone(); var version = '0.0.0'; + // hack to access "versions" property of the npm package object for (version in data.results[plugin_name].versions) break; for (attr in plugin) { From 8d0ef88baf3fc815916cef66b8636060209bdb33 Mon Sep 17 00:00:00 2001 From: 0ip Date: Wed, 5 Dec 2012 12:55:48 +0100 Subject: [PATCH 28/37] Adjust select width looks better :) --- src/static/css/pad.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 9897a303b..bb8da99b6 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -774,7 +774,7 @@ input[type=checkbox] { border-radius: 3px; border: 1px solid #ccc; outline: none; - min-width: 105px; + width: 120px; } .column { float: left; From 377ff1eadeed90bd1295597df996a575840254c9 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Wed, 5 Dec 2012 14:04:48 +0100 Subject: [PATCH 29/37] Fix #1219: Make api work if requireAuth is enabled --- src/node/hooks/express/webaccess.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 41bf38805..50323ef6f 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -15,8 +15,8 @@ exports.basicAuth = function (req, res, next) { } var authorize = function (cb) { - // Do not require auth for static paths...this could be a bit brittle - if (req.path.match(/^\/(static|javascripts|pluginfw)/)) return cb(true); + // Do not require auth for static paths and the API...this could be a bit brittle + if (req.path.match(/^\/(static|javascripts|pluginfw|api)/)) return cb(true); if (req.path.indexOf('/admin') != 0) { if (!settings.requireAuthentication) return cb(true); From fe89a367cc02063586571ce64964bc691a4ac542 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Wed, 5 Dec 2012 14:16:44 +0100 Subject: [PATCH 30/37] Fix #1226: Chrome would load async js --- src/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/index.html b/src/templates/index.html index 9fd33a26a..961c6012a 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -41,7 +41,7 @@ if(language) document.documentElement.lang = language[1]; })(document) - +