diff --git a/browser/lib/util/bufferutils.js b/browser/lib/util/bufferutils.js index 1f4a0a647e..0e8747d1f1 100644 --- a/browser/lib/util/bufferutils.js +++ b/browser/lib/util/bufferutils.js @@ -5,11 +5,6 @@ var BufferUtils = (function() { function isWordArray(ob) { return ob !== null && ob !== undefined && ob.sigBytes !== undefined; } function isArrayBuffer(ob) { return ob !== null && ob !== undefined && ob.constructor === ArrayBuffer; } - // msgpack.decode for raw binary data gives a wordArray-like object that isn't a proper wordArray, - // so doesn't have a wordArray.clamp() method - function ensureProperWordArray(wordArray) { - return (wordArray.clamp !== undefined ? wordArray : WordArray.create(wordArray.words)); - } // https://gist.githubusercontent.com/jonleighton/958841/raw/f200e30dfe95212c0165ccf1ae000ca51e9de803/gistfile1.js function arrayBufferToBase64(ArrayBuffer) { @@ -81,6 +76,29 @@ var BufferUtils = (function() { BufferUtils.isBuffer = function(buf) { return isArrayBuffer(buf) || isWordArray(buf); }; + BufferUtils.toArrayBuffer = function(buf) { + if(!ArrayBuffer) + throw new Error("Can't convert to ArrayBuffer: ArrayBuffer not supported"); + + if(isArrayBuffer(buf)) + return buf; + + if(isWordArray(buf)) { + /* Backported from unreleased CryptoJS + * https://code.google.com/p/crypto-js/source/browse/branches/3.x/src/lib-typedarrays.js?r=661 */ + var arrayBuffer = new ArrayBuffer(buf.sigBytes); + var uint8View = new Uint8Array(arrayBuffer); + + for (var i = 0; i < buf.sigBytes; i++) { + uint8View[i] = (buf.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + } + + return arrayBuffer; + }; + + throw new Error("BufferUtils.toArrayBuffer expected a buffer"); + }; + BufferUtils.toWordArray = function(buf) { return isWordArray(buf) ? buf : WordArray.create(buf); }; @@ -89,7 +107,7 @@ var BufferUtils = (function() { if(isArrayBuffer(buf)) return arrayBufferToBase64(buf); if(isWordArray(buf)) - return CryptoJS.enc.Base64.stringify(ensureProperWordArray(buf)); + return CryptoJS.enc.Base64.stringify(buf); }; BufferUtils.base64Decode = function(str) { diff --git a/common/lib/types/message.js b/common/lib/types/message.js index 7ace95aa90..2dbac29c06 100644 --- a/common/lib/types/message.js +++ b/common/lib/types/message.js @@ -27,10 +27,17 @@ var Message = (function() { * although msgpack calls toJSON(), we know it is a stringify() * call if it has a non-empty arguments list */ var data = this.data; - if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { - var encoding = this.encoding; - result.encoding = encoding ? (encoding + '/base64') : 'base64'; - data = BufferUtils.base64Encode(data); + if(data && BufferUtils.isBuffer(data)) { + if(arguments.length > 0) { + /* stringify call */ + var encoding = this.encoding; + result.encoding = encoding ? (encoding + '/base64') : 'base64'; + data = BufferUtils.base64Encode(data); + } else { + /* Called by msgpack. Need to feed it an ArrayBuffer, msgpack doesn't + * understand WordArrays */ + data = BufferUtils.toArrayBuffer(data); + } } result.data = data; return result; diff --git a/common/lib/types/presencemessage.js b/common/lib/types/presencemessage.js index c435d1e001..e0a99551bb 100644 --- a/common/lib/types/presencemessage.js +++ b/common/lib/types/presencemessage.js @@ -30,14 +30,21 @@ var PresenceMessage = (function() { encoding: this.encoding }; - /* encode to base64 if we're returning real JSON; + /* encode data to base64 if present and we're returning real JSON; * although msgpack calls toJSON(), we know it is a stringify() - * call if it passes on the stringify arguments */ + * call if it has a non-empty arguments list */ var data = this.data; - if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { - var encoding = this.encoding; - result.encoding = encoding ? (encoding + '/base64') : 'base64'; - data = data.toString('base64'); + if(data && BufferUtils.isBuffer(data)) { + if(arguments.length > 0) { + /* stringify call */ + var encoding = this.encoding; + result.encoding = encoding ? (encoding + '/base64') : 'base64'; + data = BufferUtils.base64Encode(data); + } else { + /* Called by msgpack. Need to feed it an ArrayBuffer, msgpack doesn't + * understand WordArrays */ + data = BufferUtils.toArrayBuffer(data); + } } result.data = data; return result; diff --git a/nodejs/lib/util/bufferutils.js b/nodejs/lib/util/bufferutils.js index 2ff26a1ad5..df76b1291e 100644 --- a/nodejs/lib/util/bufferutils.js +++ b/nodejs/lib/util/bufferutils.js @@ -7,6 +7,8 @@ this.BufferUtils = (function() { BufferUtils.isBuffer = Buffer.isBuffer; + BufferUtils.toArrayBuffer = function(buf) { return buf; }; + BufferUtils.base64Encode = function(buf) { return buf.toString('base64'); }; BufferUtils.base64Decode = function(string) { return new Buffer(string, 'base64'); };