diff --git a/Makefile b/Makefile
index 4e870a452..b656d5d9b 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ outdoc_files = $(addprefix out/,$(doc_sources:.md=.html))
docassets = $(addprefix out/,$(wildcard doc/assets/*))
VERSION = $(shell node -e "console.log( require('./src/package.json').version )")
+UNAME := $(shell uname -s)
docs: $(outdoc_files) $(docassets)
@@ -14,7 +15,11 @@ out/doc/assets/%: doc/assets/%
out/doc/%.html: doc/%.md
mkdir -p $(@D)
node tools/doc/generate.js --format=html --template=doc/template.html $< > $@
- cat $@ | sed 's/__VERSION__/${VERSION}/' > $@
+ifeq ($(UNAME),Darwin)
+ sed -i '' 's/__VERSION__/${VERSION}/' $@
+else
+ sed -i 's/__VERSION__/${VERSION}/' $@
+endif
clean:
rm -rf out/
diff --git a/doc/api/http_api.md b/doc/api/http_api.md
index 0d2cc3756..a7fc0bedd 100644
--- a/doc/api/http_api.md
+++ b/doc/api/http_api.md
@@ -292,6 +292,34 @@ returns the text of a pad formatted as HTML
* `{code: 0, message:"ok", data: {html:"Welcome Text
More Text"}}`
* `{code: 1, message:"padID does not exist", data: null}`
+### Chat
+#### getChatHistory(padID, [start, end])
+ * API >= 1.2.7
+
+returns
+
+* a part of the chat history, when `start` and `end` are given
+* the whole chat histroy, when no extra parameters are given
+
+
+*Example returns:*
+
+* `{"code":0,"message":"ok","data":{"messages":[{"text":"foo","userId":"a.foo","time":1359199533759,"userName":"test"},{"text":"bar","userId":"a.foo","time":1359199534622,"userName":"test"}]}}`
+* `{code: 1, message:"start is higher or equal to the current chatHead", data: null}`
+* `{code: 1, message:"padID does not exist", data: null}`
+
+#### getChatHead(padID)
+ * API >= 1.2.7
+
+returns the chatHead (last number of the last chat-message) of the pad
+
+
+*Example returns:*
+
+* `{code: 0, message:"ok", data: {chatHead: 42}}`
+* `{code: 1, message:"padID does not exist", data: null}`
+
+
### Pad
Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name.
diff --git a/settings.json.template b/settings.json.template
index 04c097517..4b18d7800 100644
--- a/settings.json.template
+++ b/settings.json.template
@@ -101,5 +101,5 @@
"loglevel": "INFO",
// restrict socket.io transport methods
- "socketTransportProtocols" : ['xhr-polling', 'jsonp-polling', 'htmlfile']
+ "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"]
}
diff --git a/src/locales/en.json b/src/locales/en.json
index 37e07a154..eea35cc53 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -1 +1,115 @@
-{"index.newPad":"New Pad","index.createOpenPad":"or create/open a Pad with the name:","pad.toolbar.bold.title":"Bold (Ctrl-B)","pad.toolbar.italic.title":"Italic (Ctrl-I)","pad.toolbar.underline.title":"Underline (Ctrl-U)","pad.toolbar.strikethrough.title":"Strikethrough","pad.toolbar.ol.title":"Ordered list","pad.toolbar.ul.title":"Unordered List","pad.toolbar.indent.title":"Indent","pad.toolbar.unindent.title":"Outdent","pad.toolbar.undo.title":"Undo (Ctrl-Z)","pad.toolbar.redo.title":"Redo (Ctrl-Y)","pad.toolbar.clearAuthorship.title":"Clear Authorship Colors","pad.toolbar.import_export.title":"Import/Export from/to different file formats","pad.toolbar.timeslider.title":"Timeslider","pad.toolbar.savedRevision.title":"Saved Revisions","pad.toolbar.settings.title":"Settings","pad.toolbar.embed.title":"Embed this pad","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","pad.settings.colorcheck":"Authorship colors","pad.settings.linenocheck":"Line numbers","pad.settings.fontType":"Font type:","pad.settings.fontType.normal":"Normal","pad.settings.fontType.monospaced":"Monospace","pad.settings.globalView":"Global View","pad.settings.language":"Language:","pad.importExport.import_export":"Import/Export","pad.importExport.import":"Upload any text file or document","pad.importExport.importSuccessful":"Successful!","pad.importExport.export":"Export current pad as:","pad.importExport.exporthtml":"HTML","pad.importExport.exportplain":"Plain text","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","pad.modals.userdup":"Opened in another window","pad.modals.userdup.explanation":"This pad seems to be opened in more than one browser window on this computer.","pad.modals.userdup.advice":"Reconnect to use this window instead.","pad.modals.unauth":"Not authorized","pad.modals.unauth.explanation":"Your permissions have changed while viewing this page. Try to reconnect.","pad.modals.looping":"Disconnected.","pad.modals.looping.explanation":"There are communication problems with the synchronization server.","pad.modals.looping.cause":"Perhaps you connected through an incompatible firewall or proxy.","pad.modals.initsocketfail":"Server is unreachable.","pad.modals.initsocketfail.explanation":"Couldn't connect to the synchronization server.","pad.modals.initsocketfail.cause":"This is probably due to a problem with your browser or your internet connection.","pad.modals.slowcommit":"Disconnected.","pad.modals.slowcommit.explanation":"The server is not responding.","pad.modals.slowcommit.cause":"This could be due to problems with network connectivity.","pad.modals.deleted":"Deleted.","pad.modals.deleted.explanation":"This pad has been removed.","pad.modals.disconnected":"You have been disconnected.","pad.modals.disconnected.explanation":"The connection to the server was lost","pad.modals.disconnected.cause":"The server may be unavailable. Please notify us if this continues to happen.","pad.share":"Share this pad","pad.share.readonly":"Read only","pad.share.link":"Link","pad.share.emebdcode":"Embed URL","pad.chat":"Chat","pad.chat.title":"Open the chat for this pad.","pad.chat.loadmessages": "Load more messages","timeslider.pageTitle":"{{appTitle}} Timeslider","timeslider.toolbar.returnbutton":"Return to pad","timeslider.toolbar.authors":"Authors:","timeslider.toolbar.authorsList":"No Authors","timeslider.toolbar.exportlink.title":"Export","timeslider.exportCurrent":"Export current version as:","timeslider.version":"Version {{version}}","timeslider.saved":"Saved {{month}} {{day}}, {{year}}","timeslider.dateformat":"{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}","timeslider.month.january":"January","timeslider.month.february":"February","timeslider.month.march":"March","timeslider.month.april":"April","timeslider.month.may":"May","timeslider.month.june":"June","timeslider.month.july":"July","timeslider.month.august":"August","timeslider.month.september":"September","timeslider.month.october":"October","timeslider.month.november":"November","timeslider.month.december":"December","pad.savedrevs.marked":"This revision is now marked as a saved revision","pad.userlist.entername":"Enter your name","pad.userlist.unnamed":"unnamed","pad.userlist.guest":"Guest","pad.userlist.deny":"Deny","pad.userlist.approve":"Approve","pad.editbar.clearcolors":"Clear authorship colors on entire document?","pad.impexp.importbutton":"Import Now","pad.impexp.importing":"Importing...","pad.impexp.confirmimport":"Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?","pad.impexp.convertFailed":"We were not able to import this file. Please use a different document format or copy paste manually","pad.impexp.uploadFailed":"The upload failed, please try again","pad.impexp.importfailed":"Import failed","pad.impexp.copypaste":"Please copy paste","pad.impexp.exportdisabled":"Exporting as {{type}} format is disabled. Please contact your system administrator for details."}
\ No newline at end of file
+{
+ "index.newPad": "New Pad",
+ "index.createOpenPad": "or create/open a Pad with the name:",
+ "pad.toolbar.bold.title": "Bold (Ctrl-B)",
+ "pad.toolbar.italic.title": "Italic (Ctrl-I)",
+ "pad.toolbar.underline.title": "Underline (Ctrl-U)",
+ "pad.toolbar.strikethrough.title": "Strikethrough",
+ "pad.toolbar.ol.title": "Ordered list",
+ "pad.toolbar.ul.title": "Unordered List",
+ "pad.toolbar.indent.title": "Indent",
+ "pad.toolbar.unindent.title": "Outdent",
+ "pad.toolbar.undo.title": "Undo (Ctrl-Z)",
+ "pad.toolbar.redo.title": "Redo (Ctrl-Y)",
+ "pad.toolbar.clearAuthorship.title": "Clear Authorship Colors",
+ "pad.toolbar.import_export.title": "Import/Export from/to different file formats",
+ "pad.toolbar.timeslider.title": "Timeslider",
+ "pad.toolbar.savedRevision.title": "Saved Revisions",
+ "pad.toolbar.settings.title": "Settings",
+ "pad.toolbar.embed.title": "Embed this pad",
+ "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",
+ "pad.settings.colorcheck": "Authorship colors",
+ "pad.settings.linenocheck": "Line numbers",
+ "pad.settings.fontType": "Font type:",
+ "pad.settings.fontType.normal": "Normal",
+ "pad.settings.fontType.monospaced": "Monospace",
+ "pad.settings.globalView": "Global View",
+ "pad.settings.language": "Language:",
+ "pad.importExport.import_export": "Import/Export",
+ "pad.importExport.import": "Upload any text file or document",
+ "pad.importExport.importSuccessful": "Successful!",
+ "pad.importExport.export": "Export current pad as:",
+ "pad.importExport.exporthtml": "HTML",
+ "pad.importExport.exportplain": "Plain text",
+ "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",
+ "pad.modals.userdup": "Opened in another window",
+ "pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.",
+ "pad.modals.userdup.advice": "Reconnect to use this window instead.",
+ "pad.modals.unauth": "Not authorized",
+ "pad.modals.unauth.explanation": "Your permissions have changed while viewing this page. Try to reconnect.",
+ "pad.modals.looping": "Disconnected.",
+ "pad.modals.looping.explanation": "There are communication problems with the synchronization server.",
+ "pad.modals.looping.cause": "Perhaps you connected through an incompatible firewall or proxy.",
+ "pad.modals.initsocketfail": "Server is unreachable.",
+ "pad.modals.initsocketfail.explanation": "Couldn't connect to the synchronization server.",
+ "pad.modals.initsocketfail.cause": "This is probably due to a problem with your browser or your internet connection.",
+ "pad.modals.slowcommit": "Disconnected.",
+ "pad.modals.slowcommit.explanation": "The server is not responding.",
+ "pad.modals.slowcommit.cause": "This could be due to problems with network connectivity.",
+ "pad.modals.deleted": "Deleted.",
+ "pad.modals.deleted.explanation": "This pad has been removed.",
+ "pad.modals.disconnected": "You have been disconnected.",
+ "pad.modals.disconnected.explanation": "The connection to the server was lost",
+ "pad.modals.disconnected.cause": "The server may be unavailable. Please notify us if this continues to happen.",
+ "pad.share": "Share this pad",
+ "pad.share.readonly": "Read only",
+ "pad.share.link": "Link",
+ "pad.share.emebdcode": "Embed URL",
+ "pad.chat": "Chat",
+ "pad.chat.title": "Open the chat for this pad.",
+ "pad.chat.loadmessages": "Load more messages",
+ "timeslider.pageTitle": "{{appTitle}} Timeslider",
+ "timeslider.toolbar.returnbutton": "Return to pad",
+ "timeslider.toolbar.authors": "Authors:",
+ "timeslider.toolbar.authorsList": "No Authors",
+ "timeslider.toolbar.exportlink.title": "Export",
+ "timeslider.exportCurrent": "Export current version as:",
+ "timeslider.version": "Version {{version}}",
+ "timeslider.saved": "Saved {{month}} {{day}}, {{year}}",
+ "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
+ "timeslider.month.january": "January",
+ "timeslider.month.february": "February",
+ "timeslider.month.march": "March",
+ "timeslider.month.april": "April",
+ "timeslider.month.may": "May",
+ "timeslider.month.june": "June",
+ "timeslider.month.july": "July",
+ "timeslider.month.august": "August",
+ "timeslider.month.september": "September",
+ "timeslider.month.october": "October",
+ "timeslider.month.november": "November",
+ "timeslider.month.december": "December",
+ "timeslider.unnamedauthor": "{{num}} unnamed author",
+ "timeslider.unnamedauthors": "{{num}} unnamed authors",
+ "pad.savedrevs.marked": "This revision is now marked as a saved revision",
+ "pad.userlist.entername": "Enter your name",
+ "pad.userlist.unnamed": "unnamed",
+ "pad.userlist.guest": "Guest",
+ "pad.userlist.deny": "Deny",
+ "pad.userlist.approve": "Approve",
+ "pad.editbar.clearcolors": "Clear authorship colors on entire document?",
+ "pad.impexp.importbutton": "Import Now",
+ "pad.impexp.importing": "Importing...",
+ "pad.impexp.confirmimport": "Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?",
+ "pad.impexp.convertFailed": "We were not able to import this file. Please use a different document format or copy paste manually",
+ "pad.impexp.uploadFailed": "The upload failed, please try again",
+ "pad.impexp.importfailed": "Import failed",
+ "pad.impexp.copypaste": "Please copy paste",
+ "pad.impexp.exportdisabled": "Exporting as {{type}} format is disabled. Please contact your system administrator for details."
+}
\ No newline at end of file
diff --git a/src/node/db/API.js b/src/node/db/API.js
index 0eb404e49..a700a4915 100644
--- a/src/node/db/API.js
+++ b/src/node/db/API.js
@@ -278,6 +278,77 @@ exports.setHTML = function(padID, html, callback)
});
}
+/******************/
+/**CHAT FUNCTIONS */
+/******************/
+
+/**
+getChatHistory(padId, start, end), returns a part of or the whole chat-history of this pad
+
+Example returns:
+
+{"code":0,"message":"ok","data":{"messages":[{"text":"foo","userId":"a.foo","time":1359199533759,"userName":"test"},
+ {"text":"bar","userId":"a.foo","time":1359199534622,"userName":"test"}]}}
+
+{code: 1, message:"start is higher or equal to the current chatHead", data: null}
+
+{code: 1, message:"padID does not exist", data: null}
+*/
+exports.getChatHistory = function(padID, start, end, callback)
+{
+ if(start && end)
+ {
+ if(start < 0)
+ {
+ callback(new customError("start is below zero","apierror"));
+ return;
+ }
+ if(end < 0)
+ {
+ callback(new customError("end is below zero","apierror"));
+ return;
+ }
+ if(start > end)
+ {
+ callback(new customError("start is higher than end","apierror"));
+ return;
+ }
+ }
+
+ //get the pad
+ getPadSafe(padID, true, function(err, pad)
+ {
+ if(ERR(err, callback)) return;
+ var chatHead = pad.chatHead;
+
+ // fall back to getting the whole chat-history if a parameter is missing
+ if(!start || !end)
+ {
+ start = 0;
+ end = pad.chatHead - 1;
+ }
+
+ if(start >= chatHead)
+ {
+ callback(new customError("start is higher or equal to the current chatHead","apierror"));
+ return;
+ }
+ if(end >= chatHead)
+ {
+ callback(new customError("end is higher or equal to the current chatHead","apierror"));
+ return;
+ }
+
+ // the the whole message-log and return it to the client
+ pad.getChatMessages(start, end,
+ function(err, msgs)
+ {
+ if(ERR(err, callback)) return;
+ callback(null, {messages: msgs});
+ });
+ });
+}
+
/*****************/
/**PAD FUNCTIONS */
/*****************/
@@ -568,6 +639,23 @@ exports.checkToken = function(callback)
callback();
}
+/**
+getChatHead(padID) returns the chatHead (last number of the last chat-message) of the pad
+
+Example returns:
+
+{code: 0, message:"ok", data: {chatHead: 42}}
+{code: 1, message:"padID does not exist", data: null}
+*/
+exports.getChatHead = function(padID, callback)
+{
+ //get the pad
+ getPadSafe(padID, true, function(err, pad)
+ {
+ if(ERR(err, callback)) return;
+ callback(null, {chatHead: pad.chatHead});
+ });
+}
/**
createDiff(padID, startRev, endRev) returns an object of diffs from 2 points in a pad
diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js
index 9d017b280..1f91c737e 100644
--- a/src/node/handler/APIHandler.js
+++ b/src/node/handler/APIHandler.js
@@ -174,13 +174,13 @@ var version =
, "listAllGroups" : []
, "checkToken" : []
}
-, "1.2.2":
+, "1.2.7":
{ "createGroup" : []
, "createGroupIfNotExistsFor" : ["groupMapper"]
, "deleteGroup" : ["groupID"]
, "listPads" : ["groupID"]
, "listAllPads" : []
- , "createDiff" : ["padID", "startRev", "endRev"]
+ , "createDiff" : ["padID", "startRev", "endRev"]
, "createPad" : ["padID", "text"]
, "createGroupPad" : ["groupID", "padName", "text"]
, "createAuthor" : ["name"]
@@ -210,6 +210,9 @@ var version =
, "sendClientsMessage" : ["padID", "msg"]
, "listAllGroups" : []
, "checkToken" : []
+ , "getChatHistory" : ["padID"]
+ , "getChatHistory" : ["padID", "start", "end"]
+ , "getChatHead" : ["padID"]
}
};
diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js
index b87001416..ac856a604 100644
--- a/src/node/handler/ImportHandler.js
+++ b/src/node/handler/ImportHandler.js
@@ -176,7 +176,7 @@ exports.doImport = function(req, res, padId)
ERR(err);
//close the connection
- res.send("
<%- plugins.formatPlugins().replace(", ","\n") %>+
<%= plugins.formatParts() %>+
<%- plugins.formatPlugins().replace(", ","\n") %>-
<%= plugins.formatParts() %>-