Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Encrypt attachments in encrypted rooms, #533

Merged
merged 19 commits into from
Nov 9, 2016
Merged

Conversation

NegativeMjark
Copy link
Contributor

@NegativeMjark NegativeMjark commented Nov 2, 2016

TODO:

  • Decrypt image attachments when displaying them.
  • Do something when we get an error trying to decrypt.
  • Decrypt m.video
  • Decrypt m.audio
  • Decrypt m.file
  • Allow people to download encrypted attachments.
  • Thumbnail image attachments before sending.
  • Thumbnail video attachments before sending.

@matrixbot
Copy link
Member

Can one of the admins verify this patch?

@dbkr
Copy link
Member

dbkr commented Nov 3, 2016

@matrixbot test this please

Copy link
Member

@dbkr dbkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main thing here is probably the fact that it doesn't work with the gif hover behaviour, but I'm not about to ask you to rewrite our react code to support this. Maybe one of us can fix this on the PR branch.

}
},

decryptFile: function(file) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love the fact that a function called decryptFile downloads and decrypts a file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and also then displays it.


decryptFile: function(file) {
var url = MatrixClientPeg.get().mxcUrlToHttp(file.url);
var self = this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to use arrow functions rather than the self = this hack nowadays

// The attachment is decrypted in componentDidMount.
return (
<span className="mx_MImageBody" ref="body">
<img className="mx_MImageBody_thumbnail" src="img/encrypted-placeholder.svg" ref="image"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does the placeholder come from?

self.refs.image.onload = function() {
window.URL.revokeObjectURL(blobUrl);
};
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this post-render DOM mangling isn't great, but we do appear to do it for animated gifs anyway. Relatedly, this will mean the current play-on-hover behaviour of animated gifs won't work with encrypted attachments, so this is a thing we'll need to fix too.

@NegativeMjark
Copy link
Contributor Author

Thumb-nailing in the browser sounds hard and I think this PR is big enough already.
@dbkr PTAL.

@NegativeMjark
Copy link
Contributor Author

@dbkr Right I think this is done PTAL

Copy link
Member

@dbkr dbkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking nice. Have made some language comments. Maybe a warning somewhere about it downloading full content of everything currently, until thumbnails are sorted out?

limitations under the License.
*/

'use struct';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It's spelt 'strict'
  2. We don't need these anyway: babel adds them.

'use struct';

// Pull in the encryption lib so that we can decrypt attachments.
var encrypt = require("browser-encrypt-attachment");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're making a new file, import encrypt from 'browser-encrypt-attachment'; please.

*/

function readBlobAsDataUri(file) {
var deferred = q.defer();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const please



export function decryptFile(file) {
var url = MatrixClientPeg.get().mxcUrlToHttp(file.url);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more const

},

componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
this.fixupHeight();
var content = this.props.mxEvent.getContent();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

@@ -77,14 +86,41 @@ module.exports = React.createClass({
imgElement.src = this._getThumbUrl();
},

_getContentUrl: function() {
var content = this.props.mxEvent.getContent();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const again

var MatrixClientPeg = require('../../../MatrixClientPeg');
var ImageUtils = require('../../../ImageUtils');
var Modal = require('../../../Modal');
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
var DecryptFile = require('../../../utils/DecryptFile');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally we would follow convention within the file for require vs import, or migrate the whole file. Probably decide which though rather than adding both. ;)

);
}

var contentUrl = this._getContentUrl();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more consts please

var content = this.props.mxEvent.getContent();
var self = this;
if (content.file !== undefined && this.state.decryptedUrl === null) {
DecryptFile.decryptFile(content.file).then(function(url) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/function(x)/(x) => / then you can ditch the var self = this and just use this.

@@ -47,22 +54,89 @@ module.exports = React.createClass({
return linkText;
},

_getContentUrl: function() {
var content = this.props.mxEvent.getContent();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

@NegativeMjark
Copy link
Contributor Author

I think I've responded to the review comments @dbkr PTAL.

Unfortunately I've discovered that the data URLs don't work reliably on chrome if the URL is bigger than 2MB. https://bugs.chromium.org/p/chromium/issues/detail?id=69227.

I have a plan for getting around it, but for now I guess this "sort of works"? It certainly should be enough for people to test against with small attachments.

Copy link
Member

@dbkr dbkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@dbkr dbkr merged commit 3e9414b into master Nov 9, 2016
richvdh added a commit that referenced this pull request Nov 12, 2016
#533 originally landed in
the wrong branch, and was reverted by
#546.
#548 attempted to land it on
the develop branch, but omitted a small amount of the patch.

This lands the final part, which got missed out.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants