[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-1-0' - 6 commits - loleaflet/debug loleaflet/dist loleaflet/src loolwsd/bundled loolwsd/LOOLForKit.cpp loolwsd/LOOLKit.cpp loolwsd/LOOLKit.hpp loolwsd/LOOLWSD.cpp loolwsd/LOOLWSD.hpp loolwsd/MasterProcessSession.cpp loolwsd/protocol.txt loolwsd/Util.cpp loolwsd/Util.hpp

Pranav Kant pranavk at collabora.com
Thu Jun 23 06:06:06 UTC 2016


 loleaflet/debug/document/loleaflet.html                 |   16 ++
 loleaflet/dist/loleaflet-help.html                      |   42 -------
 loleaflet/dist/loleaflet.html                           |   16 ++
 loleaflet/dist/toolbar.css                              |   12 --
 loleaflet/dist/toolbar/jquery.simplemodal.1.4.4.min.js  |   26 ----
 loleaflet/dist/toolbar/toolbar.js                       |   19 ---
 loleaflet/src/control/Control.Menubar.js                |   14 ++
 loleaflet/src/control/Toolbar.js                        |   95 ++++++++++++++++
 loleaflet/src/core/Socket.js                            |   16 ++
 loolwsd/LOOLForKit.cpp                                  |   12 +-
 loolwsd/LOOLKit.cpp                                     |   15 ++
 loolwsd/LOOLKit.hpp                                     |    3 
 loolwsd/LOOLWSD.cpp                                     |   11 +
 loolwsd/LOOLWSD.hpp                                     |    1 
 loolwsd/MasterProcessSession.cpp                        |   14 ++
 loolwsd/Util.cpp                                        |    6 -
 loolwsd/Util.hpp                                        |    4 
 loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h |    3 
 loolwsd/protocol.txt                                    |    8 +
 19 files changed, 215 insertions(+), 118 deletions(-)

New commits:
commit 7e40679fade834bd5ead2ce4a46094ca01aa88a4
Author: Pranav Kant <pranavk at collabora.com>
Date:   Wed Jun 22 14:43:47 2016 +0530

    Vexify all dialogs and move toolbar help to menubar
    
    This makes jquery.simplemodal library in our tree useless, lets
    kill it.
    
    This commit is a cherry-pick of:
    e48a36816ecc0695b178d761481da237aae010a8
    c632cf5716db346103afa9d7bf9d407202bd9c86
    1a46db62bd1dbc80b2e9e998aa8e35cb2ac45c2c
    a789cff8e8d782ecdb2e1d50021a359e4cbd23e8
    55ead88236b99deab9dffa40ce4a69bd9696b8ae
    10a5f8c08b825c9dc5b959fa4ac0e61053717b4a
    17abf005a8b3b2a128b967dc7e87db825c94d01b
    80a81abc460265205ad396ff3dbe88467cda7073
    95684540ea964f33fa2bb84e7a52a1892161976d

diff --git a/loleaflet/debug/document/loleaflet.html b/loleaflet/debug/document/loleaflet.html
index f0ecc5e..33364ce 100644
--- a/loleaflet/debug/document/loleaflet.html
+++ b/loleaflet/debug/document/loleaflet.html
@@ -29,6 +29,7 @@
 <link rel="localizations" href="/loleaflet/%VERSION%/l10n/localizations.json" type="application/vnd.oftn.l10n+json"/>
 <link rel="localizations" href="/loleaflet/%VERSION%/l10n/styles-localizations.json" type="application/vnd.oftn.l10n+json" />
 <link rel="localizations" href="/loleaflet/%VERSION%/l10n/uno-localizations.json" type="application/vnd.oftn.l10n+json" />
+<link rel="localizations" href="/loleaflet/%VERSION%/l10n/help-localizations.json" type="application/vnd.oftn.l10n+json"/>
 <style type="text/css"></style></head>
 <body>
     <script src="/loleaflet/%VERSION%/jquery/2.1.0/jquery.min.js"></script>
@@ -51,7 +52,6 @@
     <script src="/loleaflet/%VERSION%/toolbar/select2.min.js"></script>
     <script src="/loleaflet/%VERSION%/jqueryui/1.11.1/jquery-ui.min.js"></script>
     <script src="/loleaflet/%VERSION%/toolbar/evol.colorpicker.min.js"></script>
-    <script src="/loleaflet/%VERSION%/toolbar/jquery.simplemodal.1.4.4.min.js"></script>
     <script src="/loleaflet/%VERSION%/leaflet-src.js"></script>
     <script src="/loleaflet/%VERSION%/plugins/draw-0.2.4/dist/leaflet.draw.js"></script>
     <script src="/loleaflet/%VERSION%/scrollbar/jquery.mCustomScrollbar.js"></script>
@@ -136,5 +136,19 @@
 
     </script>
 
+    <div id="about-dialog" style="display:none; text-align: center;">
+      <h1 id="product-name">LibreOffice Online</h1>
+      <hr/>
+      <h3 id="product-string"></h3>
+      <p>
+        <h3>LOOLWSD</h3>
+        <div id="loolwsd-version"></div>
+      </p>
+      <p>
+        <h3>LOKit</h3>
+        <div id="lokit-version"></div>
+      </p>
+    </div>
+
     <script src="/loleaflet/%VERSION%/toolbar/toolbar.js"></script>
 </body></html>
diff --git a/loleaflet/dist/loleaflet-help.html b/loleaflet/dist/loleaflet-help.html
index ddb854b..2184635 100644
--- a/loleaflet/dist/loleaflet-help.html
+++ b/loleaflet/dist/loleaflet-help.html
@@ -1,12 +1,3 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-    <title>LOLeaflet Help</title>
-    <meta charset="utf-8">
-    <link rel="localizations" href="/loleaflet/dist/l10n/help-localizations.json" type="application/vnd.oftn.l10n+json"/>
-</head>
-<body onload="selectHelp()">
     <style>
         h1 {
             text-align: center;
@@ -30,21 +21,7 @@
             width: 30%;
         }
     </style>
-    <script src="/loleaflet/dist/l10n/json2.min.js"></script>
-    <script src="/loleaflet/dist/l10n/l10n.min.js"></script>
-    <script>
-        function selectHelp() {
-                if (parent.map.getDocType() === 'text') {
-                        document.getElementById('text-shortcuts').style.display='block';
-                }
-                else if (parent.map.getDocType() === 'spreadsheet') {
-                        document.getElementById('spreadsheet-shortcuts').style.display='block';
-                }
-                else if (parent.map.getDocType() === 'presentation' || parent.map.getDocType() === 'drawing') {
-                        document.getElementById('presentation-shortcuts').style.display='block';
-                }
-        }
-    </script>
+<div>
     <h1>Keyboard Shortcuts</h1>
     <div id="general-shortcuts">
         <h2>General Keyboard Shortcuts</h2>
@@ -235,19 +212,4 @@
             <tr> <td class="function">Select all in slide / drawing page</td> <td class="shortcut">Ctrl + A</td> </tr>
         </table>
     </div>
-    <script>
-        var translatableContent = document.getElementsByTagName("h1");
-        for (var i=0, max=translatableContent.length; i < max; i++) {
-            translatableContent[i].firstChild.nodeValue = translatableContent[i].firstChild.nodeValue.toLocaleString();
-        }
-        translatableContent = document.getElementsByTagName("h2");
-        for (var i=0, max=translatableContent.length; i < max; i++) {
-            translatableContent[i].firstChild.nodeValue = translatableContent[i].firstChild.nodeValue.toLocaleString();
-        }
-        translatableContent = document.getElementsByTagName("td");
-        for (var i=0, max=translatableContent.length; i < max; i++) {
-            translatableContent[i].firstChild.nodeValue = translatableContent[i].firstChild.nodeValue.toLocaleString();
-        }
-    </script>
-</body>
-</html>
+</div>
diff --git a/loleaflet/dist/loleaflet.html b/loleaflet/dist/loleaflet.html
index 501dbc3..21cd01e 100644
--- a/loleaflet/dist/loleaflet.html
+++ b/loleaflet/dist/loleaflet.html
@@ -29,6 +29,7 @@
 <link rel="localizations" href="/loleaflet/%VERSION%/l10n/localizations.json" type="application/vnd.oftn.l10n+json"/>
 <link rel="localizations" href="/loleaflet/%VERSION%/l10n/styles-localizations.json" type="application/vnd.oftn.l10n+json" />
 <link rel="localizations" href="/loleaflet/%VERSION%/l10n/uno-localizations.json" type="application/vnd.oftn.l10n+json" />
+<link rel="localizations" href="/loleaflet/%VERSION%/l10n/help-localizations.json" type="application/vnd.oftn.l10n+json"/>
 <style type="text/css"></style></head>
 <body>
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
@@ -51,7 +52,6 @@
     <script src="/loleaflet/%VERSION%/toolbar/select2.min.js"></script>
     <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
     <script src="/loleaflet/%VERSION%/toolbar/evol.colorpicker.min.js"></script>
-    <script src="/loleaflet/%VERSION%/toolbar/jquery.simplemodal.1.4.4.min.js"></script>
     <script src="/loleaflet/%VERSION%/leaflet-src.js"></script>
     <script src="/loleaflet/%VERSION%/plugins/draw-0.2.4/dist/leaflet.draw.js"></script>
     <script src="/loleaflet/%VERSION%/scrollbar/jquery.mCustomScrollbar.js"></script>
@@ -137,9 +137,9 @@
     </script>
 
     <div id="about-dialog" style="display:none; text-align: center;">
-      <h1 class="translatable">About LibreOffice Online</h1>
+      <h1 id="product-name">LibreOffice Online</h1>
       <hr/>
-      <h3 class="translatable">This version of LibreOffice Online is powered by</h3>
+      <h3 id="product-string"></h3>
       <p>
         <h3>LOOLWSD</h3>
         <div id="loolwsd-version"></div>
@@ -150,12 +150,5 @@
       </p>
     </div>
 
-    <script>
-        var translatableContent = document.getElementsByClassName("translatable");
-        for (var i=0; i < translatableContent.length; i++) {
-            translatableContent[i].innerHTML = translatableContent[i].innerHTML.toLocaleString();
-        }
-    </script>
-
     <script src="/loleaflet/%VERSION%/toolbar/toolbar.js"></script>
 </body></html>
diff --git a/loleaflet/dist/toolbar.css b/loleaflet/dist/toolbar.css
index 35e7976..e0e765a 100644
--- a/loleaflet/dist/toolbar.css
+++ b/loleaflet/dist/toolbar.css
@@ -257,18 +257,6 @@ button.leaflet-control-search-next
 .w2ui-icon.prevrecord{ background: url('/loleaflet/dist/images/lc_prevrecord.png') no-repeat center !important; }
 .w2ui-icon.lastrecord{ background: url('/loleaflet/dist/images/lc_lastrecord.png') no-repeat center !important; }
 
-#simplemodal-container a.modalCloseImg {
-	background:url('/loleaflet/dist/images/lc_closedoc.png') no-repeat;
-	width:25px;
-	height:29px;
-	display:inline;
-	z-index:3200;
-	position:absolute;
-	top:0px;
-	right:-1px;
-	cursor:pointer;
-}
-
 .inserttable-pop {
     z-index: 100000;
     box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
diff --git a/loleaflet/dist/toolbar/jquery.simplemodal.1.4.4.min.js b/loleaflet/dist/toolbar/jquery.simplemodal.1.4.4.min.js
deleted file mode 100644
index 382c736..0000000
--- a/loleaflet/dist/toolbar/jquery.simplemodal.1.4.4.min.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SimpleModal 1.4.4 - jQuery Plugin
- * http://simplemodal.com/
- * Copyright (c) 2013 Eric Martin
- * Licensed under MIT and GPL
- * Date: Sun, Jan 20 2013 15:58:56 -0800
- */
-(function(b){"function"===typeof define&&define.amd?define(["jquery"],b):b(jQuery)})(function(b){var j=[],n=b(document),k=navigator.userAgent.toLowerCase(),l=b(window),g=[],o=null,p=/msie/.test(k)&&!/opera/.test(k),q=/opera/.test(k),m,r;m=p&&/msie 6./.test(k)&&"object"!==typeof window.XMLHttpRequest;r=p&&/msie 7.0/.test(k);b.modal=function(a,h){return b.modal.impl.init(a,h)};b.modal.close=function(){b.modal.impl.close()};b.modal.focus=function(a){b.modal.impl.focus(a)};b.modal.setContainerDimensions=
-function(){b.modal.impl.setContainerDimensions()};b.modal.setPosition=function(){b.modal.impl.setPosition()};b.modal.update=function(a,h){b.modal.impl.update(a,h)};b.fn.modal=function(a){return b.modal.impl.init(this,a)};b.modal.defaults={appendTo:"body",focus:!0,opacity:50,overlayId:"simplemodal-overlay",overlayCss:{},containerId:"simplemodal-container",containerCss:{},dataId:"simplemodal-data",dataCss:{},minHeight:null,minWidth:null,maxHeight:null,maxWidth:null,autoResize:!1,autoPosition:!0,zIndex:1E3,
-close:!0,closeHTML:'<a class="modalCloseImg" title="Close"></a>',closeClass:"simplemodal-close",escClose:!0,overlayClose:!1,fixed:!0,position:null,persist:!1,modal:!0,onOpen:null,onShow:null,onClose:null};b.modal.impl={d:{},init:function(a,h){if(this.d.data)return!1;o=p&&!b.support.boxModel;this.o=b.extend({},b.modal.defaults,h);this.zIndex=this.o.zIndex;this.occb=!1;if("object"===typeof a){if(a=a instanceof b?a:b(a),this.d.placeholder=!1,0<a.parent().parent().size()&&(a.before(b("<span></span>").attr("id",
-"simplemodal-placeholder").css({display:"none"})),this.d.placeholder=!0,this.display=a.css("display"),!this.o.persist))this.d.orig=a.clone(!0)}else if("string"===typeof a||"number"===typeof a)a=b("<div></div>").html(a);else return alert("SimpleModal Error: Unsupported data type: "+typeof a),this;this.create(a);this.open();b.isFunction(this.o.onShow)&&this.o.onShow.apply(this,[this.d]);return this},create:function(a){this.getDimensions();if(this.o.modal&&m)this.d.iframe=b('<iframe src="javascript:false;"></iframe>').css(b.extend(this.o.iframeCss,
-{display:"none",opacity:0,position:"fixed",height:g[0],width:g[1],zIndex:this.o.zIndex,top:0,left:0})).appendTo(this.o.appendTo);this.d.overlay=b("<div></div>").attr("id",this.o.overlayId).addClass("simplemodal-overlay").css(b.extend(this.o.overlayCss,{display:"none",opacity:this.o.opacity/100,height:this.o.modal?j[0]:0,width:this.o.modal?j[1]:0,position:"fixed",left:0,top:0,zIndex:this.o.zIndex+1})).appendTo(this.o.appendTo);this.d.container=b("<div></div>").attr("id",this.o.containerId).addClass("simplemodal-container").css(b.extend({position:this.o.fixed?
-"fixed":"absolute"},this.o.containerCss,{display:"none",zIndex:this.o.zIndex+2})).append(this.o.close&&this.o.closeHTML?b(this.o.closeHTML).addClass(this.o.closeClass):"").appendTo(this.o.appendTo);this.d.wrap=b("<div></div>").attr("tabIndex",-1).addClass("simplemodal-wrap").css({height:"100%",outline:0,width:"100%"}).appendTo(this.d.container);this.d.data=a.attr("id",a.attr("id")||this.o.dataId).addClass("simplemodal-data").css(b.extend(this.o.dataCss,{display:"none"})).appendTo("body");this.setContainerDimensions();
-this.d.data.appendTo(this.d.wrap);(m||o)&&this.fixIE()},bindEvents:function(){var a=this;b("."+a.o.closeClass).bind("click.simplemodal",function(b){b.preventDefault();a.close()});a.o.modal&&a.o.close&&a.o.overlayClose&&a.d.overlay.bind("click.simplemodal",function(b){b.preventDefault();a.close()});n.bind("keydown.simplemodal",function(b){a.o.modal&&9===b.keyCode?a.watchTab(b):a.o.close&&a.o.escClose&&27===b.keyCode&&(b.preventDefault(),a.close())});l.bind("resize.simplemodal orientationchange.simplemodal",
-function(){a.getDimensions();a.o.autoResize?a.setContainerDimensions():a.o.autoPosition&&a.setPosition();m||o?a.fixIE():a.o.modal&&(a.d.iframe&&a.d.iframe.css({height:g[0],width:g[1]}),a.d.overlay.css({height:j[0],width:j[1]}))})},unbindEvents:function(){b("."+this.o.closeClass).unbind("click.simplemodal");n.unbind("keydown.simplemodal");l.unbind(".simplemodal");this.d.overlay.unbind("click.simplemodal")},fixIE:function(){var a=this.o.position;b.each([this.d.iframe||null,!this.o.modal?null:this.d.overlay,
-"fixed"===this.d.container.css("position")?this.d.container:null],function(b,e){if(e){var f=e[0].style;f.position="absolute";if(2>b)f.removeExpression("height"),f.removeExpression("width"),f.setExpression("height",'document.body.scrollHeight > document.body.clientHeight ? document.body.scrollHeight : document.body.clientHeight + "px"'),f.setExpression("width",'document.body.scrollWidth > document.body.clientWidth ? document.body.scrollWidth : document.body.clientWidth + "px"');else{var c,d;a&&a.constructor===
-Array?(c=a[0]?"number"===typeof a[0]?a[0].toString():a[0].replace(/px/,""):e.css("top").replace(/px/,""),c=-1===c.indexOf("%")?c+' + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"':parseInt(c.replace(/%/,""))+' * ((document.documentElement.clientHeight || document.body.clientHeight) / 100) + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"',a[1]&&(d="number"===typeof a[1]?
-a[1].toString():a[1].replace(/px/,""),d=-1===d.indexOf("%")?d+' + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"':parseInt(d.replace(/%/,""))+' * ((document.documentElement.clientWidth || document.body.clientWidth) / 100) + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"')):(c='(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"',
-d='(document.documentElement.clientWidth || document.body.clientWidth) / 2 - (this.offsetWidth / 2) + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"');f.removeExpression("top");f.removeExpression("left");f.setExpression("top",c);f.setExpression("left",d)}}})},focus:function(a){var h=this,a=a&&-1!==b.inArray(a,["first","last"])?a:"first",e=b(":input:enabled:visible:"+a,h.d.wrap);setTimeout(function(){0<e.length?e.focus():h.d.wrap.focus()},
-10)},getDimensions:function(){var a="undefined"===typeof window.innerHeight?l.height():window.innerHeight;j=[n.height(),n.width()];g=[a,l.width()]},getVal:function(a,b){return a?"number"===typeof a?a:"auto"===a?0:0<a.indexOf("%")?parseInt(a.replace(/%/,""))/100*("h"===b?g[0]:g[1]):parseInt(a.replace(/px/,"")):null},update:function(a,b){if(!this.d.data)return!1;this.d.origHeight=this.getVal(a,"h");this.d.origWidth=this.getVal(b,"w");this.d.data.hide();a&&this.d.container.css("height",a);b&&this.d.container.css("width",
-b);this.setContainerDimensions();this.d.data.show();this.o.focus&&this.focus();this.unbindEvents();this.bindEvents()},setContainerDimensions:function(){var a=m||r,b=this.d.origHeight?this.d.origHeight:q?this.d.container.height():this.getVal(a?this.d.container[0].currentStyle.height:this.d.container.css("height"),"h"),a=this.d.origWidth?this.d.origWidth:q?this.d.container.width():this.getVal(a?this.d.container[0].currentStyle.width:this.d.container.css("width"),"w"),e=this.d.data.outerHeight(!0),f=
-this.d.data.outerWidth(!0);this.d.origHeight=this.d.origHeight||b;this.d.origWidth=this.d.origWidth||a;var c=this.o.maxHeight?this.getVal(this.o.maxHeight,"h"):null,d=this.o.maxWidth?this.getVal(this.o.maxWidth,"w"):null,c=c&&c<g[0]?c:g[0],d=d&&d<g[1]?d:g[1],i=this.o.minHeight?this.getVal(this.o.minHeight,"h"):"auto",b=b?this.o.autoResize&&b>c?c:b<i?i:b:e?e>c?c:this.o.minHeight&&"auto"!==i&&e<i?i:e:i,c=this.o.minWidth?this.getVal(this.o.minWidth,"w"):"auto",a=a?this.o.autoResize&&a>d?d:a<c?c:a:f?
-f>d?d:this.o.minWidth&&"auto"!==c&&f<c?c:f:c;this.d.container.css({height:b,width:a});this.d.wrap.css({overflow:e>b||f>a?"auto":"visible"});this.o.autoPosition&&this.setPosition()},setPosition:function(){var a,b;a=g[0]/2-this.d.container.outerHeight(!0)/2;b=g[1]/2-this.d.container.outerWidth(!0)/2;var e="fixed"!==this.d.container.css("position")?l.scrollTop():0;this.o.position&&"[object Array]"===Object.prototype.toString.call(this.o.position)?(a=e+(this.o.position[0]||a),b=this.o.position[1]||b):
-a=e+a;this.d.container.css({left:b,top:a})},watchTab:function(a){if(0<b(a.target).parents(".simplemodal-container").length){if(this.inputs=b(":input:enabled:visible:first, :input:enabled:visible:last",this.d.data[0]),!a.shiftKey&&a.target===this.inputs[this.inputs.length-1]||a.shiftKey&&a.target===this.inputs[0]||0===this.inputs.length)a.preventDefault(),this.focus(a.shiftKey?"last":"first")}else a.preventDefault(),this.focus()},open:function(){this.d.iframe&&this.d.iframe.show();b.isFunction(this.o.onOpen)?
-this.o.onOpen.apply(this,[this.d]):(this.d.overlay.show(),this.d.container.show(),this.d.data.show());this.o.focus&&this.focus();this.bindEvents()},close:function(){if(!this.d.data)return!1;this.unbindEvents();if(b.isFunction(this.o.onClose)&&!this.occb)this.occb=!0,this.o.onClose.apply(this,[this.d]);else{if(this.d.placeholder){var a=b("#simplemodal-placeholder");this.o.persist?a.replaceWith(this.d.data.removeClass("simplemodal-data").css("display",this.display)):(this.d.data.hide().remove(),a.replaceWith(this.d.orig))}else this.d.data.hide().remove();
-this.d.container.hide().remove();this.d.overlay.hide();this.d.iframe&&this.d.iframe.hide().remove();this.d.overlay.remove();this.d={}}}}});
diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js
index 9417931..1ae7b40 100644
--- a/loleaflet/dist/toolbar/toolbar.js
+++ b/loleaflet/dist/toolbar/toolbar.js
@@ -210,9 +210,6 @@ function onClick(id) {
 		w2ui['toolbar-up-more'].render();
 		resizeToolbar();
 	}
-	else if (id === 'help') {
-		map.showLOKeyboardHelp();
-	}
 	else if (id === 'close') {
 		window.parent.postMessage('close', '*');
 		map.remove();
@@ -353,8 +350,6 @@ $(function () {
 			{type: 'button',  id: 'inserttable',  img: 'inserttable', hint: _('Insert table')},
 			{type: 'button',  id: 'annotation', img: 'annotation', hint: _('Insert comment'), uno: 'InsertAnnotation'},
 			{type: 'button',  id: 'insertgraphic',  img: 'insertgraphic', hint: _('Insert graphic')},
-			{type: 'break'},
-			{type: 'button',  id: 'help',  img: 'help', hint: _('Help')},
 			{type: 'html', id: 'right'},
 			{type: 'button',  id: 'more', img: 'more', hint: _('More')},
 			{type: 'button',  id: 'close',  img: 'closedoc', hint: _('Close document'), hidden: true}
diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 3f6f220..54a1d95 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -2,7 +2,7 @@
  * Toolbar handler
  */
 
-/* global $ window */
+/* global $ window vex brandProductName */
 L.Map.include({
 
 	// a mapping of uno commands to more readable toolbar items
@@ -155,12 +155,80 @@ L.Map.include({
 
 	showLOKeyboardHelp: function() {
 		var w = window.innerWidth / 2;
-		var h = window.innerHeight / 2;
-		$.modal('<iframe src="/loleaflet/dist/loleaflet-help.html" width="' + w + '" height="' + h + '" style="border:0">',
-		        this._modalDialogOptions);
+		$.get('/loleaflet/dist/loleaflet-help.html', function(data) {
+			vex.open({
+				content: data,
+				showCloseButton: true,
+				escapeButtonCloses: true,
+				overlayClosesOnClick: true,
+				contentCSS: {width: w + 'px'},
+				buttons: {},
+				afterOpen: function($vexContent) {
+					// Display help according to document opened
+					if (map.getDocType() === 'text') {
+						document.getElementById('text-shortcuts').style.display='block';
+					}
+					else if (map.getDocType() === 'spreadsheet') {
+						document.getElementById('spreadsheet-shortcuts').style.display='block';
+					}
+					else if (map.getDocType() === 'presentation' || map.getDocType() === 'drawing') {
+						document.getElementById('presentation-shortcuts').style.display='block';
+					}
+
+					// Lets transalte
+					var i, max;
+					var translatableContent = $vexContent.find('h1');
+					for (i = 0, max = translatableContent.length; i < max; i++) {
+						translatableContent[i].firstChild.nodeValue = translatableContent[i].firstChild.nodeValue.toLocaleString();
+					}
+					translatableContent = $vexContent.find('h2');
+					for (i = 0, max = translatableContent.length; i < max; i++) {
+						translatableContent[i].firstChild.nodeValue = translatableContent[i].firstChild.nodeValue.toLocaleString();
+					}
+					translatableContent = $vexContent.find('td');
+					for (i = 0, max = translatableContent.length; i < max; i++) {
+						translatableContent[i].firstChild.nodeValue = translatableContent[i].firstChild.nodeValue.toLocaleString();
+					}
+
+					// workaround for https://github.com/HubSpot/vex/issues/43
+					$('.vex-overlay').css({ 'pointer-events': 'none'});
+					$('.vex').click(function() {
+						vex.close($vexContent.data().vex.id);
+					});
+					$('.vex-content').click(function(e) {
+						e.stopPropagation();
+					});
+				}
+			});
+		});
 	},
 
 	showLOAboutDialog: function() {
-		$('#about-dialog').modal(this._modalDialogOptions);
+		// Move the div sitting in 'body' as vex-content and make it visible
+		var content = $('#about-dialog').clone().css({display: 'block'});
+		// fill product-name and product-string
+		var productName = (typeof brandProductName !== 'undefined') ? brandProductName : 'LibreOffice Online';
+		content.find('#product-name').text(productName);
+		var productString = _('This version of %productName is powered by');
+		content.find('#product-string').text(productString.replace('%productName', productName));
+		var w = window.innerWidth / 2;
+		vex.open({
+			content: content,
+			showCloseButton: true,
+			escapeButtonCloses: true,
+			overlayClosesOnClick: true,
+			contentCSS: { width: w + 'px'},
+			buttons: {},
+			afterOpen: function($vexContent) {
+				// workaround for https://github.com/HubSpot/vex/issues/43
+				$('.vex-overlay').css({ 'pointer-events': 'none'});
+				$('.vex').click(function() {
+					vex.close($vexContent.data().vex.id);
+				});
+				$('.vex-content').click(function(e) {
+					e.stopPropagation();
+				});
+			}
+		});
 	}
 });
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index f8b5564..8ca6002 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -139,7 +139,7 @@ L.Socket = L.Class.extend({
 		else if (textMsg.startsWith('lokitversion ')) {
 			var lokitVersionObj = JSON.parse(textMsg.substring(textMsg.indexOf('{')));
 			$('#lokit-version').text(lokitVersionObj.ProductName + ' ' +
-			                         lokitVersionObj.ProductVersion + lokitVersionObj.ProductExtension +
+			                         lokitVersionObj.ProductVersion + lokitVersionObj.ProductExtension.replace('.10.','-') +
 			                         ' (git hash: ' + lokitVersionObj.BuildId.substring(0, 7) + ')');
 		}
 		else if (textMsg.startsWith('error:') && command.errorCmd === 'load') {
commit 02d6630a605344336da4687ce76b21654a47ccd5
Author: Pranav Kant <pranavk at collabora.com>
Date:   Tue Jun 21 22:11:33 2016 +0530

    Make new version string as a JSON string
    
    ... easy to differentiate on client side among various version
    info parts, especially for LOKit version information.
    
    Change-Id: I4ba18c60367fb9166462b535bc46953a82a8435d

diff --git a/loleaflet/dist/loleaflet.html b/loleaflet/dist/loleaflet.html
index 0a1bb9a..501dbc3 100644
--- a/loleaflet/dist/loleaflet.html
+++ b/loleaflet/dist/loleaflet.html
@@ -139,7 +139,7 @@
     <div id="about-dialog" style="display:none; text-align: center;">
       <h1 class="translatable">About LibreOffice Online</h1>
       <hr/>
-      <h3 class="translatable">This version of LibreOffice Online is powered by<h3>
+      <h3 class="translatable">This version of LibreOffice Online is powered by</h3>
       <p>
         <h3>LOOLWSD</h3>
         <div id="loolwsd-version"></div>
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 08402ab..f8b5564 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -127,16 +127,20 @@ L.Socket = L.Class.extend({
 		var command = this.parseServerCmd(textMsg);
 		if (textMsg.startsWith('loolserver ')) {
 			// This must be the first message, unless we reconnect.
-			var versionStr = textMsg.split(' ');
-			$('#loolwsd-version').text(versionStr[1] + ' ' + versionStr[2]);
+			var loolwsdVersionObj = JSON.parse(textMsg.substring(textMsg.indexOf('{')));
+			$('#loolwsd-version').text(loolwsdVersionObj.Version +
+			                           ' (git hash: ' + loolwsdVersionObj.Hash + ')');
 
 			// TODO: For now we expect perfect match in protocol versions
-			if (versionStr[3] !== this.ProtocolVersionNumber) {
+			if (loolwsdVersionObj.Protocol !== this.ProtocolVersionNumber) {
 				this.fire('error', {msg: _('Unsupported server version.')});
 			}
 		}
 		else if (textMsg.startsWith('lokitversion ')) {
-			$('#lokit-version').text(textMsg.substring(13));
+			var lokitVersionObj = JSON.parse(textMsg.substring(textMsg.indexOf('{')));
+			$('#lokit-version').text(lokitVersionObj.ProductName + ' ' +
+			                         lokitVersionObj.ProductVersion + lokitVersionObj.ProductExtension +
+			                         ' (git hash: ' + lokitVersionObj.BuildId.substring(0, 7) + ')');
 		}
 		else if (textMsg.startsWith('error:') && command.errorCmd === 'load') {
 			this.close();
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 2862a42..33e9da9 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -78,7 +78,11 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
         // Send LOOL version information
         std::string version, hash;
         Util::getVersionInfo(version, hash);
-        sendTextFrame("loolserver " + version + " " + hash + " " + GetProtocolVersion());
+        std::string versionStr =
+            "{ \"Version\":  \"" + version + "\", " +
+            "\"Hash\":     \"" + hash + "\", " +
+            "\"Protocol\": \"" + GetProtocolVersion() + "\" }";
+        sendTextFrame("loolserver " + versionStr);
         // Send LOKit version information
         sendTextFrame("lokitversion " + LOOLWSD::LOKitVersion);
 
commit 0b8d53db462d47ab0d2ac2edf92f122c16b99c10
Author: Pranav Kant <pranavk at collabora.com>
Date:   Tue Jun 21 19:16:20 2016 +0530

    loleaflet: 'Keyboard shortcuts' in new 'Help' menubar item
    
    Change-Id: I0a924505970e9ed13ea45ebc85ef14a618646b2d

diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js
index 67f7ee3..9417931 100644
--- a/loleaflet/dist/toolbar/toolbar.js
+++ b/loleaflet/dist/toolbar/toolbar.js
@@ -211,21 +211,7 @@ function onClick(id) {
 		resizeToolbar();
 	}
 	else if (id === 'help') {
-		var w = window.innerWidth / 2;
-		var h = window.innerHeight / 2;
-		$.modal('<iframe src="/loleaflet/dist/loleaflet-help.html" width="' + w + '" height="' + h + '" style="border:0">', {
-			overlayClose:true,
-			opacity: 80,
-			overlayCss: {
-				backgroundColor : '#000'
-			},
-			containerCss: {
-				overflow : 'hidden',
-				backgroundColor : '#fff',
-				padding : '20px',
-				border : '2px solid #000'
-			}
-		});
+		map.showLOKeyboardHelp();
 	}
 	else if (id === 'close') {
 		window.parent.postMessage('close', '*');
diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index d1d3ae5..8b34cac 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -46,7 +46,8 @@ L.Control.Menubar = L.Control.extend({
 																						{name: _('Cell'), type: 'unocommand', uno: '.uno:EntireCell'}]},
 												  {name: _('Merge cells'), type: 'unocommand', uno: '.uno:MergeCells'}]
 			},
-			{name: _('Help'), type: 'menu', menu: [{name: _('About'), id: 'about', type: 'action'}]
+			{name: _('Help'), type: 'menu', menu: [{name: _('Keyboard shortcuts'), id: 'keyboard-shortcuts', type: 'action'},
+			                                       {name: _('About'), id: 'about', type: 'action'}]
 			}
 		],
 
@@ -90,7 +91,8 @@ L.Control.Menubar = L.Control.extend({
 												 {type: 'separator'},
 												 {name: _('Fullscreen presentation'), id: 'fullscreen-presentation', type: 'action'}]
 			},
-			{name: _('Help'), type: 'menu', menu: [{name: _('About'), id: 'about', type: 'action'}]
+			{name: _('Help'), type: 'menu', menu: [{name: _('Keyboard shortcuts'), id: 'keyboard-shortcuts', type: 'action'},
+			                                       {name: _('About'), id: 'about', type: 'action'}]
 			}
 		],
 
@@ -128,7 +130,8 @@ L.Control.Menubar = L.Control.extend({
 												 {name: _('Delete row'), type: 'unocommand', uno: '.uno:DeleteRows'},
 												 {name: _('Delete column'), type: 'unocommand', uno: '.uno:DeleteColumns'}]
 			},
-			{name: _('Help'), type: 'menu', menu: [{name: _('About'), id: 'about', type: 'action'}]
+			{name: _('Help'), type: 'menu', menu: [{name: _('Keyboard shortcuts'), id: 'keyboard-shortcuts', type: 'action'},
+			                                       {name: _('About'), id: 'about', type: 'action'}]
 			}
 		],
 
@@ -298,19 +301,9 @@ L.Control.Menubar = L.Control.extend({
 				callback: this._onDeleteSlide
 			}, this);
 		} else if (id === 'about') {
-			$('#about-dialog').modal({
-				overlayClose:true,
-				opacity: 80,
-				overlayCss: {
-					backgroundColor : '#000'
-				},
-				containerCss: {
-					overflow : 'hidden',
-					backgroundColor : '#fff',
-					padding : '20px',
-					border : '2px solid #000'
-				}
-			});
+			map.showLOAboutDialog();
+		} else if (id === 'keyboard-shortcuts') {
+			map.showLOKeyboardHelp();
 		}
 	},
 
diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 5ec6050..3f6f220 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -1,6 +1,8 @@
 /*
  * Toolbar handler
  */
+
+/* global $ window */
 L.Map.include({
 
 	// a mapping of uno commands to more readable toolbar items
@@ -9,6 +11,20 @@ L.Map.include({
 		'.uno:CharFontName'
 	],
 
+	_modalDialogOptions: {
+		overlayClose:true,
+		opacity: 80,
+		overlayCss: {
+			backgroundColor : '#000'
+		},
+		containerCss: {
+			overflow : 'hidden',
+			backgroundColor : '#fff',
+			padding : '20px',
+			border : '2px solid #000'
+		}
+	},
+
 	applyFont: function (fontName) {
 		if (this.getPermission() === 'edit') {
 			var msg = 'uno .uno:CharFontName {' +
@@ -135,5 +151,16 @@ L.Map.include({
 
 	renderFont: function (fontName) {
 		this._socket.sendMessage('renderfont font=' + window.encodeURIComponent(fontName));
+	},
+
+	showLOKeyboardHelp: function() {
+		var w = window.innerWidth / 2;
+		var h = window.innerHeight / 2;
+		$.modal('<iframe src="/loleaflet/dist/loleaflet-help.html" width="' + w + '" height="' + h + '" style="border:0">',
+		        this._modalDialogOptions);
+	},
+
+	showLOAboutDialog: function() {
+		$('#about-dialog').modal(this._modalDialogOptions);
 	}
 });
commit 16bb6007a440aa6eab21131d011223856c922405
Author: Pranav Kant <pranavk at collabora.com>
Date:   Tue Jun 21 15:05:11 2016 +0530

    loleaflet: Dialog to show loolwsd, lokit version information
    
    Change-Id: Ie05f0597d3464b5e7705bd1d1ff4ab5c03af013f

diff --git a/loleaflet/dist/loleaflet.html b/loleaflet/dist/loleaflet.html
index a9f6613..0a1bb9a 100644
--- a/loleaflet/dist/loleaflet.html
+++ b/loleaflet/dist/loleaflet.html
@@ -136,5 +136,26 @@
 
     </script>
 
+    <div id="about-dialog" style="display:none; text-align: center;">
+      <h1 class="translatable">About LibreOffice Online</h1>
+      <hr/>
+      <h3 class="translatable">This version of LibreOffice Online is powered by<h3>
+      <p>
+        <h3>LOOLWSD</h3>
+        <div id="loolwsd-version"></div>
+      </p>
+      <p>
+        <h3>LOKit</h3>
+        <div id="lokit-version"></div>
+      </p>
+    </div>
+
+    <script>
+        var translatableContent = document.getElementsByClassName("translatable");
+        for (var i=0; i < translatableContent.length; i++) {
+            translatableContent[i].innerHTML = translatableContent[i].innerHTML.toLocaleString();
+        }
+    </script>
+
     <script src="/loleaflet/%VERSION%/toolbar/toolbar.js"></script>
 </body></html>
diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index d655c5f..d1d3ae5 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -4,6 +4,7 @@
 
 /* global $ _ map title vex */
 L.Control.Menubar = L.Control.extend({
+	// TODO: Some mechanism to stop the need to copy duplicate menus (eg. Help)
 	options: {
 		text:  [
 			{name: _('File'), type: 'menu', menu: [{name: _('Save'), type: 'unocommand', uno: '.uno:Save'},
@@ -44,6 +45,8 @@ L.Control.Menubar = L.Control.extend({
 																						{name: _('Column'), type: 'unocommand', uno: '.uno:EntireColumn'},
 																						{name: _('Cell'), type: 'unocommand', uno: '.uno:EntireCell'}]},
 												  {name: _('Merge cells'), type: 'unocommand', uno: '.uno:MergeCells'}]
+			},
+			{name: _('Help'), type: 'menu', menu: [{name: _('About'), id: 'about', type: 'action'}]
 			}
 		],
 
@@ -86,6 +89,8 @@ L.Control.Menubar = L.Control.extend({
 												 {name: _('Delete slide'), id: 'deletepage', type: 'action'},
 												 {type: 'separator'},
 												 {name: _('Fullscreen presentation'), id: 'fullscreen-presentation', type: 'action'}]
+			},
+			{name: _('Help'), type: 'menu', menu: [{name: _('About'), id: 'about', type: 'action'}]
 			}
 		],
 
@@ -122,6 +127,8 @@ L.Control.Menubar = L.Control.extend({
 												 {type: 'separator'},
 												 {name: _('Delete row'), type: 'unocommand', uno: '.uno:DeleteRows'},
 												 {name: _('Delete column'), type: 'unocommand', uno: '.uno:DeleteColumns'}]
+			},
+			{name: _('Help'), type: 'menu', menu: [{name: _('About'), id: 'about', type: 'action'}]
 			}
 		],
 
@@ -290,6 +297,20 @@ L.Control.Menubar = L.Control.extend({
 				message: _('Are you sure you want to delete this slide?'),
 				callback: this._onDeleteSlide
 			}, this);
+		} else if (id === 'about') {
+			$('#about-dialog').modal({
+				overlayClose:true,
+				opacity: 80,
+				overlayCss: {
+					backgroundColor : '#000'
+				},
+				containerCss: {
+					overflow : 'hidden',
+					backgroundColor : '#fff',
+					padding : '20px',
+					border : '2px solid #000'
+				}
+			});
 		}
 	},
 
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 49092c8..08402ab 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -2,7 +2,7 @@
  * L.Socket contains methods for the communication with the server
  */
 
-/* global _ vex */
+/* global _ vex $ */
 L.Socket = L.Class.extend({
 	ProtocolVersionNumber: '0.1',
 
@@ -127,11 +127,17 @@ L.Socket = L.Class.extend({
 		var command = this.parseServerCmd(textMsg);
 		if (textMsg.startsWith('loolserver ')) {
 			// This must be the first message, unless we reconnect.
-			// TODO: For now we expect perfect match.
-			if (textMsg.substring(11) !== this.ProtocolVersionNumber) {
+			var versionStr = textMsg.split(' ');
+			$('#loolwsd-version').text(versionStr[1] + ' ' + versionStr[2]);
+
+			// TODO: For now we expect perfect match in protocol versions
+			if (versionStr[3] !== this.ProtocolVersionNumber) {
 				this.fire('error', {msg: _('Unsupported server version.')});
 			}
 		}
+		else if (textMsg.startsWith('lokitversion ')) {
+			$('#lokit-version').text(textMsg.substring(13));
+		}
 		else if (textMsg.startsWith('error:') && command.errorCmd === 'load') {
 			this.close();
 
commit 1cc416b5c7ac61716fa4ee5f426b5e7d3e3fe011
Author: Pranav Kant <pranavk at collabora.com>
Date:   Tue Jun 21 00:28:00 2016 +0530

    loolwsd: Send LOKit version information to clients
    
    Send as a response to 'loolclient' message received from the
    client
    
    Change-Id: I3d33f9fd087489aa9bf5a94f591ab04e208cbf13

diff --git a/loolwsd/LOOLForKit.cpp b/loolwsd/LOOLForKit.cpp
index 7904e0c..e7c977e 100644
--- a/loolwsd/LOOLForKit.cpp
+++ b/loolwsd/LOOLForKit.cpp
@@ -135,7 +135,8 @@ static void cleanupChildren()
 static int createLibreOfficeKit(const std::string& childRoot,
                                 const std::string& sysTemplate,
                                 const std::string& loTemplate,
-                                const std::string& loSubPath)
+                                const std::string& loSubPath,
+                                bool queryVersion = false)
 {
     Log::debug("Forking a loolkit process.");
 
@@ -157,7 +158,7 @@ static int createLibreOfficeKit(const std::string& childRoot,
             Thread::sleep(std::stoul(std::getenv("SLEEPKITFORDEBUGGER")) * 1000);
         }
 
-        lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, NoCapsForKit);
+        lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, NoCapsForKit, queryVersion);
     }
     else
     {
@@ -308,7 +309,8 @@ int main(int argc, char** argv)
     Log::info("Preinit stage OK.");
 
     // We must have at least one child, more are created dynamically.
-    if (createLibreOfficeKit(childRoot, sysTemplate, loTemplate, loSubPath) < 0)
+    // Ask this first child to send version information to master process
+    if (createLibreOfficeKit(childRoot, sysTemplate, loTemplate, loSubPath, true) < 0)
     {
         Log::error("Failed to create a kit process.");
         std::_Exit(Application::EXIT_SOFTWARE);
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 183768b..7cbd37a 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -1109,7 +1109,8 @@ void lokit_main(const std::string& childRoot,
                 const std::string& sysTemplate,
                 const std::string& loTemplate,
                 const std::string& loSubPath,
-                bool noCapabilities)
+                bool noCapabilities,
+                bool queryVersion)
 {
     // Reinitialize logging when forked.
     Log::initialize("kit");
@@ -1260,7 +1261,17 @@ void lokit_main(const std::string& childRoot,
         // Open websocket connection between the child process and WSD.
         HTTPClientSession cs("127.0.0.1", MasterPortNumber);
         cs.setTimeout(0);
-        HTTPRequest request(HTTPRequest::HTTP_GET, std::string(NEW_CHILD_URI) + "pid=" + pid);
+
+        std::string requestUrl = std::string(NEW_CHILD_URI) + "pid=" + pid;
+        if (queryVersion)
+        {
+            char* versionInfo = loKit->pClass->getVersionInfo(loKit);
+            std::string encodedVersionStr;
+            URI::encode(std::string(versionInfo), "", encodedVersionStr);
+            requestUrl += "&version=" + encodedVersionStr;
+            free(versionInfo);
+        }
+        HTTPRequest request(HTTPRequest::HTTP_GET, requestUrl);
         HTTPResponse response;
         auto ws = std::make_shared<WebSocket>(cs, request, response);
         ws->setReceiveTimeout(0);
diff --git a/loolwsd/LOOLKit.hpp b/loolwsd/LOOLKit.hpp
index 2f43022..4206133 100644
--- a/loolwsd/LOOLKit.hpp
+++ b/loolwsd/LOOLKit.hpp
@@ -13,7 +13,8 @@ void lokit_main(const std::string& childRoot,
                 const std::string& sysTemplate,
                 const std::string& loTemplate,
                 const std::string& loSubPath,
-                bool noCapabilities);
+                bool noCapabilities,
+                bool queryVersionInfo);
 
 bool globalPreinit(const std::string &loTemplate);
 
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index dc6db02..09004ca 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -915,6 +915,10 @@ public:
                 {
                     pid = std::stoi(param.second);
                 }
+                else if (param.first == "version")
+                {
+                    LOOLWSD::LOKitVersion = param.second;
+                }
             }
 
             if (pid <= 0)
@@ -1157,6 +1161,7 @@ std::string LOOLWSD::LoSubPath = "lo";
 std::string LOOLWSD::ServerName;
 std::string LOOLWSD::FileServerRoot;
 std::string LOOLWSD::AdminCreds;
+std::string LOOLWSD::LOKitVersion;
 bool LOOLWSD::AllowLocalStorage = false;
 bool LOOLWSD::SSLEnabled =
 #if ENABLE_SSL
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index 1fcdac6..8de18e4 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -44,6 +44,7 @@ public:
     static std::string ServerName;
     static std::string FileServerRoot;
     static std::string AdminCreds;
+    static std::string LOKitVersion;
     static bool AllowLocalStorage;
     static bool SSLEnabled;
 
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 93fcbd0..2862a42 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -71,11 +71,17 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
         if (std::get<0>(versionTuple) != ProtocolMajorVersionNumber ||
             std::get<1>(versionTuple) != ProtocolMinorVersionNumber)
         {
-            sendTextFrame("error: cmd=loolclient kind=badversion");
+            sendTextFrame("error: cmd=loolclient kind=badprotocolversion");
             return false;
         }
 
-        sendTextFrame("loolserver " + GetProtocolVersion());
+        // Send LOOL version information
+        std::string version, hash;
+        Util::getVersionInfo(version, hash);
+        sendTextFrame("loolserver " + version + " " + hash + " " + GetProtocolVersion());
+        // Send LOKit version information
+        sendTextFrame("lokitversion " + LOOLWSD::LOKitVersion);
+
         return true;
     }
 
diff --git a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
index 110d4d5..81d65c1 100644
--- a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
@@ -75,6 +75,9 @@ struct _LibreOfficeKitClass
     void (*setDocumentPassword) (LibreOfficeKit* pThis,
             char const* pURL,
             char const* pPassword);
+
+    /// @see lok::Office::getVersionInfo().
+    char* (*getVersionInfo) (LibreOfficeKit* pThis);
 #endif
 
 };
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 25ea3f5..82819ea 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -171,7 +171,7 @@ pong
 server -> client
 ================
 
-loolserver <major.minor[-patch]>
+loolserver <loolwsd version> <loolwsd git hash> <major.minor[-patch]>
 
     Upon connection, the server must announce the version number it supports.
     Major: an integer that must always match between client and server,
@@ -181,6 +181,12 @@ loolserver <major.minor[-patch]>
            Security fixes that do not alter the API would bump the minor version number.
     Patch: an optional string that is informational.
 
+lokitversion <product_name> <product_version> <product_extension> <build_id>
+
+    Version information of underlying LOKit process.
+
+    Eg: LibreOfficeDev 5.3 .0.0.alpha0 <git hash>
+
 contextmenu: <json description of the context menu>
 
     When the user right-clicks in the document, the content of the context
commit d2534ad21be95be055172651ecfa1b2ad20d67c7
Author: Pranav Kant <pranavk at collabora.com>
Date:   Mon Jun 20 15:21:35 2016 +0530

    loolwsd: Restructure version information functions
    
    ... so that version information can be sent to clients.
    
    Change-Id: Icc90f31fabb501f816ff1dca0c618a73660c88bc

diff --git a/loolwsd/LOOLForKit.cpp b/loolwsd/LOOLForKit.cpp
index 4ff57cf..7904e0c 100644
--- a/loolwsd/LOOLForKit.cpp
+++ b/loolwsd/LOOLForKit.cpp
@@ -252,7 +252,9 @@ int main(int argc, char** argv)
         }
         else if (std::strstr(cmd, "--version") == cmd)
         {
-            Util::displayVersionInfo("loolforkit");
+            std::string version, hash;
+            Util::getVersionInfo(version, hash);
+            std::cout << "loolforkit " << version << " - " << hash << std::endl;
         }
 #if ENABLE_DEBUG
         // this process has various privileges - don't run arbitrary code.
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 1119d55..dc6db02 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -1487,7 +1487,11 @@ Process::PID LOOLWSD::createForKit()
 int LOOLWSD::main(const std::vector<std::string>& /*args*/)
 {
     if (DisplayVersion)
-        Util::displayVersionInfo("loolwsd");
+    {
+        std::string version, hash;
+        Util::getVersionInfo(version, hash);
+        std::cout << "loolwsd " << version << " - " << hash << std::endl;
+    }
 
 #if ENABLE_SSL
     initializeSSL();
diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp
index cad72a1..6bc06cc 100644
--- a/loolwsd/Util.cpp
+++ b/loolwsd/Util.cpp
@@ -457,11 +457,11 @@ namespace Util
             Log::syserror("Cannot set thread name to " + s + ".");
     }
 
-    void displayVersionInfo(const char *app)
+    void getVersionInfo(std::string& version, std::string& hash)
     {
-        std::string hash(LOOLWSD_VERSION_HASH);
+        version = std::string(LOOLWSD_VERSION);
+        hash = std::string(LOOLWSD_VERSION_HASH);
         hash.resize(std::min(8, (int)hash.length()));
-        std::cout << app << " " << LOOLWSD_VERSION << " - " << hash << std::endl;
     }
 
     std::string UniqueId()
diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp
index 5340899..b323eb7 100644
--- a/loolwsd/Util.hpp
+++ b/loolwsd/Util.hpp
@@ -109,8 +109,8 @@ namespace Util
 
     void setThreadName(const std::string& s);
 
-    /// Display version information
-    void displayVersionInfo(const char *app);
+    /// Get version information
+    void getVersionInfo(std::string& version, std::string& hash);
 
     /// Return a string that is unique across processes and calls.
     std::string UniqueId();


More information about the Libreoffice-commits mailing list