From 8b316eaeef960807c70b543e12deeacefe49c3e1 Mon Sep 17 00:00:00 2001 From: konovalovsergey Date: Mon, 6 Jun 2016 16:45:33 +0300 Subject: [PATCH 01/20] response-content-disposition -> disposition --- Common/sources/storage-fs.js | 2 +- DocService/sources/server.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/sources/storage-fs.js b/Common/sources/storage-fs.js index a5b09e85c..7103bb067 100644 --- a/Common/sources/storage-fs.js +++ b/Common/sources/storage-fs.js @@ -1 +1 @@ -var fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var utils = require("./utils"); var crypto = require('crypto'); var configStorage = require('config').get('storage'); var cfgBucketName = configStorage.get('bucketName'); var cfgStorageFolderName = configStorage.get('storageFolderName'); var cfgStorageExternalHost = configStorage.get('externalHost'); var configFs = configStorage.get('fs'); var cfgStorageFolderPath = configFs.get('folderPath'); var cfgStorageSecretString = configFs.get('secretString'); function getFilePath(strPath) { return path.join(cfgStorageFolderPath, strPath); } function getOutputPath(strPath) { return strPath.replace(/\\/g, '/'); } function removeEmptyParent(strPath, done) { if (cfgStorageFolderPath.length + 1 >= strPath.length) { done(); } else { fs.readdir(strPath, function(err, list) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { if (list.length > 0) { done(); } else { fs.rmdir(strPath, function(err) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { removeEmptyParent(path.dirname(strPath), function(err) { done(err); }); } }); } } }); } } exports.getObject = function(strPath) { return utils.readFile(getFilePath(strPath)); }; exports.putObject = function(strPath, buffer, contentLength) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); mkdirp(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { //todo 0666 if (Buffer.isBuffer(buffer)) { fs.writeFile(fsPath, buffer, function(err) { if (err) { reject(err); } else { resolve(); } }); } else { utils.promiseCreateWriteStream(fsPath).then(function(writable) { buffer.pipe(writable); }).catch(function(err) { reject(err); }); } } }); }); }; exports.listObjects = function(strPath) { return utils.listObjects(getFilePath(strPath)).then(function(values) { return values.map(function(curvalue) { return getOutputPath(curvalue.substring(cfgStorageFolderPath.length + 1)); }); }); }; exports.deleteObject = function(strPath) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); fs.unlink(fsPath, function(err) { if (err) { reject(err); } else { //resolve(); removeEmptyParent(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { resolve(); } }); } }); }); }; exports.deleteObjects = function(strPaths) { return Promise.all(strPaths.map(exports.deleteObject)); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return new Promise(function(resolve, reject) { var userFriendlyName = optFilename ? encodeURIComponent(optFilename) : path.basename(strPath); var uri = '/' + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath + '/' + userFriendlyName; var url = (cfgStorageExternalHost ? cfgStorageExternalHost : baseUrl) + uri; var date = new Date(); var expires = Math.ceil(date.getTime() / 1000) + (optUrlExpires || 604800); // отключил время жизни т.к. существует сценарий, при котором объект // получаемый по ссылке запрашивается после того как закончилось время // его жизни. var md5 = crypto.createHash('md5').update(/*expires + */uri + cfgStorageSecretString).digest("base64"); md5 = md5.replace(/\+/g, "-"); md5 = md5.replace(/\//g, "_"); url += ('?md5=' + md5 + '&expires=' + expires); url += '&response-content-disposition=' + encodeURIComponent(utils.getContentDisposition(null, null, opt_type)); resolve(utils.changeOnlyOfficeUrl(url, strPath, optFilename)); }); }; +var fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var utils = require("./utils"); var crypto = require('crypto'); var configStorage = require('config').get('storage'); var cfgBucketName = configStorage.get('bucketName'); var cfgStorageFolderName = configStorage.get('storageFolderName'); var cfgStorageExternalHost = configStorage.get('externalHost'); var configFs = configStorage.get('fs'); var cfgStorageFolderPath = configFs.get('folderPath'); var cfgStorageSecretString = configFs.get('secretString'); function getFilePath(strPath) { return path.join(cfgStorageFolderPath, strPath); } function getOutputPath(strPath) { return strPath.replace(/\\/g, '/'); } function removeEmptyParent(strPath, done) { if (cfgStorageFolderPath.length + 1 >= strPath.length) { done(); } else { fs.readdir(strPath, function(err, list) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { if (list.length > 0) { done(); } else { fs.rmdir(strPath, function(err) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { removeEmptyParent(path.dirname(strPath), function(err) { done(err); }); } }); } } }); } } exports.getObject = function(strPath) { return utils.readFile(getFilePath(strPath)); }; exports.putObject = function(strPath, buffer, contentLength) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); mkdirp(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { //todo 0666 if (Buffer.isBuffer(buffer)) { fs.writeFile(fsPath, buffer, function(err) { if (err) { reject(err); } else { resolve(); } }); } else { utils.promiseCreateWriteStream(fsPath).then(function(writable) { buffer.pipe(writable); }).catch(function(err) { reject(err); }); } } }); }); }; exports.listObjects = function(strPath) { return utils.listObjects(getFilePath(strPath)).then(function(values) { return values.map(function(curvalue) { return getOutputPath(curvalue.substring(cfgStorageFolderPath.length + 1)); }); }); }; exports.deleteObject = function(strPath) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); fs.unlink(fsPath, function(err) { if (err) { reject(err); } else { //resolve(); removeEmptyParent(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { resolve(); } }); } }); }); }; exports.deleteObjects = function(strPaths) { return Promise.all(strPaths.map(exports.deleteObject)); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return new Promise(function(resolve, reject) { var userFriendlyName = optFilename ? encodeURIComponent(optFilename) : path.basename(strPath); var uri = '/' + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath + '/' + userFriendlyName; var url = (cfgStorageExternalHost ? cfgStorageExternalHost : baseUrl) + uri; var date = new Date(); var expires = Math.ceil(date.getTime() / 1000) + (optUrlExpires || 604800); // отключил время жизни т.к. существует сценарий, при котором объект // получаемый по ссылке запрашивается после того как закончилось время // его жизни. var md5 = crypto.createHash('md5').update(/*expires + */uri + cfgStorageSecretString).digest("base64"); md5 = md5.replace(/\+/g, "-"); md5 = md5.replace(/\//g, "_"); url += ('?md5=' + md5 + '&expires=' + expires); url += '&disposition=' + encodeURIComponent(utils.getContentDisposition(null, null, opt_type)); resolve(utils.changeOnlyOfficeUrl(url, strPath, optFilename)); }); }; diff --git a/DocService/sources/server.js b/DocService/sources/server.js index d9ba8f2ff..69e140ea4 100644 --- a/DocService/sources/server.js +++ b/DocService/sources/server.js @@ -93,7 +93,7 @@ if (cluster.isMaster) { app.use('/' + cfgBucketName + '/' + cfgStorageFolderName, (req, res, next) => { var index = req.url.lastIndexOf('/'); if (-1 != index) { - var contentDisposition = req.query['response-content-disposition'] || 'attachment'; + var contentDisposition = req.query['disposition'] || 'attachment'; var sendFileOptions = { root: configStorage.get('fs.folderPath'), dotfiles: 'deny', From 59820e49e2306cca337df3788c300c6c08181c00 Mon Sep 17 00:00:00 2001 From: "Alexander.Trofimov" Date: Tue, 7 Jun 2016 17:50:59 +0300 Subject: [PATCH 02/20] min count = 1 --- Common/sources/license.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/sources/license.js b/Common/sources/license.js index 5fcf2be55..5fa5693f7 100644 --- a/Common/sources/license.js +++ b/Common/sources/license.js @@ -5,7 +5,7 @@ const constants = require('./constants'); exports.readLicense = function() { const resMax = {count: 999999, type: constants.LICENSE_RESULT.Success}; - var res = {count: 2, type: constants.LICENSE_RESULT.Error}; + var res = {count: 1, type: constants.LICENSE_RESULT.Error}; try { var oLicense = JSON.parse(fs.readFileSync(config.get('license_file')).toString()); const sign = oLicense['signature']; @@ -24,7 +24,7 @@ exports.readLicense = function() { } } } catch(e) { - res.count = 2; + res.count = 1; res.type = constants.LICENSE_RESULT.Error; } return res; From 2f0af5b4473fb3bd47a8073e8882b7aa51c3a8f1 Mon Sep 17 00:00:00 2001 From: Alexey Golubev Date: Tue, 14 Jun 2016 14:24:06 +0300 Subject: [PATCH 03/20] Increase log level till "INFO" --- Common/config/log4js/production.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/config/log4js/production.json b/Common/config/log4js/production.json index e922eeefd..bdaac17ed 100644 --- a/Common/config/log4js/production.json +++ b/Common/config/log4js/production.json @@ -4,6 +4,6 @@ }], "replaceConsole": "true", "levels": { - "nodeJS": "ERROR" + "nodeJS": "INFO" } -} \ No newline at end of file +} From c926594c2e58470b1707c35e9a097051f8cb042b Mon Sep 17 00:00:00 2001 From: Alexey Golubev Date: Tue, 14 Jun 2016 14:34:36 +0300 Subject: [PATCH 04/20] Update production.json --- Common/config/log4js/production.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/config/log4js/production.json b/Common/config/log4js/production.json index bdaac17ed..541d3efab 100644 --- a/Common/config/log4js/production.json +++ b/Common/config/log4js/production.json @@ -4,6 +4,6 @@ }], "replaceConsole": "true", "levels": { - "nodeJS": "INFO" + "nodeJS": "WARN" } } From b7d4ee69d08ea251fa1e8db0958f39ca722d7777 Mon Sep 17 00:00:00 2001 From: "Alexander.Trofimov" Date: Thu, 16 Jun 2016 18:05:36 +0300 Subject: [PATCH 05/20] add Connections --- Common/sources/constants.js | 5 +++- DocService/sources/DocsCoServer.js | 40 +++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Common/sources/constants.js b/Common/sources/constants.js index 9eb94f1f5..04dbed98e 100644 --- a/Common/sources/constants.js +++ b/Common/sources/constants.js @@ -9,9 +9,12 @@ exports.LICENSE_RESULT = { Error : 1, Expired : 2, Success : 3, - UnknownUser : 4 + UnknownUser : 4, + Connections : 5 }; +exports.LICENSE_CONNECTIONS = 21; + exports.AVS_OFFICESTUDIO_FILE_UNKNOWN = 0x0000; exports.AVS_OFFICESTUDIO_FILE_DOCUMENT = 0x0040; exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0001; diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index 1d4c017cd..899ec26fc 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -1825,7 +1825,45 @@ exports.install = function(server, callbackFunction) { } function _checkLicense(conn) { - sendData(conn, {type: 'license', license: licenseInfo}); + return co(function* () { + try { + var license = licenseInfo; + if (constants.LICENSE_RESULT.Success !== licenseInfo) { + license = constants.LICENSE_RESULT.Success; + + var count = constants.LICENSE_CONNECTIONS; + var cursor = '0', sum = 0, scanRes, tmp, length, i, users; + while (true) { + scanRes = yield utils.promiseRedis(redisClient, redisClient.scan, cursor, 'MATCH', redisKeyPresenceHash + '*'); + tmp = scanRes[1]; + sum += (length = tmp.length); + + for (i = 0; i < length; ++i) { + if (sum >= count) { + license = constants.LICENSE_RESULT.Connections; + break; + } + + users = yield utils.promiseRedis(redisClient, redisClient.hlen, tmp[i]); + sum += users - (0 !== users ? 1 : 0); + } + + if (sum >= count) { + license = constants.LICENSE_RESULT.Connections; + break; + } + + cursor = scanRes[0]; + if ('0' === cursor) { + break; + } + } + } + sendData(conn, {type: 'license', license: license}); + } catch (err) { + logger.error('_checkLicense error:\r\n%s', err.stack); + } + }); } sockjs_echo.installHandlers(server, {prefix: '/doc/['+constants.DOC_ID_PATTERN+']*/c', log: function(severity, message) { From b00d888b98ba9160e4de9b6fdfca9668b52e835f Mon Sep 17 00:00:00 2001 From: konovalovsergey Date: Thu, 16 Jun 2016 19:54:13 +0300 Subject: [PATCH 06/20] =?UTF-8?q?=D0=B2=20=D0=BB=D0=BE=D0=B3=D0=B0=D1=85?= =?UTF-8?q?=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=BD=D0=B0=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DocService/sources/DocsCoServer.js | 2 +- DocService/sources/canvasservice.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index 899ec26fc..be485a048 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -1230,7 +1230,7 @@ exports.install = function(server, callbackFunction) { if (bIsRestore) { curIndexUser = user.indexUser; } else { - upsertRes = yield canvasService.commandOpenStartPromise(cmd, true); + upsertRes = yield canvasService.commandOpenStartPromise(docId, cmd, true); var bCreate = upsertRes.affectedRows == 1; if (bCreate) { curIndexUser = 1; diff --git a/DocService/sources/canvasservice.js b/DocService/sources/canvasservice.js index 6179fab96..2c5c09b63 100644 --- a/DocService/sources/canvasservice.js +++ b/DocService/sources/canvasservice.js @@ -1 +1 @@ -var pathModule = require('path'); var urlModule = require('url'); var co = require('co'); var sqlBase = require('./baseConnector'); var docsCoServer = require('./DocsCoServer'); var taskResult = require('./taskresult'); var logger = require('./../../Common/sources/logger'); var utils = require('./../../Common/sources/utils'); var constants = require('./../../Common/sources/constants'); var commonDefines = require('./../../Common/sources/commondefines'); var storage = require('./../../Common/sources/storage-base'); var formatChecker = require('./../../Common/sources/formatchecker'); var statsDClient = require('./../../Common/sources/statsdclient'); var config = require('config'); var config_server = config.get('services.CoAuthoring.server'); var config_utils = config.get('services.CoAuthoring.utils'); var pubsubRedis = require('./pubsubRedis'); var cfgTypesUpload = config_utils.get('limits_image_types_upload'); var cfgTypesCopy = config_utils.get('limits_image_types_copy'); var cfgImageSize = config_server.get('limits_image_size'); var cfgImageDownloadTimeout = config_server.get('limits_image_download_timeout'); var cfgRedisPrefix = config.get('services.CoAuthoring.redis.prefix'); var SAVE_TYPE_PART_START = 0; var SAVE_TYPE_PART = 1; var SAVE_TYPE_COMPLETE = 2; var SAVE_TYPE_COMPLETE_ALL = 3; var clientStatsD = statsDClient.getClient(); var redisClient = pubsubRedis.getClientRedis(); var redisKeySaved = cfgRedisPrefix + constants.REDIS_KEY_SAVED; var redisKeyShutdown = cfgRedisPrefix + constants.REDIS_KEY_SHUTDOWN; function OutputDataWrap(type, data) { this['type'] = type; this['data'] = data; } OutputDataWrap.prototype = { fromObject: function(data) { this['type'] = data['type']; this['data'] = new OutputData(); this['data'].fromObject(data['data']); }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function OutputData(type) { this['type'] = type; this['status'] = undefined; this['data'] = undefined; } OutputData.prototype = { fromObject: function(data) { this['type'] = data['type']; this['status'] = data['status']; this['data'] = data['data']; }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getStatus: function() { return this['status']; }, setStatus: function(data) { this['status'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function* getOutputData(cmd, outputData, key, status, statusInfo, optConn, optAdditionalOutput) { var docId = cmd.getDocId(); switch (status) { case taskResult.FileStatus.SaveVersion: case taskResult.FileStatus.UpdateVersion: case taskResult.FileStatus.Ok: if(taskResult.FileStatus.Ok == status) { outputData.setStatus('ok'); } else if(taskResult.FileStatus.SaveVersion == status) { if (optConn && optConn.user.view) { outputData.setStatus('updateversion'); } else { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = status; updateMask.statusInfo = statusInfo; var updateTask = new taskResult.TaskResultData(); updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateTask, updateMask); if (updateIfRes.affectedRows > 0) { outputData.setStatus('ok'); } else { outputData.setStatus('updateversion'); } } } else { outputData.setStatus('updateversion'); } var command = cmd.getCommand(); if ('open' != command && 'reopen' != command) { var strPath = key + '/' + cmd.getOutputPath(); if (optConn) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = strPath; optAdditionalOutput.needUrlMethod = 2; } } else { if (optConn) { outputData.setData(yield storage.getSignedUrls(optConn.baseUrl, key)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = key; optAdditionalOutput.needUrlMethod = 0; } } break; case taskResult.FileStatus.NeedParams: outputData.setStatus('needparams'); var settingsPath = key + '/' + 'settings.json'; if (optConn) { outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, settingsPath)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = settingsPath; optAdditionalOutput.needUrlMethod = 1; } break; case taskResult.FileStatus.NeedPassword: outputData.setStatus('needpassword'); break; case taskResult.FileStatus.Err: case taskResult.FileStatus.ErrToReload: outputData.setStatus('err'); outputData.setData(statusInfo); if (taskResult.FileStatus.ErrToReload == status) { yield cleanupCache(key); } break; } } function* addRandomKeyTaskCmd(cmd) { var task = yield* taskResult.addRandomKeyTask(cmd.getDocId()); cmd.setSaveKey(task.key); } function* saveParts(cmd) { var result = false; var saveType = cmd.getSaveType(); var filename; if (SAVE_TYPE_COMPLETE_ALL === saveType) { filename = 'Editor.bin'; } else { filename = 'Editor' + (cmd.getSaveIndex() || '') + '.bin'; } if (SAVE_TYPE_PART_START === saveType || SAVE_TYPE_COMPLETE_ALL === saveType) { yield* addRandomKeyTaskCmd(cmd); } if (cmd.getUrl()) { result = true; } else { var buffer = cmd.getData(); yield storage.putObject(cmd.getSaveKey() + '/' + filename, buffer, buffer.length); //delete data to prevent serialize into json cmd.data = null; result = (SAVE_TYPE_COMPLETE_ALL === saveType || SAVE_TYPE_COMPLETE === saveType); } return result; } function getSaveTask(cmd) { cmd.setData(null); var queueData = new commonDefines.TaskQueueData(); queueData.setCmd(cmd); queueData.setToFile(constants.OUTPUT_NAME + '.' + formatChecker.getStringFromFormat(cmd.getOutputFormat())); //todo paid //if (cmd.vkey) { // bool // bPaid; // Signature.getVKeyParams(cmd.vkey, out bPaid); // oTaskQueueData.m_bPaid = bPaid; //} return queueData; } function getUpdateResponse(cmd) { var updateTask = new taskResult.TaskResultData(); updateTask.key = cmd.getSaveKey() ? cmd.getSaveKey() : cmd.getDocId(); var statusInfo = cmd.getStatusInfo(); if (constants.NO_ERROR == statusInfo) { updateTask.status = taskResult.FileStatus.Ok; } else if (constants.CONVERT_DOWNLOAD == statusInfo) { updateTask.status = taskResult.FileStatus.ErrToReload; } else if (constants.CONVERT_NEED_PARAMS == statusInfo) { updateTask.status = taskResult.FileStatus.NeedParams; } else if (constants.CONVERT_DRM == statusInfo) { updateTask.status = taskResult.FileStatus.NeedPassword; } else { updateTask.status = taskResult.FileStatus.Err; } updateTask.statusInfo = statusInfo; if (cmd.getTitle()) { updateTask.title = cmd.getTitle(); } return updateTask; } var cleanupCache = co.wrap(function* (docId) { //todo redis ? var res = false; var removeRes = yield taskResult.remove(docId); if (removeRes.affectedRows > 0) { yield storage.deletePath(docId); res = true; } return res; }); function commandOpenStartPromise(cmd, opt_updateUserIndex) { var task = new taskResult.TaskResultData(); task.key = cmd.getDocId(); task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; task.title = cmd.getTitle(); return taskResult.upsert(task, opt_updateUserIndex); } function* commandOpen(conn, cmd, outputData, opt_upsertRes) { var upsertRes; if (opt_upsertRes) { upsertRes = opt_upsertRes; } else { upsertRes = yield commandOpenStartPromise(cmd); } //if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values //http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html var bCreate = upsertRes.affectedRows == 1; if (!bCreate) { var selectRes = yield taskResult.select(cmd.getDocId()); if (selectRes.length > 0) { var row = selectRes[0]; yield* getOutputData(cmd, outputData, cmd.getDocId(), row.status, row.status_info, conn); } } else { //add task cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); var priority = constants.QUEUE_PRIORITY_HIGH; var formatIn = formatChecker.getFormatFromString(cmd.getFormat()); //decrease pdf, djvu, xps convert priority becase long open time if (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS === formatIn) { priority = constants.QUEUE_PRIORITY_LOW; } yield* docsCoServer.addTask(dataQueue, priority); } } function* commandReopen(cmd) { var task = new taskResult.TaskResultData(); task.key = cmd.getDocId(); task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; var upsertRes = yield taskResult.update(task); if (upsertRes.affectedRows > 0) { //add task cmd.setUrl(null);//url may expire cmd.setSaveKey(cmd.getDocId()); cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); dataQueue.setFromSettings(true); yield* docsCoServer.addTask(dataQueue, constants.QUEUE_PRIORITY_HIGH); } } function* commandSave(cmd, outputData) { var completeParts = yield* saveParts(cmd); if (completeParts) { var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSendMailMerge(cmd, outputData) { var completeParts = yield* saveParts(cmd); var isErr = false; if (completeParts) { isErr = true; var getRes = yield* docsCoServer.getCallback(cmd.getDocId()); if (getRes) { var mailMergeSend = cmd.getMailMergeSend(); mailMergeSend.setUrl(getRes.server.href); mailMergeSend.setBaseUrl(getRes.baseUrl); //меняем JsonKey и SaveKey, новый key нужет потому что за одну конвертацию делается часть, а json нужен всегда mailMergeSend.setJsonKey(cmd.getSaveKey()); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); isErr = false; } } if (isErr) { outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } else { outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } } function* commandSfctByCmd(cmd) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } function* commandSfct(cmd, outputData) { yield* commandSfctByCmd(cmd); outputData.setStatus('ok'); } function isDisplayedImage(strName) { var res = 0; if (strName) { //шаблон display[N]image.ext var findStr = constants.DISPLAY_PREFIX; var index = strName.indexOf(findStr); if (-1 != index) { if (index + findStr.length < strName.length) { var displayN = parseInt(strName[index + findStr.length]); if (1 <= displayN && displayN <= 6) { var imageIndex = index + findStr.length + 1; if (imageIndex == strName.indexOf("image", imageIndex)) res = displayN; } } } } return res; } function* commandImgurls(conn, cmd, outputData) { var supportedFormats; var urls; var errorCode = constants.NO_ERROR; var isImgUrl = 'imgurl' == cmd.getCommand(); if (isImgUrl) { urls = [cmd.getData()]; supportedFormats = cfgTypesUpload || 'jpg'; } else { urls = cmd.getData(); supportedFormats = cfgTypesCopy || 'jpg'; } //todo Promise.all() var displayedImageMap = {};//to make one imageIndex for ole object urls var imageCount = 0; var outputUrls = []; for (var i = 0; i < urls.length; ++i) { var urlSource = urls[i]; var urlParsed; var data = undefined; if (urlSource.startsWith('data:')) { var delimiterIndex = urlSource.indexOf(','); if (-1 != delimiterIndex && (urlSource.length - (delimiterIndex + 1)) * 0.75 <= cfgImageSize) { data = new Buffer(urlSource.substring(delimiterIndex + 1), 'base64'); } } else if(urlSource) { //todo stream data = yield utils.downloadUrlPromise(urlSource, cfgImageDownloadTimeout * 1000, cfgImageSize); urlParsed = urlModule.parse(urlSource); } var outputUrl = {url: 'error', path: 'error'}; if (data) { var format = formatChecker.getImageFormat(data); var formatStr; if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN == format && urlParsed) { //bin, txt occur in ole object case var ext = pathModule.extname(urlParsed.pathname); if ('.bin' == ext || '.txt' == ext) { formatStr = ext.substring(1); } } else { formatStr = formatChecker.getStringFromFormat(format); } if (formatStr && -1 !== supportedFormats.indexOf(formatStr)) { var userid = cmd.getUserId(); var imageIndex = cmd.getSaveIndex() + imageCount; imageCount++; var strLocalPath = 'media/' + utils.crc32(userid).toString(16) + '_'; if (urlParsed) { var urlBasename = pathModule.basename(urlParsed.pathname); var displayN = isDisplayedImage(urlBasename); if (displayN > 0) { var displayedImageName = urlBasename.substring(0, urlBasename.length - formatStr.length - 1); var tempIndex = displayedImageMap[displayedImageName]; if (null != tempIndex) { imageIndex = tempIndex; imageCount--; } else { displayedImageMap[displayedImageName] = imageIndex; } strLocalPath += constants.DISPLAY_PREFIX + displayN; } } strLocalPath += 'image' + imageIndex + '.' + formatStr; var strPath = cmd.getDocId() + '/' + strLocalPath; yield storage.putObject(strPath, data, data.length); var imgUrl = yield storage.getSignedUrl(conn.baseUrl, strPath); outputUrl = {url: imgUrl, path: strLocalPath}; } } if (isImgUrl && ('error' === outputUrl.url || 'error' === outputUrl.path)) { errorCode = constants.UPLOAD_EXTENSION; break; } outputUrls.push(outputUrl); } if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(outputUrls); } } function* commandPathUrl(conn, cmd, outputData) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; var strPath = cmd.getDocId() + '/' + cmd.getData(); var url = yield storage.getSignedUrl(conn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition); var errorCode = constants.NO_ERROR; if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(url); } } function* commandSaveFromOrigin(cmd, outputData) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromOrigin(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSfcCallback(cmd, isSfcm) { var docId = cmd.getDocId(); logger.debug('Start commandSfcCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var isError = constants.NO_ERROR != statusInfo && constants.CONVERT_CORRUPTED != statusInfo; var savePathDoc = saveKey + '/' + cmd.getOutputPath(); var savePathChanges = saveKey + '/changes.zip'; var savePathHistory = saveKey + '/changesHistory.json'; var getRes = yield* docsCoServer.getCallback(docId); if (getRes) { logger.debug('Callback commandSfcCallback: docId = %s callback = %s', docId, getRes.server.href); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (cmd.getUserId()) { outputSfc.setUsers([cmd.getUserId()]); } if (isSfcm) { outputSfc.setActions(undefined); outputSfc.setUserData(cmd.getUserData()); } else { //use UserId case UserActionId miss in gc convertion var userActionId = cmd.getUserActionId() || cmd.getUserId(); if (userActionId) { outputSfc.setActions([new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, userActionId)]); } } if (!isError) { try { var data = yield storage.getObject(savePathHistory); outputSfc.setChangeHistory(data.toString('utf-8')); outputSfc.setUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathDoc)); outputSfc.setChangeUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathChanges)); } catch (e) { logger.error('Error commandSfcCallback: docId = %s\r\n%s', docId, e.stack); } if (outputSfc.getUrl() && outputSfc.getUsers().length > 0) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSaveForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSave); } } else { isError = true; } } if (isError) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.CorruptedForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } } var uri = getRes.server.href; var postData = JSON.stringify(outputSfc); if (isSfcm) { var lastSave = cmd.getLastSave(); if (lastSave && !isError) { yield* docsCoServer.setForceSave(docId, lastSave, savePathDoc); } try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } else { //if anybody in document stop save var hasEditors = yield* docsCoServer.hasEditors(docId); logger.debug('hasEditors commandSfcCallback: docId = %s hasEditors = %d', docId, hasEditors); if (!hasEditors) { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = taskResult.FileStatus.SaveVersion; updateMask.statusInfo = cmd.getData(); var updateIfTask = new taskResult.TaskResultData(); updateIfTask.status = taskResult.FileStatus.UpdateVersion; updateIfTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask); if (updateIfRes.affectedRows > 0) { var replyStr = null; try { replyStr = yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { replyStr = null; logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } var requestRes = false; var replyData = docsCoServer.parseReplyData(docId, replyStr); if (replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error) { //в случае comunity server придет запрос в CommandService проверяем результат var multi = redisClient.multi([ ['get', redisKeySaved + docId], ['del', redisKeySaved + docId] ]); var execRes = yield utils.promiseRedis(multi, multi.exec); var savedVal = execRes[0]; requestRes = (null == savedVal || '1' === savedVal); } if (requestRes) { yield docsCoServer.cleanDocumentOnExitPromise(docId, true); } else { var updateTask = new taskResult.TaskResultData(); updateTask.key = docId; updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; yield taskResult.update(updateTask); } } } } } if (docsCoServer.getIsShutdown() && !isSfcm) { yield utils.promiseRedis(redisClient, redisClient.srem, redisKeyShutdown, docId); } logger.debug('End commandSfcCallback: docId = %s', docId); } function* commandSendMMCallback(cmd) { var docId = cmd.getDocId(); logger.debug('Start commandSendMMCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (constants.NO_ERROR == statusInfo) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MailMerge); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } var mailMergeSendData = cmd.getMailMergeSend(); var outputMailMerge = new commonDefines.OutputMailMerge(mailMergeSendData); outputSfc.setMailMerge(outputMailMerge); outputSfc.setUsers([mailMergeSendData.getUserId()]); var data = yield storage.getObject(saveKey + '/' + cmd.getOutputPath()); var xml = data.toString('utf8'); var files = xml.match(/[< ]file.*?\/>/g); var recordRemain = (mailMergeSendData.getRecordTo() - mailMergeSendData.getRecordFrom() + 1); var recordIndexStart = mailMergeSendData.getRecordCount() - recordRemain; for (var i = 0; i < files.length; ++i) { var file = files[i]; var fieldRes = /field=["'](.*?)["']/.exec(file); outputMailMerge.setTo(fieldRes[1]); outputMailMerge.setRecordIndex(recordIndexStart + i); var pathRes = /path=["'](.*?)["']/.exec(file); var signedUrl = yield storage.getSignedUrl(mailMergeSendData.getBaseUrl(), saveKey + '/' + pathRes[1]); outputSfc.setUrl(signedUrl); var uri = mailMergeSendData.getUrl(); var postData = JSON.stringify(outputSfc); try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } var newRecordFrom = mailMergeSendData.getRecordFrom() + Math.max(files.length, 1); if (newRecordFrom <= mailMergeSendData.getRecordTo()) { mailMergeSendData.setRecordFrom(newRecordFrom); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } else { logger.debug('End MailMerge: docId = %s', docId); } logger.debug('End commandSendMMCallback: docId = %s', docId); } exports.openDocument = function(conn, cmd, opt_upsertRes) { return co(function* () { var outputData; var docId = conn ? conn.docId : 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start command: docId = %s %s', docId, JSON.stringify(cmd)); outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'open': //yield utils.sleep(5000); yield* commandOpen(conn, cmd, outputData, opt_upsertRes); break; case 'reopen': yield* commandReopen(cmd); break; case 'imgurl': case 'imgurls': yield* commandImgurls(conn, cmd, outputData); break; case 'pathurl': yield* commandPathUrl(conn, cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } if(clientStatsD) { clientStatsD.timing('coauth.openDocument.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error openDocument: docId = %s\r\n%s', docId, e.stack); if (!outputData) { outputData = new OutputData(); } outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } finally { if (outputData && outputData.getStatus()) { logger.debug('Response command: docId = %s %s', docId, JSON.stringify(outputData)); docsCoServer.sendData(conn, new OutputDataWrap('documentOpen', outputData)); } logger.debug('End command: docId = %s', docId); } }); }; exports.downloadAs = function(req, res) { return co(function* () { var docId = 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } var strCmd = req.query['cmd']; var cmd = new commonDefines.InputCommand(JSON.parse(strCmd)); docId = cmd.getDocId(); logger.debug('Start downloadAs: docId = %s %s', docId, strCmd); cmd.setData(req.body); var outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'save': yield* commandSave(cmd, outputData); break; case 'savefromorigin': yield* commandSaveFromOrigin(cmd, outputData); break; case 'sendmm': yield* commandSendMailMerge(cmd, outputData); break; case 'sfct': yield* commandSfct(cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } var strRes = JSON.stringify(outputData); res.send(strRes); logger.debug('End downloadAs: docId = %s %s', docId, strRes); if(clientStatsD) { clientStatsD.timing('coauth.downloadAs.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error downloadAs: docId = %s\r\n%s', docId, e.stack); res.sendStatus(400); } }); }; exports.saveFromChanges = function(docId, statusInfo, optFormat, opt_userId, opt_queue) { return co(function* () { try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start saveFromChanges: docId = %s', docId); var task = new taskResult.TaskResultData(); task.key = docId; //делаем select, потому что за время timeout информация могла измениться var selectRes = yield taskResult.select(docId); var row = selectRes.length > 0 ? selectRes[0] : null; if (row && row.status == taskResult.FileStatus.SaveVersion && row.status_info == statusInfo) { if (null == optFormat) { optFormat = constants.AVS_OFFICESTUDIO_FILE_OTHER_TEAMLAB_INNER; } var cmd = new commonDefines.InputCommand(); cmd.setCommand('sfc'); cmd.setDocId(docId); cmd.setOutputFormat(optFormat); cmd.setData(statusInfo); cmd.setUserActionId(opt_userId); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_NORMAL, opt_queue); if (docsCoServer.getIsShutdown()) { yield utils.promiseRedis(redisClient, redisClient.sadd, redisKeyShutdown, docId); } logger.debug('AddTask saveFromChanges: docId = %s', docId); } else { if (row) { logger.debug('saveFromChanges status mismatch: docId = %s; row: %d; %d; expected: %d', docId, row.status, row.status_info, statusInfo); } } if (clientStatsD) { clientStatsD.timing('coauth.saveFromChanges', new Date() - startDate); } } catch (e) { logger.error('Error saveFromChanges: docId = %s\r\n%s', docId, e.stack); } }); }; exports.receiveTask = function(data, dataRaw) { return co(function* () { var docId = 'null'; try { var task = new commonDefines.TaskQueueData(JSON.parse(data)); if (task) { var cmd = task.getCmd(); docId = cmd.getDocId(); logger.debug('Start receiveTask: docId = %s %s', docId, data); var updateTask = getUpdateResponse(cmd); var updateRes = yield taskResult.update(updateTask); if (updateRes.affectedRows > 0) { var outputData = new OutputData(cmd.getCommand()); var command = cmd.getCommand(); var additionalOutput = {needUrlKey: null, needUrlMethod: null}; if ('open' == command || 'reopen' == command) { //yield utils.sleep(5000); yield* getOutputData(cmd, outputData, cmd.getDocId(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('save' == command || 'savefromorigin' == command || 'sfct' == command) { yield* getOutputData(cmd, outputData, cmd.getSaveKey(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('sfcm' == command) { yield* commandSfcCallback(cmd, true); } else if ('sfc' == command) { yield* commandSfcCallback(cmd, false); } else if ('sendmm' == command) { yield* commandSendMMCallback(cmd); } else if ('conv' == command) { //nothing } if (outputData.getStatus()) { logger.debug('Send receiveTask: docId = %s %s', docId, JSON.stringify(outputData)); var output = new OutputDataWrap('documentOpen', outputData); yield* docsCoServer.publish({ type: commonDefines.c_oPublishType.receiveTask, cmd: cmd, output: output, needUrlKey: additionalOutput.needUrlKey, needUrlMethod: additionalOutput.needUrlMethod }); } } yield* docsCoServer.removeResponse(dataRaw); logger.debug('End receiveTask: docId = %s', docId); } } catch (err) { logger.debug('Error receiveTask: docId = %s\r\n%s', docId, err.stack); } }); }; exports.cleanupCache = cleanupCache; exports.commandSfctByCmd = commandSfctByCmd; exports.commandOpenStartPromise = commandOpenStartPromise; exports.OutputDataWrap = OutputDataWrap; exports.OutputData = OutputData; +var pathModule = require('path'); var urlModule = require('url'); var co = require('co'); var sqlBase = require('./baseConnector'); var docsCoServer = require('./DocsCoServer'); var taskResult = require('./taskresult'); var logger = require('./../../Common/sources/logger'); var utils = require('./../../Common/sources/utils'); var constants = require('./../../Common/sources/constants'); var commonDefines = require('./../../Common/sources/commondefines'); var storage = require('./../../Common/sources/storage-base'); var formatChecker = require('./../../Common/sources/formatchecker'); var statsDClient = require('./../../Common/sources/statsdclient'); var config = require('config'); var config_server = config.get('services.CoAuthoring.server'); var config_utils = config.get('services.CoAuthoring.utils'); var pubsubRedis = require('./pubsubRedis'); var cfgTypesUpload = config_utils.get('limits_image_types_upload'); var cfgTypesCopy = config_utils.get('limits_image_types_copy'); var cfgImageSize = config_server.get('limits_image_size'); var cfgImageDownloadTimeout = config_server.get('limits_image_download_timeout'); var cfgRedisPrefix = config.get('services.CoAuthoring.redis.prefix'); var SAVE_TYPE_PART_START = 0; var SAVE_TYPE_PART = 1; var SAVE_TYPE_COMPLETE = 2; var SAVE_TYPE_COMPLETE_ALL = 3; var clientStatsD = statsDClient.getClient(); var redisClient = pubsubRedis.getClientRedis(); var redisKeySaved = cfgRedisPrefix + constants.REDIS_KEY_SAVED; var redisKeyShutdown = cfgRedisPrefix + constants.REDIS_KEY_SHUTDOWN; function OutputDataWrap(type, data) { this['type'] = type; this['data'] = data; } OutputDataWrap.prototype = { fromObject: function(data) { this['type'] = data['type']; this['data'] = new OutputData(); this['data'].fromObject(data['data']); }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function OutputData(type) { this['type'] = type; this['status'] = undefined; this['data'] = undefined; } OutputData.prototype = { fromObject: function(data) { this['type'] = data['type']; this['status'] = data['status']; this['data'] = data['data']; }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getStatus: function() { return this['status']; }, setStatus: function(data) { this['status'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function* getOutputData(cmd, outputData, key, status, statusInfo, optConn, optAdditionalOutput) { var docId = cmd.getDocId(); switch (status) { case taskResult.FileStatus.SaveVersion: case taskResult.FileStatus.UpdateVersion: case taskResult.FileStatus.Ok: if(taskResult.FileStatus.Ok == status) { outputData.setStatus('ok'); } else if(taskResult.FileStatus.SaveVersion == status) { if (optConn && optConn.user.view) { outputData.setStatus('updateversion'); } else { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = status; updateMask.statusInfo = statusInfo; var updateTask = new taskResult.TaskResultData(); updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateTask, updateMask); if (updateIfRes.affectedRows > 0) { outputData.setStatus('ok'); } else { outputData.setStatus('updateversion'); } } } else { outputData.setStatus('updateversion'); } var command = cmd.getCommand(); if ('open' != command && 'reopen' != command) { var strPath = key + '/' + cmd.getOutputPath(); if (optConn) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = strPath; optAdditionalOutput.needUrlMethod = 2; } } else { if (optConn) { outputData.setData(yield storage.getSignedUrls(optConn.baseUrl, key)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = key; optAdditionalOutput.needUrlMethod = 0; } } break; case taskResult.FileStatus.NeedParams: outputData.setStatus('needparams'); var settingsPath = key + '/' + 'settings.json'; if (optConn) { outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, settingsPath)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = settingsPath; optAdditionalOutput.needUrlMethod = 1; } break; case taskResult.FileStatus.NeedPassword: outputData.setStatus('needpassword'); break; case taskResult.FileStatus.Err: case taskResult.FileStatus.ErrToReload: outputData.setStatus('err'); outputData.setData(statusInfo); if (taskResult.FileStatus.ErrToReload == status) { yield cleanupCache(key); } break; } } function* addRandomKeyTaskCmd(cmd) { var task = yield* taskResult.addRandomKeyTask(cmd.getDocId()); cmd.setSaveKey(task.key); } function* saveParts(cmd) { var result = false; var saveType = cmd.getSaveType(); var filename; if (SAVE_TYPE_COMPLETE_ALL === saveType) { filename = 'Editor.bin'; } else { filename = 'Editor' + (cmd.getSaveIndex() || '') + '.bin'; } if (SAVE_TYPE_PART_START === saveType || SAVE_TYPE_COMPLETE_ALL === saveType) { yield* addRandomKeyTaskCmd(cmd); } if (cmd.getUrl()) { result = true; } else { var buffer = cmd.getData(); yield storage.putObject(cmd.getSaveKey() + '/' + filename, buffer, buffer.length); //delete data to prevent serialize into json cmd.data = null; result = (SAVE_TYPE_COMPLETE_ALL === saveType || SAVE_TYPE_COMPLETE === saveType); } return result; } function getSaveTask(cmd) { cmd.setData(null); var queueData = new commonDefines.TaskQueueData(); queueData.setCmd(cmd); queueData.setToFile(constants.OUTPUT_NAME + '.' + formatChecker.getStringFromFormat(cmd.getOutputFormat())); //todo paid //if (cmd.vkey) { // bool // bPaid; // Signature.getVKeyParams(cmd.vkey, out bPaid); // oTaskQueueData.m_bPaid = bPaid; //} return queueData; } function getUpdateResponse(cmd) { var updateTask = new taskResult.TaskResultData(); updateTask.key = cmd.getSaveKey() ? cmd.getSaveKey() : cmd.getDocId(); var statusInfo = cmd.getStatusInfo(); if (constants.NO_ERROR == statusInfo) { updateTask.status = taskResult.FileStatus.Ok; } else if (constants.CONVERT_DOWNLOAD == statusInfo) { updateTask.status = taskResult.FileStatus.ErrToReload; } else if (constants.CONVERT_NEED_PARAMS == statusInfo) { updateTask.status = taskResult.FileStatus.NeedParams; } else if (constants.CONVERT_DRM == statusInfo) { updateTask.status = taskResult.FileStatus.NeedPassword; } else { updateTask.status = taskResult.FileStatus.Err; } updateTask.statusInfo = statusInfo; if (cmd.getTitle()) { updateTask.title = cmd.getTitle(); } return updateTask; } var cleanupCache = co.wrap(function* (docId) { //todo redis ? var res = false; var removeRes = yield taskResult.remove(docId); if (removeRes.affectedRows > 0) { yield storage.deletePath(docId); res = true; } return res; }); function commandOpenStartPromise(docId, cmd, opt_updateUserIndex) { var task = new taskResult.TaskResultData(); task.key = docId; task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; if (cmd) { task.title = cmd.getTitle(); } else { logger.warn("commandOpenStartPromise empty cmd: docId = %s", docId); } return taskResult.upsert(task, opt_updateUserIndex); } function* commandOpen(conn, cmd, outputData, opt_upsertRes) { var upsertRes; if (opt_upsertRes) { upsertRes = opt_upsertRes; } else { upsertRes = yield commandOpenStartPromise(cmd.getDocId(), cmd); } //if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values //http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html var bCreate = upsertRes.affectedRows == 1; if (!bCreate) { var selectRes = yield taskResult.select(cmd.getDocId()); if (selectRes.length > 0) { var row = selectRes[0]; yield* getOutputData(cmd, outputData, cmd.getDocId(), row.status, row.status_info, conn); } } else { //add task cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); var priority = constants.QUEUE_PRIORITY_HIGH; var formatIn = formatChecker.getFormatFromString(cmd.getFormat()); //decrease pdf, djvu, xps convert priority becase long open time if (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS === formatIn) { priority = constants.QUEUE_PRIORITY_LOW; } yield* docsCoServer.addTask(dataQueue, priority); } } function* commandReopen(cmd) { var task = new taskResult.TaskResultData(); task.key = cmd.getDocId(); task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; var upsertRes = yield taskResult.update(task); if (upsertRes.affectedRows > 0) { //add task cmd.setUrl(null);//url may expire cmd.setSaveKey(cmd.getDocId()); cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); dataQueue.setFromSettings(true); yield* docsCoServer.addTask(dataQueue, constants.QUEUE_PRIORITY_HIGH); } } function* commandSave(cmd, outputData) { var completeParts = yield* saveParts(cmd); if (completeParts) { var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSendMailMerge(cmd, outputData) { var completeParts = yield* saveParts(cmd); var isErr = false; if (completeParts) { isErr = true; var getRes = yield* docsCoServer.getCallback(cmd.getDocId()); if (getRes) { var mailMergeSend = cmd.getMailMergeSend(); mailMergeSend.setUrl(getRes.server.href); mailMergeSend.setBaseUrl(getRes.baseUrl); //меняем JsonKey и SaveKey, новый key нужет потому что за одну конвертацию делается часть, а json нужен всегда mailMergeSend.setJsonKey(cmd.getSaveKey()); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); isErr = false; } } if (isErr) { outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } else { outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } } function* commandSfctByCmd(cmd) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } function* commandSfct(cmd, outputData) { yield* commandSfctByCmd(cmd); outputData.setStatus('ok'); } function isDisplayedImage(strName) { var res = 0; if (strName) { //шаблон display[N]image.ext var findStr = constants.DISPLAY_PREFIX; var index = strName.indexOf(findStr); if (-1 != index) { if (index + findStr.length < strName.length) { var displayN = parseInt(strName[index + findStr.length]); if (1 <= displayN && displayN <= 6) { var imageIndex = index + findStr.length + 1; if (imageIndex == strName.indexOf("image", imageIndex)) res = displayN; } } } } return res; } function* commandImgurls(conn, cmd, outputData) { var supportedFormats; var urls; var errorCode = constants.NO_ERROR; var isImgUrl = 'imgurl' == cmd.getCommand(); if (isImgUrl) { urls = [cmd.getData()]; supportedFormats = cfgTypesUpload || 'jpg'; } else { urls = cmd.getData(); supportedFormats = cfgTypesCopy || 'jpg'; } //todo Promise.all() var displayedImageMap = {};//to make one imageIndex for ole object urls var imageCount = 0; var outputUrls = []; for (var i = 0; i < urls.length; ++i) { var urlSource = urls[i]; var urlParsed; var data = undefined; if (urlSource.startsWith('data:')) { var delimiterIndex = urlSource.indexOf(','); if (-1 != delimiterIndex && (urlSource.length - (delimiterIndex + 1)) * 0.75 <= cfgImageSize) { data = new Buffer(urlSource.substring(delimiterIndex + 1), 'base64'); } } else if(urlSource) { //todo stream data = yield utils.downloadUrlPromise(urlSource, cfgImageDownloadTimeout * 1000, cfgImageSize); urlParsed = urlModule.parse(urlSource); } var outputUrl = {url: 'error', path: 'error'}; if (data) { var format = formatChecker.getImageFormat(data); var formatStr; if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN == format && urlParsed) { //bin, txt occur in ole object case var ext = pathModule.extname(urlParsed.pathname); if ('.bin' == ext || '.txt' == ext) { formatStr = ext.substring(1); } } else { formatStr = formatChecker.getStringFromFormat(format); } if (formatStr && -1 !== supportedFormats.indexOf(formatStr)) { var userid = cmd.getUserId(); var imageIndex = cmd.getSaveIndex() + imageCount; imageCount++; var strLocalPath = 'media/' + utils.crc32(userid).toString(16) + '_'; if (urlParsed) { var urlBasename = pathModule.basename(urlParsed.pathname); var displayN = isDisplayedImage(urlBasename); if (displayN > 0) { var displayedImageName = urlBasename.substring(0, urlBasename.length - formatStr.length - 1); var tempIndex = displayedImageMap[displayedImageName]; if (null != tempIndex) { imageIndex = tempIndex; imageCount--; } else { displayedImageMap[displayedImageName] = imageIndex; } strLocalPath += constants.DISPLAY_PREFIX + displayN; } } strLocalPath += 'image' + imageIndex + '.' + formatStr; var strPath = cmd.getDocId() + '/' + strLocalPath; yield storage.putObject(strPath, data, data.length); var imgUrl = yield storage.getSignedUrl(conn.baseUrl, strPath); outputUrl = {url: imgUrl, path: strLocalPath}; } } if (isImgUrl && ('error' === outputUrl.url || 'error' === outputUrl.path)) { errorCode = constants.UPLOAD_EXTENSION; break; } outputUrls.push(outputUrl); } if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(outputUrls); } } function* commandPathUrl(conn, cmd, outputData) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; var strPath = cmd.getDocId() + '/' + cmd.getData(); var url = yield storage.getSignedUrl(conn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition); var errorCode = constants.NO_ERROR; if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(url); } } function* commandSaveFromOrigin(cmd, outputData) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromOrigin(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSfcCallback(cmd, isSfcm) { var docId = cmd.getDocId(); logger.debug('Start commandSfcCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var isError = constants.NO_ERROR != statusInfo && constants.CONVERT_CORRUPTED != statusInfo; var savePathDoc = saveKey + '/' + cmd.getOutputPath(); var savePathChanges = saveKey + '/changes.zip'; var savePathHistory = saveKey + '/changesHistory.json'; var getRes = yield* docsCoServer.getCallback(docId); if (getRes) { logger.debug('Callback commandSfcCallback: docId = %s callback = %s', docId, getRes.server.href); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (cmd.getUserId()) { outputSfc.setUsers([cmd.getUserId()]); } if (isSfcm) { outputSfc.setActions(undefined); outputSfc.setUserData(cmd.getUserData()); } else { //use UserId case UserActionId miss in gc convertion var userActionId = cmd.getUserActionId() || cmd.getUserId(); if (userActionId) { outputSfc.setActions([new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, userActionId)]); } } if (!isError) { try { var data = yield storage.getObject(savePathHistory); outputSfc.setChangeHistory(data.toString('utf-8')); outputSfc.setUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathDoc)); outputSfc.setChangeUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathChanges)); } catch (e) { logger.error('Error commandSfcCallback: docId = %s\r\n%s', docId, e.stack); } if (outputSfc.getUrl() && outputSfc.getUsers().length > 0) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSaveForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSave); } } else { isError = true; } } if (isError) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.CorruptedForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } } var uri = getRes.server.href; var postData = JSON.stringify(outputSfc); if (isSfcm) { var lastSave = cmd.getLastSave(); if (lastSave && !isError) { yield* docsCoServer.setForceSave(docId, lastSave, savePathDoc); } try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } else { //if anybody in document stop save var hasEditors = yield* docsCoServer.hasEditors(docId); logger.debug('hasEditors commandSfcCallback: docId = %s hasEditors = %d', docId, hasEditors); if (!hasEditors) { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = taskResult.FileStatus.SaveVersion; updateMask.statusInfo = cmd.getData(); var updateIfTask = new taskResult.TaskResultData(); updateIfTask.status = taskResult.FileStatus.UpdateVersion; updateIfTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask); if (updateIfRes.affectedRows > 0) { var replyStr = null; try { replyStr = yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { replyStr = null; logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } var requestRes = false; var replyData = docsCoServer.parseReplyData(docId, replyStr); if (replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error) { //в случае comunity server придет запрос в CommandService проверяем результат var multi = redisClient.multi([ ['get', redisKeySaved + docId], ['del', redisKeySaved + docId] ]); var execRes = yield utils.promiseRedis(multi, multi.exec); var savedVal = execRes[0]; requestRes = (null == savedVal || '1' === savedVal); } if (requestRes) { yield docsCoServer.cleanDocumentOnExitPromise(docId, true); } else { var updateTask = new taskResult.TaskResultData(); updateTask.key = docId; updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; yield taskResult.update(updateTask); } } } } } if (docsCoServer.getIsShutdown() && !isSfcm) { yield utils.promiseRedis(redisClient, redisClient.srem, redisKeyShutdown, docId); } logger.debug('End commandSfcCallback: docId = %s', docId); } function* commandSendMMCallback(cmd) { var docId = cmd.getDocId(); logger.debug('Start commandSendMMCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (constants.NO_ERROR == statusInfo) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MailMerge); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } var mailMergeSendData = cmd.getMailMergeSend(); var outputMailMerge = new commonDefines.OutputMailMerge(mailMergeSendData); outputSfc.setMailMerge(outputMailMerge); outputSfc.setUsers([mailMergeSendData.getUserId()]); var data = yield storage.getObject(saveKey + '/' + cmd.getOutputPath()); var xml = data.toString('utf8'); var files = xml.match(/[< ]file.*?\/>/g); var recordRemain = (mailMergeSendData.getRecordTo() - mailMergeSendData.getRecordFrom() + 1); var recordIndexStart = mailMergeSendData.getRecordCount() - recordRemain; for (var i = 0; i < files.length; ++i) { var file = files[i]; var fieldRes = /field=["'](.*?)["']/.exec(file); outputMailMerge.setTo(fieldRes[1]); outputMailMerge.setRecordIndex(recordIndexStart + i); var pathRes = /path=["'](.*?)["']/.exec(file); var signedUrl = yield storage.getSignedUrl(mailMergeSendData.getBaseUrl(), saveKey + '/' + pathRes[1]); outputSfc.setUrl(signedUrl); var uri = mailMergeSendData.getUrl(); var postData = JSON.stringify(outputSfc); try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } var newRecordFrom = mailMergeSendData.getRecordFrom() + Math.max(files.length, 1); if (newRecordFrom <= mailMergeSendData.getRecordTo()) { mailMergeSendData.setRecordFrom(newRecordFrom); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } else { logger.debug('End MailMerge: docId = %s', docId); } logger.debug('End commandSendMMCallback: docId = %s', docId); } exports.openDocument = function(conn, cmd, opt_upsertRes) { return co(function* () { var outputData; var docId = conn ? conn.docId : 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start command: docId = %s %s', docId, JSON.stringify(cmd)); outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'open': //yield utils.sleep(5000); yield* commandOpen(conn, cmd, outputData, opt_upsertRes); break; case 'reopen': yield* commandReopen(cmd); break; case 'imgurl': case 'imgurls': yield* commandImgurls(conn, cmd, outputData); break; case 'pathurl': yield* commandPathUrl(conn, cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } if(clientStatsD) { clientStatsD.timing('coauth.openDocument.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error openDocument: docId = %s\r\n%s', docId, e.stack); if (!outputData) { outputData = new OutputData(); } outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } finally { if (outputData && outputData.getStatus()) { logger.debug('Response command: docId = %s %s', docId, JSON.stringify(outputData)); docsCoServer.sendData(conn, new OutputDataWrap('documentOpen', outputData)); } logger.debug('End command: docId = %s', docId); } }); }; exports.downloadAs = function(req, res) { return co(function* () { var docId = 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } var strCmd = req.query['cmd']; var cmd = new commonDefines.InputCommand(JSON.parse(strCmd)); docId = cmd.getDocId(); logger.debug('Start downloadAs: docId = %s %s', docId, strCmd); cmd.setData(req.body); var outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'save': yield* commandSave(cmd, outputData); break; case 'savefromorigin': yield* commandSaveFromOrigin(cmd, outputData); break; case 'sendmm': yield* commandSendMailMerge(cmd, outputData); break; case 'sfct': yield* commandSfct(cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } var strRes = JSON.stringify(outputData); res.send(strRes); logger.debug('End downloadAs: docId = %s %s', docId, strRes); if(clientStatsD) { clientStatsD.timing('coauth.downloadAs.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error downloadAs: docId = %s\r\n%s', docId, e.stack); res.sendStatus(400); } }); }; exports.saveFromChanges = function(docId, statusInfo, optFormat, opt_userId, opt_queue) { return co(function* () { try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start saveFromChanges: docId = %s', docId); var task = new taskResult.TaskResultData(); task.key = docId; //делаем select, потому что за время timeout информация могла измениться var selectRes = yield taskResult.select(docId); var row = selectRes.length > 0 ? selectRes[0] : null; if (row && row.status == taskResult.FileStatus.SaveVersion && row.status_info == statusInfo) { if (null == optFormat) { optFormat = constants.AVS_OFFICESTUDIO_FILE_OTHER_TEAMLAB_INNER; } var cmd = new commonDefines.InputCommand(); cmd.setCommand('sfc'); cmd.setDocId(docId); cmd.setOutputFormat(optFormat); cmd.setData(statusInfo); cmd.setUserActionId(opt_userId); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_NORMAL, opt_queue); if (docsCoServer.getIsShutdown()) { yield utils.promiseRedis(redisClient, redisClient.sadd, redisKeyShutdown, docId); } logger.debug('AddTask saveFromChanges: docId = %s', docId); } else { if (row) { logger.debug('saveFromChanges status mismatch: docId = %s; row: %d; %d; expected: %d', docId, row.status, row.status_info, statusInfo); } } if (clientStatsD) { clientStatsD.timing('coauth.saveFromChanges', new Date() - startDate); } } catch (e) { logger.error('Error saveFromChanges: docId = %s\r\n%s', docId, e.stack); } }); }; exports.receiveTask = function(data, dataRaw) { return co(function* () { var docId = 'null'; try { var task = new commonDefines.TaskQueueData(JSON.parse(data)); if (task) { var cmd = task.getCmd(); docId = cmd.getDocId(); logger.debug('Start receiveTask: docId = %s %s', docId, data); var updateTask = getUpdateResponse(cmd); var updateRes = yield taskResult.update(updateTask); if (updateRes.affectedRows > 0) { var outputData = new OutputData(cmd.getCommand()); var command = cmd.getCommand(); var additionalOutput = {needUrlKey: null, needUrlMethod: null}; if ('open' == command || 'reopen' == command) { //yield utils.sleep(5000); yield* getOutputData(cmd, outputData, cmd.getDocId(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('save' == command || 'savefromorigin' == command || 'sfct' == command) { yield* getOutputData(cmd, outputData, cmd.getSaveKey(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('sfcm' == command) { yield* commandSfcCallback(cmd, true); } else if ('sfc' == command) { yield* commandSfcCallback(cmd, false); } else if ('sendmm' == command) { yield* commandSendMMCallback(cmd); } else if ('conv' == command) { //nothing } if (outputData.getStatus()) { logger.debug('Send receiveTask: docId = %s %s', docId, JSON.stringify(outputData)); var output = new OutputDataWrap('documentOpen', outputData); yield* docsCoServer.publish({ type: commonDefines.c_oPublishType.receiveTask, cmd: cmd, output: output, needUrlKey: additionalOutput.needUrlKey, needUrlMethod: additionalOutput.needUrlMethod }); } } yield* docsCoServer.removeResponse(dataRaw); logger.debug('End receiveTask: docId = %s', docId); } } catch (err) { logger.debug('Error receiveTask: docId = %s\r\n%s', docId, err.stack); } }); }; exports.cleanupCache = cleanupCache; exports.commandSfctByCmd = commandSfctByCmd; exports.commandOpenStartPromise = commandOpenStartPromise; exports.OutputDataWrap = OutputDataWrap; exports.OutputData = OutputData; \ No newline at end of file From 98a7458aebdf9f63219b44610a9803fb854e5b4b Mon Sep 17 00:00:00 2001 From: "Alexander.Trofimov" Date: Mon, 20 Jun 2016 18:34:32 +0300 Subject: [PATCH 07/20] add AGPL header --- Common/sources/commondefines.js | 32 ++++++++++++++++ Common/sources/constants.js | 31 +++++++++++++++ Common/sources/formatchecker.js | 32 ++++++++++++++++ Common/sources/license.js | 32 ++++++++++++++++ Common/sources/logger.js | 32 ++++++++++++++++ Common/sources/rabbitMQCore.js | 32 ++++++++++++++++ Common/sources/statsdclient.js | 32 ++++++++++++++++ Common/sources/storage-base.js | 2 +- Common/sources/storage-fs.js | 2 +- Common/sources/storage-s3.js | 2 +- Common/sources/taskqueueRabbitMQ.js | 32 ++++++++++++++++ Common/sources/utils.js | 32 ++++++++++++++++ DocService/sources/DocsCoServer.js | 32 ++++++++++++++++ DocService/sources/baseConnector.js | 32 ++++++++++++++++ DocService/sources/canvasservice.js | 2 +- DocService/sources/converterservice.js | 32 ++++++++++++++++ DocService/sources/database.js | 2 +- DocService/sources/fileuploaderservice.js | 32 ++++++++++++++++ DocService/sources/fontservice.js | 32 ++++++++++++++++ DocService/sources/gc.js | 32 ++++++++++++++++ DocService/sources/mySqlBaseConnector.js | 2 +- DocService/sources/postgreSqlBaseConnector.js | 32 ++++++++++++++++ DocService/sources/pubsubRabbitMQ.js | 32 ++++++++++++++++ DocService/sources/pubsubRedis.js | 32 ++++++++++++++++ DocService/sources/server.js | 32 ++++++++++++++++ DocService/sources/shutdown.js | 38 +++++++++++-------- DocService/sources/taskresult.js | 32 ++++++++++++++++ FileConverter/sources/converter.js | 32 ++++++++++++++++ FileConverter/sources/convertermaster.js | 32 ++++++++++++++++ Gruntfile.js | 32 ++++++++++++++++ Metrics/config/config.js | 32 ++++++++++++++++ SpellChecker/sources/server.js | 34 ++++++++++++++++- SpellChecker/sources/spellCheck.js | 34 ++++++++++++++++- 33 files changed, 862 insertions(+), 23 deletions(-) diff --git a/Common/sources/commondefines.js b/Common/sources/commondefines.js index f01eeaacb..ff537da2a 100644 --- a/Common/sources/commondefines.js +++ b/Common/sources/commondefines.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 constants = require('./constants'); function InputCommand(data) { diff --git a/Common/sources/constants.js b/Common/sources/constants.js index 04dbed98e..33e1d1386 100644 --- a/Common/sources/constants.js +++ b/Common/sources/constants.js @@ -1,3 +1,34 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ exports.DOC_ID_PATTERN = '0-9-.a-zA-Z_='; exports.CHAR_DELIMITER = String.fromCharCode(5); diff --git a/Common/sources/formatchecker.js b/Common/sources/formatchecker.js index 5886ffe72..c417b5fb3 100644 --- a/Common/sources/formatchecker.js +++ b/Common/sources/formatchecker.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 path = require('path'); var constants = require('./constants'); var logger = require('./logger'); diff --git a/Common/sources/license.js b/Common/sources/license.js index 5fa5693f7..9fdefd7f5 100644 --- a/Common/sources/license.js +++ b/Common/sources/license.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + const crypto = require('crypto'); const fs = require('fs'); const config = require('config').get('license'); diff --git a/Common/sources/logger.js b/Common/sources/logger.js index 4d0f832d1..0ac5fa36e 100644 --- a/Common/sources/logger.js +++ b/Common/sources/logger.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 config = require('config'); var log4js = require('log4js'); diff --git a/Common/sources/rabbitMQCore.js b/Common/sources/rabbitMQCore.js index c95256ed4..19e88d26c 100644 --- a/Common/sources/rabbitMQCore.js +++ b/Common/sources/rabbitMQCore.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + 'use strict'; var config = require('config'); var amqp = require('amqplib/callback_api'); diff --git a/Common/sources/statsdclient.js b/Common/sources/statsdclient.js index 327a19aee..d90749685 100644 --- a/Common/sources/statsdclient.js +++ b/Common/sources/statsdclient.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 statsD = require('node-statsd'); var configStatsD = require('config').get('statsd'); diff --git a/Common/sources/storage-base.js b/Common/sources/storage-base.js index 2d2a926aa..09fa2a6a9 100644 --- a/Common/sources/storage-base.js +++ b/Common/sources/storage-base.js @@ -1 +1 @@ -'use strict'; var config = require('config'); var utils = require('./utils'); var logger = require('./logger'); var storage = require('./' + config.get('storage.name')); function getStoragePath(strPath) { return strPath.replace(/\\/g, '/'); } exports.getObject = function(strPath) { return storage.getObject(getStoragePath(strPath)); }; exports.putObject = function(strPath, buffer, contentLength) { return storage.putObject(getStoragePath(strPath), buffer, contentLength); }; exports.listObjects = function(strPath) { return storage.listObjects(getStoragePath(strPath)).catch(function(e) { logger.error('storage.listObjects:\r\n%s', e.stack); return []; }); }; exports.deleteObject = function(strPath) { return storage.deleteObject(getStoragePath(strPath)); }; exports.deleteObjects = function(strPaths) { var StoragePaths = strPaths.map(function(curValue) { return getStoragePath(curValue); }); return storage.deleteObjects(StoragePaths); }; exports.deletePath = function(strPath) { return exports.listObjects(getStoragePath(strPath)).then(function(list) { return exports.deleteObjects(list); }); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return storage.getSignedUrl(baseUrl, getStoragePath(strPath), optUrlExpires, optFilename, opt_type); }; exports.getSignedUrls = function(baseUrl, strPath, optUrlExpires) { return exports.listObjects(getStoragePath(strPath)).then(function(list) { return Promise.all(list.map(function(curValue) { return exports.getSignedUrl(baseUrl, curValue, optUrlExpires); })).then(function(urls) { var outputMap = {}; for (var i = 0; i < list.length && i < urls.length; ++i) { outputMap[exports.getRelativePath(strPath, list[i])] = urls[i]; } return outputMap; }); }); }; exports.getSignedUrlsByArray = function(baseUrl, list, optPath, optUrlExpires) { return Promise.all(list.map(function(curValue) { return exports.getSignedUrl(baseUrl, curValue, optUrlExpires); })).then(function(urls) { var outputMap = {}; for (var i = 0; i < list.length && i < urls.length; ++i) { if (optPath) { outputMap[exports.getRelativePath(optPath, list[i])] = urls[i]; } else { outputMap[list[i]] = urls[i]; } } return outputMap; }); }; exports.getRelativePath = function(strBase, strPath) { return strPath.substring(strBase.length + 1); }; +/* * (c) Copyright Ascensio System SIA 2010-2016 * * 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 * */ 'use strict'; var config = require('config'); var utils = require('./utils'); var logger = require('./logger'); var storage = require('./' + config.get('storage.name')); function getStoragePath(strPath) { return strPath.replace(/\\/g, '/'); } exports.getObject = function(strPath) { return storage.getObject(getStoragePath(strPath)); }; exports.putObject = function(strPath, buffer, contentLength) { return storage.putObject(getStoragePath(strPath), buffer, contentLength); }; exports.listObjects = function(strPath) { return storage.listObjects(getStoragePath(strPath)).catch(function(e) { logger.error('storage.listObjects:\r\n%s', e.stack); return []; }); }; exports.deleteObject = function(strPath) { return storage.deleteObject(getStoragePath(strPath)); }; exports.deleteObjects = function(strPaths) { var StoragePaths = strPaths.map(function(curValue) { return getStoragePath(curValue); }); return storage.deleteObjects(StoragePaths); }; exports.deletePath = function(strPath) { return exports.listObjects(getStoragePath(strPath)).then(function(list) { return exports.deleteObjects(list); }); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return storage.getSignedUrl(baseUrl, getStoragePath(strPath), optUrlExpires, optFilename, opt_type); }; exports.getSignedUrls = function(baseUrl, strPath, optUrlExpires) { return exports.listObjects(getStoragePath(strPath)).then(function(list) { return Promise.all(list.map(function(curValue) { return exports.getSignedUrl(baseUrl, curValue, optUrlExpires); })).then(function(urls) { var outputMap = {}; for (var i = 0; i < list.length && i < urls.length; ++i) { outputMap[exports.getRelativePath(strPath, list[i])] = urls[i]; } return outputMap; }); }); }; exports.getSignedUrlsByArray = function(baseUrl, list, optPath, optUrlExpires) { return Promise.all(list.map(function(curValue) { return exports.getSignedUrl(baseUrl, curValue, optUrlExpires); })).then(function(urls) { var outputMap = {}; for (var i = 0; i < list.length && i < urls.length; ++i) { if (optPath) { outputMap[exports.getRelativePath(optPath, list[i])] = urls[i]; } else { outputMap[list[i]] = urls[i]; } } return outputMap; }); }; exports.getRelativePath = function(strBase, strPath) { return strPath.substring(strBase.length + 1); }; \ No newline at end of file diff --git a/Common/sources/storage-fs.js b/Common/sources/storage-fs.js index 7103bb067..2039e4a5e 100644 --- a/Common/sources/storage-fs.js +++ b/Common/sources/storage-fs.js @@ -1 +1 @@ -var fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var utils = require("./utils"); var crypto = require('crypto'); var configStorage = require('config').get('storage'); var cfgBucketName = configStorage.get('bucketName'); var cfgStorageFolderName = configStorage.get('storageFolderName'); var cfgStorageExternalHost = configStorage.get('externalHost'); var configFs = configStorage.get('fs'); var cfgStorageFolderPath = configFs.get('folderPath'); var cfgStorageSecretString = configFs.get('secretString'); function getFilePath(strPath) { return path.join(cfgStorageFolderPath, strPath); } function getOutputPath(strPath) { return strPath.replace(/\\/g, '/'); } function removeEmptyParent(strPath, done) { if (cfgStorageFolderPath.length + 1 >= strPath.length) { done(); } else { fs.readdir(strPath, function(err, list) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { if (list.length > 0) { done(); } else { fs.rmdir(strPath, function(err) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { removeEmptyParent(path.dirname(strPath), function(err) { done(err); }); } }); } } }); } } exports.getObject = function(strPath) { return utils.readFile(getFilePath(strPath)); }; exports.putObject = function(strPath, buffer, contentLength) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); mkdirp(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { //todo 0666 if (Buffer.isBuffer(buffer)) { fs.writeFile(fsPath, buffer, function(err) { if (err) { reject(err); } else { resolve(); } }); } else { utils.promiseCreateWriteStream(fsPath).then(function(writable) { buffer.pipe(writable); }).catch(function(err) { reject(err); }); } } }); }); }; exports.listObjects = function(strPath) { return utils.listObjects(getFilePath(strPath)).then(function(values) { return values.map(function(curvalue) { return getOutputPath(curvalue.substring(cfgStorageFolderPath.length + 1)); }); }); }; exports.deleteObject = function(strPath) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); fs.unlink(fsPath, function(err) { if (err) { reject(err); } else { //resolve(); removeEmptyParent(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { resolve(); } }); } }); }); }; exports.deleteObjects = function(strPaths) { return Promise.all(strPaths.map(exports.deleteObject)); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return new Promise(function(resolve, reject) { var userFriendlyName = optFilename ? encodeURIComponent(optFilename) : path.basename(strPath); var uri = '/' + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath + '/' + userFriendlyName; var url = (cfgStorageExternalHost ? cfgStorageExternalHost : baseUrl) + uri; var date = new Date(); var expires = Math.ceil(date.getTime() / 1000) + (optUrlExpires || 604800); // отключил время жизни т.к. существует сценарий, при котором объект // получаемый по ссылке запрашивается после того как закончилось время // его жизни. var md5 = crypto.createHash('md5').update(/*expires + */uri + cfgStorageSecretString).digest("base64"); md5 = md5.replace(/\+/g, "-"); md5 = md5.replace(/\//g, "_"); url += ('?md5=' + md5 + '&expires=' + expires); url += '&disposition=' + encodeURIComponent(utils.getContentDisposition(null, null, opt_type)); resolve(utils.changeOnlyOfficeUrl(url, strPath, optFilename)); }); }; +/* * (c) Copyright Ascensio System SIA 2010-2016 * * 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 fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var utils = require("./utils"); var crypto = require('crypto'); var configStorage = require('config').get('storage'); var cfgBucketName = configStorage.get('bucketName'); var cfgStorageFolderName = configStorage.get('storageFolderName'); var cfgStorageExternalHost = configStorage.get('externalHost'); var configFs = configStorage.get('fs'); var cfgStorageFolderPath = configFs.get('folderPath'); var cfgStorageSecretString = configFs.get('secretString'); function getFilePath(strPath) { return path.join(cfgStorageFolderPath, strPath); } function getOutputPath(strPath) { return strPath.replace(/\\/g, '/'); } function removeEmptyParent(strPath, done) { if (cfgStorageFolderPath.length + 1 >= strPath.length) { done(); } else { fs.readdir(strPath, function(err, list) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { if (list.length > 0) { done(); } else { fs.rmdir(strPath, function(err) { if (err) { //не реагируем на ошибку, потому скорее всего эта папка удалилась в соседнем потоке done(); } else { removeEmptyParent(path.dirname(strPath), function(err) { done(err); }); } }); } } }); } } exports.getObject = function(strPath) { return utils.readFile(getFilePath(strPath)); }; exports.putObject = function(strPath, buffer, contentLength) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); mkdirp(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { //todo 0666 if (Buffer.isBuffer(buffer)) { fs.writeFile(fsPath, buffer, function(err) { if (err) { reject(err); } else { resolve(); } }); } else { utils.promiseCreateWriteStream(fsPath).then(function(writable) { buffer.pipe(writable); }).catch(function(err) { reject(err); }); } } }); }); }; exports.listObjects = function(strPath) { return utils.listObjects(getFilePath(strPath)).then(function(values) { return values.map(function(curvalue) { return getOutputPath(curvalue.substring(cfgStorageFolderPath.length + 1)); }); }); }; exports.deleteObject = function(strPath) { return new Promise(function(resolve, reject) { var fsPath = getFilePath(strPath); fs.unlink(fsPath, function(err) { if (err) { reject(err); } else { //resolve(); removeEmptyParent(path.dirname(fsPath), function(err) { if (err) { reject(err); } else { resolve(); } }); } }); }); }; exports.deleteObjects = function(strPaths) { return Promise.all(strPaths.map(exports.deleteObject)); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return new Promise(function(resolve, reject) { var userFriendlyName = optFilename ? encodeURIComponent(optFilename) : path.basename(strPath); var uri = '/' + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath + '/' + userFriendlyName; var url = (cfgStorageExternalHost ? cfgStorageExternalHost : baseUrl) + uri; var date = new Date(); var expires = Math.ceil(date.getTime() / 1000) + (optUrlExpires || 604800); // отключил время жизни т.к. существует сценарий, при котором объект // получаемый по ссылке запрашивается после того как закончилось время // его жизни. var md5 = crypto.createHash('md5').update(/*expires + */uri + cfgStorageSecretString).digest("base64"); md5 = md5.replace(/\+/g, "-"); md5 = md5.replace(/\//g, "_"); url += ('?md5=' + md5 + '&expires=' + expires); url += '&disposition=' + encodeURIComponent(utils.getContentDisposition(null, null, opt_type)); resolve(utils.changeOnlyOfficeUrl(url, strPath, optFilename)); }); }; \ No newline at end of file diff --git a/Common/sources/storage-s3.js b/Common/sources/storage-s3.js index 9bb309070..5af57d5bc 100644 --- a/Common/sources/storage-s3.js +++ b/Common/sources/storage-s3.js @@ -1 +1 @@ -'use strict'; var url = require('url'); var path = require('path'); var AWS = require('aws-sdk'); var mime = require('mime'); var s3urlSigner = require('amazon-s3-url-signer'); var utils = require('./utils'); var configStorage = require('config').get('storage'); var cfgRegion = configStorage.get('region'); var cfgEndpoint = configStorage.get('endpoint'); var cfgBucketName = configStorage.get('bucketName'); var cfgStorageFolderName = configStorage.get('storageFolderName'); var cfgAccessKeyId = configStorage.get('accessKeyId'); var cfgSecretAccessKey = configStorage.get('secretAccessKey'); var cfgUseRequestToGetUrl = configStorage.get('useRequestToGetUrl'); var cfgUseSignedUrl = configStorage.get('useSignedUrl'); var cfgExternalHost = configStorage.get('externalHost'); /** * Don't hard-code your credentials! * Export the following environment variables instead: * * export AWS_ACCESS_KEY_ID='AKID' * export AWS_SECRET_ACCESS_KEY='SECRET' */ var configS3 = { region: cfgRegion, endpoint: cfgEndpoint, accessKeyId: cfgAccessKeyId, secretAccessKey: cfgSecretAccessKey }; if (configS3.endpoint) { configS3.sslEnabled = false; configS3.s3ForcePathStyle = true; } AWS.config.update(configS3); var s3Client = new AWS.S3(); if (configS3.endpoint) { s3Client.endpoint = new AWS.Endpoint(configS3.endpoint); } var cfgEndpointParsed = null; if (cfgEndpoint) { cfgEndpointParsed = url.parse(cfgEndpoint); } //This operation enables you to delete multiple objects from a bucket using a single HTTP request. You may specify up to 1000 keys. var MAX_DELETE_OBJECTS = 1000; function getFilePath(strPath) { //todo return cfgStorageFolderName + '/' + strPath; } function joinListObjects(inputArray, outputArray) { var length = inputArray.length; for (var i = 0; i < length; i++) { outputArray.push(inputArray[i].Key.substring((cfgStorageFolderName + '/').length)); } } function listObjectsExec(output, params, resolve, reject) { s3Client.listObjects(params, function(err, data) { if (err) { reject(err); } else { joinListObjects(data.Contents, output); if (data.IsTruncated && (data.NextMarker || data.Contents.length > 0)) { params.Marker = data.NextMarker || data.Contents[data.Contents.length - 1].Key; listObjectsExec(output, params, resolve, reject); } else { resolve(output); } } }); } function mapDeleteObjects(currentValue) { return {Key: currentValue}; } function deleteObjectsHelp(aKeys) { return new Promise(function(resolve, reject) { //By default, the operation uses verbose mode in which the response includes the result of deletion of each key in your request. //In quiet mode the response includes only keys where the delete operation encountered an error. var params = {Bucket: cfgBucketName, Delete: {Objects: aKeys, Quiet: true}}; s3Client.deleteObjects(params, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); } exports.getObject = function(strPath) { return new Promise(function(resolve, reject) { var params = {Bucket: cfgBucketName, Key: getFilePath(strPath)}; s3Client.getObject(params, function(err, data) { if (err) { reject(err); } else { resolve(data.Body); } }); }); }; exports.putObject = function(strPath, buffer, contentLength) { return new Promise(function(resolve, reject) { //todo рассмотреть Expires var params = {Bucket: cfgBucketName, Key: getFilePath(strPath), Body: buffer, ContentLength: contentLength, ContentType: mime.lookup(strPath)}; s3Client.putObject(params, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); }; exports.listObjects = function(strPath) { return new Promise(function(resolve, reject) { var params = {Bucket: cfgBucketName, Prefix: getFilePath(strPath)}; var output = []; listObjectsExec(output, params, resolve, reject); }); }; exports.deleteObject = function(strPath) { return new Promise(function(resolve, reject) { var params = {Bucket: cfgBucketName, Key: getFilePath(strPath)}; s3Client.deleteObject(params, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); }; exports.deleteObjects = function(strPaths) { var aKeys = strPaths.map(function (currentValue) { return {Key: getFilePath(currentValue)}; }); var deletePromises = []; for (var i = 0; i < aKeys.length; i += MAX_DELETE_OBJECTS) { deletePromises.push(deleteObjectsHelp(aKeys.slice(i, i + MAX_DELETE_OBJECTS))); } return Promise.all(deletePromises); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return new Promise(function(resolve, reject) { var expires = optUrlExpires || 604800; var contentDisposition = utils.getContentDispositionS3(optFilename || path.basename(strPath), null, opt_type); if (cfgUseRequestToGetUrl) { //default Expires 900 seconds var params = { Bucket: cfgBucketName, Key: getFilePath(strPath), ResponseContentDisposition: contentDisposition, Expires: expires }; s3Client.getSignedUrl('getObject', params, function(err, data) { if (err) { reject(err); } else { resolve(utils.changeOnlyOfficeUrl(data, strPath, optFilename)); } }); } else { var host; if (cfgRegion) { host = 'https://s3-'+cfgRegion+'.amazonaws.com'; } else if (cfgEndpointParsed && (cfgEndpointParsed.hostname == 'localhost' || cfgEndpointParsed.hostname == '127.0.0.1') && 80 == cfgEndpointParsed.port) { host = (cfgExternalHost ? cfgExternalHost : baseUrl) + cfgEndpointParsed.path; } else { host = cfgEndpoint; } if (host && host.length > 0 && '/' != host[host.length - 1]) { host += '/'; } var newUrl; if (cfgUseSignedUrl) { //todo уйти от parse var hostParsed = url.parse(host); var protocol = hostParsed.protocol.substring(0, hostParsed.protocol.length - 1); var signerOptions = { host: hostParsed.hostname, port: hostParsed.port, protocol: protocol, useSubdomain: false }; var awsUrlSigner = s3urlSigner.urlSigner(cfgAccessKeyId, cfgSecretAccessKey, signerOptions); newUrl = awsUrlSigner.getUrl('GET', getFilePath(strPath), cfgBucketName, expires, contentDisposition); } else { newUrl = host + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath; } resolve(utils.changeOnlyOfficeUrl(newUrl, strPath, optFilename)); } }); }; +/* * (c) Copyright Ascensio System SIA 2010-2016 * * 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 * */ 'use strict'; var url = require('url'); var path = require('path'); var AWS = require('aws-sdk'); var mime = require('mime'); var s3urlSigner = require('amazon-s3-url-signer'); var utils = require('./utils'); var configStorage = require('config').get('storage'); var cfgRegion = configStorage.get('region'); var cfgEndpoint = configStorage.get('endpoint'); var cfgBucketName = configStorage.get('bucketName'); var cfgStorageFolderName = configStorage.get('storageFolderName'); var cfgAccessKeyId = configStorage.get('accessKeyId'); var cfgSecretAccessKey = configStorage.get('secretAccessKey'); var cfgUseRequestToGetUrl = configStorage.get('useRequestToGetUrl'); var cfgUseSignedUrl = configStorage.get('useSignedUrl'); var cfgExternalHost = configStorage.get('externalHost'); /** * Don't hard-code your credentials! * Export the following environment variables instead: * * export AWS_ACCESS_KEY_ID='AKID' * export AWS_SECRET_ACCESS_KEY='SECRET' */ var configS3 = { region: cfgRegion, endpoint: cfgEndpoint, accessKeyId: cfgAccessKeyId, secretAccessKey: cfgSecretAccessKey }; if (configS3.endpoint) { configS3.sslEnabled = false; configS3.s3ForcePathStyle = true; } AWS.config.update(configS3); var s3Client = new AWS.S3(); if (configS3.endpoint) { s3Client.endpoint = new AWS.Endpoint(configS3.endpoint); } var cfgEndpointParsed = null; if (cfgEndpoint) { cfgEndpointParsed = url.parse(cfgEndpoint); } //This operation enables you to delete multiple objects from a bucket using a single HTTP request. You may specify up to 1000 keys. var MAX_DELETE_OBJECTS = 1000; function getFilePath(strPath) { //todo return cfgStorageFolderName + '/' + strPath; } function joinListObjects(inputArray, outputArray) { var length = inputArray.length; for (var i = 0; i < length; i++) { outputArray.push(inputArray[i].Key.substring((cfgStorageFolderName + '/').length)); } } function listObjectsExec(output, params, resolve, reject) { s3Client.listObjects(params, function(err, data) { if (err) { reject(err); } else { joinListObjects(data.Contents, output); if (data.IsTruncated && (data.NextMarker || data.Contents.length > 0)) { params.Marker = data.NextMarker || data.Contents[data.Contents.length - 1].Key; listObjectsExec(output, params, resolve, reject); } else { resolve(output); } } }); } function mapDeleteObjects(currentValue) { return {Key: currentValue}; } function deleteObjectsHelp(aKeys) { return new Promise(function(resolve, reject) { //By default, the operation uses verbose mode in which the response includes the result of deletion of each key in your request. //In quiet mode the response includes only keys where the delete operation encountered an error. var params = {Bucket: cfgBucketName, Delete: {Objects: aKeys, Quiet: true}}; s3Client.deleteObjects(params, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); } exports.getObject = function(strPath) { return new Promise(function(resolve, reject) { var params = {Bucket: cfgBucketName, Key: getFilePath(strPath)}; s3Client.getObject(params, function(err, data) { if (err) { reject(err); } else { resolve(data.Body); } }); }); }; exports.putObject = function(strPath, buffer, contentLength) { return new Promise(function(resolve, reject) { //todo рассмотреть Expires var params = {Bucket: cfgBucketName, Key: getFilePath(strPath), Body: buffer, ContentLength: contentLength, ContentType: mime.lookup(strPath)}; s3Client.putObject(params, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); }; exports.listObjects = function(strPath) { return new Promise(function(resolve, reject) { var params = {Bucket: cfgBucketName, Prefix: getFilePath(strPath)}; var output = []; listObjectsExec(output, params, resolve, reject); }); }; exports.deleteObject = function(strPath) { return new Promise(function(resolve, reject) { var params = {Bucket: cfgBucketName, Key: getFilePath(strPath)}; s3Client.deleteObject(params, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); }; exports.deleteObjects = function(strPaths) { var aKeys = strPaths.map(function (currentValue) { return {Key: getFilePath(currentValue)}; }); var deletePromises = []; for (var i = 0; i < aKeys.length; i += MAX_DELETE_OBJECTS) { deletePromises.push(deleteObjectsHelp(aKeys.slice(i, i + MAX_DELETE_OBJECTS))); } return Promise.all(deletePromises); }; exports.getSignedUrl = function(baseUrl, strPath, optUrlExpires, optFilename, opt_type) { return new Promise(function(resolve, reject) { var expires = optUrlExpires || 604800; var contentDisposition = utils.getContentDispositionS3(optFilename || path.basename(strPath), null, opt_type); if (cfgUseRequestToGetUrl) { //default Expires 900 seconds var params = { Bucket: cfgBucketName, Key: getFilePath(strPath), ResponseContentDisposition: contentDisposition, Expires: expires }; s3Client.getSignedUrl('getObject', params, function(err, data) { if (err) { reject(err); } else { resolve(utils.changeOnlyOfficeUrl(data, strPath, optFilename)); } }); } else { var host; if (cfgRegion) { host = 'https://s3-'+cfgRegion+'.amazonaws.com'; } else if (cfgEndpointParsed && (cfgEndpointParsed.hostname == 'localhost' || cfgEndpointParsed.hostname == '127.0.0.1') && 80 == cfgEndpointParsed.port) { host = (cfgExternalHost ? cfgExternalHost : baseUrl) + cfgEndpointParsed.path; } else { host = cfgEndpoint; } if (host && host.length > 0 && '/' != host[host.length - 1]) { host += '/'; } var newUrl; if (cfgUseSignedUrl) { //todo уйти от parse var hostParsed = url.parse(host); var protocol = hostParsed.protocol.substring(0, hostParsed.protocol.length - 1); var signerOptions = { host: hostParsed.hostname, port: hostParsed.port, protocol: protocol, useSubdomain: false }; var awsUrlSigner = s3urlSigner.urlSigner(cfgAccessKeyId, cfgSecretAccessKey, signerOptions); newUrl = awsUrlSigner.getUrl('GET', getFilePath(strPath), cfgBucketName, expires, contentDisposition); } else { newUrl = host + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath; } resolve(utils.changeOnlyOfficeUrl(newUrl, strPath, optFilename)); } }); }; \ No newline at end of file diff --git a/Common/sources/taskqueueRabbitMQ.js b/Common/sources/taskqueueRabbitMQ.js index 021a2e049..6492fa474 100644 --- a/Common/sources/taskqueueRabbitMQ.js +++ b/Common/sources/taskqueueRabbitMQ.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + 'use strict'; var config = require('config'); var events = require('events'); diff --git a/Common/sources/utils.js b/Common/sources/utils.js index b33756b56..500e91e2d 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 fs = require('fs'); var path = require('path'); var url = require('url'); diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index be485a048..99e29247a 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + /* ----------------------------------------------------view-режим--------------------------------------------------------- * 1) Для view-режима обновляем страницу (без быстрого перехода), чтобы пользователь не считался за редактируемого и не diff --git a/DocService/sources/baseConnector.js b/DocService/sources/baseConnector.js index ab1e28f45..885c65198 100644 --- a/DocService/sources/baseConnector.js +++ b/DocService/sources/baseConnector.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 sqlDataBaseType = { mySql : 'mysql', postgreSql : 'postgres' diff --git a/DocService/sources/canvasservice.js b/DocService/sources/canvasservice.js index 2c5c09b63..6d3624cf8 100644 --- a/DocService/sources/canvasservice.js +++ b/DocService/sources/canvasservice.js @@ -1 +1 @@ -var pathModule = require('path'); var urlModule = require('url'); var co = require('co'); var sqlBase = require('./baseConnector'); var docsCoServer = require('./DocsCoServer'); var taskResult = require('./taskresult'); var logger = require('./../../Common/sources/logger'); var utils = require('./../../Common/sources/utils'); var constants = require('./../../Common/sources/constants'); var commonDefines = require('./../../Common/sources/commondefines'); var storage = require('./../../Common/sources/storage-base'); var formatChecker = require('./../../Common/sources/formatchecker'); var statsDClient = require('./../../Common/sources/statsdclient'); var config = require('config'); var config_server = config.get('services.CoAuthoring.server'); var config_utils = config.get('services.CoAuthoring.utils'); var pubsubRedis = require('./pubsubRedis'); var cfgTypesUpload = config_utils.get('limits_image_types_upload'); var cfgTypesCopy = config_utils.get('limits_image_types_copy'); var cfgImageSize = config_server.get('limits_image_size'); var cfgImageDownloadTimeout = config_server.get('limits_image_download_timeout'); var cfgRedisPrefix = config.get('services.CoAuthoring.redis.prefix'); var SAVE_TYPE_PART_START = 0; var SAVE_TYPE_PART = 1; var SAVE_TYPE_COMPLETE = 2; var SAVE_TYPE_COMPLETE_ALL = 3; var clientStatsD = statsDClient.getClient(); var redisClient = pubsubRedis.getClientRedis(); var redisKeySaved = cfgRedisPrefix + constants.REDIS_KEY_SAVED; var redisKeyShutdown = cfgRedisPrefix + constants.REDIS_KEY_SHUTDOWN; function OutputDataWrap(type, data) { this['type'] = type; this['data'] = data; } OutputDataWrap.prototype = { fromObject: function(data) { this['type'] = data['type']; this['data'] = new OutputData(); this['data'].fromObject(data['data']); }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function OutputData(type) { this['type'] = type; this['status'] = undefined; this['data'] = undefined; } OutputData.prototype = { fromObject: function(data) { this['type'] = data['type']; this['status'] = data['status']; this['data'] = data['data']; }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getStatus: function() { return this['status']; }, setStatus: function(data) { this['status'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function* getOutputData(cmd, outputData, key, status, statusInfo, optConn, optAdditionalOutput) { var docId = cmd.getDocId(); switch (status) { case taskResult.FileStatus.SaveVersion: case taskResult.FileStatus.UpdateVersion: case taskResult.FileStatus.Ok: if(taskResult.FileStatus.Ok == status) { outputData.setStatus('ok'); } else if(taskResult.FileStatus.SaveVersion == status) { if (optConn && optConn.user.view) { outputData.setStatus('updateversion'); } else { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = status; updateMask.statusInfo = statusInfo; var updateTask = new taskResult.TaskResultData(); updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateTask, updateMask); if (updateIfRes.affectedRows > 0) { outputData.setStatus('ok'); } else { outputData.setStatus('updateversion'); } } } else { outputData.setStatus('updateversion'); } var command = cmd.getCommand(); if ('open' != command && 'reopen' != command) { var strPath = key + '/' + cmd.getOutputPath(); if (optConn) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = strPath; optAdditionalOutput.needUrlMethod = 2; } } else { if (optConn) { outputData.setData(yield storage.getSignedUrls(optConn.baseUrl, key)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = key; optAdditionalOutput.needUrlMethod = 0; } } break; case taskResult.FileStatus.NeedParams: outputData.setStatus('needparams'); var settingsPath = key + '/' + 'settings.json'; if (optConn) { outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, settingsPath)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = settingsPath; optAdditionalOutput.needUrlMethod = 1; } break; case taskResult.FileStatus.NeedPassword: outputData.setStatus('needpassword'); break; case taskResult.FileStatus.Err: case taskResult.FileStatus.ErrToReload: outputData.setStatus('err'); outputData.setData(statusInfo); if (taskResult.FileStatus.ErrToReload == status) { yield cleanupCache(key); } break; } } function* addRandomKeyTaskCmd(cmd) { var task = yield* taskResult.addRandomKeyTask(cmd.getDocId()); cmd.setSaveKey(task.key); } function* saveParts(cmd) { var result = false; var saveType = cmd.getSaveType(); var filename; if (SAVE_TYPE_COMPLETE_ALL === saveType) { filename = 'Editor.bin'; } else { filename = 'Editor' + (cmd.getSaveIndex() || '') + '.bin'; } if (SAVE_TYPE_PART_START === saveType || SAVE_TYPE_COMPLETE_ALL === saveType) { yield* addRandomKeyTaskCmd(cmd); } if (cmd.getUrl()) { result = true; } else { var buffer = cmd.getData(); yield storage.putObject(cmd.getSaveKey() + '/' + filename, buffer, buffer.length); //delete data to prevent serialize into json cmd.data = null; result = (SAVE_TYPE_COMPLETE_ALL === saveType || SAVE_TYPE_COMPLETE === saveType); } return result; } function getSaveTask(cmd) { cmd.setData(null); var queueData = new commonDefines.TaskQueueData(); queueData.setCmd(cmd); queueData.setToFile(constants.OUTPUT_NAME + '.' + formatChecker.getStringFromFormat(cmd.getOutputFormat())); //todo paid //if (cmd.vkey) { // bool // bPaid; // Signature.getVKeyParams(cmd.vkey, out bPaid); // oTaskQueueData.m_bPaid = bPaid; //} return queueData; } function getUpdateResponse(cmd) { var updateTask = new taskResult.TaskResultData(); updateTask.key = cmd.getSaveKey() ? cmd.getSaveKey() : cmd.getDocId(); var statusInfo = cmd.getStatusInfo(); if (constants.NO_ERROR == statusInfo) { updateTask.status = taskResult.FileStatus.Ok; } else if (constants.CONVERT_DOWNLOAD == statusInfo) { updateTask.status = taskResult.FileStatus.ErrToReload; } else if (constants.CONVERT_NEED_PARAMS == statusInfo) { updateTask.status = taskResult.FileStatus.NeedParams; } else if (constants.CONVERT_DRM == statusInfo) { updateTask.status = taskResult.FileStatus.NeedPassword; } else { updateTask.status = taskResult.FileStatus.Err; } updateTask.statusInfo = statusInfo; if (cmd.getTitle()) { updateTask.title = cmd.getTitle(); } return updateTask; } var cleanupCache = co.wrap(function* (docId) { //todo redis ? var res = false; var removeRes = yield taskResult.remove(docId); if (removeRes.affectedRows > 0) { yield storage.deletePath(docId); res = true; } return res; }); function commandOpenStartPromise(docId, cmd, opt_updateUserIndex) { var task = new taskResult.TaskResultData(); task.key = docId; task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; if (cmd) { task.title = cmd.getTitle(); } else { logger.warn("commandOpenStartPromise empty cmd: docId = %s", docId); } return taskResult.upsert(task, opt_updateUserIndex); } function* commandOpen(conn, cmd, outputData, opt_upsertRes) { var upsertRes; if (opt_upsertRes) { upsertRes = opt_upsertRes; } else { upsertRes = yield commandOpenStartPromise(cmd.getDocId(), cmd); } //if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values //http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html var bCreate = upsertRes.affectedRows == 1; if (!bCreate) { var selectRes = yield taskResult.select(cmd.getDocId()); if (selectRes.length > 0) { var row = selectRes[0]; yield* getOutputData(cmd, outputData, cmd.getDocId(), row.status, row.status_info, conn); } } else { //add task cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); var priority = constants.QUEUE_PRIORITY_HIGH; var formatIn = formatChecker.getFormatFromString(cmd.getFormat()); //decrease pdf, djvu, xps convert priority becase long open time if (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS === formatIn) { priority = constants.QUEUE_PRIORITY_LOW; } yield* docsCoServer.addTask(dataQueue, priority); } } function* commandReopen(cmd) { var task = new taskResult.TaskResultData(); task.key = cmd.getDocId(); task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; var upsertRes = yield taskResult.update(task); if (upsertRes.affectedRows > 0) { //add task cmd.setUrl(null);//url may expire cmd.setSaveKey(cmd.getDocId()); cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); dataQueue.setFromSettings(true); yield* docsCoServer.addTask(dataQueue, constants.QUEUE_PRIORITY_HIGH); } } function* commandSave(cmd, outputData) { var completeParts = yield* saveParts(cmd); if (completeParts) { var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSendMailMerge(cmd, outputData) { var completeParts = yield* saveParts(cmd); var isErr = false; if (completeParts) { isErr = true; var getRes = yield* docsCoServer.getCallback(cmd.getDocId()); if (getRes) { var mailMergeSend = cmd.getMailMergeSend(); mailMergeSend.setUrl(getRes.server.href); mailMergeSend.setBaseUrl(getRes.baseUrl); //меняем JsonKey и SaveKey, новый key нужет потому что за одну конвертацию делается часть, а json нужен всегда mailMergeSend.setJsonKey(cmd.getSaveKey()); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); isErr = false; } } if (isErr) { outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } else { outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } } function* commandSfctByCmd(cmd) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } function* commandSfct(cmd, outputData) { yield* commandSfctByCmd(cmd); outputData.setStatus('ok'); } function isDisplayedImage(strName) { var res = 0; if (strName) { //шаблон display[N]image.ext var findStr = constants.DISPLAY_PREFIX; var index = strName.indexOf(findStr); if (-1 != index) { if (index + findStr.length < strName.length) { var displayN = parseInt(strName[index + findStr.length]); if (1 <= displayN && displayN <= 6) { var imageIndex = index + findStr.length + 1; if (imageIndex == strName.indexOf("image", imageIndex)) res = displayN; } } } } return res; } function* commandImgurls(conn, cmd, outputData) { var supportedFormats; var urls; var errorCode = constants.NO_ERROR; var isImgUrl = 'imgurl' == cmd.getCommand(); if (isImgUrl) { urls = [cmd.getData()]; supportedFormats = cfgTypesUpload || 'jpg'; } else { urls = cmd.getData(); supportedFormats = cfgTypesCopy || 'jpg'; } //todo Promise.all() var displayedImageMap = {};//to make one imageIndex for ole object urls var imageCount = 0; var outputUrls = []; for (var i = 0; i < urls.length; ++i) { var urlSource = urls[i]; var urlParsed; var data = undefined; if (urlSource.startsWith('data:')) { var delimiterIndex = urlSource.indexOf(','); if (-1 != delimiterIndex && (urlSource.length - (delimiterIndex + 1)) * 0.75 <= cfgImageSize) { data = new Buffer(urlSource.substring(delimiterIndex + 1), 'base64'); } } else if(urlSource) { //todo stream data = yield utils.downloadUrlPromise(urlSource, cfgImageDownloadTimeout * 1000, cfgImageSize); urlParsed = urlModule.parse(urlSource); } var outputUrl = {url: 'error', path: 'error'}; if (data) { var format = formatChecker.getImageFormat(data); var formatStr; if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN == format && urlParsed) { //bin, txt occur in ole object case var ext = pathModule.extname(urlParsed.pathname); if ('.bin' == ext || '.txt' == ext) { formatStr = ext.substring(1); } } else { formatStr = formatChecker.getStringFromFormat(format); } if (formatStr && -1 !== supportedFormats.indexOf(formatStr)) { var userid = cmd.getUserId(); var imageIndex = cmd.getSaveIndex() + imageCount; imageCount++; var strLocalPath = 'media/' + utils.crc32(userid).toString(16) + '_'; if (urlParsed) { var urlBasename = pathModule.basename(urlParsed.pathname); var displayN = isDisplayedImage(urlBasename); if (displayN > 0) { var displayedImageName = urlBasename.substring(0, urlBasename.length - formatStr.length - 1); var tempIndex = displayedImageMap[displayedImageName]; if (null != tempIndex) { imageIndex = tempIndex; imageCount--; } else { displayedImageMap[displayedImageName] = imageIndex; } strLocalPath += constants.DISPLAY_PREFIX + displayN; } } strLocalPath += 'image' + imageIndex + '.' + formatStr; var strPath = cmd.getDocId() + '/' + strLocalPath; yield storage.putObject(strPath, data, data.length); var imgUrl = yield storage.getSignedUrl(conn.baseUrl, strPath); outputUrl = {url: imgUrl, path: strLocalPath}; } } if (isImgUrl && ('error' === outputUrl.url || 'error' === outputUrl.path)) { errorCode = constants.UPLOAD_EXTENSION; break; } outputUrls.push(outputUrl); } if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(outputUrls); } } function* commandPathUrl(conn, cmd, outputData) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; var strPath = cmd.getDocId() + '/' + cmd.getData(); var url = yield storage.getSignedUrl(conn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition); var errorCode = constants.NO_ERROR; if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(url); } } function* commandSaveFromOrigin(cmd, outputData) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromOrigin(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSfcCallback(cmd, isSfcm) { var docId = cmd.getDocId(); logger.debug('Start commandSfcCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var isError = constants.NO_ERROR != statusInfo && constants.CONVERT_CORRUPTED != statusInfo; var savePathDoc = saveKey + '/' + cmd.getOutputPath(); var savePathChanges = saveKey + '/changes.zip'; var savePathHistory = saveKey + '/changesHistory.json'; var getRes = yield* docsCoServer.getCallback(docId); if (getRes) { logger.debug('Callback commandSfcCallback: docId = %s callback = %s', docId, getRes.server.href); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (cmd.getUserId()) { outputSfc.setUsers([cmd.getUserId()]); } if (isSfcm) { outputSfc.setActions(undefined); outputSfc.setUserData(cmd.getUserData()); } else { //use UserId case UserActionId miss in gc convertion var userActionId = cmd.getUserActionId() || cmd.getUserId(); if (userActionId) { outputSfc.setActions([new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, userActionId)]); } } if (!isError) { try { var data = yield storage.getObject(savePathHistory); outputSfc.setChangeHistory(data.toString('utf-8')); outputSfc.setUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathDoc)); outputSfc.setChangeUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathChanges)); } catch (e) { logger.error('Error commandSfcCallback: docId = %s\r\n%s', docId, e.stack); } if (outputSfc.getUrl() && outputSfc.getUsers().length > 0) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSaveForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSave); } } else { isError = true; } } if (isError) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.CorruptedForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } } var uri = getRes.server.href; var postData = JSON.stringify(outputSfc); if (isSfcm) { var lastSave = cmd.getLastSave(); if (lastSave && !isError) { yield* docsCoServer.setForceSave(docId, lastSave, savePathDoc); } try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } else { //if anybody in document stop save var hasEditors = yield* docsCoServer.hasEditors(docId); logger.debug('hasEditors commandSfcCallback: docId = %s hasEditors = %d', docId, hasEditors); if (!hasEditors) { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = taskResult.FileStatus.SaveVersion; updateMask.statusInfo = cmd.getData(); var updateIfTask = new taskResult.TaskResultData(); updateIfTask.status = taskResult.FileStatus.UpdateVersion; updateIfTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask); if (updateIfRes.affectedRows > 0) { var replyStr = null; try { replyStr = yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { replyStr = null; logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } var requestRes = false; var replyData = docsCoServer.parseReplyData(docId, replyStr); if (replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error) { //в случае comunity server придет запрос в CommandService проверяем результат var multi = redisClient.multi([ ['get', redisKeySaved + docId], ['del', redisKeySaved + docId] ]); var execRes = yield utils.promiseRedis(multi, multi.exec); var savedVal = execRes[0]; requestRes = (null == savedVal || '1' === savedVal); } if (requestRes) { yield docsCoServer.cleanDocumentOnExitPromise(docId, true); } else { var updateTask = new taskResult.TaskResultData(); updateTask.key = docId; updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; yield taskResult.update(updateTask); } } } } } if (docsCoServer.getIsShutdown() && !isSfcm) { yield utils.promiseRedis(redisClient, redisClient.srem, redisKeyShutdown, docId); } logger.debug('End commandSfcCallback: docId = %s', docId); } function* commandSendMMCallback(cmd) { var docId = cmd.getDocId(); logger.debug('Start commandSendMMCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (constants.NO_ERROR == statusInfo) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MailMerge); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } var mailMergeSendData = cmd.getMailMergeSend(); var outputMailMerge = new commonDefines.OutputMailMerge(mailMergeSendData); outputSfc.setMailMerge(outputMailMerge); outputSfc.setUsers([mailMergeSendData.getUserId()]); var data = yield storage.getObject(saveKey + '/' + cmd.getOutputPath()); var xml = data.toString('utf8'); var files = xml.match(/[< ]file.*?\/>/g); var recordRemain = (mailMergeSendData.getRecordTo() - mailMergeSendData.getRecordFrom() + 1); var recordIndexStart = mailMergeSendData.getRecordCount() - recordRemain; for (var i = 0; i < files.length; ++i) { var file = files[i]; var fieldRes = /field=["'](.*?)["']/.exec(file); outputMailMerge.setTo(fieldRes[1]); outputMailMerge.setRecordIndex(recordIndexStart + i); var pathRes = /path=["'](.*?)["']/.exec(file); var signedUrl = yield storage.getSignedUrl(mailMergeSendData.getBaseUrl(), saveKey + '/' + pathRes[1]); outputSfc.setUrl(signedUrl); var uri = mailMergeSendData.getUrl(); var postData = JSON.stringify(outputSfc); try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } var newRecordFrom = mailMergeSendData.getRecordFrom() + Math.max(files.length, 1); if (newRecordFrom <= mailMergeSendData.getRecordTo()) { mailMergeSendData.setRecordFrom(newRecordFrom); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } else { logger.debug('End MailMerge: docId = %s', docId); } logger.debug('End commandSendMMCallback: docId = %s', docId); } exports.openDocument = function(conn, cmd, opt_upsertRes) { return co(function* () { var outputData; var docId = conn ? conn.docId : 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start command: docId = %s %s', docId, JSON.stringify(cmd)); outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'open': //yield utils.sleep(5000); yield* commandOpen(conn, cmd, outputData, opt_upsertRes); break; case 'reopen': yield* commandReopen(cmd); break; case 'imgurl': case 'imgurls': yield* commandImgurls(conn, cmd, outputData); break; case 'pathurl': yield* commandPathUrl(conn, cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } if(clientStatsD) { clientStatsD.timing('coauth.openDocument.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error openDocument: docId = %s\r\n%s', docId, e.stack); if (!outputData) { outputData = new OutputData(); } outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } finally { if (outputData && outputData.getStatus()) { logger.debug('Response command: docId = %s %s', docId, JSON.stringify(outputData)); docsCoServer.sendData(conn, new OutputDataWrap('documentOpen', outputData)); } logger.debug('End command: docId = %s', docId); } }); }; exports.downloadAs = function(req, res) { return co(function* () { var docId = 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } var strCmd = req.query['cmd']; var cmd = new commonDefines.InputCommand(JSON.parse(strCmd)); docId = cmd.getDocId(); logger.debug('Start downloadAs: docId = %s %s', docId, strCmd); cmd.setData(req.body); var outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'save': yield* commandSave(cmd, outputData); break; case 'savefromorigin': yield* commandSaveFromOrigin(cmd, outputData); break; case 'sendmm': yield* commandSendMailMerge(cmd, outputData); break; case 'sfct': yield* commandSfct(cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } var strRes = JSON.stringify(outputData); res.send(strRes); logger.debug('End downloadAs: docId = %s %s', docId, strRes); if(clientStatsD) { clientStatsD.timing('coauth.downloadAs.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error downloadAs: docId = %s\r\n%s', docId, e.stack); res.sendStatus(400); } }); }; exports.saveFromChanges = function(docId, statusInfo, optFormat, opt_userId, opt_queue) { return co(function* () { try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start saveFromChanges: docId = %s', docId); var task = new taskResult.TaskResultData(); task.key = docId; //делаем select, потому что за время timeout информация могла измениться var selectRes = yield taskResult.select(docId); var row = selectRes.length > 0 ? selectRes[0] : null; if (row && row.status == taskResult.FileStatus.SaveVersion && row.status_info == statusInfo) { if (null == optFormat) { optFormat = constants.AVS_OFFICESTUDIO_FILE_OTHER_TEAMLAB_INNER; } var cmd = new commonDefines.InputCommand(); cmd.setCommand('sfc'); cmd.setDocId(docId); cmd.setOutputFormat(optFormat); cmd.setData(statusInfo); cmd.setUserActionId(opt_userId); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_NORMAL, opt_queue); if (docsCoServer.getIsShutdown()) { yield utils.promiseRedis(redisClient, redisClient.sadd, redisKeyShutdown, docId); } logger.debug('AddTask saveFromChanges: docId = %s', docId); } else { if (row) { logger.debug('saveFromChanges status mismatch: docId = %s; row: %d; %d; expected: %d', docId, row.status, row.status_info, statusInfo); } } if (clientStatsD) { clientStatsD.timing('coauth.saveFromChanges', new Date() - startDate); } } catch (e) { logger.error('Error saveFromChanges: docId = %s\r\n%s', docId, e.stack); } }); }; exports.receiveTask = function(data, dataRaw) { return co(function* () { var docId = 'null'; try { var task = new commonDefines.TaskQueueData(JSON.parse(data)); if (task) { var cmd = task.getCmd(); docId = cmd.getDocId(); logger.debug('Start receiveTask: docId = %s %s', docId, data); var updateTask = getUpdateResponse(cmd); var updateRes = yield taskResult.update(updateTask); if (updateRes.affectedRows > 0) { var outputData = new OutputData(cmd.getCommand()); var command = cmd.getCommand(); var additionalOutput = {needUrlKey: null, needUrlMethod: null}; if ('open' == command || 'reopen' == command) { //yield utils.sleep(5000); yield* getOutputData(cmd, outputData, cmd.getDocId(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('save' == command || 'savefromorigin' == command || 'sfct' == command) { yield* getOutputData(cmd, outputData, cmd.getSaveKey(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('sfcm' == command) { yield* commandSfcCallback(cmd, true); } else if ('sfc' == command) { yield* commandSfcCallback(cmd, false); } else if ('sendmm' == command) { yield* commandSendMMCallback(cmd); } else if ('conv' == command) { //nothing } if (outputData.getStatus()) { logger.debug('Send receiveTask: docId = %s %s', docId, JSON.stringify(outputData)); var output = new OutputDataWrap('documentOpen', outputData); yield* docsCoServer.publish({ type: commonDefines.c_oPublishType.receiveTask, cmd: cmd, output: output, needUrlKey: additionalOutput.needUrlKey, needUrlMethod: additionalOutput.needUrlMethod }); } } yield* docsCoServer.removeResponse(dataRaw); logger.debug('End receiveTask: docId = %s', docId); } } catch (err) { logger.debug('Error receiveTask: docId = %s\r\n%s', docId, err.stack); } }); }; exports.cleanupCache = cleanupCache; exports.commandSfctByCmd = commandSfctByCmd; exports.commandOpenStartPromise = commandOpenStartPromise; exports.OutputDataWrap = OutputDataWrap; exports.OutputData = OutputData; \ No newline at end of file +/* * (c) Copyright Ascensio System SIA 2010-2016 * * 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 pathModule = require('path'); var urlModule = require('url'); var co = require('co'); var sqlBase = require('./baseConnector'); var docsCoServer = require('./DocsCoServer'); var taskResult = require('./taskresult'); var logger = require('./../../Common/sources/logger'); var utils = require('./../../Common/sources/utils'); var constants = require('./../../Common/sources/constants'); var commonDefines = require('./../../Common/sources/commondefines'); var storage = require('./../../Common/sources/storage-base'); var formatChecker = require('./../../Common/sources/formatchecker'); var statsDClient = require('./../../Common/sources/statsdclient'); var config = require('config'); var config_server = config.get('services.CoAuthoring.server'); var config_utils = config.get('services.CoAuthoring.utils'); var pubsubRedis = require('./pubsubRedis'); var cfgTypesUpload = config_utils.get('limits_image_types_upload'); var cfgTypesCopy = config_utils.get('limits_image_types_copy'); var cfgImageSize = config_server.get('limits_image_size'); var cfgImageDownloadTimeout = config_server.get('limits_image_download_timeout'); var cfgRedisPrefix = config.get('services.CoAuthoring.redis.prefix'); var SAVE_TYPE_PART_START = 0; var SAVE_TYPE_PART = 1; var SAVE_TYPE_COMPLETE = 2; var SAVE_TYPE_COMPLETE_ALL = 3; var clientStatsD = statsDClient.getClient(); var redisClient = pubsubRedis.getClientRedis(); var redisKeySaved = cfgRedisPrefix + constants.REDIS_KEY_SAVED; var redisKeyShutdown = cfgRedisPrefix + constants.REDIS_KEY_SHUTDOWN; function OutputDataWrap(type, data) { this['type'] = type; this['data'] = data; } OutputDataWrap.prototype = { fromObject: function(data) { this['type'] = data['type']; this['data'] = new OutputData(); this['data'].fromObject(data['data']); }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function OutputData(type) { this['type'] = type; this['status'] = undefined; this['data'] = undefined; } OutputData.prototype = { fromObject: function(data) { this['type'] = data['type']; this['status'] = data['status']; this['data'] = data['data']; }, getType: function() { return this['type']; }, setType: function(data) { this['type'] = data; }, getStatus: function() { return this['status']; }, setStatus: function(data) { this['status'] = data; }, getData: function() { return this['data']; }, setData: function(data) { this['data'] = data; } }; function* getOutputData(cmd, outputData, key, status, statusInfo, optConn, optAdditionalOutput) { var docId = cmd.getDocId(); switch (status) { case taskResult.FileStatus.SaveVersion: case taskResult.FileStatus.UpdateVersion: case taskResult.FileStatus.Ok: if(taskResult.FileStatus.Ok == status) { outputData.setStatus('ok'); } else if(taskResult.FileStatus.SaveVersion == status) { if (optConn && optConn.user.view) { outputData.setStatus('updateversion'); } else { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = status; updateMask.statusInfo = statusInfo; var updateTask = new taskResult.TaskResultData(); updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateTask, updateMask); if (updateIfRes.affectedRows > 0) { outputData.setStatus('ok'); } else { outputData.setStatus('updateversion'); } } } else { outputData.setStatus('updateversion'); } var command = cmd.getCommand(); if ('open' != command && 'reopen' != command) { var strPath = key + '/' + cmd.getOutputPath(); if (optConn) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = strPath; optAdditionalOutput.needUrlMethod = 2; } } else { if (optConn) { outputData.setData(yield storage.getSignedUrls(optConn.baseUrl, key)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = key; optAdditionalOutput.needUrlMethod = 0; } } break; case taskResult.FileStatus.NeedParams: outputData.setStatus('needparams'); var settingsPath = key + '/' + 'settings.json'; if (optConn) { outputData.setData(yield storage.getSignedUrl(optConn.baseUrl, settingsPath)); } else if (optAdditionalOutput) { optAdditionalOutput.needUrlKey = settingsPath; optAdditionalOutput.needUrlMethod = 1; } break; case taskResult.FileStatus.NeedPassword: outputData.setStatus('needpassword'); break; case taskResult.FileStatus.Err: case taskResult.FileStatus.ErrToReload: outputData.setStatus('err'); outputData.setData(statusInfo); if (taskResult.FileStatus.ErrToReload == status) { yield cleanupCache(key); } break; } } function* addRandomKeyTaskCmd(cmd) { var task = yield* taskResult.addRandomKeyTask(cmd.getDocId()); cmd.setSaveKey(task.key); } function* saveParts(cmd) { var result = false; var saveType = cmd.getSaveType(); var filename; if (SAVE_TYPE_COMPLETE_ALL === saveType) { filename = 'Editor.bin'; } else { filename = 'Editor' + (cmd.getSaveIndex() || '') + '.bin'; } if (SAVE_TYPE_PART_START === saveType || SAVE_TYPE_COMPLETE_ALL === saveType) { yield* addRandomKeyTaskCmd(cmd); } if (cmd.getUrl()) { result = true; } else { var buffer = cmd.getData(); yield storage.putObject(cmd.getSaveKey() + '/' + filename, buffer, buffer.length); //delete data to prevent serialize into json cmd.data = null; result = (SAVE_TYPE_COMPLETE_ALL === saveType || SAVE_TYPE_COMPLETE === saveType); } return result; } function getSaveTask(cmd) { cmd.setData(null); var queueData = new commonDefines.TaskQueueData(); queueData.setCmd(cmd); queueData.setToFile(constants.OUTPUT_NAME + '.' + formatChecker.getStringFromFormat(cmd.getOutputFormat())); //todo paid //if (cmd.vkey) { // bool // bPaid; // Signature.getVKeyParams(cmd.vkey, out bPaid); // oTaskQueueData.m_bPaid = bPaid; //} return queueData; } function getUpdateResponse(cmd) { var updateTask = new taskResult.TaskResultData(); updateTask.key = cmd.getSaveKey() ? cmd.getSaveKey() : cmd.getDocId(); var statusInfo = cmd.getStatusInfo(); if (constants.NO_ERROR == statusInfo) { updateTask.status = taskResult.FileStatus.Ok; } else if (constants.CONVERT_DOWNLOAD == statusInfo) { updateTask.status = taskResult.FileStatus.ErrToReload; } else if (constants.CONVERT_NEED_PARAMS == statusInfo) { updateTask.status = taskResult.FileStatus.NeedParams; } else if (constants.CONVERT_DRM == statusInfo) { updateTask.status = taskResult.FileStatus.NeedPassword; } else { updateTask.status = taskResult.FileStatus.Err; } updateTask.statusInfo = statusInfo; if (cmd.getTitle()) { updateTask.title = cmd.getTitle(); } return updateTask; } var cleanupCache = co.wrap(function* (docId) { //todo redis ? var res = false; var removeRes = yield taskResult.remove(docId); if (removeRes.affectedRows > 0) { yield storage.deletePath(docId); res = true; } return res; }); function commandOpenStartPromise(docId, cmd, opt_updateUserIndex) { var task = new taskResult.TaskResultData(); task.key = docId; task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; if (cmd) { task.title = cmd.getTitle(); } else { logger.warn("commandOpenStartPromise empty cmd: docId = %s", docId); } return taskResult.upsert(task, opt_updateUserIndex); } function* commandOpen(conn, cmd, outputData, opt_upsertRes) { var upsertRes; if (opt_upsertRes) { upsertRes = opt_upsertRes; } else { upsertRes = yield commandOpenStartPromise(cmd.getDocId(), cmd); } //if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values //http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html var bCreate = upsertRes.affectedRows == 1; if (!bCreate) { var selectRes = yield taskResult.select(cmd.getDocId()); if (selectRes.length > 0) { var row = selectRes[0]; yield* getOutputData(cmd, outputData, cmd.getDocId(), row.status, row.status_info, conn); } } else { //add task cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); var priority = constants.QUEUE_PRIORITY_HIGH; var formatIn = formatChecker.getFormatFromString(cmd.getFormat()); //decrease pdf, djvu, xps convert priority becase long open time if (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU === formatIn || constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS === formatIn) { priority = constants.QUEUE_PRIORITY_LOW; } yield* docsCoServer.addTask(dataQueue, priority); } } function* commandReopen(cmd) { var task = new taskResult.TaskResultData(); task.key = cmd.getDocId(); task.status = taskResult.FileStatus.WaitQueue; task.statusInfo = constants.NO_ERROR; var upsertRes = yield taskResult.update(task); if (upsertRes.affectedRows > 0) { //add task cmd.setUrl(null);//url may expire cmd.setSaveKey(cmd.getDocId()); cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS); cmd.setEmbeddedFonts(false); var dataQueue = new commonDefines.TaskQueueData(); dataQueue.setCmd(cmd); dataQueue.setToFile('Editor.bin'); dataQueue.setFromSettings(true); yield* docsCoServer.addTask(dataQueue, constants.QUEUE_PRIORITY_HIGH); } } function* commandSave(cmd, outputData) { var completeParts = yield* saveParts(cmd); if (completeParts) { var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSendMailMerge(cmd, outputData) { var completeParts = yield* saveParts(cmd); var isErr = false; if (completeParts) { isErr = true; var getRes = yield* docsCoServer.getCallback(cmd.getDocId()); if (getRes) { var mailMergeSend = cmd.getMailMergeSend(); mailMergeSend.setUrl(getRes.server.href); mailMergeSend.setBaseUrl(getRes.baseUrl); //меняем JsonKey и SaveKey, новый key нужет потому что за одну конвертацию делается часть, а json нужен всегда mailMergeSend.setJsonKey(cmd.getSaveKey()); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); isErr = false; } } if (isErr) { outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } else { outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } } function* commandSfctByCmd(cmd) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } function* commandSfct(cmd, outputData) { yield* commandSfctByCmd(cmd); outputData.setStatus('ok'); } function isDisplayedImage(strName) { var res = 0; if (strName) { //шаблон display[N]image.ext var findStr = constants.DISPLAY_PREFIX; var index = strName.indexOf(findStr); if (-1 != index) { if (index + findStr.length < strName.length) { var displayN = parseInt(strName[index + findStr.length]); if (1 <= displayN && displayN <= 6) { var imageIndex = index + findStr.length + 1; if (imageIndex == strName.indexOf("image", imageIndex)) res = displayN; } } } } return res; } function* commandImgurls(conn, cmd, outputData) { var supportedFormats; var urls; var errorCode = constants.NO_ERROR; var isImgUrl = 'imgurl' == cmd.getCommand(); if (isImgUrl) { urls = [cmd.getData()]; supportedFormats = cfgTypesUpload || 'jpg'; } else { urls = cmd.getData(); supportedFormats = cfgTypesCopy || 'jpg'; } //todo Promise.all() var displayedImageMap = {};//to make one imageIndex for ole object urls var imageCount = 0; var outputUrls = []; for (var i = 0; i < urls.length; ++i) { var urlSource = urls[i]; var urlParsed; var data = undefined; if (urlSource.startsWith('data:')) { var delimiterIndex = urlSource.indexOf(','); if (-1 != delimiterIndex && (urlSource.length - (delimiterIndex + 1)) * 0.75 <= cfgImageSize) { data = new Buffer(urlSource.substring(delimiterIndex + 1), 'base64'); } } else if(urlSource) { //todo stream data = yield utils.downloadUrlPromise(urlSource, cfgImageDownloadTimeout * 1000, cfgImageSize); urlParsed = urlModule.parse(urlSource); } var outputUrl = {url: 'error', path: 'error'}; if (data) { var format = formatChecker.getImageFormat(data); var formatStr; if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN == format && urlParsed) { //bin, txt occur in ole object case var ext = pathModule.extname(urlParsed.pathname); if ('.bin' == ext || '.txt' == ext) { formatStr = ext.substring(1); } } else { formatStr = formatChecker.getStringFromFormat(format); } if (formatStr && -1 !== supportedFormats.indexOf(formatStr)) { var userid = cmd.getUserId(); var imageIndex = cmd.getSaveIndex() + imageCount; imageCount++; var strLocalPath = 'media/' + utils.crc32(userid).toString(16) + '_'; if (urlParsed) { var urlBasename = pathModule.basename(urlParsed.pathname); var displayN = isDisplayedImage(urlBasename); if (displayN > 0) { var displayedImageName = urlBasename.substring(0, urlBasename.length - formatStr.length - 1); var tempIndex = displayedImageMap[displayedImageName]; if (null != tempIndex) { imageIndex = tempIndex; imageCount--; } else { displayedImageMap[displayedImageName] = imageIndex; } strLocalPath += constants.DISPLAY_PREFIX + displayN; } } strLocalPath += 'image' + imageIndex + '.' + formatStr; var strPath = cmd.getDocId() + '/' + strLocalPath; yield storage.putObject(strPath, data, data.length); var imgUrl = yield storage.getSignedUrl(conn.baseUrl, strPath); outputUrl = {url: imgUrl, path: strLocalPath}; } } if (isImgUrl && ('error' === outputUrl.url || 'error' === outputUrl.path)) { errorCode = constants.UPLOAD_EXTENSION; break; } outputUrls.push(outputUrl); } if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(outputUrls); } } function* commandPathUrl(conn, cmd, outputData) { var contentDisposition = cmd.getInline() ? constants.CONTENT_DISPOSITION_INLINE : constants.CONTENT_DISPOSITION_ATTACHMENT; var strPath = cmd.getDocId() + '/' + cmd.getData(); var url = yield storage.getSignedUrl(conn.baseUrl, strPath, null, cmd.getTitle(), contentDisposition); var errorCode = constants.NO_ERROR; if (constants.NO_ERROR !== errorCode) { outputData.setStatus('err'); outputData.setData(errorCode); } else { outputData.setStatus('ok'); outputData.setData(url); } } function* commandSaveFromOrigin(cmd, outputData) { yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromOrigin(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); outputData.setStatus('ok'); outputData.setData(cmd.getSaveKey()); } function* commandSfcCallback(cmd, isSfcm) { var docId = cmd.getDocId(); logger.debug('Start commandSfcCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var isError = constants.NO_ERROR != statusInfo && constants.CONVERT_CORRUPTED != statusInfo; var savePathDoc = saveKey + '/' + cmd.getOutputPath(); var savePathChanges = saveKey + '/changes.zip'; var savePathHistory = saveKey + '/changesHistory.json'; var getRes = yield* docsCoServer.getCallback(docId); if (getRes) { logger.debug('Callback commandSfcCallback: docId = %s callback = %s', docId, getRes.server.href); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (cmd.getUserId()) { outputSfc.setUsers([cmd.getUserId()]); } if (isSfcm) { outputSfc.setActions(undefined); outputSfc.setUserData(cmd.getUserData()); } else { //use UserId case UserActionId miss in gc convertion var userActionId = cmd.getUserActionId() || cmd.getUserId(); if (userActionId) { outputSfc.setActions([new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, userActionId)]); } } if (!isError) { try { var data = yield storage.getObject(savePathHistory); outputSfc.setChangeHistory(data.toString('utf-8')); outputSfc.setUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathDoc)); outputSfc.setChangeUrl(yield storage.getSignedUrl(getRes.baseUrl, savePathChanges)); } catch (e) { logger.error('Error commandSfcCallback: docId = %s\r\n%s', docId, e.stack); } if (outputSfc.getUrl() && outputSfc.getUsers().length > 0) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSaveForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MustSave); } } else { isError = true; } } if (isError) { if (isSfcm) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.CorruptedForce); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } } var uri = getRes.server.href; var postData = JSON.stringify(outputSfc); if (isSfcm) { var lastSave = cmd.getLastSave(); if (lastSave && !isError) { yield* docsCoServer.setForceSave(docId, lastSave, savePathDoc); } try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } else { //if anybody in document stop save var hasEditors = yield* docsCoServer.hasEditors(docId); logger.debug('hasEditors commandSfcCallback: docId = %s hasEditors = %d', docId, hasEditors); if (!hasEditors) { var updateMask = new taskResult.TaskResultData(); updateMask.key = docId; updateMask.status = taskResult.FileStatus.SaveVersion; updateMask.statusInfo = cmd.getData(); var updateIfTask = new taskResult.TaskResultData(); updateIfTask.status = taskResult.FileStatus.UpdateVersion; updateIfTask.statusInfo = constants.NO_ERROR; var updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask); if (updateIfRes.affectedRows > 0) { var replyStr = null; try { replyStr = yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { replyStr = null; logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } var requestRes = false; var replyData = docsCoServer.parseReplyData(docId, replyStr); if (replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error) { //в случае comunity server придет запрос в CommandService проверяем результат var multi = redisClient.multi([ ['get', redisKeySaved + docId], ['del', redisKeySaved + docId] ]); var execRes = yield utils.promiseRedis(multi, multi.exec); var savedVal = execRes[0]; requestRes = (null == savedVal || '1' === savedVal); } if (requestRes) { yield docsCoServer.cleanDocumentOnExitPromise(docId, true); } else { var updateTask = new taskResult.TaskResultData(); updateTask.key = docId; updateTask.status = taskResult.FileStatus.Ok; updateTask.statusInfo = constants.NO_ERROR; yield taskResult.update(updateTask); } } } } } if (docsCoServer.getIsShutdown() && !isSfcm) { yield utils.promiseRedis(redisClient, redisClient.srem, redisKeyShutdown, docId); } logger.debug('End commandSfcCallback: docId = %s', docId); } function* commandSendMMCallback(cmd) { var docId = cmd.getDocId(); logger.debug('Start commandSendMMCallback: docId = %s', docId); var saveKey = cmd.getSaveKey(); var statusInfo = cmd.getStatusInfo(); var outputSfc = new commonDefines.OutputSfcData(); outputSfc.setKey(docId); if (constants.NO_ERROR == statusInfo) { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.MailMerge); } else { outputSfc.setStatus(docsCoServer.c_oAscServerStatus.Corrupted); } var mailMergeSendData = cmd.getMailMergeSend(); var outputMailMerge = new commonDefines.OutputMailMerge(mailMergeSendData); outputSfc.setMailMerge(outputMailMerge); outputSfc.setUsers([mailMergeSendData.getUserId()]); var data = yield storage.getObject(saveKey + '/' + cmd.getOutputPath()); var xml = data.toString('utf8'); var files = xml.match(/[< ]file.*?\/>/g); var recordRemain = (mailMergeSendData.getRecordTo() - mailMergeSendData.getRecordFrom() + 1); var recordIndexStart = mailMergeSendData.getRecordCount() - recordRemain; for (var i = 0; i < files.length; ++i) { var file = files[i]; var fieldRes = /field=["'](.*?)["']/.exec(file); outputMailMerge.setTo(fieldRes[1]); outputMailMerge.setRecordIndex(recordIndexStart + i); var pathRes = /path=["'](.*?)["']/.exec(file); var signedUrl = yield storage.getSignedUrl(mailMergeSendData.getBaseUrl(), saveKey + '/' + pathRes[1]); outputSfc.setUrl(signedUrl); var uri = mailMergeSendData.getUrl(); var postData = JSON.stringify(outputSfc); try { yield* docsCoServer.sendServerRequest(docId, uri, postData); } catch (err) { logger.error('sendServerRequest error: docId = %s;url = %s;data = %s\r\n%s', docId, uri, postData, err.stack); } } var newRecordFrom = mailMergeSendData.getRecordFrom() + Math.max(files.length, 1); if (newRecordFrom <= mailMergeSendData.getRecordTo()) { mailMergeSendData.setRecordFrom(newRecordFrom); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW); } else { logger.debug('End MailMerge: docId = %s', docId); } logger.debug('End commandSendMMCallback: docId = %s', docId); } exports.openDocument = function(conn, cmd, opt_upsertRes) { return co(function* () { var outputData; var docId = conn ? conn.docId : 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start command: docId = %s %s', docId, JSON.stringify(cmd)); outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'open': //yield utils.sleep(5000); yield* commandOpen(conn, cmd, outputData, opt_upsertRes); break; case 'reopen': yield* commandReopen(cmd); break; case 'imgurl': case 'imgurls': yield* commandImgurls(conn, cmd, outputData); break; case 'pathurl': yield* commandPathUrl(conn, cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } if(clientStatsD) { clientStatsD.timing('coauth.openDocument.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error openDocument: docId = %s\r\n%s', docId, e.stack); if (!outputData) { outputData = new OutputData(); } outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); } finally { if (outputData && outputData.getStatus()) { logger.debug('Response command: docId = %s %s', docId, JSON.stringify(outputData)); docsCoServer.sendData(conn, new OutputDataWrap('documentOpen', outputData)); } logger.debug('End command: docId = %s', docId); } }); }; exports.downloadAs = function(req, res) { return co(function* () { var docId = 'null'; try { var startDate = null; if(clientStatsD) { startDate = new Date(); } var strCmd = req.query['cmd']; var cmd = new commonDefines.InputCommand(JSON.parse(strCmd)); docId = cmd.getDocId(); logger.debug('Start downloadAs: docId = %s %s', docId, strCmd); cmd.setData(req.body); var outputData = new OutputData(cmd.getCommand()); switch (cmd.getCommand()) { case 'save': yield* commandSave(cmd, outputData); break; case 'savefromorigin': yield* commandSaveFromOrigin(cmd, outputData); break; case 'sendmm': yield* commandSendMailMerge(cmd, outputData); break; case 'sfct': yield* commandSfct(cmd, outputData); break; default: outputData.setStatus('err'); outputData.setData(constants.UNKNOWN); break; } var strRes = JSON.stringify(outputData); res.send(strRes); logger.debug('End downloadAs: docId = %s %s', docId, strRes); if(clientStatsD) { clientStatsD.timing('coauth.downloadAs.' + cmd.getCommand(), new Date() - startDate); } } catch (e) { logger.error('Error downloadAs: docId = %s\r\n%s', docId, e.stack); res.sendStatus(400); } }); }; exports.saveFromChanges = function(docId, statusInfo, optFormat, opt_userId, opt_queue) { return co(function* () { try { var startDate = null; if(clientStatsD) { startDate = new Date(); } logger.debug('Start saveFromChanges: docId = %s', docId); var task = new taskResult.TaskResultData(); task.key = docId; //делаем select, потому что за время timeout информация могла измениться var selectRes = yield taskResult.select(docId); var row = selectRes.length > 0 ? selectRes[0] : null; if (row && row.status == taskResult.FileStatus.SaveVersion && row.status_info == statusInfo) { if (null == optFormat) { optFormat = constants.AVS_OFFICESTUDIO_FILE_OTHER_TEAMLAB_INNER; } var cmd = new commonDefines.InputCommand(); cmd.setCommand('sfc'); cmd.setDocId(docId); cmd.setOutputFormat(optFormat); cmd.setData(statusInfo); cmd.setUserActionId(opt_userId); yield* addRandomKeyTaskCmd(cmd); var queueData = getSaveTask(cmd); queueData.setFromChanges(true); yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_NORMAL, opt_queue); if (docsCoServer.getIsShutdown()) { yield utils.promiseRedis(redisClient, redisClient.sadd, redisKeyShutdown, docId); } logger.debug('AddTask saveFromChanges: docId = %s', docId); } else { if (row) { logger.debug('saveFromChanges status mismatch: docId = %s; row: %d; %d; expected: %d', docId, row.status, row.status_info, statusInfo); } } if (clientStatsD) { clientStatsD.timing('coauth.saveFromChanges', new Date() - startDate); } } catch (e) { logger.error('Error saveFromChanges: docId = %s\r\n%s', docId, e.stack); } }); }; exports.receiveTask = function(data, dataRaw) { return co(function* () { var docId = 'null'; try { var task = new commonDefines.TaskQueueData(JSON.parse(data)); if (task) { var cmd = task.getCmd(); docId = cmd.getDocId(); logger.debug('Start receiveTask: docId = %s %s', docId, data); var updateTask = getUpdateResponse(cmd); var updateRes = yield taskResult.update(updateTask); if (updateRes.affectedRows > 0) { var outputData = new OutputData(cmd.getCommand()); var command = cmd.getCommand(); var additionalOutput = {needUrlKey: null, needUrlMethod: null}; if ('open' == command || 'reopen' == command) { //yield utils.sleep(5000); yield* getOutputData(cmd, outputData, cmd.getDocId(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('save' == command || 'savefromorigin' == command || 'sfct' == command) { yield* getOutputData(cmd, outputData, cmd.getSaveKey(), updateTask.status, updateTask.statusInfo, null, additionalOutput); } else if ('sfcm' == command) { yield* commandSfcCallback(cmd, true); } else if ('sfc' == command) { yield* commandSfcCallback(cmd, false); } else if ('sendmm' == command) { yield* commandSendMMCallback(cmd); } else if ('conv' == command) { //nothing } if (outputData.getStatus()) { logger.debug('Send receiveTask: docId = %s %s', docId, JSON.stringify(outputData)); var output = new OutputDataWrap('documentOpen', outputData); yield* docsCoServer.publish({ type: commonDefines.c_oPublishType.receiveTask, cmd: cmd, output: output, needUrlKey: additionalOutput.needUrlKey, needUrlMethod: additionalOutput.needUrlMethod }); } } yield* docsCoServer.removeResponse(dataRaw); logger.debug('End receiveTask: docId = %s', docId); } } catch (err) { logger.debug('Error receiveTask: docId = %s\r\n%s', docId, err.stack); } }); }; exports.cleanupCache = cleanupCache; exports.commandSfctByCmd = commandSfctByCmd; exports.commandOpenStartPromise = commandOpenStartPromise; exports.OutputDataWrap = OutputDataWrap; exports.OutputData = OutputData; \ No newline at end of file diff --git a/DocService/sources/converterservice.js b/DocService/sources/converterservice.js index 2a9a0dee2..2f8bb1cdf 100644 --- a/DocService/sources/converterservice.js +++ b/DocService/sources/converterservice.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 config = require('config'); var co = require('co'); var taskResult = require('./taskresult'); diff --git a/DocService/sources/database.js b/DocService/sources/database.js index 3d622a8c8..0a4bd8f15 100644 --- a/DocService/sources/database.js +++ b/DocService/sources/database.js @@ -1 +1 @@ -var mongoDB = require('mongodb'); var config = require('./config.json'); var _errorConnection = true; var logger = require('./../../Common/sources/logger'); function CreateDbClient(){ return new mongoDB.Db(config['mongodb']['database'], new mongoDB.Server(config['mongodb']['host'], config['mongodb']['port'], {auto_reconnect: true}), {safe:false}); } exports.insert = function (_collectionName, _newElement) { var _db = CreateDbClient(); if (!_db) { logger.error ("Error _db"); return; } // Открываем базу данных _db.open (function (err, db) { if (!err) { // Открываем коллекцию. Если её не существует, она будет создана db.collection(_collectionName, function(err, collection) { if (!err) { collection.insert (_newElement); } else { logger.error ("Error collection"); return; } db.close(); }); } else { logger.error ("Error open database"); } }); }; exports.remove = function (_collectionName, _removeElements) { var _db = CreateDbClient(); if (!_db) { logger.error ("Error _db"); return; } // Открываем базу данных _db.open (function (err, db) { if (!err) { // Открываем коллекцию. Если её не существует, она будет создана db.collection(_collectionName, function(err, collection) { if (!err) { collection.remove (_removeElements, function(err, collection) { // Все элементы удалены logger.info ("All elements remove"); }); } else { logger.error ("Error collection"); return; } db.close(); }); } else { logger.error ("Error open database"); } }); }; exports.load = function (_collectionName, callbackFunction) { var _db = CreateDbClient(); if (!_db) { logger.error ("Error _db"); return callbackFunction (null); } var result = []; // Открываем базу данных _db.open (function (err, db) { // Открываем коллекцию. Если её не существует, она будет создана db.collection(_collectionName, function(err, collection) { // Получаем все элементы коллекции с помощью find() collection.find(function(err, cursor) { cursor.each(function(err, item) { // Null обозначает последний элемент if (item != null) { if (!result.hasOwnProperty (item.docid)) result[item.docid] = [item]; else result[item.docid].push(item); } else callbackFunction (result); }); db.close(); }); }); }); }; \ No newline at end of file +/* * (c) Copyright Ascensio System SIA 2010-2016 * * 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 mongoDB = require('mongodb'); var config = require('./config.json'); var _errorConnection = true; var logger = require('./../../Common/sources/logger'); function CreateDbClient(){ return new mongoDB.Db(config['mongodb']['database'], new mongoDB.Server(config['mongodb']['host'], config['mongodb']['port'], {auto_reconnect: true}), {safe:false}); } exports.insert = function (_collectionName, _newElement) { var _db = CreateDbClient(); if (!_db) { logger.error ("Error _db"); return; } // Открываем базу данных _db.open (function (err, db) { if (!err) { // Открываем коллекцию. Если её не существует, она будет создана db.collection(_collectionName, function(err, collection) { if (!err) { collection.insert (_newElement); } else { logger.error ("Error collection"); return; } db.close(); }); } else { logger.error ("Error open database"); } }); }; exports.remove = function (_collectionName, _removeElements) { var _db = CreateDbClient(); if (!_db) { logger.error ("Error _db"); return; } // Открываем базу данных _db.open (function (err, db) { if (!err) { // Открываем коллекцию. Если её не существует, она будет создана db.collection(_collectionName, function(err, collection) { if (!err) { collection.remove (_removeElements, function(err, collection) { // Все элементы удалены logger.info ("All elements remove"); }); } else { logger.error ("Error collection"); return; } db.close(); }); } else { logger.error ("Error open database"); } }); }; exports.load = function (_collectionName, callbackFunction) { var _db = CreateDbClient(); if (!_db) { logger.error ("Error _db"); return callbackFunction (null); } var result = []; // Открываем базу данных _db.open (function (err, db) { // Открываем коллекцию. Если её не существует, она будет создана db.collection(_collectionName, function(err, collection) { // Получаем все элементы коллекции с помощью find() collection.find(function(err, cursor) { cursor.each(function(err, item) { // Null обозначает последний элемент if (item != null) { if (!result.hasOwnProperty (item.docid)) result[item.docid] = [item]; else result[item.docid].push(item); } else callbackFunction (result); }); db.close(); }); }); }); }; \ No newline at end of file diff --git a/DocService/sources/fileuploaderservice.js b/DocService/sources/fileuploaderservice.js index ebb7d06a0..a85187b0b 100644 --- a/DocService/sources/fileuploaderservice.js +++ b/DocService/sources/fileuploaderservice.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 multiparty = require('multiparty'); var co = require('co'); var taskResult = require('./taskresult'); diff --git a/DocService/sources/fontservice.js b/DocService/sources/fontservice.js index 759a611d7..31738e116 100644 --- a/DocService/sources/fontservice.js +++ b/DocService/sources/fontservice.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 fs = require('fs'); var path = require('path'); var util = require('util'); diff --git a/DocService/sources/gc.js b/DocService/sources/gc.js index dca966c07..c119fdc2e 100644 --- a/DocService/sources/gc.js +++ b/DocService/sources/gc.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 config = require('config').get('services.CoAuthoring'); var co = require('co'); var cron = require('cron'); diff --git a/DocService/sources/mySqlBaseConnector.js b/DocService/sources/mySqlBaseConnector.js index cc14c7e84..ad576b15f 100644 --- a/DocService/sources/mySqlBaseConnector.js +++ b/DocService/sources/mySqlBaseConnector.js @@ -1 +1 @@ -var mysql = require('mysql'); var configSql = require('config').get('services.CoAuthoring.sql'); var pool = mysql.createPool({ host : configSql.get('dbHost'), port : configSql.get('dbPort'), user : configSql.get('dbUser'), password : configSql.get('dbPass'), database : configSql.get('dbName'), charset : configSql.get('charset'), timezone : '+0000', flags : '-FOUND_ROWS' }); var logger = require('./../../Common/sources/logger'); exports.sqlQuery = function (sqlCommand, callbackFunction) { pool.getConnection(function(err, connection) { if (err) { logger.error('pool.getConnection error: %s', err); if (callbackFunction) callbackFunction(err, null); return; } connection.query(sqlCommand, function (error, result) { connection.release(); if (error) { logger.error('________________________error_____________________'); logger.error('sqlQuery: %s sqlCommand: %s', error.code, sqlCommand); logger.error(error); logger.error('_____________________end_error_____________________'); } if (callbackFunction) callbackFunction(error, result); }); }); }; exports.sqlEscape = function (value) { return pool.escape(value); }; \ No newline at end of file +/* * (c) Copyright Ascensio System SIA 2010-2016 * * 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 mysql = require('mysql'); var configSql = require('config').get('services.CoAuthoring.sql'); var pool = mysql.createPool({ host : configSql.get('dbHost'), port : configSql.get('dbPort'), user : configSql.get('dbUser'), password : configSql.get('dbPass'), database : configSql.get('dbName'), charset : configSql.get('charset'), timezone : '+0000', flags : '-FOUND_ROWS' }); var logger = require('./../../Common/sources/logger'); exports.sqlQuery = function (sqlCommand, callbackFunction) { pool.getConnection(function(err, connection) { if (err) { logger.error('pool.getConnection error: %s', err); if (callbackFunction) callbackFunction(err, null); return; } connection.query(sqlCommand, function (error, result) { connection.release(); if (error) { logger.error('________________________error_____________________'); logger.error('sqlQuery: %s sqlCommand: %s', error.code, sqlCommand); logger.error(error); logger.error('_____________________end_error_____________________'); } if (callbackFunction) callbackFunction(error, result); }); }); }; exports.sqlEscape = function (value) { return pool.escape(value); }; \ No newline at end of file diff --git a/DocService/sources/postgreSqlBaseConnector.js b/DocService/sources/postgreSqlBaseConnector.js index fbd596693..3fbc761b5 100644 --- a/DocService/sources/postgreSqlBaseConnector.js +++ b/DocService/sources/postgreSqlBaseConnector.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 pg = require('pg'); var configSql = require('config').get('services.CoAuthoring.sql'); var connectionString = 'postgres://' + configSql.get('dbUser') + ':' + configSql.get('dbPass') + '@' + configSql.get('dbHost') + diff --git a/DocService/sources/pubsubRabbitMQ.js b/DocService/sources/pubsubRabbitMQ.js index 5a198530b..7789ce02d 100644 --- a/DocService/sources/pubsubRabbitMQ.js +++ b/DocService/sources/pubsubRabbitMQ.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + 'use strict'; var events = require('events'); var util = require('util'); diff --git a/DocService/sources/pubsubRedis.js b/DocService/sources/pubsubRedis.js index 97e224f03..7a3dbc908 100644 --- a/DocService/sources/pubsubRedis.js +++ b/DocService/sources/pubsubRedis.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + 'use strict'; var config = require('config').get('services.CoAuthoring.redis'); var events = require('events'); diff --git a/DocService/sources/server.js b/DocService/sources/server.js index 69e140ea4..b10323f8c 100644 --- a/DocService/sources/server.js +++ b/DocService/sources/server.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + const fs = require('fs'); const cluster = require('cluster'); const configCommon = require('config'); diff --git a/DocService/sources/shutdown.js b/DocService/sources/shutdown.js index 2a8937d0d..110153552 100644 --- a/DocService/sources/shutdown.js +++ b/DocService/sources/shutdown.js @@ -1,27 +1,35 @@ /* + * (c) Copyright Ascensio System SIA 2010-2016 * - * (c) Copyright Ascensio System Limited 2010-2016 + * 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 freeware. You can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). - * In accordance with Section 7(a) of the GNU GPL 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 * - * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR - * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, + * EU, LV-1021. * - * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * 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. * - * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display - * Appropriate Legal Notices, as required under Section 5 of the GNU GPL 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. * - * Pursuant to Section 7 ยง 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains - * relevant author attributions when distributing the software. If the display of the logo in its graphic - * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" - * in every copy of the program you distribute. - * Pursuant to Section 7 ยง 3(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 * */ + 'use strict'; var config = require('config'); var configCoAuthoring = config.get('services.CoAuthoring'); diff --git a/DocService/sources/taskresult.js b/DocService/sources/taskresult.js index 89d605a48..b4ce80a7e 100644 --- a/DocService/sources/taskresult.js +++ b/DocService/sources/taskresult.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 sqlBase = require('./baseConnector'); var logger = require('./../../Common/sources/logger'); var utils = require('./../../Common/sources/utils'); diff --git a/FileConverter/sources/converter.js b/FileConverter/sources/converter.js index 3b6a3afe3..0d061a5c1 100644 --- a/FileConverter/sources/converter.js +++ b/FileConverter/sources/converter.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + 'use strict' var os = require('os'); var path = require('path'); diff --git a/FileConverter/sources/convertermaster.js b/FileConverter/sources/convertermaster.js index a9cddd139..138ce3fe6 100644 --- a/FileConverter/sources/convertermaster.js +++ b/FileConverter/sources/convertermaster.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + const cluster = require('cluster'); const logger = require('./../../Common/sources/logger'); diff --git a/Gruntfile.js b/Gruntfile.js index 433ae619a..01474b0de 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 packageFile = require('./package.json'); module.exports = function (grunt) { diff --git a/Metrics/config/config.js b/Metrics/config/config.js index d9151a2e6..26c0d3350 100644 --- a/Metrics/config/config.js +++ b/Metrics/config/config.js @@ -1,3 +1,35 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 + * + */ + /* Required Variables: diff --git a/SpellChecker/sources/server.js b/SpellChecker/sources/server.js index fe41319de..ea91193fe 100644 --- a/SpellChecker/sources/server.js +++ b/SpellChecker/sources/server.js @@ -1,4 +1,36 @@ -var cluster = require('cluster'); +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 cluster = require('cluster'); var config = require('config').get('SpellChecker'); //process.env.NODE_ENV = config.get('server.mode'); diff --git a/SpellChecker/sources/spellCheck.js b/SpellChecker/sources/spellCheck.js index 67cb169f4..a0f7d2040 100644 --- a/SpellChecker/sources/spellCheck.js +++ b/SpellChecker/sources/spellCheck.js @@ -1,4 +1,36 @@ -var sockjs = require('sockjs'), +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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'), nodehun = require('nodehun'), config = require('config').get('SpellChecker'), logger = require('./../../Common/sources/logger'), From 2ccdb2e315e1600ecbaec8ad3e5fb89640910df0 Mon Sep 17 00:00:00 2001 From: "Alexander.Trofimov" Date: Mon, 20 Jun 2016 19:02:34 +0300 Subject: [PATCH 08/20] build events return error status --- DocService/sources/DocsCoServer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index 99e29247a..5976ab3d1 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -724,6 +724,7 @@ function* bindEvents(docId, callback, baseUrl, opt_userAction) { } var userAction = opt_userAction ? opt_userAction : new commonDefines.OutputAction(commonDefines.c_oAscUserAction.AllIn, null); yield* sendStatusDocument(docId, bChangeBase, userAction, oCallbackUrl, baseUrl); + return commonDefines.c_oAscServerCommandErrors.NoError; } function* cleanDocumentOnExit(docId, deleteChanges) { @@ -2095,7 +2096,7 @@ exports.commandFromServer = function (req, res) { logger.debug('Start commandFromServer: docId = %s c = %s', docId, query.c); switch (query.c) { case 'info': - yield* bindEvents(docId, query.callback, utils.getBaseUrlByRequest(req)); + result = yield* bindEvents(docId, query.callback, utils.getBaseUrlByRequest(req)); break; case 'drop': if (query.userid) { From 2829fe5a8add679d2650dba7a91e5a7dae8e02ca Mon Sep 17 00:00:00 2001 From: "Alexey.Golubev" Date: Tue, 21 Jun 2016 13:15:45 +0300 Subject: [PATCH 09/20] Updated readme --- Readme.txt | 52 +++++++++------------------------------------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/Readme.txt b/Readme.txt index f5f8d38ed..d6138f669 100644 --- a/Readme.txt +++ b/Readme.txt @@ -3,15 +3,13 @@ ВНИМАНИЕ, инструкция описывает разворачивание сервиса документов на Windows-платформе. -0. Остановить сайт IIS сайт на 8001 порту(тестовый пример не надо оставливать) - 1. Установка необходимых компонентов Для работы сервиса документов необходимо установить в системе следующие компоненты (если не указано дополнительно, нужно ставить последнюю стабильную версию, любой разрядности, с дефолтными настройками): а) 32-х разрядную версии Node.js 4.0.x (https://nodejs.org/dist/v4.0.0/node-v4.0.0-x86.msi) Для уточнения существующей версии Node.js выполните 'node -v' 32-х разрядная версия требуется только для модуля проверки орфографии, если не планируется использовать этот модуль можно использовать 64-х разрядную версию. - б) MySql Server 5.6 и выше (http://dev.mysql.com/downloads/windows/installer/) При установке для пользователя root используйте пароль onlyoffice + б) MySql Server 5.5 и выше (http://dev.mysql.com/downloads/windows/installer/) При установке для пользователя root используйте пароль onlyoffice в) Erlang (http://www.erlang.org/download.html) г) RabbitMQ (https://www.rabbitmq.com/releases/rabbitmq-server/v3.5.4/rabbitmq-server-3.5.4.exe) д) Redis (https://github.com/MSOpenTech/redis/releases/download/win-2.8.2102/Redis-x64-2.8.2102.msi) @@ -21,64 +19,32 @@ 2. Настройка системы а) Настройка БД - Выполните скрипт в mysql document-server/schema/createdb.sql - - б) Установка npm модулей. - Запустите скрипт install_npm_modules.bat + Выполните скрипт в mysql schema/createdb.sql - в) Установка Web Monitor для RabbitMQ подробности(https://www.rabbitmq.com/management.html) + + б) Установка Web Monitor для RabbitMQ подробности(https://www.rabbitmq.com/management.html) открытивает cmd. переходим в папку (`cd /d Installation-directory/sbin`) вызываем(rabbitmq-plugins.bat enable rabbitmq_management) Web Monitor распологается по адресу(http://localhost:15672/). логин/пароль(guest/guest) - г) Если по какой-то причине у вас не стартует Redis, либо он стартует и через какое-то время падает, попробуйте в настройках конфига выставить размер параметра maxheap. Для WIN7 x64 файл конфига лежит тут: C:\Program Files\Redis\redis.windows-service.conf. В файле ищем строку + в) Если по какой-то причине у вас не стартует Redis, либо он стартует и через какое-то время падает, попробуйте в настройках конфига выставить размер параметра maxheap. Для WIN7 x64 файл конфига лежит тут: C:\Program Files\Redis\redis.windows-service.conf. В файле ищем строку # maxheap и меняет ее, например, на maxheap 128MB. Перезапускаем сервис. - д) Создать папку App_Data в папке nodeJSProjects. - - е) Если папка с меню называется не office или лежит не на одном уровне с OfficeWeb. то нужно создать локальный файл конфига nodeJSProjects\Common\config\local.json(под svn заливать не нужно) - с содержимым(в элементах static_content.path указать путь к меню) -{ - "services": { - "CoAuthoring": { - "server": { - "static_content": [ - { - "name": "/OfficeWeb", - "path": "../../../OfficeWeb" - }, - { - "name": "/office", - "path": "../../../office" - } - ] - } - } - } -} 3. Запуск сервиса -Запустите скрипт `run_services.bat` +Запустите скрипт `run.bat` Замечания - а) Все конфиги для серверной части храняться в папке nodeJSProjects\Common\config + а) Все конфиги для серверной части храняться в папке Common\config - default.json общие конфиги одинаковые для всех версий продакшина. - production-windows.json конфиги для запуска продакшин-версии на windows платформе - production-linux.json конфиги для запуска продакшин-версии на linux платформе - - development-windows.json конфиги для запуска девелоперской-версии на windows платформе (Эта конфигурация используется при запуске run_services.bat) + - development-windows.json конфиги для запуска девелоперской-версии на windows платформе (Эта конфигурация используется при запуске run.bat) - При необходимости внести временные изменения в конфиги создайте файл local.json и переопределите значения там. Файл коммитить под svn не надо. Это позволит случайно не залить локальные правки и избежать потери конфига при обновлении svn. Пример использования описан в пункте 2-д. Подробно о файлах конфигурации см. https://github.com/lorenwest/node-config/wiki/Configuration-Files + При необходимости внести временные изменения в конфиги создайте файл local.json и переопределите значения там. Это позволит случайно не залить локальные правки и избежать потери конфига при обновлении репозитория. Подробно о файлах конфигурации см. https://github.com/lorenwest/node-config/wiki/Configuration-Files -4. Лицензия. - Чтобы заработали комментарии, чат и другие платные возможности необходимо указать файл с лицензией (если путь не указан, то файл лицензии пытается открыться из корневой папки с именем 'licence.lic'): -{ - "license": { - "license_file": "./../../license.lic" - } -} -Актуальная версия лицензии по запросу. From ad51f6ff70249bd4941adb42f2134faee4cb7a74 Mon Sep 17 00:00:00 2001 From: "Alexander.Trofimov" Date: Wed, 22 Jun 2016 10:27:14 +0300 Subject: [PATCH 10/20] CommandError -> UnknownError add UnknownCommand = 5 error --- Common/sources/commondefines.js | 5 +++-- DocService/sources/DocsCoServer.js | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Common/sources/commondefines.js b/Common/sources/commondefines.js index ff537da2a..364095519 100644 --- a/Common/sources/commondefines.js +++ b/Common/sources/commondefines.js @@ -677,8 +677,9 @@ var c_oAscServerCommandErrors = { NoError: 0, DocumentIdError: 1, ParseError: 2, - CommandError: 3, - NotModify: 4 + UnknownError: 3, + NotModify: 4, + UnknownCommand: 5 }; exports.TaskQueueData = TaskQueueData; diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index 5976ab3d1..b4a9a5bc1 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -2136,7 +2136,7 @@ exports.commandFromServer = function (req, res) { //start new convert var status = yield* converterService.convertFromChanges(docId, baseUrl, lastSave, query.userdata); if (constants.NO_ERROR !== status.err) { - result = commonDefines.c_oAscServerCommandErrors.CommandError; + result = commonDefines.c_oAscServerCommandErrors.UnknownError; } } } else { @@ -2144,12 +2144,12 @@ exports.commandFromServer = function (req, res) { } break; default: - result = commonDefines.c_oAscServerCommandErrors.CommandError; + result = commonDefines.c_oAscServerCommandErrors.UnknownCommand; break; } } } catch (err) { - result = commonDefines.c_oAscServerCommandErrors.CommandError; + result = commonDefines.c_oAscServerCommandErrors.UnknownError; logger.error('Error commandFromServer: docId = %s\r\n%s', docId, err.stack); } finally { var output = JSON.stringify({'key': req.query.key, 'error': result}); From 8f11e949d4305882b7bea5c407db0ee44cccd996 Mon Sep 17 00:00:00 2001 From: Alexey Golubev Date: Wed, 22 Jun 2016 19:23:21 +0300 Subject: [PATCH 11/20] Update package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index dd8388e1b..7ab8640eb 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "./**/sources/*.js", "./Common/package.json", "./DocService/package.json", + "./DocService/public/healthcheck.docx", "./FileConverter/package.json", "./Metrics/package.json", "./SpellChecker/package.json", From 383ed7779faa7fe653326c91bd8a1f84882789ef Mon Sep 17 00:00:00 2001 From: "Alexey.Golubev" Date: Fri, 24 Jun 2016 11:59:48 +0300 Subject: [PATCH 12/20] Added DoctRender.config to repo --- .gitignore | 4 +++- FileConverter/bin/DoctRenderer.config | 19 +++++++++++++++++++ run.bat | 7 +++---- 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 FileConverter/bin/DoctRenderer.config diff --git a/.gitignore b/.gitignore index f810a9dcd..a345939cc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,9 @@ Common/config/local.json license.lic App_Data/ */node_modules -FileConverter/Bin +FileConverter/Bin/*.dll +FileConverter/Bin/*.exe +FileConverter/Bin/HtmlFileInternal DocService/npm-debug.log build node_modules \ No newline at end of file diff --git a/FileConverter/bin/DoctRenderer.config b/FileConverter/bin/DoctRenderer.config new file mode 100644 index 000000000..fc465ac5e --- /dev/null +++ b/FileConverter/bin/DoctRenderer.config @@ -0,0 +1,19 @@ + + ../../../sdkjs/common/Native/native.js + ../../../sdkjs/common/Native/jquery_native.js + ../../../web-apps/vendor/xregexp/xregexp-all-min.js + ../../../sdkjs/common/AllFonts.js + ../../../web-apps/vendor/jquery/jquery.min.js + + ../../../sdkjs/word/sdk-all-min.js + ../../../sdkjs/word/sdk-all.js + + + ../../../sdkjs/slide/sdk-all-min.js + ../../../sdkjs/slide/sdk-all.js + + + ../../../sdkjs/cell/sdk-all-min.js + ../../../sdkjs/cell/sdk-all.js + + \ No newline at end of file diff --git a/run.bat b/run.bat index dc1125866..12f266817 100644 --- a/run.bat +++ b/run.bat @@ -6,14 +6,13 @@ ECHO copy file to converter ECHO ---------------------------------------- mkdir "%~dp0\App_Data" -mkdir "%~dp0\FileConverter\Bin" -mkdir "%~dp0\FileConverter\Bin\HtmlFileInternal" +mkdir "%~dp0\FileConverter\bin" +mkdir "%~dp0\FileConverter\bin\HtmlFileInternal" -cd /D "%~dp0\FileConverter\Bin" || goto ERROR +cd /D "%~dp0\FileConverter\bin" || goto ERROR copy "..\..\..\core\build\bin\windows\icudt.dll" "." copy "..\..\..\core\build\bin\icu\win_32\icudt55.dll" "." copy "..\..\..\core\build\bin\icu\win_32\icuuc55.dll" "." -copy "..\..\..\core\build\lib\DoctRenderer.config" "." copy "..\..\..\core\build\lib\win_32\doctrenderer.dll" "." copy "..\..\..\core\build\lib\win_32\HtmlRenderer.dll" "." copy "..\..\..\core\build\lib\win_32\DjVuFile.dll" "." From 93659e608ae70f413d7bfded1625c54eeb9003d6 Mon Sep 17 00:00:00 2001 From: "Alexey.Golubev" Date: Fri, 24 Jun 2016 12:09:08 +0300 Subject: [PATCH 13/20] Bin -> bin --- .gitignore | 10 +++++++--- run-mac.command | 10 +++++----- run.bat | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index a345939cc..b181a8b70 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,13 @@ Common/config/local.json license.lic App_Data/ */node_modules -FileConverter/Bin/*.dll -FileConverter/Bin/*.exe -FileConverter/Bin/HtmlFileInternal +FileConverter/bin/*.dll +FileConverter/bin/*.dylib +FileConverter/bin/*.exe +FileConverter/bin/x2t +FileConverter/bin/*.S +FileConverter/bin/font_selection.bin +FileConverter/bin/HtmlFileInternal DocService/npm-debug.log build node_modules \ No newline at end of file diff --git a/run-mac.command b/run-mac.command index 09a5c885a..e9b352bef 100755 --- a/run-mac.command +++ b/run-mac.command @@ -25,10 +25,10 @@ RunCommand() { } CreateDir "$BASEDIR/App_Data" -CreateDir "$BASEDIR/FileConverter/Bin" -CreateDir "$BASEDIR/FileConverter/Bin/HtmlFileInternal" +CreateDir "$BASEDIR/FileConverter/bin" +CreateDir "$BASEDIR/FileConverter/bin/HtmlFileInternal" -cd "$BASEDIR/FileConverter/Bin" +cd "$BASEDIR/FileConverter/bin" cp -v "../../../core/build/bin/mac/icudtl_dat.S" "." cp -v "../../../core/build/bin/mac/x2t" "." @@ -54,7 +54,7 @@ sed "s/$SEARCH/$REPLACE/g" "../../../core/build/lib/DoctRenderer.config" > "Doct echo $BASEDIR chmod -v +x $BASEDIR/../core/build/bin/AllFontsGen/mac_64 -bash -cv "$BASEDIR/../core/build/bin/AllFontsGen/mac_64 '' '$BASEDIR/../sdkjs/Common/AllFonts.js' '$BASEDIR/../sdkjs/Common/Images' '$BASEDIR/FileConverter/Bin/font_selection.bin'" +bash -cv "$BASEDIR/../core/build/bin/AllFontsGen/mac_64 '' '$BASEDIR/../sdkjs/Common/AllFonts.js' '$BASEDIR/../sdkjs/Common/Images' '$BASEDIR/FileConverter/bin/font_selection.bin'" echo "----------------------------------------" @@ -78,6 +78,6 @@ RunCommand "redis-server /usr/local/etc/redis.conf" RunCommand "export NODE_CONFIG_DIR=$BASEDIR/Common/config && export NODE_ENV=development-mac && cd $BASEDIR/DocService/sources && node server.js" RunCommand "export NODE_CONFIG_DIR=$BASEDIR/Common/config && export NODE_ENV=development-mac && cd $BASEDIR/DocService/sources && node gc.js" -RunCommand "export NODE_CONFIG_DIR=$BASEDIR/Common/config && export NODE_ENV=development-mac && export DYLD_LIBRARY_PATH=../../FileConverter/Bin/ && cd $BASEDIR/FileConverter/sources && node convertermaster.js" +RunCommand "export NODE_CONFIG_DIR=$BASEDIR/Common/config && export NODE_ENV=development-mac && export DYLD_LIBRARY_PATH=../../FileConverter/bin/ && cd $BASEDIR/FileConverter/sources && node convertermaster.js" diff --git a/run.bat b/run.bat index 12f266817..e489657d0 100644 --- a/run.bat +++ b/run.bat @@ -25,7 +25,7 @@ copy "..\..\..\core\build\lib\win_32\HtmlFileInternal.exe" ".\HtmlFileInternal" xcopy /s/h/e/k/c/y/q "..\..\..\core\build\cef\win_32" ".\HtmlFileInternal" copy "..\..\..\core\build\bin\windows\x2t32.exe" "." -"..\..\..\core\build\bin\AllFontsGen\windows_32.exe" "%windir%\Fonts" "%~dp0\..\sdkjs\common\AllFonts.js" "%~dp0\..\sdkjs\common\Images" "%~dp0\FileConverter\Bin\font_selection.bin" +"..\..\..\core\build\bin\AllFontsGen\windows_32.exe" "%windir%\Fonts" "%~dp0\..\sdkjs\common\AllFonts.js" "%~dp0\..\sdkjs\common\Images" "%~dp0\FileConverter\bin\font_selection.bin" ECHO. ECHO ---------------------------------------- From 0ffb3a4a3c9f240036b2dd5b51c39ddcd3f18386 Mon Sep 17 00:00:00 2001 From: "Alexey.Golubev" Date: Fri, 24 Jun 2016 12:13:29 +0300 Subject: [PATCH 14/20] Copy DoctRenderer.config from FileConverter/bin --- Makefile | 1 - package.json | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 57ad4a919..c24d24617 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,6 @@ GRUNT_FILES = Gruntfile.js.out FILE_CONVERTER = $(OUTPUT)/FileConverter/bin FILE_CONVERTER_FILES += ../core/build/lib/linux_64/*.so -FILE_CONVERTER_FILES += ../core/build/lib/DoctRenderer.config FILE_CONVERTER_FILES += ../core/build/bin/icu/linux_64/*.so* FILE_CONVERTER_FILES += ../core/build/bin/linux/x2t FILE_CONVERTER_FILES += ../core/build/bin/linux/icudtl_dat.S diff --git a/package.json b/package.json index 7ab8640eb..e7a3ff65a 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "./DocService/package.json", "./DocService/public/healthcheck.docx", "./FileConverter/package.json", + "./FileConverter/bin/DoctRenderer.config", "./Metrics/package.json", "./SpellChecker/package.json", "./Common/config/*.json", From 3682e635e05d4831fe8f71ab56987945d8ce46a9 Mon Sep 17 00:00:00 2001 From: "Alexey.Golubev" Date: Fri, 24 Jun 2016 15:23:11 +0300 Subject: [PATCH 15/20] Changed path to 3rd party libs. --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c24d24617..f98341ac0 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,10 @@ GRUNT_FILES = Gruntfile.js.out FILE_CONVERTER = $(OUTPUT)/FileConverter/bin FILE_CONVERTER_FILES += ../core/build/lib/linux_64/*.so -FILE_CONVERTER_FILES += ../core/build/bin/icu/linux_64/*.so* +FILE_CONVERTER_FILES += /usr/local/lib/libicudata.so.55 +FILE_CONVERTER_FILES += /usr/local/lib/libicuuc.so.55 FILE_CONVERTER_FILES += ../core/build/bin/linux/x2t -FILE_CONVERTER_FILES += ../core/build/bin/linux/icudtl_dat.S +FILE_CONVERTER_FILES += ../v8/third_party/icu/linux/icudtl_dat.S HTML_FILE_INTERNAL := $(FILE_CONVERTER)/HtmlFileInternal HTML_FILE_INTERNAL_FILES += ../core/build/lib/linux_64/HtmlFileInternal From 25e88685a55af79658bf2e0dc39b09146b3c1d2d Mon Sep 17 00:00:00 2001 From: alexandervnuchkov Date: Fri, 24 Jun 2016 15:35:08 +0300 Subject: [PATCH 16/20] Readme.md translation --- Readme.txt | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 Readme.txt diff --git a/Readme.txt b/Readme.txt deleted file mode 100644 index d6138f669..000000000 --- a/Readme.txt +++ /dev/null @@ -1,50 +0,0 @@ -Настройка сервиса документов -============================ - -ВНИМАНИЕ, инструкция описывает разворачивание сервиса документов на Windows-платформе. - -1. Установка необходимых компонентов - -Для работы сервиса документов необходимо установить в системе следующие компоненты (если не указано дополнительно, нужно ставить последнюю стабильную версию, любой разрядности, с дефолтными настройками): - а) 32-х разрядную версии Node.js 4.0.x (https://nodejs.org/dist/v4.0.0/node-v4.0.0-x86.msi) - Для уточнения существующей версии Node.js выполните 'node -v' - 32-х разрядная версия требуется только для модуля проверки орфографии, если не планируется использовать этот модуль можно использовать 64-х разрядную версию. - б) MySql Server 5.5 и выше (http://dev.mysql.com/downloads/windows/installer/) При установке для пользователя root используйте пароль onlyoffice - в) Erlang (http://www.erlang.org/download.html) - г) RabbitMQ (https://www.rabbitmq.com/releases/rabbitmq-server/v3.5.4/rabbitmq-server-3.5.4.exe) - д) Redis (https://github.com/MSOpenTech/redis/releases/download/win-2.8.2102/Redis-x64-2.8.2102.msi) - е) Python 2.7.x (http://www.python.org/download/releases/2.7.3/#download) - ё) Microsoft Visual C++ Express 2010 (?) (требуется для сборки модулей для Spellchecker) - -2. Настройка системы - - а) Настройка БД - Выполните скрипт в mysql schema/createdb.sql - - - б) Установка Web Monitor для RabbitMQ подробности(https://www.rabbitmq.com/management.html) - открытивает cmd. переходим в папку (`cd /d Installation-directory/sbin`) - вызываем(rabbitmq-plugins.bat enable rabbitmq_management) - Web Monitor распологается по адресу(http://localhost:15672/). логин/пароль(guest/guest) - - в) Если по какой-то причине у вас не стартует Redis, либо он стартует и через какое-то время падает, попробуйте в настройках конфига выставить размер параметра maxheap. Для WIN7 x64 файл конфига лежит тут: C:\Program Files\Redis\redis.windows-service.conf. В файле ищем строку - # maxheap - и меняет ее, например, на - maxheap 128MB. - Перезапускаем сервис. - - -3. Запуск сервиса - -Запустите скрипт `run.bat` - -Замечания - - а) Все конфиги для серверной части храняться в папке Common\config - - default.json общие конфиги одинаковые для всех версий продакшина. - - production-windows.json конфиги для запуска продакшин-версии на windows платформе - - production-linux.json конфиги для запуска продакшин-версии на linux платформе - - development-windows.json конфиги для запуска девелоперской-версии на windows платформе (Эта конфигурация используется при запуске run.bat) - - При необходимости внести временные изменения в конфиги создайте файл local.json и переопределите значения там. Это позволит случайно не залить локальные правки и избежать потери конфига при обновлении репозитория. Подробно о файлах конфигурации см. https://github.com/lorenwest/node-config/wiki/Configuration-Files - From 1f186755f8229740e461a81066bf3292412507d6 Mon Sep 17 00:00:00 2001 From: alexandervnuchkov Date: Fri, 24 Jun 2016 15:40:36 +0300 Subject: [PATCH 17/20] corrections for Readme.md --- Readme.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 20d6723d2..acb2b1f70 100644 --- a/Readme.md +++ b/Readme.md @@ -5,34 +5,51 @@ This instruction describes document service deployment for Windows based platfor 1. Installing necessary components For the document service to work correctly it is necessary to install the following components for your Windows system (if not specified additionally, the latest version for 32 or 64 bit Windows can be installed with default settings): + a) Node.js 4.0.x 32 bit version (https://nodejs.org/dist/v4.0.0/node-v4.0.0-x86.msi) - To find out which Node.js version is used on your system currently run the `node -v` command - The 32 bit version is necessary for the spellchecking module only. In case you do not plan to use this module, you can install 64 bit Node.js version. + + To find out which Node.js version is used on your system currently run the `node -v` command + + The 32 bit version is necessary for the spellchecking module only. In case you do not plan to use this module, you can install 64 bit Node.js version. + b) MySql Server version 5.5 or later (http://dev.mysql.com/downloads/windows/installer/). When installing use the `onlyoffice` password for the `root` user + c) Erlang (http://www.erlang.org/download.html) + d) RabbitMQ (https://www.rabbitmq.com/releases/rabbitmq-server/v3.5.4/rabbitmq-server-3.5.4.exe) + e) Redis (https://github.com/MSOpenTech/redis/releases/download/win-2.8.2102/Redis-x64-2.8.2102.msi) + f) Python 2.7.x (http://www.python.org/download/releases/2.7.3/#download) + g) Microsoft Visual C++ Express 2010 (necessary for the spellchecker modules build) 2. Setting up the system a) Database setup + Run the schema/createdb.sql script for MySQL b) Install the Web Monitor for RabbitMQ (see the details for the installation here - https://www.rabbitmq.com/management.html) + Open the command line `cmd` executable. Switch to the installation directory using the `cd /d Installation-directory/sbin` command. + Run the following command: + ``` rabbitmq-plugins.bat enable rabbitmq_management ``` + The Web Monitor is located at the http://localhost:15672/ address. Use the `guest/guest` for the login/password combination. c) If Redis does not start or crashes after the start for some reason, try to change the `maxheap` parameter in the config settings. For 64 bit version of Windows 7 the config file can be found here: C:\Program Files\Redis\redis.windows-service.conf. + Find the `# maxheap ` line and change it to, e.g. + ``` maxheap 128MB ``` + Restart the service. 3. Running the service @@ -41,7 +58,7 @@ Run the `run.bat` script to start the service. Notes - All config files for the server part can be foun in the 'Common\config' folder + All config files for the server part can be foun in the `Common\config` folder * `default.json` - common config files similar for all production versions. * `production-windows.json` - config files for the production version running on a Windows based platform. * `production-linux.json` - config files for the production version running on a Linux based platform. From 440744d6a3bdbe453904fdde74cdc222cbeccb43 Mon Sep 17 00:00:00 2001 From: alexandervnuchkov Date: Fri, 24 Jun 2016 15:42:43 +0300 Subject: [PATCH 18/20] Readme.md --- Readme.md | 67 +++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/Readme.md b/Readme.md index acb2b1f70..e901b4a83 100644 --- a/Readme.md +++ b/Readme.md @@ -2,67 +2,66 @@ This instruction describes document service deployment for Windows based platform. -1. Installing necessary components +### Installing necessary components For the document service to work correctly it is necessary to install the following components for your Windows system (if not specified additionally, the latest version for 32 or 64 bit Windows can be installed with default settings): - a) Node.js 4.0.x 32 bit version (https://nodejs.org/dist/v4.0.0/node-v4.0.0-x86.msi) +a) Node.js 4.0.x 32 bit version (https://nodejs.org/dist/v4.0.0/node-v4.0.0-x86.msi) - To find out which Node.js version is used on your system currently run the `node -v` command +To find out which Node.js version is used on your system currently run the `node -v` command - The 32 bit version is necessary for the spellchecking module only. In case you do not plan to use this module, you can install 64 bit Node.js version. +The 32 bit version is necessary for the spellchecking module only. In case you do not plan to use this module, you can install 64 bit Node.js version. - b) MySql Server version 5.5 or later (http://dev.mysql.com/downloads/windows/installer/). When installing use the `onlyoffice` password for the `root` user +b) MySql Server version 5.5 or later (http://dev.mysql.com/downloads/windows/installer/). When installing use the `onlyoffice` password for the `root` user - c) Erlang (http://www.erlang.org/download.html) +c) Erlang (http://www.erlang.org/download.html) - d) RabbitMQ (https://www.rabbitmq.com/releases/rabbitmq-server/v3.5.4/rabbitmq-server-3.5.4.exe) +d) RabbitMQ (https://www.rabbitmq.com/releases/rabbitmq-server/v3.5.4/rabbitmq-server-3.5.4.exe) - e) Redis (https://github.com/MSOpenTech/redis/releases/download/win-2.8.2102/Redis-x64-2.8.2102.msi) +e) Redis (https://github.com/MSOpenTech/redis/releases/download/win-2.8.2102/Redis-x64-2.8.2102.msi) - f) Python 2.7.x (http://www.python.org/download/releases/2.7.3/#download) +f) Python 2.7.x (http://www.python.org/download/releases/2.7.3/#download) - g) Microsoft Visual C++ Express 2010 (necessary for the spellchecker modules build) +g) Microsoft Visual C++ Express 2010 (necessary for the spellchecker modules build) -2. Setting up the system +### Setting up the system - a) Database setup +a) Database setup - Run the schema/createdb.sql script for MySQL +Run the schema/createdb.sql script for MySQL - b) Install the Web Monitor for RabbitMQ (see the details for the installation here - https://www.rabbitmq.com/management.html) +b) Install the Web Monitor for RabbitMQ (see the details for the installation here - https://www.rabbitmq.com/management.html) - Open the command line `cmd` executable. Switch to the installation directory using the `cd /d Installation-directory/sbin` command. +Open the command line `cmd` executable. Switch to the installation directory using the `cd /d Installation-directory/sbin` command. - Run the following command: +Run the following command: - ``` - rabbitmq-plugins.bat enable rabbitmq_management - ``` +``` +rabbitmq-plugins.bat enable rabbitmq_management +``` - The Web Monitor is located at the http://localhost:15672/ address. Use the `guest/guest` for the login/password combination. +The Web Monitor is located at the http://localhost:15672/ address. Use the `guest/guest` for the login/password combination. - c) If Redis does not start or crashes after the start for some reason, try to change the `maxheap` parameter in the config settings. For 64 bit version of Windows 7 the config file can be found here: C:\Program Files\Redis\redis.windows-service.conf. +c) If Redis does not start or crashes after the start for some reason, try to change the `maxheap` parameter in the config settings. For 64 bit version of Windows 7 the config file can be found here: C:\Program Files\Redis\redis.windows-service.conf. - Find the `# maxheap ` line and change it to, e.g. +Find the `# maxheap ` line and change it to, e.g. - ``` - maxheap 128MB - ``` +``` +maxheap 128MB +``` - Restart the service. +Restart the service. -3. Running the service +### Running the service Run the `run.bat` script to start the service. Notes - All config files for the server part can be foun in the `Common\config` folder - * `default.json` - common config files similar for all production versions. - * `production-windows.json` - config files for the production version running on a Windows based platform. - * `production-linux.json` - config files for the production version running on a Linux based platform. - * `development-windows.json` - config files for the development version running on a Windows based platform (this configuration is used when running the 'run.bat' script). - - In case it is necessary to temporarily edit the config files, create the local.json file and reassign the values there. It will allow to prevent from uploading local changes and losing config files when updating the repository. See https://github.com/lorenwest/node-config/wiki/Configuration-Files for more information about the configuration files. +All config files for the server part can be foun in the `Common\config` folder +* `default.json` - common config files similar for all production versions. +* `production-windows.json` - config files for the production version running on a Windows based platform. +* `production-linux.json` - config files for the production version running on a Linux based platform. +* `development-windows.json` - config files for the development version running on a Windows based platform (this configuration is used when running the 'run.bat' script). +In case it is necessary to temporarily edit the config files, create the local.json file and reassign the values there. It will allow to prevent from uploading local changes and losing config files when updating the repository. See https://github.com/lorenwest/node-config/wiki/Configuration-Files for more information about the configuration files. \ No newline at end of file From 0e732f386ad4430c18e7aa126d33e2cf9be87e13 Mon Sep 17 00:00:00 2001 From: "Alexander.Trofimov" Date: Fri, 24 Jun 2016 16:50:40 +0300 Subject: [PATCH 19/20] add .travis.yml --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..4af5e0e47 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "6" + - "4" \ No newline at end of file From ddb8e396607e8b2e64709696a45878d46136d2ea Mon Sep 17 00:00:00 2001 From: Alexey Golubev Date: Fri, 24 Jun 2016 19:40:05 +0300 Subject: [PATCH 20/20] Update Makefile debug --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f98341ac0..6389be326 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ GRUNT_FILES = Gruntfile.js.out FILE_CONVERTER = $(OUTPUT)/FileConverter/bin FILE_CONVERTER_FILES += ../core/build/lib/linux_64/*.so -FILE_CONVERTER_FILES += /usr/local/lib/libicudata.so.55 -FILE_CONVERTER_FILES += /usr/local/lib/libicuuc.so.55 +FILE_CONVERTER_FILES += /usr/local/lib/libicudata.so.55* +FILE_CONVERTER_FILES += /usr/local/lib/libicuuc.so.55* FILE_CONVERTER_FILES += ../core/build/bin/linux/x2t FILE_CONVERTER_FILES += ../v8/third_party/icu/linux/icudtl_dat.S