@@ -38,13 +38,16 @@ const {URL} = require('url');
38
38
const co = require ( 'co' ) ;
39
39
const jwt = require ( 'jsonwebtoken' ) ;
40
40
const config = require ( 'config' ) ;
41
+ const { createReadStream } = require ( 'fs' ) ;
42
+ const { lstat, readdir } = require ( 'fs/promises' ) ;
41
43
const utf7 = require ( 'utf7' ) ;
42
44
const mimeDB = require ( 'mime-db' ) ;
43
45
const xmlbuilder2 = require ( 'xmlbuilder2' ) ;
44
46
const logger = require ( './../../Common/sources/logger' ) ;
45
47
const utils = require ( './../../Common/sources/utils' ) ;
46
48
const constants = require ( './../../Common/sources/constants' ) ;
47
49
const commonDefines = require ( './../../Common/sources/commondefines' ) ;
50
+ const formatChecker = require ( './../../Common/sources/formatchecker' ) ;
48
51
const operationContext = require ( './../../Common/sources/operationContext' ) ;
49
52
const tenantManager = require ( './../../Common/sources/tenantManager' ) ;
50
53
const sqlBase = require ( './databaseConnectors/baseConnector' ) ;
@@ -57,6 +60,7 @@ const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expi
57
60
const cfgTokenEnableBrowser = config . get ( 'services.CoAuthoring.token.enable.browser' ) ;
58
61
const cfgCallbackRequestTimeout = config . get ( 'services.CoAuthoring.server.callbackRequestTimeout' ) ;
59
62
const cfgAllowPrivateIPAddressForSignedRequests = config . get ( 'services.CoAuthoring.server.allowPrivateIPAddressForSignedRequests' ) ;
63
+ const cfgNewFileTemplate = config . get ( 'services.CoAuthoring.server.newFileTemplate' ) ;
60
64
const cfgDownloadTimeout = config . get ( 'FileConverter.converter.downloadTimeout' ) ;
61
65
const cfgWopiFileInfoBlockList = config . get ( 'wopi.fileInfoBlockList' ) ;
62
66
const cfgWopiWopiZone = config . get ( 'wopi.wopiZone' ) ;
@@ -80,6 +84,9 @@ const cfgWopiExponentOld = config.get('wopi.exponentOld');
80
84
const cfgWopiPrivateKeyOld = config . get ( 'wopi.privateKeyOld' ) ;
81
85
const cfgWopiHost = config . get ( 'wopi.host' ) ;
82
86
87
+ let templatesFolderLocalesCache = null ;
88
+ const templateFilesSizeCache = { } ;
89
+
83
90
let mimeTypesByExt = ( function ( ) {
84
91
let mimeTypesByExt = { } ;
85
92
for ( let mimeType in mimeDB ) {
@@ -169,13 +176,12 @@ function discovery(req, res) {
169
176
xmlApp . ele ( 'action' , { name : 'view' , ext : ext . edit [ j ] , urlsrc : urlTemplateView } ) . up ( ) ;
170
177
xmlApp . ele ( 'action' , { name : 'embedview' , ext : ext . edit [ j ] , urlsrc : urlTemplateEmbedView } ) . up ( ) ;
171
178
xmlApp . ele ( 'action' , { name : 'mobileView' , ext : ext . edit [ j ] , urlsrc : urlTemplateMobileView } ) . up ( ) ;
172
- if ( "oform" !== ext . edit [ j ] ) {
173
- //todo config
174
- xmlApp . ele ( 'action' , { name : 'editnew' , ext : ext . edit [ j ] , requires : 'locks,update' , urlsrc : urlTemplateEdit } ) . up ( ) ;
175
- }
176
179
xmlApp . ele ( 'action' , { name : 'edit' , ext : ext . edit [ j ] , default : 'true' , requires : 'locks,update' , urlsrc : urlTemplateEdit } ) . up ( ) ;
177
180
xmlApp . ele ( 'action' , { name : 'mobileEdit' , ext : ext . edit [ j ] , requires : 'locks,update' , urlsrc : urlTemplateMobileEdit } ) . up ( ) ;
178
181
}
182
+ constants . SUPPORTED_TEMPLATES_EXTENSIONS [ name ] . forEach (
183
+ extension => xmlApp . ele ( 'action' , { name : 'editnew' , ext : extension , requires : 'locks,update' , urlsrc : urlTemplateEdit } ) . up ( )
184
+ ) ;
179
185
xmlApp . up ( ) ;
180
186
}
181
187
//end section for MS WOPI connectors
@@ -373,6 +379,7 @@ function getEditorHtml(req, res) {
373
379
try {
374
380
ctx . initFromRequest ( req ) ;
375
381
yield ctx . initTenantCache ( ) ;
382
+ const tenNewFileTemplate = ctx . getCfg ( 'services.CoAuthoring.server.newFileTemplate' , cfgNewFileTemplate ) ;
376
383
const tenTokenEnableBrowser = ctx . getCfg ( 'services.CoAuthoring.token.enable.browser' , cfgTokenEnableBrowser ) ;
377
384
const tenTokenOutboxAlgorithm = ctx . getCfg ( 'services.CoAuthoring.token.outbox.algorithm' , cfgTokenOutboxAlgorithm ) ;
378
385
const tenTokenOutboxExpires = ctx . getCfg ( 'services.CoAuthoring.token.outbox.expires' , cfgTokenOutboxExpires ) ;
@@ -390,6 +397,8 @@ function getEditorHtml(req, res) {
390
397
let mode = req . params . mode ;
391
398
let sc = req . query [ 'sc' ] ;
392
399
let hostSessionId = req . query [ 'hid' ] ;
400
+ let lang = req . query [ 'lang' ] ;
401
+ let ui = req . query [ 'ui' ] ;
393
402
let access_token = req . body [ 'access_token' ] || "" ;
394
403
let access_token_ttl = parseInt ( req . body [ 'access_token_ttl' ] ) || 0 ;
395
404
@@ -433,13 +442,38 @@ function getEditorHtml(req, res) {
433
442
return ;
434
443
}
435
444
//save common info
445
+ const fileType = getFileTypeByInfo ( fileInfo ) ;
436
446
if ( undefined === lockId ) {
437
- let fileType = getFileTypeByInfo ( fileInfo ) ;
438
447
lockId = crypto . randomBytes ( 16 ) . toString ( 'base64' ) ;
439
448
let commonInfo = JSON . stringify ( { lockId : lockId , fileInfo : fileInfo } ) ;
440
449
yield canvasService . commandOpenStartPromise ( ctx , docId , utils . getBaseUrlByRequest ( ctx , req ) , commonInfo , fileType ) ;
441
450
}
442
451
452
+ // TODO: throw error if format not supported?
453
+ if ( fileInfo . Size === 0 && fileType . length !== 0 ) {
454
+ const wopiParams = getWopiParams ( undefined , fileInfo , wopiSrc , access_token , access_token_ttl ) ;
455
+
456
+ if ( templatesFolderLocalesCache === null ) {
457
+ const dirContent = yield readdir ( `${ tenNewFileTemplate } /` , { withFileTypes : true } ) ;
458
+ templatesFolderLocalesCache = dirContent . filter ( dirObject => dirObject . isDirectory ( ) ) . map ( dirObject => dirObject . name ) ;
459
+ }
460
+
461
+ const localePrefix = lang || ui || 'en' ;
462
+ let locale = constants . TEMPLATES_FOLDER_LOCALE_COLLISON_MAP [ localePrefix ] ?? templatesFolderLocalesCache . find ( locale => locale . startsWith ( localePrefix ) ) ;
463
+ if ( locale === undefined ) {
464
+ locale = 'en-US' ;
465
+ }
466
+
467
+ const filePath = `${ tenNewFileTemplate } /${ locale } /new.${ fileType } ` ;
468
+ if ( ! templateFilesSizeCache [ filePath ] ) {
469
+ templateFilesSizeCache [ filePath ] = yield lstat ( filePath ) ;
470
+ }
471
+
472
+ const templateFileInfo = templateFilesSizeCache [ filePath ] ;
473
+ const templateFileStream = createReadStream ( filePath ) ;
474
+ yield putFile ( ctx , wopiParams , undefined , templateFileStream , templateFileInfo . size , fileInfo . UserId , false , false , false ) ;
475
+ }
476
+
443
477
//Lock
444
478
if ( 'view' !== mode ) {
445
479
let lockRes = yield lock ( ctx , 'LOCK' , lockId , fileInfo , userAuth ) ;
@@ -506,7 +540,7 @@ function getConverterHtml(req, res) {
506
540
return ;
507
541
}
508
542
509
- let wopiParams = getWopiParams ( null , fileInfo , wopiSrc , access_token , access_token_ttl ) ;
543
+ let wopiParams = getWopiParams ( undefined , fileInfo , wopiSrc , access_token , access_token_ttl ) ;
510
544
511
545
let docId = yield converterService . convertAndEdit ( ctx , wopiParams , ext , targetext ) ;
512
546
if ( docId ) {
0 commit comments