Mercurial > psgxs
changeset 56:99bd1d1ac071
Migration to node-xmpp, done!
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Wed, 10 Aug 2011 15:11:22 -0700 |
parents | fd69d35cf2e6 |
children | addbf6bbfaa8 |
files | backends/directory.js backends/file.js configuration.js errors.js fdsq.js forms.js modules.js modules/mod_disco.js modules/mod_http.js modules/mod_owner.js modules/mod_publish.js modules/mod_publish_message.js nodes.js notifs.js psgxs.js storage.js |
diffstat | 16 files changed, 161 insertions(+), 186 deletions(-) [+] |
line wrap: on
line diff
--- a/backends/directory.js +++ b/backends/directory.js @@ -74,6 +74,7 @@ backend.save = function(dir) { } backend.load = function(dir) { + var parse = require('ltx').parse; if (!dir) dir = 'data'; @@ -86,23 +87,11 @@ backend.load = function(dir) { } fs.readdir(dir, function(err, files) { - var xmpp = require('xmpp'); - function parseStanza(path, content) { - var stanza = null; - var stream = new xmpp.Stream({ - stanza: function (stanza) { - path[content] = stanza; - } - }); - stream.opened = true; - stream.data(path[content]); - } - function endParsing(o) { var regexp = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ/; for (var i in o) { if (typeof o[i] == 'string' && i == 'content') - parseStanza(o, i); + o[i] = parse(o[i]); else if (typeof o[i] == 'string' && regexp(o[i])) { var today = new Date(); today.setFromISO8601(o[i]); @@ -120,6 +109,9 @@ backend.load = function(dir) { if (/^\./.test(file)) continue; + if (!/\.json$/.test(file)) + continue; + var nodeID = decodeURI(file.replace(/\.json$/, '').replace('%2f', '/')); var data = fs.readFileSync(dir+'/'+file).toString();
--- a/backends/file.js +++ b/backends/file.js @@ -50,23 +50,12 @@ backend.save = function(file) { } backend.load = function(file) { - var xmpp = require('xmpp'); - function parseStanza(path, content) { - var stanza = null; - var stream = new xmpp.Stream({ - stanza: function (stanza) { - path[content] = stanza; - } - }); - stream.opened = true; - stream.data(path[content]); - } - + var parse = require('ltx').parse; function endParsing(o) { var regexp = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ/; for (var i in o) { if (typeof o[i] == 'string' && i == 'content') - parseStanza(o, i); + o[i] = parse(o[i]); else if (typeof o[i] == 'string' && regexp(o[i])) { var today = new Date(); today.setFromISO8601(o[i]);
--- a/configuration.js +++ b/configuration.js @@ -21,18 +21,17 @@ var config = exports; -config.jid = 'pubsub.example.org'; +config.jid = 'pubsub.ubuntu'; config.password = 'hellohello'; -config.host = 'localhost'; -config.port = 5347; -config.superOwner = ['you@example.com']; +config.superOwner = ['you@ubuntu']; config.version = '0.1'; config.os = 'GNU/Linux'; -config.allowCreateNode = [/@example\.com$/]; // value is an array of RegExp JIDs. If only super-owner should be able to create nodes, use []. +config.allowCreateNode = [/@ubuntu$/]; // value is an array of RegExp JIDs. If only super-owner should be able to create nodes, use []. config.backend = 'directory'; // Put backends in “backends” directory. config.access = 'open'; // values include open, whitelist (by members) and authorize (owners of the node receive notification). presence and roster aren’t implemented yet. config.pluginsDir = 'modules'; config.hideNonAccessibleNodes = true; +config.debug = true; config.activated = [ 'auto-create',
--- a/errors.js +++ b/errors.js @@ -197,20 +197,22 @@ var reverse = {}; })(errors); exports.makeError = function(response, errorNumber, payload) { - response.attr.type = 'error'; + response.attrs.type = 'error'; if (payload) response.cnode(payload); var e = reverse[errorNumber]; - response.c('error', {type: e.type}); - response.c(e.error, {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up(); + var Element = require('ltx').Element; + var error = new Element('error', {type: e.type}); + error.c(e.error, {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up(); + response.cnode(error); if (e.reason) { if (e.feature) - response.c(e.reason, {xmlns: 'http://jabber.org/protocol/pubsub#errors', feature: e.feature}); + error.c(e.reason, {xmlns: 'http://jabber.org/protocol/pubsub#errors', feature: e.feature}).up(); else - response.c(e.reason, {xmlns: 'http://jabber.org/protocol/pubsub#errors'}); + error.c(e.reason, {xmlns: 'http://jabber.org/protocol/pubsub#errors'}).up(); } return response;
--- a/fdsq.js +++ b/fdsq.js @@ -19,41 +19,14 @@ 'use strict'; -var sha1hex = require('sha1').hex; +var JID = require('node-xmpp').JID; var fdsq = exports; -fdsq.makeRandomId = function() { - return sha1hex(Date()+Math.random()); -}; - -var JID = function(jid) { - this.full = jid; - - var s = jid.indexOf('/'); - if (s == -1) - this.resource = ''; - else { - this.resource = jid.substring(s+1); - jid = jid.substr(0, s); - } - - var a = jid.indexOf('@'); - if (a == -1) { - this.user = ''; - this.server = jid; - } else { - this.user = jid.substr(0, a); - this.server = jid.substr(a+1); - } - this.bare = jid; -}; fdsq.toBare = function(jid) { - var j = new JID(jid); - return j.bare; + return new JID(jid).bare().toString(); }; fdsq.toResource = function(jid) { - var j = new JID(jid); - return j.resource; + return new JID(jid).resource; };
--- a/forms.js +++ b/forms.js @@ -19,7 +19,7 @@ 'use strict'; -var xmpp = require('xmpp') +var Element = require('ltx').Element; var service_configuration = require('./configuration').service_configuration; var parseBoolean = function(b) { @@ -29,7 +29,7 @@ var parseBoolean = function(b) { } exports.build = function(type, desc, content, labels, title, instructions) { - var x = xmpp.stanza('x', {xmlns: 'jabber:x:data', type: type}); + var x = new Element('x', {xmlns: 'jabber:x:data', type: type}); if (typeof desc == 'string') desc = service_configuration[desc];
--- a/modules.js +++ b/modules.js @@ -31,7 +31,8 @@ var fdsq = require('./fdsq'); var sandbox = { process: process, config: require('./configuration'), - xmpp: require('xmpp'), + Element: require('ltx').Element, + uuid: require('uuid'), errors: require('./errors'), forms: require('./forms'), makeError: require('./errors').makeError, @@ -39,7 +40,6 @@ var sandbox = { NS: require('./namespaces'), require: require, storage: require('./storage'), - makeRandomId: fdsq.makeRandomId, JID: { toBare: fdsq.toBare, toResource: fdsq.toResource @@ -54,11 +54,11 @@ for (var i in files) { fs.readFile(dir + '/' + file, function(err, data) { if (err) { - console.log('ERROR: loading module “'+file+'”.'); // FIXME: file is always the last file of the list… + console.log('Erreur de chargement de module.'); return; } - Script.runInNewContext(data, sandbox, dir + '/' + file); // FIXME: the same. + Script.runInNewContext(data, sandbox, dir + '/' + file); var module = sandbox.exports; sandbox.exports = {}; @@ -67,6 +67,7 @@ for (var i in files) { console.log('WARNING: module '+j+' already loaded.'); modules[j] = module[j]; + console.log('Module '+j+' loaded!'); } }); }
--- a/modules/mod_disco.js +++ b/modules/mod_disco.js @@ -53,7 +53,7 @@ exports.disco_info = { // SECTION 5.1: Discover Features } else { - response.c('query', {xmlns: NS.DISCO_INFO}) + var query = new Element('query', {xmlns: NS.DISCO_INFO}) .c('identity', {category: 'pubsub', type: 'service', name: 'PubSub JavaScript Server'}).up() .c('feature', {'var': NS.DISCO_INFO}).up() .c('feature', {'var': NS.DISCO_ITEMS}).up() @@ -61,9 +61,11 @@ exports.disco_info = { .c('feature', {'var': 'jabber:iq:version'}).up() .c('feature', {'var': NS.COMMANDS}).up(); + response.cnode(query); + for (var i in config.activated) if (typeof i == 'string') - response.c('feature', {'var': 'http://jabber.org/protocol/pubsub#' + config.activated[i]}).up(); + query.c('feature', {'var': 'http://jabber.org/protocol/pubsub#' + config.activated[i]}).up(); } return response;
--- a/modules/mod_http.js +++ b/modules/mod_http.js @@ -31,7 +31,6 @@ var regex = /^mod_.*\.js/; var Script = process.binding('evals').Script; var sandbox = { config: require('./configuration'), - xmpp: require('xmpp'), errors: require('./errors'), forms: require('./forms'), makeError: require('./errors').makeError,
--- a/modules/mod_owner.js +++ b/modules/mod_owner.js @@ -35,7 +35,7 @@ exports.create = { if (!nodeID || nodeID == '') { if (!config.enabled('instant-nodes')) return makeError(response, errors.owner.create.instant_nodes_not_supported.n); - nodeID = makeRandomId(); + nodeID = uuid(); instant = true; } if (storage.existsNode(nodeID))
--- a/modules/mod_publish.js +++ b/modules/mod_publish.js @@ -51,7 +51,7 @@ exports.publish = { var itemID = item.getAttribute('id'); if (!config.enabled('item-ids') && itemID) return makeError(response, errors.itemid_required.n); - itemID = itemID? itemID: makeRandomId(); + itemID = itemID? itemID: uuid(); if (item.tags.length != 1) return makeError(response, errors.pub.publish.bad_payload.n);
--- a/modules/mod_publish_message.js +++ b/modules/mod_publish_message.js @@ -46,7 +46,7 @@ exports.publishMessage = { if (!config.enabled('item-ids')) return makeError(response, errors.itemid_required.n); - var itemID = makeRandomId(); + var itemID = uuid(); var now = new Date();
--- a/nodes.js +++ b/nodes.js @@ -24,7 +24,7 @@ var errors = require('./errors'); var config = require('./configuration'); var service_configuration = config.service_configuration; var Configuration = config.Configuration; -var makeRandomId = require('./fdsq').makeRandomId; +var uuid = require('uuid'); exports.Item = function() { this.content = null; @@ -94,7 +94,7 @@ exports.Node.prototype = { if (this.subscribers[jid]) subid = this.subscribers[jid].subid; else - subid = makeRandomId(); + subid = uuid(); } this.subscribers[jid] = {
--- a/notifs.js +++ b/notifs.js @@ -1,6 +1,6 @@ 'use strict'; -var xmpp = require('xmpp'); +var Element = require('ltx').Element; var storage = require('./storage'); var config = require('./configuration'); var conn; @@ -14,24 +14,24 @@ function _(obj, color) { }; exports.send = function(notifs, type, nodeID, a1, a2) { - var ev = xmpp.stanza('event', {xmlns: 'http://jabber.org/protocol/pubsub#event'}); + var ev = new Element('event', {xmlns: 'http://jabber.org/protocol/pubsub#event'}); if (type == 'affiliations') { - ev.attr.xmlns = 'http://jabber.org/protocol/pubsub'; + ev.attrs.xmlns = 'http://jabber.org/protocol/pubsub'; var args = {}; for (i in a1) { - var attr = a1[i]; + var attrs = a1[i]; if (i == 'affiliation') - args.affiliation = attr; + args.affiliation = attrs; else if (i == 'jid') - args.jid = attr; + args.jid = attrs; } - var affiliations = xmpp.stanza('affiliations', {node: nodeID}) + var affiliations = new Element('affiliations', {node: nodeID}) .c('affiliation', args); ev.cnode(affiliations); } else if (type == 'collection') { - var collection = xmpp.stanza('collection', {node: nodeID}); + var collection = new Element('collection', {node: nodeID}); if (a1 == 'associate') collection.cnode('associate', {node: nodeID}); else @@ -43,7 +43,7 @@ exports.send = function(notifs, type, no return; } - var configuration = xmpp.stanza('configuration', {node: nodeID}); + var configuration = new Element('configuration', {node: nodeID}); if (a1) { var x = forms.build('node_config', config.service_configuration.node_config, storage.getConfiguration(nodeID)); if (x) @@ -51,12 +51,12 @@ exports.send = function(notifs, type, no } ev.cnode(configuration); } else if (type == 'delete') { - var del = xmpp.stanza('delete', {node: nodeID}); + var del = new Element('delete', {node: nodeID}); if (a1) del.c('redirect', {uri: a1}); ev.cnode(del); } else if (type == 'items') { - var items = xmpp.stanza(type, {node: nodeID}); + var items = new Element(type, {node: nodeID}); if (a2 == 'retract') for (var i in a1) items.s('retract', {id: i}); @@ -70,7 +70,7 @@ exports.send = function(notifs, type, no args.node = item.node; if (item.publisher) args.publisher = item.publisher; - var it = xmpp.stanza('item', args); + var it = new Element('item', args); if (item.content) it.cnode(item.content); items.cnode(it); @@ -85,24 +85,24 @@ exports.send = function(notifs, type, no var args = {node: nodeID}; for (i in a1) { - var attr = a1[i]; + var attrs = a1[i]; if (i == 'subscription') { - if (attr == 'none' || attr == 'pending' || attr == 'subscribed' || attr == 'unconfigured') - args[i] = attr; + if (attrs == 'none' || attrs == 'pending' || attrs == 'subscribed' || attrs == 'unconfigured') + args[i] = attrs; else { _('Error #3', 41) return; } } else if (i == 'jid' || i == 'subid') - args[i] = attr; + args[i] = attrs; else if (i == 'expiry') - args[i] = attr.toString(); + args[i] = attrs.toString(); } if (!args.jid || args.jid == '') { _('Error #2', 41) return; } - var sub = xmpp.stanza('subscription', args); + var sub = new Element('subscription', args); ev.cnode(sub); } else { _('Error #1', 41) @@ -151,7 +151,7 @@ exports.send = function(notifs, type, no } } - var message = xmpp.message({to: i, from: config.jid, id: conn.getUniqueId(), type: 'headline'}); + var message = new Element('message', {to: i, from: config.jid, id: conn.getUniqueId(), type: 'headline'}); message.cnode(ev); conn.send(message); } @@ -162,7 +162,7 @@ exports.sendDigest = function(jid, nodeI if (sub.digestTimeout) sub.digestTimeout = false; - var message = xmpp.message({to: jid, from: config.jid, id: conn.getUniqueId(), type: 'headline'}); + var message = new Element('message', {to: jid, from: config.jid, id: conn.getUniqueId(), type: 'headline'}); for (var i in sub.digest) message.cnode(sub.digest[i]); conn.send(message);
--- a/psgxs.js +++ b/psgxs.js @@ -19,31 +19,61 @@ * along with PSĜS. If not, see <http://www.gnu.org/licenses/>. */ -'use strict'; +//'use strict'; + +var config = require('./configuration'); + +var xmpp = require('node-xmpp'); +var conn = new xmpp.Component({ + jid: config.jid, + password: config.password, + host: 'localhost', + port: 5347 +}); + +if (config.debug) + (function() { + var send = conn.send; + conn.send = function(s) { + console.log('Sent: [1;32m' + s + '[0m'); + send.call(conn, s); + }; + })(); -var xmpp = require('xmpp'); -var sha1 = require('sha1'); +conn.on('stanza', function (stanza) { + if (config.debug) + console.log('Recv: [1;34m' + stanza + '[0m'); + + if (stanza.is('iq')) + onIq(stanza); + else if (stanza.is('message')) + onMessage(stanza); + else if (stanza.is('presence')) + onPresence(stanza); +}); + +conn._uniqueId = 42; +conn.getUniqueId = function(suffix) { + return ++this._uniqueId + (suffix?(":"+suffix):""); +}; + +var Element = xmpp.Element; +Element.prototype.getAttribute = function(name) { + return this.attrs[name]; +}; + + require('./iso8601'); var storage = require('./storage'); var errors = require('./errors'); var makeError = errors.makeError; -var fdsq = require('./fdsq'); -var toBare = fdsq.toBare; -var config = require('./configuration'); var forms = require('./forms'); -var conn = new xmpp.Connection(config.host, config.port); var notifs = require('./notifs'); notifs.setConnection(conn); var modules = require('./modules'); -var service_configuration = config.service_configuration; -var componentJID = config.jid; -var componentPassword = config.password; - -conn.log = function (_, m) { console.log(m); }; - function _(obj, color) { var str = require('sys').inspect(obj, false, null); if (color) @@ -56,17 +86,6 @@ process.addListener('uncaughtException', console.log('\x1b[41;1mUncaught exception (' + err + '), this should never happen:\x1b[0m\n' + err.stack); }); -if (typeof xmpp.StanzaBuilder.cnode != 'function' || typeof xmpp.StanzaBuilder.prototype.cnode != 'function') { - xmpp.StanzaBuilder.prototype.cnode = function (stanza) - { - var parent = this.last_node[this.last_node.length-1]; - parent.tags.push(stanza); - parent.children.push(stanza); - this.last_node.push(stanza); - return this; - }; -} - function onIq(stanza) { var type = stanza.getAttribute('type'); var from = stanza.getAttribute('to'); @@ -75,45 +94,24 @@ function onIq(stanza) { var response; if (id) - response = xmpp.iq({to: to, from: from, type: 'result', id: id}); - else - response = xmpp.iq({to: to, from: from, type: 'result'}); + response = new Element('iq', {to: to, from: from, type: 'result', id: id}); + else + response = new Element('iq', {to: to, from: from, type: 'result'}); var send = {}; - for (var i in stanza.tags) { - var child1 = stanza.tags[i]; - if (child1.name == 'pubsub') { - for (var j in child1.tags) { - var child2 = child1.tags[j]; - - for (var k in modules) { - var module = modules[k]; - - if (module.stanza && (module.stanza != 'iq')) - continue; - - if (module.type && (module.type != type)) - continue; + if (stanza.children.length != 1) + return makeError(response, errors.bad_request.n); - if (module.child2 && (module.child2 != child2.name)) - continue; - - if (module.ns && (module.ns != child2.attr.xmlns)) - continue; - - if (module.number && (module.number != j)) - continue; + var payload = stanza.children[0]; + var tag = payload.name; + var ns = payload.attrs.xmlns; + var contents = payload.children; + + if (tag == 'pubsub') { + for (var j in contents) { + var child = contents[j]; - send.response = module.func(response, stanza, child2, to, from); - if (send.response) { - response = send.response; - send.good = true; - delete send.response; - } - } - } - } else { for (var k in modules) { var module = modules[k]; @@ -123,16 +121,19 @@ function onIq(stanza) { if (module.type && (module.type != type)) continue; - if (module.child && (module.child != child1.name)) + if (module.child && (module.child != tag)) continue; - if (module.ns && (module.ns != child1.attr.xmlns)) + if (module.ns && (module.ns != child.getNS())) + continue; + + if (module.child2 && (module.child2 != child.name)) continue; if (module.number && (module.number != k)) continue; - send.response = module.func(response, stanza, child1, to, from); + send.response = module.func(response, stanza, payload, to, from); if (send.response) { response = send.response; send.good = true; @@ -140,6 +141,32 @@ function onIq(stanza) { } } } + } else { + for (var k in modules) { + var module = modules[k]; + + if (module.stanza && (module.stanza != 'iq')) + continue; + + if (module.type && (module.type != type)) + continue; + + if (module.child && (module.child != tag)) + continue; + + if (module.ns && (module.ns != ns)) + continue; + + if (module.number && (module.number != k)) + continue; + + send.response = module.func(response, stanza, payload, to, from); + if (send.response) { + response = send.response; + send.good = true; + delete send.response; + } + } } conn.send(send.good? response: makeError(response, errors.feature_not_implemented.n)); @@ -152,14 +179,14 @@ function onMessage(stanza) { var response; if (id) - response = xmpp.message({to: to, from: from, id: id}); + response = new Element('message', {to: to, from: from, id: id}); else - response = xmpp.message({to: to, from: from}); + response = new Element('message', {to: to, from: from}); var send = false; - for (var i in stanza.tags) { - var child = stanza.tags[i]; + for (var i in stanza.children) { + var child = stanza.children[i]; for (var k in modules) { var module = modules[k]; @@ -172,7 +199,7 @@ function onMessage(stanza) { if (module.child && (module.child != child.name)) continue; - if (module.ns && (module.ns != child.attr.xmlns)) + if (module.ns && (module.ns != child.attrs.xmlns)) continue; if (module.number && (module.number != k)) @@ -221,27 +248,18 @@ function onPresence(stanza) { var response; if (id) - response = xmpp.presence({to: to, from: from, id: id}); + response = new Element('presence', {to: to, from: from, id: id}); else - response = xmpp.presence({to: to, from: from}); + response = new Element('presence', {to: to, from: from}); makeError(response, errors.feature_not_implemented.n); } -conn.connect(componentJID, componentPassword, function (status, condition) { - if (status == xmpp.Status.CONNECTED) { - conn.addHandler(onMessage, null, 'message', null, null, null); - conn.addHandler(onIq, null, 'iq', null, null, null); - conn.addHandler(onPresence, null, 'presence', null, null, null); +if (process.argv.length >= 3) + storage.load(process.argv[2]); +else + storage.load(); - if (process.argv.length >= 3) - storage.load(process.argv[2]); - else - storage.load(); - - var stdin = process.openStdin(); - stdin.setEncoding('utf8'); - stdin.addListener('data', storage.debug); - } else - conn.log(xmpp.LogLevel.DEBUG, 'New connection status: ' + status + (condition? (' ('+condition+')'): '')); -}); +var stdin = process.openStdin(); +stdin.setEncoding('utf8'); +stdin.addListener('data', storage.debug);
--- a/storage.js +++ b/storage.js @@ -20,7 +20,6 @@ 'use strict'; var fs = require('fs'); -var sha1hex = require('sha1').hex; require('./iso8601'); var errors = require('./errors'); var config = require('./configuration'); @@ -28,6 +27,7 @@ var service_configuration = config.servi var Configuration = config.Configuration; var fdsq = require('./fdsq'); var toBare = fdsq.toBare; +var uuid = require('uuid'); var nodes = require('./nodes'); var Node = nodes.Node; @@ -208,7 +208,7 @@ storage.setItem = function(nodeID, itemI return node; if (typeof itemID != 'string') - itemID = fdsq.makeRandomId(); + itemID = uuid(); var i = node.setItem(itemID, content); if (content)