+/*jslint sloppy: true, continue: true, forin: true, regexp: true, undef: false, node: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */
+/*globals kiwi_root */
var tls = null;
var net = null;
var http = null;
_ = objs._;
starttls = objs.starttls;
kiwi = require('./kiwi.js');
-}
+};
*/
this.setTitle = function () {
process.title = 'kiwiirc';
-}
+};
this.changeUser = function () {
if (typeof kiwi.config.group !== 'undefined' && kiwi.config.group !== '') {
var ircNumerics = {
RPL_WELCOME: '001',
+ RPL_MYINFO: '004',
RPL_ISUPPORT: '005',
RPL_WHOISUSER: '311',
RPL_WHOISSERVER: '312',
RPL_WHOISIDLE: '317',
RPL_ENDOFWHOIS: '318',
RPL_WHOISCHANNELS: '319',
+ RPL_LISTSTART: '321',
+ RPL_LIST: '322',
+ RPL_LISTEND: '323',
RPL_NOTOPIC: '331',
RPL_TOPIC: '332',
RPL_NAMEREPLY: '353',
this.parseIRCMessage = function (websocket, ircSocket, data) {
/*global ircSocketDataHandler */
- var msg, regex, opts, options, opt, i, j, matches, nick, users, chan, channel, params, prefix, prefixes, nicklist, caps, rtn, obj;
- regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:]+)?) )?([a-z0-9]+)(?:(?: ([^:]+))?(?: :(.+))?)$/i;
+ var msg, regex, opts, options, opt, i, j, matches, nick, users, chan, channel, params, prefix, prefixes, nicklist, caps, rtn, obj, tmp, namespace;
+ //regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:\/]+)?) )?([a-z0-9]+)(?:(?: ([^:]+))?(?: :(.+))?)$/i;
+ //regex = /^(?::(\S+) )?(\S+)(?: (?!:)(.+?))?(?: :(.+))?$/i;
+ regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:\/]+)?) )?(\S+)(?: (?!:)(.+?))?(?: :(.+))?$/i;
+
msg = regex.exec(data);
if (msg) {
msg = {
params: msg[6] || '',
trailing: (msg[7]) ? msg[7].trim() : ''
};
+
switch (msg.command.toUpperCase()) {
case 'PING':
websocket.sendServerLine('PONG ' + msg.trailing);
ircSocket.IRC.CAP.requested = [];
ircSocket.IRC.registered = true;
}
- websocket.sendClientEvent('connect', {connected: true, host: null});
+ //regex = /([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:\/]+)/i;
+ //matches = regex.exec(msg.trailing);
+ nick = msg.params.split(' ')[0];
+ websocket.sendClientEvent('connect', {connected: true, host: null, nick: nick});
break;
case ircNumerics.RPL_ISUPPORT:
opts = msg.params.split(" ");
for (i = 0; i < opts.length; i++) {
opt = opts[i].split("=", 2);
opt[0] = opt[0].toUpperCase();
- ircSocket.IRC.options[opt[0]] = opt[1] || true;
+ ircSocket.IRC.options[opt[0]] = (typeof opt[1] !== 'undefined') ? opt[1] : true;
if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES'], opt[0])) {
if (opt[0] === 'PREFIX') {
regex = /\(([^)]*)\)(.*)/;
for (j = 0; j < matches[2].length; j++) {
//ircSocket.IRC.options[opt[0]][matches[2].charAt(j)] = matches[1].charAt(j);
ircSocket.IRC.options[opt[0]].push({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)});
- //console.log({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)});
}
- //console.log(ircSocket.IRC.options);
+
}
}
}
}
+
websocket.sendClientEvent('options', {server: '', "options": ircSocket.IRC.options});
break;
case ircNumerics.RPL_WHOISUSER:
case ircNumerics.RPL_WHOISMODES:
websocket.sendClientEvent('whois', {server: '', nick: msg.params.split(" ", 3)[1], "msg": msg.trailing});
break;
+
+ case ircNumerics.RPL_LISTSTART:
+ (function () {
+ websocket.sendClientEvent('list_start', {server: ''});
+ }());
+ break;
+ case ircNumerics.RPL_LISTEND:
+ (function () {
+ websocket.sendClientEvent('list_end', {server: ''});
+ }());
+ break;
+
+ case ircNumerics.RPL_LIST:
+ (function () {
+ var parts, channel, num_users, modes, topic;
+
+ parts = msg.params.split(' ');
+ channel = parts[1];
+ num_users = parts[2];
+ modes = msg.trailing.split(' ', 1);
+ topic = msg.trailing.substring(msg.trailing.indexOf(' ') + 1);
+
+ websocket.sendClientEvent('list_channel', {
+ server: '',
+ channel: channel,
+ topic: topic,
+ modes: modes,
+ num_users: num_users
+ });
+ }());
+ break;
+
case ircNumerics.RPL_WHOISIDLE:
params = msg.params.split(" ", 4);
rtn = {server: '', nick: params[1], idle: params[2]};
// It's a CTCP response
websocket.sendClientEvent('ctcp_response', {nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing.substr(1, msg.trailing.length - 2)});
} else {
- websocket.sendClientEvent('notice', {nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing});
+ websocket.sendClientEvent('notice', {nick: msg.nick, ident: msg.ident, hostname: msg.hostname, target: msg.params.trim(), msg: msg.trailing});
}
break;
case 'NICK':
// It's a CTCP request
if (msg.trailing.substr(1, 6) === 'ACTION') {
websocket.sendClientEvent('action', {nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing.substr(7, msg.trailing.length - 2)});
+ } else if (msg.trailing.substr(1, 4) === 'KIWI') {
+ tmp = msg.trailing.substr(6, msg.trailing.length - 2);
+ namespace = tmp.split(' ', 1)[0];
+ websocket.sendClientEvent('kiwi', {namespace: namespace, data: tmp.substr(namespace.length + 1)});
+
} else if (msg.trailing.substr(1, 7) === 'VERSION') {
ircSocket.write('NOTICE ' + msg.nick + ' :' + String.fromCharCode(1) + 'VERSION KiwiIRC' + String.fromCharCode(1) + '\r\n');
} else {
console.log("Unknown command (" + String(msg.command).toUpperCase() + ")");
}
} else {
- console.log("Malformed IRC line");
+ console.log("Malformed IRC line: " + data);
}
};
this.httpHandler = function (request, response) {
- var uri, subs, useragent, agent, server_set, server, nick, debug, touchscreen, hash,
+ var uri, uri_parts, subs, useragent, agent, server_set, server, nick, debug, touchscreen, hash,
min = {}, public_http_path;
if (kiwi.config.handle_http) {
uri = url.parse(request.url, true);
+ uri_parts = uri.pathname.split('/');
+
subs = uri.pathname.substr(0, 4);
if (uri.pathname === '/js/all.js') {
if (kiwi.cache.alljs === '') {
public_http_path = kiwi.kiwi_root + '/' + kiwi.config.public_http;
+ min.underscore = fs.readFileSync(public_http_path + 'js/underscore.min.js');
min.util = fs.readFileSync(public_http_path + 'js/util.js');
min.gateway = fs.readFileSync(public_http_path + 'js/gateway.js');
min.front = fs.readFileSync(public_http_path + 'js/front.js');
min.iscroll = fs.readFileSync(public_http_path + 'js/iscroll.js');
- min.ast = jsp.parse(min.util + min.gateway + min.front + min.iscroll);
+ min.ast = jsp.parse(min.underscore + min.util + min.gateway + min.front + min.iscroll);
min.ast = pro.ast_mangle(min.ast);
min.ast = pro.ast_squeeze(min.ast);
min.final_code = pro.gen_code(min.ast);
request.addListener('end', function () {
kiwi.fileServer.serve(request, response);
});
- } else if (uri.pathname === '/') {
- useragent = (response.headers) ? response.headers['user-agent'] : '';
- if (useragent.indexOf('android') !== -1) {
+ } else if (uri.pathname === '/' || uri_parts[1] === 'client') {
+ useragent = (typeof request.headers === 'string') ? request.headers['user-agent'] : '';
+ if (useragent.match(/android/i) !== -1) {
agent = 'android';
touchscreen = true;
- } else if (useragent.indexOf('iphone') !== -1) {
+ } else if (useragent.match(/iphone/) !== -1) {
agent = 'iphone';
touchscreen = true;
- } else if (useragent.indexOf('ipad') !== -1) {
+ } else if (useragent.match(/ipad/) !== -1) {
agent = 'ipad';
touchscreen = true;
- } else if (useragent.indexOf('ipod') !== -1) {
+ } else if (useragent.match(/ipod/) !== -1) {
agent = 'ipod';
touchscreen = true;
} else {
agent = 'normal';
touchscreen = false;
}
+ agent = 'normal';
+ touchscreen = false;
- if (uri.query) {
- server_set = ((typeof uri.query.server !== 'undefined') && (uri.query.server !== ''));
- server = uri.query.server || 'irc.anonnet.org';
- nick = uri.query.nick || '';
- debug = (uri.query.debug !== '');
+ if (uri_parts[1] !== 'client') {
+ if (uri.query) {
+ server_set = ((typeof uri.query.server !== 'undefined') && (uri.query.server !== ''));
+ server = uri.query.server || 'irc.anonnet.org';
+ nick = uri.query.nick || '';
+ debug = (uri.query.debug !== '');
+ } else {
+ server_set = false;
+ server = 'irc.anonnet.org';
+ nick = '';
+ }
} else {
- server_set = false;
- server = 'irc.anonnet.org';
- nick = '';
+ server_set = ((typeof uri_parts[2] !== 'undefined') && (uri_parts[2] !== ''));
+ server = server_set ? uri_parts[2] : 'irc.anonnet.org';
+ nick = uri.query.nick || '';
}
+
response.setHeader('X-Generated-By', 'KiwiIRC');
hash = crypto.createHash('md5').update(touchscreen ? 't' : 'f').update(debug ? 't' : 'f').update(server_set ? 't' : 'f').update(server).update(nick).update(agent).update(JSON.stringify(kiwi.config)).digest('base64');
if (kiwi.cache.html[hash]) {
websocket.sendClientEvent = function (event_name, data) {
var ev = kiwi.kiwi_mod.run(event_name, data, {websocket: this});
- if(ev === null) return;
+ if (ev === null) {
+ return;
+ }
data.event = event_name;
websocket.emit('message', data);
websocket.sendServerLine = function (data, eol) {
eol = (typeof eol === 'undefined') ? '\r\n' : eol;
- websocket.ircSocket.write(data + eol);
+
+ try {
+ websocket.ircSocket.write(data + eol);
+ } catch (e) { }
};
websocket.on('irc connect', kiwi.websocketIRCConnect);
}
websocket.sendServerLine('CAP LS');
websocket.sendServerLine('NICK ' + nick);
- websocket.sendServerLine('USER ' + nick.replace(/[^0-9a-zA-Z\-_.]/, '') + '_kiwi 0 0 :' + nick);
+ websocket.sendServerLine('USER kiwi_' + nick.replace(/[^0-9a-zA-Z\-_.]/, '') + ' 0 0 :' + nick);
if ((callback) && (typeof (callback) === 'function')) {
callback();
break;
case 'action':
if ((args.target) && (args.msg)) {
- websocket.sendServerLine('PRIVMSG ' + args.target + ' :\ 1' + String.fromCharCode(1) + 'ACTION ' + args.msg + String.fromCharCode(1));
+ websocket.sendServerLine('PRIVMSG ' + args.target + ' :' + String.fromCharCode(1) + 'ACTION ' + args.msg + String.fromCharCode(1));
}
break;
+
+ case 'kiwi':
+ if ((args.target) && (args.data)) {
+ websocket.sendServerLine('PRIVMSG ' + args.target + ' :' + String.fromCharCode(1) + 'KIWI ' + args.data + String.fromCharCode(1));
+ }
+ break;
+
case 'raw':
websocket.sendServerLine(args.data);
break;
/*
* KiwiIRC controlling via STDIN
*/
-this.startControll = function () {
- process.stdin.resume();
- process.stdin.on('data', function (chunk) {
- var parts = chunk.toString().trim().split(' ');
- switch (parts[0]) {
- case 'rehash':
- console.log('Rehashing...');
- console.log(kiwi.rehash() ? 'Rehash complete' : 'Rehash failed');
- break;
-
- case 'recode':
- console.log('Recoding...');
- console.log(kiwi.recode() ? 'Recode complete' : 'Recode failed');
- break;
-
- case 'mod':
- if (parts[1] === 'reload') {
- console.log('Reloading module (' + parts[2] + ')..');
- kiwi.kiwi_mod.reloadModule(parts[2]);
- }
- break;
+this.manageControll = function (data) {
+ var parts = data.toString().trim().split(' '),
+ connections_cnt = 0,
+ i;
+ switch (parts[0]) {
+ case 'rehash':
+ console.log('Rehashing...');
+ console.log(kiwi.rehash() ? 'Rehash complete' : 'Rehash failed');
+ break;
+
+ case 'recode':
+ console.log('Recoding...');
+ console.log(kiwi.recode() ? 'Recode complete' : 'Recode failed');
+ break;
+
+ case 'mod':
+ if (parts[1] === 'reload') {
+ console.log('Reloading module (' + parts[2] + ')..');
+ kiwi.kiwi_mod.reloadModule(parts[2]);
+ }
+ break;
+
+ case 'cache':
+ if (parts[1] === 'clear') {
+ kiwi.cache.html = {};
+ kiwi.cache.alljs = '';
+ console.log('HTML cache cleared');
+ }
+ break;
- default:
- console.log('Unknown command \'' + parts[0] + '\'');
- }
- });
-};
\ No newline at end of file
+ case 'status':
+ for (i in kiwi.connections) {
+ connections_cnt = connections_cnt + parseInt(kiwi.connections[i].count, 10);
+ }
+ console.log(connections_cnt.toString() + ' connected clients');
+ break;
+
+ default:
+ console.log('Unknown command \'' + parts[0] + '\'');
+ }
+};