blather 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data/LICENSE +2 -0
  2. data/README.rdoc +54 -29
  3. data/Rakefile +94 -13
  4. data/VERSION.yml +4 -0
  5. data/examples/drb_client.rb +2 -4
  6. data/examples/echo.rb +13 -8
  7. data/examples/pubsub/cli.rb +64 -0
  8. data/examples/pubsub/ping_pong.rb +18 -0
  9. data/examples/pubsub/pubsub_dsl.rb +52 -0
  10. data/examples/pubsub_client.rb +39 -0
  11. data/examples/rosterprint.rb +14 -0
  12. data/examples/xmpp4r/echo.rb +35 -0
  13. data/ext/extconf.rb +65 -0
  14. data/lib/blather.rb +18 -121
  15. data/lib/blather/client.rb +13 -0
  16. data/lib/blather/client/client.rb +165 -0
  17. data/lib/blather/client/dsl.rb +99 -0
  18. data/lib/blather/client/pubsub.rb +53 -0
  19. data/lib/blather/client/pubsub/node.rb +27 -0
  20. data/lib/blather/core_ext/active_support.rb +1 -0
  21. data/lib/blather/core_ext/libxml.rb +7 -1
  22. data/lib/blather/errors.rb +39 -18
  23. data/lib/blather/errors/sasl_error.rb +87 -0
  24. data/lib/blather/errors/stanza_error.rb +262 -0
  25. data/lib/blather/errors/stream_error.rb +253 -0
  26. data/lib/blather/jid.rb +9 -16
  27. data/lib/blather/roster.rb +9 -0
  28. data/lib/blather/roster_item.rb +7 -4
  29. data/lib/blather/stanza.rb +19 -25
  30. data/lib/blather/stanza/disco.rb +9 -0
  31. data/lib/blather/stanza/disco/disco_info.rb +84 -0
  32. data/lib/blather/stanza/disco/disco_items.rb +59 -0
  33. data/lib/blather/stanza/iq.rb +16 -4
  34. data/lib/blather/stanza/iq/query.rb +6 -4
  35. data/lib/blather/stanza/iq/roster.rb +38 -38
  36. data/lib/blather/stanza/pubsub.rb +33 -0
  37. data/lib/blather/stanza/pubsub/affiliations.rb +52 -0
  38. data/lib/blather/stanza/pubsub/errors.rb +9 -0
  39. data/lib/blather/stanza/pubsub/event.rb +21 -0
  40. data/lib/blather/stanza/pubsub/items.rb +59 -0
  41. data/lib/blather/stanza/pubsub/owner.rb +9 -0
  42. data/lib/blather/stanza/pubsub/subscriptions.rb +57 -0
  43. data/lib/blather/stream.rb +125 -57
  44. data/lib/blather/stream/client.rb +26 -0
  45. data/lib/blather/stream/component.rb +34 -0
  46. data/lib/blather/stream/parser.rb +17 -27
  47. data/lib/blather/stream/resource.rb +21 -24
  48. data/lib/blather/stream/sasl.rb +60 -37
  49. data/lib/blather/stream/session.rb +12 -19
  50. data/lib/blather/stream/stream_handler.rb +39 -0
  51. data/lib/blather/stream/tls.rb +22 -18
  52. data/lib/blather/xmpp_node.rb +91 -17
  53. data/spec/blather/core_ext/libxml_spec.rb +58 -0
  54. data/spec/blather/errors/sasl_error_spec.rb +56 -0
  55. data/spec/blather/errors/stanza_error_spec.rb +148 -0
  56. data/spec/blather/errors/stream_error_spec.rb +114 -0
  57. data/spec/blather/errors_spec.rb +40 -0
  58. data/spec/blather/jid_spec.rb +0 -7
  59. data/spec/blather/roster_item_spec.rb +5 -0
  60. data/spec/blather/roster_spec.rb +6 -6
  61. data/spec/blather/stanza/discos/disco_info_spec.rb +207 -0
  62. data/spec/blather/stanza/discos/disco_items_spec.rb +136 -0
  63. data/spec/blather/stanza/iq/query_spec.rb +9 -2
  64. data/spec/blather/stanza/iq/roster_spec.rb +117 -1
  65. data/spec/blather/stanza/iq_spec.rb +29 -0
  66. data/spec/blather/stanza/presence/subscription_spec.rb +12 -1
  67. data/spec/blather/stanza/presence_spec.rb +29 -0
  68. data/spec/blather/stanza/pubsub/affiliations_spec.rb +46 -0
  69. data/spec/blather/stanza/pubsub/items_spec.rb +59 -0
  70. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +63 -0
  71. data/spec/blather/stanza/pubsub_spec.rb +26 -0
  72. data/spec/blather/stanza_spec.rb +13 -1
  73. data/spec/blather/stream/client_spec.rb +787 -0
  74. data/spec/blather/stream/component_spec.rb +86 -0
  75. data/spec/blather/xmpp_node_spec.rb +75 -22
  76. data/spec/fixtures/pubsub.rb +157 -0
  77. data/spec/spec_helper.rb +6 -14
  78. metadata +86 -74
  79. data/CHANGELOG +0 -5
  80. data/Manifest +0 -47
  81. data/blather.gemspec +0 -41
  82. data/lib/blather/stanza/error.rb +0 -31
  83. data/spec/blather/stream_spec.rb +0 -462
  84. data/spec/build_safe.rb +0 -20
