diff --git a/Common/config/default.json b/Common/config/default.json index d1416644..f7db7369 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -100,7 +100,11 @@ "modulusOld": "qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==", "exponentOld": "AQAB", "privateKeyOld": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj", - "refreshLockInterval": "10m" + "refreshLockInterval": "10m", + "dummy" : { + "enable": true, + "sampleFilePath": "" + } }, "tenants": { "baseDir": "", diff --git a/Common/sources/storage-s3.js b/Common/sources/storage-s3.js index 71d15510..32aaede0 100644 --- a/Common/sources/storage-s3.js +++ b/Common/sources/storage-s3.js @@ -74,8 +74,8 @@ let configS3 = { }; if (configS3.endpoint) { - configS3.sslEnabled = cfgSslEnabled; - configS3.s3ForcePathStyle = cfgS3ForcePathStyle; + configS3.tls = cfgSslEnabled; + configS3.forcePathStyle = cfgS3ForcePathStyle; } const client = new S3Client(configS3); diff --git a/DocService/npm-shrinkwrap.json b/DocService/npm-shrinkwrap.json index 91fd5adf..d384c95c 100644 --- a/DocService/npm-shrinkwrap.json +++ b/DocService/npm-shrinkwrap.json @@ -2657,9 +2657,9 @@ } }, "oracledb": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/oracledb/-/oracledb-6.0.1.tgz", - "integrity": "sha512-N5/Y4IkCFQCumqjEXi3snrclDKjDMMeawq/z/5Ydm5+BxjV3kg9wCaTAp++JTLlCWASb4JMXqK70PctmAkZh3g==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/oracledb/-/oracledb-6.3.0.tgz", + "integrity": "sha512-fr3U66QxgGXb5cs/ozLBQU50TMbZcBQEWvSaj2rJAXG8KRrsZcGOK8JTlZL1yJHeW8cSjOm6n/wTw3SJksGjDg==" }, "packet-reader": { "version": "1.0.0", diff --git a/DocService/package.json b/DocService/package.json index c8342474..5dc7d96a 100644 --- a/DocService/package.json +++ b/DocService/package.json @@ -36,7 +36,7 @@ "multi-integer-range": "4.0.7", "multiparty": "4.2.1", "mysql2": "2.3.3", - "oracledb": "6.0.1", + "oracledb": "6.3.0", "pg": "8.11.3", "redis": "4.6.11", "retry": "0.12.0", diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index e6f66361..5541656a 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -1396,7 +1396,7 @@ function getRequestParams(ctx, req, opt_isNotInBody) { const tenTokenEnableRequestInbox = ctx.getCfg('services.CoAuthoring.token.enable.request.inbox', cfgTokenEnableRequestInbox); const tenTokenRequiredParams = ctx.getCfg('services.CoAuthoring.server.tokenRequiredParams', cfgTokenRequiredParams); - let res = {code: constants.NO_ERROR, isDecoded: false, params: undefined}; + let res = {code: constants.NO_ERROR, description: "", isDecoded: false, params: undefined}; if (req.body && Buffer.isBuffer(req.body) && req.body.length > 0 && !opt_isNotInBody) { res.params = JSON.parse(req.body.toString('utf8')); } else { @@ -1427,6 +1427,7 @@ function getRequestParams(ctx, req, opt_isNotInBody) { } else if (constants.JWT_EXPIRED_CODE == checkJwtRes.code) { res.code = constants.VKEY_KEY_EXPIRE; } + res.description = checkJwtRes.description; } } return res; diff --git a/DocService/sources/canvasservice.js b/DocService/sources/canvasservice.js index 37636738..69206e77 100644 --- a/DocService/sources/canvasservice.js +++ b/DocService/sources/canvasservice.js @@ -292,7 +292,7 @@ var getOutputData = co.wrap(function* (ctx, cmd, outputData, key, optConn, optAd } break; case commonDefines.FileStatus.None: - outputData.setStatus('none'); + //this status has no handler break; case commonDefines.FileStatus.WaitQueue: //task in the queue. response will be after convertion @@ -302,6 +302,7 @@ var getOutputData = co.wrap(function* (ctx, cmd, outputData, key, optConn, optAd outputData.setData(constants.UNKNOWN); break; } + return status; }); function* addRandomKeyTaskCmd(ctx, cmd) { var task = yield* taskResult.addRandomKeyTask(ctx, cmd.getDocId()); @@ -517,8 +518,8 @@ function* commandOpen(ctx, conn, cmd, outputData, opt_upsertRes, opt_bIsRestore) } } function* commandOpenFillOutput(ctx, conn, cmd, outputData, opt_bIsRestore) { - yield getOutputData(ctx, cmd, outputData, cmd.getDocId(), conn, undefined, opt_bIsRestore); - return 'none' === outputData.getStatus(); + let status = yield getOutputData(ctx, cmd, outputData, cmd.getDocId(), conn, undefined, opt_bIsRestore); + return commonDefines.FileStatus.None === status; } function* commandReopen(ctx, conn, cmd, outputData) { const tenOpenProtectedFile = ctx.getCfg('services.CoAuthoring.server.openProtectedFile', cfgOpenProtectedFile); @@ -1336,7 +1337,7 @@ exports.openDocument = function(ctx, conn, cmd, opt_upsertRes, opt_bIsRestore) { outputData.setData(constants.UNKNOWN); } finally { - if (outputData && outputData.getStatus()) { + if (outputData?.getStatus()) { ctx.logger.debug('Response command: %s', JSON.stringify(outputData)); docsCoServer.sendData(ctx, conn, new OutputDataWrap('documentOpen', outputData)); } @@ -1583,8 +1584,12 @@ exports.downloadFile = function(req, res) { } ctx.initFromRequest(req); yield ctx.initTenantCache(); - let url = decodeURI(req.get('x-url')); ctx.setDocId(req.params.docid); + //todo remove in 8.1. For compatibility + let url = req.get('x-url'); + if (url) { + url = decodeURI(url); + } ctx.logger.info('Start downloadFile'); const tenTokenEnableBrowser = ctx.getCfg('services.CoAuthoring.token.enable.browser', cfgTokenEnableBrowser); const tenDownloadMaxBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgDownloadMaxBytes); @@ -1593,32 +1598,35 @@ exports.downloadFile = function(req, res) { const tenAllowPrivateIPAddressForSignedRequests = ctx.getCfg('services.CoAuthoring.server.allowPrivateIPAddressForSignedRequests', cfgAllowPrivateIPAddressForSignedRequests); let authorization; - if (tenTokenEnableBrowser) { - let checkJwtRes = yield docsCoServer.checkJwtHeader(ctx, req, 'Authorization', 'Bearer ', commonDefines.c_oAscSecretType.Browser); - let errorDescription; - if (checkJwtRes.decoded) { - let decoded = checkJwtRes.decoded; - if (decoded.changesUrl) { - url = decoded.changesUrl; - } else if (decoded.document && -1 !== tenDownloadFileAllowExt.indexOf(decoded.document.fileType)) { - url = decoded.document.url; - } else if (decoded.url && -1 !== tenDownloadFileAllowExt.indexOf(decoded.fileType)) { + let errorDescription; + let authRes = yield docsCoServer.getRequestParams(ctx, req); + if (authRes.code === constants.NO_ERROR) { + let decoded = authRes.params; + if (decoded.changesUrl) { + url = decoded.changesUrl; + } else if (decoded.document && -1 !== tenDownloadFileAllowExt.indexOf(decoded.document.fileType)) { + url = decoded.document.url; + } else if (decoded.url && -1 !== tenDownloadFileAllowExt.indexOf(decoded.fileType)) { + url = decoded.url; + } else if (!tenTokenEnableBrowser) { + //todo token required + if (decoded.url) { url = decoded.url; - } else { - errorDescription = 'access deny'; } } else { - errorDescription = checkJwtRes.description; - } - if (errorDescription) { - ctx.logger.warn('Error downloadFile jwt: description = %s', errorDescription); - res.sendStatus(403); - return; - } - if (utils.canIncludeOutboxAuthorization(ctx, url)) { - let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Outbox); - authorization = utils.fillJwtForRequest(ctx, {url: url}, secret, false); + errorDescription = 'access deny'; } + } else { + errorDescription = authRes.description || 'need token'; + } + if (errorDescription) { + ctx.logger.warn('Error downloadFile jwt: description = %s', errorDescription); + res.sendStatus(403); + return; + } + if (utils.canIncludeOutboxAuthorization(ctx, url)) { + let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Outbox); + authorization = utils.fillJwtForRequest(ctx, {url: url}, secret, false); } let urlParsed = urlModule.parse(url); let filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname); diff --git a/DocService/sources/converterservice.js b/DocService/sources/converterservice.js index 6ee74f54..2dcbe0f6 100644 --- a/DocService/sources/converterservice.js +++ b/DocService/sources/converterservice.js @@ -275,6 +275,7 @@ function convertRequest(req, res, isJson) { cmd.setFormat(filetype); cmd.setDocId(docId); cmd.setOutputFormat(outputFormat); + let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat()); cmd.setCodepage(commonDefines.c_oAscEncodingsMap[params.codePage] || commonDefines.c_oAscCodePageUtf8); cmd.setDelimiter(parseIntParam(params.delimiter) || commonDefines.c_oAscCsvDelimiter.Comma); @@ -283,11 +284,18 @@ function convertRequest(req, res, isJson) { if (params.region && locale[params.region.toLowerCase()]) { cmd.setLCID(locale[params.region.toLowerCase()].id); } + let jsonParams = {}; if (params.documentLayout) { - cmd.setJsonParams(JSON.stringify({'documentLayout': params.documentLayout})); + jsonParams['documentLayout'] = params.documentLayout; } if (params.spreadsheetLayout) { - cmd.setJsonParams(JSON.stringify({'spreadsheetLayout': params.spreadsheetLayout})); + jsonParams['spreadsheetLayout'] = params.spreadsheetLayout; + } + if (params.watermark) { + jsonParams['watermark'] = params.watermark; + } + if (Object.keys(jsonParams).length > 0) { + cmd.setJsonParams(JSON.stringify(jsonParams)); } if (params.password) { if (params.password.length > constants.PASSWORD_MAX_LENGTH) { @@ -323,8 +331,8 @@ function convertRequest(req, res, isJson) { break; } cmd.setThumbnail(thumbnailData); - if (false == thumbnailData.getFirst()) { - cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_IMAGE); + if (false === thumbnailData.getFirst() && 0 !== (constants.AVS_OFFICESTUDIO_FILE_IMAGE & cmd.getOutputFormat())) { + outputExt = 'zip'; } } var documentRenderer = params.documentRenderer; @@ -350,7 +358,6 @@ function convertRequest(req, res, isJson) { } cmd.setTextParams(textParamsData); } - let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat()); if (params.title) { cmd.setTitle(path.basename(params.title, path.extname(params.title)) + '.' + outputExt); } diff --git a/DocService/sources/databaseConnectors/mssqlConnector.js b/DocService/sources/databaseConnectors/mssqlConnector.js index 63811803..af42a9f4 100644 --- a/DocService/sources/databaseConnectors/mssqlConnector.js +++ b/DocService/sources/databaseConnectors/mssqlConnector.js @@ -46,7 +46,7 @@ const connectionConfiguration = { user: configSql.get('dbUser'), password: configSql.get('dbPass'), server: configSql.get('dbHost'), - port: configSql.get('dbPort'), + port: parseInt(configSql.get('dbPort')), database: configSql.get('dbName'), pool: { max: configSql.get('connectionlimit'), diff --git a/DocService/sources/databaseConnectors/mysqlConnector.js b/DocService/sources/databaseConnectors/mysqlConnector.js index 3736309a..96535bd4 100644 --- a/DocService/sources/databaseConnectors/mysqlConnector.js +++ b/DocService/sources/databaseConnectors/mysqlConnector.js @@ -41,7 +41,7 @@ const cfgTableResult = config.get('services.CoAuthoring.sql.tableResult'); const pool = mysql.createPool({ host : configSql.get('dbHost'), - port : configSql.get('dbPort'), + port : parseInt(configSql.get('dbPort')), user : configSql.get('dbUser'), password : configSql.get('dbPass'), database : configSql.get('dbName'), diff --git a/DocService/sources/databaseConnectors/oracleConnector.js b/DocService/sources/databaseConnectors/oracleConnector.js index 9cd78ff0..eb9e8035 100644 --- a/DocService/sources/databaseConnectors/oracleConnector.js +++ b/DocService/sources/databaseConnectors/oracleConnector.js @@ -117,7 +117,16 @@ async function executeQuery(ctx, sqlCommand, values = [], noModifyRes = false, n throw error; } finally { - connection?.close(); + if (connection) { + try { + // Put the connection back in the pool + await connection.close(); + } catch (error) { + if (!noLog) { + ctx.logger.error(`connection.close() error while executing query: ${sqlCommand}\n${error.stack}`); + } + } + } } } diff --git a/DocService/sources/databaseConnectors/postgreConnector.js b/DocService/sources/databaseConnectors/postgreConnector.js index f92de249..2f844829 100644 --- a/DocService/sources/databaseConnectors/postgreConnector.js +++ b/DocService/sources/databaseConnectors/postgreConnector.js @@ -45,7 +45,7 @@ const cfgEditor = config.get('services.CoAuthoring.editor'); let connectionConfig = { host: configSql.get('dbHost'), - port: configSql.get('dbPort'), + port: parseInt(configSql.get('dbPort')), user: configSql.get('dbUser'), password: configSql.get('dbPass'), database: configSql.get('dbName'), diff --git a/DocService/sources/server.js b/DocService/sources/server.js index 6744a689..88098314 100644 --- a/DocService/sources/server.js +++ b/DocService/sources/server.js @@ -60,6 +60,7 @@ const tenantManager = require('./../../Common/sources/tenantManager'); const configStorage = config.get('storage'); const cfgWopiEnable = config.get('wopi.enable'); +const cfgWopiDummyEnable = config.get('wopi.dummy.enable'); const cfgHtmlTemplate = config.get('wopi.htmlTemplate'); const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser'); const cfgTokenEnableRequestInbox = config.get('services.CoAuthoring.token.enable.request.inbox'); @@ -249,6 +250,7 @@ docsCoServer.install(server, () => { app.post('/savefile/:docid', rawFileParser, canvasService.saveFile); app.get('/printfile/:docid/:filename', canvasService.printFile); app.get('/downloadfile/:docid', canvasService.downloadFile); + app.post('/downloadfile/:docid', rawFileParser, canvasService.downloadFile); app.get('/healthcheck', utils.checkClientIp, docsCoServer.healthCheck); app.get('/baseurl', (req, res) => { @@ -292,6 +294,24 @@ docsCoServer.install(server, () => { res.sendStatus(404); }); } + function checkWopiDummyEnable(req, res, next) { + //todo may be move code into wopiClient or wopiClient.discovery... + let ctx = new operationContext.Context(); + ctx.initFromRequest(req); + ctx.initTenantCache() + .then(() => { + const tenWopiEnable = ctx.getCfg('wopi.enable', cfgWopiEnable); + const tenWopiDummyEnable = ctx.getCfg('wopi.dummy.enable', cfgWopiDummyEnable); + if (tenWopiEnable && tenWopiDummyEnable) { + next(); + } else { + res.sendStatus(404); + } + }).catch((err) => { + ctx.logger.error('checkWopiDummyEnable error: %s', err.stack); + res.sendStatus(404); + }); + } //todo dest let fileForms = multer({limits: {fieldSize: cfgDownloadMaxBytes}}); app.get('/hosting/discovery', checkWopiEnable, utils.checkClientIp, wopiClient.discovery); @@ -301,8 +321,12 @@ docsCoServer.install(server, () => { app.post('/hosting/wopi/:documentType/:mode', checkWopiEnable, urleEcodedParser, forms.none(), utils.lowercaseQueryString, wopiClient.getEditorHtml); app.post('/hosting/wopi/convert-and-edit/:ext/:targetext', checkWopiEnable, urleEcodedParser, forms.none(), utils.lowercaseQueryString, wopiClient.getConverterHtml); app.get('/hosting/wopi/convert-and-edit-handler', checkWopiEnable, utils.lowercaseQueryString, converterService.getConverterHtmlHandler); + app.get('/wopi/files/:docid', apicache.middleware("5 minutes"), checkWopiDummyEnable, utils.lowercaseQueryString, wopiClient.dummyCheckFileInfo); + app.post('/wopi/files/:docid', checkWopiDummyEnable, wopiClient.dummyOk); + app.get('/wopi/files/:docid/contents', apicache.middleware("5 minutes"), checkWopiDummyEnable, wopiClient.dummyGetFile); + app.post('/wopi/files/:docid/contents', checkWopiDummyEnable, wopiClient.dummyOk); - app.post('/dummyCallback', utils.checkClientIp, rawFileParser, function(req, res){ + app.post('/dummyCallback', utils.checkClientIp, apicache.middleware("5 minutes"), rawFileParser, function(req, res){ let ctx = new operationContext.Context(); ctx.initFromRequest(req); //yield ctx.initTenantCache();//no need diff --git a/DocService/sources/wopiClient.js b/DocService/sources/wopiClient.js index 328d06f0..dde84f91 100644 --- a/DocService/sources/wopiClient.js +++ b/DocService/sources/wopiClient.js @@ -33,13 +33,14 @@ 'use strict'; const path = require('path'); +const { pipeline } = require('node:stream/promises'); const crypto = require('crypto'); const {URL} = require('url'); const co = require('co'); const jwt = require('jsonwebtoken'); const config = require('config'); const { createReadStream } = require('fs'); -const { lstat, readdir } = require('fs/promises'); +const { stat, lstat, readdir } = require('fs/promises'); const utf7 = require('utf7'); const mimeDB = require('mime-db'); const xmlbuilder2 = require('xmlbuilder2'); @@ -54,6 +55,7 @@ const sqlBase = require('./databaseConnectors/baseConnector'); const taskResult = require('./taskresult'); const canvasService = require('./canvasservice'); const converterService = require('./converterservice'); +const mime = require('mime'); const cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm'); const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires'); @@ -83,6 +85,7 @@ const cfgWopiModulusOld = config.get('wopi.modulusOld'); const cfgWopiExponentOld = config.get('wopi.exponentOld'); const cfgWopiPrivateKeyOld = config.get('wopi.privateKeyOld'); const cfgWopiHost = config.get('wopi.host'); +const cfgWopiDummySampleFilePath = config.get('wopi.dummy.sampleFilePath'); let templatesFolderLocalesCache = null; const templateFilesSizeCache = {}; @@ -862,7 +865,75 @@ function getWopiParams(lockId, fileInfo, wopiSrc, access_token, access_token_ttl hostSessionId: null, userSessionId: null, mode: null }; return {commonInfo: commonInfo, userAuth: userAuth, LastModifiedTime: null}; -}; +} + +async function dummyCheckFileInfo(req, res) { + if (true) { + //static output for performance reason + res.json({ + BaseFileName: "sample.docx", + OwnerId: "userId", + Size: 100,//no need to set actual size for test + UserId: "userId",//test ignores + UserFriendlyName: "user", + Version: 0, + UserCanWrite: true, + SupportsGetLock: true, + SupportsLocks: true, + SupportsUpdate: true, + }); + } else { + let fileInfo; + let 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']; + ctx.logger.debug('dummyCheckFileInfo access_token:%s', access_token); + let sampleFileStat = await stat(tenWopiDummySampleFilePath); + + fileInfo = JSON.parse(Buffer.from(access_token, 'base64').toString('ascii')); + fileInfo.BaseFileName = path.basename(tenWopiDummySampleFilePath); + fileInfo.Size = sampleFileStat.size; + } catch (err) { + ctx.logger.error('dummyCheckFileInfo error:%s', err.stack); + } finally { + if (fileInfo) { + res.json(fileInfo); + } else { + res.sendStatus(400) + } + } + } +} + +async function dummyGetFile(req, res) { + let ctx = new operationContext.Context(); + ctx.initFromRequest(req); + try { + await ctx.initTenantCache(); + + const tenWopiDummySampleFilePath = ctx.getCfg('wopi.dummy.sampleFilePath', cfgWopiDummySampleFilePath); + let sampleFileStat = await stat(tenWopiDummySampleFilePath); + res.setHeader('Content-Length', sampleFileStat.size); + res.setHeader('Content-Type', mime.getType(tenWopiDummySampleFilePath)); + + await pipeline( + createReadStream(tenWopiDummySampleFilePath), + res, + ); + } catch (err) { + ctx.logger.error('dummyGetFile error:%s', err.stack); + } finally { + if (!res.headersSent) { + res.sendStatus(400); + } + } +} +function dummyOk(req, res) { + res.sendStatus(200); +} exports.discovery = discovery; exports.collaboraCapabilities = collaboraCapabilities; @@ -880,3 +951,6 @@ exports.fillStandardHeaders = fillStandardHeaders; exports.getWopiUnlockMarker = getWopiUnlockMarker; exports.getWopiModifiedMarker = getWopiModifiedMarker; exports.getFileTypeByInfo = getFileTypeByInfo; +exports.dummyCheckFileInfo = dummyCheckFileInfo; +exports.dummyGetFile = dummyGetFile; +exports.dummyOk = dummyOk; diff --git a/FileConverter/sources/converter.js b/FileConverter/sources/converter.js index 95ac9542..dc21ee59 100644 --- a/FileConverter/sources/converter.js +++ b/FileConverter/sources/converter.js @@ -763,8 +763,11 @@ function* streamEnd(streamObj, text) { streamObj.writeStream.end(text, 'utf8'); yield utils.promiseWaitClose(streamObj.writeStream); } -function* processUploadToStorage(ctx, dir, storagePath, calcChecksum, opt_specialDirDst) { +function* processUploadToStorage(ctx, dir, storagePath, calcChecksum, opt_specialDirDst, opt_ignorPrefix) { var list = yield utils.listObjects(dir); + if (opt_ignorPrefix) { + list = list.filter((dir) => !dir.startsWith(opt_ignorPrefix)); + } if (list.length < MAX_OPEN_FILES) { yield* processUploadToStorageChunk(ctx, list, dir, storagePath, calcChecksum, opt_specialDirDst); } else { @@ -804,13 +807,11 @@ function* processUploadToStorageErrorFile(ctx, dataConvert, tempDirs, childRes, let outputPath = path.join(tempDirs.temp, 'console.txt'); fs.writeFileSync(outputPath, output, {encoding: 'utf8'}); - //remove result dir with temp dir inside(see m_sTempDir param) to reduce the amount of data transferred - //todo filter on upload - fs.rmSync(tempDirs.result, { recursive: true, force: true }); - + //ignore result dir with temp dir inside(see m_sTempDir param) to reduce the amount of data transferred + let ignorePrefix = path.normalize(tempDirs.result); let format = path.extname(dataConvert.fileFrom).substring(1) || "unknown"; - yield* processUploadToStorage(ctx, tempDirs.temp, format + '/' + dataConvert.key , false, tenErrorFiles); + yield* processUploadToStorage(ctx, tempDirs.temp, format + '/' + dataConvert.key , false, tenErrorFiles, ignorePrefix); ctx.logger.debug('processUploadToStorage error complete(id=%s)', dataConvert.key); } function writeProcessOutputToLog(ctx, childRes, isDebug) {