diff --git a/filemanager/inc/class.filemanager_collab.inc.php b/filemanager/inc/class.filemanager_collab.inc.php
index 9384df3b3b..1838f1c903 100644
--- a/filemanager/inc/class.filemanager_collab.inc.php
+++ b/filemanager/inc/class.filemanager_collab.inc.php
@@ -40,16 +40,37 @@ class filemanager_collab extends filemanager_collab_bo {
*/
function join_session ($es_id)
{
- $response = $this->initSession($es_id);
+ $paths = explode('/webdav.php', $es_id);
+ if (Api\Vfs::check_access($paths[1], Api\Vfs::READABLE))
+ {
+ $response = $this->initSession($es_id);
+ $response['success'] = true;
+ }
$response += array (
'id' => $GLOBALS['egw_info']['user']['account_id'],
- 'full_name' => $GLOBALS['egw_info']['user']['account_fullname'],
- 'success' => true
+ 'full_name' => $GLOBALS['egw_info']['user']['account_fullname']
);
return $response;
}
+ /**
+ * This function gets called when user leaves the session
+ *
+ * @param string $es_id
+ * @param string $member_id
+ *
+ * @return array returns an array of data as response for client-side
+ */
+ function leave_session ($es_id, $member_id)
+ {
+ return array (
+ 'session_id' => $es_id,
+ 'memberid' => $member_id,
+ 'success' => $this->OP_removeMember($es_id, $member_id)
+ );
+ }
+
/**
* Polling mechanisim to sysncronise data
*
@@ -63,11 +84,15 @@ class filemanager_collab extends filemanager_collab_bo {
$response = array();
if (is_array($params))
{
+ $paths = explode('/webdav.php', $params['args']['es_id']);
switch ($params['command'])
{
case 'join_session':
$response = $this->join_session($params['args']['es_id'],$params['args']['user_id']);
break;
+ case 'leave_session':
+ $response = $this->leave_session($params['args']['es_id'],$params['args']['member_id']);
+ break;
case 'sync_ops':
try
{
@@ -78,7 +103,7 @@ class filemanager_collab extends filemanager_collab_bo {
{
$client_ops = $params['args']['client_ops']? $params['args']['client_ops']: [];
$current_seq_head = $this->OP_getHeadSeq($es_id);
- if ($seq_head == $current_seq_head) {
+ if ($seq_head == $current_seq_head && $this->is_collabAllowed($es_id)) {
if (count($client_ops)>0)
{
@@ -141,4 +166,26 @@ class filemanager_collab extends filemanager_collab_bo {
return $this->OP_getHeadSeq($es_id);
}
+ /**
+ *
+ * @param type $es_id
+ * @param type $action
+ */
+ function ajax_actions ($es_id, $action)
+ {
+ switch ($action)
+ {
+ case 'save':
+ $this->SESSION_Save($es_id);
+ break;
+ }
+ }
+
+ function is_collabAllowed ($es_id)
+ {
+ $paths = explode('/webdav.php', $es_id);
+ $allowed = Api\Vfs::check_access($paths[1], Api\Vfs::WRITABLE) &&
+ !preg_match('/\/api\/js\/webodf\/template.odf$/', $es_id);
+ return $allowed;
+ }
}
\ No newline at end of file
diff --git a/filemanager/inc/class.filemanager_collab_bo.inc.php b/filemanager/inc/class.filemanager_collab_bo.inc.php
index 8e869ee648..227ca27249 100644
--- a/filemanager/inc/class.filemanager_collab_bo.inc.php
+++ b/filemanager/inc/class.filemanager_collab_bo.inc.php
@@ -80,14 +80,12 @@ class filemanager_collab_bo
$result = self::db2id($this->SESSION_add2Db($es_id));
}
- if (is_null($result['member_id'] = $this->MEMBER_getUserMemberId($es_id, $user_id)))
- {
- $this->MEMBER_add2Db($es_id, $user_id, $color);
- $result['member_id'] = $this->MEMBER_getLastMember();
+ $this->MEMBER_add2Db($es_id, $user_id, $color);
- $this->OP_addMember($es_id, $result['member_id'], $full_name, $user_id, $color, $imageUrl);
- }
+ $result['member_id'] = $this->MEMBER_getLastMember();
+
+ $this->OP_addMember($es_id, $result['member_id'], $full_name, $user_id, $color, $imageUrl);
return $result;
}
@@ -212,6 +210,24 @@ class filemanager_collab_bo
$this->OP_add2Db($op, $es_id);
}
+ /**
+ * Function to remove member from list
+ *
+ * @param string $es_id session id
+ * @param string $member_id membe id
+ *
+ * @return boolean returns true if remove member is successful otherwise false
+ */
+ function OP_removeMember ($es_id, $member_id)
+ {
+ $op = array (
+ 'optype' => 'RemoveMember',
+ 'memberid' => (string) $member_id,
+ 'timestamp' => self::getTimeStamp()
+ );
+ return $this->OP_add2Db($op, $es_id)?true:false;
+ }
+
/**
* Function to get top head seq for a given session
*
@@ -302,7 +318,7 @@ class filemanager_collab_bo
'collab_optype' => $op['optype'],
'collab_opspec' => json_encode($op)
);
- $this->db->insert(self::OP_TABLE, $data,false,__LINE__, __FILE__,'filemanager');
+ return $this->db->insert(self::OP_TABLE, $data,false,__LINE__, __FILE__,'filemanager');
}
/**
@@ -344,6 +360,30 @@ class filemanager_collab_bo
return is_array($member)? $member['collab_member_id']: null;
}
+ /**
+ * Function to get member record of specific member id
+ *
+ * @param string $member_id member id
+ *
+ * @return string member id or null
+ * @throws Exception throws exception if no member id is given
+ */
+ protected function MEMBER_getUserLastMemberId ($es_id, $user_id)
+ {
+ if (!$es_id || !$user_id) throw new Exception (self::EXCEPTION_MESSAGE_NO_SESSION);
+ $query = $this->db->select(
+ self::MEMBER_TABLE,
+ 'collab_member_id',
+ array('collab_es_id' => $es_id, 'collab_uid' => $user_id),
+ __LINE__,
+ __FILE__,
+ false,
+ "ORDER BY `collab_member_id` DESC LIMIT 1;"
+ );
+ $member = $query->fetchRow();
+ return is_array($member)? $member['collab_member_id']: null;
+ }
+
/**
* Utility function to map DB fields to ids
*
diff --git a/filemanager/inc/class.filemanager_ui.inc.php b/filemanager/inc/class.filemanager_ui.inc.php
index 8b85d2f460..7befe41402 100644
--- a/filemanager/inc/class.filemanager_ui.inc.php
+++ b/filemanager/inc/class.filemanager_ui.inc.php
@@ -17,7 +17,7 @@ use EGroupware\Api\Egw;
use EGroupware\Api\Etemplate;
use EGroupware\Api\Vfs;
-use filemanager_collab_bo;
+
/**
* Filemanage user interface class
*/
@@ -1485,14 +1485,21 @@ class filemanager_ui
{
$tmpl = new Etemplate('filemanager.editor');
$file_path = $_GET['path'];
+ $paths = explode('/webdav.php', $file_path);
// Include css files used by wodocollabeditor
Api\Framework::includeCSS('/api/js/webodf/collab/app/resources/app.css');
Api\Framework::includeCSS('/api/js/webodf/collab/wodocollabpane.css');
Api\Framework::includeCSS('/api/js/webodf/collab/wodotexteditor.css');
Api\Framework::includeJS('/filemanager/js/collab.js',null, 'filemanager');
- $tmpl->setElementAttribute('tools', 'actions', self::getActions_edit());
- $preserve = $content = array('file_path' => $file_path);
+ $actions = self::getActions_edit();
+ if (!Api\Vfs::check_access($paths[1], Api\Vfs::WRITABLE))
+ {
+ unset ($actions['save']);
+ unset ($actions['delete']);
+ }
+ $tmpl->setElementAttribute('tools', 'actions', $actions);
+ $preserve = $content = array('file_path' => $file_path);
$tmpl->exec('filemanager.filemanager_ui.editor',$content,array(),array(),$preserve,2);
}
diff --git a/filemanager/js/app.js b/filemanager/js/app.js
index c9fe8a0917..608e6d61de 100644
--- a/filemanager/js/app.js
+++ b/filemanager/js/app.js
@@ -1016,7 +1016,7 @@ app.classes.filemanager = AppJS.extend(
*
* @todo: creating new empty odt file
*/
- list_editor_new: function (_egwAction) {
+ editor_new: function (_egwAction) {
var self = this,
template_url = '/api/js/webodf/template.odt';
egw.open_link(egw.link('/index.php', {
diff --git a/filemanager/js/collab.js b/filemanager/js/collab.js
index 43f6e64d17..f9d77f1001 100644
--- a/filemanager/js/collab.js
+++ b/filemanager/js/collab.js
@@ -8,6 +8,7 @@
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
+
/*egw:uses
/filemanager/js/collab_config.js;
/api/js/webodf/collab/dojo-amalgamation.js;
@@ -23,12 +24,20 @@
*/
app.classes.filemanager = app.classes.filemanager.extend({
/*
- * odf editor object
+ * @var editor odf editor object
*/
editor: {},
+ /**
+ * @var regexp for acceptable mime types
+ */
editor_mime: RegExp(/application\/vnd\.oasis\.opendocument\.text/),
+ /**
+ * @var collab_server server object
+ */
+ collab_server: {},
+
/**
* Destructor
*/
@@ -36,6 +45,7 @@ app.classes.filemanager = app.classes.filemanager.extend({
{
delete this.editor;
delete editor_mime;
+ delete collab_server;
// call parent
this._super.apply(this, arguments);
},
@@ -58,7 +68,7 @@ app.classes.filemanager = app.classes.filemanager.extend({
// need to make body rock solid to avoid extra scrollbars
jQuery('body').css({overflow:'hidden'});
var self = this;
- jQuery(window).on('unload', function(){self.editor.leaveSession()});
+ jQuery(window).on('unload', function(){self.editor_leaveSession()});
this._init_odf_collab_editor ();
}
},
@@ -136,6 +146,16 @@ app.classes.filemanager = app.classes.filemanager.extend({
}
},
+ /**
+ * Function to leave the current editing session
+ * and as result it will call client-side and server leave session.
+ */
+ editor_leaveSession: function ()
+ {
+ this.editor.leaveSession(function(){});
+ this.collab_server.server.leaveSession(this.collab_server.es_id, this.collab_server.memberid);
+ },
+
/**
* Method to close an opened document
*
@@ -151,7 +171,7 @@ app.classes.filemanager = app.classes.filemanager.extend({
{
var closeFn = function ()
{
- self.editor.leaveSession(function(){});
+ self.editor_leaveSession();
if (action != 'new')
{
window.close();
@@ -184,33 +204,6 @@ app.classes.filemanager = app.classes.filemanager.extend({
}
},
- /**
- * Method to create a new document
- * @param {object} _egwAction egw action object
- *
- * @todo: creating new empty odt file
- */
- editor_new: function (_egwAction) {
- var self = this,
- template_url = '/api/js/webodf/template.odt';
-
- if (Object.keys(this.editor).length > 0)
- {
- this.editor_close(_egwAction, function(){
-
- // TODO create new temp file
-
- });
- }
- else
- {
- egw.open_link(egw.link('/index.php', {
- menuaction: 'filemanager.filemanager_ui.editor',
- path: template_url
- }), '', egw.link_get_registry('filemanager','view_popup'));
- }
- },
-
/**
* Method call for saving edited document
*
@@ -239,6 +232,7 @@ app.classes.filemanager = app.classes.filemanager.extend({
success: function(data) {
egw(window).message(egw.lang('Document %1 successfully has been saved.', filename[1]));
self.editor.setDocumentModified(false);
+ egw.json('filemanager.filemanager_collab.ajax_actions',[self.editor_getSessionId(), 'save']).sendRequest();
},
error: function () {},
data: blob,
@@ -270,7 +264,7 @@ app.classes.filemanager = app.classes.filemanager.extend({
// Add odt extension if not exist
if (!file_path.match(/\.odt$/,'ig')) file_path += '.odt';
widgetFilePath.set_value(file_path);
- self.editor.leaveSession(function(){});
+ self.editor_leaveSession();
self.editor.getDocumentAsByteArray(saveByteArrayLocally);
self._init_odf_collab_editor();
egw.refresh('','filemanager');
@@ -429,8 +423,12 @@ app.classes.filemanager = app.classes.filemanager.extend({
function joinSession(_sessionId)
{
var sid = _sessionId;
+
server.joinSession(userId, sid, function (_memberId) {
memberId = _memberId;
+ // Set server object for current session
+ self.collab_server = {server:server, memberid: memberId, es_id: sid};
+
if (Object.keys(self.editor).length == 0) {
Wodo.createCollabTextEditor('filemanager-editor_odfEditor', editorOptions, onEditorCreated);
} else {
@@ -459,6 +457,5 @@ app.classes.filemanager = app.classes.filemanager.extend({
});
});
}
-
});
diff --git a/filemanager/templates/default/index.xet b/filemanager/templates/default/index.xet
index 00831cadd5..57ff1e4320 100644
--- a/filemanager/templates/default/index.xet
+++ b/filemanager/templates/default/index.xet
@@ -54,7 +54,7 @@