Skip to content

Commit

Permalink
lots more changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kkaefer committed Jan 14, 2011
1 parent 14219d1 commit 1a7b16d
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 92 deletions.
7 changes: 6 additions & 1 deletion config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ exports.xmpp = {
// host: 'jabber.org',
// jid: 'jabber.org',
// muc: 'conference.jabber.org'

host: 'localhost',
jid: 'localhost',
muc: 'conference.localhost'
muc: 'conference.localhost',

host: 'chat.developmentseed.org',
jid: 'chat.developmentseed.org',
muc: 'conference.chat.developmentseed.org'
};

exports.irc = {
Expand Down
14 changes: 11 additions & 3 deletions lib/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,22 @@ exports.xmlFind = function find(xml, name) {

exports.xmlPath = function path(xml, path) {
path = path.split('.');
xml = [ xml ];

for (var k = 0; k < path.length; k++) {
for (var i = 0; i < xml.length; i++) {
if (xml[i].$name === path[k]) xml = xml[i];
var elements = [];
for (var j = 0; j < xml.length; j++) {
for (var i = 0; i < xml[j].length; i++) {
if (xml[j][i].$name === path[k]) {
elements.push(xml[j][i]);
}
}
}
if (elements.length) xml = elements;
else return;
}

return xml;
return xml[0];
};

exports.xml.auth = exports.xml.$.bind(undefined, 'auth');
Expand Down
54 changes: 46 additions & 8 deletions lib/ircd.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,23 @@ Connection.prototype.setup = function() {
}
}
});

this.stream.on('end', function() { connection.emit('end'); });
this.stream.on('close', function() { connection.emit('close'); });
};

Connection.prototype.end = function() {
this.stream.end();
switch (this.stream.readyState) {
case 'writeOnly': // The other party disconnected the stream already.
case 'open':
case 'opening':
this.stream.end();
break;
case 'readOnly': // We already ended the stream.
case 'closed': // The stream is already closed.
// Nothing to do.
break;
}
};

Connection.prototype.PASS = function(pass) {
Expand All @@ -89,6 +102,7 @@ Connection.prototype.USER = function(line) {
this.reply('003', ':This server was created ' + this.config.created);
this.reply('004', this.config.host + ' ' + this.config.name + '-' + this.config.version + ' ');

this.loggedIn = true;
this.emit('login');
};

Expand All @@ -100,7 +114,11 @@ Connection.prototype.JOIN = function(line) {
// Discard optional password.
var channel = line.split(' ', 1)[0];
var rest = line.substring(channel.length + 1);
this.emit('join', channel, rest);

var channels = channel.split(',');
for (var i = 0; i < channels.length; i++) {
this.emit('join', channels[i], rest);
}
};

Connection.prototype.MODE = function(line) {
Expand All @@ -112,38 +130,58 @@ Connection.prototype.MODE = function(line) {
Connection.prototype.PRIVMSG = function(line) {
var recipient = line.split(' ', 1)[0];
var message = line.substring(recipient.length + 1);
if (message[0] === ':') message = message.substring(1);
this.emit('privmsg', recipient, message);
};

Connection.prototype.PART = function(line) {
var channel = line.split(' ', 1)[0];
this.emit('part', channel);
}
};

Connection.prototype.PONG = function(line) {
this.emit('pong', line);
};

Connection.prototype.QUIT = function(line) {
this.emit('quit', line);
};

Connection.prototype.reply = function(code, msg) {
var str = ':' + this.config.name + ' ' + code + ' ' + this.user.nick + ' ' + msg + '\r\n';
console.log(GREEN('IRC out>> ' + util.inspect(str)));
this.stream.write(str);
};

Connection.prototype.error = function(msg) {
var str = 'ERROR :' + msg + '\r\n';
console.log(GREEN('IRC out>> ' + util.inspect(str)));
this.stream.write(str);
};

Connection.prototype.command = function(cmd, msg, user) {
var str = ':' + (user || (this.user.nick + '!' + this.user.user)) + ' ' + cmd + ' ' + msg + '\r\n';
console.log(GREEN('IRC out>> ' + util.inspect(str)));
this.stream.write(str);
}
};



exports.sanitizeNick = function(str) {
var nick = str.replace(/([^\x30-\x7D-]|@)+/g, '_');
if (nick.match(/^[\x5B-\x60\x7B-\x7D-]/)) nick = '_' + nick;
return nick;
// This is how it should be according to RFC:
// return str.replace(/([^\x30-\x7D-]|@)+/g, '_');

// Most clients support UTF-8, however, so we just strip control characters.
// We replace spaces with a non-breaking space because they really aren't allowed.
return str.replace(/ /g, '\u00A0').replace(/[\x00-\x2F@]+/g, '_');
};

exports.sanitizeUser = function(str) {
return str.replace(/[\0\r\n @]+/g, '_');
}
};

