DocumentServer/NodeJsProjects/CoAuthoring/sources/DocsCoServer.js
nikolay ivanov a8be6b9e72 init repo
2014-07-05 18:22:49 +00:00

902 lines
35 KiB
JavaScript

/*
* (c) Copyright Ascensio System SIA 2010-2014
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
var sockjs = require("sockjs"),
_ = require("underscore"),
dataBase = null,
http = require("http"),
config = require("./config.json");
if (config["mongodb"]) {
dataBase = require("./database");
}
var logger = require("./../../Common/sources/logger");
var c_oAscRecalcIndexTypes = {
RecalcIndexAdd: 1,
RecalcIndexRemove: 2
};
var c_oAscLockTypeElem = {
Range: 1,
Object: 2,
Sheet: 3
};
var c_oAscLockTypeElemSubType = {
DeleteColumns: 1,
InsertColumns: 2,
DeleteRows: 3,
InsertRows: 4,
ChangeProperties: 5
};
var c_oAscLockTypeElemPresentation = {
Object: 1,
Slide: 2,
Presentation: 3
};
function CRecalcIndexElement(recalcType, position, bIsSaveIndex) {
if (! (this instanceof CRecalcIndexElement)) {
return new CRecalcIndexElement(recalcType, position, bIsSaveIndex);
}
this._recalcType = recalcType;
this._position = position;
this._count = 1;
this.m_bIsSaveIndex = !!bIsSaveIndex;
return this;
}
CRecalcIndexElement.prototype = {
constructor: CRecalcIndexElement,
getLockOther: function (position, type) {
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? +1 : -1;
if (position === this._position && c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType && true === this.m_bIsSaveIndex) {
return null;
} else {
if (position === this._position && c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType && c_oAscLockTypes.kLockTypeMine === type && false === this.m_bIsSaveIndex) {
return null;
} else {
if (position < this._position) {
return position;
} else {
return (position + inc);
}
}
}
},
getLockSaveOther: function (position, type) {
if (this.m_bIsSaveIndex) {
return position;
}
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? +1 : -1;
if (position === this._position && c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType && true === this.m_bIsSaveIndex) {
return null;
} else {
if (position === this._position && c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType && c_oAscLockTypes.kLockTypeMine === type && false === this.m_bIsSaveIndex) {
return null;
} else {
if (position < this._position) {
return position;
} else {
return (position + inc);
}
}
}
},
getLockMe: function (position) {
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? -1 : +1;
if (position < this._position) {
return position;
} else {
return (position + inc);
}
},
getLockMe2: function (position) {
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? -1 : +1;
if (true !== this.m_bIsSaveIndex || position < this._position) {
return position;
} else {
return (position + inc);
}
}
};
function CRecalcIndex() {
if (! (this instanceof CRecalcIndex)) {
return new CRecalcIndex();
}
this._arrElements = [];
return this;
}
CRecalcIndex.prototype = {
constructor: CRecalcIndex,
add: function (recalcType, position, count, bIsSaveIndex) {
for (var i = 0; i < count; ++i) {
this._arrElements.push(new CRecalcIndexElement(recalcType, position, bIsSaveIndex));
}
},
clear: function () {
this._arrElements.length = 0;
},
getLockOther: function (position, type) {
var newPosition = position;
var count = this._arrElements.length;
for (var i = 0; i < count; ++i) {
newPosition = this._arrElements[i].getLockOther(newPosition, type);
if (null === newPosition) {
break;
}
}
return newPosition;
},
getLockSaveOther: function (position, type) {
var newPosition = position;
var count = this._arrElements.length;
for (var i = 0; i < count; ++i) {
newPosition = this._arrElements[i].getLockSaveOther(newPosition, type);
if (null === newPosition) {
break;
}
}
return newPosition;
},
getLockMe: function (position) {
var newPosition = position;
var count = this._arrElements.length;
for (var i = count - 1; i >= 0; --i) {
newPosition = this._arrElements[i].getLockMe(newPosition);
if (null === newPosition) {
break;
}
}
return newPosition;
},
getLockMe2: function (position) {
var newPosition = position;
var count = this._arrElements.length;
for (var i = count - 1; i >= 0; --i) {
newPosition = this._arrElements[i].getLockMe2(newPosition);
if (null === newPosition) {
break;
}
}
return newPosition;
}
};
exports.install = function (server, callbackFunction) {
var sockjs_opts = {
sockjs_url: "http://cdn.sockjs.org/sockjs-0.3.min.js"
},
sockjs_echo = sockjs.createServer(sockjs_opts),
connections = [],
messages = {},
objchanges = {},
indexuser = {},
locks = {},
arrsavelock = [],
dataHandler,
urlParse = new RegExp("^/doc/([0-9-.a-zA-Z_=]*)/c.+", "i"),
serverPort = 80;
sockjs_echo.on("connection", function (conn) {
if (null == conn) {
logger.error("null == conn");
return;
}
conn.on("data", function (message) {
try {
var data = JSON.parse(message);
dataHandler[data.type](conn, data);
} catch(e) {
logger.error("error receiving response:" + e);
}
});
conn.on("error", function () {
logger.error("On error");
});
conn.on("close", function () {
var connection = this,
docLock, userLocks, participants, reconected;
logger.info("Connection closed or timed out");
connections = _.reject(connections, function (el) {
return el.connection.id === connection.id;
});
reconected = _.any(connections, function (el) {
return el.connection.sessionId === connection.sessionId;
});
var state = (false == reconected) ? false : undefined;
participants = getParticipants(conn.docId);
var participantsMap = _.map(participants, function (conn) {
return {
id: conn.connection.userId,
username: conn.connection.userName
};
});
sendParticipantsState(participants, state, connection.userId, connection.userName, participantsMap);
if (!reconected) {
if (undefined != arrsavelock[conn.docId] && connection.userId == arrsavelock[conn.docId].user) {
if (null != arrsavelock[conn.docId].saveLockTimeOutId) {
clearTimeout(arrsavelock[conn.docId].saveLockTimeOutId);
}
arrsavelock[conn.docId] = undefined;
}
if (0 >= participants.length) {
if (dataBase) {
dataBase.remove("messages", {
docid: conn.docId
});
}
delete messages[conn.docId];
if (objchanges[conn.docId] && 0 < objchanges[conn.docId].length) {
sendChangesToServer(conn.serverHost, conn.serverPath, conn.docId);
}
if (dataBase) {
dataBase.remove("changes", {
docid: conn.docId
});
}
delete objchanges[conn.docId];
if (null != arrsavelock[conn.docId] && null != arrsavelock[conn.docId].saveLockTimeOutId) {
clearTimeout(arrsavelock[conn.docId].saveLockTimeOutId);
}
arrsavelock[conn.docId] = undefined;
}
docLock = locks[connection.docId];
if (docLock) {
userLocks = [];
if ("array" === typeOf(docLock)) {
for (var nIndex = 0; nIndex < docLock.length; ++nIndex) {
if (docLock[nIndex].sessionId === connection.sessionId) {
userLocks.push(docLock[nIndex]);
docLock.splice(nIndex, 1);
--nIndex;
}
}
} else {
for (var keyLockElem in docLock) {
if (docLock[keyLockElem].sessionId === connection.sessionId) {
userLocks.push(docLock[keyLockElem]);
delete docLock[keyLockElem];
}
}
}
_.each(participants, function (participant) {
sendData(participant.connection, {
type: "releaselock",
locks: _.map(userLocks, function (e) {
return {
block: e.block,
user: e.user,
time: Date.now(),
changes: null
};
})
});
});
}
}
});
});
function sendData(conn, data) {
conn.write(JSON.stringify(data));
}
function sendParticipantsState(participants, stateConnect, _userId, _userName, participantsMap) {
_.each(participants, function (participant) {
if (participant.connection.userId !== _userId) {
sendData(participant.connection, {
type: "participants",
participants: participantsMap
});
sendData(participant.connection, {
type: "connectstate",
state: stateConnect,
id: _userId,
username: _userName
});
}
});
}
function getParticipants(docId, exludeuserId) {
return _.filter(connections, function (el) {
return el.connection.docId === docId && el.connection.userId !== exludeuserId;
});
}
function sendChangesToServer(serverHost, serverPath, docId) {
if (!serverHost || !serverPath) {
return;
}
var options = {
host: serverHost,
port: serverPort,
path: serverPath,
method: "POST"
};
var req = http.request(options, function (res) {
res.setEncoding("utf8");
});
req.on("error", function (e) {
logger.warn("problem with request on server: " + e.message);
});
var sendData = JSON.stringify({
"id": docId,
"c": "cc"
});
req.write(sendData);
req.end();
}
function _recalcLockArray(userId, _locks, oRecalcIndexColumns, oRecalcIndexRows) {
if (null == _locks) {
return;
}
var count = _locks.length;
var element = null,
oRangeOrObjectId = null;
var i;
var sheetId = -1;
for (i = 0; i < count; ++i) {
if (userId === _locks[i].user) {
continue;
}
element = _locks[i].block;
if (c_oAscLockTypeElem.Range !== element["type"] || c_oAscLockTypeElemSubType.InsertColumns === element["subType"] || c_oAscLockTypeElemSubType.InsertRows === element["subType"]) {
continue;
}
sheetId = element["sheetId"];
oRangeOrObjectId = element["rangeOrObjectId"];
if (oRecalcIndexColumns.hasOwnProperty(sheetId)) {
oRangeOrObjectId["c1"] = oRecalcIndexColumns[sheetId].getLockMe2(oRangeOrObjectId["c1"]);
oRangeOrObjectId["c2"] = oRecalcIndexColumns[sheetId].getLockMe2(oRangeOrObjectId["c2"]);
}
if (oRecalcIndexRows.hasOwnProperty(sheetId)) {
oRangeOrObjectId["r1"] = oRecalcIndexRows[sheetId].getLockMe2(oRangeOrObjectId["r1"]);
oRangeOrObjectId["r2"] = oRecalcIndexRows[sheetId].getLockMe2(oRangeOrObjectId["r2"]);
}
}
}
function _addRecalcIndex(oRecalcIndex) {
var nIndex = 0;
var nRecalcType = c_oAscRecalcIndexTypes.RecalcIndexAdd;
var oRecalcIndexElement = null;
var oRecalcIndexResult = {};
for (var sheetId in oRecalcIndex) {
if (oRecalcIndex.hasOwnProperty(sheetId)) {
if (!oRecalcIndexResult.hasOwnProperty(sheetId)) {
oRecalcIndexResult[sheetId] = new CRecalcIndex();
}
for (; nIndex < oRecalcIndex[sheetId]._arrElements.length; ++nIndex) {
oRecalcIndexElement = oRecalcIndex[sheetId]._arrElements[nIndex];
if (true === oRecalcIndexElement.m_bIsSaveIndex) {
continue;
}
nRecalcType = (c_oAscRecalcIndexTypes.RecalcIndexAdd === oRecalcIndexElement._recalcType) ? c_oAscRecalcIndexTypes.RecalcIndexRemove : c_oAscRecalcIndexTypes.RecalcIndexAdd;
oRecalcIndexResult[sheetId].add(nRecalcType, oRecalcIndexElement._position, oRecalcIndexElement._count, true);
}
}
}
return oRecalcIndexResult;
}
function compareExcelBlock(newBlock, oldBlock) {
if (null !== newBlock.subType && null !== oldBlock.subType) {
return true;
}
if ((c_oAscLockTypeElemSubType.ChangeProperties === oldBlock.subType && c_oAscLockTypeElem.Sheet !== newBlock.type) || (c_oAscLockTypeElemSubType.ChangeProperties === newBlock.subType && c_oAscLockTypeElem.Sheet !== oldBlock.type)) {
return false;
}
var resultLock = false;
if (newBlock.type === c_oAscLockTypeElem.Range) {
if (oldBlock.type === c_oAscLockTypeElem.Range) {
if (c_oAscLockTypeElemSubType.InsertRows === oldBlock.subType || c_oAscLockTypeElemSubType.InsertColumns === oldBlock.subType) {
resultLock = false;
} else {
if (isInterSection(newBlock.rangeOrObjectId, oldBlock.rangeOrObjectId)) {
resultLock = true;
}
}
} else {
if (oldBlock.type === c_oAscLockTypeElem.Sheet) {
resultLock = true;
}
}
} else {
if (newBlock.type === c_oAscLockTypeElem.Sheet) {
resultLock = true;
} else {
if (newBlock.type === c_oAscLockTypeElem.Object) {
if (oldBlock.type === c_oAscLockTypeElem.Sheet) {
resultLock = true;
} else {
if (oldBlock.type === c_oAscLockTypeElem.Object && oldBlock.rangeOrObjectId === newBlock.rangeOrObjectId) {
resultLock = true;
}
}
}
}
}
return resultLock;
}
function isInterSection(range1, range2) {
if (range2.c1 > range1.c2 || range2.c2 < range1.c1 || range2.r1 > range1.r2 || range2.r2 < range1.r1) {
return false;
}
return true;
}
function typeOf(obj) {
if (obj === undefined) {
return "undefined";
}
if (obj === null) {
return "null";
}
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
function comparePresentationBlock(newBlock, oldBlock) {
var resultLock = false;
switch (newBlock.type) {
case c_oAscLockTypeElemPresentation.Presentation:
if (c_oAscLockTypeElemPresentation.Presentation === oldBlock.type) {
resultLock = newBlock.val === oldBlock.val;
}
break;
case c_oAscLockTypeElemPresentation.Slide:
if (c_oAscLockTypeElemPresentation.Slide === oldBlock.type) {
resultLock = newBlock.val === oldBlock.val;
} else {
if (c_oAscLockTypeElemPresentation.Object === oldBlock.type) {
resultLock = newBlock.val === oldBlock.slideId;
}
}
break;
case c_oAscLockTypeElemPresentation.Object:
if (c_oAscLockTypeElemPresentation.Slide === oldBlock.type) {
resultLock = newBlock.slideId === oldBlock.val;
} else {
if (c_oAscLockTypeElemPresentation.Object === oldBlock.type) {
resultLock = newBlock.objId === oldBlock.objId;
}
}
break;
}
return resultLock;
}
dataHandler = (function () {
function auth(conn, data) {
if (data.token && data.user) {
var parsed = urlParse.exec(conn.url);
if (parsed.length > 1) {
conn.docId = parsed[1];
} else {}
if (!indexuser.hasOwnProperty(conn.docId)) {
indexuser[conn.docId] = 1;
} else {
indexuser[conn.docId] += 1;
}
conn.sessionState = 1;
conn.userId = data.user + indexuser[conn.docId];
conn.userName = data.username;
conn.serverHost = data.serverHost;
conn.serverPath = data.serverPath;
if (data.sessionId !== null && _.isString(data.sessionId) && data.sessionId !== "") {
logger.info("restored old session id=" + data.sessionId);
connections = _.reject(connections, function (el) {
return el.connection.sessionId === data.sessionId;
});
conn.sessionId = data.sessionId;
} else {
conn.sessionId = conn.id;
}
connections.push({
connection: conn
});
var participants = getParticipants(conn.docId);
var participantsMap = _.map(participants, function (conn) {
return {
id: conn.connection.userId,
username: conn.connection.userName
};
});
sendData(conn, {
type: "auth",
result: 1,
sessionId: conn.sessionId,
participants: participantsMap,
messages: messages[conn.docid],
locks: locks[conn.docId],
changes: objchanges[conn.docId],
indexuser: indexuser[conn.docId]
});
sendParticipantsState(participants, true, conn.userId, conn.userName, participantsMap);
}
}
function message(conn, data) {
var participants = getParticipants(conn.docId),
msg = {
docid: conn.docId,
message: data.message,
time: Date.now(),
user: conn.userId,
username: conn.userName
};
if (!messages.hasOwnProperty(conn.docId)) {
messages[conn.docId] = [msg];
} else {
messages[conn.docId].push(msg);
}
logger.info("database insert message: " + JSON.stringify(msg));
if (dataBase) {
dataBase.insert("messages", msg);
}
_.each(participants, function (participant) {
sendData(participant.connection, {
type: "message",
messages: [msg]
});
});
}
function getlock(conn, data) {
var participants = getParticipants(conn.docId),
documentLocks;
if (!locks.hasOwnProperty(conn.docId)) {
locks[conn.docId] = {};
}
documentLocks = locks[conn.docId];
var arrayBlocks = data.block;
var isLock = false;
var i = 0;
var lengthArray = (arrayBlocks) ? arrayBlocks.length : 0;
for (; i < lengthArray; ++i) {
logger.info("getLock id: " + arrayBlocks[i]);
if (documentLocks.hasOwnProperty(arrayBlocks[i]) && documentLocks[arrayBlocks[i]] !== null) {
isLock = true;
break;
}
}
if (0 === lengthArray) {
isLock = true;
}
if (!isLock) {
for (i = 0; i < lengthArray; ++i) {
documentLocks[arrayBlocks[i]] = {
time: Date.now(),
user: conn.userId,
block: arrayBlocks[i],
sessionId: conn.sessionId
};
}
}
_.each(participants, function (participant) {
sendData(participant.connection, {
type: "getlock",
locks: locks[conn.docId]
});
});
}
function getlockrange(conn, data) {
var participants = getParticipants(conn.docId),
documentLocks,
documentLock;
if (!locks.hasOwnProperty(conn.docId)) {
locks[conn.docId] = [];
}
documentLocks = locks[conn.docId];
var arrayBlocks = data.block;
var isLock = false;
var isExistInArray = false;
var i = 0,
blockRange = null;
var lengthArray = (arrayBlocks) ? arrayBlocks.length : 0;
for (; i < lengthArray && false === isLock; ++i) {
blockRange = arrayBlocks[i];
for (var keyLockInArray in documentLocks) {
if (true === isLock) {
break;
}
if (!documentLocks.hasOwnProperty(keyLockInArray)) {
continue;
}
documentLock = documentLocks[keyLockInArray];
if (documentLock.user === conn.userId && blockRange.sheetId === documentLock.block.sheetId && blockRange.type === c_oAscLockTypeElem.Object && documentLock.block.type === c_oAscLockTypeElem.Object && documentLock.block.rangeOrObjectId === blockRange.rangeOrObjectId) {
isExistInArray = true;
break;
}
if (c_oAscLockTypeElem.Sheet === blockRange.type && c_oAscLockTypeElem.Sheet === documentLock.block.type) {
if (documentLock.user === conn.userId) {
if (blockRange.sheetId === documentLock.block.sheetId) {
isExistInArray = true;
break;
} else {
continue;
}
} else {
isLock = true;
break;
}
}
if (documentLock.user === conn.userId || !(documentLock.block) || blockRange.sheetId !== documentLock.block.sheetId) {
continue;
}
isLock = compareExcelBlock(blockRange, documentLock.block);
}
}
if (0 === lengthArray) {
isLock = true;
}
if (!isLock && !isExistInArray) {
for (i = 0; i < lengthArray; ++i) {
blockRange = arrayBlocks[i];
documentLocks.push({
time: Date.now(),
user: conn.userId,
block: blockRange,
sessionId: conn.sessionId
});
}
}
_.each(participants, function (participant) {
sendData(participant.connection, {
type: "getlock",
locks: locks[conn.docId]
});
});
}
function getlockpresentation(conn, data) {
var participants = getParticipants(conn.docId),
documentLocks,
documentLock;
if (!locks.hasOwnProperty(conn.docId)) {
locks[conn.docId] = [];
}
documentLocks = locks[conn.docId];
var arrayBlocks = data.block;
var isLock = false;
var isExistInArray = false;
var i = 0,
blockRange = null;
var lengthArray = (arrayBlocks) ? arrayBlocks.length : 0;
for (; i < lengthArray && false === isLock; ++i) {
blockRange = arrayBlocks[i];
for (var keyLockInArray in documentLocks) {
if (true === isLock) {
break;
}
if (!documentLocks.hasOwnProperty(keyLockInArray)) {
continue;
}
documentLock = documentLocks[keyLockInArray];
if (documentLock.user === conn.userId || !(documentLock.block)) {
continue;
}
isLock = comparePresentationBlock(blockRange, documentLock.block);
}
}
if (0 === lengthArray) {
isLock = true;
}
if (!isLock && !isExistInArray) {
for (i = 0; i < lengthArray; ++i) {
blockRange = arrayBlocks[i];
documentLocks.push({
time: Date.now(),
user: conn.userId,
block: blockRange,
sessionId: conn.sessionId
});
}
}
_.each(participants, function (participant) {
sendData(participant.connection, {
type: "getlock",
locks: locks[conn.docId]
});
});
}
function savechanges(conn, data) {
var docLock, userLocks, participants;
if (data.endSaveChanges) {
docLock = locks[conn.docId];
if (docLock) {
if ("array" === typeOf(docLock)) {
userLocks = [];
for (var nIndex = 0; nIndex < docLock.length; ++nIndex) {
if (null !== docLock[nIndex] && docLock[nIndex].sessionId === conn.sessionId) {
userLocks.push(docLock[nIndex]);
docLock.splice(nIndex, 1);
--nIndex;
}
}
} else {
userLocks = _.filter(docLock, function (el) {
return el !== null && el.sessionId === conn.sessionId;
});
for (var i = 0; i < userLocks.length; i++) {
delete docLock[userLocks[i].block];
}
}
}
} else {
userLocks = [];
}
var objchange = {
docid: conn.docId,
changes: data.changes,
time: Date.now(),
user: conn.userId
};
if (!objchanges.hasOwnProperty(conn.docId)) {
objchanges[conn.docId] = [objchange];
} else {
objchanges[conn.docId].push(objchange);
}
logger.info("database insert changes: " + JSON.stringify(objchange));
if (dataBase) {
dataBase.insert("changes", objchange);
}
if (!data.endSaveChanges) {
sendData(conn, {
type: "savePartChanges"
});
} else {
if (data.isExcel) {
var oElement = null;
var oRecalcIndexColumns = null,
oRecalcIndexRows = null;
var oChanges = JSON.parse(data.changes);
var nCount = oChanges.length;
var nIndexChanges = 0;
for (; nIndexChanges < nCount; ++nIndexChanges) {
oElement = oChanges[nIndexChanges];
if ("object" === typeof oElement) {
if ("0" === oElement["type"]) {
oRecalcIndexColumns = _addRecalcIndex(oElement["index"]);
} else {
if ("1" === oElement["type"]) {
oRecalcIndexRows = _addRecalcIndex(oElement["index"]);
}
}
}
if (null !== oRecalcIndexColumns && null !== oRecalcIndexRows) {
_recalcLockArray(conn.userId, locks[conn.docId], oRecalcIndexColumns, oRecalcIndexRows);
oRecalcIndexColumns = null;
oRecalcIndexRows = null;
break;
}
}
}
}
participants = getParticipants(conn.docId, conn.userId);
_.each(participants, function (participant) {
sendData(participant.connection, {
type: "savechanges",
changes: data.changes,
locks: _.map(userLocks, function (e) {
return {
block: e.block,
user: e.user,
time: Date.now(),
changes: null
};
})
});
});
}
function issavelock(conn) {
var _docId = conn.docId;
var _userId = conn.userId;
var _time = Date.now();
var isSaveLock = (undefined === arrsavelock[_docId]) ? false : arrsavelock[_docId].savelock;
if (false === isSaveLock) {
arrsavelock[conn.docId] = {
docid: _docId,
savelock: true,
time: Date.now(),
user: conn.userId
};
var _tmpSaveLock = arrsavelock[_docId];
arrsavelock[conn.docId].saveLockTimeOutId = setTimeout(function () {
if (_tmpSaveLock && _userId == _tmpSaveLock.user && _time == _tmpSaveLock.time) {
arrsavelock[_docId] = undefined;
}
},
60000);
}
sendData(conn, {
type: "savelock",
savelock: isSaveLock
});
}
function unsavelock(conn) {
if (undefined != arrsavelock[conn.docId] && conn.userId != arrsavelock[conn.docId].user) {
return;
}
if (arrsavelock[conn.docId] && null != arrsavelock[conn.docId].saveLockTimeOutId) {
clearTimeout(arrsavelock[conn.docId].saveLockTimeOutId);
}
arrsavelock[conn.docId] = undefined;
sendData(conn, {
type: "unsavelock"
});
}
function getmessages(conn) {
sendData(conn, {
type: "message",
messages: messages[conn.docId]
});
}
function getusers(conn) {
var participants = getParticipants(conn.docId);
sendData(conn, {
type: "getusers",
participants: _.map(participants, function (conn) {
return {
id: conn.connection.userId,
username: conn.connection.userName
};
})
});
}
return {
auth: auth,
message: message,
getlock: getlock,
getlockrange: getlockrange,
getlockpresentation: getlockpresentation,
savechanges: savechanges,
issavelock: issavelock,
unsavelock: unsavelock,
getmessages: getmessages,
getusers: getusers
};
} ());
sockjs_echo.installHandlers(server, {
prefix: "/doc/[0-9-.a-zA-Z_=]*/c",
log: function (severity, message) {
logger.info(message);
}
});
var callbackLoadMessages = (function (arrayElements) {
if (null != arrayElements) {
messages = arrayElements;
if (dataBase) {
dataBase.remove("messages", {});
}
}
if (dataBase) {
dataBase.load("changes", callbackLoadChanges);
} else {
callbackLoadChanges(null);
}
});
var callbackLoadChanges = (function (arrayElements) {
if (null != arrayElements) {
if (dataBase) {
dataBase.remove("changes", {});
}
}
callbackFunction();
});
if (dataBase) {
dataBase.load("messages", callbackLoadMessages);
} else {
callbackLoadMessages(null);
}
};