@@ -0,0 +1,99 @@
1
+ require File.join(File.dirname(__FILE__), 'client')
2
+
3
+ module Blather
4
+ module DSL
5
+ def client
6
+ @client ||= Client.new
7
+ end
8
+ module_function :client
9
+
10
+ ##
11
+ # Prepare server settings
12
+ # setup [node@domain/resource], [password], [host], [port]
13
+ # host and port are optional defaulting to the domain in the JID and 5222 respectively
14
+ def setup(jid, password, host = nil, port = nil)
15
+ client.setup(jid, password, host, port)
16
+ at_exit { client.run }
17
+ end
18
+
19
+ ##
20
+ # Shutdown the connection.
21
+ # Flushes the write buffer then stops EventMachine
22
+ def shutdown
23
+ client.stop
24
+ end
25
+
26
+ ##
27
+ # Set handler for a stanza type
28
+ def handle(stanza_type, *guards, &block)
29
+ client.register_handler stanza_type, *guards, &block
30
+ end
31
+
32
+ ##
33
+ # Wrapper for "handle :ready" (just a bit of syntactic sugar)
34
+ def when_ready(&block)
35
+ handle :ready, &block
36
+ end
37
+
38
+ ##
39
+ # Set current status
40
+ def status(state = nil, msg = nil)
41
+ client.status = state, msg
42
+ end
43
+
44
+ ##
45
+ # Direct access to the roster
46
+ def roster
47
+ client.roster
48
+ end
49
+
50
+ ##
51
+ # Write data to the stream
52
+ # Anything that resonds to #to_s can be paseed to the stream
53
+ def write(stanza)
54
+ client.write(stanza)
55
+ end
56
+
57
+ ##
58
+ # Helper method to make sending basic messages easier
59
+ # say [jid], [msg]
60
+ def say(to, msg)
61
+ client.write Blather::Stanza::Message.new(to, msg)
62
+ end
63
+
64
+ ##
65
+ # Wrapper to grab the current JID
66
+ def jid
67
+ client.jid
68
+ end
69
+
70
+ ##
71
+ #
72
+ def discover(what, who, where, &callback)
73
+ stanza = Blather::Stanza.class_from_registration(:query, "http://jabber.org/protocol/disco##{what}").new
74
+ stanza.to = who
75
+ stanza.node = where
76
+
77
+ client.temporary_handler stanza.id, &callback
78
+ write stanza
79
+ end
80
+
81
+ ##
82
+ # PubSub proxy
83
+ def pubsub
84
+ client.pubsub
85
+ end
86
+
87
+ ##
88
+ # Checks to see if the method is part of the handlers list.
89
+ # If so it creates a handler, otherwise it'll pass it back
90
+ # to Ruby's method_missing handler
91
+ def method_missing(method, *args, &block)
92
+ if Blather::Stanza.handler_list.include?(method)
93
+ handle method, *args, &block
94
+ else
95
+ super
96
+ end
97
+ end
98
+ end #DSL
99
+ end #Blather
@@ -0,0 +1,53 @@
1
+ module Blather
2
+ class Client
3
+
4
+ class PubSub
5
+ attr_accessor :host
6
+
7
+ def affiliations(&callback)
8
+ request Stanza::PubSub::Affiliations.new(:get, @host), :affiliates, callback
9
+ end
10
+
11
+ def subscriptions(&callback)
12
+ request Stanza::PubSub::Subscriptions.new(:get, @host), :subscriptions, callback
13
+ end
14
+
15
+ def nodes(path, &callback)
16
+ stanza = Stanza::DiscoItems.new(:get, path)
17
+ stanza.to = @host
18
+ request stanza, :items, callback
19
+ end
20
+
21
+ def node(path)
22
+ stanza = Stanza::DiscoInfo.new(:get, path)
23
+ stanza.to = @host
24
+ request(stanza) { |node| yield Stanza::PubSub::Node.import(node) }
25
+ end
26
+
27
+ def items(path, list = [], max = nil, &callback)
28
+ request Stanza::PubSub.items(@host, path, list, max), :items, callback
29
+ end
30
+ =begin
31
+ def create(node)
32
+ end
33
+
34
+ def publish(node, payload)
35
+ end
36
+
37
+ def subscribe(node)
38
+ DSL.client.write Stanza::PubSub::Subscribe.new(:set, host, node, DSL.client.jid)
39
+ end
40
+
41
+ def unsubscribe(node)
42
+ DSL.client.write Stanza::PubSub::Unsubscribe.new(:set, host, node, DSL.client.jid)
43
+ end
44
+ =end
45
+ private
46
+ def request(node, method = nil, callback, &block)
47
+ block = lambda { |node| callback.call node.__send__(method) } unless block_given?
48
+ DSL.client.write_with_handler(node, &block)
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ module Blather
2
+ class Client
3
+ class PubSub
4
+
5
+ class Node
6
+ attr_accessor :path
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def info(&block)
13
+ DSL.client.write_with_handler Stanza::DiscoInfo.new(:get, path), &block
14
+ end
15
+
16
+ def items(&block)
17
+ DSL.client.write_with_handler Stanza::PubSub.items(path), &block
18
+ end
19
+
20
+ def nodes(&block)
21
+ DSL.client.write_with_handler Stanza::DiscoItems.new(:get, path), &block
22
+ end
23
+ end
24
+
25
+ end #PubSub
26
+ end #Client
27
+ end #Blather
@@ -124,6 +124,7 @@ end
124
124
 
