[Libreoffice-commits] online.git: 5 commits - loleaflet/build loleaflet/debug loleaflet/src loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/LOOLWSD.cpp loolwsd/protocol.txt

Mihai Varga mihai.varga at collabora.com
Thu Oct 22 08:41:18 PDT 2015


 loleaflet/build/deps.js                               |   12 +++
 loleaflet/debug/document/document_simple_example.html |    1 
 loleaflet/src/control/Control.InsertImg.js            |   25 ++++++
 loleaflet/src/layer/tile/TileLayer.js                 |    8 ++
 loleaflet/src/map/handler/Map.FileInserter.js         |   67 ++++++++++++++++++
 loolwsd/LOOLSession.cpp                               |   46 ++++++++++++
 loolwsd/LOOLSession.hpp                               |    2 
 loolwsd/LOOLWSD.cpp                                   |   27 +++++++
 loolwsd/protocol.txt                                  |   13 +++
 9 files changed, 200 insertions(+), 1 deletion(-)

New commits:
commit f03459611a5679bf222442066f82f7b3bf0a3033
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 22 18:40:43 2015 +0300

    loleaflet: file insert control

diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 6f668c3..277e40b 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -260,6 +260,13 @@ var deps = {
 		desc: 'Search control with two buttons (previous / next).'
 	},
 
+	ControlInsertImg: {
+		src: ['control/Control.js',
+		      'control/Control.InsertImg.js'],
+		heading: 'Controls',
+		desc: 'Handles inserting an image in the document.'
+	},
+
 	ControlParts: {
 		src: ['control/Control.js',
 		      'control/Control.Parts.js'],
diff --git a/loleaflet/debug/document/document_simple_example.html b/loleaflet/debug/document/document_simple_example.html
index c7a30a2..166b8e1 100644
--- a/loleaflet/debug/document/document_simple_example.html
+++ b/loleaflet/debug/document/document_simple_example.html
@@ -74,6 +74,7 @@
     globalMap.addControl(L.control.zoom());
     globalMap.addControl(L.control.parts());
     globalMap.addControl(L.control.search());
+    globalMap.addControl(L.control.insertImg());
     globalMap.addControl(L.control.dialog());
     globalMap.addControl(L.control.partsPreview());
     globalMap.addControl(L.control.tabs());
diff --git a/loleaflet/src/control/Control.InsertImg.js b/loleaflet/src/control/Control.InsertImg.js
new file mode 100644
index 0000000..f542eb0
--- /dev/null
+++ b/loleaflet/src/control/Control.InsertImg.js
@@ -0,0 +1,25 @@
+/*
+ * L.Control.InsertImg
+ */
+
+L.Control.InsertImg = L.Control.extend({
+	onAdd: function (map) {
+        this._insertImg = L.DomUtil.create('input', 'leaflet-control-insertimage leaflet-bar');
+		this._insertImg.type = 'file';
+		L.DomEvent['on'](this._insertImg, 'change', this._onChange, this);
+		return this._insertImg;
+	},
+
+	_onChange: function () {
+		if ('files' in this._insertImg) {
+			for (var i = 0; i < this._insertImg.files.length; i++) {
+				var file = this._insertImg.files[i];
+				this._map.insertFile(file);
+			}
+		}
+	}
+});
+
+L.control.insertImg = function (options) {
+	return new L.Control.InsertImg(options);
+};
commit 6e8bd4fdf0d0b3c6c0b10248d2ba0c658bf82188
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 22 18:38:35 2015 +0300

    loleaflet: file insert handler
    
    It sends a file to the server to the /insertfile endpoint,
    once the file has been saved in the loolwsd choot, loolwsd is then
    notified to insert it in the document
    
    TODO: avoid the last roundtrip

diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 3618529..6f668c3 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -235,6 +235,11 @@ var deps = {
 		desc: 'Creates a presentation slide show.'
 	},
 
+	FileInserter: {
+		src: ['map/handler/Map.FileInserter.js'],
+		desc: 'Handles inserting a file (image) in the document.'
+	},
+
 	MarkerDrag: {
 		src: ['layer/marker/Marker.Drag.js'],
 		deps: ['Marker'],
diff --git a/loleaflet/src/map/handler/Map.FileInserter.js b/loleaflet/src/map/handler/Map.FileInserter.js
new file mode 100644
index 0000000..ed47465
--- /dev/null
+++ b/loleaflet/src/map/handler/Map.FileInserter.js
@@ -0,0 +1,67 @@
+/*
+ * L.Map.FileInserter is handling the fileInserter action
+ */
+
+L.Map.mergeOptions({
+	fileInserter: true
+});
+
+L.Map.FileInserter = L.Handler.extend({
+
+	initialize: function (map) {
+		this._map = map;
+		this._childId = null;
+		this._toInsert = {};
+		var parser = document.createElement('a');
+		var protocol = window.location.protocol === 'file:' ? 'http:' : window.location.protocol;
+		parser.href = map.options.server;
+		this._url = protocol + '//' + parser.hostname + ':' + parser.port + '/insertfile';
+	},
+
+	addHooks: function () {
+		this._map.on('insertfile', this._onInsertFile, this);
+		this._map.on('childid', this._onChildIdMsg, this);
+	},
+
+	removeHooks: function () {
+		this._map.off('insertfile', this._onInsertFile, this);
+		this._map.off('childid', this._onChildIdMsg, this);
+	},
+
+	_onInsertFile: function (e) {
+		if (!this._childId) {
+			L.Socket.sendMessage('getchildid');
+			this._toInsert[Date.now()] = e.file;
+		}
+		else {
+			this._sendFile(Date.now(), e.file);
+		}
+	},
+
+	_onChildIdMsg: function (e) {
+		this._childId = e.id;
+		for (var name in this._toInsert) {
+			this._sendFile(name, this._toInsert[name]);
+		}
+		this._toInsert = {};
+	},
+
+	_sendFile: function (name, file) {
+		var url = this._url;
+		console.log(url);
+		var xmlHttp = new XMLHttpRequest();
+		xmlHttp.onreadystatechange = function () {
+			if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
+				L.Socket.sendMessage('insertfile name=' + name + ' type=graphic');
+			}
+		};
+		xmlHttp.open('POST', url, true);
+		var formData = new FormData();
+		formData.append('name', name);
+		formData.append('childid', this._childId);
+		formData.append('file', file);
+		xmlHttp.send(formData);
+	}
+});
+
+L.Map.addInitHook('addHandler', 'fileInserter', L.Map.FileInserter);
commit e5d1d856aa0d102f6cc39f3e4adc27708947bfd8
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 22 18:36:38 2015 +0300

    loleaflet: getchildid msg handler

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 5daa295..5b1aad0 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -195,6 +195,9 @@ L.TileLayer = L.GridLayer.extend({
 		else if (textMsg.startsWith('error:')) {
 			this._onErrorMsg(textMsg);
 		}
+		else if (textMsg.startsWith('getchildid:')) {
+			this._onGetChildIdMsg(textMsg);
+		}
 		else if (textMsg.startsWith('graphicselection:')) {
 			this._onGraphicSelectionMsg(textMsg);
 		}
@@ -302,6 +305,11 @@ L.TileLayer = L.GridLayer.extend({
 		this._map.fire('error', {cmd: command.errorCmd, kind: command.errorKind});
 	},
 
+	_onGetChildIdMsg: function (textMsg) {
+		var command = L.Socket.parseServerCmd(textMsg);
+		this._map.fire('childid', {id: command.id});
+	},
+
 	_onGraphicSelectionMsg: function (textMsg) {
 		if (textMsg.match('EMPTY')) {
 			this._graphicSelection = new L.LatLngBounds(new L.LatLng(0, 0), new L.LatLng(0, 0));
commit 58d7c99f19fc244c5d14da5b064027daf0c4b9da
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 22 18:32:19 2015 +0300

    loolwsd: added getChildId and insertFile methods
    
    getChildId is used to get the chroot's name and insertFile inserts a the
    /user/thedocument/insertfile/file_name file in the document

diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 15a2825..c46ec93 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -319,7 +319,9 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
     else if (tokens[0] != "canceltiles" &&
              tokens[0] != "commandvalues" &&
              tokens[0] != "downloadas" &&
+             tokens[0] != "getchildid" &&
              tokens[0] != "gettextselection" &&
+             tokens[0] != "insertfile" &&
              tokens[0] != "invalidatetiles" &&
              tokens[0] != "key" &&
              tokens[0] != "mouse" &&
@@ -735,7 +737,9 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
         // i.e. need to be handled in a child process.
 
         assert(tokens[0] == "downloadas" ||
+               tokens[0] == "getchildid" ||
                tokens[0] == "gettextselection" ||
+               tokens[0] == "insertfile" ||
                tokens[0] == "key" ||
                tokens[0] == "mouse" ||
                tokens[0] == "uno" ||
@@ -748,7 +752,11 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
         {
             _loKitDocument->pClass->setPart(_loKitDocument, _clientPart);
         }
-        if (tokens[0] == "downloadas")
+        if (tokens[0] == "getchildid")
+        {
+            return getChildId();
+        }
+        else if (tokens[0] == "downloadas")
         {
             return downloadAs(buffer, length, tokens);
         }
@@ -756,6 +764,10 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
         {
             return getTextSelection(buffer, length, tokens);
         }
+        else if (tokens[0] == "insertfile")
+        {
+            return insertFile(buffer, length, tokens);
+        }
         else if (tokens[0] == "key")
         {
             return keyEvent(buffer, length, tokens);
@@ -1072,6 +1084,12 @@ bool ChildProcessSession::downloadAs(const char* /*buffer*/, int /*length*/, Str
     return true;
 }
 
+bool ChildProcessSession::getChildId()
+{
+    sendTextFrame("getchildid: id=" + _childId);
+    return true;
+}
+
 bool ChildProcessSession::getTextSelection(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
 {
     std::string mimeType;
@@ -1089,6 +1107,32 @@ bool ChildProcessSession::getTextSelection(const char* /*buffer*/, int /*length*
     return true;
 }
 
+bool ChildProcessSession::insertFile(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
+{
+    std::string name, type;
+
+    if (tokens.count() != 3 ||
+        !getTokenString(tokens[1], "name", name),
+        !getTokenString(tokens[2], "type", type))
+    {
+        sendTextFrame("error: cmd=insertfile kind=syntax");
+        return false;
+    }
+
+    if (type == "graphic") {
+        std::string fileName = "file://" + jailDocumentURL + "/insertfile/" + name;
+        std::string command = ".uno:InsertGraphic";
+        std::string arguments = "{"
+            "\"FileName\":{"
+                "\"type\":\"string\","
+                "\"value\":\"" + fileName + "\""
+            "}}";
+        _loKitDocument->pClass->postUnoCommand(_loKitDocument, command.c_str(), arguments.c_str());
+    }
+
+    return true;
+}
+
 bool ChildProcessSession::keyEvent(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
 {
     int type, charcode, keycode;
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index 85d9d5a..b8eb7e1 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -185,7 +185,9 @@ public:
     virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
     bool downloadAs(const char *buffer, int length, Poco::StringTokenizer& tokens);
+    bool getChildId();
     bool getTextSelection(const char *buffer, int length, Poco::StringTokenizer& tokens);
+    bool insertFile(const char *buffer, int length, Poco::StringTokenizer& tokens);
     bool keyEvent(const char *buffer, int length, Poco::StringTokenizer& tokens);
     bool mouseEvent(const char *buffer, int length, Poco::StringTokenizer& tokens);
     bool unoCommand(const char *buffer, int length, Poco::StringTokenizer& tokens);
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index ede153d..e3ce9e4 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -22,10 +22,19 @@ downloadas downloadas name=<fileName> id=<id> format=<document format> options=<
     Exports the current document to the desired format and returns a download URL
     The id identifies the request on the client.
 
+getchildid
+
+    Requests the child id so that it knows where the files needs to be sent when it is
+    inserted in the document
+
 gettextselection mimetype=<mimeType>
 
     Request selection's content
 
+insertfile name=<name> type=<type>
+
+    Inserts the file with the name <name> into the document, we currently support type = 'graphic'
+
 invalidatetiles part=<partNumber> tileposx=<xpos> tileposy=<ypos> tilewidth=<tileWidth> tileheight=<tileHeight>
 
     All parameters are numbers. Makes the server remove any cached
@@ -99,6 +108,10 @@ error: cmd=<command> kind=<kind>
     message that caused the error. <kind> is some single-word
     classification
 
+getchildid: id=<id>
+
+    Returns the child id
+
 invalidate: part=<partNumber> x=<x> y=<y> width=<width> height=<height>
 
     All parameters are numbers. Tells the client to invalidate any
commit 28f35551806a9279af6bf9b6e59dc5b5b4d37d3f
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 22 18:27:29 2015 +0300

    loolwsd: insert file HTTP request handler
    
    The client send a file through an http post request, the handler saves
    the file in a temporary directory then moves it in the specified chroot

diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index c241e08..4771ec4 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -201,6 +201,7 @@ public:
             std::string cd = header.get("Content-Disposition");
             Poco::Net::MessageHeader::splitParameters(cd, disp, params);
         }
+
         if (!params.has("filename"))
             return;
 
@@ -286,6 +287,32 @@ public:
                 tempDirectory.setFileName("");
                 File(tempDirectory).remove(/*recursive=*/true);
             }
+            else if (tokens.count() >= 2 && tokens[1] == "insertfile")
+            {
+                response.set("Access-Control-Allow-Origin", "*");
+                response.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
+                response.set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
+
+                std::string tmpPath;
+                ConvertToPartHandler handler(tmpPath);
+                Poco::Net::HTMLForm form(request, request.stream(), handler);
+                if (form.has("childid") && form.has("name"))
+                {
+                    std::string dirPath = LOOLWSD::childRoot + Path::separator() + form.get("childid") + LOOLSession::jailDocumentURL +
+                        Path::separator() + "insertfile";
+                    File(dirPath).createDirectory();
+                    std::string fileName = dirPath + Path::separator() + form.get("name");
+                    File(tmpPath).moveTo(fileName);
+
+                    response.setStatus(HTTPResponse::HTTP_OK);
+                    response.send();
+                }
+                else
+                {
+                    response.setStatus(HTTPResponse::HTTP_BAD_REQUEST);
+                    response.send();
+                }
+            }
             else if (tokens.count() >= 4)
             {
                 // The user might request a file to download


More information about the Libreoffice-commits mailing list