33 changed files with 701 additions and 806 deletions
Split View
Diff Options
-
8config/config.example.js
-
2customize.dist/src/outer.css
-
1docs/example.nginx.conf
-
2lib/commands/admin-rpc.js
-
28lib/commands/channel.js
-
11lib/commands/pin-rpc.js
-
11lib/historyKeeper.js
-
8lib/hk-util.js
-
113lib/workers/crypto-worker.js
-
91lib/workers/db-worker.js
-
269lib/workers/index.js
-
1www/code/inner.js
-
18www/common/common-interface.js
-
150www/common/common-ui-elements.js
-
27www/common/diffMarked.js
-
7www/common/inner/common-modal.js
-
67www/common/onlyoffice/inner.js
-
3www/common/outer/async-store.js
-
2www/common/outer/team.js
-
21www/common/sframe-app-framework.js
-
117www/common/sframe-common-outer.js
-
1www/common/sframe-common.js
-
23www/common/translations/messages.ca.json
-
134www/filepicker/main.js
-
18www/poll/inner.js
-
14www/secureiframe/app-secure.less
-
4www/secureiframe/inner.html
-
158www/secureiframe/inner.js
-
35www/secureiframe/main.js
-
17www/share/app-share.less
-
30www/share/index.html
-
29www/share/inner.html
-
87www/share/inner.js
@ -1,113 +0,0 @@ |
|||
/* jshint esversion: 6 */ |
|||
/* global process */ |
|||
const Nacl = require('tweetnacl/nacl-fast'); |
|||
|
|||
const COMMANDS = {}; |
|||
|
|||
COMMANDS.INLINE = function (data, cb) { |
|||
var signedMsg; |
|||
try { |
|||
signedMsg = Nacl.util.decodeBase64(data.msg); |
|||
} catch (e) { |
|||
return void cb('E_BAD_MESSAGE'); |
|||
} |
|||
|
|||
var validateKey; |
|||
try { |
|||
validateKey = Nacl.util.decodeBase64(data.key); |
|||
} catch (e) { |
|||
return void cb("E_BADKEY"); |
|||
} |
|||
// validate the message
|
|||
const validated = Nacl.sign.open(signedMsg, validateKey); |
|||
if (!validated) { |
|||
return void cb("FAILED"); |
|||
} |
|||
cb(); |
|||
}; |
|||
|
|||
const checkDetachedSignature = function (signedMsg, signature, publicKey) { |
|||
if (!(signedMsg && publicKey)) { return false; } |
|||
|
|||
var signedBuffer; |
|||
var pubBuffer; |
|||
var signatureBuffer; |
|||
|
|||
try { |
|||
signedBuffer = Nacl.util.decodeUTF8(signedMsg); |
|||
} catch (e) { |
|||
throw new Error("INVALID_SIGNED_BUFFER"); |
|||
} |
|||
|
|||
try { |
|||
pubBuffer = Nacl.util.decodeBase64(publicKey); |
|||
} catch (e) { |
|||
throw new Error("INVALID_PUBLIC_KEY"); |
|||
} |
|||
|
|||
try { |
|||
signatureBuffer = Nacl.util.decodeBase64(signature); |
|||
} catch (e) { |
|||
throw new Error("INVALID_SIGNATURE"); |
|||
} |
|||
|
|||
if (pubBuffer.length !== 32) { |
|||
throw new Error("INVALID_PUBLIC_KEY_LENGTH"); |
|||
} |
|||
|
|||
if (signatureBuffer.length !== 64) { |
|||
throw new Error("INVALID_SIGNATURE_LENGTH"); |
|||
} |
|||
|
|||
if (Nacl.sign.detached.verify(signedBuffer, signatureBuffer, pubBuffer) !== true) { |
|||
throw new Error("FAILED"); |
|||
} |
|||
}; |
|||
|
|||
COMMANDS.DETACHED = function (data, cb) { |
|||
try { |
|||
checkDetachedSignature(data.msg, data.sig, data.key); |
|||
} catch (err) { |
|||
return void cb(err && err.message); |
|||
} |
|||
cb(); |
|||
}; |
|||
|
|||
COMMANDS.HASH_CHANNEL_LIST = function (data, cb) { |
|||
var channels = data.channels; |
|||
if (!Array.isArray(channels)) { return void cb('INVALID_CHANNEL_LIST'); } |
|||
var uniques = []; |
|||
|
|||
channels.forEach(function (a) { |
|||
if (uniques.indexOf(a) === -1) { uniques.push(a); } |
|||
}); |
|||
uniques.sort(); |
|||
|
|||
var hash = Nacl.util.encodeBase64(Nacl.hash(Nacl |
|||
.util.decodeUTF8(JSON.stringify(uniques)))); |
|||
|
|||
cb(void 0, hash); |
|||
}; |
|||
|
|||
process.on('message', function (data) { |
|||
if (!data || !data.txid) { |
|||
return void process.send({ |
|||
error:'E_INVAL' |
|||
}); |
|||
} |
|||
|
|||
const cb = function (err, value) { |
|||
process.send({ |
|||
txid: data.txid, |
|||
error: err, |
|||
value: value, |
|||
}); |
|||
}; |
|||
|
|||
const command = COMMANDS[data.command]; |
|||
if (typeof(command) !== 'function') { |
|||
return void cb("E_BAD_COMMAND"); |
|||
} |
|||
|
|||
command(data, cb); |
|||
}); |
|||
@ -1,134 +0,0 @@ |
|||
// Load #1, load as little as possible because we are in a race to get the loading screen up.
|
|||
define([ |
|||
'/bower_components/nthen/index.js', |
|||
'/api/config', |
|||
'jquery', |
|||
'/common/requireconfig.js', |
|||
], function (nThen, ApiConfig, $, RequireConfig) { |
|||
var requireConfig = RequireConfig(); |
|||
|
|||
var create = function (config) { |
|||
// Loaded in load #2
|
|||
var sframeChan; |
|||
nThen(function (waitFor) { |
|||
$(waitFor()); |
|||
}).nThen(function (waitFor) { |
|||
var req = { |
|||
cfg: requireConfig, |
|||
req: [ '/common/loading.js' ], |
|||
pfx: window.location.origin |
|||
}; |
|||
window.rc = requireConfig; |
|||
window.apiconf = ApiConfig; |
|||
$('#sbox-filePicker-iframe').attr('src', |
|||
ApiConfig.httpSafeOrigin + '/filepicker/inner.html?' + requireConfig.urlArgs + |
|||
'#' + encodeURIComponent(JSON.stringify(req))); |
|||
|
|||
// This is a cheap trick to avoid loading sframe-channel in parallel with the
|
|||
// loading screen setup.
|
|||
var done = waitFor(); |
|||
var onMsg = function (msg) { |
|||
var data = JSON.parse(msg.data); |
|||
if (data.q !== 'READY') { return; } |
|||
window.removeEventListener('message', onMsg); |
|||
var _done = done; |
|||
done = function () { }; |
|||
_done(); |
|||
}; |
|||
window.addEventListener('message', onMsg); |
|||
}).nThen(function (/*waitFor*/) { |
|||
var Cryptpad = config.modules.Cryptpad; |
|||
var Utils = config.modules.Utils; |
|||
|
|||
nThen(function (waitFor) { |
|||
// The inner iframe tries to get some data from us every ms (cache, store...).
|
|||
// It will send a "READY" message and wait for our answer with the correct txid.
|
|||
// First, we have to answer to this message, otherwise we're going to block
|
|||
// sframe-boot.js. Then we can start the channel.
|
|||
var msgEv = Utils.Util.mkEvent(); |
|||
var iframe = $('#sbox-filePicker-iframe')[0].contentWindow; |
|||
var postMsg = function (data) { |
|||
iframe.postMessage(data, '*'); |
|||
}; |
|||
var w = waitFor(); |
|||
var whenReady = function (msg) { |
|||
if (msg.source !== iframe) { return; } |
|||
var data = JSON.parse(msg.data); |
|||
if (!data.txid) { return; } |
|||
// Remove the listener once we've received the READY message
|
|||
window.removeEventListener('message', whenReady); |
|||
// Answer with the requested data
|
|||
postMsg(JSON.stringify({ txid: data.txid, language: Cryptpad.getLanguage(), localStore: window.localStore, cache: window.cpCache })); |
|||
|
|||
// Then start the channel
|
|||
window.addEventListener('message', function (msg) { |
|||
if (msg.source !== iframe) { return; } |
|||
msgEv.fire(msg); |
|||
}); |
|||
config.modules.SFrameChannel.create(msgEv, postMsg, waitFor(function (sfc) { |
|||
sframeChan = sfc; |
|||
})); |
|||
w(); |
|||
}; |
|||
window.addEventListener('message', whenReady); |
|||
}).nThen(function () { |
|||
var updateMeta = function () { |
|||
//console.log('EV_METADATA_UPDATE');
|
|||
var metaObj; |
|||
nThen(function (waitFor) { |
|||
Cryptpad.getMetadata(waitFor(function (err, n) { |
|||
if (err) { console.log(err); } |
|||
metaObj = n; |
|||
})); |
|||
}).nThen(function (/*waitFor*/) { |
|||
metaObj.doc = {}; |
|||
var additionalPriv = { |
|||
fileHost: ApiConfig.fileHost, |
|||
loggedIn: Utils.LocalStore.isLoggedIn(), |
|||
origin: window.location.origin, |
|||
pathname: window.location.pathname, |
|||
feedbackAllowed: Utils.Feedback.state, |
|||
types: config.types |
|||
}; |
|||
for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; } |
|||
|
|||
sframeChan.event('EV_METADATA_UPDATE', metaObj); |
|||
}); |
|||
}; |
|||
Cryptpad.onMetadataChanged(updateMeta); |
|||
sframeChan.onReg('EV_METADATA_UPDATE', updateMeta); |
|||
|
|||
config.addCommonRpc(sframeChan); |
|||
|
|||
sframeChan.on('Q_GET_FILES_LIST', function (types, cb) { |
|||
Cryptpad.getSecureFilesList(types, function (err, data) { |
|||
cb({ |
|||
error: err, |
|||
data: data |
|||
}); |
|||
}); |
|||
}); |
|||
|
|||
sframeChan.on('EV_FILE_PICKER_CLOSE', function () { |
|||
config.onClose(); |
|||
}); |
|||
sframeChan.on('EV_FILE_PICKED', function (data) { |
|||
config.onFilePicked(data); |
|||
}); |
|||
sframeChan.on('Q_UPLOAD_FILE', function (data, cb) { |
|||
config.onFileUpload(sframeChan, data, cb); |
|||
}); |
|||
}); |
|||
}); |
|||
var refresh = function (types) { |
|||
if (!sframeChan) { return; } |
|||
sframeChan.event('EV_FILE_PICKER_REFRESH', types); |
|||
}; |
|||
return { |
|||
refresh: refresh |
|||
}; |
|||
}; |
|||
return { |
|||
create: create |
|||
}; |
|||
}); |
|||
@ -1,17 +0,0 @@ |
|||
@import (reference) '../../customize/src/less2/include/tippy.less'; |
|||
@import (reference) '../../customize/src/less2/include/modal.less'; |
|||
@import (reference) '../../customize/src/less2/include/alertify.less'; |
|||
@import (reference) '../../customize/src/less2/include/checkmark.less'; |
|||
@import (reference) '../../customize/src/less2/include/password-input.less'; |
|||
@import (reference) '../../customize/src/less2/include/usergrid.less'; |
|||
@import (reference) '../../customize/src/less2/include/modals-ui-elements.less'; |
|||
|
|||
&.cp-app-share { |
|||
.tippy_main(); |
|||
.alertify_main(); |
|||
.modals-ui-elements_main(); |
|||
.checkmark_main(20px); |
|||
.password_main(); |
|||
.modal_main(); |
|||
.usergrid_main(); |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<title>CryptPad</title> |
|||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|||
<meta name="referrer" content="no-referrer" /> |
|||
<script async data-bootload="main.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> |
|||
<style> |
|||
html, body { |
|||
margin: 0px; |
|||
padding: 0px; |
|||
} |
|||
#sbox-iframe { |
|||
position:fixed; |
|||
top:0px; |
|||
left:0px; |
|||
bottom:0px; |
|||
right:0px; |
|||
width:100%; |
|||
height:100%; |
|||
border:none; |
|||
margin:0; |
|||
padding:0; |
|||
overflow:hidden; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<iframe id="sbox-iframe"> |
|||
@ -1,29 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html style="height: 100%; background: transparent;"> |
|||
<head> |
|||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> |
|||
<script async data-bootload="/share/inner.js" data-main="/common/sframe-boot.js?ver=1.6" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> |
|||
<style> |
|||
.loading-hidden { display: none; } |
|||
body #cp-loading { |
|||
display: none; |
|||
position: absolute; |
|||
top: 15vh; |
|||
bottom: 15vh; |
|||
left: 10vw; |
|||
right: 10vw; |
|||
z-index: 200000; |
|||
overflow: hidden; |
|||
} |
|||
body #cp-loading .cp-loading-container { |
|||
margin-top: 35vh; |
|||
} |
|||
body #cp-loading .cp-loading-cryptofist { |
|||
display: none; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body class="cp-app-share" style="background: transparent;"> |
|||
</body> |
|||
</html> |
|||
|
|||
@ -1,87 +0,0 @@ |
|||
define([ |
|||
'jquery', |
|||
'/bower_components/nthen/index.js', |
|||
'/common/sframe-common.js', |
|||
'/common/common-ui-elements.js', |
|||
'/common/common-interface.js', |
|||
|
|||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', |
|||
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', |
|||
'less!/share/app-share.less', |
|||
], function ( |
|||
$, |
|||
nThen, |
|||
SFCommon, |
|||
UIElements, |
|||
UI) |
|||
{ |
|||
var APP = window.APP = {}; |
|||
|
|||
var init = false; |
|||
var andThen = function (common) { |
|||
if (init) { return; } |
|||
init = true; |
|||
|
|||
var metadataMgr = common.getMetadataMgr(); |
|||
var sframeChan = common.getSframeChannel(); |
|||
|
|||
var hideShareDialog = function () { |
|||
sframeChan.event('EV_SHARE_CLOSE'); |
|||
}; |
|||
|
|||
var createShareDialog = function (data) { |
|||
var priv = metadataMgr.getPrivateData(); |
|||
var hashes = priv.hashes; |
|||
var origin = priv.origin; |
|||
var pathname = priv.pathname; |
|||
var f = (data && data.file) ? UIElements.createFileShareModal |
|||
: UIElements.createShareModal; |
|||
|
|||
var friends = common.getFriends(); |
|||
|
|||
var modal = f({ |
|||
origin: origin, |
|||
pathname: pathname, |
|||
password: priv.password, |
|||
isTemplate: priv.isTemplate, |
|||
hashes: hashes, |
|||
common: common, |
|||
title: data.title, |
|||
friends: friends, |
|||
onClose: function () { |
|||
hideShareDialog(); |
|||
}, |
|||
fileData: { |
|||
hash: hashes.fileHash, |
|||
password: priv.password |
|||
} |
|||
}); |
|||
$('button.cancel').click(); // Close any existing alertify
|
|||
UI.openCustomModal(modal); |
|||
}; |
|||
sframeChan.on('EV_SHARE_REFRESH', function (data) { |
|||
createShareDialog(data); |
|||
}); |
|||
}; |
|||
|
|||
var main = function () { |
|||
var common; |
|||
|
|||
nThen(function (waitFor) { |
|||
$(waitFor(function () { |
|||
UI.removeLoadingScreen(); |
|||
})); |
|||
SFCommon.create(waitFor(function (c) { APP.common = common = c; })); |
|||
}).nThen(function (/*waitFor*/) { |
|||
var metadataMgr = common.getMetadataMgr(); |
|||
if (metadataMgr.getMetadataLazy() !== 'uninitialized') { |
|||
andThen(common); |
|||
return; |
|||
} |
|||
metadataMgr.onChange(function () { |
|||
andThen(common); |
|||
}); |
|||
}); |
|||
}; |
|||
main(); |
|||
}); |
|||
Write
Preview
Loading…
Cancel
Save