Merge branch 'backbone_ui' of https://github.com/M2Ys4U/KiwiIRC into backbone_ui
[KiwiIRC.git] / server / irc / connection.js
CommitLineData
2a8e95d1
D
1var 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 8var IrcConnection = function (hostname, port, ssl, nick, user, pass) {
2a8e95d1
D
9 var that = this;
10 events.EventEmitter.call(this);
11
12 if (ssl) {
831b41b0 13 this.socket = tls.connect({host: hostname, port: port, rejectUnauthorized: global.config.reject_unauthorised_certificates}, connect_handler);
2a8e95d1
D
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};
47util.inherits(IrcConnection, events.EventEmitter);
48
49module.exports.IrcConnection = IrcConnection;
50
51
52IrcConnection.prototype.write = function (data, callback) {
53 write.call(this, data + '\r\n', 'utf-8', callback);
54};
55
56IrcConnection.prototype.end = function (data, callback) {
2a8e95d1
D
57 end.call(this, data + '\r\n', 'utf-8', callback);
58};
59
c08717da
D
60IrcConnection.prototype.dispose = function () {
61 this.removeAllListeners();
62};
63
64
2a8e95d1
D
65var write = function (data, encoding, callback) {
66 this.socket.write(data, encoding, callback);
67};
68
69var end = function (data, encoding, callback) {
70 this.socket.end(data, encoding, callback);
71};
72
73
74var 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
111function 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
138parse_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
139var 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};