edgeconnect-cryptpad-deploy.../www/integration/main.js
Richard Robert Reitz addc3725ea
Some checks failed
build / build (push) Has been cancelled
first commit
2025-08-28 15:13:14 +02:00

288 lines
9.8 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later
define([
'/api/config',
'/common/sframe-common-outer.js',
'/common/common-hash.js',
'/common/common-util.js',
'/components/tweetnacl/nacl-fast.min.js'
], function (Config, SCO, Hash, Util) {
var getTxid = function () {
return Math.random().toString(16).replace('0.', '');
};
var init = function () {
console.warn('INIT');
var p = window.parent;
var txid = getTxid();
p.postMessage({ q: 'INTEGRATION_READY', txid: txid }, '*');
var makeChan = function () {
var handlers = {};
var commands = {};
var _sendCb = function (txid, args) {
p.postMessage({ ack: txid, args: args}, '*');
};
var onMsg = function (ev) {
if (ev.source !== p) { return; }
var data = ev.data;
// On ack
if (data.ack) {
if (handlers[data.ack]) {
handlers[data.ack](data.args);
delete handlers[data.ack];
}
return;
}
// On new command
var msg = data.msg;
if (!msg) { return; }
var txid = data.txid;
if (commands[msg.q]) {
commands[msg.q](msg.data, function (args) {
_sendCb(txid, args);
});
return;
}
};
window.addEventListener('message', onMsg);
var send = function (q, data, cb) {
var txid = getTxid();
if (cb) { handlers[txid] = cb; }
p.postMessage({ msg: {
q: q,
data: data,
}, txid: txid}, '*');
setTimeout(function () {
delete handlers[txid];
}, 60000);
};
var on = function (q, handler) {
if (typeof(handler) !== "function") { return; }
commands[q] = handler;
};
return {
send: send,
on: on
};
};
var chan = makeChan();
//var isNew = false;
var checkSession = function (oldKey, cb) {
var channel = Hash.hrefToHexChannelId(Hash.hashToHref(oldKey));
var prefix = channel.slice(0,2);
var url = `/datastore/${prefix}/${channel}.ndjson`;
var http = new XMLHttpRequest();
http.open('HEAD', url);
http.onreadystatechange = function() {
if (this.readyState === this.DONE) {
console.error(this.status);
if (this.status === 200) {
return cb({state: true});
}
if (this.status === 404) {
return cb({state: false});
}
cb({error: 'Internal server error'});
}
};
http.send();
};
let sanitizeKey = key => {
try {
Util.decodeBase64(key);
return key;
} catch (e) {
return Util.encodeBase64(Util.decodeUTF8(key)).replaceAll('=', '');
}
};
chan.on('GET_SESSION', function (data, cb) {
if (data.keepOld) { // they provide their own key, we must turn it into a hash
var key = sanitizeKey(data.key) + "000000000000000000000000000000000";
console.warn('KEY', key);
return void cb({
key: `/2/integration/edit/${key.slice(0,24)}/`
});
}
var getHash = function () {
//isNew = true;
return Hash.createRandomHash('integration');
};
var oldKey = data.key;
if (!oldKey) { return void cb({ key: getHash() }); }
checkSession(oldKey, function (obj) {
if (!obj || obj.error) { return cb(obj); }
cb({
key: obj.state ? oldKey : getHash()
});
});
});
var reload = function (data) {
chan.send('RELOAD', data);
};
var onHasUnsavedChanges = function (unsavedChanges, cb) {
chan.send('HAS_UNSAVED_CHANGES', unsavedChanges, cb);
};
var onInsertImage = function (data, cb) {
chan.send('ON_INSERT_IMAGE', data, cb);
};
var onReady = function () {
chan.send('DOCUMENT_READY', {});
};
let downloadAs;
chan.on('DOWNLOAD_AS', function (format) {
if (typeof(downloadAs) !== "function") {
console.error('UNSUPPORTED COMMAND', 'downloadAs');
return;
}
downloadAs(format);
});
let setDownloadAs = f => {
downloadAs = f;
};
let onDownloadAs = function (blob) { // DownloadAs callback
chan.send('ON_DOWNLOADAS', blob);
};
let getInstanceURL = function () {
return Config.httpUnsafeOrigin;
};
let getBlobServer = function (documentURL, cb) {
let xhr = new XMLHttpRequest();
let data = encodeURIComponent(documentURL);
let url = getInstanceURL() + '/ooapidl?url=' + data;
xhr.open('GET', url, true);
xhr.responseType = 'blob';
//xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response;
// myBlob is now the blob that the object URL pointed to.
cb(null, blob);
} else {
cb(this.status);
}
};
xhr.onerror = function (e) {
cb(e.message);
};
xhr.send();
};
let saveBlobServer = function (cfg, blob, cb) {
let {callbackUrl, name, key} = cfg;
let xhr = new XMLHttpRequest();
name = encodeURIComponent(name);
callbackUrl = encodeURIComponent(callbackUrl);
key = encodeURIComponent(key);
let query = `name=${name}&cb=${callbackUrl}&key=${key}`;
let url = getInstanceURL() + `/oosave?${query}`;
xhr.open('POST', url, true);
xhr.responseType = 'blob';
//xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
console.error(this.status);
if (this.status === 200) {
cb();
} else {
cb(this.status);
}
};
xhr.onerror = function (e) {
cb(e.message);
};
xhr.send(blob);
};
chan.on('START', function (data, cb) {
console.warn('INNER START', data);
// data.key is a hash
var href = Hash.hashToHref(data.key, data.application);
if (data.editorConfig.lang) {
var LS_LANG = "CRYPTPAD_LANG";
localStorage.setItem(LS_LANG, data.editorConfig.lang);
}
let fileName = data.name || `document.${data.ext}`;
var save = function (obj, cb) {
let cbUrl = data.editorConfig.callbackUrl;
if (!data.autosave && cbUrl) {
saveBlobServer({
callbackUrl: cbUrl,
name: fileName,
key: data.documentKey
}, obj.blob, cb);
return;
}
chan.send('SAVE', obj.blob, function (err) {
if (err) { return cb({error: err}); }
cb();
});
};
console.error(Hash.hrefToHexChannelId(href));
let startApp = function (blob) {
window.CP_integration_outer = {
pathname: `/${data.application}/`,
hash: data.key,
href: href,
initialState: blob,
config: {
readOnly: data.readOnly,
fileName: data.name,
fileType: data.ext,
autosave: data.autosave,
user: data.editorConfig.user,
_: data._config
},
utils: {
onReady: onReady,
onDownloadAs,
setDownloadAs,
save: save,
reload: reload,
onHasUnsavedChanges: onHasUnsavedChanges,
onInsertImage: onInsertImage
}
};
let path = "/common/sframe-app-outer.js";
if (['sheet', 'doc', 'presentation'].includes(data.application)) {
path = '/common/onlyoffice/main.js';
}
require([path], function () {
console.warn('SAO REQUIRED');
delete window.CP_integration_outer;
cb();
});
};
if (data.document) { return void startApp(data.document); }
getBlobServer(data.url, (err, blob) => {
if (err) {
return void cb({error: err});
}
startApp(blob);
});
});
};
init();
/*
nThen(function (waitFor) {
}).nThen(function () {
});
*/
});