Use data:// URI rather than blob: URI to avoid XSS
This commit is contained in:
parent
b69e88d4e3
commit
ee1768f644
5 changed files with 37 additions and 59 deletions
|
@ -49,12 +49,10 @@ export default class MAudioBody extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
||||||
decryptFile(content.file).then((blob) => {
|
decryptFile(content.file).then((url) => {
|
||||||
if (!this._unmounted) {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
decryptedUrl: window.URL.createObjectURL(blob),
|
decryptedUrl: url
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.warn("Unable to decrypt attachment: ", err)
|
console.warn("Unable to decrypt attachment: ", err)
|
||||||
// Set a placeholder image when we can't decrypt the image.
|
// Set a placeholder image when we can't decrypt the image.
|
||||||
|
@ -63,13 +61,6 @@ export default class MAudioBody extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this._unmounted = true;
|
|
||||||
if (this.state.decryptedUrl) {
|
|
||||||
window.URL.revokeObjectURL(this.state.decryptedUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var DecryptFile = require('../../../utils/DecryptFile');
|
var DecryptFile = require('../../../utils/DecryptFile');
|
||||||
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'MFileBody',
|
displayName: 'MFileBody',
|
||||||
|
|
||||||
|
@ -66,12 +67,10 @@ module.exports = React.createClass({
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
var self = this;
|
var self = this;
|
||||||
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
||||||
DecryptFile.decryptFile(content.file).then(function(blob) {
|
DecryptFile.decryptFile(content.file).then(function(url) {
|
||||||
if (!self._unmounted) {
|
|
||||||
self.setState({
|
self.setState({
|
||||||
decryptedUrl: window.URL.createObjectURL(blob),
|
decryptedUrl: url,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.warn("Unable to decrypt attachment: ", err)
|
console.warn("Unable to decrypt attachment: ", err)
|
||||||
// Set a placeholder image when we can't decrypt the image.
|
// Set a placeholder image when we can't decrypt the image.
|
||||||
|
@ -80,13 +79,6 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
this._unmounted = true;
|
|
||||||
if (this.state.decryptedUrl) {
|
|
||||||
window.URL.revokeObjectURL(this.state.decryptedUrl);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
|
|
||||||
|
|
|
@ -109,12 +109,10 @@ module.exports = React.createClass({
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
var self = this;
|
var self = this;
|
||||||
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
||||||
DecryptFile.decryptFile(content.file).then(function(blob) {
|
DecryptFile.decryptFile(content.file).then(function(url) {
|
||||||
if (!self._unmounted) {
|
|
||||||
self.setState({
|
self.setState({
|
||||||
decryptedUrl: window.URL.createObjectURL(blob),
|
decryptedUrl: url,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.warn("Unable to decrypt attachment: ", err)
|
console.warn("Unable to decrypt attachment: ", err)
|
||||||
// Set a placeholder image when we can't decrypt the image.
|
// Set a placeholder image when we can't decrypt the image.
|
||||||
|
@ -125,10 +123,6 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
dis.unregister(this.dispatcherRef);
|
dis.unregister(this.dispatcherRef);
|
||||||
this._unmounted = true;
|
|
||||||
if (this.state.decryptedUrl) {
|
|
||||||
window.URL.revokeObjectURL(this.state.decryptedUrl);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onAction: function(payload) {
|
onAction: function(payload) {
|
||||||
|
|
|
@ -88,21 +88,13 @@ module.exports = React.createClass({
|
||||||
content.info.thumbnail_file
|
content.info.thumbnail_file
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
thumbnailPromise.then(function(thumbnailBlob) {
|
thumbnailPromise.then(function(thumbnailUrl) {
|
||||||
DecryptFile.decryptFile(
|
DecryptFile.decryptFile(
|
||||||
content.file
|
content.file
|
||||||
).then(function(contentBlob) {
|
).then(function(contentUrl) {
|
||||||
if (self._unmounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var contentUrl = window.URL.createObjectURL(contentBlob);
|
|
||||||
var thumbUrl = null;
|
|
||||||
if (thumbnailBlob) {
|
|
||||||
thumbUrl = window.URL.createObjectURL(thumbnailBlob);
|
|
||||||
}
|
|
||||||
self.setState({
|
self.setState({
|
||||||
decryptedUrl: contentUrl,
|
decryptedUrl: contentUrl,
|
||||||
decryptedThumbnailUrl: thumbUrl,
|
decryptedThumbnailUrl: thumbnailUrl,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
|
@ -113,17 +105,6 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
this._unmounted = true;
|
|
||||||
if (this.state.decryptedUrl) {
|
|
||||||
window.URL.revokeObjectURL(this.state.decryptedUrl);
|
|
||||||
}
|
|
||||||
if (this.state.decryptedThumbnailUrl) {
|
|
||||||
window.URL.revokeObjectURL(this.state.decryptedThumbnailUrl);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,26 @@ var encrypt = require("browser-encrypt-attachment");
|
||||||
require("isomorphic-fetch");
|
require("isomorphic-fetch");
|
||||||
// Grab the client so that we can turn mxc:// URLs into https:// URLS.
|
// Grab the client so that we can turn mxc:// URLs into https:// URLS.
|
||||||
var MatrixClientPeg = require('../MatrixClientPeg');
|
var MatrixClientPeg = require('../MatrixClientPeg');
|
||||||
|
var q = require('q');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read blob as a data:// URI.
|
||||||
|
* @return {Promise} A promise that resolves with the data:// URI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function readBlobAsDataUri(file) {
|
||||||
|
var deferred = q.defer();
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function(e) {
|
||||||
|
deferred.resolve(e.target.result);
|
||||||
|
};
|
||||||
|
reader.onerror = function(e) {
|
||||||
|
deferred.reject(e);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function decryptFile(file) {
|
export function decryptFile(file) {
|
||||||
|
@ -37,6 +57,6 @@ export function decryptFile(file) {
|
||||||
}).then(function(dataArray) {
|
}).then(function(dataArray) {
|
||||||
// Turn the array into a Blob and give it the correct MIME-type.
|
// Turn the array into a Blob and give it the correct MIME-type.
|
||||||
var blob = new Blob([dataArray], {type: file.mimetype});
|
var blob = new Blob([dataArray], {type: file.mimetype});
|
||||||
return blob;
|
return readBlobAsDataUri(blob);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue