# HG changeset patch # User Emmanuel Gil Peyrot # Date 1288889452 -3600 # Node ID b2faacfefb90c4bd4641d90b81a2e31272fc9208 # Parent e007a6364bf0900f5e849e69b474672792c544cc Rewrite of the module manager; fix of some modules; fix of the directory backend. diff --git a/backends/directory.js b/backends/directory.js --- a/backends/directory.js +++ b/backends/directory.js @@ -54,26 +54,19 @@ backend.save = function(dir) { var inspect = require('sys').inspect; + for (var nodeID in data) + fs.writeFile(dir+'/'+nodeID+'.json', inspect(data[nodeID], false, null)); + var toDelete = []; for (var i in files) { - var nodeID = files[i]; - if (nodeID in data) { - fs.writeFile(dir+'/'+nodeID+'.json', inspect(data[nodeID], false, null)); - delete data[nodeID]; - } else - toDelete.push(nodeID); + var file = files[i]; + if (!(file.replace(/\.json$/, '') in data)) + toDelete.push(file); } - for (var nodeID in data) { - inspect(nodeID); - inspect(data[nodeID]); - fs.writeFile(dir+'/'+nodeID+'.json', inspect(data[nodeID], false, null)); - } - - for (var nodeID in toDelete) { - fs.unlink(toDelete[nodeID]); - } + for (var nodeID in toDelete) + fs.unlink(dir+'/'+toDelete[nodeID]); }); }); } diff --git a/modules.js b/modules.js --- a/modules.js +++ b/modules.js @@ -9,6 +9,10 @@ for (var i in files) { continue; var module = require('./modules/' + files[i]); - for (var j in module) + for (var j in module) { + if (typeof modules[j] != 'undefined') + console.log('WARNING: module '+j+' already loaded.'); + modules[j] = module[j]; + } } diff --git a/modules/mod_adhoc.js b/modules/mod_adhoc.js --- a/modules/mod_adhoc.js +++ b/modules/mod_adhoc.js @@ -7,7 +7,7 @@ var toBareJID = require('../util').toBar var NS = require('../namespaces'); // XEP-0050: Ad-Hoc Commands -exports.configureSub = { +exports.adHoc = { type: 'set', child: 'command', ns: NS.COMMANDS, diff --git a/modules/mod_configure.js b/modules/mod_configure.js --- a/modules/mod_configure.js +++ b/modules/mod_configure.js @@ -11,7 +11,7 @@ exports.getConfigure = { type: 'get', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'configure', + child2: 'configure', func: function(response, stanza, request, to) { if (!config.enabled('config-node')) return makeError(response, errors.owner.configure.node_configuration_not_supported.n); @@ -26,10 +26,14 @@ exports.getConfigure = { if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only') return makeError(response, errors.pub.publish.insufficient_privileges.n); + var conf = storage.getConfiguration(nodeID); + if (!conf) + return makeError(response, 42); // FIXME + response.c('pubsub', {xmlns: NS.PUBSUB_OWNER}); response.c('configure', {node: nodeID}); - var form = forms.build('form', 'node_config', 'default', true); + var form = forms.build('form', 'node_config', conf, true); response.cnode(form); return response; @@ -41,7 +45,7 @@ exports.default = { type: 'get', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'default', + child2: 'default', func: function(response) { if (!config.enabled('config-node')) return makeError(response, errors.owner.default_options.node_configuration_not_supported.n); @@ -61,7 +65,7 @@ exports.setConfigure = { type: 'set', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'configure', + child2: 'configure', func: function(response, stanza, request, to) { if (!config.enabled('config-node')) return makeError(response, errors.owner.configure.node_configuration_not_supported.n); @@ -92,7 +96,8 @@ exports.setConfigure = { if (typeof form == 'number') return makeError(response, form); - var conf = form; + // TODO: verify the form. + var conf = form.fields; var set = storage.configure(nodeID, conf); if (typeof set == 'number') @@ -101,3 +106,51 @@ exports.setConfigure = { return response; } } + +// SECTION 8.1.3: Create and Configure a Node (configure) +exports.setConfigure2 = { + type: 'set', + child: 'pubsub', + ns: NS.PUBSUB, + child2: 'configure', + number: 1, + func: function(response, stanza, request, to) { + if (!config.enabled('config-node')) + return makeError(response, errors.owner.configure.node_configuration_not_supported.n); + + var nodeID = stanza.tags[0].tags[0].getAttribute('node'); + if (!nodeID) + return makeError(response, errors.nodeid_required.n); + if (!storage.existsNode(nodeID)) + return makeError(response, errors.node_does_not_exist.n); + + var affil = storage.getAffiliation(toBareJID(to), nodeID); + if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only') + return makeError(response, errors.forbidden.n); + + var x = request.getChild('x', 'jabber:x:data'); + if (!x) + return makeError(response, errors.bad_request.n); + + var type = x.getAttribute('type'); + if (type == 'cancel') { + conn.send(response); + return; + } + if (type != 'submit') + return makeError(response, errors.bad_request.n); + + var form = forms.parse(x, true); + if (typeof form == 'number') + return makeError(response, form); + + // TODO: verify the form. + var conf = form.fields; + + var set = storage.configure(nodeID, conf); + if (typeof set == 'number') + return makeError(response, set); + + return null; + } +} diff --git a/modules/mod_manage.js b/modules/mod_manage.js --- a/modules/mod_manage.js +++ b/modules/mod_manage.js @@ -10,7 +10,7 @@ exports.manageRetrieveSub = { type: 'get', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'subscriptions', + child2: 'subscriptions', func: function(response, stanza, request, to) { if (!config.enabled('manage-subscriptions')) return makeError(response, errors.owner.manage_subscriptions.not_supported.n); @@ -41,7 +41,7 @@ exports.manageRetrieveAff = { type: 'get', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'affiliations', + child2: 'affiliations', func: function(response, stanza, request, to) { if (!config.enabled('modify-affiliations')) return makeError(response, errors.owner.manage_affiliations.not_supported.n); @@ -72,7 +72,7 @@ exports.modifySub = { type: 'set', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'subscriptions', + child2: 'subscriptions', func: function(response, stanza, request, to) { if (!config.enabled('manage-subscriptions')) return makeError(response, errors.owner.manage_subscriptions.not_supported.n); //XXX @@ -124,7 +124,7 @@ exports.modifyAff = { type: 'set', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'affiliations', + child2: 'affiliations', func: function(response, stanza, request, to) { if (!config.enabled('modify-affiliations')) return makeError(response, errors.owner.manage_affiliations.not_supported.n); //XXX diff --git a/modules/mod_options.js b/modules/mod_options.js --- a/modules/mod_options.js +++ b/modules/mod_options.js @@ -7,11 +7,11 @@ var toBareJID = require('../util').toBar var NS = require('../namespaces'); // SECTION 6.3.2: Configure Subscription Options (Request) -exports.configureSub = { +exports.getConfigureSub = { type: 'get', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'options', + child2: 'options', func: function(response, stanza, request, to) { if (!config.enabled('subscription-options')) return makeError(response, errors.sub.configure.subscription_options_not_supported.n); @@ -47,7 +47,7 @@ exports.configureSub = { type: 'set', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'options', + child2: 'options', func: function(response, stanza, request, to) { if (!config.enabled('subscription-options')) return makeError(response, errors.sub.subscribe.not_supported.n); @@ -83,7 +83,7 @@ exports.defaultSub = { type: 'get', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'default', + child2: 'default', func: function(response, stanza, request) { if (!config.enabled('retrieve-default-sub')) return makeError(response, errors.sub.default_options.default_subscription_configuration_retrieval_not_supported.n); diff --git a/modules/mod_owner.js b/modules/mod_owner.js --- a/modules/mod_owner.js +++ b/modules/mod_owner.js @@ -8,11 +8,11 @@ var toBareJID = require('../util').toBar var NS = require('../namespaces'); // SECTION 8.1: Create a Node -exports.getConfigure = { +exports.create = { type: 'set', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'create', + child2: 'create', func: function(response, stanza, request, to) { if (!config.enabled('create-nodes')) return makeError(response, errors.owner.create.node_creation_not_supported.n); @@ -45,7 +45,10 @@ exports.getConfigure = { if (!right) return makeError(response, errors.forbidden.n); - var r = storage.createNode(nodeID); + conf = {}; + conf['pubsub#creator'] = bare; + + var r = storage.createNode(nodeID, conf); if (typeof r == 'number') return makeError(response, r); @@ -62,7 +65,7 @@ exports['delete'] = { type: 'set', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'delete', + child2: 'delete', func: function(response, stanza, request, to) { if (!config.enabled('delete-nodes')) return makeError(response, errors.feature_not_implemented.n); //XXX @@ -77,11 +80,11 @@ exports['delete'] = { if (affil != 'super-owner' && affil != 'owner') return makeError(response, errors.forbidden.n); - var notifs = storage.deleteNode(nodeID); - if (typeof notifs == 'number') + var notifications = storage.deleteNode(nodeID); + if (typeof notifications == 'number') return makeError(response, r); - notifs.send(notifs, 'delete', nodeID); + notifs.send(notifications, 'delete', nodeID); return response; } @@ -92,7 +95,7 @@ exports.purge = { type: 'set', child: 'pubsub', ns: NS.PUBSUB_OWNER, - pschild: 'purge', + child2: 'purge', func: function(response, stanza, request, to) { if (!config.enabled('purge-nodes')) return makeError(response, errors.owner.purge.node_purging_not_supported.n); //XXX @@ -110,11 +113,11 @@ exports.purge = { if (!config.enabled('persistent-items')) //FIXME: autre condition, supporté par le node return makeError(response, errors.owner.purge.node_does_not_persist_items.n); - var notifs = storage.purgeNode(nodeID); - if (typeof notifs == 'number') + var notifications = storage.purgeNode(nodeID); + if (typeof notifications == 'number') return makeError(response, r); - notifs.send(notifs, 'purge', nodeID); + notifs.send(notifications, 'purge', nodeID); return response; } diff --git a/modules/mod_publish.js b/modules/mod_publish.js --- a/modules/mod_publish.js +++ b/modules/mod_publish.js @@ -8,7 +8,7 @@ exports.retrieveSub = { type: 'set', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'publish', + child2: 'publish', func: function(response, stanza, request, to) { if (!config.enabled('publish')) return makeError(response, errors.pub.publish.item_publication_not_supported.n); @@ -94,7 +94,7 @@ exports.retrieveSub = { type: 'set', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'retract', + child2: 'retract', func: function(response, stanza, request, to) { if (!config.enabled('retract-items')) return makeError(response, errors.pub.retract.item_deletion_not_supported.n); diff --git a/modules/mod_retrieve.js b/modules/mod_retrieve.js --- a/modules/mod_retrieve.js +++ b/modules/mod_retrieve.js @@ -10,7 +10,7 @@ exports.retrieveSubscriptions = { type: 'get', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'subscriptions', + child2: 'subscriptions', func: function(response, stanza, request) { if (!config.enabled('retrieve-subscriptions')) return makeError(response, errors.subscriptions_retrieval_not_supported.n); @@ -38,7 +38,7 @@ exports.retrieveAffiliations = { type: 'get', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'affiliations', + child2: 'affiliations', func: function(response, stanza, request) { if (!config.enabled('retrieve-affiliations')) return makeError(response, errors.affiliations_retrieval_not_supported.n); @@ -67,7 +67,7 @@ exports.retrieveItems = { type: 'get', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'items', + child2: 'items', func: function(response, stanza, request) { if (!config.enabled('retrieve-items')) return makeError(response, errors.sub.default_options.node_configuration_not_supported.n); diff --git a/modules/mod_subscribe.js b/modules/mod_subscribe.js --- a/modules/mod_subscribe.js +++ b/modules/mod_subscribe.js @@ -10,7 +10,7 @@ exports.subscribe = { type: 'set', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'subscribe', + child2: 'subscribe', func: function(response, stanza, request, to) { if (!config.enabled('subscribe')) return makeError(response, errors.sub.subscribe.not_supported.n); @@ -104,7 +104,7 @@ exports.unsubscribe = { type: 'set', child: 'pubsub', ns: NS.PUBSUB, - pschild: 'unsubscribe', + child2: 'unsubscribe', func: function(response, stanza, request) { if (!config.enabled('subscribe')) return makeError(response, errors.sub.subscribe.not_supported.n); diff --git a/psgxs.js b/psgxs.js --- a/psgxs.js +++ b/psgxs.js @@ -77,40 +77,64 @@ function onIq(stanza) { else response = xmpp.iq({to: to, from: from, type: 'result'}); - var sent = false; + var send = false; + + 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]; - for (var i in modules) { - var module = modules[i]; - if (module.type && (type != module.type)) - continue; + if (module.type && (module.type != type)) + continue; + + if (module.child2 && (module.child2 != child2.name)) + continue; - for (var j in stanza.tags) { - var child = stanza.tags[j]; - if (module.child && (child.name != module.child)) - continue; + if (module.ns && (module.ns != child2.attr.xmlns)) + continue; + + if (module.number && (module.number != j)) + continue; - if (module.ns && (child.attr.xmlns != module.ns)) - continue; + var toSend = module.func(response, stanza, child2, to); + if (toSend) { + response = toSend; + send = true; + delete toSend; + } + } + } + } else { + for (var k in modules) { + var module = modules[k]; - if (module.child == 'pubsub') { - var child2 = child.getChild(module.pschild, child.attr.xmlns); - if (child2) - child = child2; + if (module.type && (module.type != type)) + continue; - if (module.pschild && (!child || module.pschild != child.name)) + if (module.child && (module.child != child1.name)) continue; - } + + if (module.ns && (module.ns != child1.attr.xmlns)) + continue; - var toSend = module.func(response, stanza, child, to); - if (toSend) { - conn.send(toSend); - sent = true; + if (module.number && (module.number != k)) + continue; + + var toSend = module.func(response, stanza, child2, to); + if (toSend) { + response = toSend; + send = true; + delete toSend; + } } } } - if (!sent) - conn.send(makeError(response, errors.feature_not_implemented.n)); + conn.send(send? response: makeError(response, errors.feature_not_implemented.n)); } function onMessage(stanza) {