Commit | Line | Data |
---|---|---|
2a8e95d1 D |
1 | var net = require('net'), |
2 | tls = require('tls'), | |
3 | events = require('events'), | |
15fefff7 D |
4 | util = require('util'), |
5 | _ = require('underscore'), | |
6 | config = require('../configuration.js'); | |
2a8e95d1 | 7 | |
15fefff7 | 8 | var IrcConnection = function (hostname, port, ssl, nick, user, pass) { |
2a8e95d1 D |
9 | var that = this; |
10 | events.EventEmitter.call(this); | |
11 | ||
12 | if (ssl) { | |
13 | this.socket = tls.connect(port, hostname, {}, connect_handler); | |
14 | } else { | |
15 | this.socket = net.createConnection(port, hostname); | |
16 | this.socket.on('connect', function () { | |
17 | connect_handler.apply(that, arguments); | |
18 | }); | |
19 | } | |
20 | ||
d2d91c10 D |
21 | this.socket.on('error', function (event) { |
22 | that.emit('error', event); | |
2a8e95d1 D |
23 | }); |
24 | ||
25 | this.socket.setEncoding('utf-8'); | |
26 | ||
27 | this.socket.on('data', function () { | |
28 | parse.apply(that, arguments); | |
29 | }); | |
30 | ||
31 | this.socket.on('close', function () { | |
32 | that.emit('close'); | |
33 | }); | |
34 | ||
35 | this.connected = false; | |
36 | this.registered = false; | |
37 | this.nick = nick; | |
38 | this.user = user; | |
15fefff7 | 39 | this.irc_host = {hostname: hostname, port: port}; |
2a8e95d1 D |
40 | this.ssl = !(!ssl); |
41 | this.options = Object.create(null); | |
42 | ||
2a8e95d1 D |
43 | this.password = pass; |
44 | this.hold_last = false; | |
45 | this.held_data = ''; | |
46 | }; | |
47 | util.inherits(IrcConnection, events.EventEmitter); | |
48 | ||
49 | module.exports.IrcConnection = IrcConnection; | |
50 | ||
51 | ||
52 | IrcConnection.prototype.write = function (data, callback) { | |
53 | write.call(this, data + '\r\n', 'utf-8', callback); | |
54 | }; | |
55 | ||
56 | IrcConnection.prototype.end = function (data, callback) { | |
2a8e95d1 D |
57 | end.call(this, data + '\r\n', 'utf-8', callback); |
58 | }; | |
59 | ||
c08717da D |
60 | IrcConnection.prototype.dispose = function () { |
61 | this.removeAllListeners(); | |
62 | }; | |
63 | ||
64 | ||
2a8e95d1 D |
65 | var write = function (data, encoding, callback) { |
66 | this.socket.write(data, encoding, callback); | |
67 | }; | |
68 | ||
69 | var end = function (data, encoding, callback) { | |
70 | this.socket.end(data, encoding, callback); | |
71 | }; | |
72 | ||
73 | ||
74 | var connect_handler = function () { | |
15fefff7 D |
75 | var that = this, |
76 | connect_data; | |
77 | ||
78 | // Build up data to be used for webirc/etc detection | |
79 | connect_data = { | |
80 | user: this.user, | |
81 | nick: this.nick, | |
82 | realname: '[www.kiwiirc.com] ' + this.nick, | |
83 | username: this.nick.replace(/[^0-9a-zA-Z\-_.]/, ''), | |
84 | irc_host: this.irc_host | |
85 | }; | |
86 | ||
87 | // Let the webirc/etc detection modify any required parameters | |
88 | connect_data = findWebIrc(connect_data); | |
89 | ||
90 | // Send any initial data for webirc/etc | |
91 | if (connect_data.prepend_data) { | |
92 | _.each(connect_data.prepend_data, function(data) { | |
93 | that.write(data); | |
94 | }); | |
2a8e95d1 | 95 | } |
15fefff7 | 96 | |
2a8e95d1 D |
97 | if (this.password) { |
98 | this.write('PASS ' + this.password); | |
99 | } | |
15fefff7 D |
100 | |
101 | this.write('NICK ' + connect_data.nick); | |
102 | this.write('USER ' + connect_data.username + ' 0 0 :' + connect_data.realname); | |
2a8e95d1 D |
103 | |
104 | this.connected = true; | |
2a8e95d1 D |
105 | this.emit('connected'); |
106 | }; | |
107 | ||
2a8e95d1 | 108 | |
15fefff7 D |
109 | |
110 | ||
111 | function findWebIrc(connect_data) { | |
b737610b JA |
112 | var webirc_pass = global.config.webirc_pass; |
113 | var ip_as_username = global.config.ip_as_username; | |
15fefff7 D |
114 | var tmp; |
115 | ||
116 | // Do we have a WEBIRC password for this? | |
117 | if (webirc_pass && webirc_pass[connect_data.irc_host.hostname]) { | |
118 | tmp = 'WEBIRC ' + webirc_pass[connect_data.irc_host.hostname] + ' KiwiIRC '; | |
119 | tmp += connect_data.user.hostname + ' ' + connect_data.user.address; | |
120 | connect_data.prepend_data = [tmp]; | |
121 | } | |
122 | ||
123 | ||
124 | // Check if we need to pass the users IP as its username/ident | |
125 | if (ip_as_username && ip_as_username.indexOf(connect_data.irc_host.hostname) > -1) { | |
126 | // Get a hex value of the clients IP | |
127 | connect_data.username = connect_data.user.address.split('.').map(function(i, idx){ | |
128 | return parseInt(i, 10).toString(16); | |
129 | }).join(''); | |
130 | ||
131 | } | |
132 | ||
133 | return connect_data; | |
134 | } | |
135 | ||
136 | ||
137 | ||
138 | parse_regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:\/]+)?) )?(\S+)(?: (?!:)(.+?))?(?: :(.+))?$/i; | |
2a8e95d1 D |
139 | var parse = function (data) { |
140 | var i, | |
141 | msg, | |
142 | msg2, | |
143 | trm; | |
144 | ||
145 | if ((this.hold_last) && (this.held_data !== '')) { | |
146 | data = this.held_data + data; | |
147 | this.hold_last = false; | |
148 | this.held_data = ''; | |
149 | } | |
150 | if (data.substr(-1) !== '\n') { | |
151 | this.hold_last = true; | |
152 | } | |
153 | data = data.split("\n"); | |
154 | for (i = 0; i < data.length; i++) { | |
155 | if (data[i]) { | |
156 | if ((this.hold_last) && (i === data.length - 1)) { | |
157 | this.held_data = data[i]; | |
158 | break; | |
159 | } | |
160 | ||
161 | // We have a complete line of data, parse it! | |
162 | msg = parse_regex.exec(data[i].replace(/^\r+|\r+$/, '')); | |
163 | if (msg) { | |
164 | msg = { | |
165 | prefix: msg[1], | |
166 | nick: msg[2], | |
167 | ident: msg[3], | |
168 | hostname: msg[4] || '', | |
169 | command: msg[5], | |
170 | params: msg[6] || '', | |
171 | trailing: (msg[7]) ? msg[7].trim() : '' | |
172 | }; | |
173 | msg.params = msg.params.split(' '); | |
174 | ||
175 | this.emit('irc_' + msg.command.toUpperCase(), msg); | |
176 | } else { | |
177 | console.log("Malformed IRC line: " + data[i].replace(/^\r+|\r+$/, '')); | |
178 | } | |
179 | } | |
180 | } | |
181 | }; |