Fix SharedArrayBuffer cross-origin issues for X2T
parent
1e12b85b7c
commit
d547c90168
|
@ -20,6 +20,7 @@ define([
|
|||
'/common/onlyoffice/oodoc_base.js',
|
||||
'/common/onlyoffice/ooslide_base.js',
|
||||
'/common/outer/worker-channel.js',
|
||||
'/common/outer/x2t.js',
|
||||
|
||||
'/bower_components/file-saver/FileSaver.min.js',
|
||||
|
||||
|
@ -47,7 +48,8 @@ define([
|
|||
EmptyCell,
|
||||
EmptyDoc,
|
||||
EmptySlide,
|
||||
Channel)
|
||||
Channel,
|
||||
X2T)
|
||||
{
|
||||
var saveAs = window.saveAs;
|
||||
var Nacl = window.nacl;
|
||||
|
@ -60,7 +62,7 @@ define([
|
|||
var DISPLAY_RESTORE_BUTTON = false;
|
||||
var NEW_VERSION = 4;
|
||||
var PENDING_TIMEOUT = 30000;
|
||||
var CURRENT_VERSION = 'v4';
|
||||
var CURRENT_VERSION = X2T.CURRENT_VERSION;
|
||||
//var READONLY_REFRESH_TO = 15000;
|
||||
|
||||
var debug = function (x, type) {
|
||||
|
@ -1699,239 +1701,81 @@ define([
|
|||
makeChannel();
|
||||
};
|
||||
|
||||
var x2tReady = Util.mkEvent(true);
|
||||
var fetchFonts = function (x2t) {
|
||||
var path = '/common/onlyoffice/'+CURRENT_VERSION+'/fonts/';
|
||||
var x2tConvertData = function (data, fileName, format, cb) {
|
||||
var sframeChan = common.getSframeChannel();
|
||||
var e = getEditor();
|
||||
var fonts = e.FontLoader.fontInfos;
|
||||
var files = e.FontLoader.fontFiles;
|
||||
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, waitFor(function (err, buffer) {
|
||||
if (buffer) {
|
||||
x2t.FS.writeFile('/working/fonts/' + name, buffer);
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
||||
}).nThen(function () {
|
||||
x2tReady.fire();
|
||||
var files = e.FontLoader.fontFiles.map(function (f) {
|
||||
return { 'Id': f.Id, };
|
||||
});
|
||||
};
|
||||
|
||||
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');
|
||||
x2tInitialized = true;
|
||||
fetchFonts(x2t);
|
||||
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);
|
||||
});
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
sframeChan.query('Q_OO_CONVERT', {
|
||||
data: data,
|
||||
type: type,
|
||||
fileName: fileName,
|
||||
outputFormat: format,
|
||||
images: window.frames[0].AscCommon.g_oDocumentUrls.urls || {},
|
||||
fonts: fonts,
|
||||
fonts_files: files,
|
||||
mediasSources: getMediasSources(),
|
||||
mediasData: mediasData
|
||||
}, function (err, obj) {
|
||||
if (err || !obj || !obj.data) {
|
||||
UI.warn(Messages.error);
|
||||
cb();
|
||||
}
|
||||
|
||||
x2t.onRuntimeInitialized = function() {
|
||||
debug("x2t in runtime initialized");
|
||||
// Init x2t js module
|
||||
x2tInit(x2t);
|
||||
x2tReady.reg(function () {
|
||||
cb(x2t);
|
||||
});
|
||||
};
|
||||
cb(obj.data, obj.images);
|
||||
}, {
|
||||
raw: true
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Converting Data
|
||||
|
||||
This function converts a data in a specific format to the outputformat
|
||||
The filename extension needs to represent the input format
|
||||
Example: fileName=cryptpad.bin outputFormat=xlsx
|
||||
*/
|
||||
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; }
|
||||
return;
|
||||
};
|
||||
var getFromId = function (ext) {
|
||||
var id = getFormatId(ext);
|
||||
if (!id) { return ''; }
|
||||
return '<m_nFormatFrom>'+id+'</m_nFormatFrom>';
|
||||
};
|
||||
var getToId = function (ext) {
|
||||
var id = getFormatId(ext);
|
||||
if (!id) { return ''; }
|
||||
return '<m_nFormatTo>'+id+'</m_nFormatTo>';
|
||||
};
|
||||
var x2tConvertDataInternal = function(x2t, data, fileName, outputFormat) {
|
||||
debug("Converting Data for " + fileName + " to " + outputFormat);
|
||||
|
||||
// PDF
|
||||
var pdfData = '';
|
||||
if (outputFormat === "pdf" && typeof(data) === "object" && data.bin && data.buffer) {
|
||||
// Add conversion rules
|
||||
pdfData = "<m_bIsNoBase64>false</m_bIsNoBase64>" +
|
||||
"<m_sFontDir>/working/fonts/</m_sFontDir>";
|
||||
// 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(window.frames[0].AscCommon.g_oDocumentUrls.urls || {}).forEach(function (_mediaFileName) {
|
||||
var mediaFileName = _mediaFileName.substring(6);
|
||||
var mediasSources = getMediasSources();
|
||||
var mediaSource = mediasSources[mediaFileName];
|
||||
var 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||
+ "<TaskQueueDataConvert xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
|
||||
+ "<m_sFileFrom>/working/" + fileName + "</m_sFileFrom>"
|
||||
+ "<m_sFileTo>/working/" + fileName + "." + outputFormat + "</m_sFileTo>"
|
||||
+ pdfData
|
||||
+ getFromId(inputFormat)
|
||||
+ getToId(outputFormat)
|
||||
+ "<m_bIsNoBase64>false</m_bIsNoBase64>"
|
||||
+ "</TaskQueueDataConvert>";
|
||||
// writing params file to mounted working disk (in memory)
|
||||
x2t.FS.writeFile('/working/params.xml', params);
|
||||
// running conversion
|
||||
x2t.ccall("runX2T", ["number"], ["string"], ["/working/params.xml"]);
|
||||
// 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");
|
||||
UI.removeModals();
|
||||
UI.warn(Messages.error);
|
||||
return "";
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
APP.printPdf = function (obj, cb) {
|
||||
getX2T(function (x2t) {
|
||||
//var e = getEditor();
|
||||
//var d = e.asc_nativePrint(undefined, undefined, 0x100 + opts.printType).ImData;
|
||||
var bin = getContent();
|
||||
var xlsData = x2tConvertDataInternal(x2t, {
|
||||
buffer: obj.data,
|
||||
bin: bin
|
||||
}, 'output.bin', 'pdf');
|
||||
if (xlsData) {
|
||||
var md = common.getMetadataMgr().getMetadataLazy();
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
var title = md.title || md.defaultTitle || type;
|
||||
var blob = new Blob([xlsData], {type: "application/pdf"});
|
||||
//var url = URL.createObjectURL(blob, { type: "application/pdf" });
|
||||
saveAs(blob, title+'.pdf');
|
||||
//window.open(url);
|
||||
cb({
|
||||
"type":"save",
|
||||
"status":"ok",
|
||||
//"data":url + "?disposition=inline&ooname=output.pdf"
|
||||
});
|
||||
/*
|
||||
ooChannel.send({
|
||||
"type":"documentOpen",
|
||||
"data": {
|
||||
"type":"save",
|
||||
"status":"ok",
|
||||
"data":url + "?disposition=inline&ooname=output.pdf"
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
var bin = getContent();
|
||||
x2tConvertData({
|
||||
buffer: obj.data,
|
||||
bin: bin
|
||||
}, 'output.bin', 'pdf', function (xlsData) {
|
||||
if (!xlsData) { return; }
|
||||
var md = common.getMetadataMgr().getMetadataLazy();
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
var title = md.title || md.defaultTitle || type;
|
||||
var blob = new Blob([xlsData], {type: "application/pdf"});
|
||||
saveAs(blob, title+'.pdf');
|
||||
cb({
|
||||
"type":"save",
|
||||
"status":"ok",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var x2tSaveAndConvertDataInternal = function(x2t, data, filename, extension, finalFilename) {
|
||||
var x2tSaveAndConvertData = function(data, filename, extension, finalFilename) {
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
var xlsData;
|
||||
|
||||
// PDF
|
||||
if (type === "sheet" && extension === "pdf") {
|
||||
var e = getEditor();
|
||||
var d = e.asc_nativePrint(undefined, undefined, 0x101).ImData;
|
||||
xlsData = x2tConvertDataInternal(x2t, {
|
||||
x2tConvertData({
|
||||
buffer: d.data,
|
||||
bin: data
|
||||
}, filename, extension);
|
||||
if (xlsData) {
|
||||
var _blob = new Blob([xlsData], {type: "application/bin;charset=utf-8"});
|
||||
UI.removeModals();
|
||||
saveAs(_blob, finalFilename);
|
||||
}
|
||||
}, filename, extension, function (res) {
|
||||
if (res) {
|
||||
var _blob = new Blob([res], {type: "application/bin;charset=utf-8"});
|
||||
UI.removeModals();
|
||||
saveAs(_blob, finalFilename);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (type === "sheet" && extension !== 'xlsx') {
|
||||
xlsData = x2tConvertDataInternal(x2t, data, filename, 'xlsx');
|
||||
filename += '.xlsx';
|
||||
} else if (type === "presentation" && extension !== "pptx") {
|
||||
xlsData = x2tConvertDataInternal(x2t, data, filename, 'pptx');
|
||||
filename += '.pptx';
|
||||
} else if (type === "doc" && extension !== "docx") {
|
||||
xlsData = x2tConvertDataInternal(x2t, data, filename, 'docx');
|
||||
filename += '.docx';
|
||||
}
|
||||
xlsData = x2tConvertDataInternal(x2t, data, filename, extension);
|
||||
if (xlsData) {
|
||||
var blob = new Blob([xlsData], {type: "application/bin;charset=utf-8"});
|
||||
UI.removeModals();
|
||||
saveAs(blob, finalFilename);
|
||||
}
|
||||
};
|
||||
|
||||
var x2tSaveAndConvertData = function(data, filename, extension, finalName) {
|
||||
getX2T(function (x2t) {
|
||||
x2tSaveAndConvertDataInternal(x2t, data, filename, extension, finalName);
|
||||
x2tConvertData(data, filename, extension, function (xlsData) {
|
||||
if (xlsData) {
|
||||
var blob = new Blob([xlsData], {type: "application/bin;charset=utf-8"});
|
||||
UI.removeModals();
|
||||
saveAs(blob, finalFilename);
|
||||
return;
|
||||
}
|
||||
UI.warn(Messages.error);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2004,32 +1848,29 @@ define([
|
|||
$select.find('button').addClass('btn');
|
||||
};
|
||||
|
||||
var x2tImportImagesInternal = function(x2t, images, i, callback) {
|
||||
var x2tImportImagesInternal = function(images, i, callback) {
|
||||
if (i >= images.length) {
|
||||
callback();
|
||||
} else {
|
||||
debug("Import image " + i);
|
||||
var handleFileData = {
|
||||
name: images[i],
|
||||
name: images[i].name,
|
||||
mediasSources: getMediasSources(),
|
||||
callback: function() {
|
||||
debug("next image");
|
||||
x2tImportImagesInternal(x2t, images, i+1, callback);
|
||||
x2tImportImagesInternal(images, i+1, callback);
|
||||
},
|
||||
};
|
||||
var filePath = "/working/media/" + images[i];
|
||||
debug("Import filename " + filePath);
|
||||
var fileData = x2t.FS.readFile("/working/media/" + images[i], { encoding : "binary" });
|
||||
debug("Importing data");
|
||||
var fileData = images[i].data;
|
||||
debug("Buffer");
|
||||
debug(fileData.buffer);
|
||||
var blob = new Blob([fileData.buffer], {type: 'image/png'});
|
||||
blob.name = images[i];
|
||||
blob.name = images[i].name;
|
||||
APP.FMImages.handleFile(blob, handleFileData);
|
||||
}
|
||||
};
|
||||
|
||||
var x2tImportImages = function (x2t, callback) {
|
||||
var x2tImportImages = function (images, callback) {
|
||||
if (!APP.FMImages) {
|
||||
var fmConfigImages = {
|
||||
noHandlers: true,
|
||||
|
@ -2055,14 +1896,8 @@ define([
|
|||
|
||||
// Import Images
|
||||
debug("Import Images");
|
||||
var files = x2t.FS.readdir("/working/media/");
|
||||
var images = [];
|
||||
files.forEach(function (file) {
|
||||
if (file !== "." && file !== "..") {
|
||||
images.push(file);
|
||||
}
|
||||
});
|
||||
x2tImportImagesInternal(x2t, images, 0, function() {
|
||||
debug(images);
|
||||
x2tImportImagesInternal(images, 0, function() {
|
||||
debug("Sync media sources elements");
|
||||
debug(getMediasSources());
|
||||
APP.onLocal();
|
||||
|
@ -2072,26 +1907,12 @@ define([
|
|||
};
|
||||
|
||||
|
||||
var x2tConvertData = function (x2t, data, filename, extension, callback) {
|
||||
var convertedContent;
|
||||
// Convert from ODF format:
|
||||
// first convert to Office format then to the selected extension
|
||||
if (filename.endsWith(".ods")) {
|
||||
console.log(x2t, data, filename, extension);
|
||||
convertedContent = x2tConvertDataInternal(x2t, new Uint8Array(data), filename, "xlsx");
|
||||
console.log(convertedContent);
|
||||
convertedContent = x2tConvertDataInternal(x2t, convertedContent, filename + ".xlsx", extension);
|
||||
} else if (filename.endsWith(".odt")) {
|
||||
convertedContent = x2tConvertDataInternal(x2t, new Uint8Array(data), filename, "docx");
|
||||
convertedContent = x2tConvertDataInternal(x2t, convertedContent, filename + ".docx", extension);
|
||||
} else if (filename.endsWith(".odp")) {
|
||||
convertedContent = x2tConvertDataInternal(x2t, new Uint8Array(data), filename, "pptx");
|
||||
convertedContent = x2tConvertDataInternal(x2t, convertedContent, filename + ".pptx", extension);
|
||||
} else {
|
||||
convertedContent = x2tConvertDataInternal(x2t, new Uint8Array(data), filename, extension);
|
||||
}
|
||||
x2tImportImages(x2t, function() {
|
||||
callback(convertedContent);
|
||||
var x2tImportData = function (data, filename, extension, callback) {
|
||||
x2tConvertData(new Uint8Array(data), filename, extension, function (binData, images) {
|
||||
if (!binData) { return void UI.warn(Messages.error); }
|
||||
x2tImportImages(images, function() {
|
||||
callback(binData);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2145,10 +1966,8 @@ define([
|
|||
]);
|
||||
UI.openCustomModal(UI.dialog.customModal(div, {buttons: []}));
|
||||
setTimeout(function () {
|
||||
getX2T(function (x2t) {
|
||||
x2tConvertData(x2t, new Uint8Array(content), filename.name, "bin", function(c) {
|
||||
importFile(c);
|
||||
});
|
||||
x2tImportData(new Uint8Array(content), filename.name, "bin", function(c) {
|
||||
importFile(c);
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
|
|
@ -143,6 +143,22 @@ define([
|
|||
}
|
||||
sframeChan.event('EV_OO_EVENT', obj);
|
||||
});
|
||||
|
||||
// X2T
|
||||
var x2t;
|
||||
var onConvert = function (obj, cb) {
|
||||
x2t.convert(obj, cb);
|
||||
};
|
||||
sframeChan.on('Q_OO_CONVERT', function (obj, cb) {
|
||||
if (x2t) { return void onConvert(obj, cb); }
|
||||
require(['/common/outer/x2t.js'], function (X2T) {
|
||||
x2t = X2T.start();
|
||||
onConvert(obj, cb);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
};
|
||||
SFCommonO.start({
|
||||
hash: hash,
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
define([
|
||||
'/bower_components/nthen/index.js',
|
||||
'/common/common-util.js',
|
||||
], function (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 = '/common/onlyoffice/'+CURRENT_VERSION+'/fonts/';
|
||||
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, 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');
|
||||
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 '<m_nFormatFrom>'+id+'</m_nFormatFrom>';
|
||||
};
|
||||
var getToId = function (ext) {
|
||||
var id = getFormatId(ext);
|
||||
if (!id) { return ''; }
|
||||
return '<m_nFormatTo>'+id+'</m_nFormatTo>';
|
||||
};
|
||||
|
||||
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 = "<m_bIsNoBase64>false</m_bIsNoBase64>" +
|
||||
"<m_sFontDir>/working/fonts/</m_sFontDir>";
|
||||
// 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) {
|
||||
var mediaFileName = _mediaFileName.substring(6);
|
||||
var mediasSources = obj.mediasSources || {};
|
||||
var mediasData = obj.mediasData || {};
|
||||
var mediaSource = mediasSources[mediaFileName];
|
||||
var 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||
+ "<TaskQueueDataConvert xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
|
||||
+ "<m_sFileFrom>/working/" + fileName + "</m_sFileFrom>"
|
||||
+ "<m_sFileTo>/working/" + fileName + "." + outputFormat + "</m_sFileTo>"
|
||||
+ pdfData
|
||||
+ getFromId(inputFormat)
|
||||
+ getToId(outputFormat)
|
||||
+ "<m_bIsNoBase64>false</m_bIsNoBase64>"
|
||||
+ "</TaskQueueDataConvert>";
|
||||
// writing params file to mounted working disk (in memory)
|
||||
x2t.FS.writeFile('/working/params.xml', params);
|
||||
// running conversion
|
||||
x2t.ccall("runX2T", ["number"], ["string"], ["/working/params.xml"]);
|
||||
// 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) {
|
||||
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;
|
||||
});
|
|
@ -8,7 +8,6 @@ define([
|
|||
'/common/hyperscript.js',
|
||||
'/customize/messages.js',
|
||||
'/common/common-interface.js',
|
||||
'/common/common-util.js',
|
||||
|
||||
'/bower_components/file-saver/FileSaver.min.js',
|
||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||
|
@ -23,8 +22,7 @@ define([
|
|||
SFCommon,
|
||||
h,
|
||||
Messages,
|
||||
UI,
|
||||
Util
|
||||
UI
|
||||
)
|
||||
{
|
||||
var APP = {};
|
||||
|
@ -32,126 +30,21 @@ define([
|
|||
var common;
|
||||
var sFrameChan;
|
||||
|
||||
var debug = console.debug;
|
||||
|
||||
var x2tReady = Util.mkEvent(true);
|
||||
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');
|
||||
x2tInitialized = true;
|
||||
x2tReady.fire();
|
||||
//fetchFonts(x2t);
|
||||
debug("x2t mount done");
|
||||
};
|
||||
var getX2t = function (cb) {
|
||||
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);
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
/*
|
||||
Converting Data
|
||||
|
||||
This function converts a data in a specific format to the outputformat
|
||||
The filename extension needs to represent the input format
|
||||
Example: fileName=cryptpad.bin outputFormat=xlsx
|
||||
*/
|
||||
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 '<m_nFormatFrom>'+id+'</m_nFormatFrom>';
|
||||
};
|
||||
var getToId = function (ext) {
|
||||
var id = getFormatId(ext);
|
||||
if (!id) { return ''; }
|
||||
return '<m_nFormatTo>'+id+'</m_nFormatTo>';
|
||||
};
|
||||
var x2tConvertDataInternal = function(x2t, data, fileName, outputFormat) {
|
||||
debug("Converting Data for " + fileName + " to " + outputFormat);
|
||||
|
||||
var inputFormat = fileName.split('.').pop();
|
||||
|
||||
x2t.FS.writeFile('/working/' + fileName, data);
|
||||
var params = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||
+ "<TaskQueueDataConvert xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
|
||||
+ "<m_sFileFrom>/working/" + fileName + "</m_sFileFrom>"
|
||||
+ "<m_sFileTo>/working/" + fileName + "." + outputFormat + "</m_sFileTo>"
|
||||
+ getFromId(inputFormat)
|
||||
+ getToId(outputFormat)
|
||||
+ "<m_bIsNoBase64>false</m_bIsNoBase64>"
|
||||
+ "</TaskQueueDataConvert>";
|
||||
// writing params file to mounted working disk (in memory)
|
||||
x2t.FS.writeFile('/working/params.xml', params);
|
||||
// running conversion
|
||||
x2t.ccall("runX2T", ["number"], ["string"], ["/working/params.xml"]);
|
||||
// reading output file from working disk (in memory)
|
||||
var result;
|
||||
try {
|
||||
result = x2t.FS.readFile('/working/' + fileName + "." + outputFormat);
|
||||
} catch (e) {
|
||||
console.error(e, x2t.FS);
|
||||
debug("Failed reading converted file");
|
||||
UI.warn(Messages.error);
|
||||
return "";
|
||||
}
|
||||
return result;
|
||||
};
|
||||
var x2tConverter = function (typeSrc, typeTarget) {
|
||||
return function (data, name, cb) {
|
||||
getX2t(function (x2t) {
|
||||
if (typeSrc === 'ods') {
|
||||
data = x2tConvertDataInternal(x2t, data, name, 'xlsx');
|
||||
name += '.xlsx';
|
||||
var sframeChan = common.getSframeChannel();
|
||||
sframeChan.query('Q_OO_CONVERT', {
|
||||
data: data,
|
||||
fileName: name,
|
||||
outputFormat: typeTarget,
|
||||
}, function (err, obj) {
|
||||
if (err || !obj || !obj.data) {
|
||||
UI.warn(Messages.error);
|
||||
cb();
|
||||
}
|
||||
if (typeSrc === 'odt') {
|
||||
data = x2tConvertDataInternal(x2t, data, name, 'docx');
|
||||
name += '.docx';
|
||||
}
|
||||
if (typeSrc === 'odp') {
|
||||
data = x2tConvertDataInternal(x2t, data, name, 'pptx');
|
||||
name += '.pptx';
|
||||
}
|
||||
cb(x2tConvertDataInternal(x2t, data, name, typeTarget));
|
||||
cb(obj.data, obj.images);
|
||||
}, {
|
||||
raw: true
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,11 +17,26 @@ define([
|
|||
category = window.location.hash.slice(1);
|
||||
window.location.hash = '';
|
||||
}
|
||||
var addRpc = function (sframeChan) {
|
||||
// X2T
|
||||
var x2t;
|
||||
var onConvert = function (obj, cb) {
|
||||
x2t.convert(obj, cb);
|
||||
};
|
||||
sframeChan.on('Q_OO_CONVERT', function (obj, cb) {
|
||||
if (x2t) { return void onConvert(obj, cb); }
|
||||
require(['/common/outer/x2t.js'], function (X2T) {
|
||||
x2t = X2T.start();
|
||||
onConvert(obj, cb);
|
||||
});
|
||||
});
|
||||
};
|
||||
var addData = function (obj) {
|
||||
if (category) { obj.category = category; }
|
||||
};
|
||||
SFCommonO.start({
|
||||
noRealtime: true,
|
||||
addRpc: addRpc,
|
||||
addData: addData
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue