diff --git a/config.example.js b/config.example.js
index 43438aea6..7af6cf8af 100644
--- a/config.example.js
+++ b/config.example.js
@@ -82,23 +82,6 @@ module.exports = {
*/
websocketPath: '/cryptpad_websocket',
- /* it is assumed that your websocket will bind to the same port as http
- * you can override this behaviour by supplying a number via websocketPort
- */
- //websocketPort: 3000,
-
- /* if you want to run a different version of CryptPad but using the same websocket
- * server, you should use the other server port as websocketPort and disable
- * the websockets on that server
- */
- //useExternalWebsocket: false,
-
- /* If CryptPad is proxied without using https, the server needs to know.
- * Specify 'useSecureWebsockets: true' so that it can send
- * Content Security Policy Headers that prevent http and https from mixing
- */
- useSecureWebsockets: false,
-
/* CryptPad can log activity to stdout
* This may be useful for debugging
*/
@@ -238,14 +221,6 @@ module.exports = {
*/
suppressRPCErrors: false,
-
- /* WARNING: EXPERIMENTAL
- *
- * CryptPad features experimental support for encrypted file upload.
- * Our encryption format is still liable to change. As such, we do not
- * guarantee that files uploaded now will be supported in the future
- */
-
/* Setting this value to anything other than true will cause file upload
* attempts to be rejected outright.
*/
diff --git a/customize.dist/bkregister.jpg b/customize.dist/bkregister.jpg
new file mode 100644
index 000000000..03660433f
Binary files /dev/null and b/customize.dist/bkregister.jpg differ
diff --git a/customize.dist/code.svg b/customize.dist/code.svg
new file mode 100644
index 000000000..29647b529
--- /dev/null
+++ b/customize.dist/code.svg
@@ -0,0 +1,14 @@
+
+
+
diff --git a/customize.dist/images/AaronMacSween.jpg b/customize.dist/images/AaronMacSween.jpg
new file mode 100644
index 000000000..2ee96ea6f
Binary files /dev/null and b/customize.dist/images/AaronMacSween.jpg differ
diff --git a/customize.dist/images/CalebJames.jpg b/customize.dist/images/CalebJames.jpg
new file mode 100644
index 000000000..65d5a6cae
Binary files /dev/null and b/customize.dist/images/CalebJames.jpg differ
diff --git a/customize.dist/images/Catalin.jpg b/customize.dist/images/Catalin.jpg
index 3a7cb2f13..109a5404b 100644
Binary files a/customize.dist/images/Catalin.jpg and b/customize.dist/images/Catalin.jpg differ
diff --git a/customize.dist/images/LudovicDuboist.jpg b/customize.dist/images/LudovicDuboist.jpg
new file mode 100644
index 000000000..6a9988942
Binary files /dev/null and b/customize.dist/images/LudovicDuboist.jpg differ
diff --git a/customize.dist/images/Pierre-new.jpg b/customize.dist/images/Pierre-new.jpg
index b4fef2583..4f197aeb0 100644
Binary files a/customize.dist/images/Pierre-new.jpg and b/customize.dist/images/Pierre-new.jpg differ
diff --git a/customize.dist/images/YannFlory.jpg b/customize.dist/images/YannFlory.jpg
new file mode 100644
index 000000000..19d10ec56
Binary files /dev/null and b/customize.dist/images/YannFlory.jpg differ
diff --git a/customize.dist/images/atest.jpg b/customize.dist/images/atest.jpg
new file mode 100644
index 000000000..4ce7014fe
Binary files /dev/null and b/customize.dist/images/atest.jpg differ
diff --git a/customize.dist/pages.js b/customize.dist/pages.js
index dfaf3d6b3..9e2759786 100644
--- a/customize.dist/pages.js
+++ b/customize.dist/pages.js
@@ -46,7 +46,9 @@ define([
h('div.container', [
h('div.row', [
footerCol(null, [
- setHTML(h('div.cp-bio-foot'), '
With CryptPad, you can make quick collaborative documents for taking notes and writing down ideas together.
'),
+ h('div.cp-bio-foot', [
+ h('p', Msg.main_footerText)
+ ])
], ''),
/* footerCol(null, [
footLink('/about.html', 'about'),
@@ -121,45 +123,110 @@ define([
]),
]),
h('div.container.cp-container', [
- /*h('center', [
- h('h1', Msg.about)
- ]),
- setHTML(h('p'), 'CryptPad is created inside of the Research Team at XWiki SAS, a small business located in Paris France and Iasi Romania. There are 3 core team members working on CryptPad plus a number of contributors both inside and outside of XWiki SAS.'),*/
h('div.row', [
- h('h2.col-12', 'Core Developers'),
- h('div.col-md-4', [
- h('img.bio-avatar', {'src': '/customize/images/aaron.jpg'}),
- h('h3', "Aaron MacSween"),
- setHTML(h('div#bio'), '
Aaron transitioned into distributed systems development from a background in jazz and live stage performance.
He appreciates the elegance of biological systems and functional programming, and focused on both as a student at the University of Toronto, where he studied cognitive and computer sciences.
He moved to Paris in 2015 to work as a research engineer at XWiki SAS, after having dedicated significant time to various cryptography-related software projects.
He spends his spare time experimenting with guitars, photography, science fiction, and spicy food.
Caleb is a cryptography developer, Machine Technology graduate of the Franklin County Technical School and lifelong tinkerer.
In 2011, he started the cjdns Open Source project to show that secure networking could be invisible and easily deployed.
After joining XWiki SAS in 2014, he started the CryptPad project with the intent of bringing the same transparent security to collaborative editing.
He\'s always trying to learn from more experienced colleagues and when someone passes through the Research Team office, his favorite words are "Pull up a chair!".
')
+ h('hr'),
+ setHTML(h('div#bioCaleb'), '
Caleb is a cryptography developer, Machine Technology graduate of the Franklin County Technical School and lifelong tinkerer. In 2011, he started the cjdns Open Source project to show that secure networking could be invisible and easily deployed. After joining XWiki SAS in 2014, he started the CryptPad project with the intent of bringing the same transparent security to collaborative editing. He\'s always trying to learn from more experienced colleagues and when someone passes through the Research Team office, his favorite words are "Pull up a chair!".
Aaron transitioned into distributed systems development from a background in jazz and live stage performance. He appreciates the elegance of biological systems and functional programming, and focused on both as a student at the University of Toronto, where he studied cognitive and computer sciences. He moved to Paris in 2015 to work as a research engineer at XWiki SAS, after having dedicated significant time to various cryptography-related software projects. He spends his spare time experimenting with guitars, photography, science fiction, and spicy food.
In 2015, Yann graduated with an engineering degree from Ecole Centrale de Lille majoring in Data Science. In his studies he worked on a project to detect defects in optical fiber using image processing technology. Upon joining XWiki SAS, Yann developed a Wiki page recommendation system, a common API for accessing data server-side and client-side, and an integrated development environment for development of XWiki applications. Yann is soft spoken but brutally efficient, he is known to say "It will take 5 minutes".
Resident CSS wizard and emoji extraordinaire, Pierre is passionate about anything related to technology. He loves to hack around computers and put parts together.
He is currently studying at 42, where he learns about algorithms, networking, kernel programming and graphics.
As a part of an internship, he joined XWiki SAS and worked on CryptPad to improve user experience. He also maintains the Spanish translation.
')
+ h('hr'),
+ setHTML(h('div#bioPierre'), '
Resident CSS wizard and emoji extraordinaire, Pierre is passionate about anything related to technology. He loves to hack around computers and put parts together. He is currently studying at 42, where he learns about algorithms, networking, kernel programming and graphics. As a part of an internship, he joined XWiki SAS and worked on CryptPad to improve user experience. He also maintains the Spanish translation.
Catalin is a Maths majour and has worked in B2B sales for 12 years. Design was always his passion and 3 years ago he started to dedicate himself to web design and front-end.
At the beginning of 2017 he joined the XWiki family, where he worked both on the business and the community side of XWiki, including the research team and CryptPad.
')
+ h('hr'),
+ setHTML(h('div#bioCatalin'), '
Catalin is a Maths majour and has worked in B2B sales for 12 years. Design was always his passion and 3 years ago he started to dedicate himself to web design and front-end. At the beginning of 2017 he joined the XWiki, where he worked both on the business and the community side of XWiki, including the research team and CryptPad.
A graduate of PolyTech (X90) and Telecom School in Paris, Ludovic Dubost started his career as a software architect for Netscape Communications Europe. He then became CTO of NetValue, one of the first French start-ups that went public. He left NetValue after the company was purchased by Nielsen/NetRatings and in 2004 launched XWiki, the next generation wiki.
Since the very beginning, Ludovic has been immensely helpful to the CryptPad project. He believed in the idea when there was nothing more than the collaborative pad and his help with sales strategy for the project.
A graduate of PolyTech (X90) and Telecom School in Paris, Ludovic Dubost started his career as a software architect for Netscape Communications Europe. He then became CTO of NetValue, one of the first French start-ups that went public. He left NetValue after the company was purchased by Nielsen/NetRatings and in 2004 launched XWiki, the next generation wiki. Since the very beginning, Ludovic has been immensely helpful to the CryptPad project. He believed in the idea when there was nothing more than the collaborative pad and his help with sales strategy for the project.
Le lien peut être copié et partagé de manièé de manière publique.";
+ out.profile_inviteButtonTitle = 'Créer un lien pour inviter cet utilisateur à se connecter avec vous.';
+ out.profile_inviteExplanation = "Cliquer sur OK créera un lien vers une session de messagerie sécurisée uniquement accessible par {0}.
Le lien peut être copié et partagé de manière publique.";
out.profile_viewMyProfile = "Voir mon profil";
// contacts/userlist
@@ -413,7 +413,7 @@ define(function () {
"
Vous pouvez importer les pads récents de ce navigateur pour les avoir dans votre compte utilisateur.
",
"
Si vous utilisez un ordinateur partagé, vous devez vous déconnecter avant de partir, fermer l'onglet n'est pas suffisant.
",
""
- ];
+ ].join('');
// Settings
out.settings_cat_account = "Compte";
@@ -487,8 +487,8 @@ define(function () {
out.todo_title = "CryptTodo";
out.todo_newTodoNamePlaceholder = "Décrivez votre tâche...";
out.todo_newTodoNameTitle = "Ajouter cette tâche à votre liste";
- out.todo_markAsCompleteTitle = "Marquer tâche comme terminée";
- out.todo_markAsIncompleteTitle = "Marquer tâche comme non incomplète";
+ out.todo_markAsCompleteTitle = "Marquer cette tâche comme terminée";
+ out.todo_markAsIncompleteTitle = "Marquer cette tâche comme incomplète";
out.todo_removeTaskTitle = "Enlever cette tâche de votre liste";
// pad
@@ -506,7 +506,7 @@ define(function () {
//contact.html
out.main_about_p2 = 'Si vous avez des questions ou commentaires, vous pouvez nous tweeter, ouvrir une issue sur GitHub, venir dire bonjour sur notre salle Matrix ou IRC (#cryptpad sur irc.freenode.net), ou bien encore nous envoyer un email.';
- out.main_info = "
Collaborez avec confiance
Développez vos idées en groupe avec des document partagés; la technologie Zero Knowledge sécurise vos données.";
+ out.main_info = "
Collaborez avec confiance
Développez vos idées en groupe avec des documents partagés; la technologie Zero Knowledge sécurise vos données.";
out.main_catch_phrase = "Le Cloud Zero Knowledge";
out.main_howitworks = 'Comment ça fonctionne';
@@ -536,6 +536,7 @@ define(function () {
out.main_whiteboardPad = 'Tableau blanc';
out.main_localPads = 'Pads Locaux';
out.main_yourCryptDrive = 'Votre CryptDrive';
+ out.main_footerText = "Avec CryptPad, vous pouvez créer des documents collaboratifs rapidement pour prendre des notes à plusieurs.";
out.footer_applications = "Applications";
out.footer_contact = "Contact";
@@ -589,7 +590,7 @@ define(function () {
out.header_support = '';
out.updated_0_header_logoTitle = 'Retourner vers votre CryptDrive';
out.header_logoTitle = out.updated_0_header_logoTitle;
- out.header_homeTitle = "Aller sur la page d'acceuil";
+ out.header_homeTitle = "Aller sur la page d'accueil";
// Initial states
diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js
index c89d524a0..acab6951d 100644
--- a/customize.dist/translations/messages.js
+++ b/customize.dist/translations/messages.js
@@ -404,13 +404,15 @@ define(function () {
out.register_header = "Welcome to CryptPad";
out.register_explanation = [
- "
Lets go over a couple things first
",
- "
",
- "
Your password is your secret key which encrypts all of your pads. If you lose it there is no way we can recover your data.
",
- "
You can import pads which were recently viewed in your browser so you have them in your account.
",
- "
If you are using a shared computer, you need to log out when you are done, closing the tab is not enough.
",
+ "
Lets go over a couple things first:
",
+ "
",
+ "
Your password is your secret key which encrypts all of your pads. If you lose it there is no way we can recover your data.
",
+ "
You can import pads which were recently viewed in your browser so you have them in your account.
",
+ "
If you are using a shared computer, you need to log out when you are done, closing the tab is not enough.
",
"
"
].join('');
+ out.register_testimonial =" \"Tools like Etherpad and Google Docs [...] all share a weakness, which is that whomever owns the document server can see everything you're typing. Cryptpad is a free/open project that uses some of the ideas behind blockchain to implement a \"zero-knowledge\" version of a collaborative document editor, ensuring that only the people working on a document can see it.\" ";
+ out.register_testimonial_name = "Cory Doctorow";
out.register_writtenPassword = "I have written down my username and password, proceed";
out.register_cancel = "Go back";
@@ -512,7 +514,7 @@ define(function () {
// contact.html
out.main_about_p2 = 'If you have any questions or comments, feel free to reach out! You can tweet us, open an issue on GitHub. Come say hi on our Matrix channel or IRC (#cryptpad on irc.freenode.net), or send us an email.';
- out.main_info = "
Collaborate in Confidence
Grow your ideas together with shared documents while Zero Knowledge technology secures your privacy; even from us.";
+ out.main_info = "
Collaborate in Confidence
Grow your ideas together with shared documents while Zero Knowledge technology secures your privacy; even from us.";
out.main_catch_phrase = "The Zero Knowledge Cloud";
out.main_howitworks = 'How It Works';
@@ -543,6 +545,7 @@ define(function () {
out.main_whiteboardPad = 'Whiteboard';
out.main_localPads = 'Local Pads';
out.main_yourCryptDrive = 'Your CryptDrive';
+ out.main_footerText = "With CryptPad, you can make quick collaborative documents for taking notes and writing down ideas together.";
out.footer_applications = "Applications";
out.footer_contact = "Contact";
@@ -682,13 +685,13 @@ define(function () {
// Tips
out.tips = {};
- out.tips.lag = "The green icon in the upper right shows the quality of your internet connection to the CryptPad server.";
out.tips.shortcuts = "`ctrl+b`, `ctrl+i` and `ctrl+u` are quick shortcuts for bold, italic and underline.";
out.tips.indent = "In numbered and bulleted lists, you can use tab or shift+tab to quickly increase or decrease indentation.";
- out.tips.title = "You can set the title of your pad by clicking the top center.";
out.tips.store = "Every time you visit a pad, if you're logged in it will be saved to your CryptDrive.";
out.tips.marker = "You can highlight text in a pad using the \"marker\" item in the styles dropdown menu.";
out.tips.driveUpload = "Registered users can upload encrypted files by dragging and dropping them into their CryptDrive.";
+ out.tips.filenames = "You can rename files in your CryptDrive, this name is just for you.";
+ out.tips.drive = "Logged in users can organize their files in their CryptDrive, accessible from the CryptPad icon at the top left of all pads.";
out.feedback_about = "If you're reading this, you were probably curious why CryptPad is requesting web pages when you perform certain actions";
out.feedback_privacy = "We care about your privacy, and at the same time we want CryptPad to be very easy to use. We use this file to figure out which UI features matter to our users, by requesting it along with a parameter specifying which action was taken.";
diff --git a/package.json b/package.json
index a2b893d21..9821b6bdb 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server",
- "version": "1.12.0",
+ "version": "1.13.0",
"dependencies": {
"chainpad-server": "^1.0.1",
"express": "~4.10.1",
diff --git a/www/code/code.less b/www/code/code.less
index 7c39ead2b..36883f377 100644
--- a/www/code/code.less
+++ b/www/code/code.less
@@ -30,6 +30,7 @@ body {
min-width: 20%;
max-width: 80%;
resize: horizontal;
+ font-size: initial;
}
.CodeMirror.fullPage {
//min-width: 100%;
diff --git a/www/code/main.js b/www/code/main.js
index 7ac345fb6..a7e6f1447 100644
--- a/www/code/main.js
+++ b/www/code/main.js
@@ -410,6 +410,7 @@ define([
}
});
+/*
// add the splitter
if (!$iframe.has('.cp-splitter').length) {
var $preview = $iframe.find('#previewContainer');
@@ -437,6 +438,7 @@ define([
});
});
}
+*/
Cryptpad.removeLoadingScreen();
setEditable(true);
diff --git a/www/common/common-file.js b/www/common/common-file.js
index 66e5eaefc..8dcff2081 100644
--- a/www/common/common-file.js
+++ b/www/common/common-file.js
@@ -6,6 +6,23 @@ define([
var Nacl = window.nacl;
var module = {};
+ var blobToArrayBuffer = function (blob, cb) {
+ var reader = new FileReader();
+ reader.onloadend = function () {
+ cb(void 0, this.result);
+ };
+ reader.readAsArrayBuffer(blob);
+ };
+
+ var arrayBufferToString = function (AB) {
+ try {
+ return Nacl.util.encodeBase64(new Uint8Array(AB));
+ } catch (e) {
+ console.error(e);
+ return null;
+ }
+ };
+
module.create = function (common, config) {
var File = {};
@@ -227,19 +244,33 @@ define([
queue.next();
};
- var handleFile = File.handleFile = function (file, e) {
- var reader = new FileReader();
- reader.onloadend = function () {
+ var handleFile = File.handleFile = function (file, e, thumbnail) {
+ var thumb;
+ var finish = function (arrayBuffer) {
+ var metadata = {
+ name: file.name,
+ type: file.type,
+ };
+ if (thumb) { metadata.thumbnail = thumb; }
queue.push({
- blob: this.result,
- metadata: {
- name: file.name,
- type: file.type,
- },
+ blob: arrayBuffer,
+ metadata: metadata,
dropEvent: e
});
};
- reader.readAsArrayBuffer(file);
+
+ var processFile = function () {
+ blobToArrayBuffer(file, function (e, buffer) {
+ finish(buffer);
+ });
+ };
+
+ if (!thumbnail) { return void processFile(); }
+ blobToArrayBuffer(thumbnail, function (e, buffer) {
+ if (e) { console.error(e); }
+ thumb = arrayBufferToString(buffer);
+ processFile();
+ });
};
var onFileDrop = File.onFileDrop = function (file, e) {
diff --git a/www/common/common-messaging.js b/www/common/common-messaging.js
index f92eaed33..e4f2d20e3 100644
--- a/www/common/common-messaging.js
+++ b/www/common/common-messaging.js
@@ -256,7 +256,7 @@ define([
var $friend = ui.getFriend(curvePublic);
var $chat = ui.getChannel(curvePublic);
$friend.remove();
- $chat.remove();
+ if ($chat) { $chat.remove(); }
ui.showInfo();
};
@@ -892,7 +892,7 @@ define([
var addToFriendList = Msg.addToFriendList = function (common, data, cb) {
var proxy = common.getProxy();
var friends = getFriendList(proxy);
- var pubKey = data.curvePublic;
+ var pubKey = data.curvePublic; // todo validata data
if (pubKey === proxy.curvePublic) { return void cb("E_MYKEY"); }
@@ -938,7 +938,7 @@ define([
var todo = function (yes) {
if (yes) {
pending[sender] = msgData;
- msg = ["FRIEND_REQ_OK", chan, createData(common, msgData.channel)];
+ msg = ["FRIEND_REQ_OK", chan, createData(proxy, msgData.channel)];
}
msgStr = Crypto.encrypt(JSON.stringify(msg), key);
network.sendto(sender, msgStr);
@@ -1005,7 +1005,7 @@ define([
if (!parsed.hashData) { return; }
// Message
var chan = parsed.hashData.channel;
- var myData = createData(common);
+ var myData = createData(common.getProxy());
var msg = ["FRIEND_REQ", chan, myData];
// Encryption
var keyStr = parsed.hashData.key;
diff --git a/www/common/common-realtime.js b/www/common/common-realtime.js
index d592ae70e..5b0483008 100644
--- a/www/common/common-realtime.js
+++ b/www/common/common-realtime.js
@@ -8,6 +8,8 @@ define([
var BAD_STATE_TIMEOUT = typeof(AppConfig.badStateTimeout) === 'number'?
AppConfig.badStateTimeout: 30000;
+ var connected = false;
+
/*
TODO make this not blow up when disconnected or lagging...
*/
@@ -20,6 +22,7 @@ define([
}
var to = setTimeout(function () {
+ if (!connected) { return; }
realtime.abort();
// don't launch more than one popup
if (common.infiniteSpinnerDetected) { return; }
@@ -38,5 +41,10 @@ define([
}, 0);
};
+ common.setConnectionState = function (bool) {
+ if (typeof(bool) !== 'boolean') { return; }
+ connected = bool;
+ };
+
return common;
});
diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js
new file mode 100644
index 000000000..0e739699b
--- /dev/null
+++ b/www/common/common-thumbnail.js
@@ -0,0 +1,51 @@
+define([
+ '/bower_components/tweetnacl/nacl-fast.min.js',
+], function () {
+ var Nacl = window.nacl;
+ var Thumb = {
+ dimension: 150, // thumbnails are all 150px
+ };
+
+ // create thumbnail image from metadata
+ // return an img tag, or undefined if anything goes wrong
+ Thumb.fromMetadata = function (metadata) {
+ if (!metadata || typeof(metadata) !== 'object' || !metadata.thumbnail) { return; }
+ try {
+ var u8 = Nacl.util.decodeBase64(metadata.thumbnail);
+ var blob = new Blob([u8], {
+ type: 'image/png'
+ });
+ var url = URL.createObjectURL(blob);
+ var img = new Image();
+ img.src = url;
+ img.width = Thumb.dimension;
+ img.height = Thumb.dimension;
+ return img;
+ } catch (e) {
+ console.error(e);
+ return;
+ }
+ };
+
+ // assumes that your canvas is square
+ // nodeback returning blob
+ Thumb.fromCanvas = function (canvas, cb) {
+ canvas = canvas;
+ var c2 = document.createElement('canvas');
+ var d = Thumb.dimension;
+ c2.width = d;
+ c2.height = 2;
+
+ var ctx = c2.getContext('2d');
+ ctx.drawImage(canvas, 0, 0, d, d);
+ c2.toBlob(function (blob) {
+ cb(void 0, blob);
+ });
+ };
+
+ Thumb.fromVideo = function (video, cb) {
+ cb = cb; // WIP
+ };
+
+ return Thumb;
+});
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index defca3a59..88ad0fde7 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -571,6 +571,7 @@ define([
_onDisplayNameChanged.forEach(function (h) {
h(newName, isLocal);
});
+ common.clearTooltips();
};
// STORAGE
@@ -1848,12 +1849,18 @@ define([
Store.ready(function (err, storeObj) {
store = common.store = env.store = storeObj;
-
common.addDirectMessageHandler(common);
var proxy = getProxy();
var network = getNetwork();
+ network.on('disconnect', function () {
+ Realtime.setConnectionState(false);
+ });
+ network.on('reconnect', function () {
+ Realtime.setConnectionState(true);
+ });
+
if (Object.keys(proxy).length === 1) {
feedback("FIRST_APP_USE", true);
}
diff --git a/www/common/curve.js b/www/common/curve.js
index 0c39ba421..98790f385 100644
--- a/www/common/curve.js
+++ b/www/common/curve.js
@@ -50,25 +50,35 @@ define([
};
Curve.deriveKeys = function (theirs, mine) {
- var pub = decodeBase64(theirs);
- var secret = decodeBase64(mine);
+ try {
+ var pub = decodeBase64(theirs);
+ var secret = decodeBase64(mine);
- var sharedSecret = Nacl.box.before(pub, secret);
- var salt = decodeUTF8('CryptPad.signingKeyGenerationSalt');
+ var sharedSecret = Nacl.box.before(pub, secret);
+ var salt = decodeUTF8('CryptPad.signingKeyGenerationSalt');
- // 64 uint8s
- var hash = Nacl.hash(concatenateUint8s([salt, sharedSecret]));
- var signKp = Nacl.sign.keyPair.fromSeed(hash.subarray(0, 32));
- var cryptKey = hash.subarray(32, 64);
+ // 64 uint8s
+ var hash = Nacl.hash(concatenateUint8s([salt, sharedSecret]));
+ var signKp = Nacl.sign.keyPair.fromSeed(hash.subarray(0, 32));
+ var cryptKey = hash.subarray(32, 64);
- return {
- cryptKey: encodeBase64(cryptKey),
- signKey: encodeBase64(signKp.secretKey),
- validateKey: encodeBase64(signKp.publicKey)
- };
+ return {
+ cryptKey: encodeBase64(cryptKey),
+ signKey: encodeBase64(signKp.secretKey),
+ validateKey: encodeBase64(signKp.publicKey)
+ };
+ } catch (e) {
+ console.error('invalid keys or other problem deriving keys');
+ console.error(e);
+ return null;
+ }
};
Curve.createEncryptor = function (keys) {
+ if (!keys || typeof(keys) !== 'object') {
+ return void console.error("invalid input for createEncryptor");
+ }
+
var cryptKey = decodeBase64(keys.cryptKey);
var signKey = decodeBase64(keys.signKey);
var validateKey = decodeBase64(keys.validateKey);
diff --git a/www/common/media-tag.js b/www/common/media-tag.js
index b43220c84..042cb5200 100644
--- a/www/common/media-tag.js
+++ b/www/common/media-tag.js
@@ -1 +1 @@
-(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory();else if(typeof define==="function"&&define.amd)define([],factory);else if(typeof exports==="object")exports["MediaTag"]=factory();else root["MediaTag"]=factory()})(this,function(){return function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.i=function(value){return value};__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{configurable:false,enumerable:true,get:getter})}};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module["default"]}:function getModuleExports(){return module};__webpack_require__.d(getter,"a",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p="";return __webpack_require__(__webpack_require__.s=95)}([function(module,exports,__webpack_require__){"use strict";var Identifier={IMAGE:"image",AUDIO:"audio",VIDEO:"video",PDF:"pdf",DASH:"dash",DOWNLOAD:"download",CRYPTO:"crypto",CLEAR_KEY:"clear-key",MEDIA_OBJECT:"media-object"};module.exports=Identifier},function(module,exports,__webpack_require__){"use strict";var Type={MATCHER:"matcher",RENDERER:"renderer",FILTER:"filter",SANITIZER:"sanitizer"};module.exports=Type},function(module,exports,__webpack_require__){"use strict";var ProcessingEngine=__webpack_require__(34);var MatchingEngine=__webpack_require__(33);var PluginStore=__webpack_require__(53);var UriStore=__webpack_require__(54);var MediaTag=__webpack_require__(31);function MediaTagAPI(elements){if(elements instanceof Array){var mediaObjects=[];elements.forEach(function(element){if(element.mediaObject){mediaObjects.push(element.mediaObject)}else{var _mediaTag=new MediaTag(element,MediaTagAPI.processingEngine);_mediaTag.mediaObjects.forEach(function(mediaObject){mediaObjects.push(MediaTagAPI.processingEngine.start(mediaObject))})}});return mediaObjects}var element=elements;var mediaTag=new MediaTag(element,MediaTagAPI.processingEngine);mediaTag.mediaObjects.forEach(function(mediaObject){MediaTagAPI.processingEngine.start(mediaObject)})}MediaTagAPI.pluginStore=MediaTagAPI.pluginStore||new PluginStore;MediaTagAPI.uriStore=MediaTagAPI.uriStore||new UriStore("../plugins");MediaTagAPI.processingEngine=MediaTagAPI.processingEngine||new ProcessingEngine(MediaTagAPI.pluginStore);MediaTagAPI.matchingEngine=MediaTagAPI.matchingEngine||new MatchingEngine(MediaTagAPI.pluginStore,MediaTagAPI.uriStore);MediaTagAPI.loadingEngine=null;module.exports=MediaTagAPI},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i=0){CryptoFilter.mediaTypes.splice(index,1)}};CryptoFilter.removeAllAllowedMediaTypes=function(mediaTypes){mediaTypes.forEach(function(mediaType){CryptoFilter.removeAllowedMediaType(mediaType)})};CryptoFilter.isAllowedMediaType=function(mediaType){return CryptoFilter.mediaTypes.some(function(type){return type===mediaType})};module.exports=CryptoFilter},,function(module,exports,__webpack_require__){"use strict";var hide=__webpack_require__(13);var show=__webpack_require__(14);module.exports=function(mediaObjectToActivate,mediaTag){mediaTag.mediaObjects.forEach(function(mediaObject){hide(mediaObject)});mediaTag.activeMediaObject=mediaObjectToActivate;show(mediaObjectToActivate)}},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i0}}]);return AttributesObject}();module.exports=AttributesObject},function(module,exports,__webpack_require__){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return call&&(typeof call==="object"||typeof call==="function")?call:self}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass)}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass}var Errors={PluginExists:function(_Error){_inherits(PluginExists,_Error);function PluginExists(objPlugin){_classCallCheck(this,PluginExists);return _possibleConstructorReturn(this,(PluginExists.__proto__||Object.getPrototypeOf(PluginExists)).call(this,'Plugin with same "'+objPlugin.identifier+'" identifier found.'))}return PluginExists}(Error),TypeNotFound:function(_Error2){_inherits(TypeNotFound,_Error2);function TypeNotFound(){_classCallCheck(this,TypeNotFound);return _possibleConstructorReturn(this,(TypeNotFound.__proto__||Object.getPrototypeOf(TypeNotFound)).call(this,"Media Tag could not find the content type of an instance.}."))}return TypeNotFound}(Error),FilterExists:function(_Error3){_inherits(FilterExists,_Error3);function FilterExists(filter){_classCallCheck(this,FilterExists);return _possibleConstructorReturn(this,(FilterExists.__proto__||Object.getPrototypeOf(FilterExists)).call(this,'Filter with same "'+filter.identifier+' identifier found."'))}return FilterExists}(Error),FetchFail:function(_Error4){_inherits(FetchFail,_Error4);function FetchFail(response){_classCallCheck(this,FetchFail);return _possibleConstructorReturn(this,(FetchFail.__proto__||Object.getPrototypeOf(FetchFail)).call(this,'Could not fetch "'+response.url+'", received "'+response.status+": "+response.statusText+'".'))}return FetchFail}(Error),InvalidCryptoKey:function(_Error5){_inherits(InvalidCryptoKey,_Error5);function InvalidCryptoKey(){_classCallCheck(this,InvalidCryptoKey);return _possibleConstructorReturn(this,(InvalidCryptoKey.__proto__||Object.getPrototypeOf(InvalidCryptoKey)).call(this,"Invalid cryptographic key."))}return InvalidCryptoKey}(Error),InvalidCryptoLib:function(_Error6){_inherits(InvalidCryptoLib,_Error6);function InvalidCryptoLib(){_classCallCheck(this,InvalidCryptoLib);return _possibleConstructorReturn(this,(InvalidCryptoLib.__proto__||Object.getPrototypeOf(InvalidCryptoLib)).call(this,"Invalid cryptographic algorithm name."))}return InvalidCryptoLib}(Error),FailedCrypto:function(_Error7){_inherits(FailedCrypto,_Error7);function FailedCrypto(err){_classCallCheck(this,FailedCrypto);return _possibleConstructorReturn(this,(FailedCrypto.__proto__||Object.getPrototypeOf(FailedCrypto)).call(this,"Failed to decrypt file"+(err&&err.message?" "+err.message:"")+"."))}return FailedCrypto}(Error)};module.exports=Errors},function(module,exports,__webpack_require__){"use strict";var Permission={ALLOWED:0,REQUIRED:1,FORBIDDEN:2};module.exports=Permission},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i MediaTag cannot find a plugin able to renderer your content ","Download");MediaTag.processingEngine.setDefaultPlugin(defaultPlugin);MediaTag.CryptoFilter=CryptoFilter;var allowedMediaTypes=["image/png","image/jpeg","image/jpg","image/gif","audio/mp3","audio/ogg","audio/wav","audio/webm","video/mp4","video/ogg","video/webm","application/pdf","application/dash+xml","download"];MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes);var Configuration=__webpack_require__(29);var Permission=__webpack_require__(17);var Identifier=__webpack_require__(0);var configuration=new Configuration;MediaTag.PdfPlugin=PdfPlugin;MediaTag.PdfPlugin.viewer="/pdfjs/web/viewer.html";MediaTag.processingEngine.configure(configuration);module.exports=MediaTag},function(module,exports,__webpack_require__){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return call&&(typeof call==="object"||typeof call==="function")?call:self}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass)}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass}var Type=__webpack_require__(1);var Occurrence=__webpack_require__(5);var Plugin=__webpack_require__(6);var Sanitizer=function(_Plugin){_inherits(Sanitizer,_Plugin);function Sanitizer(identifier){_classCallCheck(this,Sanitizer);return _possibleConstructorReturn(this,(Sanitizer.__proto__||Object.getPrototypeOf(Sanitizer)).call(this,identifier,Type.SANITIZER,Occurrence.EVERY))}return Sanitizer}(Plugin);module.exports=Sanitizer},,,function(module,exports,__webpack_require__){"use strict";var Action={clear:__webpack_require__(24),show:__webpack_require__(14),hide:__webpack_require__(13),upgrade:__webpack_require__(26),downgrade:__webpack_require__(25),activate:__webpack_require__(9)};module.exports=Action},function(module,exports,__webpack_require__){"use strict";module.exports=function(mediaObject){mediaObject.clearContents()}},function(module,exports,__webpack_require__){"use strict";var activate=__webpack_require__(9);module.exports=function(mediaTag){var index=mediaTag.mediaObjects.indexOf(mediaTag.activeMediaObject);if(index>0){activate(mediaTag.mediaObjects[index-1],mediaTag)}}},function(module,exports,__webpack_require__){"use strict";var activate=__webpack_require__(9);module.exports=function(mediaTag){var index=mediaTag.mediaObjects.indexOf(mediaTag.activeMediaObject);if(index1){if(PARANOIA){if(typeof N[l]!=="number"){throw new Error("E_UNSAFE_TYPE")}if(N[l]>255){throw new Error("E_OUT_OF_BOUNDS")}}if(N[l]!==255){return void N[l]++}N[l]=0;if(l===0){throw new Error("E_NONCE_TOO_LARGE")}}}},{key:"encodePrefix",value:function encodePrefix(p){return[65280,255].map(function(n,i){return(p&n)>>(1-i)*8})}},{key:"decodePrefix",value:function decodePrefix(A){return A[0]<<8|A[1]}},{key:"joinChunks",value:function joinChunks(chunks){return new Blob(chunks)}},{key:"slice",value:function slice(u8){return Array.prototype.slice.call(u8)}},{key:"getRandomKeyStr",value:function getRandomKeyStr(){var Nacl=window.nacl;var rdm=Nacl.randomBytes(18);return Nacl.util.encodeBase64(rdm)}},{key:"getKeyFromStr",value:function getKeyFromStr(str){return window.nacl.util.decodeBase64(str)}},{key:"encrypt",value:function encrypt(){}},{key:"decrypt",value:function decrypt(u8,key,done){var Nacl=window.nacl;var progress=function progress(offset){var ev=new Event("decryptionProgress");ev.percent=offset/u8.length*100;window.document.dispatchEvent(ev)};var nonce=Cryptopad.createNonce();var i=0;var prefix=u8.subarray(0,2);var metadataLength=Cryptopad.decodePrefix(prefix);var res={metadata:undefined};var metaBox=new Uint8Array(u8.subarray(2,2+metadataLength));var metaChunk=Nacl.secretbox.open(metaBox,nonce,key);Cryptopad.increment(nonce);try{res.metadata=JSON.parse(Nacl.util.encodeUTF8(metaChunk))}catch(e){return done("E_METADATA_DECRYPTION")}if(!res.metadata){return done("NO_METADATA")}var takeChunk=function takeChunk(cb){setTimeout(function(){var start=i*cypherChunkLength+2+metadataLength;var end=start+cypherChunkLength;i++;var box=new Uint8Array(u8.subarray(start,end));var plaintext=Nacl.secretbox.open(box,nonce,key);Cryptopad.increment(nonce);if(!plaintext){return void cb("DECRYPTION_FAILURE")}progress(Math.min(end,u8.length));cb(void 0,plaintext)})};var chunks=[];var again=function again(){takeChunk(function(e,plaintext){if(e){return setTimeout(function(){done(e)})}if(plaintext){if(i*cypherChunkLength1){return array[0]}return window.location.protocol}},{key:"hostname",value:function hostname(AttributeObject){var array=AttributeObject.getAttribute("src").split("://");if(array.length>1){return array[1].split("/")[0]}return window.location.hostname}},{key:"source",value:function source(AttributeObject){var source=AttributeObject.getAttribute("src");return source}},{key:"schemes",value:function schemes(AttributeObject){return/\w+:/.exec(AttributeObject.getAttribute("src"))}},{key:"sources",value:function sources(AttributeObject){var sources=AttributeObject.getAttribute("sources")||AttributeObject.getAttribute("srcs");if(sources){return JSON.parse(sources)}return null}},{key:"actions",value:function actions(AttributeObject){var actions=AttributeObject.getAttribute("actions");if(actions){return JSON.parse(actions)}return null}},{key:"parse",value:function parse(AttributeObject){return{protocol:Parser.protocol(AttributeObject),hostname:Parser.hostname(AttributeObject),src:Parser.source(AttributeObject),type:Parser.type(AttributeObject),extension:Parser.extension(AttributeObject),mime:Parser.mime(AttributeObject),sources:Parser.sources(AttributeObject),actions:Parser.actions(AttributeObject)}}}]);return Parser}();module.exports=Parser},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i=ProcessingEngine.STACK_LIMIT){console.error(this.snapshots[stackId]);throw new Error("Plugin stack size exceed")}if(this.snapshots[stackId].length>=ProcessingEngine.SNAPSHOT_LIMIT){console.error(this.snapshots[stackId]);throw new Error("Plugin snapshots size exceed")}var rendererCount=0;this.stacks[stackId].forEach(function(plugin){if(plugin.type===Type.RENDERER){rendererCount++}});if(rendererCount>1){console.error(this.snapshots[stackId]);throw new Error("More of one renderer in the stack")}if(this.stacks[stackId].length===0&&!this.stats[stackId][Type.RENDERER]){if(!this.defaultPlugin){throw new Error("No default plugin assignated")}this.stacks[stackId].unshift(this.defaultPlugin)}}},{key:"return",value:function _return(mediaObject){var stackId=mediaObject.getId();var plugin=this.unstack(mediaObject);if(!plugin){return}try{if(!this.stats[stackId]){this.stats[stackId]={}}if(this.stats[stackId][plugin.type]){this.stats[stackId][plugin.type]+=1}else{this.stats[stackId][plugin.type]=1}}catch(err){console.error(err,this.snapshots[stackId])}if(this.stacks[stackId].length===0&&plugin.type===Type.RENDERER){this.run(mediaObject)}else if(plugin.type!==Type.SANITIZER){this.fill(mediaObject)}this.snapshot(mediaObject);this.check(mediaObject);this.run(mediaObject)}},{key:"process",value:function process(mediaObject){var stackId=mediaObject.getId();var size=this.stacks[stackId].length;var plugin=this.stacks[stackId][size-1];if(plugin){plugin.process(mediaObject)}else{console.log(this.stacks);throw new Error("Impossible to run a undefined plugin")}}},{key:"isStacked",value:function isStacked(mediaObject,plugin){var stackId=mediaObject.getId();if(this.stacks[stackId]){if(this.stacks[stackId].includes(plugin)){return true}}return false}},{key:"setDefaultPlugin",value:function setDefaultPlugin(plugin){this.defaultPlugin=plugin}}]);return ProcessingEngine}();ProcessingEngine.STACK_LIMIT=100;ProcessingEngine.SNAPSHOT_LIMIT=100;module.exports=ProcessingEngine},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i=0){CryptoFilter.mediaTypes.splice(index,1)}};CryptoFilter.removeAllAllowedMediaTypes=function(mediaTypes){mediaTypes.forEach(function(mediaType){CryptoFilter.removeAllowedMediaType(mediaType)})};CryptoFilter.isAllowedMediaType=function(mediaType){return CryptoFilter.mediaTypes.some(function(type){return type===mediaType})};module.exports=CryptoFilter},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i0}}]);return AttributesObject}();module.exports=AttributesObject},function(module,exports,__webpack_require__){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return call&&(typeof call==="object"||typeof call==="function")?call:self}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass)}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass}var Errors={PluginExists:function(_Error){_inherits(PluginExists,_Error);function PluginExists(objPlugin){_classCallCheck(this,PluginExists);return _possibleConstructorReturn(this,(PluginExists.__proto__||Object.getPrototypeOf(PluginExists)).call(this,'Plugin with same "'+objPlugin.identifier+'" identifier found.'))}return PluginExists}(Error),TypeNotFound:function(_Error2){_inherits(TypeNotFound,_Error2);function TypeNotFound(){_classCallCheck(this,TypeNotFound);return _possibleConstructorReturn(this,(TypeNotFound.__proto__||Object.getPrototypeOf(TypeNotFound)).call(this,"Media Tag could not find the content type of an instance.}."))}return TypeNotFound}(Error),FilterExists:function(_Error3){_inherits(FilterExists,_Error3);function FilterExists(filter){_classCallCheck(this,FilterExists);return _possibleConstructorReturn(this,(FilterExists.__proto__||Object.getPrototypeOf(FilterExists)).call(this,'Filter with same "'+filter.identifier+' identifier found."'))}return FilterExists}(Error),FetchFail:function(_Error4){_inherits(FetchFail,_Error4);function FetchFail(response){_classCallCheck(this,FetchFail);return _possibleConstructorReturn(this,(FetchFail.__proto__||Object.getPrototypeOf(FetchFail)).call(this,'Could not fetch "'+response.url+'", received "'+response.status+": "+response.statusText+'".'))}return FetchFail}(Error),InvalidCryptoKey:function(_Error5){_inherits(InvalidCryptoKey,_Error5);function InvalidCryptoKey(){_classCallCheck(this,InvalidCryptoKey);return _possibleConstructorReturn(this,(InvalidCryptoKey.__proto__||Object.getPrototypeOf(InvalidCryptoKey)).call(this,"Invalid cryptographic key."))}return InvalidCryptoKey}(Error),InvalidCryptoLib:function(_Error6){_inherits(InvalidCryptoLib,_Error6);function InvalidCryptoLib(){_classCallCheck(this,InvalidCryptoLib);return _possibleConstructorReturn(this,(InvalidCryptoLib.__proto__||Object.getPrototypeOf(InvalidCryptoLib)).call(this,"Invalid cryptographic algorithm name."))}return InvalidCryptoLib}(Error),FailedCrypto:function(_Error7){_inherits(FailedCrypto,_Error7);function FailedCrypto(err){_classCallCheck(this,FailedCrypto);return _possibleConstructorReturn(this,(FailedCrypto.__proto__||Object.getPrototypeOf(FailedCrypto)).call(this,"Failed to decrypt file"+(err&&err.message?" "+err.message:"")+"."))}return FailedCrypto}(Error)};module.exports=Errors},function(module,exports,__webpack_require__){"use strict";var MediaTag=__webpack_require__(21);var ImagePlugin=__webpack_require__(43);var AudioPlugin=__webpack_require__(44);var VideoPlugin=__webpack_require__(45);var PdfPlugin=__webpack_require__(46);var DashPlugin=__webpack_require__(47);var DownloadPlugin=__webpack_require__(48);var CryptoFilter=__webpack_require__(7);var ClearKeyFilter=__webpack_require__(49);var MediaObjectSanitizer=__webpack_require__(50);MediaTag.pluginStore.store(new ImagePlugin);MediaTag.pluginStore.store(new AudioPlugin);MediaTag.pluginStore.store(new VideoPlugin);MediaTag.pluginStore.store(new PdfPlugin);MediaTag.pluginStore.store(new DashPlugin);MediaTag.pluginStore.store(new DownloadPlugin);MediaTag.pluginStore.store(new CryptoFilter);MediaTag.pluginStore.store(new ClearKeyFilter);MediaTag.pluginStore.store(new MediaObjectSanitizer);var Salsa20Poly1305Algorithm=__webpack_require__(51);var CryptpadAlgorithm=__webpack_require__(52);CryptoFilter.functionStore.store("salsa20poly1305",Salsa20Poly1305Algorithm);CryptoFilter.functionStore.store("cryptpad",CryptpadAlgorithm);var defaultPlugin=new DownloadPlugin("
MediaTag cannot find a plugin able to renderer your content
","Download");MediaTag.processingEngine.setDefaultPlugin(defaultPlugin);MediaTag.CryptoFilter=CryptoFilter;var allowedMediaTypes=["image/png","image/jpeg","image/jpg","image/gif","audio/mp3","audio/ogg","audio/wav","audio/webm","video/mp4","video/ogg","video/webm","application/pdf","application/dash+xml","download"];MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes);var Configuration=__webpack_require__(53);var Permission=__webpack_require__(14);var Identifier=__webpack_require__(0);var configuration=new Configuration;MediaTag.PdfPlugin=PdfPlugin;MediaTag.PdfPlugin.viewer="/pdfjs/web/viewer.html";MediaTag.processingEngine.configure(configuration);module.exports=MediaTag},function(module,exports,__webpack_require__){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return call&&(typeof call==="object"||typeof call==="function")?call:self}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass)}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass}var Type=__webpack_require__(1);var Occurrence=__webpack_require__(5);var Plugin=__webpack_require__(6);var Sanitizer=function(_Plugin){_inherits(Sanitizer,_Plugin);function Sanitizer(identifier){_classCallCheck(this,Sanitizer);return _possibleConstructorReturn(this,(Sanitizer.__proto__||Object.getPrototypeOf(Sanitizer)).call(this,identifier,Type.SANITIZER,Occurrence.EVERY))}return Sanitizer}(Plugin);module.exports=Sanitizer},function(module,exports,__webpack_require__){"use strict";var ImageMatcher=__webpack_require__(22);var AudioMatcher=__webpack_require__(23);var VideoMatcher=__webpack_require__(24);var PdfMatcher=__webpack_require__(25);var DashMatcher=__webpack_require__(26);var DownloadMatcher=__webpack_require__(27);var CryptoMatcher=__webpack_require__(28);var ClearKeyMatcher=__webpack_require__(29);var MediaObjectMatcher=__webpack_require__(30);var MediaTag=__webpack_require__(2);MediaTag.pluginStore.store(new ImageMatcher);MediaTag.pluginStore.store(new AudioMatcher);MediaTag.pluginStore.store(new VideoMatcher);MediaTag.pluginStore.store(new PdfMatcher);MediaTag.pluginStore.store(new DashMatcher);MediaTag.pluginStore.store(new DownloadMatcher);MediaTag.pluginStore.store(new CryptoMatcher);MediaTag.pluginStore.store(new ClearKeyMatcher);MediaTag.pluginStore.store(new MediaObjectMatcher);module.exports=MediaTag},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i=ProcessingEngine.STACK_LIMIT){console.error(this.snapshots[stackId]);throw new Error("Plugin stack size exceed")}if(this.snapshots[stackId].length>=ProcessingEngine.SNAPSHOT_LIMIT){console.error(this.snapshots[stackId]);throw new Error("Plugin snapshots size exceed")}var rendererCount=0;this.stacks[stackId].forEach(function(plugin){if(plugin.type===Type.RENDERER){rendererCount++}});if(rendererCount>1){console.error(this.snapshots[stackId]);throw new Error("More of one renderer in the stack")}if(this.stacks[stackId].length===0&&!this.stats[stackId][Type.RENDERER]){if(!this.defaultPlugin){throw new Error("No default plugin assignated")}this.stacks[stackId].unshift(this.defaultPlugin)}}},{key:"return",value:function _return(mediaObject){var stackId=mediaObject.getId();var plugin=this.unstack(mediaObject);if(!plugin){return}try{if(!this.stats[stackId]){this.stats[stackId]={}}if(this.stats[stackId][plugin.type]){this.stats[stackId][plugin.type]+=1}else{this.stats[stackId][plugin.type]=1}}catch(err){console.error(err,this.snapshots[stackId])}if(this.stacks[stackId].length===0&&plugin.type===Type.RENDERER){this.run(mediaObject)}else if(plugin.type!==Type.SANITIZER){this.fill(mediaObject)}this.snapshot(mediaObject);this.check(mediaObject);this.run(mediaObject)}},{key:"process",value:function process(mediaObject){var stackId=mediaObject.getId();var size=this.stacks[stackId].length;var plugin=this.stacks[stackId][size-1];if(plugin){plugin.process(mediaObject)}else{console.log(this.stacks);throw new Error("Impossible to run a undefined plugin")}}},{key:"isStacked",value:function isStacked(mediaObject,plugin){var stackId=mediaObject.getId();if(this.stacks[stackId]){if(this.stacks[stackId].includes(plugin)){return true}}return false}},{key:"setDefaultPlugin",value:function setDefaultPlugin(plugin){this.defaultPlugin=plugin}}]);return ProcessingEngine}();ProcessingEngine.STACK_LIMIT=100;ProcessingEngine.SNAPSHOT_LIMIT=100;module.exports=ProcessingEngine},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i0){activate(mediaTag.mediaObjects[index-1],mediaTag)}}},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i1){return array[0]}return window.location.protocol}},{key:"hostname",value:function hostname(AttributeObject){var array=AttributeObject.getAttribute("src").split("://");if(array.length>1){return array[1].split("/")[0]}return window.location.hostname}},{key:"source",value:function source(AttributeObject){var source=AttributeObject.getAttribute("src");return source}},{key:"schemes",value:function schemes(AttributeObject){return/\w+:/.exec(AttributeObject.getAttribute("src"))}},{key:"sources",value:function sources(AttributeObject){var sources=AttributeObject.getAttribute("sources")||AttributeObject.getAttribute("srcs");if(sources){return JSON.parse(sources)}return null}},{key:"actions",value:function actions(AttributeObject){var actions=AttributeObject.getAttribute("actions");if(actions){return JSON.parse(actions)}return null}},{key:"parse",value:function parse(AttributeObject){return{protocol:Parser.protocol(AttributeObject),hostname:Parser.hostname(AttributeObject),src:Parser.source(AttributeObject),type:Parser.type(AttributeObject),extension:Parser.extension(AttributeObject),mime:Parser.mime(AttributeObject),sources:Parser.sources(AttributeObject),actions:Parser.actions(AttributeObject)}}}]);return Parser}();module.exports=Parser},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i1){if(PARANOIA){if(typeof N[l]!=="number"){throw new Error("E_UNSAFE_TYPE")}if(N[l]>255){throw new Error("E_OUT_OF_BOUNDS")}}if(N[l]!==255){return void N[l]++}N[l]=0;if(l===0){throw new Error("E_NONCE_TOO_LARGE")}}}},{key:"encodePrefix",value:function encodePrefix(p){return[65280,255].map(function(n,i){return(p&n)>>(1-i)*8})}},{key:"decodePrefix",value:function decodePrefix(A){return A[0]<<8|A[1]}},{key:"joinChunks",value:function joinChunks(chunks){return new Blob(chunks)}},{key:"slice",value:function slice(u8){return Array.prototype.slice.call(u8)}},{key:"getRandomKeyStr",value:function getRandomKeyStr(){var Nacl=window.nacl;var rdm=Nacl.randomBytes(18);return Nacl.util.encodeBase64(rdm)}},{key:"getKeyFromStr",value:function getKeyFromStr(str){return window.nacl.util.decodeBase64(str)}},{key:"encrypt",value:function encrypt(){}},{key:"decrypt",value:function decrypt(u8,key,done){var Nacl=window.nacl;var progress=function progress(offset){var ev=new Event("decryptionProgress");ev.percent=offset/u8.length*100;window.document.dispatchEvent(ev)};var nonce=Cryptopad.createNonce();var i=0;var prefix=u8.subarray(0,2);var metadataLength=Cryptopad.decodePrefix(prefix);var res={metadata:undefined};var metaBox=new Uint8Array(u8.subarray(2,2+metadataLength));var metaChunk=Nacl.secretbox.open(metaBox,nonce,key);Cryptopad.increment(nonce);try{res.metadata=JSON.parse(Nacl.util.encodeUTF8(metaChunk))}catch(e){return done("E_METADATA_DECRYPTION")}if(!res.metadata){return done("NO_METADATA")}var takeChunk=function takeChunk(cb){setTimeout(function(){var start=i*cypherChunkLength+2+metadataLength;var end=start+cypherChunkLength;i++;var box=new Uint8Array(u8.subarray(start,end));var plaintext=Nacl.secretbox.open(box,nonce,key);Cryptopad.increment(nonce);if(!plaintext){return void cb("DECRYPTION_FAILURE")}progress(Math.min(end,u8.length));cb(void 0,plaintext)})};var chunks=[];var again=function again(){takeChunk(function(e,plaintext){if(e){return setTimeout(function(){done(e)})}if(plaintext){if(i*cypherChunkLength 1 && arguments[1] !== undefined ? arguments[1] : 'document.pdf';
-
- if (isDataSchema(url)) {
- console.warn('getPDFFileNameFromURL: ' + 'ignoring "data:" URL for performance reasons.');
- return defaultFilename;
- }
- var reURI = /^(?:(?:[^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
- var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
- var splitURI = reURI.exec(url);
- var suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
- if (suggestedFilename) {
- suggestedFilename = suggestedFilename[0];
- if (suggestedFilename.indexOf('%') !== -1) {
- try {
- suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
- } catch (e) {}
- }
+ var query;
+ var title;
+ if (/\#/.test(url)) {
+ url.replace(/\#(.*)$/, function (all, t) {
+ title = t;
+ });
}
- return suggestedFilename || defaultFilename;
+ return title || 'document.pdf';
}
function normalizeWheelEventDelta(evt) {
var delta = Math.sqrt(evt.deltaX * evt.deltaX + evt.deltaY * evt.deltaY);
@@ -1192,11 +1181,13 @@ var PDFViewerApplication = {
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
this.url = url;
this.baseUrl = url.split('#')[0];
- var title = (0, _ui_utils.getPDFFileNameFromURL)(url, '');
+
+ var title = _ui_utils.getPDFFileNameFromURL(url);
if (!title) {
try {
title = decodeURIComponent((0, _pdfjsLib.getFilenameFromUrl)(url)) || url;
} catch (e) {
+ console.error(e)
title = url;
}
}
diff --git a/www/file/file.less b/www/file/file.less
index fa6485806..785c5e566 100644
--- a/www/file/file.less
+++ b/www/file/file.less
@@ -24,7 +24,7 @@ body {
}
#app.ready {
- background: url('/customize/bg3.jpg') no-repeat center center;
+ //background: url('/customize/bg3.jpg') no-repeat center center;
background-size: cover;
background-position: center;
}
diff --git a/www/file/main.js b/www/file/main.js
index f5e499f18..79bd70af8 100644
--- a/www/file/main.js
+++ b/www/file/main.js
@@ -91,7 +91,14 @@ define([
Title.updateTitle(title || Title.defaultTitle);
toolbar.addElement(['pageTitle'], {pageTitle: title});
- var displayFile = function (ev, sizeMb) {
+ var displayFile = function (ev, sizeMb, CB) {
+ var called_back;
+ var cb = function (e) {
+ if (called_back) { return; }
+ called_back = true;
+ if (CB) { CB(e); }
+ };
+
var $mt = $dlview.find('media-tag');
var cryptKey = secret.keys && secret.keys.fileKeyStr;
var hexFileName = Cryptpad.base64ToHex(secret.channel);
@@ -127,7 +134,7 @@ define([
// make pdfs big
var toolbarHeight = $iframe.find('#toolbar').height();
- $iframe.find('media-tag iframe').css({
+ var $another_iframe = $iframe.find('media-tag iframe').css({
'height': 'calc(100vh - ' + toolbarHeight + 'px)',
'width': '100vw',
'position': 'absolute',
@@ -135,10 +142,19 @@ define([
'left': 0,
'border': 0
});
+
+ if ($another_iframe.length) {
+ $another_iframe.load(function () {
+ cb();
+ });
+ } else {
+ cb();
+ }
})
.on('decryptionError', function (e) {
var error = e.originalEvent;
- Cryptpad.alert(error.message);
+ //Cryptpad.alert(error.message);
+ cb(error.message);
})
.on('decryptionProgress', function (e) {
var progress = e.originalEvent;
@@ -188,7 +204,9 @@ define([
var onClick = function (ev) {
if (decrypting) { return; }
decrypting = true;
- displayFile(ev, sizeMb);
+ displayFile(ev, sizeMb, function (err) {
+ if (err) { Cryptpad.alert(err); }
+ });
};
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
$dlform.find('#dl, #progress').click(onClick);
diff --git a/www/invite/index.html b/www/invite/index.html
index 9aed29ca5..6ee841719 100644
--- a/www/invite/index.html
+++ b/www/invite/index.html
@@ -2,7 +2,7 @@
- Cryptpad: Zero Knowledge, Collaborative Real Time Editing
+ CryptPad: Zero Knowledge, Collaborative Real Time Editing
diff --git a/www/pad/ckeditor-inner.html b/www/pad/ckeditor-inner.html
index 3386430dc..511bd5f40 100644
--- a/www/pad/ckeditor-inner.html
+++ b/www/pad/ckeditor-inner.html
@@ -1,3 +1,3 @@
Rich Text Editor, editor1
\ No newline at end of file
+img,input,textarea{cursor:default}
diff --git a/www/pad/main.js b/www/pad/main.js
index d47c207e7..817607ded 100644
--- a/www/pad/main.js
+++ b/www/pad/main.js
@@ -313,6 +313,10 @@ define([
if (!readOnly && !initializing) {
userDocStateDom.setAttribute("contenteditable", "true"); // lol wtf
}
+ $(userDocStateDom).find('script, applet, object, iframe').remove();
+ $(userDocStateDom).find('a').filter(function (i, x) {
+ return ! /^(https|http|ftp):\/\/[^\s\n]*$/.test(x.getAttribute('href'));
+ }).remove();
var patch = (DD).diff(inner, userDocStateDom);
(DD).apply(inner, patch);
if (readOnly) {
@@ -625,8 +629,10 @@ define([
if (stringify(hjson2) !== stringify(hjson)) {
console.log('err');
console.error("shjson2 !== shjson");
- Cryptpad.errorLoadingScreen(Messages.wrongApp);
- throw new Error();
+ // TODO(cjd): This is removed because the XSS filter in applyHjson()
+ // is applied on incoming content so it causes this to fail.
+ //Cryptpad.errorLoadingScreen(Messages.wrongApp);
+ //throw new Error();
}
}
} else {
diff --git a/www/pad/wysiwygarea-plugin.js b/www/pad/wysiwygarea-plugin.js
index 1abf010ef..d63bc4f10 100644
--- a/www/pad/wysiwygarea-plugin.js
+++ b/www/pad/wysiwygarea-plugin.js
@@ -470,13 +470,16 @@
// CryptPad
var _iframe = window._iframe = iframe.$;
- var fw = this;
+ var fw = this;
+ _iframe.contentWindow.onload = function () {}
var intr = setInterval(function () {
//console.log(_iframe.contentWindow.document.body);
- if (_iframe.contentWindow && _iframe.contentWindow.document && _iframe.contentWindow.document.body) {
- clearInterval(intr);
- CKEDITOR.tools.callFunction(fw._.frameLoadedHandler, _iframe.contentWindow);
- }
+ if (!_iframe.contentWindow) { return; }
+ if (!_iframe.contentWindow.document) { return; }
+ if (_iframe.contentWindow.document.readyState !== 'complete') { return; }
+ if (!_iframe.contentWindow.document.getElementsByTagName('title').length) { return; }
+ clearInterval(intr);
+ CKEDITOR.tools.callFunction(fw._.frameLoadedHandler, _iframe.contentWindow);
}, 10);
return;
diff --git a/www/profile/index.html b/www/profile/index.html
index 9aed29ca5..6ee841719 100644
--- a/www/profile/index.html
+++ b/www/profile/index.html
@@ -2,7 +2,7 @@
- Cryptpad: Zero Knowledge, Collaborative Real Time Editing
+ CryptPad: Zero Knowledge, Collaborative Real Time Editing
diff --git a/www/slide/slide.less b/www/slide/slide.less
index 9e020f98f..8358f849a 100644
--- a/www/slide/slide.less
+++ b/www/slide/slide.less
@@ -36,6 +36,7 @@ h6 { font-size: 24px; }
body {
.CodeMirror {
height: 100%;
+ font-size: initial;
}
.CodeMirror-focused .cm-matchhighlight {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
diff --git a/www/whiteboard/main.js b/www/whiteboard/main.js
index 337cd8794..3871337cd 100644
--- a/www/whiteboard/main.js
+++ b/www/whiteboard/main.js
@@ -11,6 +11,7 @@ define([
'/common/cryptget.js',
'/whiteboard/colors.js',
'/customize/application_config.js',
+ '/common/common-thumbnail.js',
'/bower_components/secure-fabric.js/dist/fabric.min.js',
'/bower_components/file-saver/FileSaver.min.js',
@@ -19,7 +20,7 @@ define([
'less!/customize/src/less/cryptpad.less',
'less!/whiteboard/whiteboard.less',
'less!/customize/src/less/toolbar.less',
-], function ($, Config, Realtime, Crypto, Toolbar, TextPatcher, JSONSortify, JsonOT, Cryptpad, Cryptget, Colors, AppConfig) {
+], function ($, Config, Realtime, Crypto, Toolbar, TextPatcher, JSONSortify, JsonOT, Cryptpad, Cryptget, Colors, AppConfig, Thumb) {
var saveAs = window.saveAs;
var Messages = Cryptpad.Messages;
@@ -212,13 +213,18 @@ window.canvas = canvas;
module.FM = Cryptpad.createFileManager({});
module.upload = function (title) {
- $canvas[0].toBlob(function (blob) {
- blob.name = title;
- var reader = new FileReader();
- reader.onloadend = function () {
- module.FM.handleFile(blob);
- };
- reader.readAsArrayBuffer(blob);
+ var canvas = $canvas[0];
+ var finish = function (thumb) {
+ canvas.toBlob(function (blob) {
+ blob.name = title;
+ module.FM.handleFile(blob, void 0, thumb);
+ });
+ };
+
+ Thumb.fromCanvas(canvas, function (e, blob) {
+ // carry on even if you can't get a thumbnail
+ if (e) { console.error(e); }
+ finish(blob);
});
};