mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
[linter] auto-fix
This commit is contained in:
@ -32,27 +32,27 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = require('config');
|
||||
var util = require('util');
|
||||
const config = require('config');
|
||||
const util = require('util');
|
||||
|
||||
var log4js = require('log4js');
|
||||
const log4js = require('log4js');
|
||||
const layouts = require('log4js/lib/layouts');
|
||||
|
||||
// https://stackoverflow.com/a/36643588
|
||||
var dateToJSONWithTZ = function (d) {
|
||||
var timezoneOffsetInHours = -(d.getTimezoneOffset() / 60); //UTC minus local time
|
||||
var sign = timezoneOffsetInHours >= 0 ? '+' : '-';
|
||||
var leadingZero = Math.abs(timezoneOffsetInHours) < 10 ? '0' : '';
|
||||
const dateToJSONWithTZ = function (d) {
|
||||
const timezoneOffsetInHours = -(d.getTimezoneOffset() / 60); //UTC minus local time
|
||||
const sign = timezoneOffsetInHours >= 0 ? '+' : '-';
|
||||
const leadingZero = Math.abs(timezoneOffsetInHours) < 10 ? '0' : '';
|
||||
|
||||
//It's a bit unfortunate that we need to construct a new Date instance
|
||||
//(we don't want _d_ Date instance to be modified)
|
||||
var correctedDate = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
|
||||
const correctedDate = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
|
||||
correctedDate.setHours(d.getHours() + timezoneOffsetInHours);
|
||||
var iso = correctedDate.toISOString().replace('Z', '');
|
||||
const iso = correctedDate.toISOString().replace('Z', '');
|
||||
return iso + sign + leadingZero + Math.abs(timezoneOffsetInHours).toString() + ':00';
|
||||
};
|
||||
|
||||
log4js.addLayout('json', function (config) {
|
||||
log4js.addLayout('json', (config) => {
|
||||
return function (logEvent) {
|
||||
logEvent['startTime'] = dateToJSONWithTZ(logEvent['startTime']);
|
||||
logEvent['message'] = util.format(...logEvent['data']);
|
||||
@ -66,11 +66,11 @@ log4js.addLayout('json', function (config) {
|
||||
* @param {object} cfg
|
||||
* @returns {function}
|
||||
*/
|
||||
log4js.addLayout('patternWithTokens', function (cfg) {
|
||||
log4js.addLayout('patternWithTokens', (cfg) => {
|
||||
const pattern = cfg && cfg.pattern ? cfg.pattern : '%m';
|
||||
const baseTokens = cfg && cfg.tokens ? cfg.tokens : {};
|
||||
const tokens = Object.assign({}, baseTokens, {
|
||||
usid: function (ev) {
|
||||
usid (ev) {
|
||||
const id = ev && ev.context && ev.context.USERSESSIONID;
|
||||
return id ? ` [${id}]` : '';
|
||||
}
|
||||
@ -80,7 +80,7 @@ log4js.addLayout('patternWithTokens', function (cfg) {
|
||||
|
||||
log4js.configure(config.get('log.filePath'));
|
||||
|
||||
var logger = log4js.getLogger('nodeJS');
|
||||
const logger = log4js.getLogger('nodeJS');
|
||||
|
||||
if (config.get('log.options.replaceConsole')) {
|
||||
console.log = logger.info.bind(logger);
|
||||
|
||||
@ -73,14 +73,14 @@ Context.prototype.initFromConnection = function (conn) {
|
||||
const userId = conn.user?.id;
|
||||
const shardKey = utils.getShardKeyByConnection(this, conn);
|
||||
const wopiSrc = utils.getWopiSrcByConnection(this, conn);
|
||||
let userSessionId = utils.getSessionIdByConnection(this, conn);
|
||||
const userSessionId = utils.getSessionIdByConnection(this, conn);
|
||||
this.init(tenant, docId || this.docId, userId || this.userId, shardKey, wopiSrc, userSessionId);
|
||||
};
|
||||
Context.prototype.initFromRequest = function (req) {
|
||||
const tenant = tenantManager.getTenantByRequest(this, req);
|
||||
const shardKey = utils.getShardKeyByRequest(this, req);
|
||||
const wopiSrc = utils.getWopiSrcByRequest(this, req);
|
||||
let userSessionId = utils.getSessionIdByRequest(this, req);
|
||||
const userSessionId = utils.getSessionIdByRequest(this, req);
|
||||
this.init(tenant, this.docId, this.userId, shardKey, wopiSrc, userSessionId);
|
||||
};
|
||||
Context.prototype.initFromTaskQueueData = function (task) {
|
||||
|
||||
@ -559,7 +559,7 @@ function sendData(ctx, conn, data) {
|
||||
ctx.logger.debug('sendData: type = %s', type);
|
||||
}
|
||||
function sendDataWarning(ctx, conn, code, description) {
|
||||
sendData(ctx, conn, {type: 'warning', code: code, message: description});
|
||||
sendData(ctx, conn, {type: 'warning', code, message: description});
|
||||
}
|
||||
function sendDataMessage(ctx, conn, msg) {
|
||||
if (!conn.permissions || false !== conn.permissions.chat) {
|
||||
@ -607,7 +607,7 @@ function modifyConnectionForPassword(ctx, conn, isEnterCorrectPassword) {
|
||||
return co(function* () {
|
||||
if (isEnterCorrectPassword) {
|
||||
conn.isEnterCorrectPassword = true;
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
const sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
});
|
||||
@ -1823,7 +1823,7 @@ exports.install = function (server, callbackFunction) {
|
||||
const handshake = socket.handshake;
|
||||
const token = handshake?.auth?.session || handshake?.auth?.token;
|
||||
if (tenTokenEnableBrowser || token) {
|
||||
let secretType = !!handshake?.auth?.session ? commonDefines.c_oAscSecretType.Session : commonDefines.c_oAscSecretType.Browser;
|
||||
const secretType = handshake?.auth?.session ? commonDefines.c_oAscSecretType.Session : commonDefines.c_oAscSecretType.Browser;
|
||||
checkJwtRes = yield checkJwt(ctx, token, secretType);
|
||||
if (!checkJwtRes.decoded) {
|
||||
res = new Error('not authorized');
|
||||
@ -2070,7 +2070,7 @@ exports.install = function (server, callbackFunction) {
|
||||
modifyConnectionEditorToView(ctx, conn);
|
||||
conn.isCloseCoAuthoring = true;
|
||||
yield addPresence(ctx, conn, true);
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
const sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
}
|
||||
@ -2330,7 +2330,7 @@ exports.install = function (server, callbackFunction) {
|
||||
// We put it in an array, because we need to send data to open/save the document
|
||||
connections.push(conn);
|
||||
yield addPresence(ctx, conn, true);
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
const sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
sendFileError(ctx, conn, errorId, code, opt_notWarn);
|
||||
}
|
||||
@ -4104,7 +4104,7 @@ exports.install = function (server, callbackFunction) {
|
||||
ctx.logger.debug('changeConnectionInfo: userId = %s', data.useridoriginal);
|
||||
participant.user.username = cmd.getUserName();
|
||||
yield addPresence(ctx, participant, false);
|
||||
let sessionToken = yield fillJwtByConnection(ctx, participant);
|
||||
const sessionToken = yield fillJwtByConnection(ctx, participant);
|
||||
sendDataRefreshToken(ctx, participant, sessionToken);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ async function proxyRequest(req, res) {
|
||||
let userId = '';
|
||||
let userName = '';
|
||||
let userCustomerId = '';
|
||||
let checkJwtRes = await docsCoServer.checkJwtHeader(ctx, req, 'Authorization', 'Bearer ', commonDefines.c_oAscSecretType.Session);
|
||||
const checkJwtRes = await docsCoServer.checkJwtHeader(ctx, req, 'Authorization', 'Bearer ', commonDefines.c_oAscSecretType.Session);
|
||||
if (!checkJwtRes || checkJwtRes.err) {
|
||||
ctx.logger.error('proxyRequest: checkJwtHeader error: %s', checkJwtRes?.err);
|
||||
res.status(403).json({
|
||||
|
||||
@ -1562,10 +1562,10 @@ exports.saveFile = function (req, res) {
|
||||
ctx.logger.debug('Start saveFile');
|
||||
|
||||
let isValidJwt = false;
|
||||
let checkJwtRes = yield docsCoServer.checkJwt(ctx, cmd.getTokenSession(), commonDefines.c_oAscSecretType.Session);
|
||||
const checkJwtRes = yield docsCoServer.checkJwt(ctx, cmd.getTokenSession(), commonDefines.c_oAscSecretType.Session);
|
||||
if (checkJwtRes.decoded) {
|
||||
let doc = checkJwtRes.decoded.document;
|
||||
var edit = checkJwtRes.decoded.editorConfig;
|
||||
const doc = checkJwtRes.decoded.document;
|
||||
const edit = checkJwtRes.decoded.editorConfig;
|
||||
if (doc.ds_encrypted && !edit.ds_view && !edit.ds_isCloseCoAuthoring) {
|
||||
isValidJwt = true;
|
||||
docId = doc.key;
|
||||
@ -1607,8 +1607,8 @@ function getPrintFileUrl(ctx, docId, baseUrl, filename) {
|
||||
const tenTokenSessionExpires = ms(ctx.getCfg('services.CoAuthoring.token.session.expires', cfgTokenSessionExpires));
|
||||
|
||||
baseUrl = utils.checkBaseUrl(ctx, baseUrl);
|
||||
let payload = {document: {key: docId}};
|
||||
let token = yield docsCoServer.signToken(
|
||||
const payload = {document: {key: docId}};
|
||||
const token = yield docsCoServer.signToken(
|
||||
ctx,
|
||||
payload,
|
||||
tenTokenSessionAlgorithm,
|
||||
@ -1650,9 +1650,9 @@ exports.printFile = function (req, res) {
|
||||
ctx.setDocId(docId);
|
||||
ctx.logger.info('Start printFile');
|
||||
|
||||
let checkJwtRes = yield docsCoServer.checkJwt(ctx, token, commonDefines.c_oAscSecretType.Session);
|
||||
const checkJwtRes = yield docsCoServer.checkJwt(ctx, token, commonDefines.c_oAscSecretType.Session);
|
||||
if (checkJwtRes.decoded) {
|
||||
let docIdBase = checkJwtRes.decoded.document.key;
|
||||
const docIdBase = checkJwtRes.decoded.document.key;
|
||||
if (!docId.startsWith(docIdBase)) {
|
||||
ctx.logger.warn('Error printFile jwt: description = %s', 'access deny');
|
||||
res.sendStatus(403);
|
||||
|
||||
@ -33,42 +33,42 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
var config = require('config');
|
||||
var co = require('co');
|
||||
const config = require('config');
|
||||
const co = require('co');
|
||||
const mime = require('mime');
|
||||
var taskResult = require('./taskresult');
|
||||
var utils = require('./../../Common/sources/utils');
|
||||
var constants = require('./../../Common/sources/constants');
|
||||
var commonDefines = require('./../../Common/sources/commondefines');
|
||||
var docsCoServer = require('./DocsCoServer');
|
||||
var canvasService = require('./canvasservice');
|
||||
var wopiClient = require('./wopiClient');
|
||||
var storage = require('./../../Common/sources/storage/storage-base');
|
||||
var formatChecker = require('./../../Common/sources/formatchecker');
|
||||
var statsDClient = require('./../../Common/sources/statsdclient');
|
||||
var storageBase = require('./../../Common/sources/storage/storage-base');
|
||||
var operationContext = require('./../../Common/sources/operationContext');
|
||||
const taskResult = require('./taskresult');
|
||||
const utils = require('./../../Common/sources/utils');
|
||||
const constants = require('./../../Common/sources/constants');
|
||||
const commonDefines = require('./../../Common/sources/commondefines');
|
||||
const docsCoServer = require('./DocsCoServer');
|
||||
const canvasService = require('./canvasservice');
|
||||
const wopiClient = require('./wopiClient');
|
||||
const storage = require('./../../Common/sources/storage/storage-base');
|
||||
const formatChecker = require('./../../Common/sources/formatchecker');
|
||||
const statsDClient = require('./../../Common/sources/statsdclient');
|
||||
const storageBase = require('./../../Common/sources/storage/storage-base');
|
||||
const operationContext = require('./../../Common/sources/operationContext');
|
||||
const sqlBase = require('./databaseConnectors/baseConnector');
|
||||
const utilsDocService = require('./utilsDocService');
|
||||
|
||||
const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
||||
|
||||
var CONVERT_ASYNC_DELAY = 1000;
|
||||
const CONVERT_ASYNC_DELAY = 1000;
|
||||
|
||||
var clientStatsD = statsDClient.getClient();
|
||||
const clientStatsD = statsDClient.getClient();
|
||||
|
||||
function* getConvertStatus(ctx, docId, encryptedUserPassword, selectRes, opt_checkPassword) {
|
||||
var status = new commonDefines.ConvertStatus(constants.NO_ERROR);
|
||||
const status = new commonDefines.ConvertStatus(constants.NO_ERROR);
|
||||
if (selectRes.length > 0) {
|
||||
var row = selectRes[0];
|
||||
let password = opt_checkPassword && sqlBase.DocumentPassword.prototype.getCurPassword(ctx, row.password);
|
||||
const row = selectRes[0];
|
||||
const password = opt_checkPassword && sqlBase.DocumentPassword.prototype.getCurPassword(ctx, row.password);
|
||||
switch (row.status) {
|
||||
case commonDefines.FileStatus.Ok:
|
||||
if (password) {
|
||||
let isCorrectPassword;
|
||||
if (encryptedUserPassword) {
|
||||
let decryptedPassword = yield utils.decryptPassword(ctx, password);
|
||||
let userPassword = yield utils.decryptPassword(ctx, encryptedUserPassword);
|
||||
const decryptedPassword = yield utils.decryptPassword(ctx, password);
|
||||
const userPassword = yield utils.decryptPassword(ctx, encryptedUserPassword);
|
||||
isCorrectPassword = decryptedPassword === userPassword;
|
||||
}
|
||||
if (isCorrectPassword) {
|
||||
@ -96,7 +96,7 @@ function* getConvertStatus(ctx, docId, encryptedUserPassword, selectRes, opt_che
|
||||
status.err = constants.UNKNOWN;
|
||||
break;
|
||||
}
|
||||
var lastOpenDate = row.last_open_date;
|
||||
const lastOpenDate = row.last_open_date;
|
||||
if (new Date().getTime() - lastOpenDate.getTime() > utils.getConvertionTimeout(ctx)) {
|
||||
status.err = constants.CONVERT_TIMEOUT;
|
||||
}
|
||||
@ -107,8 +107,8 @@ function* getConvertStatus(ctx, docId, encryptedUserPassword, selectRes, opt_che
|
||||
}
|
||||
function* getConvertPath(ctx, docId, fileTo, formatTo) {
|
||||
if (constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML === formatTo || constants.AVS_OFFICESTUDIO_FILE_OTHER_ODF === formatTo) {
|
||||
let list = yield storage.listObjects(ctx, docId);
|
||||
let baseName = path.basename(fileTo, path.extname(fileTo));
|
||||
const list = yield storage.listObjects(ctx, docId);
|
||||
const baseName = path.basename(fileTo, path.extname(fileTo));
|
||||
for (let i = 0; i < list.length; ++i) {
|
||||
if (path.basename(list[i], path.extname(list[i])) === baseName) {
|
||||
return list[i];
|
||||
@ -124,8 +124,8 @@ function* getConvertUrl(ctx, baseUrl, fileToPath, title) {
|
||||
return yield storage.getSignedUrl(ctx, baseUrl, fileToPath, commonDefines.c_oAscUrlTypes.Temporary, title);
|
||||
}
|
||||
function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority, opt_expiration, opt_queue, opt_checkPassword) {
|
||||
var docId = cmd.getDocId();
|
||||
var startDate = null;
|
||||
const docId = cmd.getDocId();
|
||||
let startDate = null;
|
||||
if (clientStatsD) {
|
||||
startDate = new Date();
|
||||
}
|
||||
@ -133,7 +133,7 @@ function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority,
|
||||
|
||||
let bCreate = false;
|
||||
if (!opt_taskExist) {
|
||||
let task = new taskResult.TaskResultData();
|
||||
const task = new taskResult.TaskResultData();
|
||||
task.tenant = ctx.tenant;
|
||||
task.key = docId;
|
||||
task.status = commonDefines.FileStatus.WaitQueue;
|
||||
@ -142,27 +142,27 @@ function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority,
|
||||
const upsertRes = yield taskResult.upsert(ctx, task);
|
||||
bCreate = upsertRes.isInsert;
|
||||
}
|
||||
var selectRes;
|
||||
var status;
|
||||
let selectRes;
|
||||
let status;
|
||||
if (!bCreate) {
|
||||
selectRes = yield taskResult.select(ctx, docId);
|
||||
status = yield* getConvertStatus(ctx, cmd.getDocId(), cmd.getPassword(), selectRes, opt_checkPassword);
|
||||
}
|
||||
if (bCreate || commonDefines.FileStatus.None === selectRes?.[0]?.status) {
|
||||
var queueData = new commonDefines.TaskQueueData();
|
||||
const queueData = new commonDefines.TaskQueueData();
|
||||
queueData.setCtx(ctx);
|
||||
queueData.setCmd(cmd);
|
||||
if (opt_fileTo) {
|
||||
queueData.setToFile(opt_fileTo);
|
||||
}
|
||||
queueData.setFromOrigin(true);
|
||||
var priority = null != opt_priority ? opt_priority : constants.QUEUE_PRIORITY_LOW;
|
||||
const priority = null != opt_priority ? opt_priority : constants.QUEUE_PRIORITY_LOW;
|
||||
yield* docsCoServer.addTask(queueData, priority, opt_queue, opt_expiration);
|
||||
status = new commonDefines.ConvertStatus(constants.NO_ERROR);
|
||||
}
|
||||
//wait
|
||||
if (!async) {
|
||||
var waitTime = 0;
|
||||
let waitTime = 0;
|
||||
while (true) {
|
||||
if (status.end || constants.NO_ERROR != status.err) {
|
||||
break;
|
||||
@ -201,7 +201,7 @@ async function convertFromChanges(
|
||||
opt_initShardKey,
|
||||
opt_jsonParams
|
||||
) {
|
||||
var cmd = new commonDefines.InputCommand();
|
||||
const cmd = new commonDefines.InputCommand();
|
||||
cmd.setCommand('sfcm');
|
||||
cmd.setDocId(docId);
|
||||
cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML);
|
||||
@ -237,18 +237,18 @@ async function convertFromChanges(
|
||||
cmd.appendJsonParams(opt_jsonParams);
|
||||
}
|
||||
|
||||
let commandSfctByCmdRes = await canvasService.commandSfctByCmd(ctx, cmd, opt_priority, opt_expiration, opt_queue, opt_initShardKey);
|
||||
const commandSfctByCmdRes = await canvasService.commandSfctByCmd(ctx, cmd, opt_priority, opt_expiration, opt_queue, opt_initShardKey);
|
||||
if (!commandSfctByCmdRes) {
|
||||
return new commonDefines.ConvertStatus(constants.UNKNOWN);
|
||||
}
|
||||
var fileTo = constants.OUTPUT_NAME;
|
||||
let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat());
|
||||
let fileTo = constants.OUTPUT_NAME;
|
||||
const outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat());
|
||||
if (outputExt) {
|
||||
fileTo += '.' + outputExt;
|
||||
}
|
||||
let status = await co(convertByCmd(ctx, cmd, true, fileTo, undefined, opt_priority, opt_expiration, opt_queue));
|
||||
const status = await co(convertByCmd(ctx, cmd, true, fileTo, undefined, opt_priority, opt_expiration, opt_queue));
|
||||
if (status.end) {
|
||||
let fileToPath = await co(getConvertPath(ctx, docId, fileTo, cmd.getOutputFormat()));
|
||||
const fileToPath = await co(getConvertPath(ctx, docId, fileTo, cmd.getOutputFormat()));
|
||||
status.setExtName(path.extname(fileToPath));
|
||||
status.setUrl(await co(getConvertUrl(ctx, baseUrl, fileToPath, cmd.getTitle())));
|
||||
}
|
||||
@ -260,13 +260,13 @@ function parseIntParam(val) {
|
||||
|
||||
function convertRequest(req, res, isJson) {
|
||||
return co(function* () {
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
ctx.logger.info('convertRequest start');
|
||||
let params;
|
||||
let authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||
const authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||
if (authRes.code === constants.NO_ERROR) {
|
||||
params = authRes.params;
|
||||
} else {
|
||||
@ -274,8 +274,8 @@ function convertRequest(req, res, isJson) {
|
||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(authRes.code), isJson);
|
||||
return;
|
||||
}
|
||||
let filetype = params.filetype || params.fileType || '';
|
||||
let outputtype = params.outputtype || params.outputType || '';
|
||||
const filetype = params.filetype || params.fileType || '';
|
||||
const outputtype = params.outputtype || params.outputType || '';
|
||||
ctx.setDocId(params.key);
|
||||
|
||||
if (params.key && !constants.DOC_ID_REGEX.test(params.key)) {
|
||||
@ -311,8 +311,8 @@ function convertRequest(req, res, isJson) {
|
||||
}
|
||||
}
|
||||
//todo use hash of params as id
|
||||
let docId = 'conv_' + params.key + '_' + outputFormat;
|
||||
var cmd = new commonDefines.InputCommand();
|
||||
const docId = 'conv_' + params.key + '_' + outputFormat;
|
||||
const cmd = new commonDefines.InputCommand();
|
||||
cmd.setCommand('conv');
|
||||
cmd.setUrl(params.url);
|
||||
cmd.setEmbeddedFonts(false); //params.embeddedfonts'];
|
||||
@ -328,7 +328,7 @@ function convertRequest(req, res, isJson) {
|
||||
if (params.region) {
|
||||
cmd.setLCID(utilsDocService.localeToLCID(params.region));
|
||||
}
|
||||
let jsonParams = {};
|
||||
const jsonParams = {};
|
||||
if (params.documentLayout) {
|
||||
jsonParams['documentLayout'] = params.documentLayout;
|
||||
}
|
||||
@ -347,18 +347,18 @@ function convertRequest(req, res, isJson) {
|
||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||
return;
|
||||
}
|
||||
let encryptedPassword = yield utils.encryptPassword(ctx, params.password);
|
||||
const encryptedPassword = yield utils.encryptPassword(ctx, params.password);
|
||||
cmd.setPassword(encryptedPassword);
|
||||
}
|
||||
if (authRes.isDecoded) {
|
||||
cmd.setWithAuthorization(true);
|
||||
}
|
||||
var thumbnail = params.thumbnail;
|
||||
let thumbnail = params.thumbnail;
|
||||
if (thumbnail) {
|
||||
if (typeof thumbnail === 'string') {
|
||||
thumbnail = JSON.parse(thumbnail);
|
||||
}
|
||||
var thumbnailData = new commonDefines.CThumbnailData(thumbnail);
|
||||
const thumbnailData = new commonDefines.CThumbnailData(thumbnail);
|
||||
//constants from CXIMAGE_FORMAT_
|
||||
switch (cmd.getOutputFormat()) {
|
||||
case constants.AVS_OFFICESTUDIO_FILE_IMAGE_JPG:
|
||||
@ -379,12 +379,12 @@ function convertRequest(req, res, isJson) {
|
||||
outputExt = 'zip';
|
||||
}
|
||||
}
|
||||
var documentRenderer = params.documentRenderer;
|
||||
let documentRenderer = params.documentRenderer;
|
||||
if (documentRenderer) {
|
||||
if (typeof documentRenderer === 'string') {
|
||||
documentRenderer = JSON.parse(documentRenderer);
|
||||
}
|
||||
var textParamsData = new commonDefines.CTextParams();
|
||||
const textParamsData = new commonDefines.CTextParams();
|
||||
switch (documentRenderer.textAssociation) {
|
||||
case 'plainParagraph':
|
||||
textParamsData.setAssociation(3);
|
||||
@ -405,7 +405,7 @@ function convertRequest(req, res, isJson) {
|
||||
if (params.title) {
|
||||
cmd.setTitle(path.basename(params.title, path.extname(params.title)) + '.' + outputExt);
|
||||
}
|
||||
var async = typeof params.async === 'string' ? 'true' == params.async : params.async;
|
||||
let async = typeof params.async === 'string' ? 'true' == params.async : params.async;
|
||||
if (async && !req.query[constants.SHARD_KEY_API_NAME] && !req.query[constants.SHARD_KEY_WOPI_NAME] && process.env.DEFAULT_SHARD_KEY) {
|
||||
ctx.logger.warn(
|
||||
'convertRequest set async=false. Pass query string parameter "%s" to correctly process request in sharded cluster',
|
||||
@ -414,17 +414,17 @@ function convertRequest(req, res, isJson) {
|
||||
async = false;
|
||||
}
|
||||
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN !== cmd.getOutputFormat()) {
|
||||
let fileTo = constants.OUTPUT_NAME + '.' + outputExt;
|
||||
var status = yield* convertByCmd(ctx, cmd, async, fileTo, undefined, undefined, undefined, undefined, true);
|
||||
const fileTo = constants.OUTPUT_NAME + '.' + outputExt;
|
||||
const status = yield* convertByCmd(ctx, cmd, async, fileTo, undefined, undefined, undefined, undefined, true);
|
||||
if (status.end) {
|
||||
let fileToPath = yield* getConvertPath(ctx, docId, fileTo, cmd.getOutputFormat());
|
||||
const fileToPath = yield* getConvertPath(ctx, docId, fileTo, cmd.getOutputFormat());
|
||||
status.setExtName(path.extname(fileToPath));
|
||||
status.setUrl(yield* getConvertUrl(ctx, utils.getBaseUrlByRequest(ctx, req), fileToPath, cmd.getTitle()));
|
||||
ctx.logger.debug('convertRequest: url = %s', status.url);
|
||||
}
|
||||
utils.fillResponse(req, res, status, isJson);
|
||||
} else {
|
||||
var addresses = utils.forwarded(req);
|
||||
const addresses = utils.forwarded(req);
|
||||
ctx.logger.warn('Error convert unknown outputtype: query = %j from = %s', params, addresses);
|
||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), isJson);
|
||||
}
|
||||
@ -445,28 +445,28 @@ function convertRequestXml(req, res) {
|
||||
|
||||
function builderRequest(req, res) {
|
||||
return co(function* () {
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
ctx.logger.info('builderRequest start');
|
||||
let authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||
let params = authRes.params;
|
||||
const authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||
const params = authRes.params;
|
||||
let docId = params.key;
|
||||
ctx.setDocId(docId);
|
||||
|
||||
let error = authRes.code;
|
||||
let urls;
|
||||
let end = false;
|
||||
let needCreateId = !docId;
|
||||
let isInBody = req.body && Buffer.isBuffer(req.body) && req.body.length > 0;
|
||||
const needCreateId = !docId;
|
||||
const isInBody = req.body && Buffer.isBuffer(req.body) && req.body.length > 0;
|
||||
if (error === constants.NO_ERROR && (params.key || params.url || isInBody)) {
|
||||
if (needCreateId) {
|
||||
let task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'bld_', 8);
|
||||
const task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'bld_', 8);
|
||||
docId = task.key;
|
||||
ctx.setDocId(docId);
|
||||
}
|
||||
let cmd = new commonDefines.InputCommand();
|
||||
const cmd = new commonDefines.InputCommand();
|
||||
cmd.setCommand('builder');
|
||||
cmd.setBuilderParams({argument: params.argument});
|
||||
if (authRes.isDecoded) {
|
||||
@ -480,7 +480,7 @@ function builderRequest(req, res) {
|
||||
yield storageBase.putObject(ctx, docId + '/script.docbuilder', req.body, req.body.length);
|
||||
}
|
||||
if (needCreateId) {
|
||||
let queueData = new commonDefines.TaskQueueData();
|
||||
const queueData = new commonDefines.TaskQueueData();
|
||||
queueData.setCtx(ctx);
|
||||
queueData.setCmd(cmd);
|
||||
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW);
|
||||
@ -493,7 +493,7 @@ function builderRequest(req, res) {
|
||||
);
|
||||
async = false;
|
||||
}
|
||||
let status = yield* convertByCmd(ctx, cmd, async, undefined, undefined, constants.QUEUE_PRIORITY_LOW);
|
||||
const status = yield* convertByCmd(ctx, cmd, async, undefined, undefined, constants.QUEUE_PRIORITY_LOW);
|
||||
end = status.end;
|
||||
error = status.err;
|
||||
if (end) {
|
||||
@ -514,7 +514,7 @@ function builderRequest(req, res) {
|
||||
}
|
||||
function convertTo(req, res) {
|
||||
return co(function* () {
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
@ -524,7 +524,7 @@ function convertTo(req, res) {
|
||||
format = req.params.format;
|
||||
}
|
||||
//todo https://github.com/LibreOffice/core/blob/9d3366f5b392418dc83bc0adbe3d215cff4b3605/desktop/source/lib/init.cxx#L3478
|
||||
let password = req.body['Password'];
|
||||
const password = req.body['Password'];
|
||||
if (password) {
|
||||
if (password.length > constants.PASSWORD_MAX_LENGTH) {
|
||||
ctx.logger.warn('convert-to Password too long actual = %s; max = %s', password.length, constants.PASSWORD_MAX_LENGTH);
|
||||
@ -533,7 +533,7 @@ function convertTo(req, res) {
|
||||
}
|
||||
}
|
||||
//by analogy with Password
|
||||
let passwordToOpen = req.body['PasswordToOpen'];
|
||||
const passwordToOpen = req.body['PasswordToOpen'];
|
||||
if (passwordToOpen) {
|
||||
if (passwordToOpen.length > constants.PASSWORD_MAX_LENGTH) {
|
||||
ctx.logger.warn('convert-to PasswordToOpen too long actual = %s; max = %s', passwordToOpen.length, constants.PASSWORD_MAX_LENGTH);
|
||||
@ -541,13 +541,13 @@ function convertTo(req, res) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let pdfVer = req.body['PDFVer'];
|
||||
const pdfVer = req.body['PDFVer'];
|
||||
if (pdfVer && pdfVer.startsWith('PDF/A') && 'pdf' === format) {
|
||||
format = 'pdfa';
|
||||
}
|
||||
let fullSheetPreview = req.body['FullSheetPreview'];
|
||||
let lang = req.body['lang'];
|
||||
let outputFormat = formatChecker.getFormatFromString(format);
|
||||
const fullSheetPreview = req.body['FullSheetPreview'];
|
||||
const lang = req.body['lang'];
|
||||
const outputFormat = formatChecker.getFormatFromString(format);
|
||||
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === outputFormat) {
|
||||
ctx.logger.warn('convert-to unexpected format = %s', format);
|
||||
res.sendStatus(400);
|
||||
@ -557,22 +557,22 @@ function convertTo(req, res) {
|
||||
if (req.files?.length > 0 && req.files[0].originalname && req.files[0].buffer) {
|
||||
const file = req.files[0];
|
||||
originalname = file.originalname;
|
||||
let filetype = path.extname(file.originalname).substring(1);
|
||||
const filetype = path.extname(file.originalname).substring(1);
|
||||
if (filetype && !constants.EXTENTION_REGEX.test(filetype)) {
|
||||
ctx.logger.warn('convertRequest unexpected filetype = %s', filetype);
|
||||
res.sendStatus(400);
|
||||
return;
|
||||
}
|
||||
|
||||
let task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'conv_', 8);
|
||||
const task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'conv_', 8);
|
||||
docId = task.key;
|
||||
ctx.setDocId(docId);
|
||||
|
||||
//todo stream
|
||||
let buffer = file.buffer;
|
||||
const buffer = file.buffer;
|
||||
yield storageBase.putObject(ctx, docId + '/origin.' + filetype, buffer, buffer.length);
|
||||
|
||||
let cmd = new commonDefines.InputCommand();
|
||||
const cmd = new commonDefines.InputCommand();
|
||||
cmd.setCommand('conv');
|
||||
cmd.setDocId(docId);
|
||||
cmd.setFormat(filetype);
|
||||
@ -601,33 +601,33 @@ function convertTo(req, res) {
|
||||
});
|
||||
}
|
||||
if (password) {
|
||||
let encryptedPassword = yield utils.encryptPassword(ctx, password);
|
||||
const encryptedPassword = yield utils.encryptPassword(ctx, password);
|
||||
cmd.setSavePassword(encryptedPassword);
|
||||
}
|
||||
if (passwordToOpen) {
|
||||
let encryptedPassword = yield utils.encryptPassword(ctx, passwordToOpen);
|
||||
const encryptedPassword = yield utils.encryptPassword(ctx, passwordToOpen);
|
||||
cmd.setPassword(encryptedPassword);
|
||||
}
|
||||
|
||||
fileTo = constants.OUTPUT_NAME;
|
||||
let outputExt = formatChecker.getStringFromFormat(outputFormat);
|
||||
const outputExt = formatChecker.getStringFromFormat(outputFormat);
|
||||
if (outputExt) {
|
||||
fileTo += '.' + outputExt;
|
||||
}
|
||||
|
||||
let queueData = new commonDefines.TaskQueueData();
|
||||
const queueData = new commonDefines.TaskQueueData();
|
||||
queueData.setCtx(ctx);
|
||||
queueData.setCmd(cmd);
|
||||
queueData.setToFile(fileTo);
|
||||
queueData.setFromOrigin(true);
|
||||
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW);
|
||||
|
||||
let async = false;
|
||||
const async = false;
|
||||
status = yield* convertByCmd(ctx, cmd, async, fileTo);
|
||||
}
|
||||
if (status && status.end && constants.NO_ERROR === status.err) {
|
||||
let filename = path.basename(originalname, path.extname(originalname)) + path.extname(fileTo);
|
||||
let streamObj = yield storage.createReadStream(ctx, `${docId}/${fileTo}`);
|
||||
const filename = path.basename(originalname, path.extname(originalname)) + path.extname(fileTo);
|
||||
const streamObj = yield storage.createReadStream(ctx, `${docId}/${fileTo}`);
|
||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename, null, constants.CONTENT_DISPOSITION_INLINE));
|
||||
res.setHeader('Content-Length', streamObj.contentLength);
|
||||
res.setHeader('Content-Type', mime.getType(filename));
|
||||
@ -649,15 +649,15 @@ function convertAndEdit(ctx, wopiParams, filetypeFrom, filetypeTo) {
|
||||
try {
|
||||
ctx.logger.info('convert-and-edit start');
|
||||
|
||||
let task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'conv_', 8);
|
||||
let docId = task.key;
|
||||
let outputFormat = formatChecker.getFormatFromString(filetypeTo);
|
||||
const task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'conv_', 8);
|
||||
const docId = task.key;
|
||||
const outputFormat = formatChecker.getFormatFromString(filetypeTo);
|
||||
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === outputFormat) {
|
||||
ctx.logger.debug('convert-and-edit unknown outputFormat %s', filetypeTo);
|
||||
return;
|
||||
}
|
||||
|
||||
let cmd = new commonDefines.InputCommand();
|
||||
const cmd = new commonDefines.InputCommand();
|
||||
cmd.setCommand('conv');
|
||||
cmd.setDocId(docId);
|
||||
cmd.setUrl('dummy-url');
|
||||
@ -666,18 +666,18 @@ function convertAndEdit(ctx, wopiParams, filetypeFrom, filetypeTo) {
|
||||
cmd.setOutputFormat(outputFormat);
|
||||
|
||||
let fileTo = constants.OUTPUT_NAME;
|
||||
let outputExt = formatChecker.getStringFromFormat(outputFormat);
|
||||
const outputExt = formatChecker.getStringFromFormat(outputFormat);
|
||||
if (outputExt) {
|
||||
fileTo += '.' + outputExt;
|
||||
}
|
||||
|
||||
let queueData = new commonDefines.TaskQueueData();
|
||||
const queueData = new commonDefines.TaskQueueData();
|
||||
queueData.setCtx(ctx);
|
||||
queueData.setCmd(cmd);
|
||||
queueData.setToFile(fileTo);
|
||||
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW);
|
||||
|
||||
let async = true;
|
||||
const async = true;
|
||||
yield* convertByCmd(ctx, cmd, async, fileTo);
|
||||
return docId;
|
||||
} catch (err) {
|
||||
@ -689,17 +689,17 @@ function convertAndEdit(ctx, wopiParams, filetypeFrom, filetypeTo) {
|
||||
}
|
||||
function getConverterHtmlHandler(req, res) {
|
||||
return co(function* () {
|
||||
let isJson = true;
|
||||
let ctx = new operationContext.Context();
|
||||
const isJson = true;
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
ctx.logger.info('convert-and-edit-handler start');
|
||||
const tenTokenEnableBrowser = ctx.getCfg('services.CoAuthoring.token.enable.browser', cfgTokenEnableBrowser);
|
||||
|
||||
let wopiSrc = req.query['wopisrc'];
|
||||
let access_token = req.query['access_token'];
|
||||
let targetext = req.query['targetext'];
|
||||
const wopiSrc = req.query['wopisrc'];
|
||||
const access_token = req.query['access_token'];
|
||||
const targetext = req.query['targetext'];
|
||||
let docId = req.query['docid'];
|
||||
ctx.setDocId(docId);
|
||||
if (
|
||||
@ -716,9 +716,9 @@ function getConverterHtmlHandler(req, res) {
|
||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||
return;
|
||||
}
|
||||
let token = req.query['token'];
|
||||
const token = req.query['token'];
|
||||
if (tenTokenEnableBrowser || token) {
|
||||
let checkJwtRes = yield docsCoServer.checkJwt(ctx, token, commonDefines.c_oAscSecretType.Browser);
|
||||
const checkJwtRes = yield docsCoServer.checkJwt(ctx, token, commonDefines.c_oAscSecretType.Browser);
|
||||
if (checkJwtRes.decoded) {
|
||||
docId = checkJwtRes.decoded.docId;
|
||||
} else {
|
||||
@ -729,14 +729,14 @@ function getConverterHtmlHandler(req, res) {
|
||||
}
|
||||
ctx.setDocId(docId);
|
||||
|
||||
let selectRes = yield taskResult.select(ctx, docId);
|
||||
let status = yield* getConvertStatus(ctx, docId, undefined, selectRes);
|
||||
const selectRes = yield taskResult.select(ctx, docId);
|
||||
const status = yield* getConvertStatus(ctx, docId, undefined, selectRes);
|
||||
if (status.end && constants.NO_ERROR === status.err) {
|
||||
let fileTo = `${docId}/${constants.OUTPUT_NAME}.${targetext}`;
|
||||
const fileTo = `${docId}/${constants.OUTPUT_NAME}.${targetext}`;
|
||||
|
||||
let metadata = yield storage.headObject(ctx, fileTo);
|
||||
let streamObj = yield storage.createReadStream(ctx, fileTo);
|
||||
let putRelativeRes = yield wopiClient.putRelativeFile(
|
||||
const metadata = yield storage.headObject(ctx, fileTo);
|
||||
const streamObj = yield storage.createReadStream(ctx, fileTo);
|
||||
const putRelativeRes = yield wopiClient.putRelativeFile(
|
||||
ctx,
|
||||
wopiSrc,
|
||||
access_token,
|
||||
|
||||
@ -32,17 +32,17 @@
|
||||
|
||||
'use strict';
|
||||
const crypto = require('crypto');
|
||||
var multiparty = require('multiparty');
|
||||
var co = require('co');
|
||||
const multiparty = require('multiparty');
|
||||
const co = require('co');
|
||||
const utilsDocService = require('./utilsDocService');
|
||||
var docsCoServer = require('./DocsCoServer');
|
||||
var utils = require('./../../Common/sources/utils');
|
||||
var constants = require('./../../Common/sources/constants');
|
||||
var storageBase = require('./../../Common/sources/storage/storage-base');
|
||||
var formatChecker = require('./../../Common/sources/formatchecker');
|
||||
const docsCoServer = require('./DocsCoServer');
|
||||
const utils = require('./../../Common/sources/utils');
|
||||
const constants = require('./../../Common/sources/constants');
|
||||
const storageBase = require('./../../Common/sources/storage/storage-base');
|
||||
const formatChecker = require('./../../Common/sources/formatchecker');
|
||||
const commonDefines = require('./../../Common/sources/commondefines');
|
||||
const operationContext = require('./../../Common/sources/operationContext');
|
||||
var config = require('config');
|
||||
const config = require('config');
|
||||
|
||||
const cfgImageSize = config.get('services.CoAuthoring.server.limits_image_size');
|
||||
const cfgTypesUpload = config.get('services.CoAuthoring.utils.limits_image_types_upload');
|
||||
@ -51,10 +51,10 @@ const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.brow
|
||||
const PATTERN_ENCRYPTED = 'ENCRYPTED;';
|
||||
|
||||
function checkJwtUploadTransformRes(ctx, errorName, checkJwtRes) {
|
||||
var res = {err: true, docId: null, userid: null, encrypted: null};
|
||||
const res = {err: true, docId: null, userid: null, encrypted: null};
|
||||
if (checkJwtRes.decoded) {
|
||||
var doc = checkJwtRes.decoded.document;
|
||||
var edit = checkJwtRes.decoded.editorConfig;
|
||||
const doc = checkJwtRes.decoded.document;
|
||||
const edit = checkJwtRes.decoded.editorConfig;
|
||||
//todo check view and pdf editor (temporary fix)
|
||||
if (!edit.ds_isCloseCoAuthoring) {
|
||||
res.err = false;
|
||||
@ -74,9 +74,9 @@ function checkJwtUploadTransformRes(ctx, errorName, checkJwtRes) {
|
||||
exports.uploadImageFile = function (req, res) {
|
||||
return co(function* () {
|
||||
let httpStatus = 200;
|
||||
var docId = 'null';
|
||||
let output = {};
|
||||
let ctx = new operationContext.Context();
|
||||
let docId = 'null';
|
||||
const output = {};
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
@ -92,7 +92,7 @@ exports.uploadImageFile = function (req, res) {
|
||||
//todo remove compatibility with previous versions
|
||||
checkJwtRes = yield docsCoServer.checkJwt(ctx, req.query['token'], commonDefines.c_oAscSecretType.Session);
|
||||
}
|
||||
let transformedRes = checkJwtUploadTransformRes(ctx, 'uploadImageFile', checkJwtRes);
|
||||
const transformedRes = checkJwtUploadTransformRes(ctx, 'uploadImageFile', checkJwtRes);
|
||||
if (!transformedRes.err) {
|
||||
docId = transformedRes.docId || docId;
|
||||
encrypted = transformedRes.encrypted;
|
||||
@ -105,13 +105,13 @@ exports.uploadImageFile = function (req, res) {
|
||||
if (200 === httpStatus && docId && req.body && Buffer.isBuffer(req.body)) {
|
||||
let buffer = req.body;
|
||||
if (buffer.length <= tenImageSize) {
|
||||
var format = formatChecker.getImageFormat(ctx, buffer);
|
||||
var formatStr = formatChecker.getStringFromFormat(format);
|
||||
let format = formatChecker.getImageFormat(ctx, buffer);
|
||||
let formatStr = formatChecker.getStringFromFormat(format);
|
||||
if (encrypted && PATTERN_ENCRYPTED === buffer.toString('utf8', 0, PATTERN_ENCRYPTED.length)) {
|
||||
formatStr = buffer.toString('utf8', PATTERN_ENCRYPTED.length, buffer.indexOf(';', PATTERN_ENCRYPTED.length));
|
||||
}
|
||||
var supportedFormats = tenTypesUpload || 'jpg';
|
||||
let formatLimit = formatStr && -1 !== supportedFormats.indexOf(formatStr);
|
||||
const supportedFormats = tenTypesUpload || 'jpg';
|
||||
const formatLimit = formatStr && -1 !== supportedFormats.indexOf(formatStr);
|
||||
if (formatLimit) {
|
||||
if (format === constants.AVS_OFFICESTUDIO_FILE_IMAGE_TIFF) {
|
||||
buffer = yield utilsDocService.convertImageToPng(ctx, buffer);
|
||||
@ -119,9 +119,9 @@ exports.uploadImageFile = function (req, res) {
|
||||
formatStr = formatChecker.getStringFromFormat(format);
|
||||
}
|
||||
//a hash is written at the beginning to avoid errors during parallel upload in co-editing
|
||||
var strImageName = crypto.randomBytes(16).toString('hex');
|
||||
var strPathRel = 'media/' + strImageName + '.' + formatStr;
|
||||
var strPath = docId + '/' + strPathRel;
|
||||
const strImageName = crypto.randomBytes(16).toString('hex');
|
||||
const strPathRel = 'media/' + strImageName + '.' + formatStr;
|
||||
const strPath = docId + '/' + strPathRel;
|
||||
|
||||
buffer = yield utilsDocService.fixImageExifRotation(ctx, buffer);
|
||||
|
||||
|
||||
@ -104,11 +104,11 @@ if (!mimeDB['application/vnd.visio2013']) {
|
||||
mimeDB['application/vnd.visio2013'] = {extensions: ['vsdx', 'vstx', 'vssx', 'vsdm', 'vstm', 'vssm']};
|
||||
}
|
||||
|
||||
let mimeTypesByExt = (function () {
|
||||
let mimeTypesByExt = {};
|
||||
for (let mimeType in mimeDB) {
|
||||
const mimeTypesByExt = (function () {
|
||||
const mimeTypesByExt = {};
|
||||
for (const mimeType in mimeDB) {
|
||||
if (mimeDB.hasOwnProperty(mimeType)) {
|
||||
let val = mimeDB[mimeType];
|
||||
const val = mimeDB[mimeType];
|
||||
if (val.extensions) {
|
||||
val.extensions.forEach(value => {
|
||||
if (!mimeTypesByExt[value]) {
|
||||
@ -130,7 +130,7 @@ async function getTemplatesFolderExts(ctx) {
|
||||
templatesFolderExtsCache = dirContent
|
||||
.filter(dirObject => dirObject.isFile())
|
||||
.reduce((result, item, index, array) => {
|
||||
let ext = path.extname(item.name).substring(1);
|
||||
const ext = path.extname(item.name).substring(1);
|
||||
result[ext] = ext;
|
||||
return result;
|
||||
}, {});
|
||||
@ -141,7 +141,7 @@ async function getTemplatesFolderExts(ctx) {
|
||||
function discovery(req, res) {
|
||||
return co(function* () {
|
||||
const xml = xmlbuilder2.create({version: '1.0', encoding: 'utf-8'});
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
@ -171,18 +171,18 @@ function discovery(req, res) {
|
||||
const tenWopiExponentOld = ctx.getCfg('wopi.exponentOld', cfgWopiExponentOld);
|
||||
const tenWopiHost = ctx.getCfg('wopi.host', cfgWopiHost);
|
||||
|
||||
let baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
||||
let names = ['Word', 'Excel', 'PowerPoint', 'Pdf'];
|
||||
let favIconUrls = [tenWopiFavIconUrlWord, tenWopiFavIconUrlCell, tenWopiFavIconUrlSlide, tenWopiFavIconUrlPdf];
|
||||
let exts = [
|
||||
const baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
||||
const names = ['Word', 'Excel', 'PowerPoint', 'Pdf'];
|
||||
const favIconUrls = [tenWopiFavIconUrlWord, tenWopiFavIconUrlCell, tenWopiFavIconUrlSlide, tenWopiFavIconUrlPdf];
|
||||
const exts = [
|
||||
{targetext: 'docx', view: tenWopiWordView, edit: tenWopiWordEdit},
|
||||
{targetext: 'xlsx', view: tenWopiCellView, edit: tenWopiCellEdit},
|
||||
{targetext: 'pptx', view: tenWopiSlideView, edit: tenWopiSlideEdit},
|
||||
{targetext: null, view: tenWopiPdfView, edit: tenWopiPdfEdit}
|
||||
];
|
||||
let documentTypes = [`word`, `cell`, `slide`, `pdf`];
|
||||
const documentTypes = [`word`, `cell`, `slide`, `pdf`];
|
||||
//todo check sdkjs-ooxml addon
|
||||
let addVisio =
|
||||
const addVisio =
|
||||
(tenWopiDiagramView.length > 0 || tenWopiDiagramEdit.length > 0) &&
|
||||
(constants.PACKAGE_TYPE_OS !== license.packageType || process.env?.NODE_ENV?.startsWith('development-'));
|
||||
if (addVisio) {
|
||||
@ -192,39 +192,39 @@ function discovery(req, res) {
|
||||
documentTypes.push(`diagram`);
|
||||
}
|
||||
|
||||
let templatesFolderExtsCache = yield getTemplatesFolderExts(ctx);
|
||||
let formsExts = tenWopiForms.reduce((result, item, index, array) => {
|
||||
const templatesFolderExtsCache = yield getTemplatesFolderExts(ctx);
|
||||
const formsExts = tenWopiForms.reduce((result, item, index, array) => {
|
||||
result[item] = item;
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
let templateStart = `${baseUrl}/hosting/wopi`;
|
||||
const templateStart = `${baseUrl}/hosting/wopi`;
|
||||
let templateEnd = `<rs=DC_LLCC&><dchat=DISABLE_CHAT&><embed=EMBEDDED&>`;
|
||||
templateEnd += `<fs=FULLSCREEN&><hid=HOST_SESSION_ID&><rec=RECORDING&>`;
|
||||
templateEnd += `<sc=SESSION_CONTEXT&><thm=THEME_ID&><ui=UI_LLCC&>`;
|
||||
templateEnd += `<wopisrc=WOPI_SOURCE&>&`;
|
||||
let xmlZone = xml.ele('wopi-discovery').ele('net-zone', {name: tenWopiWopiZone});
|
||||
const xmlZone = xml.ele('wopi-discovery').ele('net-zone', {name: tenWopiWopiZone});
|
||||
//start section for MS WOPI connectors
|
||||
for (let i = 0; i < names.length; ++i) {
|
||||
let name = names[i];
|
||||
const name = names[i];
|
||||
let favIconUrl = favIconUrls[i];
|
||||
if (!(favIconUrl.startsWith('http://') || favIconUrl.startsWith('https://'))) {
|
||||
favIconUrl = baseUrl + favIconUrl;
|
||||
}
|
||||
let ext = exts[i];
|
||||
let urlTemplateView = `${templateStart}/${documentTypes[i]}/view?${templateEnd}`;
|
||||
let urlTemplateEmbedView = `${templateStart}/${documentTypes[i]}/view?embed=1&${templateEnd}`;
|
||||
let urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
||||
let urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
||||
let urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
||||
let urlTemplateFormSubmit = `${templateStart}/${documentTypes[i]}/edit?formsubmit=1&${templateEnd}`;
|
||||
let xmlApp = xmlZone.ele('app', {name: name, favIconUrl: favIconUrl});
|
||||
const ext = exts[i];
|
||||
const urlTemplateView = `${templateStart}/${documentTypes[i]}/view?${templateEnd}`;
|
||||
const urlTemplateEmbedView = `${templateStart}/${documentTypes[i]}/view?embed=1&${templateEnd}`;
|
||||
const urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
||||
const urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
||||
const urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
||||
const urlTemplateFormSubmit = `${templateStart}/${documentTypes[i]}/edit?formsubmit=1&${templateEnd}`;
|
||||
const xmlApp = xmlZone.ele('app', {name, favIconUrl});
|
||||
for (let j = 0; j < ext.view.length; ++j) {
|
||||
xmlApp.ele('action', {name: 'view', ext: ext.view[j], default: 'true', urlsrc: urlTemplateView}).up();
|
||||
xmlApp.ele('action', {name: 'embedview', ext: ext.view[j], urlsrc: urlTemplateEmbedView}).up();
|
||||
xmlApp.ele('action', {name: 'mobileView', ext: ext.view[j], urlsrc: urlTemplateMobileView}).up();
|
||||
if (ext.targetext) {
|
||||
let urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
||||
const urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
||||
xmlApp.ele('action', {name: 'convert', ext: ext.view[j], targetext: ext.targetext, requires: 'update', urlsrc: urlConvert}).up();
|
||||
}
|
||||
}
|
||||
@ -248,16 +248,16 @@ function discovery(req, res) {
|
||||
//end section for MS WOPI connectors
|
||||
//start section for collabora nexcloud connectors
|
||||
for (let i = 0; i < exts.length; ++i) {
|
||||
let ext = exts[i];
|
||||
let urlTemplateView = `${templateStart}/${documentTypes[i]}/view?${templateEnd}`;
|
||||
let urlTemplateEmbedView = `${templateStart}/${documentTypes[i]}/view?embed=1&${templateEnd}`;
|
||||
let urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
||||
let urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
||||
let urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
||||
let urlTemplateFormSubmit = `${templateStart}/${documentTypes[i]}/edit?formsubmit=1&${templateEnd}`;
|
||||
let mimeTypesDuplicate = new Set(); //to remove duplicates for each editor(allow html for word and excel)
|
||||
const ext = exts[i];
|
||||
const urlTemplateView = `${templateStart}/${documentTypes[i]}/view?${templateEnd}`;
|
||||
const urlTemplateEmbedView = `${templateStart}/${documentTypes[i]}/view?embed=1&${templateEnd}`;
|
||||
const urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
||||
const urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
||||
const urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
||||
const urlTemplateFormSubmit = `${templateStart}/${documentTypes[i]}/edit?formsubmit=1&${templateEnd}`;
|
||||
const mimeTypesDuplicate = new Set(); //to remove duplicates for each editor(allow html for word and excel)
|
||||
for (let j = 0; j < ext.view.length; ++j) {
|
||||
let mimeTypes = mimeTypesByExt[ext.view[j]];
|
||||
const mimeTypes = mimeTypesByExt[ext.view[j]];
|
||||
if (mimeTypes) {
|
||||
mimeTypes.forEach(value => {
|
||||
if (mimeTypesDuplicate.has(value)) {
|
||||
@ -265,12 +265,12 @@ function discovery(req, res) {
|
||||
} else {
|
||||
mimeTypesDuplicate.add(value);
|
||||
}
|
||||
let xmlApp = xmlZone.ele('app', {name: value});
|
||||
const xmlApp = xmlZone.ele('app', {name: value});
|
||||
xmlApp.ele('action', {name: 'view', ext: '', default: 'true', urlsrc: urlTemplateView}).up();
|
||||
xmlApp.ele('action', {name: 'embedview', ext: '', urlsrc: urlTemplateEmbedView}).up();
|
||||
xmlApp.ele('action', {name: 'mobileView', ext: '', urlsrc: urlTemplateMobileView}).up();
|
||||
if (ext.targetext) {
|
||||
let urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
||||
const urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
||||
xmlApp.ele('action', {name: 'convert', ext: '', targetext: ext.targetext, requires: 'update', urlsrc: urlConvert}).up();
|
||||
}
|
||||
xmlApp.up();
|
||||
@ -279,7 +279,7 @@ function discovery(req, res) {
|
||||
}
|
||||
mimeTypesDuplicate.clear();
|
||||
for (let j = 0; j < ext.edit.length; ++j) {
|
||||
let mimeTypes = mimeTypesByExt[ext.edit[j]];
|
||||
const mimeTypes = mimeTypesByExt[ext.edit[j]];
|
||||
if (mimeTypes) {
|
||||
mimeTypes.forEach(value => {
|
||||
if (mimeTypesDuplicate.has(value)) {
|
||||
@ -287,7 +287,7 @@ function discovery(req, res) {
|
||||
} else {
|
||||
mimeTypesDuplicate.add(value);
|
||||
}
|
||||
let xmlApp = xmlZone.ele('app', {name: value});
|
||||
const xmlApp = xmlZone.ele('app', {name: value});
|
||||
if (formsExts[ext.edit[j]]) {
|
||||
xmlApp.ele('action', {name: 'edit', ext: '', default: 'true', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||
xmlApp.ele('action', {name: 'formsubmit', ext: '', requires: 'locks,update', urlsrc: urlTemplateFormSubmit}).up();
|
||||
@ -303,14 +303,14 @@ function discovery(req, res) {
|
||||
}
|
||||
}
|
||||
}
|
||||
let xmlApp = xmlZone.ele('app', {name: 'Capabilities'});
|
||||
const xmlApp = xmlZone.ele('app', {name: 'Capabilities'});
|
||||
xmlApp.ele('action', {ext: '', name: 'getinfo', requires: 'locks,update', urlsrc: `${baseUrl}/hosting/capabilities`}).up();
|
||||
xmlApp.up();
|
||||
//end section for collabora nexcloud connectors
|
||||
let xmlDiscovery = xmlZone.up();
|
||||
const xmlDiscovery = xmlZone.up();
|
||||
if (tenWopiPublicKeyOld && tenWopiPublicKey) {
|
||||
let exponent = numberToBase64(tenWopiExponent);
|
||||
let exponentOld = numberToBase64(tenWopiExponentOld);
|
||||
const exponent = numberToBase64(tenWopiExponent);
|
||||
const exponentOld = numberToBase64(tenWopiExponentOld);
|
||||
xmlDiscovery
|
||||
.ele('proof-key', {
|
||||
oldvalue: tenWopiPublicKeyOld,
|
||||
@ -318,7 +318,7 @@ function discovery(req, res) {
|
||||
oldexponent: exponentOld,
|
||||
value: tenWopiPublicKey,
|
||||
modulus: tenWopiModulus,
|
||||
exponent: exponent
|
||||
exponent
|
||||
})
|
||||
.up();
|
||||
}
|
||||
@ -334,7 +334,7 @@ function discovery(req, res) {
|
||||
}
|
||||
function collaboraCapabilities(req, res) {
|
||||
return co(function* () {
|
||||
let output = {
|
||||
const output = {
|
||||
'convert-to': {available: true, endpoint: '/lool/convert-to'},
|
||||
hasMobileSupport: true,
|
||||
hasProxyPrefix: false,
|
||||
@ -342,7 +342,7 @@ function collaboraCapabilities(req, res) {
|
||||
hasTemplateSource: true,
|
||||
productVersion: commonDefines.buildVersion
|
||||
};
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
@ -363,7 +363,7 @@ function isWopiUnlockMarker(url) {
|
||||
}
|
||||
function isWopiModifiedMarker(url) {
|
||||
if (isWopiCallback(url)) {
|
||||
let obj = JSON.parse(url);
|
||||
const obj = JSON.parse(url);
|
||||
return obj.fileInfo && obj.fileInfo.LastModifiedTime;
|
||||
}
|
||||
}
|
||||
@ -390,8 +390,8 @@ function setIsShutdown(val) {
|
||||
}
|
||||
function getLastModifiedTimeFromCallbacks(callbacks) {
|
||||
for (let i = callbacks.length; i >= 0; --i) {
|
||||
let callback = callbacks[i];
|
||||
let lastModifiedTime = isWopiModifiedMarker(callback);
|
||||
const callback = callbacks[i];
|
||||
const lastModifiedTime = isWopiModifiedMarker(callback);
|
||||
if (lastModifiedTime) {
|
||||
return lastModifiedTime;
|
||||
}
|
||||
@ -410,13 +410,13 @@ function parseWopiCallback(ctx, userAuthStr, opt_url) {
|
||||
let commonInfo = null;
|
||||
let lastModifiedTime = null;
|
||||
if (opt_url) {
|
||||
let commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, opt_url, 1);
|
||||
const commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, opt_url, 1);
|
||||
if (isWopiCallback(commonInfoStr)) {
|
||||
commonInfo = JSON.parse(commonInfoStr);
|
||||
if (commonInfo.fileInfo) {
|
||||
lastModifiedTime = commonInfo.fileInfo.LastModifiedTime;
|
||||
if (lastModifiedTime) {
|
||||
let callbacks = sqlBase.UserCallback.prototype.getCallbacks(ctx, opt_url);
|
||||
const callbacks = sqlBase.UserCallback.prototype.getCallbacks(ctx, opt_url);
|
||||
lastModifiedTime = getLastModifiedTimeFromCallbacks(callbacks);
|
||||
}
|
||||
} else {
|
||||
@ -424,43 +424,43 @@ function parseWopiCallback(ctx, userAuthStr, opt_url) {
|
||||
}
|
||||
}
|
||||
}
|
||||
wopiParams = {commonInfo: commonInfo, userAuth: userAuth, LastModifiedTime: lastModifiedTime};
|
||||
wopiParams = {commonInfo, userAuth, LastModifiedTime: lastModifiedTime};
|
||||
ctx.logger.debug('parseWopiCallback wopiParams:%j', wopiParams);
|
||||
}
|
||||
return wopiParams;
|
||||
}
|
||||
function checkAndInvalidateCache(ctx, docId, fileInfo) {
|
||||
return co(function* () {
|
||||
let res = {success: true, lockId: undefined};
|
||||
let selectRes = yield taskResult.select(ctx, docId);
|
||||
const res = {success: true, lockId: undefined};
|
||||
const selectRes = yield taskResult.select(ctx, docId);
|
||||
if (selectRes.length > 0) {
|
||||
let row = selectRes[0];
|
||||
const row = selectRes[0];
|
||||
if (row.callback) {
|
||||
let commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback, 1);
|
||||
const commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback, 1);
|
||||
if (isWopiCallback(commonInfoStr)) {
|
||||
let commonInfo = JSON.parse(commonInfoStr);
|
||||
const commonInfo = JSON.parse(commonInfoStr);
|
||||
res.lockId = commonInfo.lockId;
|
||||
ctx.logger.debug('wopiEditor lockId from DB lockId=%s', res.lockId);
|
||||
let unlockMarkStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
||||
const unlockMarkStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
||||
ctx.logger.debug('wopiEditor commonInfoStr=%s', commonInfoStr);
|
||||
ctx.logger.debug('wopiEditor unlockMarkStr=%s', unlockMarkStr);
|
||||
let hasUnlockMarker = isWopiUnlockMarker(unlockMarkStr);
|
||||
let isUpdateVersion = commonDefines.FileStatus.UpdateVersion === row.status;
|
||||
const hasUnlockMarker = isWopiUnlockMarker(unlockMarkStr);
|
||||
const isUpdateVersion = commonDefines.FileStatus.UpdateVersion === row.status;
|
||||
ctx.logger.debug('wopiEditor hasUnlockMarker=%s isUpdateVersion=%s', hasUnlockMarker, isUpdateVersion);
|
||||
if (hasUnlockMarker || isUpdateVersion) {
|
||||
let fileInfoVersion = fileInfo.Version;
|
||||
let cacheVersion = commonInfo.fileInfo.Version;
|
||||
let fileInfoModified = fileInfo.LastModifiedTime;
|
||||
let cacheModified = commonInfo.fileInfo.LastModifiedTime;
|
||||
const fileInfoVersion = fileInfo.Version;
|
||||
const cacheVersion = commonInfo.fileInfo.Version;
|
||||
const fileInfoModified = fileInfo.LastModifiedTime;
|
||||
const cacheModified = commonInfo.fileInfo.LastModifiedTime;
|
||||
ctx.logger.debug('wopiEditor version fileInfo=%s; cache=%s', fileInfoVersion, cacheVersion);
|
||||
ctx.logger.debug('wopiEditor LastModifiedTime fileInfo=%s; cache=%s', fileInfoModified, cacheModified);
|
||||
if (fileInfoVersion !== cacheVersion || fileInfoModified !== cacheModified) {
|
||||
var mask = new taskResult.TaskResultData();
|
||||
const mask = new taskResult.TaskResultData();
|
||||
mask.tenant = ctx.tenant;
|
||||
mask.key = docId;
|
||||
mask.last_open_date = row.last_open_date;
|
||||
//cleanupRes can be false in case of simultaneous opening. it is OK
|
||||
let cleanupRes = yield canvasService.cleanupCacheIf(ctx, mask);
|
||||
const cleanupRes = yield canvasService.cleanupCacheIf(ctx, mask);
|
||||
ctx.logger.debug('wopiEditor cleanupRes=%s', cleanupRes);
|
||||
res.lockId = undefined;
|
||||
}
|
||||
@ -513,11 +513,11 @@ async function checkAndReplaceEmptyFile(ctx, fileInfo, wopiSrc, access_token, ac
|
||||
|
||||
const templateFileInfo = templateFilesSizeCache[filePath];
|
||||
const templateFileStream = createReadStream(filePath);
|
||||
let postRes = await putFile(ctx, wopiParams, undefined, templateFileStream, templateFileInfo.size, fileInfo.UserId, false, false, false);
|
||||
const postRes = await putFile(ctx, wopiParams, undefined, templateFileStream, templateFileInfo.size, fileInfo.UserId, false, false, false);
|
||||
if (postRes) {
|
||||
//update Size
|
||||
fileInfo.Size = templateFileInfo.size;
|
||||
let body = parsePutFileResponse(ctx, postRes);
|
||||
const body = parsePutFileResponse(ctx, postRes);
|
||||
//collabora nexcloud connector
|
||||
if (body?.LastModifiedTime) {
|
||||
//update LastModifiedTime
|
||||
@ -527,7 +527,7 @@ async function checkAndReplaceEmptyFile(ctx, fileInfo, wopiSrc, access_token, ac
|
||||
}
|
||||
}
|
||||
function createDocId(ctx, wopiSrc, mode, fileInfo) {
|
||||
let fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
const fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
let docId = undefined;
|
||||
if ('view' !== mode) {
|
||||
docId = `${fileId}`;
|
||||
@ -550,12 +550,12 @@ async function preOpen(ctx, lockId, docId, fileInfo, userAuth, baseUrl, fileType
|
||||
if (undefined === lockId) {
|
||||
//Use deterministic(not random) lockId to fix issues with forgotten openings due to integrator failures
|
||||
lockId = docId;
|
||||
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
||||
const commonInfo = JSON.stringify({lockId, fileInfo});
|
||||
await canvasService.commandOpenStartPromise(ctx, docId, baseUrl, commonInfo, fileType);
|
||||
}
|
||||
//Lock
|
||||
if ('view' !== userAuth.mode) {
|
||||
let lockRes = await lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
||||
const lockRes = await lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
||||
return !!lockRes;
|
||||
}
|
||||
return true;
|
||||
@ -599,7 +599,7 @@ async function prepareDocumentForEditing(ctx, wopiSrc, fileInfo, userAuth, fileT
|
||||
|
||||
function getEditorHtml(req, res) {
|
||||
return co(function* () {
|
||||
let params = {
|
||||
const params = {
|
||||
key: undefined,
|
||||
apiQuery: '',
|
||||
fileInfo: {},
|
||||
@ -609,7 +609,7 @@ function getEditorHtml(req, res) {
|
||||
documentType: undefined,
|
||||
docs_api_config: {}
|
||||
};
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
@ -617,10 +617,10 @@ function getEditorHtml(req, res) {
|
||||
const tenTokenOutboxExpires = ctx.getCfg('services.CoAuthoring.token.outbox.expires', cfgTokenOutboxExpires);
|
||||
const tenWopiFileInfoBlockList = ctx.getCfg('wopi.fileInfoBlockList', cfgWopiFileInfoBlockList);
|
||||
|
||||
let wopiSrc = req.query['wopisrc'];
|
||||
let fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
const wopiSrc = req.query['wopisrc'];
|
||||
const fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
ctx.setDocId(fileId);
|
||||
let usid = req.query['usid'] || crypto.randomUUID();
|
||||
const usid = req.query['usid'] || crypto.randomUUID();
|
||||
ctx.setUserSessionId(usid);
|
||||
|
||||
ctx.logger.info('wopiEditor start');
|
||||
@ -630,26 +630,26 @@ function getEditorHtml(req, res) {
|
||||
params.apiQuery = `?${constants.SHARD_KEY_WOPI_NAME}=${encodeURIComponent(wopiSrc)}`;
|
||||
params.documentType = req.params.documentType;
|
||||
let mode = req.params.mode;
|
||||
let sc = req.query['sc'];
|
||||
let lang = req.query['lang'];
|
||||
let ui = req.query['ui'];
|
||||
let access_token = req.body['access_token'] || '';
|
||||
let access_token_ttl = parseInt(req.body['access_token_ttl']) || 0;
|
||||
let docs_api_config = req.body['docs_api_config'];
|
||||
const sc = req.query['sc'];
|
||||
const lang = req.query['lang'];
|
||||
const ui = req.query['ui'];
|
||||
const access_token = req.body['access_token'] || '';
|
||||
const access_token_ttl = parseInt(req.body['access_token_ttl']) || 0;
|
||||
const docs_api_config = req.body['docs_api_config'];
|
||||
if (docs_api_config) {
|
||||
params.docs_api_config = JSON.parse(docs_api_config);
|
||||
}
|
||||
// Create user authentication object
|
||||
const userAuth = (params.userAuth = {
|
||||
wopiSrc: wopiSrc,
|
||||
access_token: access_token,
|
||||
access_token_ttl: access_token_ttl,
|
||||
wopiSrc,
|
||||
access_token,
|
||||
access_token_ttl,
|
||||
userSessionId: usid,
|
||||
mode: mode,
|
||||
mode,
|
||||
forcedViewMode: false
|
||||
});
|
||||
|
||||
let fileInfo = (params.fileInfo = yield checkFileInfo(ctx, wopiSrc, access_token, sc));
|
||||
const fileInfo = (params.fileInfo = yield checkFileInfo(ctx, wopiSrc, access_token, sc));
|
||||
if (!fileInfo) {
|
||||
params.fileInfo = {};
|
||||
return;
|
||||
@ -680,8 +680,8 @@ function getEditorHtml(req, res) {
|
||||
delete params.fileInfo[item];
|
||||
});
|
||||
|
||||
let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
const options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
const secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
params.token = jwt.sign(params, secret, options);
|
||||
} catch (err) {
|
||||
ctx.logger.error('wopiEditor error: %s', err.stack);
|
||||
@ -700,8 +700,8 @@ function getEditorHtml(req, res) {
|
||||
}
|
||||
function getConverterHtml(req, res) {
|
||||
return co(function* () {
|
||||
let params = {statusHandler: undefined};
|
||||
let ctx = new operationContext.Context();
|
||||
const params = {statusHandler: undefined};
|
||||
const ctx = new operationContext.Context();
|
||||
try {
|
||||
ctx.initFromRequest(req);
|
||||
yield ctx.initTenantCache();
|
||||
@ -709,15 +709,15 @@ function getConverterHtml(req, res) {
|
||||
const tenTokenOutboxExpires = ctx.getCfg('services.CoAuthoring.token.outbox.expires', cfgTokenOutboxExpires);
|
||||
const tenWopiHost = ctx.getCfg('wopi.host', cfgWopiHost);
|
||||
|
||||
let wopiSrc = req.query['wopisrc'];
|
||||
let fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
const wopiSrc = req.query['wopisrc'];
|
||||
const fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
ctx.setDocId(fileId);
|
||||
ctx.logger.info('convert-and-edit start');
|
||||
|
||||
let access_token = req.body['access_token'] || '';
|
||||
let access_token_ttl = parseInt(req.body['access_token_ttl']) || 0;
|
||||
let ext = req.params.ext;
|
||||
let targetext = req.params.targetext;
|
||||
const access_token = req.body['access_token'] || '';
|
||||
const access_token_ttl = parseInt(req.body['access_token_ttl']) || 0;
|
||||
const ext = req.params.ext;
|
||||
const targetext = req.params.targetext;
|
||||
|
||||
if (!(wopiSrc && access_token && access_token_ttl && ext && targetext)) {
|
||||
ctx.logger.debug(
|
||||
@ -731,24 +731,24 @@ function getConverterHtml(req, res) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fileInfo = yield checkFileInfo(ctx, wopiSrc, access_token);
|
||||
const fileInfo = yield checkFileInfo(ctx, wopiSrc, access_token);
|
||||
if (!fileInfo) {
|
||||
ctx.logger.info('convert-and-edit checkFileInfo error');
|
||||
return;
|
||||
}
|
||||
|
||||
let wopiParams = getWopiParams(undefined, fileInfo, wopiSrc, access_token, access_token_ttl);
|
||||
const wopiParams = getWopiParams(undefined, fileInfo, wopiSrc, access_token, access_token_ttl);
|
||||
|
||||
let docId = yield converterService.convertAndEdit(ctx, wopiParams, ext, targetext);
|
||||
const docId = yield converterService.convertAndEdit(ctx, wopiParams, ext, targetext);
|
||||
if (docId) {
|
||||
let baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
||||
const baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
||||
params.statusHandler = `${baseUrl}/hosting/wopi/convert-and-edit-handler`;
|
||||
params.statusHandler += `?${constants.SHARD_KEY_WOPI_NAME}=${encodeURIComponent(wopiSrc)}&access_token=${encodeURIComponent(access_token)}`;
|
||||
params.statusHandler += `&targetext=${encodeURIComponent(targetext)}&docId=${encodeURIComponent(docId)}`;
|
||||
let tokenData = {docId: docId};
|
||||
let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
let token = jwt.sign(tokenData, secret, options);
|
||||
const tokenData = {docId};
|
||||
const options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
const secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
const token = jwt.sign(tokenData, secret, options);
|
||||
|
||||
params.statusHandler += `&token=${encodeURIComponent(token)}`;
|
||||
}
|
||||
@ -776,10 +776,10 @@ function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId,
|
||||
if (!wopiParams.userAuth || !wopiParams.commonInfo) {
|
||||
return postRes;
|
||||
}
|
||||
let fileInfo = wopiParams.commonInfo.fileInfo;
|
||||
let userAuth = wopiParams.userAuth;
|
||||
let uri = `${userAuth.wopiSrc}/contents?access_token=${encodeURIComponent(userAuth.access_token)}`;
|
||||
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||
const fileInfo = wopiParams.commonInfo.fileInfo;
|
||||
const userAuth = wopiParams.userAuth;
|
||||
const uri = `${userAuth.wopiSrc}/contents?access_token=${encodeURIComponent(userAuth.access_token)}`;
|
||||
const filterStatus = yield checkIpFilter(ctx, uri);
|
||||
if (0 !== filterStatus) {
|
||||
return postRes;
|
||||
}
|
||||
@ -787,9 +787,9 @@ function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId,
|
||||
//collabora nexcloud connector sets only UserCanWrite=true
|
||||
const canEdit = fileInfo.UserCanOnlyComment || fileInfo.UserCanWrite || fileInfo.UserCanReview;
|
||||
if (fileInfo && (fileInfo.SupportsUpdate || canEdit)) {
|
||||
let commonInfo = wopiParams.commonInfo;
|
||||
const commonInfo = wopiParams.commonInfo;
|
||||
//todo add all the users who contributed changes to the document in this PutFile request to X-WOPI-Editors
|
||||
let headers = {'X-WOPI-Override': 'PUT', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-Editors': userLastChangeId};
|
||||
const headers = {'X-WOPI-Override': 'PUT', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-Editors': userLastChangeId};
|
||||
yield wopiUtils.fillStandardHeaders(ctx, headers, uri, userAuth.access_token);
|
||||
headers['X-LOOL-WOPI-IsModifiedByUser'] = isModifiedByUser;
|
||||
headers['X-LOOL-WOPI-IsAutosave'] = isAutosave;
|
||||
@ -802,7 +802,7 @@ function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId,
|
||||
|
||||
ctx.logger.debug('wopi PutFile request uri=%s headers=%j', uri, headers);
|
||||
//isInJwtToken is true because it passed checkIpFilter for wopi
|
||||
let isInJwtToken = true;
|
||||
const isInJwtToken = true;
|
||||
postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, isInJwtToken, headers);
|
||||
ctx.logger.debug('wopi PutFile response headers=%j', postRes.response.headers);
|
||||
ctx.logger.debug('wopi PutFile response body:%s', postRes.body);
|
||||
@ -824,13 +824,13 @@ function putRelativeFile(ctx, wopiSrc, access_token, data, dataStream, dataSize,
|
||||
ctx.logger.info('wopi putRelativeFile start');
|
||||
const tenCallbackRequestTimeout = ctx.getCfg('services.CoAuthoring.server.callbackRequestTimeout', cfgCallbackRequestTimeout);
|
||||
|
||||
let uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||
const uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
const filterStatus = yield checkIpFilter(ctx, uri);
|
||||
if (0 !== filterStatus) {
|
||||
return res;
|
||||
}
|
||||
|
||||
let headers = {'X-WOPI-Override': 'PUT_RELATIVE', 'X-WOPI-SuggestedTarget': utf7.encode(suggestedTarget || suggestedExt)};
|
||||
const headers = {'X-WOPI-Override': 'PUT_RELATIVE', 'X-WOPI-SuggestedTarget': utf7.encode(suggestedTarget || suggestedExt)};
|
||||
if (isFileConversion) {
|
||||
headers['X-WOPI-FileConversion'] = isFileConversion;
|
||||
}
|
||||
@ -839,8 +839,8 @@ function putRelativeFile(ctx, wopiSrc, access_token, data, dataStream, dataSize,
|
||||
|
||||
ctx.logger.debug('wopi putRelativeFile request uri=%s headers=%j', uri, headers);
|
||||
//isInJwtToken is true because it passed checkIpFilter for wopi
|
||||
let isInJwtToken = true;
|
||||
let postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, isInJwtToken, headers);
|
||||
const isInJwtToken = true;
|
||||
const postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, isInJwtToken, headers);
|
||||
ctx.logger.debug('wopi putRelativeFile response headers=%j', postRes.response.headers);
|
||||
ctx.logger.debug('wopi putRelativeFile response body:%s', postRes.body);
|
||||
res = JSON.parse(postRes.body);
|
||||
@ -920,7 +920,7 @@ async function refreshFile(ctx, wopiParams, baseUrl) {
|
||||
let res;
|
||||
try {
|
||||
ctx.logger.info('wopi RefreshFile start');
|
||||
let userAuth = wopiParams.userAuth;
|
||||
const userAuth = wopiParams.userAuth;
|
||||
if (!userAuth) {
|
||||
return;
|
||||
}
|
||||
@ -935,8 +935,8 @@ async function refreshFile(ctx, wopiParams, baseUrl) {
|
||||
if (!prepareResult) {
|
||||
return;
|
||||
}
|
||||
let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
let secret = await tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
const options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
const secret = await tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
res.token = jwt.sign(res, secret, options);
|
||||
} catch (err) {
|
||||
res = undefined;
|
||||
@ -953,20 +953,20 @@ function checkFileInfo(ctx, wopiSrc, access_token, opt_sc) {
|
||||
ctx.logger.info('wopi checkFileInfo start');
|
||||
const tenDownloadTimeout = ctx.getCfg('FileConverter.converter.downloadTimeout', cfgDownloadTimeout);
|
||||
|
||||
let uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||
const uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
const filterStatus = yield checkIpFilter(ctx, uri);
|
||||
if (0 !== filterStatus) {
|
||||
return fileInfo;
|
||||
}
|
||||
let headers = {};
|
||||
const headers = {};
|
||||
if (opt_sc) {
|
||||
headers['X-WOPI-SessionContext'] = opt_sc;
|
||||
}
|
||||
yield wopiUtils.fillStandardHeaders(ctx, headers, uri, access_token);
|
||||
ctx.logger.debug('wopi checkFileInfo request uri=%s headers=%j', uri, headers);
|
||||
//isInJwtToken is true because it passed checkIpFilter for wopi
|
||||
let isInJwtToken = true;
|
||||
let getRes = yield utils.downloadUrlPromise(ctx, uri, tenDownloadTimeout, undefined, undefined, isInJwtToken, headers);
|
||||
const isInJwtToken = true;
|
||||
const getRes = yield utils.downloadUrlPromise(ctx, uri, tenDownloadTimeout, undefined, undefined, isInJwtToken, headers);
|
||||
ctx.logger.debug(`wopi checkFileInfo headers=%j body=%s`, getRes.response.headers, getRes.body);
|
||||
fileInfo = JSON.parse(getRes.body);
|
||||
} catch (err) {
|
||||
@ -988,20 +988,20 @@ function lock(ctx, command, lockId, fileInfo, userAuth) {
|
||||
if (!userAuth) {
|
||||
return false;
|
||||
}
|
||||
let wopiSrc = userAuth.wopiSrc;
|
||||
let access_token = userAuth.access_token;
|
||||
let uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||
const wopiSrc = userAuth.wopiSrc;
|
||||
const access_token = userAuth.access_token;
|
||||
const uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
const filterStatus = yield checkIpFilter(ctx, uri);
|
||||
if (0 !== filterStatus) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let headers = {'X-WOPI-Override': command, 'X-WOPI-Lock': lockId};
|
||||
const headers = {'X-WOPI-Override': command, 'X-WOPI-Lock': lockId};
|
||||
yield wopiUtils.fillStandardHeaders(ctx, headers, uri, access_token);
|
||||
ctx.logger.debug('wopi %s request uri=%s headers=%j', command, uri, headers);
|
||||
//isInJwtToken is true because it passed checkIpFilter for wopi
|
||||
let isInJwtToken = true;
|
||||
let postRes = yield utils.postRequestPromise(
|
||||
const isInJwtToken = true;
|
||||
const postRes = yield utils.postRequestPromise(
|
||||
ctx,
|
||||
uri,
|
||||
undefined,
|
||||
@ -1034,23 +1034,23 @@ async function unlock(ctx, wopiParams) {
|
||||
if (!wopiParams.userAuth || !wopiParams.commonInfo) {
|
||||
return;
|
||||
}
|
||||
let fileInfo = wopiParams.commonInfo.fileInfo;
|
||||
const fileInfo = wopiParams.commonInfo.fileInfo;
|
||||
if (fileInfo && fileInfo.SupportsLocks) {
|
||||
let wopiSrc = wopiParams.userAuth.wopiSrc;
|
||||
let lockId = wopiParams.commonInfo.lockId;
|
||||
let access_token = wopiParams.userAuth.access_token;
|
||||
let uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
let filterStatus = await checkIpFilter(ctx, uri);
|
||||
const wopiSrc = wopiParams.userAuth.wopiSrc;
|
||||
const lockId = wopiParams.commonInfo.lockId;
|
||||
const access_token = wopiParams.userAuth.access_token;
|
||||
const uri = `${wopiSrc}?access_token=${encodeURIComponent(access_token)}`;
|
||||
const filterStatus = await checkIpFilter(ctx, uri);
|
||||
if (0 !== filterStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
let headers = {'X-WOPI-Override': 'UNLOCK', 'X-WOPI-Lock': lockId};
|
||||
const headers = {'X-WOPI-Override': 'UNLOCK', 'X-WOPI-Lock': lockId};
|
||||
await wopiUtils.fillStandardHeaders(ctx, headers, uri, access_token);
|
||||
ctx.logger.debug('wopi Unlock request uri=%s headers=%j', uri, headers);
|
||||
//isInJwtToken is true because it passed checkIpFilter for wopi
|
||||
let isInJwtToken = true;
|
||||
let postRes = await utils.postRequestPromise(
|
||||
const isInJwtToken = true;
|
||||
const postRes = await utils.postRequestPromise(
|
||||
ctx,
|
||||
uri,
|
||||
undefined,
|
||||
@ -1088,8 +1088,8 @@ function numberToBase64(val) {
|
||||
|
||||
function checkIpFilter(ctx, uri) {
|
||||
return co(function* () {
|
||||
let urlParsed = new URL(uri);
|
||||
let filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname);
|
||||
const urlParsed = new URL(uri);
|
||||
const filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname);
|
||||
if (0 !== filterStatus) {
|
||||
ctx.logger.warn('wopi checkIpFilter error: url = %s', uri);
|
||||
}
|
||||
@ -1097,15 +1097,15 @@ function checkIpFilter(ctx, uri) {
|
||||
});
|
||||
}
|
||||
function getWopiParams(lockId, fileInfo, wopiSrc, access_token, access_token_ttl) {
|
||||
let commonInfo = {lockId: lockId, fileInfo: fileInfo};
|
||||
let userAuth = {
|
||||
wopiSrc: wopiSrc,
|
||||
access_token: access_token,
|
||||
access_token_ttl: access_token_ttl,
|
||||
const commonInfo = {lockId, fileInfo};
|
||||
const userAuth = {
|
||||
wopiSrc,
|
||||
access_token,
|
||||
access_token_ttl,
|
||||
userSessionId: null,
|
||||
mode: null
|
||||
};
|
||||
return {commonInfo: commonInfo, userAuth: userAuth, LastModifiedTime: null};
|
||||
return {commonInfo, userAuth, LastModifiedTime: null};
|
||||
}
|
||||
|
||||
async function dummyCheckFileInfo(req, res) {
|
||||
@ -1125,14 +1125,14 @@ async function dummyCheckFileInfo(req, res) {
|
||||
});
|
||||
} else {
|
||||
let fileInfo;
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
ctx.initFromRequest(req);
|
||||
try {
|
||||
await ctx.initTenantCache();
|
||||
const tenWopiDummySampleFilePath = ctx.getCfg('wopi.dummy.sampleFilePath', cfgWopiDummySampleFilePath);
|
||||
let access_token = req.query['access_token'];
|
||||
const access_token = req.query['access_token'];
|
||||
ctx.logger.debug('dummyCheckFileInfo access_token:%s', access_token);
|
||||
let sampleFileStat = await stat(tenWopiDummySampleFilePath);
|
||||
const sampleFileStat = await stat(tenWopiDummySampleFilePath);
|
||||
|
||||
fileInfo = JSON.parse(Buffer.from(access_token, 'base64').toString('ascii'));
|
||||
fileInfo.BaseFileName = path.basename(tenWopiDummySampleFilePath);
|
||||
@ -1150,13 +1150,13 @@ async function dummyCheckFileInfo(req, res) {
|
||||
}
|
||||
|
||||
async function dummyGetFile(req, res) {
|
||||
let ctx = new operationContext.Context();
|
||||
const ctx = new operationContext.Context();
|
||||
ctx.initFromRequest(req);
|
||||
try {
|
||||
await ctx.initTenantCache();
|
||||
|
||||
const tenWopiDummySampleFilePath = ctx.getCfg('wopi.dummy.sampleFilePath', cfgWopiDummySampleFilePath);
|
||||
let sampleFileStat = await stat(tenWopiDummySampleFilePath);
|
||||
const sampleFileStat = await stat(tenWopiDummySampleFilePath);
|
||||
res.setHeader('Content-Length', sampleFileStat.size);
|
||||
res.setHeader('Content-Type', mime.getType(tenWopiDummySampleFilePath));
|
||||
|
||||
|
||||
@ -584,17 +584,17 @@ function* processDownloadFromStorage(ctx, dataConvert, cmd, task, tempDirs, auth
|
||||
function* concatFiles(source, template) {
|
||||
template = template || 'Editor';
|
||||
//concatenate EditorN.ext parts in Editor.ext
|
||||
let list = yield utils.listObjects(source, true);
|
||||
const list = yield utils.listObjects(source, true);
|
||||
list.sort(utils.compareStringByLength);
|
||||
const createdTargets = new Set();
|
||||
for (let i = 0; i < list.length; ++i) {
|
||||
let file = list[i];
|
||||
const file = list[i];
|
||||
if (file.match(new RegExp(`${template}\\d+\\.`))) {
|
||||
let target = file.replace(new RegExp(`(${template})\\d+(\\..*)`), '$1$2');
|
||||
const target = file.replace(new RegExp(`(${template})\\d+(\\..*)`), '$1$2');
|
||||
const isFirst = !createdTargets.has(target);
|
||||
const writeOpts = isFirst ? undefined : {flags: 'a'};
|
||||
let writeStream = yield utils.promiseCreateWriteStream(target, writeOpts);
|
||||
let readStream = yield utils.promiseCreateReadStream(file);
|
||||
const writeStream = yield utils.promiseCreateWriteStream(target, writeOpts);
|
||||
const readStream = yield utils.promiseCreateReadStream(file);
|
||||
// Use raw pipeline for file-to-file operations to surface real errors
|
||||
yield pipeline(readStream, writeStream);
|
||||
if (isFirst) {
|
||||
|
||||
Reference in New Issue
Block a user