From e423bcb83aaf2f00b588792c154a2bfe35edc94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henri=20Niemel=C3=A4inen?= Date: Fri, 10 Apr 2015 15:36:18 +0200 Subject: [PATCH] Fix charset conversion for invalid charsets If icu detects an charset that cannot be converted with iconv, return original buffer --- lib/irc.js | 25 +++++++++++------ package.json | 3 +- test/data/fixtures.json | 10 ++++++- test/test-convert-encoding.js | 53 +++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 test/test-convert-encoding.js diff --git a/lib/irc.js b/lib/irc.js index 9bc96d3e..45eba0ab 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -1026,18 +1026,25 @@ Client.prototype.ctcp = function(to, type, text) { }; Client.prototype.convertEncoding = function(str) { - var self = this; + var self = this, out = str; if (self.opt.encoding) { - var charsetDetector = require('node-icu-charset-detector'); - var Iconv = require('iconv').Iconv; - var charset = charsetDetector.detectCharset(str).toString(); - var to = new Iconv(charset, self.opt.encoding); - - return to.convert(str); - } else { - return str; + try { + var charsetDetector = require('node-icu-charset-detector'); + var Iconv = require('iconv').Iconv; + var charset = charsetDetector.detectCharset(str); + var converter = new Iconv(charset.toString(), self.opt.encoding); + + out = converter.convert(str); + } catch (err) { + if (self.opt.debug) { + util.log('\u001b[01;31mERROR: ' + err + '\u001b[0m'); + util.inspect({ str: str, charset: charset }); + } + } } + + return out; }; // blatantly stolen from irssi's splitlong.pl. Thanks, Bjoern Krombholz! Client.prototype._updateMaxLineLength = function() { diff --git a/package.json b/package.json index 1fd07288..d759bc0f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "xAndy ", "Mischa Spiegelmock ", "Justin Gallardo ", - "Chris Nehren " + "Chris Nehren ", + "Henri Niemeläinen " ], "repository": { "type": "git", diff --git a/test/data/fixtures.json b/test/data/fixtures.json index f0b0671b..be47f9df 100644 --- a/test/data/fixtures.json +++ b/test/data/fixtures.json @@ -147,5 +147,13 @@ "nick is as expected after 433", "maxLineLength is as expected after 433" ] - } + }, + "convert-encoding": { + "causesException": [ + ":ubottu!ubottu@ubuntu/bot/ubottu MODE #ubuntu -bo *!~Brian@* ubottu\r\n", + "Elizabeth", + ":sblack1!~sblack1@unaffiliated/sblack1 NICK :sblack\r\n", + ":TijG!~TijG@null.1ago.be PRIVMSG #ubuntu :ThinkPad\r\n" + ] + } } diff --git a/test/test-convert-encoding.js b/test/test-convert-encoding.js new file mode 100644 index 00000000..bbd62fac --- /dev/null +++ b/test/test-convert-encoding.js @@ -0,0 +1,53 @@ +var irc = require('../lib/irc'); +var test = require('tape'); +var testHelpers = require('./helpers'); +var checks = testHelpers.getFixtures('convert-encoding'); +var bindTo = { opt: { encoding: 'utf-8' } }; + +test('irc.Client.convertEncoding old', function(assert) { + var convertEncoding = function(str) { + var self = this; + + if (self.opt.encoding) { + var charsetDetector = require('node-icu-charset-detector'); + var Iconv = require('iconv').Iconv; + var charset = charsetDetector.detectCharset(str).toString(); + var to = new Iconv(charset, self.opt.encoding); + + return to.convert(str); + } else { + return str; + } + }.bind(bindTo); + + checks.causesException.forEach(function iterate(line) { + var causedException = false; + try { + convertEncoding(line); + } catch (e) { + causedException = true; + } + + assert.equal(causedException, true, line + ' caused exception'); + }); + + assert.end(); +}); + +test('irc.Client.convertEncoding', function(assert) { + var convertEncoding = irc.Client.prototype.convertEncoding.bind(bindTo); + + checks.causesException.forEach(function iterate(line) { + var causedException = false; + + try { + convertEncoding(line); + } catch (e) { + causedException = true; + } + + assert.equal(causedException, false, line + ' didn\'t cause exception'); + }); + + assert.end(); +});