exports.sanitizeMessage = function(str) {
return str.replace(/\r?\n/g, ' ');
};


58 changes: 33 additions & 25 deletions lib/xmpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,12 @@ Connection.prototype.createParser = function() {
cb.onEndElementNS(function(elem, prefix, uri) {
var element = tree.shift();
if (tree.length === 1) {
// if (element.$name === 'iq' && ) {
// xml.$render(xml.iq({ from: element.to, to: element.from, id: element.id, type: 'result' }));
// }
// else
if (element.id && (element.id in self.requests)) {
// If the response has an ID associated with it, call the corresponding
// function supplied when placing the request.
var command = self.requests[element.id];
command.call(self, element);
}
// else if (element.$name in self) {
// self[element.$name](element);
// }
else {
self.emit(element.$name, element);
}
Expand All @@ -121,27 +114,27 @@ Connection.prototype.setupStream = function() {

this.stream = net.createConnection(this.config.port, this.config.host);
this.stream.setEncoding('ascii');
this.stream.on('error', function(err) { self.emit('error'); });
this.stream.on('connect', function() { self.initStream(); });
this.stream.on('secure', function() { self.initStream(); });
this.stream.on('data', function(str) {
console.log(BLUE('in <- ' + str));
self.parser.parseString(str);
});
this.stream.on('end', function() { self.emit('end'); });
this.stream.on('close', function() { self.emit('close'); });
};

Connection.prototype.setupHandlers = function() {
this.on('error', function(error) {
console.log(error);
});

this.once('features', function(features) {
if (find(features, 'starttls').length)
this.startTLS();
else
else {
this.emit('error', 'Server does not support STARTTLS.');

// DEBUG: Proceed anyway without SSL!
this.detectFeatures(features);
}
});
};

Expand Down Expand Up @@ -204,10 +197,20 @@ Connection.prototype.authenticate = function(user) {
};

Connection.prototype.end = function() {
console.log(PURPLE('out -> ' + '</stream:stream>'));
this.stream.write('</stream:stream>');
this.stream.end();
}
switch (this.stream.readyState) {
case 'writeOnly': // The other party disconnected the stream already.
case 'open':
case 'opening':
console.log(PURPLE('out -> ' + '</stream:stream>'));
this.stream.end('</stream:stream>');
break;
case 'readOnly': // We already ended the stream.
case 'closed': // The stream is already closed.
// Nothing to do.
break;

}
};

Connection.prototype.request = function(stanza, callback) {
var id = 'medium' + (this.uniqueID++);
Expand All @@ -232,7 +235,7 @@ Connection.prototype.bind = function() {
this.request(
xml.iq({ type: 'set' }, xml.bind({ xmlns: 'urn:ietf:params:xml:ns:xmpp-bind' })),
function(response) {
this.user = new JID(path(response, 'iq.bind.jid').$body);
this.user = new JID(path(response, 'bind.jid').$body);
this.emit('bind');
}
);
Expand All @@ -254,34 +257,39 @@ Connection.prototype.startSession = function() {
Connection.prototype.roomInfo = function(roomJID, callback) {
var query = xml.query({ xmlns: 'http://jabber.org/protocol/disco#info' });
var stanza = xml.iq({ type: 'get', to: roomJID }, query);
this.request(stanza, callback || noop);
this.request(stanza, callback);
};

Connection.prototype.roomItems = function(roomJID, callback) {
var query = xml.query({ xmlns: 'http://jabber.org/protocol/disco#items' });
var stanza = xml.iq({ type: 'get', to: roomJID }, query);
this.request(stanza, callback || noop);
}
this.request(stanza, callback);
};

Connection.prototype.roomPresence = function(nickJID, callback) {
var capability = xml.x({ xmlns: 'http://jabber.org/protocol/muc' });
var stanza = xml.presence({ to: nickJID }, capability);
this.request(stanza, callback || noop);
this.request(stanza, callback);
};

Connection.prototype.roomMessage = function(roomJID, message, callback) {
var body = xml.body(null, message);
var stanza = xml.message({ to: roomJID, type: 'groupchat' }, body);
this.request(stanza, callback || noop);
}
this.request(stanza, callback);
};

Connection.prototype.roomNick = function(nickJID, callback) {
var stanza = xml.presence({ to: nickJID });
this.request(stanza, callback || noop);
this.request(stanza, callback);
};

Connection.prototype.leaveRoom = function(roomJID) {
var stanza = xml.presence({ to: roomJID, type: 'unavailable' });
this.request(stanza);
}
};

Connection.prototype.userMessage = function(userJID, message, callback) {
var body = xml.body(null, message);
var stanza = xml.message({ to: userJID, type: 'chat' }, body);
this.request(stanza, callback);
};
Loading

0 comments on commit 1a7b16d

Please sign in to comment.