1 var net
= require('net'),
3 events
= require('events'),
4 util
= require('util'),
5 _
= require('underscore');
7 var IrcConnection = function (hostname
, port
, ssl
, nick
, user
, pass
) {
9 events
.EventEmitter
.call(this);
12 this.socket
= tls
.connect({
15 rejectUnauthorized
: global
.config
.reject_unauthorised_certificates
17 connect_handler
.apply(that
, arguments
);
20 this.socket
= net
.createConnection(port
, hostname
);
21 this.socket
.on('connect', function () {
22 connect_handler
.apply(that
, arguments
);
26 this.socket
.on('error', function (event
) {
27 that
.emit('error', event
);
30 this.socket
.setEncoding('utf-8');
32 this.socket
.on('data', function () {
33 parse
.apply(that
, arguments
);
36 this.socket
.on('close', function () {
40 this.connected
= false;
41 this.registered
= false;
42 this.cap_negotiation
= true;
45 this.username
= this.nick
.replace(/[^0-9a-zA-Z\-_.]/, ''),
46 this.irc_host
= {hostname
: hostname
, port
: port
};
48 this.options
= Object
.create(null);
49 this.cap
= {requested
: [], enabled
: []};
53 this.hold_last
= false;
56 util
.inherits(IrcConnection
, events
.EventEmitter
);
58 module
.exports
.IrcConnection
= IrcConnection
;
61 IrcConnection
.prototype.write = function (data
, callback
) {
62 write
.call(this, data
+ '\r\n', 'utf-8', callback
);
65 IrcConnection
.prototype.end = function (data
, callback
) {
66 end
.call(this, data
+ '\r\n', 'utf-8', callback
);
69 IrcConnection
.prototype.dispose = function () {
70 this.removeAllListeners();
74 var write = function (data
, encoding
, callback
) {
75 this.socket
.write(data
, encoding
, callback
);
78 var end = function (data
, encoding
, callback
) {
79 this.socket
.end(data
, encoding
, callback
);
83 var connect_handler = function () {
87 // Build up data to be used for webirc/etc detection
91 realname
: '[www.kiwiirc.com] ' + this.nick
,
92 username
: this.username
,
93 irc_host
: this.irc_host
96 // Let the webirc/etc detection modify any required parameters
97 connect_data
= findWebIrc
.call(this, connect_data
);
99 // Send any initial data for webirc/etc
100 if (connect_data
.prepend_data
) {
101 _
.each(connect_data
.prepend_data
, function(data
) {
106 this.write('CAP LS');
108 this.registration_timeout
= setTimeout(function () {
112 this.connected
= true;
113 this.emit('connected');
116 IrcConnection
.prototype.register = function () {
117 if (this.registration_timeout
!== null) {
118 clearTimeout(this.registeration_timeout
);
119 this.registration_timeout
= null;
121 if ((this.password
) && (!this.sasl
)) {
122 this.write('PASS ' + this.password
);
124 this.write('NICK ' + this.nick
);
125 this.write('USER ' + this.username
+ ' 0 0 :' + '[www.kiwiirc.com] ' + this.nick
);
126 if (this.cap_negotation
) {
127 this.write('CAP END');
133 function findWebIrc(connect_data
) {
134 var webirc_pass
= global
.config
.webirc_pass
;
135 var ip_as_username
= global
.config
.ip_as_username
;
138 // Do we have a WEBIRC password for this?
139 if (webirc_pass
&& webirc_pass
[connect_data
.irc_host
.hostname
]) {
140 tmp
= 'WEBIRC ' + webirc_pass
[connect_data
.irc_host
.hostname
] + ' KiwiIRC ';
141 tmp
+= connect_data
.user
.hostname
+ ' ' + connect_data
.user
.address
;
142 connect_data
.prepend_data
= [tmp
];
146 // Check if we need to pass the users IP as its username/ident
147 if (ip_as_username
&& ip_as_username
.indexOf(connect_data
.irc_host
.hostname
) > -1) {
148 // Get a hex value of the clients IP
149 this.username
= connect_data
.user
.address
.split('.').map(function(i
, idx
){
150 return parseInt(i
, 10).toString(16);
160 parse_regex
= /^(?:(?:(?:(@[^ ]+) )?):(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:\/]+)?) )?(\S+)(?: (?!:)(.+?))?(?: :(.+))?$/i;
161 var parse = function (data
) {
170 if ((this.hold_last
) && (this.held_data
!== '')) {
171 data
= this.held_data
+ data
;
172 this.hold_last
= false;
175 if (data
.substr(-1) !== '\n') {
176 this.hold_last
= true;
178 data
= data
.split("\n");
179 for (i
= 0; i
< data
.length
; i
++) {
181 if ((this.hold_last
) && (i
=== data
.length
- 1)) {
182 this.held_data
= data
[i
];
186 // We have a complete line of data, parse it!
187 msg
= parse_regex
.exec(data
[i
].replace(/^\r+|\r+$/, ''));
190 tags
= msg
[1].split(';');
191 for (j
= 0; j
< tags
.length
; j
++) {
192 tag
= tags
[j
].split('=');
193 tags
[j
] = {tag
: tag
[0], value
: tag
[1]};
201 hostname
: msg
[5] || '',
203 params
: msg
[7] || '',
204 trailing
: (msg
[8]) ? msg
[8].trim() : ''
206 msg
.params
= msg
.params
.split(' ');
208 this.emit('irc_' + msg
.command
.toUpperCase(), msg
);
210 console
.log("Malformed IRC line: " + data
[i
].replace(/^\r+|\r+$/, ''));