comparison psgxs.js @ 1:c2954a9e5665

Add a super-owner that has power over all nodes; add support for affiliation changes; support pubsub#creator metadata; change pubsub#digest_frequency default; and use better default config values.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 28 Jun 2010 21:55:30 +0200
parents 9ee956af41e3
children d3ae2f8b685d
comparison
equal deleted inserted replaced
0:9ee956af41e3 1:c2954a9e5665
57 response = xmpp.iq({to: to, from: from, type: 'result', id: id}); 57 response = xmpp.iq({to: to, from: from, type: 'result', id: id});
58 else 58 else
59 response = xmpp.iq({to: to, from: from, type: 'result'}); 59 response = xmpp.iq({to: to, from: from, type: 'result'});
60 60
61 if (type == 'get') { 61 if (type == 'get') {
62
63 // XEP-0092
62 if (stanza.getChild('query', 'jabber:iq:version')) { 64 if (stanza.getChild('query', 'jabber:iq:version')) {
63 var os = 'GNU/Linux';
64 var query = xmpp.stanza('query', {xmlns: 'jabber:iq:version'}) 65 var query = xmpp.stanza('query', {xmlns: 'jabber:iq:version'})
65 .s('name').t('PubSubJS') 66 .s('name').t('PSĜS')
66 .s('version').t('Pas releasé') 67 .s('version').t(config.version)
67 .s('os').t(os); 68 .s('os').t(config.os);
68 response.cx(query); 69 response.cx(query);
69 70
70 // SECTION 5.1 71 // SECTION 5.1
71 } else if (stanza.getChild('query', 'http://jabber.org/protocol/disco#info')) { 72 } else if (stanza.getChild('query', 'http://jabber.org/protocol/disco#info')) {
72 var query = stanza.getChild('query', 'http://jabber.org/protocol/disco#info'); 73 var query = stanza.getChild('query', 'http://jabber.org/protocol/disco#info');
102 var q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#info'}) 103 var q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#info'})
103 .s('identity', {category: 'pubsub', type: 'service', name: 'PubSub JavaScript Server'}) 104 .s('identity', {category: 'pubsub', type: 'service', name: 'PubSub JavaScript Server'})
104 .s('feature', {'var': 'http://jabber.org/protocol/disco#info'}) 105 .s('feature', {'var': 'http://jabber.org/protocol/disco#info'})
105 .s('feature', {'var': 'http://jabber.org/protocol/disco#items'}) 106 .s('feature', {'var': 'http://jabber.org/protocol/disco#items'})
106 .s('feature', {'var': 'http://jabber.org/protocol/pubsub'}) 107 .s('feature', {'var': 'http://jabber.org/protocol/pubsub'})
108 .s('feature', {'var': 'jabber:iq:version'})
107 // .s('feature', {'var': 'http://jabber.org/protocol/commands'}) 109 // .s('feature', {'var': 'http://jabber.org/protocol/commands'})
108 for (var i in config.activated) 110 for (var i in config.activated)
109 if (typeof i == 'string') 111 if (typeof i == 'string')
110 q.s('feature', {'var': 'http://jabber.org/protocol/pubsub#' + config.activated[i]}); 112 q.s('feature', {'var': 'http://jabber.org/protocol/pubsub#' + config.activated[i]});
111 response.cx(q); 113 response.cx(q);
264 return makeError(response, errors.nodeid_required.n); 266 return makeError(response, errors.nodeid_required.n);
265 if (!storage.existsNode(nodeID)) 267 if (!storage.existsNode(nodeID))
266 return makeError(response, errors.node_does_not_exist.n); 268 return makeError(response, errors.node_does_not_exist.n);
267 269
268 var affil = storage.getAffiliation(toBareJID(to), nodeID); 270 var affil = storage.getAffiliation(toBareJID(to), nodeID);
269 if (affil != 'owner' && affil != 'publisher' && affil != 'member') 271 if (affil != 'super-owner' && affil != 'owner' && affil != 'publisher' && affil != 'member')
270 return makeError(response, errors.pub.publish.insufficient_privileges.n); 272 return makeError(response, errors.pub.publish.insufficient_privileges.n);
271 273
272 var item = []; 274 var item = [];
273 for (var i=0; i<items.children.length; i++) { 275 for (var i=0; i<items.children.length; i++) {
274 var j = items.children[i]; 276 var j = items.children[i];
315 } else 317 } else
316 return makeError(response, errors.feature_not_implemented.n); 318 return makeError(response, errors.feature_not_implemented.n);
317 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner')) { 319 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner')) {
318 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner'); 320 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner');
319 321
320 // SECTION 322 // SECTION 8.2
321 if (pubsub.getChild('configure')) { 323 if (pubsub.getChild('configure')) {
322 if (!config.enabled('config-node')) 324 if (!config.enabled('config-node'))
323 return makeError(response, errors.owner.configure.node_configuration_not_supported.n); 325 return makeError(response, errors.owner.configure.node_configuration_not_supported.n);
324 326
325 var nodeID = pubsub.getChild('configure').getAttribute('node'); 327 var nodeID = pubsub.getChild('configure').getAttribute('node');
327 return makeError(response, errors.nodeid_required.n); 329 return makeError(response, errors.nodeid_required.n);
328 if (!storage.existsNode(nodeID)) 330 if (!storage.existsNode(nodeID))
329 return makeError(response, errors.node_does_not_exist.n); 331 return makeError(response, errors.node_does_not_exist.n);
330 332
331 var affil = storage.getAffiliation(toBareJID(to), nodeID); 333 var affil = storage.getAffiliation(toBareJID(to), nodeID);
332 if (affil != 'owner' && affil != 'publish-only') 334 if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only')
333 return makeError(response, errors.pub.publish.insufficient_privileges.n); 335 return makeError(response, errors.pub.publish.insufficient_privileges.n);
334 336
335 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); 337 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'});
336 var s = xmpp.stanza('configure', {node: nodeID}); 338 var s = xmpp.stanza('configure', {node: nodeID});
337 var form = forms.build('form', 'node_config', 'default', true); 339 var form = forms.build('form', 'node_config', 'default', true);
338 s.cx(form); 340 s.cx(form);
339 p.cx(s); 341 p.cx(s);
340 response.cx(p); 342 response.cx(p);
341 343
342 // SECTION 344 // SECTION 8.3
343 } else if (pubsub.getChild('default')) { 345 } else if (pubsub.getChild('default')) {
344 if (!config.enabled('config-node')) 346 if (!config.enabled('config-node'))
345 return makeError(response, errors.owner.default_options.node_configuration_not_supported.n); 347 return makeError(response, errors.owner.default_options.node_configuration_not_supported.n);
346 348
347 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); 349 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'});
349 var form = forms.build('node_config', service_configuration.node_config, null, true); 351 var form = forms.build('node_config', service_configuration.node_config, null, true);
350 s.cx(form); 352 s.cx(form);
351 p.cx(s); 353 p.cx(s);
352 response.cx(p); 354 response.cx(p);
353 355
354 // SECTION 356 // SECTION 8.8
355 } else if (pubsub.getChild('subscriptions')) { 357 } else if (pubsub.getChild('subscriptions')) {
356 if (!config.enabled('manage-subscriptions')) 358 if (!config.enabled('manage-subscriptions'))
357 return makeError(response, errors.owner.manage_subscriptions.not_supported.n); 359 return makeError(response, errors.owner.manage_subscriptions.not_supported.n);
358 360
359 var subscriptions = pubsub.getChild('subscriptions'); 361 var subscriptions = pubsub.getChild('subscriptions');
362 if (!nodeID || nodeID == '') 364 if (!nodeID || nodeID == '')
363 return makeError(response, errors.nodeid_required.n); 365 return makeError(response, errors.nodeid_required.n);
364 if (!storage.existsNode(nodeID)) 366 if (!storage.existsNode(nodeID))
365 return makeError(response, errors.node_does_not_exist.n); 367 return makeError(response, errors.node_does_not_exist.n);
366 368
367 if (storage.getAffiliation(toBareJID(to), nodeID) != 'owner') 369 var affil = storage.getAffiliation(toBareJID(to), nodeID);
370 if (affil != 'super-owner' && affil != 'owner')
368 return makeError(response, errors.forbidden.n); 371 return makeError(response, errors.forbidden.n);
369 372
370 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); 373 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'});
371 var s = xmpp.stanza('subscriptions', {node: nodeID}); 374 var s = xmpp.stanza('subscriptions', {node: nodeID});
372 375
375 s.s('subscription', {jid: jid, subscription: subs[jid].type, subid: subs[jid].subid}) 378 s.s('subscription', {jid: jid, subscription: subs[jid].type, subid: subs[jid].subid})
376 379
377 p.cx(s); 380 p.cx(s);
378 response.cx(p); 381 response.cx(p);
379 382
380 // SECTION 383 // SECTION 8.9
381 } else if (pubsub.getChild('affiliations')) { 384 } else if (pubsub.getChild('affiliations')) {
382 if (!config.enabled('modify-affiliations')) 385 if (!config.enabled('modify-affiliations'))
383 return makeError(response, errors.owner.manage_affiliations.not_supported.n); 386 return makeError(response, errors.owner.manage_affiliations.not_supported.n);
384 387
385 var affiliations = pubsub.getChild('affiliations'); 388 var affiliations = pubsub.getChild('affiliations');
388 if (!nodeID || nodeID == '') 391 if (!nodeID || nodeID == '')
389 return makeError(response, errors.nodeid_required.n); 392 return makeError(response, errors.nodeid_required.n);
390 if (!storage.existsNode(nodeID)) 393 if (!storage.existsNode(nodeID))
391 return makeError(response, errors.node_does_not_exist.n); 394 return makeError(response, errors.node_does_not_exist.n);
392 395
393 var affil = storage.getAffiliationsFromNodeID(nodeID); 396 var affils = storage.getAffiliationsFromNodeID(nodeID);
394 if (affil[toBareJID(to)] != 'owner') 397 var affil = affils[toBareJID(to)];
398 if (affil != 'super-owner' && affil != 'owner')
395 return makeError(response, errors.owner.manage_affiliations.retrieve_list.entity_is_not_an_owner.n); 399 return makeError(response, errors.owner.manage_affiliations.retrieve_list.entity_is_not_an_owner.n);
396 400
397 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); 401 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'});
398 var s = xmpp.stanza('affiliations', {node: nodeID}); 402 var s = xmpp.stanza('affiliations', {node: nodeID});
399 403
400 for (var jid in affil) 404 for (var jid in affils)
401 s.s('affiliation', {jid: jid, affiliation: affil[jid]}) 405 s.s('affiliation', {jid: jid, affiliation: affils[jid]})
402 406
403 p.cx(s); 407 p.cx(s);
404 response.cx(p); 408 response.cx(p);
405 } else 409 } else
406 return makeError(response, errors.feature_not_implemented.n); 410 return makeError(response, errors.feature_not_implemented.n);
461 subID = storage.subscribe(nodeID, jid, 'pending', conf); 465 subID = storage.subscribe(nodeID, jid, 'pending', conf);
462 if (typeof subID == 'number') 466 if (typeof subID == 'number')
463 return makeError(response, subID); 467 return makeError(response, subID);
464 } else if (configuration['pubsub#access_model'] == 'whitelist') { 468 } else if (configuration['pubsub#access_model'] == 'whitelist') {
465 var affil = storage.getAffiliation(jid, nodeID); 469 var affil = storage.getAffiliation(jid, nodeID);
466 if (affil != 'owner' && affil != 'publisher' && affil != 'member') 470 if (affil != 'super-owner' && affil != 'owner' && affil != 'publisher' && affil != 'member')
467 return makeError(response, errors.sub.subscribe.not_on_whitelist.n); 471 return makeError(response, errors.sub.subscribe.not_on_whitelist.n);
468 472
469 subID = storage.subscribe(nodeID, jid, conf); 473 subID = storage.subscribe(nodeID, jid, conf);
470 if (typeof subID == 'number') 474 if (typeof subID == 'number')
471 return makeError(response, subID); 475 return makeError(response, subID);
479 483
480 if (config.enabled('get-pending')) { 484 if (config.enabled('get-pending')) {
481 var affiliates = storage.getAffiliationsFromNodeID(nodeID); 485 var affiliates = storage.getAffiliationsFromNodeID(nodeID);
482 var form = forms.build('form', 'subscribe_authorization', {allow: false, node: nodeID, subscriber_jid: jid}, true); //168 486 var form = forms.build('form', 'subscribe_authorization', {allow: false, node: nodeID, subscriber_jid: jid}, true); //168
483 for (var i in affiliates) { 487 for (var i in affiliates) {
484 if (affiliates[i] == 'owner') { 488 if (affiliates[i] == 'super-owner' || affiliates[i] == 'owner') {
485 var message = xmpp.message({to: i}).cx(form); 489 var message = xmpp.message({to: i}).cx(form);
486 conn.send(message); 490 conn.send(message);
487 } 491 }
488 } 492 }
489 } 493 }
547 551
548 var set = storage.configureSubscription(nodeID, jid, form); 552 var set = storage.configureSubscription(nodeID, jid, form);
549 if (typeof form == 'number') 553 if (typeof form == 'number')
550 return makeError(response, form); 554 return makeError(response, form);
551 555
552 // SECTION 556 // SECTION 7.1
553 } else if (pubsub.getChild('publish')) { 557 } else if (pubsub.getChild('publish')) {
554 if (!config.enabled('publish')) 558 if (!config.enabled('publish'))
555 return makeError(response, errors.pub.publish.item_publication_not_supported.n); 559 return makeError(response, errors.pub.publish.item_publication_not_supported.n);
556 560
557 var publish = pubsub.getChild('publish'); 561 var publish = pubsub.getChild('publish');
560 return makeError(response, errors.nodeid_required.n); 564 return makeError(response, errors.nodeid_required.n);
561 565
562 var affil = storage.getAffiliation(toBareJID(to), nodeID); 566 var affil = storage.getAffiliation(toBareJID(to), nodeID);
563 if (typeof affil == 'number') 567 if (typeof affil == 'number')
564 return makeError(response, affil); 568 return makeError(response, affil);
565 if (affil != 'owner' && affil != 'publisher' && affil != 'publish-only') 569 if (affil != 'super-owner' && affil != 'owner' && affil != 'publisher' && affil != 'publish-only')
566 return makeError(response, errors.forbidden.n); 570 return makeError(response, errors.forbidden.n);
567 571
568 var item = publish.getChild('item'); 572 var item = publish.getChild('item');
569 var itemID = item.getAttribute('id'); 573 var itemID = item.getAttribute('id');
570 if (!config.enabled('item-ids') && itemID) 574 if (!config.enabled('item-ids') && itemID)
598 var notifs = storage.purgeNode(nodeID); 602 var notifs = storage.purgeNode(nodeID);
599 if (typeof notifs == 'number') 603 if (typeof notifs == 'number')
600 return makeError(response, r); 604 return makeError(response, r);
601 } 605 }
602 606
603 if (autocreate) 607 if (autocreate) {
604 storage.createNode(nodeID, form); 608 if (!form)
609 form = {};
610 form['pubsub#creator'] = toBareJID(to);
611
612 var r = storage.createNode(nodeID, form);
613 if (typeof r == 'number')
614 return makeError(response, r);
615 }
605 616
606 var content = item.getChild(); 617 var content = item.getChild();
618
607 subscribers = storage.setItem(nodeID, itemID, content); 619 subscribers = storage.setItem(nodeID, itemID, content);
608
609 if (typeof subscribers == 'number') 620 if (typeof subscribers == 'number')
610 return makeError(response, subscribers); 621 return makeError(response, subscribers);
611 622
612 var attrs = {}; 623 var attrs = {};
613 if (content) 624 if (content)
618 629
619 response.c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}) 630 response.c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'})
620 .c('publish', {node: nodeID}) 631 .c('publish', {node: nodeID})
621 .c('item', {id: itemID}); 632 .c('item', {id: itemID});
622 633
623 // SECTION 634 // SECTION 7.2
624 } else if (pubsub.getChild('retract')) { 635 } else if (pubsub.getChild('retract')) {
625 if (!config.enabled('retract-items')) 636 if (!config.enabled('retract-items'))
626 return makeError(response, errors.pub.retract.item_deletion_not_supported.n); 637 return makeError(response, errors.pub.retract.item_deletion_not_supported.n);
627 638
628 var retract = pubsub.getChild('retract'); 639 var retract = pubsub.getChild('retract');
647 658
648 var attrs = {}; 659 var attrs = {};
649 attrs[itemID] = {}; 660 attrs[itemID] = {};
650 sendNotifs(subscribers, 'items', nodeID, attrs, 'retract') 661 sendNotifs(subscribers, 'items', nodeID, attrs, 'retract')
651 662
652 // SECTION 663 // SECTION 8.1
653 } else if (pubsub.getChild('create')) { 664 } else if (pubsub.getChild('create')) {
654 if (!config.enabled('create-nodes')) 665 if (!config.enabled('create-nodes'))
655 return makeError(response, errors.owner.create.node_creation_not_supported.n); 666 return makeError(response, errors.owner.create.node_creation_not_supported.n);
656 667
657 var instant = false; 668 var instant = false;
665 } 676 }
666 if (storage.existsNode(nodeID)) 677 if (storage.existsNode(nodeID))
667 return makeError(response, errors.nodeid_already_exists.n); 678 return makeError(response, errors.nodeid_already_exists.n);
668 679
669 var affil = storage.getAffiliation(toBareJID(to), nodeID); 680 var affil = storage.getAffiliation(toBareJID(to), nodeID);
670 if (affil != 'owner' && affil != 'publish-only') 681 if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only')
671 return makeError(response, errors.forbidden.n); 682 return makeError(response, errors.forbidden.n);
672 683
673 var configure = pubsub.getChild('configure'); 684 var configure = pubsub.getChild('configure');
674 if (configure && config.enabled('create-and-configure')) { 685 if (configure && config.enabled('create-and-configure')) {
675 if (!config.enabled('config-node')) 686 if (!config.enabled('config-node'))
687 return makeError(response, form); 698 return makeError(response, form);
688 699
689 var conf = form; 700 var conf = form;
690 } 701 }
691 702
703 if (!conf)
704 conf = {};
705 conf['pubsub#creator'] = toBareJID(to);
692 var r = storage.createNode(nodeID, conf); 706 var r = storage.createNode(nodeID, conf);
693 if (typeof r == 'number') 707 if (typeof r == 'number')
694 return makeError(response, r); 708 return makeError(response, r);
695 709
696 if (instant) 710 if (instant)
699 } else 713 } else
700 return makeError(response, errors.feature_not_implemented.n); 714 return makeError(response, errors.feature_not_implemented.n);
701 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner')) { 715 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner')) {
702 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner'); 716 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner');
703 717
704 // SECTION 718 // SECTION 8.2.4
705 if (pubsub.getChild('configure')) { 719 if (pubsub.getChild('configure')) {
706 if (!config.enabled('config-node')) 720 if (!config.enabled('config-node'))
707 return makeError(response, errors.owner.configure.node_configuration_not_supported.n); 721 return makeError(response, errors.owner.configure.node_configuration_not_supported.n);
708 722
709 var nodeID = configure.getAttribute('node'); 723 var nodeID = configure.getAttribute('node');
711 return makeError(response, errors.nodeid_required.n); 725 return makeError(response, errors.nodeid_required.n);
712 if (!storage.existsNode(nodeID)) 726 if (!storage.existsNode(nodeID))
713 return makeError(response, errors.node_does_not_exist.n); 727 return makeError(response, errors.node_does_not_exist.n);
714 728
715 var affil = storage.getAffiliation(toBareJID(to), nodeID); 729 var affil = storage.getAffiliation(toBareJID(to), nodeID);
716 if (affil != 'owner' && affil != 'publish-only') 730 if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only')
717 return makeError(response, errors.forbidden.n); 731 return makeError(response, errors.forbidden.n);
718 732
719 var x = configure.getChild('x', 'jabber:x:data'); 733 var x = configure.getChild('x', 'jabber:x:data');
720 if (!x || x.getAttribute(type) != 'submit') 734 if (!x || x.getAttribute(type) != 'submit')
721 return makeError(response, errors.bad_request.n); 735 return makeError(response, errors.bad_request.n);
728 742
729 var set = storage.configure(nodeID, conf); 743 var set = storage.configure(nodeID, conf);
730 if (typeof set == 'number') 744 if (typeof set == 'number')
731 return makeError(response, set); 745 return makeError(response, set);
732 746
733 // SECTION 747 // SECTION 8.4
734 } else if (pubsub.getChild('delete')) { 748 } else if (pubsub.getChild('delete')) {
735 if (!config.enabled('delete-nodes')) 749 if (!config.enabled('delete-nodes'))
736 return makeError(response, errors.feature_not_implemented.n); //XXX 750 return makeError(response, errors.feature_not_implemented.n); //XXX
737 751
738 var del = pubsub.getChild('delete'); 752 var del = pubsub.getChild('delete');
741 if (!nodeID) 755 if (!nodeID)
742 return makeError(response, errors.nodeid_required.n); 756 return makeError(response, errors.nodeid_required.n);
743 if (!storage.existsNode(nodeID)) 757 if (!storage.existsNode(nodeID))
744 return makeError(response, errors.node_does_not_exist.n); 758 return makeError(response, errors.node_does_not_exist.n);
745 759
746 if (storage.getAffiliation(toBareJID(to), nodeID) != 'owner') 760 var affil = storage.getAffiliation(toBareJID(to), nodeID);
761 if (affil != 'super-owner' && affil != 'owner')
747 return makeError(response, errors.forbidden.n); 762 return makeError(response, errors.forbidden.n);
748 763
749 var notifs = storage.deleteNode(nodeID); 764 var notifs = storage.deleteNode(nodeID);
750 if (typeof notifs == 'number') 765 if (typeof notifs == 'number')
751 return makeError(response, r); 766 return makeError(response, r);
752 767
753 sendNotifs(notifs, 'delete', nodeID); 768 sendNotifs(notifs, 'delete', nodeID);
754 769
755 // SECTION 770 // SECTION 8.5
756 } else if (pubsub.getChild('purge')) { 771 } else if (pubsub.getChild('purge')) {
757 if (!config.enabled('purge-nodes')) 772 if (!config.enabled('purge-nodes'))
758 return makeError(response, errors.owner.purge.node_purging_not_supported.n); //XXX 773 return makeError(response, errors.owner.purge.node_purging_not_supported.n); //XXX
759 774
760 var purge = pubsub.getChild('purge'); 775 var purge = pubsub.getChild('purge');
763 if (!nodeID) 778 if (!nodeID)
764 return makeError(response, errors.nodeid_required.n); 779 return makeError(response, errors.nodeid_required.n);
765 if (!storage.existsNode(nodeID)) 780 if (!storage.existsNode(nodeID))
766 return makeError(response, errors.node_does_not_exist.n); 781 return makeError(response, errors.node_does_not_exist.n);
767 782
768 if (storage.getAffiliation(toBareJID(to), nodeID) != 'owner') 783 var affil = storage.getAffiliation(toBareJID(to), nodeID);
784 if (affil != 'super-owner' && affil != 'owner')
769 return makeError(response, errors.forbidden.n); 785 return makeError(response, errors.forbidden.n);
770 786
771 if (!config.enabled('persistent-items')) //FIXME: autre condition, supporté par le node 787 if (!config.enabled('persistent-items')) //FIXME: autre condition, supporté par le node
772 return makeError(response, errors.owner.purge.node_does_not_persist_items.n); 788 return makeError(response, errors.owner.purge.node_does_not_persist_items.n);
773 789
775 if (typeof notifs == 'number') 791 if (typeof notifs == 'number')
776 return makeError(response, r); 792 return makeError(response, r);
777 793
778 sendNotifs(notifs, 'purge', nodeID); 794 sendNotifs(notifs, 'purge', nodeID);
779 795
780 // SECTION 796 // SECTION 8.8.2
781 } else if (pubsub.getChild('subscriptions')) { 797 } else if (pubsub.getChild('subscriptions')) {
782 if (!config.enabled('manage-subscriptions')) 798 if (!config.enabled('manage-subscriptions'))
783 return makeError(response, errors.owner.manage_subscriptions.not_supported.n); //XXX 799 return makeError(response, errors.owner.manage_subscriptions.not_supported.n); //XXX
784 800
785 var subscriptions = pubsub.getChild('subscriptions'); 801 var subscriptions = pubsub.getChild('subscriptions');
788 if (!nodeID) 804 if (!nodeID)
789 return makeError(response, errors.nodeid_required.n); 805 return makeError(response, errors.nodeid_required.n);
790 if (!storage.existsNode(nodeID)) 806 if (!storage.existsNode(nodeID))
791 return makeError(response, errors.node_does_not_exist.n); 807 return makeError(response, errors.node_does_not_exist.n);
792 808
793 if (storage.getAffiliation(toBareJID(to), nodeID) != 'owner') 809 var affil = storage.getAffiliation(toBareJID(to), nodeID);
810 if (affil != 'super-owner' && affil != 'owner')
794 return makeError(response, errors.forbidden.n); 811 return makeError(response, errors.forbidden.n);
795 812
796 var e = false; 813 var e = false;
797 for (i in subscriptions.tags) { 814 for (i in subscriptions.tags) {
798 var jid = subscriptions.tags[i].getAttribute('jid'); 815 var jid = subscriptions.tags[i].getAttribute('jid');
800 817
801 var set = storage.subscribe(nodeID, jid, subscription); 818 var set = storage.subscribe(nodeID, jid, subscription);
802 if (typeof set == 'number') 819 if (typeof set == 'number')
803 e = true; 820 e = true;
804 else { 821 else {
822 // SECTION 8.8.4
805 sendNotifs(jid, 'subscription', nodeID, {jid: jid, subscription: subscription}); 823 sendNotifs(jid, 'subscription', nodeID, {jid: jid, subscription: subscription});
806 subscriptions.tags.splice(i, 1); 824 subscriptions.tags.splice(i, 1);
807 } 825 }
808 } 826 }
809 827
810 if (e) 828 if (e)
811 return makeError(response, errors.owner.manage_subscriptions.modify.multiple_simultaneous_modifications.n, pubsub); 829 return makeError(response, errors.owner.manage_subscriptions.modify.multiple_simultaneous_modifications.n, pubsub);
812 830
813 // SECTION 831 // SECTION 8.9.2
814 } else if (pubsub.getChild('affiliations')) { 832 } else if (pubsub.getChild('affiliations')) {
815 if (!config.enabled('modify-affiliations')) 833 if (!config.enabled('modify-affiliations'))
816 return makeError(response, errors.owner.manage_affiliations.not_supported.n); //XXX 834 return makeError(response, errors.owner.manage_affiliations.not_supported.n); //XXX
817 835
818 var affiliations = pubsub.getChild('affiliations'); 836 var affiliations = pubsub.getChild('affiliations');
821 if (!nodeID) 839 if (!nodeID)
822 return makeError(response, errors.nodeid_required.n); 840 return makeError(response, errors.nodeid_required.n);
823 if (!storage.existsNode(nodeID)) 841 if (!storage.existsNode(nodeID))
824 return makeError(response, errors.node_does_not_exist.n); 842 return makeError(response, errors.node_does_not_exist.n);
825 843
826 if (storage.getAffiliation(toBareJID(to), nodeID) != 'owner') 844 var affil = storage.getAffiliation(toBareJID(to), nodeID);
845 if (affil != 'super-owner' && affil != 'owner')
827 return makeError(response, errors.forbidden.n); 846 return makeError(response, errors.forbidden.n);
828 847
829 var e = false; 848 var e = false;
830 for (i in affiliations.children) { 849 for (i in affiliations.children) {
831 var jid = affiliations.children[i].getAttribute('jid'); 850 var jid = affiliations.children[i].getAttribute('jid');
832 var affiliation = affiliations.children[i].getAttribute('affiliation'); 851 var affiliation = affiliations.children[i].getAttribute('affiliation');
833 852
834 var set = storage.setAffiliation(nodeID, jid, affiliation); 853 var set = storage.setAffiliation(nodeID, jid, affiliation);
835 if (typeof set == 'number') 854 if (typeof set == 'number')
836 e = true; 855 e = true;
837 else 856 else {
857 // SECTION 8.9.4
858 sendNotifs(jid, 'affiliations', nodeID, {jid: jid, affiliation: affiliation});
838 affiliations.children.splice(i, 1); 859 affiliations.children.splice(i, 1);
860 }
839 } 861 }
840 862
841 if (e) 863 if (e)
842 return makeError(response, errors.owner.manage_affiliations.modify.multiple_simultaneous_modifications.n, pubsub); 864 return makeError(response, errors.owner.manage_affiliations.modify.multiple_simultaneous_modifications.n, pubsub);
843 } else 865 } else
920 } 942 }
921 943
922 function sendNotifs(notifs, type, nodeID, a1, a2) { 944 function sendNotifs(notifs, type, nodeID, a1, a2) {
923 var ev = xmpp.stanza('event', {xmlns: 'http://jabber.org/protocol/pubsub#event'}); 945 var ev = xmpp.stanza('event', {xmlns: 'http://jabber.org/protocol/pubsub#event'});
924 946
925 if (type == 'collection') { 947 if (type == 'affiliations') {
948 ev.attr.xmlns = 'http://jabber.org/protocol/pubsub';
949
950 var args = {};
951 for (i in a1) {
952 var attr = a1[i];
953 if (i == 'affiliation')
954 args.affiliation = attr;
955 else if (i == 'jid')
956 args.jid = attr;
957 }
958 if (!args.jid || args.jid == '') {
959 _('Error #2', 41)
960 return;
961 }
962 var affiliation = xmpp.stanza('affiliation', );
963 var affiliations = xmpp.stanza('affiliations', {node: nodeID});
964 ev.cx(affiliations);
965 } else if (type == 'collection') {
926 var collection = xmpp.stanza('collection', {node: nodeID}); 966 var collection = xmpp.stanza('collection', {node: nodeID});
927 if (a1 == 'associate') 967 if (a1 == 'associate')
928 collection.cx('associate', {node: nodeID}); 968 collection.cx('associate', {node: nodeID});
929 else 969 else
930 collection.cx('disassociate', {node: nodeID}); 970 collection.cx('disassociate', {node: nodeID});