rootstanza.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. """
  2. SleekXMPP: The Sleek XMPP Library
  3. Copyright (C) 2010 Nathanael C. Fritz
  4. This file is part of SleekXMPP.
  5. See the file LICENSE for copying permission.
  6. """
  7. import logging
  8. from sleekxmpp.exceptions import XMPPError, IqError, IqTimeout
  9. from sleekxmpp.stanza import Error
  10. from sleekxmpp.xmlstream import ET, StanzaBase, register_stanza_plugin
  11. log = logging.getLogger(__name__)
  12. class RootStanza(StanzaBase):
  13. """
  14. A top-level XMPP stanza in an XMLStream.
  15. The RootStanza class provides a more XMPP specific exception
  16. handler than provided by the generic StanzaBase class.
  17. Methods:
  18. exception -- Overrides StanzaBase.exception
  19. """
  20. def exception(self, e):
  21. """
  22. Create and send an error reply.
  23. Typically called when an event handler raises an exception.
  24. The error's type and text content are based on the exception
  25. object's type and content.
  26. Overrides StanzaBase.exception.
  27. Arguments:
  28. e -- Exception object
  29. """
  30. if isinstance(e, IqError):
  31. # We received an Iq error reply, but it wasn't caught
  32. # locally. Using the condition/text from that error
  33. # response could leak too much information, so we'll
  34. # only use a generic error here.
  35. self.reply()
  36. self['error']['condition'] = 'undefined-condition'
  37. self['error']['text'] = 'External error'
  38. self['error']['type'] = 'cancel'
  39. log.warning('You should catch IqError exceptions')
  40. self.send()
  41. elif isinstance(e, IqTimeout):
  42. self.reply()
  43. self['error']['condition'] = 'remote-server-timeout'
  44. self['error']['type'] = 'wait'
  45. log.warning('You should catch IqTimeout exceptions')
  46. self.send()
  47. elif isinstance(e, XMPPError):
  48. # We raised this deliberately
  49. keep_id = self['id']
  50. self.reply(clear=e.clear)
  51. self['id'] = keep_id
  52. self['error']['condition'] = e.condition
  53. self['error']['text'] = e.text
  54. self['error']['type'] = e.etype
  55. if e.extension is not None:
  56. # Extended error tag
  57. extxml = ET.Element("{%s}%s" % (e.extension_ns, e.extension),
  58. e.extension_args)
  59. self['error'].append(extxml)
  60. self.send()
  61. else:
  62. # We probably didn't raise this on purpose, so send an error stanza
  63. keep_id = self['id']
  64. self.reply()
  65. self['id'] = keep_id
  66. self['error']['condition'] = 'undefined-condition'
  67. self['error']['text'] = "SleekXMPP got into trouble."
  68. self['error']['type'] = 'cancel'
  69. self.send()
  70. # log the error
  71. log.exception('Error handling {%s}%s stanza',
  72. self.namespace, self.name)
  73. # Finally raise the exception to a global exception handler
  74. self.stream.exception(e)
  75. register_stanza_plugin(RootStanza, Error)