Changeset 57:bcc9bc7a0929 for wokkel/pubsub.py
- Timestamp:
- Apr 22, 2009, 5:02:02 PM (13 years ago)
- Branch:
- default
- Convert:
- svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@169
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
wokkel/pubsub.py
r52 r57 17 17 from twisted.words.xish import domish 18 18 19 from wokkel import disco, data_form, shim19 from wokkel import disco, data_form, generic, shim 20 20 from wokkel.subprotocols import IQHandlerMixin, XMPPHandler 21 21 from wokkel.iwokkel import IPubSubClient, IPubSubService … … 32 32 NS_PUBSUB_NODE_CONFIG = NS_PUBSUB + "#node_config" 33 33 NS_PUBSUB_META_DATA = NS_PUBSUB + "#meta-data" 34 35 # In publish-subscribe namespace XPath query selector. 36 IN_NS_PUBSUB = '[@xmlns="' + NS_PUBSUB + '"]' 37 IN_NS_PUBSUB_OWNER = '[@xmlns="' + NS_PUBSUB_OWNER + '"]' 38 39 # Publish-subscribe XPath queries 40 PUBSUB_ELEMENT = '/pubsub' + IN_NS_PUBSUB 41 PUBSUB_OWNER_ELEMENT = '/pubsub' + IN_NS_PUBSUB_OWNER 42 PUBSUB_GET = IQ_GET + PUBSUB_ELEMENT 43 PUBSUB_SET = IQ_SET + PUBSUB_ELEMENT 44 PUBSUB_OWNER_GET = IQ_GET + PUBSUB_OWNER_ELEMENT 45 PUBSUB_OWNER_SET = IQ_SET + PUBSUB_OWNER_ELEMENT 46 47 # Publish-subscribe command XPath queries 48 PUBSUB_PUBLISH = PUBSUB_SET + '/publish' + IN_NS_PUBSUB 49 PUBSUB_CREATE = PUBSUB_SET + '/create' + IN_NS_PUBSUB 50 PUBSUB_SUBSCRIBE = PUBSUB_SET + '/subscribe' + IN_NS_PUBSUB 51 PUBSUB_UNSUBSCRIBE = PUBSUB_SET + '/unsubscribe' + IN_NS_PUBSUB 52 PUBSUB_OPTIONS_GET = PUBSUB_GET + '/options' + IN_NS_PUBSUB 53 PUBSUB_OPTIONS_SET = PUBSUB_SET + '/options' + IN_NS_PUBSUB 54 PUBSUB_DEFAULT = PUBSUB_OWNER_GET + '/default' + IN_NS_PUBSUB_OWNER 55 PUBSUB_CONFIGURE_GET = PUBSUB_OWNER_GET + '/configure' + IN_NS_PUBSUB_OWNER 56 PUBSUB_CONFIGURE_SET = PUBSUB_OWNER_SET + '/configure' + IN_NS_PUBSUB_OWNER 57 PUBSUB_SUBSCRIPTIONS = PUBSUB_GET + '/subscriptions' + IN_NS_PUBSUB 58 PUBSUB_AFFILIATIONS = PUBSUB_GET + '/affiliations' + IN_NS_PUBSUB 59 PUBSUB_AFFILIATIONS_GET = PUBSUB_OWNER_GET + '/affiliations' + \ 60 IN_NS_PUBSUB_OWNER 61 PUBSUB_AFFILIATIONS_SET = PUBSUB_OWNER_SET + '/affiliations' + \ 62 IN_NS_PUBSUB_OWNER 63 PUBSUB_SUBSCRIPTIONS_GET = PUBSUB_OWNER_GET + '/subscriptions' + \ 64 IN_NS_PUBSUB_OWNER 65 PUBSUB_SUBSCRIPTIONS_SET = PUBSUB_OWNER_SET + '/subscriptions' + \ 66 IN_NS_PUBSUB_OWNER 67 PUBSUB_ITEMS = PUBSUB_GET + '/items' + IN_NS_PUBSUB 68 PUBSUB_RETRACT = PUBSUB_SET + '/retract' + IN_NS_PUBSUB 69 PUBSUB_PURGE = PUBSUB_OWNER_SET + '/purge' + IN_NS_PUBSUB_OWNER 70 PUBSUB_DELETE = PUBSUB_OWNER_SET + '/delete' + IN_NS_PUBSUB_OWNER 34 NS_PUBSUB_SUBSCRIBE_OPTIONS = NS_PUBSUB + "#subscribe_options" 35 36 # XPath to match pubsub requests 37 PUBSUB_REQUEST = '/iq[@type="get" or @type="set"]/' + \ 38 'pubsub[@xmlns="' + NS_PUBSUB + '" or ' + \ 39 '@xmlns="' + NS_PUBSUB_OWNER + '"]' 71 40 72 41 class SubscriptionPending(Exception): … … 99 68 100 69 101 class BadRequest( PubSubError):70 class BadRequest(error.StanzaError): 102 71 """ 103 72 Bad request stanza error. 104 73 """ 105 74 def __init__(self, pubsubCondition=None, text=None): 106 PubSubError.__init__(self, 'bad-request', pubsubCondition, text) 75 if pubsubCondition: 76 appCondition = domish.Element((NS_PUBSUB_ERRORS, pubsubCondition)) 77 else: 78 appCondition = None 79 error.StanzaError.__init__(self, 'bad-request', 80 text=text, 81 appCondition=appCondition) 107 82 108 83 … … 168 143 169 144 170 class _PubSubRequest(xmlstream.IQ): 171 """ 172 Publish subscribe request. 173 174 @ivar verb: Request verb 175 @type verb: C{str} 176 @ivar namespace: Request namespace. 177 @type namespace: C{str} 178 @ivar method: Type attribute of the IQ request. Either C{'set'} or C{'get'} 179 @type method: C{str} 180 @ivar command: Command element of the request. This is the direct child of 181 the C{pubsub} element in the C{namespace} with the name 182 C{verb}. 183 """ 184 185 def __init__(self, xs, verb, namespace=NS_PUBSUB, method='set'): 186 xmlstream.IQ.__init__(self, xs, method) 187 self.addElement((namespace, 'pubsub')) 188 189 self.command = self.pubsub.addElement(verb) 190 191 192 def send(self, to): 193 """ 194 Send out request. 195 196 Extends L{xmlstream.IQ.send} by requiring the C{to} parameter to be 197 a L{JID} instance. 198 199 @param to: Entity to send the request to. 200 @type to: L{JID} 201 """ 202 destination = to.full() 203 return xmlstream.IQ.send(self, destination) 145 class PubSubRequest(generic.Stanza): 146 """ 147 A publish-subscribe request. 148 149 The set of instance variables used depends on the type of request. If 150 a variable is not applicable or not passed in the request, its value is 151 C{None}. 152 153 @ivar verb: The type of publish-subscribe request. See L{_requestVerbMap}. 154 @type verb: C{str}. 155 156 @ivar affiliations: Affiliations to be modified. 157 @type affiliations: C{set} 158 @ivar items: The items to be published, as L{domish.Element}s. 159 @type items: C{list} 160 @ivar itemIdentifiers: Identifiers of the items to be retrieved or 161 retracted. 162 @type itemIdentifiers: C{set} 163 @ivar maxItems: Maximum number of items to retrieve. 164 @type maxItems: C{int}. 165 @ivar nodeIdentifier: Identifier of the node the request is about. 166 @type nodeIdentifier: C{unicode} 167 @ivar nodeType: The type of node that should be created, or for which the 168 configuration is retrieved. C{'leaf'} or C{'collection'}. 169 @type nodeType: C{str} 170 @ivar options: Configurations options for nodes, subscriptions and publish 171 requests. 172 @type options: L{data_form.Form} 173 @ivar subscriber: The subscribing entity. 174 @type subscriber: L{JID} 175 @ivar subscriptionIdentifier: Identifier for a specific subscription. 176 @type subscriptionIdentifier: C{unicode} 177 @ivar subscriptions: Subscriptions to be modified, as a set of 178 L{Subscription}. 179 @type subscriptions: C{set} 180 """ 181 182 verb = None 183 184 affiliations = None 185 items = None 186 itemIdentifiers = None 187 maxItems = None 188 nodeIdentifier = None 189 nodeType = None 190 options = None 191 subscriber = None 192 subscriptionIdentifier = None 193 subscriptions = None 194 195 # Map request iq type and subelement name to request verb 196 _requestVerbMap = { 197 ('set', NS_PUBSUB, 'publish'): 'publish', 198 ('set', NS_PUBSUB, 'subscribe'): 'subscribe', 199 ('set', NS_PUBSUB, 'unsubscribe'): 'unsubscribe', 200 ('get', NS_PUBSUB, 'options'): 'optionsGet', 201 ('set', NS_PUBSUB, 'options'): 'optionsSet', 202 ('get', NS_PUBSUB, 'subscriptions'): 'subscriptions', 203 ('get', NS_PUBSUB, 'affiliations'): 'affiliations', 204 ('set', NS_PUBSUB, 'create'): 'create', 205 ('get', NS_PUBSUB_OWNER, 'default'): 'default', 206 ('get', NS_PUBSUB_OWNER, 'configure'): 'configureGet', 207 ('set', NS_PUBSUB_OWNER, 'configure'): 'configureSet', 208 ('get', NS_PUBSUB, 'items'): 'items', 209 ('set', NS_PUBSUB, 'retract'): 'retract', 210 ('set', NS_PUBSUB_OWNER, 'purge'): 'purge', 211 ('set', NS_PUBSUB_OWNER, 'delete'): 'delete', 212 ('get', NS_PUBSUB_OWNER, 'affiliations'): 'affiliationsGet', 213 ('set', NS_PUBSUB_OWNER, 'affiliations'): 'affiliationsSet', 214 ('get', NS_PUBSUB_OWNER, 'subscriptions'): 'subscriptionsGet', 215 ('set', NS_PUBSUB_OWNER, 'subscriptions'): 'subscriptionsSet', 216 } 217 218 # Map request verb to request iq type and subelement name 219 _verbRequestMap = dict(((v, k) for k, v in _requestVerbMap.iteritems())) 220 221 # Map request verb to parameter handler names 222 _parameters = { 223 'publish': ['node', 'items'], 224 'subscribe': ['nodeOrEmpty', 'jid'], 225 'unsubscribe': ['nodeOrEmpty', 'jid'], 226 'optionsGet': ['nodeOrEmpty', 'jid'], 227 'optionsSet': ['nodeOrEmpty', 'jid', 'options'], 228 'subscriptions': [], 229 'affiliations': [], 230 'create': ['nodeOrNone'], 231 'default': ['default'], 232 'configureGet': ['nodeOrEmpty'], 233 'configureSet': ['nodeOrEmpty', 'configure'], 234 'items': ['node', 'maxItems', 'itemIdentifiers'], 235 'retract': ['node', 'itemIdentifiers'], 236 'purge': ['node'], 237 'delete': ['node'], 238 'affiliationsGet': [], 239 'affiliationsSet': [], 240 'subscriptionsGet': [], 241 'subscriptionsSet': [], 242 } 243 244 def __init__(self, verb=None): 245 self.verb = verb 246 247 248 @staticmethod 249 def _findForm(element, formNamespace): 250 """ 251 Find a Data Form. 252 253 Look for an element that represents a Data Form with the specified 254 form namespace as a child element of the given element. 255 """ 256 if not element: 257 return None 258 259 form = None 260 for child in element.elements(): 261 try: 262 form = data_form.Form.fromElement(child) 263 except data_form.Error: 264 continue 265 266 if form.formNamespace != NS_PUBSUB_NODE_CONFIG: 267 continue 268 269 return form 270 271 272 def _parse_node(self, verbElement): 273 """ 274 Parse the required node identifier out of the verbElement. 275 """ 276 try: 277 self.nodeIdentifier = verbElement["node"] 278 except KeyError: 279 raise BadRequest('nodeid-required') 280 281 282 def _render_node(self, verbElement): 283 """ 284 Render the required node identifier on the verbElement. 285 """ 286 if not self.nodeIdentifier: 287 raise Exception("Node identifier is required") 288 289 verbElement['node'] = self.nodeIdentifier 290 291 292 def _parse_nodeOrEmpty(self, verbElement): 293 """ 294 Parse the node identifier out of the verbElement. May be empty. 295 """ 296 self.nodeIdentifier = verbElement.getAttribute("node", '') 297 298 299 def _render_nodeOrEmpty(self, verbElement): 300 """ 301 Render the node identifier on the verbElement. May be empty. 302 """ 303 if self.nodeIdentifier: 304 verbElement['node'] = self.nodeIdentifier 305 306 307 def _parse_nodeOrNone(self, verbElement): 308 """ 309 Parse the optional node identifier out of the verbElement. 310 """ 311 self.nodeIdentifier = verbElement.getAttribute("node") 312 313 314 def _render_nodeOrNone(self, verbElement): 315 """ 316 Render the optional node identifier on the verbElement. 317 """ 318 if self.nodeIdentifier: 319 verbElement['node'] = self.nodeIdentifier 320 321 322 def _parse_items(self, verbElement): 323 """ 324 Parse items out of the verbElement for publish requests. 325 """ 326 self.items = [] 327 for element in verbElement.elements(): 328 if element.uri == NS_PUBSUB and element.name == 'item': 329 self.items.append(element) 330 331 332 def _render_items(self, verbElement): 333 """ 334 Render items into the verbElement for publish requests. 335 """ 336 if self.items: 337 for item in self.items: 338 verbElement.addChild(item) 339 340 341 def _parse_jid(self, verbElement): 342 """ 343 Parse subscriber out of the verbElement for un-/subscribe requests. 344 """ 345 try: 346 self.subscriber = jid.internJID(verbElement["jid"]) 347 except KeyError: 348 raise BadRequest('jid-required') 349 350 351 def _render_jid(self, verbElement): 352 """ 353 Render subscriber into the verbElement for un-/subscribe requests. 354 """ 355 verbElement['jid'] = self.subscriber.full() 356 357 358 def _parse_default(self, verbElement): 359 """ 360 Parse node type out of a request for the default node configuration. 361 """ 362 form = PubSubRequest._findForm(verbElement, NS_PUBSUB_NODE_CONFIG) 363 if form and form.formType == 'submit': 364 values = form.getValues() 365 self.nodeType = values.get('pubsub#node_type', 'leaf') 366 else: 367 self.nodeType = 'leaf' 368 369 370 def _parse_configure(self, verbElement): 371 """ 372 Parse options out of a request for setting the node configuration. 373 """ 374 form = PubSubRequest._findForm(verbElement, NS_PUBSUB_NODE_CONFIG) 375 if form: 376 if form.formType == 'submit': 377 self.options = form.getValues() 378 elif form.formType == 'cancel': 379 self.options = {} 380 else: 381 raise BadRequest(text="Unexpected form type %r" % form.formType) 382 else: 383 raise BadRequest(text="Missing configuration form") 384 385 386 387 def _parse_itemIdentifiers(self, verbElement): 388 """ 389 Parse item identifiers out of items and retract requests. 390 """ 391 self.itemIdentifiers = [] 392 for element in verbElement.elements(): 393 if element.uri == NS_PUBSUB and element.name == 'item': 394 try: 395 self.itemIdentifiers.append(element["id"]) 396 except KeyError: 397 raise BadRequest() 398 399 400 def _render_itemIdentifiers(self, verbElement): 401 """ 402 Render item identifiers into items and retract requests. 403 """ 404 if self.itemIdentifiers: 405 for itemIdentifier in self.itemIdentifiers: 406 item = verbElement.addElement('item') 407 item['id'] = itemIdentifier 408 409 410 def _parse_maxItems(self, verbElement): 411 """ 412 Parse maximum items out of an items request. 413 """ 414 value = verbElement.getAttribute('max_items') 415 416 if value: 417 try: 418 self.maxItems = int(value) 419 except ValueError: 420 raise BadRequest(text="Field max_items requires a positive " + 421 "integer value") 422 423 424 def _render_maxItems(self, verbElement): 425 """ 426 Parse maximum items into an items request. 427 """ 428 if self.maxItems: 429 verbElement['max_items'] = unicode(self.maxItems) 430 431 432 def _parse_options(self, verbElement): 433 form = PubSubRequest._findForm(verbElement, NS_PUBSUB_SUBSCRIBE_OPTIONS) 434 if form: 435 if form.formType == 'submit': 436 self.options = form.getValues() 437 elif form.formType == 'cancel': 438 self.options = {} 439 else: 440 raise BadRequest(text="Unexpected form type %r" % form.formType) 441 else: 442 raise BadRequest(text="Missing options form") 443 444 def parseElement(self, element): 445 """ 446 Parse the publish-subscribe verb and parameters out of a request. 447 """ 448 generic.Stanza.parseElement(self, element) 449 450 for child in element.pubsub.elements(): 451 key = (self.stanzaType, child.uri, child.name) 452 try: 453 verb = self._requestVerbMap[key] 454 except KeyError: 455 continue 456 else: 457 self.verb = verb 458 break 459 460 if not self.verb: 461 raise NotImplementedError() 462 463 for parameter in self._parameters[verb]: 464 getattr(self, '_parse_%s' % parameter)(child) 465 466 467 def send(self, xs): 468 """ 469 Send this request to its recipient. 470 471 This renders all of the relevant parameters for this specific 472 requests into an L{xmlstream.IQ}, and invoke its C{send} method. 473 This returns a deferred that fires upon reception of a response. See 474 L{xmlstream.IQ} for details. 475 476 @param xs: The XML stream to send the request on. 477 @type xs: L{xmlstream.XmlStream} 478 @rtype: L{defer.Deferred}. 479 """ 480 481 try: 482 (self.stanzaType, 483 childURI, 484 childName) = self._verbRequestMap[self.verb] 485 except KeyError: 486 raise NotImplementedError() 487 488 iq = xmlstream.IQ(xs, self.stanzaType) 489 iq.addElement((childURI, 'pubsub')) 490 verbElement = iq.pubsub.addElement(childName) 491 492 if self.sender: 493 iq['from'] = self.sender.full() 494 if self.recipient: 495 iq['to'] = self.recipient.full() 496 497 for parameter in self._parameters[self.verb]: 498 getattr(self, '_render_%s' % parameter)(verbElement) 499 500 return iq.send() 204 501 205 502 … … 337 634 @type nodeIdentifier: C{unicode} 338 635 """ 339 340 341 request = _PubSubRequest(self.xmlstream, 'create') 342 if nodeIdentifier: 343 request.command['node'] = nodeIdentifier 636 request = PubSubRequest('create') 637 request.recipient = service 638 request.nodeIdentifier = nodeIdentifier 344 639 345 640 def cb(iq): … … 351 646 return new_node 352 647 353 return request.send(service).addCallback(cb) 648 d = request.send(self.xmlstream) 649 d.addCallback(cb) 650 return d 354 651 355 652 … … 363 660 @type nodeIdentifier: C{unicode} 364 661 """ 365 request = _PubSubRequest(self.xmlstream, 'delete', NS_PUBSUB_OWNER) 366 request.command['node'] = nodeIdentifier 367 return request.send(service) 662 request = PubSubRequest('delete') 663 request.recipient = service 664 request.nodeIdentifier = nodeIdentifier 665 return request.send(self.xmlstream) 368 666 369 667 … … 380 678 @type subscriber: L{JID} 381 679 """ 382 request = _PubSubRequest(self.xmlstream,'subscribe')383 if nodeIdentifier:384 request.command['node']= nodeIdentifier385 request. command['jid'] = subscriber.full()680 request = PubSubRequest('subscribe') 681 request.recipient = service 682 request.nodeIdentifier = nodeIdentifier 683 request.subscriber = subscriber 386 684 387 685 def cb(iq): … … 398 696 return None 399 697 400 return request.send(service).addCallback(cb) 698 d = request.send(self.xmlstream) 699 d.addCallback(cb) 700 return d 401 701 402 702 … … 412 712 @type subscriber: L{JID} 413 713 """ 414 request = _PubSubRequest(self.xmlstream,'unsubscribe')415 if nodeIdentifier:416 request.command['node']= nodeIdentifier417 request. command['jid'] = subscriber.full()418 return request.send(se rvice)714 request = PubSubRequest('unsubscribe') 715 request.recipient = service 716 request.nodeIdentifier = nodeIdentifier 717 request.subscriber = subscriber 718 return request.send(self.xmlstream) 419 719 420 720 … … 430 730 @type items: C{list} 431 731 """ 432 request = _PubSubRequest(self.xmlstream, 'publish') 433 request.command['node'] = nodeIdentifier 434 if items: 435 for item in items: 436 request.command.addChild(item) 437 438 return request.send(service) 732 request = PubSubRequest('publish') 733 request.recipient = service 734 request.nodeIdentifier = nodeIdentifier 735 request.items = items 736 return request.send(self.xmlstream) 439 737 440 738 … … 450 748 @type maxItems: C{int} 451 749 """ 452 request = _PubSubRequest(self.xmlstream, 'items', method='get')453 if nodeIdentifier:454 request.command['node']= nodeIdentifier750 request = PubSubRequest('items') 751 request.recipient = service 752 request.nodeIdentifier = nodeIdentifier 455 753 if maxItems: 456 request. command["max_items"]= str(int(maxItems))754 request.maxItems = str(int(maxItems)) 457 755 458 756 def cb(iq): … … 463 761 return items 464 762 465 return request.send(service).addCallback(cb) 763 d = request.send(self.xmlstream) 764 d.addCallback(cb) 765 return d 466 766 467 767 … … 498 798 499 799 iqHandlers = { 500 PUBSUB_PUBLISH: '_onPublish', 501 PUBSUB_CREATE: '_onCreate', 502 PUBSUB_SUBSCRIBE: '_onSubscribe', 503 PUBSUB_OPTIONS_GET: '_onOptionsGet', 504 PUBSUB_OPTIONS_SET: '_onOptionsSet', 505 PUBSUB_AFFILIATIONS: '_onAffiliations', 506 PUBSUB_ITEMS: '_onItems', 507 PUBSUB_RETRACT: '_onRetract', 508 PUBSUB_SUBSCRIPTIONS: '_onSubscriptions', 509 PUBSUB_UNSUBSCRIBE: '_onUnsubscribe', 510 511 PUBSUB_AFFILIATIONS_GET: '_onAffiliationsGet', 512 PUBSUB_AFFILIATIONS_SET: '_onAffiliationsSet', 513 PUBSUB_CONFIGURE_GET: '_onConfigureGet', 514 PUBSUB_CONFIGURE_SET: '_onConfigureSet', 515 PUBSUB_DEFAULT: '_onDefault', 516 PUBSUB_PURGE: '_onPurge', 517 PUBSUB_DELETE: '_onDelete', 518 PUBSUB_SUBSCRIPTIONS_GET: '_onSubscriptionsGet', 519 PUBSUB_SUBSCRIPTIONS_SET: '_onSubscriptionsSet', 520 800 '/*': '_onPubSubRequest', 521 801 } 522 802 … … 531 811 532 812 def connectionMade(self): 533 self.xmlstream.addObserver(PUBSUB_GET, self.handleRequest) 534 self.xmlstream.addObserver(PUBSUB_SET, self.handleRequest) 535 self.xmlstream.addObserver(PUBSUB_OWNER_GET, self.handleRequest) 536 self.xmlstream.addObserver(PUBSUB_OWNER_SET, self.handleRequest) 813 self.xmlstream.addObserver(PUBSUB_REQUEST, self.handleRequest) 537 814 538 815 … … 586 863 587 864 588 def _findForm(self, element, formNamespace): 589 if not element: 590 return None 591 592 form = None 593 for child in element.elements(): 594 try: 595 form = data_form.Form.fromElement(child) 596 except data_form.Error: 597 continue 598 599 if form.formNamespace != NS_PUBSUB_NODE_CONFIG: 600 continue 601 602 return form 603 604 605 def _getParameter_node(self, commandElement): 606 try: 607 return commandElement["node"] 608 except KeyError: 609 raise BadRequest('nodeid-required') 610 611 612 def _getParameter_nodeOrEmpty(self, commandElement): 613 return commandElement.getAttribute("node", '') 614 615 616 def _getParameter_jid(self, commandElement): 617 try: 618 return jid.internJID(commandElement["jid"]) 619 except KeyError: 620 raise BadRequest('jid-required') 621 622 623 def _getParameter_max_items(self, commandElement): 624 value = commandElement.getAttribute('max_items') 625 626 if value: 627 try: 628 return int(value) 629 except ValueError: 630 raise BadRequest(text="Field max_items requires a positive " + 631 "integer value") 632 else: 633 return None 634 635 636 def _getParameters(self, iq, *names): 637 requestor = jid.internJID(iq["from"]).userhostJID() 638 service = jid.internJID(iq["to"]) 639 640 params = [requestor, service] 641 642 if names: 643 command = names[0] 644 commandElement = getattr(iq.pubsub, command) 645 if not commandElement: 646 raise Exception("Could not find command element %r" % command) 647 648 for name in names[1:]: 649 try: 650 getter = getattr(self, '_getParameter_' + name) 651 except KeyError: 652 raise Exception("No parameter getter for this name") 653 654 params.append(getter(commandElement)) 655 656 return params 657 658 659 def _onPublish(self, iq): 660 requestor, service, nodeIdentifier = self._getParameters( 661 iq, 'publish', 'node') 662 663 items = [] 664 for element in iq.pubsub.publish.elements(): 665 if element.uri == NS_PUBSUB and element.name == 'item': 666 items.append(element) 667 668 return self.publish(requestor, service, nodeIdentifier, items) 669 670 671 def _onSubscribe(self, iq): 672 requestor, service, nodeIdentifier, subscriber = self._getParameters( 673 iq, 'subscribe', 'nodeOrEmpty', 'jid') 865 def _onPubSubRequest(self, iq): 866 request = PubSubRequest.fromElement(iq) 867 handler = getattr(self, '_on_%s' % request.verb) 868 return handler(request) 869 870 871 def _on_publish(self, request): 872 return self.publish(request.sender, request.recipient, 873 request.nodeIdentifier, request.items) 874 875 876 def _on_subscribe(self, request): 674 877 675 878 def toResponse(result): … … 682 885 return response 683 886 684 d = self.subscribe(requestor, service, nodeIdentifier, subscriber) 887 d = self.subscribe(request.sender, request.recipient, 888 request.nodeIdentifier, request.subscriber) 685 889 d.addCallback(toResponse) 686 890 return d 687 891 688 892 689 def _onUnsubscribe(self, iq): 690 requestor, service, nodeIdentifier, subscriber = self._getParameters( 691 iq, 'unsubscribe', 'nodeOrEmpty', 'jid') 692 693 return self.unsubscribe(requestor, service, nodeIdentifier, subscriber) 694 695 696 def _onOptionsGet(self, iq): 893 def _on_unsubscribe(self, request): 894 return self.unsubscribe(request.sender, request.recipient, 895 request.nodeIdentifier, request.subscriber) 896 897 898 def _on_optionsGet(self, request): 697 899 raise Unsupported('subscription-options') 698 900 699 901 700 def _on OptionsSet(self, iq):902 def _on_optionsSet(self, request): 701 903 raise Unsupported('subscription-options') 702 904 703 905 704 def _onSubscriptions(self, iq): 705 requestor, service = self._getParameters(iq) 906 def _on_subscriptions(self, request): 706 907 707 908 def toResponse(result): … … 715 916 return response 716 917 717 d = self.subscriptions(request or, service)918 d = self.subscriptions(request.sender, request.recipient) 718 919 d.addCallback(toResponse) 719 920 return d 720 921 721 922 722 def _onAffiliations(self, iq): 723 requestor, service = self._getParameters(iq) 923 def _on_affiliations(self, request): 724 924 725 925 def toResponse(result): … … 734 934 return response 735 935 736 d = self.affiliations(request or, service)936 d = self.affiliations(request.sender, request.recipient) 737 937 d.addCallback(toResponse) 738 938 return d 739 939 740 940 741 def _onCreate(self, iq): 742 requestor, service = self._getParameters(iq) 743 nodeIdentifier = iq.pubsub.create.getAttribute("node") 941 def _on_create(self, request): 744 942 745 943 def toResponse(result): 746 if not nodeIdentifier ornodeIdentifier != result:944 if not request.nodeIdentifier or request.nodeIdentifier != result: 747 945 response = domish.Element((NS_PUBSUB, 'pubsub')) 748 946 create = response.addElement('create') … … 752 950 return None 753 951 754 d = self.create(requestor, service, nodeIdentifier) 952 d = self.create(request.sender, request.recipient, 953 request.nodeIdentifier) 755 954 d.addCallback(toResponse) 756 955 return d … … 772 971 return fields 773 972 973 774 974 def _formFromConfiguration(self, values): 775 975 options = self.getConfigurationOptions() … … 780 980 781 981 return form 982 782 983 783 984 def _checkConfiguration(self, values): … … 806 1007 807 1008 808 def _onDefault(self, iq): 809 requestor, service = self._getParameters(iq) 1009 def _on_default(self, request): 810 1010 811 1011 def toResponse(options): … … 815 1015 return response 816 1016 817 form = self._findForm(iq.pubsub.config, NS_PUBSUB_NODE_CONFIG) 818 values = form and form.formType == 'result' and form.getValues() or {} 819 nodeType = values.get('pubsub#node_type', 'leaf') 820 821 if nodeType not in ('leaf', 'collections'): 1017 if request.nodeType not in ('leaf', 'collection'): 822 1018 return defer.fail(error.StanzaError('not-acceptable')) 823 1019 824 d = self.getDefaultConfiguration(requestor, service, nodeType) 1020 d = self.getDefaultConfiguration(request.sender, request.recipient, 1021 request.nodeType) 825 1022 d.addCallback(toResponse) 826 1023 return d 827 1024 828 1025 829 def _onConfigureGet(self, iq): 830 requestor, service, nodeIdentifier = self._getParameters( 831 iq, 'configure', 'nodeOrEmpty') 832 1026 def _on_configureGet(self, request): 833 1027 def toResponse(options): 834 1028 response = domish.Element((NS_PUBSUB_OWNER, "pubsub")) 835 1029 configure = response.addElement("configure") 836 configure.addChild(self._formFromConfiguration(options).toElement()) 837 838 if nodeIdentifier: 839 configure["node"] = nodeIdentifier 1030 form = self._formFromConfiguration(options) 1031 configure.addChild(form.toElement()) 1032 1033 if request.nodeIdentifier: 1034 configure["node"] = request.nodeIdentifier 840 1035 841 1036 return response 842 1037 843 d = self.getConfiguration(requestor, service, nodeIdentifier) 1038 d = self.getConfiguration(request.sender, request.recipient, 1039 request.nodeIdentifier) 844 1040 d.addCallback(toResponse) 845 1041 return d 846 1042 847 1043 848 def _onConfigureSet(self, iq): 849 requestor, service, nodeIdentifier = self._getParameters( 850 iq, 'configure', 'nodeOrEmpty') 851 852 # Search configuration form with correct FORM_TYPE and process it 853 854 form = self._findForm(iq.pubsub.configure, NS_PUBSUB_NODE_CONFIG) 855 856 if form: 857 if form.formType == 'submit': 858 options = self._checkConfiguration(form.getValues()) 859 860 return self.setConfiguration(requestor, service, 861 nodeIdentifier, options) 862 elif form.formType == 'cancel': 863 return None 864 865 raise BadRequest() 866 867 868 def _onItems(self, iq): 869 requestor, service, nodeIdentifier, maxItems = self._getParameters( 870 iq, 'items', 'nodeOrEmpty', 'max_items') 871 872 itemIdentifiers = [] 873 for child in iq.pubsub.items.elements(): 874 if child.name == 'item' and child.uri == NS_PUBSUB: 875 try: 876 itemIdentifiers.append(child["id"]) 877 except KeyError: 878 raise BadRequest() 1044 def _on_configureSet(self, request): 1045 if request.options: 1046 request.options = self._checkConfiguration(request.options) 1047 return self.setConfiguration(request.sender, request.recipient, 1048 request.nodeIdentifier, 1049 request.options) 1050 else: 1051 return None 1052 1053 1054 1055 def _on_items(self, request): 879 1056 880 1057 def toResponse(result): 881 1058 response = domish.Element((NS_PUBSUB, 'pubsub')) 882 1059 items = response.addElement('items') 883 if nodeIdentifier: 884 items["node"] = nodeIdentifier 1060 items["node"] = request.nodeIdentifier 885 1061 886 1062 for item in result: … … 889 1065 return response 890 1066 891 d = self.items(requestor, service, nodeIdentifier, maxItems, 892 itemIdentifiers) 1067 d = self.items(request.sender, request.recipient, 1068 request.nodeIdentifier, request.maxItems, 1069 request.itemIdentifiers) 893 1070 d.addCallback(toResponse) 894 1071 return d 895 1072 896 1073 897 def _onRetract(self, iq): 898 requestor, service, nodeIdentifier = self._getParameters( 899 iq, 'retract', 'node') 900 901 itemIdentifiers = [] 902 for child in iq.pubsub.retract.elements(): 903 if child.uri == NS_PUBSUB and child.name == 'item': 904 try: 905 itemIdentifiers.append(child["id"]) 906 except KeyError: 907 raise BadRequest() 908 909 return self.retract(requestor, service, nodeIdentifier, 910 itemIdentifiers) 911 912 913 def _onPurge(self, iq): 914 requestor, service, nodeIdentifier = self._getParameters( 915 iq, 'purge', 'node') 916 return self.purge(requestor, service, nodeIdentifier) 917 918 919 def _onDelete(self, iq): 920 requestor, service, nodeIdentifier = self._getParameters( 921 iq, 'delete', 'node') 922 return self.delete(requestor, service, nodeIdentifier) 923 924 925 def _onAffiliationsGet(self, iq): 1074 def _on_retract(self, request): 1075 return self.retract(request.sender, request.recipient, 1076 request.nodeIdentifier, request.itemIdentifiers) 1077 1078 1079 def _on_purge(self, request): 1080 return self.purge(request.sender, request.recipient, 1081 request.nodeIdentifier) 1082 1083 1084 def _on_delete(self, request): 1085 return self.delete(request.sender, request.recipient, 1086 request.nodeIdentifier) 1087 1088 1089 def _on_affiliationsGet(self, iq): 926 1090 raise Unsupported('modify-affiliations') 927 1091 928 1092 929 def _on AffiliationsSet(self, iq):1093 def _on_affiliationsSet(self, iq): 930 1094 raise Unsupported('modify-affiliations') 931 1095 932 1096 933 def _on SubscriptionsGet(self, iq):1097 def _on_subscriptionsGet(self, iq): 934 1098 raise Unsupported('manage-subscriptions') 935 1099 936 1100 937 def _on SubscriptionsSet(self, iq):1101 def _on_subscriptionsSet(self, iq): 938 1102 raise Unsupported('manage-subscriptions') 939 1103
Note: See TracChangeset
for help on using the changeset viewer.