Skip to content

Commit

Permalink
Add fallback encoding for non-UTF-8 lines
Browse files Browse the repository at this point in the history
Default to cp1252
  • Loading branch information
lorkki committed Apr 1, 2018
1 parent 495314b commit bdb08e6
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/clientapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ new Irc.Client({
username: 'ircbot',
gecos: 'ircbot',
encoding: 'utf8',
encoding_fallback: 'cp1252',
version: 'node.js irc-framework',
enable_chghost: false,
enable_echomessage: false,
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"iconv-lite": "^0.4.11",
"lodash": "^4.17.4",
"middleware-handler": "^0.2.0",
"socksjs": "^0.5.0"
"socksjs": "^0.5.0",
"utf-8-validate": "^4.0.0"
},
"devDependencies": {
"babel-cli": "^6.26.0",
Expand Down
1 change: 1 addition & 0 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = class IrcClient extends EventEmitter {
username: 'ircbot',
gecos: 'ircbot',
encoding: 'utf8',
encoding_fallback: 'cp1252',
version: 'node.js irc-framework',
enable_chghost: false,
enable_echomessage: false,
Expand Down
12 changes: 12 additions & 0 deletions src/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ module.exports = class Connection extends EventEmitter {
this.setEncoding('utf8');
}

if (!options.encoding_fallback || !this.setEncodingFallback(options.encoding_fallback)) {
this.setEncodingFallback('cp1252');
}

// Some transports may emit extra events
transport.on('extra', function(/*event_name, argN*/) {
that.emit.apply(that, arguments);
Expand Down Expand Up @@ -241,6 +245,14 @@ module.exports = class Connection extends EventEmitter {
}
}

setEncodingFallback(encoding) {
this.debugOut('Connection.setEncodingFallback() encoding=' + encoding);

if (this.transport) {
return this.transport.setEncodingFallback(encoding);
}
}


/**
* Process the buffered messages recieved from the IRCd
Expand Down
40 changes: 36 additions & 4 deletions src/transports/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var util = require('util');
var EventEmitter = require('events').EventEmitter;
var Socks = require('socksjs');
var iconv = require('iconv-lite');
var isValidUTF8 = require('utf-8-validate');

var SOCK_DISCONNECTED = 0;
var SOCK_CONNECTING = 1;
Expand All @@ -27,6 +28,7 @@ module.exports = class Connection extends EventEmitter {
this.socket_events = [];

this.encoding = 'utf8';
this.encoding_fallback = 'cp1252';
this.incoming_buffer = '';
}

Expand Down Expand Up @@ -154,7 +156,7 @@ module.exports = class Connection extends EventEmitter {
}

onSocketData(data) {
this.incoming_buffer += iconv.decode(data, this.encoding);
this.incoming_buffer += this.decodeBuffer(data);

var lines = this.incoming_buffer.split('\n');
if (lines[lines.length - 1] !== '') {
Expand Down Expand Up @@ -197,19 +199,49 @@ module.exports = class Connection extends EventEmitter {
}
}

decodeBuffer(data) {
if (this.encoding === 'utf8' && this.encoding_fallback) {
if (isValidUTF8(data)) {
return iconv.decode(data, 'utf8');
} else {
return iconv.decode(data, this.encoding_fallback);
}
} else {
return iconv.decode(data, this.encoding);
}
}

setEncoding(encoding) {
var encoded_test;

this.debugOut('Connection.setEncoding() encoding=' + encoding);

if (this.testEncoding(encoding)) {
this.encoding = encoding;
return true;
} else {
return false;
}
}

setEncodingFallback(encoding) {
this.debugOut('Connection.setEncodingFallback() encoding=' + encoding);

if (this.testEncoding(encoding)) {
this.encoding_fallback = encoding;
return true;
} else {
return false;
}
}

testEncoding(encoding) {
var encoded_test;

try {
encoded_test = iconv.encode('TEST', encoding);
// This test is done to check if this encoding also supports
// the ASCII charset required by the IRC protocols
// (Avoid the use of base64 or incompatible encodings)
if (encoded_test == 'TEST') { // jshint ignore:line
this.encoding = encoding;
return true;
}
return false;
Expand Down
3 changes: 3 additions & 0 deletions src/transports/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,7 @@ module.exports = class Connection extends EventEmitter {

setEncoding(encoding) {
}

setEncodingFallback(encoding) {
}
};

0 comments on commit bdb08e6

Please sign in to comment.