diff --git a/.gitignore b/.gitignore index 25c577ec..29835e6f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ node_modules settings.json static/js/jquery.min.js APIKEY.txt +bin/abiword.exe +bin/node.exe +etherpad-lite-win.zip +var/dirty.db diff --git a/README.md b/README.md index c752fe99..232c29c7 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,16 @@ Visit to test it live.
You can find the same ins # Installation + +# Windows + +1. Download +2. Extract the file +3. Open the extracted folder and double click `start.bat` +4. Open your web browser and browse to + +# Linux + **As root:**
    @@ -46,7 +56,7 @@ Visit to test it live.
    You can find the same ins **As any user (we recommend creating a separate user called etherpad-lite):**
      -
    1. Clone the git repository git clone 'git://github.com/Pita/etherpad-lite.git'
       
    2. +
    3. Move to a folder where you want to install Etherpad Lite. Clone the git repository git clone 'git://github.com/Pita/etherpad-lite.git'
       
    4. Install the dependencies with bin/installDeps.sh (if you have problems at this step, look at the section Troubleshooting below)
       
    5. Start it with bin/run.sh
       
    6. Open your web browser and visit http://localhost:9001. You like it? Look at the 'Next Steps' section below
    7. diff --git a/bin/buildForWindows.sh b/bin/buildForWindows.sh new file mode 100755 index 00000000..faad735e --- /dev/null +++ b/bin/buildForWindows.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +NODE_VERSION="0.5.4" + +#Move to the folder where ep-lite is installed +cd `dirname $0` + +#Was this script started in the bin folder? if yes move out +if [ -d "../bin" ]; then + cd "../" +fi + +#Is wget installed? +hash wget > /dev/null 2>&1 || { + echo "Please install wget" >&2 + exit 1 +} + +#Is zip installed? +hash zip > /dev/null 2>&1 || { + echo "Please install zip" >&2 + exit 1 +} + +#Is zip installed? +hash unzip > /dev/null 2>&1 || { + echo "Please install unzip" >&2 + exit 1 +} + +START_FOLDER=$(pwd); + +echo "create a clean enviroment in /tmp/etherpad-lite-win..." +rm -rf /tmp/etherpad-lite-win +cp -ar . /tmp/etherpad-lite-win +cd /tmp/etherpad-lite-win +rm -rf node_modules +rm -f etherpad-lite-win.zip + +echo "do a normal unix install first..." +bin/installDeps.sh || exit 1 + +echo "copy the windows settings template..." +cp settings.json.template_windows settings.json + +echo "resolve symbolic links..." +cp -rL node_modules node_modules_resolved +rm -rf node_modules +mv node_modules_resolved node_modules + +echo "remove sqlite, cause we can't use it with windows..." +rm -rf node_modules/ueberDB/node_modules/sqlite3 + +echo "replace log4js with a patched log4js, this log4js runs on windows too..." +rm -rf node_modules/log4js/* +wget https://github.com/Pita/log4js-node/zipball/master -O log4js.zip +unzip log4js.zip +mv Pita-log4js-node*/* node_modules/log4js +rm -rf log4js.zip Pita-log4js-node* + +echo "download windows node..." +cd bin +wget "http://nodejs.org/dist/v$NODE_VERSION/node.exe" -O node.exe + +echo "create the zip..." +cd /tmp +zip -9 -r etherpad-lite-win.zip etherpad-lite-win +mv etherpad-lite-win.zip $START_FOLDER + +echo "clean up..." +rm -rf /tmp/etherpad-lite-win + +echo "finished. You can find the zip in the etherpad lite root folder, its called etherpad-lite-win.zip" diff --git a/bin/installDeps.sh b/bin/installDeps.sh index ece5b7aa..cb367606 100755 --- a/bin/installDeps.sh +++ b/bin/installDeps.sh @@ -20,12 +20,26 @@ hash node > /dev/null 2>&1 || { exit 1 } +#check node version +NODE_VERSION=$(node --version) +if [ ! $(echo $NODE_VERSION | cut -d "." -f 1-2) = "v0.4" ]; then + echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.4.x" >&2 + exit 1 +fi + #Is npm installed? hash npm > /dev/null 2>&1 || { echo "Please install npm ( http://npmjs.org )" >&2 exit 1 } +#check npm version +NPM_VERSION=$(npm --version) +if [ ! $(echo $NPM_VERSION | cut -d "." -f 1-2) = "1.0" ]; then + echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.0.x" >&2 + exit 1 +fi + #Does a settings.json exist? if no copy the template if [ ! -f "settings.json" ]; then echo "Copy the settings template to settings.json..." diff --git a/node/handler/ExportHandler.js b/node/handler/ExportHandler.js index 8c8b775a..a87219bb 100644 --- a/node/handler/ExportHandler.js +++ b/node/handler/ExportHandler.js @@ -34,7 +34,7 @@ var tempDirectory = "/tmp"; //tempDirectory changes if the operating system is windows if(os.type().indexOf("Windows") > -1) { - tempDirectory = "c:\\Temp"; + tempDirectory = process.env.TEMP; } /** diff --git a/node/handler/ImportHandler.js b/node/handler/ImportHandler.js index 07168e95..8936e488 100644 --- a/node/handler/ImportHandler.js +++ b/node/handler/ImportHandler.js @@ -35,7 +35,7 @@ var tempDirectory = "/tmp/"; //tempDirectory changes if the operating system is windows if(os.type().indexOf("Windows") > -1) { - tempDirectory = "c:\\Temp\\"; + tempDirectory = process.env.TEMP; } /** diff --git a/node/server.js b/node/server.js index 764d5c33..bdfc631a 100644 --- a/node/server.js +++ b/node/server.js @@ -166,7 +166,7 @@ async.waterfall([ //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { - next(); + res.send('Such a padname is forbidden', 404); return; } @@ -181,7 +181,7 @@ async.waterfall([ //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { - next(); + res.send('Such a padname is forbidden', 404); return; } @@ -196,7 +196,7 @@ async.waterfall([ //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { - next(); + res.send('Such a padname is forbidden', 404); return; } @@ -225,10 +225,10 @@ async.waterfall([ //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { - next(); + res.send('Such a padname is forbidden', 404); return; } - + //if abiword is disabled, skip handling this request if(settings.abiword == null) { diff --git a/node/utils/Abiword.js b/node/utils/Abiword.js index 2122fd80..7a89a586 100644 --- a/node/utils/Abiword.js +++ b/node/utils/Abiword.js @@ -24,12 +24,14 @@ var async = require("async"); var settings = require("./Settings"); var os = require('os'); +var doConvertTask; + //on windows we have to spawn a process for each convertion, cause the plugin abicommand doesn't exist on this platform if(os.type().indexOf("Windows") > -1) { var stdoutBuffer = ""; - function doConvertTask(task, callback) + doConvertTask = function(task, callback) { //span an abiword process to perform the conversion var abiword = spawn(settings.abiword, ["--to=" + task.destFile, task.srcFile]); @@ -123,7 +125,7 @@ else } } - function doConvertTask(task, callback) + doConvertTask = function(task, callback) { abiword.stdin.write("convert " + task.srcFile + " " + task.destFile + " " + task.type + "\n"); diff --git a/package.json b/package.json index 4ae1a087..735f9b72 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "name": "Robin Buse"} ], "dependencies" : { - "socket.io" : "0.7.8", - "ueberDB" : "0.0.14", + "socket.io" : "0.7.9", + "ueberDB" : "0.0.15", "async" : "0.1.9", "joose" : "3.18.0", "express" : "2.4.4", diff --git a/settings.json.template_windows b/settings.json.template_windows new file mode 100644 index 00000000..235ec71a --- /dev/null +++ b/settings.json.template_windows @@ -0,0 +1,38 @@ +/* + This file must be valid JSON. But comments are allowed + + Please edit settings.json, not settings.json.template +*/ +{ + //Ip and port which etherpad should bind at + "ip": "0.0.0.0", + "port" : 9001, + + //The Type of the database. You can choose between sqlite and mysql + "dbType" : "dirty", + //the database specific settings + "dbSettings" : { + "filename" : "../var/dirty.db" + }, + + /* An Example of MySQL Configuration + "dbType" : "mysql", + "dbSettings" : { + "user" : "root", + "host" : "localhost", + "password": "", + "database": "store" + }, + */ + + //the default text of a pad + "defaultPadText" : "Welcome to Etherpad Lite!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nEtherpad Lite on Github: http:\/\/j.mp/ep-lite\n", + + /* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly, + but makes it impossible to debug the javascript/css */ + "minify" : false, + + /* 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" : null +} diff --git a/start.bat b/start.bat new file mode 100644 index 00000000..cf6a60f1 --- /dev/null +++ b/start.bat @@ -0,0 +1,2 @@ +cd node +..\bin\node server.js diff --git a/static/js/pad2.js b/static/js/pad2.js index 84106aff..4da0c2f9 100644 --- a/static/js/pad2.js +++ b/static/js/pad2.js @@ -17,21 +17,14 @@ /* global $, window */ var socket; +var LineNumbersDisabled = false; +var globalUserName = false; $(document).ready(function() { - //test if the url is proper, means without any ? or # that doesn't belong to a url - //if it isn't proper, clean the url a do a redirect - var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1); - var expectedURL = document.location.href.substring(0,document.location.href.lastIndexOf("/") ) + "/" + padId; - if(expectedURL != document.location.href) - { - document.location = expectedURL; - } - //start the costum js if(typeof costumStart == "function") costumStart(); - + getParams(); handshake(); }); @@ -78,6 +71,57 @@ function randomString() return "t." + randomstring; } +function getParams() +{ + var showControls = getUrlVars()["showControls"]; + var showChat = getUrlVars()["showChat"]; + var userName = getUrlVars()["userName"]; + var showLineNumbers = getUrlVars()["showLineNumbers"]; + if(showControls) + { + if(showControls == "false") + { + $('#editbar').hide(); + $('#editorcontainer').css({"top":"0px"}); + } + } + + if(showChat) + { + if(showChat == "false") + { + $('#chaticon').hide(); + } + } + + if(showLineNumbers) + { + if(showLineNumbers == "false") + { + LineNumbersDisabled = true; + } + } + + if(userName) + { + // If the username is set as a parameter we should set a global value that we can call once we have initiated the pad. + globalUserName = userName; + } +} + +function getUrlVars() +{ + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for(var i = 0; i < hashes.length; i++) + { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + return vars; +} + function handshake() { var loc = document.location; @@ -95,7 +139,6 @@ function handshake() socket.once('connect', function() { var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1); - document.title = document.title + " | " + padId; var token = readCookie("token"); @@ -115,7 +158,6 @@ function handshake() "token": token, "protocolVersion": 2 }; - socket.json.send(msg); }); @@ -136,8 +178,21 @@ function handshake() clientVars.collab_client_vars.clientAgent = "Anonymous"; pad.init(); - initalized = true; + + // If the LineNumbersDisabled value is set to true then we need to hide the Line Numbers + if (LineNumbersDisabled == true) + { + pad.changeViewOption('showLineNumbers', false); + } + + // if the globalUserName value is set we need to tell the server and the client about the new authorname + if (globalUserName !== false) + { + pad.notifyChangeName(globalUserName); // Notifies the server + $('#myusernameedit').attr({"value":globalUserName}); // Updates the current users UI + } + } //This handles every Message after the clientVars else @@ -351,12 +406,15 @@ var pad = { }; options.view[key] = value; pad.handleOptionsChange(options); - pad.collabClient.sendClientMessage( + if (key != "showLineNumbers") { - type: 'padoptions', - options: options, - changedBy: pad.myUserInfo.name || "unnamed" - }); + pad.collabClient.sendClientMessage( + { + type: 'padoptions', + options: options, + changedBy: pad.myUserInfo.name || "unnamed" + }); + } }, handleOptionsChange: function(opts) {