diff --git a/package/bin/irc/irc.js b/package/bin/irc/irc.js index 091939aa..7301f321 100644 --- a/package/bin/irc/irc.js +++ b/package/bin/irc/irc.js @@ -231,8 +231,15 @@ var line = this.data.slice(0, cr ? crlf - 1 : crlf); this.data = this.data.slice(crlf + 1); dataView = new Uint8Array(this.data); - _results.push(this.util.fromSocketData(line, function(lineStr) { - console.log('<=', "(" + _this.server + ")", lineStr); + _results.push(this.util.fromSocketData(line, function(lineStr, encoding) { + console.groupCollapsed('<=', "(" + _this.server + ")", lineStr); + console.log( + encoding, + lineStr.length + ' characters', + line.byteLength + ' bytes' + ); + _this.util.dumpBuffer(line); + console.groupEnd(); return _this.onServerMessage(_this.util.parseCommand(lineStr)); })); } else { diff --git a/package/bin/irc/irc_util.js b/package/bin/irc/irc_util.js index fd13e2ec..3af3e13a 100644 --- a/package/bin/irc/irc_util.js +++ b/package/bin/irc/irc_util.js @@ -144,6 +144,21 @@ return arrayBuffer; }; + exports.dumpBuffer = function(buffer) { + try { + var view, arr, hexes; + view = new Uint8Array(buffer); + arr = view.subarray(); + arr = Array.prototype.slice.call(arr); + hexes = arr.map(function(n) { + return (n < 16 ? '0' : '') + Number(n).toString(16).toUpperCase(); + }); + console.log(hexes.join(' ')); + } catch(e) { + console.err(e); + } + }; + function createBlob(src) { var BB = window.BlobBuilder || window.WebKitBlobBuilder; if (BB) { @@ -175,14 +190,21 @@ return f.readAsArrayBuffer(blob); }; + arrayBuffer2String = function(buf, callback) { - var blob, f; + var blob, f, hadReplacements; exports.arrayBufferConversionCount++; blob = createBlob(buf); f = new FileReader(); + hadReplacements = false; f.onload = function(e) { - exports.arrayBufferConversionCount--; - return callback(e.target.result); + if(e.target.result.match(/\ufffd/) && !hadReplacements) { + hadReplacements = true; + return f.readAsText(blob, 'ISO-8859-1'); + } else { + exports.arrayBufferConversionCount--; + return callback(e.target.result, hadReplacements ? 'ISO-8859-1' : 'UTF-8'); + } }; return f.readAsText(blob); }; diff --git a/test/irc_utils_test.js b/test/irc_utils_test.js new file mode 100644 index 00000000..1a0d2591 --- /dev/null +++ b/test/irc_utils_test.js @@ -0,0 +1,40 @@ +(function() { + "use strict"; + + describe("IRC Utils provides the following functions:", function() { + + var waitsForArrayBufferConversion; + waitsForArrayBufferConversion = function() { + return waitsFor((function() { + return !window.irc.util.isConvertingArrayBuffers(); + }), 'wait for array buffer conversion', 500); + }; + + describe("fromSocketData", function() { + var fromSocketData = irc.util.fromSocketData; + var ab, cb; + beforeEach(function() { + cb = jasmine.createSpy('cb'); + }); + + describe("handles encoding", function() { + [ + ['UTF-8', [0x61, 0xE2, 0x9C, 0x93], 'a✓'], + ['ISO-8859-1', [0x74, 0x73, 0x63, 0x68, 0xFC, 0xDF], 'tschüß'] + ].forEach(function(parts) { + var encoding = parts[0], + array = parts[1], + text = parts[2]; + it(encoding, function() { + ab = irc.util.arrayToArrayBuffer(array); + fromSocketData(ab, cb); + waitsForArrayBufferConversion(); + return runs(function() { + expect(cb).toHaveBeenCalledWith(text, encoding); + }); + }); + }); + }); + }); + }); +})(); diff --git a/test/test_runner.html b/test/test_runner.html index 6d37a429..0fec6a6a 100644 --- a/test/test_runner.html +++ b/test/test_runner.html @@ -1,7 +1,7 @@ - +
+