define([ '/api/config', '/bower_components/nthen/index.js', '/common/common-util.js', ], function (ApiConfig, nThen, Util) { var X2T = {}; var CURRENT_VERSION = X2T.CURRENT_VERSION = 'v4'; var debug = function (str) { if (localStorage.CryptPad_dev !== "1") { return; } console.debug(str); }; X2T.start = function () { var x2tReady = Util.mkEvent(true); var fetchFonts = function (x2t, obj, cb) { if (!obj.fonts) { return void cb(); } var path = ApiConfig.httpSafeOrigin + '/common/onlyoffice/'+CURRENT_VERSION+'/fonts/'; var ver = '?' + ApiConfig.requireConf.urlArgs; var fonts = obj.fonts; var files = obj.fonts_files; var suffixes = { indexR: '', indexB: '_Bold', indexBI: '_Bold_Italic', indexI: '_Italic', }; nThen(function (waitFor) { fonts.forEach(function (font) { // Check if the font is already loaded if (!font.NeedStyles) { return; } // Pick the variants we need (regular, bold, italic) ['indexR', 'indexB', 'indexI', 'indexBI'].forEach(function (k) { if (typeof(font[k]) !== "number" || font[k] === -1) { return; } // No matching file var file = files[font[k]]; var name = font.Name + suffixes[k] + '.ttf'; Util.fetch(path + file.Id + ver, waitFor(function (err, buffer) { if (buffer) { x2t.FS.writeFile('/working/fonts/' + name, buffer); } })); }); }); }).nThen(function () { cb(); }); }; var x2tInitialized = false; var x2tInit = function(x2t) { debug("x2t mount"); // x2t.FS.mount(x2t.MEMFS, {} , '/'); x2t.FS.mkdir('/working'); x2t.FS.mkdir('/working/media'); x2t.FS.mkdir('/working/fonts'); x2t.FS.mkdir('/working/themes'); x2tInitialized = true; x2tReady.fire(); debug("x2t mount done"); }; var getX2T = function (cb) { // Perform the x2t conversion require(['/common/onlyoffice/x2t/x2t.js'], function() { // FIXME why does this fail without an access-control-allow-origin header? var x2t = window.Module; x2t.run(); if (x2tInitialized) { debug("x2t runtime already initialized"); return void x2tReady.reg(function () { cb(x2t); }); } x2t.onRuntimeInitialized = function() { debug("x2t in runtime initialized"); // Init x2t js module x2tInit(x2t); x2tReady.reg(function () { cb(x2t); }); }; }); }; var getFormatId = function (ext) { // Sheets if (ext === 'xlsx') { return 257; } if (ext === 'xls') { return 258; } if (ext === 'ods') { return 259; } if (ext === 'csv') { return 260; } if (ext === 'pdf') { return 513; } // Docs if (ext === 'docx') { return 65; } if (ext === 'doc') { return 66; } if (ext === 'odt') { return 67; } if (ext === 'txt') { return 69; } if (ext === 'html') { return 70; } // Slides if (ext === 'pptx') { return 129; } if (ext === 'ppt') { return 130; } if (ext === 'odp') { return 131; } return; }; var getFromId = function (ext) { var id = getFormatId(ext); if (!id) { return ''; } return ''+id+''; }; var getToId = function (ext) { var id = getFormatId(ext); if (!id) { return ''; } return ''+id+''; }; var x2tConvertDataInternal = function(x2t, obj) { var data = obj.data; var fileName = obj.fileName; var outputFormat = obj.outputFormat; var images = obj.images; debug("Converting Data for " + fileName + " to " + outputFormat); // PDF var pdfData = ''; if (outputFormat === "pdf" && typeof(data) === "object" && data.bin && data.buffer) { // Add conversion rules pdfData = "false" + "/working/fonts/"; // writing file to mounted working disk (in memory) x2t.FS.writeFile('/working/' + fileName, data.bin); x2t.FS.writeFile('/working/pdf.bin', data.buffer); } else { // writing file to mounted working disk (in memory) x2t.FS.writeFile('/working/' + fileName, data); } // Adding images Object.keys(images || {}).forEach(function (_mediaFileName) { if (/\.bin$/.test(_mediaFileName)) { return; } var mediasSources = obj.mediasSources || {}; var mediasData = obj.mediasData || {}; var mediaData = mediasData[_mediaFileName]; var mediaFileName; if (mediaData) { // Theme image var path = _mediaFileName.split('/'); mediaFileName = path.pop(); var theme = path[path.indexOf('themes') + 1]; try { x2t.FS.mkdir('/working/themes/'+theme); x2t.FS.mkdir('/working/themes/'+theme+'/media'); } catch (e) { console.warn(e); } x2t.FS.writeFile('/working/themes/'+theme+'/media/' + mediaFileName, new Uint8Array(mediaData.content)); debug("Writing media data " + mediaFileName + " at /working/themes/"+theme+"/media/"); return; } // mediaData is undefined, check mediasSources mediaFileName = _mediaFileName.substring(6); var mediaSource = mediasSources[mediaFileName]; mediaData = mediaSource ? mediasData[mediaSource.src] : undefined; if (mediaData) { debug("Writing media data " + mediaFileName); debug("Data"); var fileData = mediaData.content; x2t.FS.writeFile('/working/media/' + mediaFileName, new Uint8Array(fileData)); } else { debug("Could not find media content for " + mediaFileName); } }); var inputFormat = fileName.split('.').pop(); var params = "" + "" + "/working/" + fileName + "" + "/working/themes" + "/working/" + fileName + "." + outputFormat + "" + pdfData + getFromId(inputFormat) + getToId(outputFormat) + "false" + ""; // writing params file to mounted working disk (in memory) x2t.FS.writeFile('/working/params.xml', params); try { // running conversion x2t.ccall("runX2T", ["number"], ["string"], ["/working/params.xml"]); } catch (e) { console.error(e); return ""; } // reading output file from working disk (in memory) var result; try { result = x2t.FS.readFile('/working/' + fileName + "." + outputFormat); } catch (e) { debug("Failed reading converted file"); return ""; } return result; }; var convert = function (obj, cb) { console.error(obj); getX2T(function (x2t) { // Fonts fetchFonts(x2t, obj, function () { var o = obj.outputFormat; if (o !== 'pdf') { // Add intermediary conversion to Microsoft Office format if needed // (bin to pdf is allowed) [ // Import from Open Document {source: '.ods', format: 'xlsx'}, {source: '.odt', format: 'docx'}, {source: '.odp', format: 'pptx'}, // Export to non Microsoft Office {source: '.bin', type: 'sheet', format: 'xlsx'}, {source: '.bin', type: 'doc', format: 'docx'}, {source: '.bin', type: 'presentation', format: 'pptx'}, ].forEach(function (_step) { if (obj.fileName.endsWith(_step.source) && obj.outputFormat !== _step.format && (!_step.type || _step.type === obj.type)) { obj.outputFormat = _step.format; obj.data = x2tConvertDataInternal(x2t, obj); obj.fileName += '.'+_step.format; } }); obj.outputFormat = o; } var data = x2tConvertDataInternal(x2t, obj); // Convert to bin -- Import // We need to extract the images var images; if (o === 'bin') { images = []; var files = x2t.FS.readdir("/working/media/"); files.forEach(function (file) { if (file !== "." && file !== "..") { var fileData = x2t.FS.readFile("/working/media/" + file, { encoding : "binary" }); images.push({ name: file, data: fileData }); } }); } cb({ data: data, images: images }); }); }); }; return { convert: convert }; }; return X2T; });