125
125
  class Array #:nodoc:
126
126
  alias_method :blank?, :empty?
127
+ def extract_options!; last.is_a?(::Hash) ? pop : {}; end
127
128
  end
128
129
 
129
130
  class Hash #:nodoc:
@@ -3,6 +3,7 @@ module LibXML # :nodoc:
3
3
 
4
4
  class Node
5
5
  alias_method :element_name, :name
6
+ alias_method :element_name=, :name=
6
7
  end
7
8
 
8
9
  class Attributes
@@ -12,10 +13,15 @@ module LibXML # :nodoc:
12
13
  attribute.remove! if attribute
13
14
  end
14
15
 
15
- alias_method :old_hash_set, :[]=
16
+ alias_method :old_hash_set, :[]= # :nodoc:
16
17
  def []=(name, val)
17
18
  val.nil? ? remove(name.to_s) : old_hash_set(name.to_s, val.to_s)
18
19
  end
20
+
21
+ alias_method :old_hash_get, :[] # :nodoc:
22
+ def [](name)
23
+ old_hash_get name.to_s
24
+ end
19
25
  end #Attributes
20
26
 
21
27
  end #XML
@@ -1,27 +1,48 @@
1
1
  module Blather
2
2
  # Main error class
3
- class BlatherError < StandardError; end
3
+ class BlatherError < StandardError
4
+ class_inheritable_array :handler_heirarchy
4
5
 
