This commit is contained in:
Iván Eixarch 2012-11-23 14:08:41 -08:00
commit 7578dad7bd
12 changed files with 101 additions and 115 deletions

View file

@ -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

View file

@ -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

View file

@ -18,59 +18,48 @@
* 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
*/
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,42 +69,31 @@ 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){
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);
@ -124,13 +102,15 @@ exports.doImport = function(req, res, padId)
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
{
if(os.type().indexOf("Windows") > -1){
setTimeout(function() {callback();}, 100);
} else {
callback();
}
});
},
//change text of the pad and broadcast the changeset
function(callback)
{
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

View file

@ -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)";

View file

@ -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);
});

View file

@ -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 <petermartischka@googlemail.com> - Primary Technology Ltd",
"contributors" : [

View file

@ -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
*/
/*

View file

@ -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");
}
}

View file

@ -310,7 +310,7 @@ function handshake()
}
else if(obj.accessStatus == "wrongPassword")
{
$("#editorloadingbox").html("<b>You're password was wrong</b><br>" +
$("#editorloadingbox").html("<b>Your password was wrong</b><br>" +
"<input id='passwordinput' type='password' name='password'>"+
"<button type='button' onclick=\"" + padutils.escapeHtml('require('+JSON.stringify(module.id)+").savePassword()") + "\">ok</button>");
}

View file

@ -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")
{

View file

@ -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 {

View file

@ -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,7 +30,9 @@ 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();
@ -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