diff --git a/bin/loadTesting/README b/bin/loadTesting/README index 297756f9d..6a7786644 100644 --- a/bin/loadTesting/README +++ b/bin/loadTesting/README @@ -3,7 +3,7 @@ This load tester is extremely useful for testing how many dormant clients can co TODO: Emulate characters being typed into a pad -HOW TO USE (from @mjd75) proper formatting at: https://github.com/Pita/etherpad-lite/issues/360 +HOW TO USE (from @mjd75) proper formatting at: https://github.com/ether/etherpad-lite/issues/360 Server 1: Installed Node.js (etc), EtherPad Lite and MySQL diff --git a/doc/api/http_api.md b/doc/api/http_api.md index 990d1b498..7ace1b0b7 100644 --- a/doc/api/http_api.md +++ b/doc/api/http_api.md @@ -9,7 +9,7 @@ The API gives another web application control of the pads. The basic functions a The API is designed in a way, so you can reuse your existing user system with their permissions, and map it to etherpad lite. Means: Your web application still has to do authentication, but you can tell etherpad lite via the api, which visitors should get which permissions. This allows etherpad lite to fit into any web application and extend it with real-time functionality. You can embed the pads via an iframe into your website. -Take a look at [HTTP API client libraries](https://github.com/Pita/etherpad-lite/wiki/HTTP-API-client-libraries) to see if a library in your favorite language. +Take a look at [HTTP API client libraries](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) to see if a library in your favorite language. ## Examples diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 788706ce7..93fd3db5b 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -18,26 +18,20 @@ * 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"); +var ERR = require("async-stacktrace") + , padManager = require("../db/PadManager") + , padMessageHandler = require("./PadMessageHandler") + , async = require("async") + , fs = require("fs") + , path = require("path") + , 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"); - -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 @@ -45,32 +39,27 @@ if(os.type().indexOf("Windows") > -1) 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(); @@ -80,57 +69,48 @@ 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; - } - } + function(callback) { + 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) - { + if(fileEndingKnown) { callback(); } //we need to rename this file with a .txt ending - else - { + 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 - function(callback) - { + //convert file to html + function(callback) { var randNum = Math.floor(Math.random()*0xFFFFFFFF); - destFile = tempDirectory + "eplite_import_" + randNum + ".txt"; - abiword.convertFile(srcFile, destFile, "txt", 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 - function(callback) - { - padManager.getPad(padId, function(err, _pad) - { + function(callback) { + padManager.getPad(padId, function(err, _pad){ if(ERR(err, callback)) return; pad = _pad; callback(); @@ -138,52 +118,47 @@ 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 - { - callback(); - } + 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); + function(callback) { + 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) - { + function(callback) { + //for node < 0.7 compatible + var fileExists = fs.exists || path.exists; async.parallel([ - function(callback) - { - fs.unlink(srcFile, callback); + function(callback){ + fileExists (srcFile, function(exist) { (exist)? fs.unlink(srcFile, callback): callback(); }); }, - function(callback) - { - fs.unlink(destFile, callback); + function(callback){ + fileExists (destFile, function(exist) { (exist)? fs.unlink(destFile, callback): callback(); }); } ], callback); } - ], function(err) - { + ], function(err) { + var status = "ok"; //check for known errors and replace the status diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index eb3f6188a..1900a86a8 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -26,7 +26,7 @@ exports.createServer = function () { { console.warn("Can't get git version for server header\n" + e.message) } - console.log("Report bugs at https://github.com/Pita/etherpad-lite/issues") + console.log("Report bugs at https://github.com/ether/etherpad-lite/issues") serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)"; 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/package.json b/src/package.json index 8c95c4d34..8f7620773 100644 --- a/src/package.json +++ b/src/package.json @@ -1,7 +1,7 @@ { "name" : "ep_etherpad-lite", "description" : "A Etherpad based on node.js", - "homepage" : "https://github.com/Pita/etherpad-lite", + "homepage" : "https://github.com/ether/etherpad-lite", "keywords" : ["etherpad", "realtime", "collaborative", "editor"], "author" : "Peter 'Pita' Martischka - Primary Technology Ltd", "contributors" : [ diff --git a/src/static/js/AttributePool.js b/src/static/js/AttributePool.js index f5990c07d..96ea9b0da 100644 --- a/src/static/js/AttributePool.js +++ b/src/static/js/AttributePool.js @@ -3,7 +3,7 @@ * 90% of the code is still like in the original Etherpad * Look at https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js * You can find a explanation what a attribute pool is here: - * https://github.com/Pita/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt + * https://github.com/ether/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt */ /* diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 2e56b950f..661ea0119 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -3266,7 +3266,7 @@ function Ace2Inner(){ } } //hide the dropdownso - if(window.parent.parent.padeditbar){ // required in case its in an iframe should probably use parent.. See Issue 327 https://github.com/Pita/etherpad-lite/issues/327 + if(window.parent.parent.padeditbar){ // required in case its in an iframe should probably use parent.. See Issue 327 https://github.com/ether/etherpad-lite/issues/327 window.parent.parent.padeditbar.toggleDropDown("none"); } } diff --git a/src/static/js/pad.js b/src/static/js/pad.js index b665c2fbd..34f2a2877 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -310,7 +310,7 @@ function handshake() } else if(obj.accessStatus == "wrongPassword") { - $("#editorloadingbox").html("You're password was wrong
" + + $("#editorloadingbox").html("Your password was wrong
" + ""+ ""); } 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") { diff --git a/tests/frontend/runner.css b/tests/frontend/runner.css index 0e4b5fd13..7d5bb7838 100644 --- a/tests/frontend/runner.css +++ b/tests/frontend/runner.css @@ -15,12 +15,15 @@ body { #iframe-container { width: 50%; height: 100%; - float:right; } #iframe-container iframe { - width: 100%; height: 100%; + position:absolute; + min-width:500px; + max-width:800px; + left:50%; + width:100%; } #mocha { diff --git a/tests/frontend/specs/language.js b/tests/frontend/specs/language.js index 87d04220c..7d294282c 100644 --- a/tests/frontend/specs/language.js +++ b/tests/frontend/specs/language.js @@ -1,10 +1,19 @@ +function deletecookie(name) { + document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; +} + describe("Language select and change", function(){ + // Destroy language cookies + deletecookie("language", null); + //create a new pad before each test run beforeEach(function(cb){ helper.newPad(cb); this.timeout(60000); }); + // Destroy language cookies + it("makes text german", function(done) { var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; @@ -21,14 +30,16 @@ describe("Language select and change", function(){ $languageoption.attr('selected','selected'); $language.change(); - helper.waitFor(function() { return $language.val() == "de"}) + helper.waitFor(function() { + return chrome$(".buttonicon-bold").parent()[0]["title"] = "Fett (Strg-B)"; + }) .done(function(){ //get the value of the bold button var $boldButton = chrome$(".buttonicon-bold").parent(); //get the title of the bold button var boldButtonTitle = $boldButton[0]["title"]; - + //check if the language is now german expect(boldButtonTitle).to.be("Fett (Strg-B)"); done(); @@ -51,7 +62,10 @@ describe("Language select and change", function(){ $languageoption.attr('selected','selected'); $language.change(); - helper.waitFor(function() { return $language.val() == "en";}) + //get the value of the bold button + var $boldButton = chrome$(".buttonicon-bold").parent(); + + helper.waitFor(function() { return $boldButton[0]["title"] != "Fett (Strg-B)";}) .done(function(){ //get the value of the bold button @@ -67,4 +81,4 @@ describe("Language select and change", function(){ }); }); -}); \ No newline at end of file +});