5
- #Parse Errors
6
- class ParseError < BlatherError; end
6
+ self.handler_heirarchy ||= []
7
+ self.handler_heirarchy << :error
7
8
 
8
- # Stream errors
9
- class StreamError < BlatherError
10
- attr_accessor :type, :text
9
+ def self.register(handler)
10
+ self.handler_heirarchy.unshift handler
11
+ end
12
+ end
11
13
 
12
- def initialize(node)
13
- @type = node.detect { |n| n.name != 'text' && n['xmlns'] == 'urn:ietf:params:xml:ns:xmpp-streams' }
14
- @text = node.detect { |n| n.name == 'text' }
14
+ ##
15
+ # Used in cases where a stanza only allows specific values for its attributes
16
+ # and an invalid value is attempted.
17
+ class ArgumentError < BlatherError
18
+ register :argument_error
19
+ end
15
20
 
16
- @extra = node.detect { |n| n['xmlns'] != 'urn:ietf:params:xml:ns:xmpp-streams' }
17
- end
21
+ ##
22
+ # The stream handler received a response it didn't know how to handle
23
+ class UnknownResponse < BlatherError
24
+ register :unknown_response_error
25
+ attr_reader :node
18
26
 
19
- def to_s
20
- "Stream Error (#{type.name}) #{"[#{@extra.name}]" if @extra}: #{text.content if text}"
21
- end
27
+ def initialize(node)
28
+ @node = node
22
29
  end
30
+ end
31
+
32
+ ##
33
+ # TLS negotiations broke down
34
+ class TLSFailure < BlatherError
35
+ register :tls_failure
36
+ end
23
37
 
24
- # Stanza errors
25
- class StanzaError < BlatherError; end
26
- class ArgumentError < StanzaError; end
27
- end
38
+ ##
39
+ # Something bad happened while parsing the incoming stream
40
+ class ParseError < BlatherError
41
+ register :parse_error
42
+ attr_reader :message
43
+
44
+ def initialize(message)
45
+ @message = message
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,87 @@
1
+ module Blather
2
+
3
+ class SASLError < BlatherError
4
+ class_inheritable_accessor :err_name
5
+ @@registrations = {}
6
+
7
+ register :sasl_error
8
+
9
+ ##
10
+ # Register the handler and type to simplify importing
11
+ def self.register(handler, err_name)
12
+ super handler
13
+ self.err_name = err_name
14
+ @@registrations[err_name] = self
15
+ end
16
+
17
+ ##
18
+ # Retreive an error class from a given name
19
+ def self.class_from_registration(err_name)
20
+ @@registrations[err_name.to_s] || self
21
+ end
22
+
23
+ ##
24
+ # Factory to create the proper error object from an error node
25
+ def self.import(node)
26
+ err_name = node.children.first.element_name
27
+ class_from_registration(err_name).new
28
+ end
29
+
30
+ ##
31
+ # XMPP defined error name
32
+ def err_name
33
+ self.class.err_name
34
+ end
35
+
36
+ ##
37
+ # The receiving entity acknowledges an <abort/> element sent by the initiating entity; sent in reply to the <abort/> element.
38
+ class Aborted < SASLError
39
+ register :sasl_aborted_error, 'aborted'
40
+ end
41
+
42
+ ##
43
+ # The data provided by the initiating entity could not be processed because the [BASE64] encoding is incorrect
44
+ # (e.g., because the encoding does not adhere to the definition in Section 3 of [BASE64]); sent in reply to a <response/>
45
+ # element or an <auth/> element with initial response data.
46
+ class IncorrectEncoding < SASLError
47
+ register :sasl_incorrect_encoding_error, 'incorrect-encoding'
48
+ end
49
+
50
+ ##
51
+ # The authzid provided by the initiating entity is invalid, either because it is incorrectly formatted or because the
52
+ # initiating entity does not have permissions to authorize that ID; sent in reply to a <response/> element or an <auth/>
53
+ # element with initial response data.
54
+ class InvalidAuthzid < SASLError
55
+ register :sasl_invalid_authzid_error, 'invalid-authzid'
56
+ end
57
+
58
+ ##
59
+ # The initiating entity did not provide a mechanism or requested a mechanism that is not supported by the receiving entity;
60
+ # sent in reply to an <auth/> element.
61
+ class InvalidMechanism < SASLError
62
+ register :sasl_invalid_mechanism_error, 'invalid-mechanism'
63
+ end
64
+
65
+ ##
66
+ # The mechanism requested by the initiating entity is weaker than server policy permits for that initiating entity; sent in
67
+ # reply to a <response/> element or an <auth/> element with initial response data.
68
+ class MechanismTooWeak < SASLError
69
+ register :sasl_mechanism_too_weak_error, 'mechanism-too-weak'
70
+ end
71
+
72
+ ##
73
+ # The authentication failed because the initiating entity did not provide valid credentials (this includes but is not limited
74
+ # to the case of an unknown username); sent in reply to a <response/> element or an <auth/> element with initial response data.
75
+ class NotAuthorized < SASLError
76
+ register :sasl_not_authorized_error, 'not-authorized'
77
+ end
78
+
79
+ ##
80
+ # The authentication failed because of a temporary error condition within the receiving entity; sent in reply to an <auth/>
81
+ # element or <response/> element.
82
+ class TemporaryAuthFailure < SASLError
83
+ register :sasl_temporary_auth_failure_error, 'temporary-auth-failure'
84
+ end
85
+ end #SASLError
86
+
87
+ end #Blather
@@ -0,0 +1,262 @@
1
+ module Blather
2
+
3
+ ##
4
+ # Stanza errors
5
+ # RFC3920 Section 9.3 (http://xmpp.org/rfcs/rfc3920.html#stanzas-error)
6
+ class StanzaError < BlatherError
7
+ VALID_TYPES = [:cancel, :continue, :modify, :auth, :wait]
8
+
9
+ class_inheritable_accessor :err_name
10
+ @@registrations = {}
11
+
12
+ register :stanza_error
13
+
14
+ attr_reader :original, :type, :text, :extras
15
+
16
+ ##
17
+ # Register the handler and type to simplify importing
18
+ def self.register(handler, err_name)
19
+ super handler
20
+ self.err_name = err_name
21
+ @@registrations[err_name] = self
22
+ end
23
+
24
+ ##
25
+ # Retreive an error class from a given name
26
+ def self.class_from_registration(err_name)
27
+ @@registrations[err_name.to_s] || self
28
+ end
29
+
30
+ ##
31
+ # Factory method for instantiating the proper class
32
+ # for the error
33
+ def self.import(node)
34
+ original = node.copy
35
+ original.remove_child 'error'
36
+
37
+ error_node = node.find_first 'child::error'
38
+
39
+ name = error_node.find_first('child::*[name()!="text"]', 'urn:ietf:params:xml:ns:xmpp-stanzas').element_name
40
+ type = error_node['type']
41
+ text = node.find_first 'descendant::text', 'urn:ietf:params:xml:ns:xmpp-stanzas'
42
+ text = text.content if text
43
+
44
+ extras = error_node.find("descendant::*[name()!='text' and name()!='#{name}']").map { |n| n }
45
+
46
+ class_from_registration(name).new original, type, text, extras
47
+ end
48
+
49
+ ##
50
+ # <tt>original</tt> An original node must be provided for stanza errors. You can't declare
51
+ # a stanza error on without a stanza.
52
+ # <tt>type</tt> is the error type specified in RFC3920 (http://xmpp.org/rfcs/rfc3920.html#rfc.section.9.3.2)
53
+ # <tt>text</tt> is an option error description
54
+ # <tt>extras</tt> an array of application specific nodes to add to the error. These should be properly namespaced.
55
+ def initialize(original, type, text = nil, extras = [])
56
+ @original = original
57
+ self.type = type
58
+ @text = text
59
+ @extras = extras
60
+ end
61
+
62
+ ##
63
+ # XMPP defined error name
64
+ def err_name
65
+ self.class.err_name
66
+ end
67
+
68
+ ##
69
+ # Set the error type (see RFC3920 Section 9.3.2 (http://xmpp.org/rfcs/rfc3920.html#rfc.section.9.3.2))
70
+ def type=(type)
71
+ type = type.to_sym
72
+ raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}" if !VALID_TYPES.include?(type)
73
+ @type = type
74
+ end
75
+
76
+ ##
77
+ # Creates an XML node from the error
78
+ def to_node
79
+ node = self.original.reply
80
+
81
+ error_node = XMPPNode.new 'error'
82
+ err = XMPPNode.new(self.err_name)
83
+ err.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
84
+ error_node << err
85
+
86
+ if self.text
87
+ text = XMPPNode.new('text')
88
+ text.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
89
+ text << self.text
90
+ error_node << text
91
+ end
92
+
93
+ self.extras.each do |extra|
94
+ extra_copy = extra.copy
95
+ extra_copy.namespace = extra.namespace
96
+ error_node << extra_copy
97
+ end
98
+
99
+ node << error_node
100
+ node.type = 'error'
101
+ node
102
+ end
103
+
104
+ ##
105
+ # Turns the object into XML fit to be sent over the stream
106
+ def to_xml
107
+ to_node.to_s
108
+ end
109
+
110
+ def inspect # :nodoc:
111
+ "Stanza Error (#{self.err_name}): #{self.text}"
112
+ end
113
+ alias_method :to_s, :inspect # :nodoc:
114
+
115
+ ##
116
+ # The sender has sent XML that is malformed or that cannot be processed (e.g., an IQ stanza that includes
117
+ # an unrecognized value of the 'type' attribute); the associated error type SHOULD be "modify"
118
+ class BadRequest < StanzaError
119
+ register :stanza_bad_request_error, 'bad-request'
120
+ end
121
+
122
+ ##
123
+ # Access cannot be granted because an existing resource or session exists with the same name or address;
124
+ # the associated error type SHOULD be "cancel"
125
+ class Conflict < StanzaError
126
+ register :stanza_conflict_error, 'conflict'
127
+ end
128
+
129
+ ##
130
+ # the feature requested is not implemented by the recipient or server and therefore cannot be processed;
131
+ # the associated error type SHOULD be "cancel".
132
+ class FeatureNotImplemented < StanzaError
133
+ register :stanza_feature_not_implemented_error, 'feature-not-implemented'
134
+ end
135
+
136
+ ##
137
+ # the requesting entity does not possess the required permissions to perform the action;
138
+ # the associated error type SHOULD be "auth".
139
+ class Forbidden < StanzaError
140
+ register :stanza_forbidden_error, 'forbidden'
141
+ end
142
+
143
+ ##
144
+ # the recipient or server can no longer be contacted at this address (the error stanza MAY contain a new address
145
+ # in the XML character data of the <gone/> element); the associated error type SHOULD be "modify".
146
+ class Gone < StanzaError
147
+ register :stanza_gone_error, 'gone'
148
+ end
149
+
150
+ ##
151
+ # the server could not process the stanza because of a misconfiguration or an otherwise-undefined internal server error;
152
+ # the associated error type SHOULD be "wait".
153
+ class InternalServerError < StanzaError
154
+ register :stanza_internal_server_error, 'internal-server-error'
155
+ end
156
+
157
+ ##
158
+ # the addressed JID or item requested cannot be found; the associated error type SHOULD be "cancel".
159
+ class ItemNotFound < StanzaError
160
+ register :stanza_item_not_found_error, 'item-not-found'
161
+ end
162
+
163
+ ##
164
+ # the addressed JID or item requested cannot be found; the associated error type SHOULD be "cancel".
165
+ class JidMalformed < StanzaError
166
+ register :stanza_jid_malformed_error, 'jid-malformed'
167
+ end
168
+
169
+ ##
170
+ # the recipient or server understands the request but is refusing to process it because it does not meet criteria defined
171
+ # by the recipient or server (e.g., a local policy regarding acceptable words in messages); the associated error type SHOULD be "modify".
172
+ class NotAcceptable < StanzaError
173
+ register :stanza_not_acceptable_error, 'not-acceptable'
174
+ end
175
+
176
+ ##
177
+ # The recipient or server does not allow any entity to perform the action; the associated error type SHOULD be "cancel".
178
+ class NotAllowed < StanzaError
179
+ register :stanza_not_allowed_error, 'not-allowed'
180
+ end
181
+
182
+ ##
183
+ # the sender must provide proper credentials before being allowed to perform the action, or has provided improper credentials;
184
+ # the associated error type SHOULD be "auth".
185
+ class NotAuthorized < StanzaError
186
+ register :stanza_not_authorized_error, 'not-authorized'
187
+ end
188
+
189
+ ##
190
+ # the requesting entity is not authorized to access the requested service because payment is required; the associated error type SHOULD be "auth".
191
+ class PaymentRequired < StanzaError
192
+ register :stanza_payment_required_error, 'payment-required'
193
+ end
194
+
195
+ ##
196
+ # the intended recipient is temporarily unavailable; the associated error type SHOULD be "wait" (note: an application MUST NOT
197
+ # return this error if doing so would provide information about the intended recipient's network availability to an entity that
198
+ # is not authorized to know such information).
199
+ class RecipientUnavailable < StanzaError
200
+ register :stanza_recipient_unavailable_error, 'recipient-unavailable'
201
+ end
202
+
203
+ ##
204
+ # the recipient or server is redirecting requests for this information to another entity, usually temporarily (the error stanza SHOULD contain
205
+ # the alternate address, which MUST be a valid JID, in the XML character data of the <redirect/> element); the associated error type SHOULD be "modify".
206
+ class Redirect < StanzaError
207
+ register :stanza_redirect_error, 'redirect'
208
+ end
209
+
210
+ ##
211
+ # the requesting entity is not authorized to access the requested service because registration is required; the associated error type SHOULD be "auth".
212
+ class RegistrationRequired < StanzaError
213
+ register :stanza_registration_required_error, 'registration-required'
214
+ end
215
+
216
+ ##
217
+ # a remote server or service specified as part or all of the JID of the intended recipient does not exist; the associated error type SHOULD be "cancel".
218
+ class RemoteServerNotFound < StanzaError
219
+ register :stanza_remote_server_not_found_error, 'remote-server-not-found'
220
+ end
221
+
222
+ ##
223
+ # a remote server or service specified as part or all of the JID of the intended recipient (or required to fulfill a request) could not be
224
+ # contacted within a reasonable amount of time; the associated error type SHOULD be "wait".
225
+ class RemoteServerTimeout < StanzaError
226
+ register :stanza_remote_server_timeout_error, 'remote-server-timeout'
227
+ end
228
+
229
+ ##
230
+ # the server or recipient lacks the system resources necessary to service the request; the associated error type SHOULD be "wait".
231
+ class ResourceConstraint < StanzaError
232
+ register :stanza_resource_constraint_error, 'resource-constraint'
233
+ end
234
+
235
+ ##
236
+ # the server or recipient does not currently provide the requested service; the associated error type SHOULD be "cancel".
237
+ class ServiceUnavailable < StanzaError
238
+ register :stanza_service_unavailable_error, 'service-unavailable'
239
+ end
240
+
241
+ ##
242
+ # the requesting entity is not authorized to access the requested service because a subscription is required; the associated error type SHOULD be "auth".
243
+ class SubscriptionRequired < StanzaError
244
+ register :stanza_subscription_required_error, 'subscription-required'
245
+ end
246
+
247
+ ##
248
+ # the error condition is not one of those defined by the other conditions in this list; any error type may be associated with this condition,
249
+ # and it SHOULD be used only in conjunction with an application-specific condition.
250
+ class UndefinedCondition < StanzaError
251
+ register :stanza_undefined_condition_error, 'undefined-condition'
252
+ end
253
+
254
+ ##
255
+ # the recipient or server understood the request but was not expecting it at this time (e.g., the request was out of order);
256
+ # the associated error type SHOULD be "wait".
257
+ class UnexpectedRequest < StanzaError
258
+ register :stanza_unexpected_request_error, 'unexpected-request'
259
+ end
260
+ end #StanzaError
261
+
262
+ end #Blather