blather 0.4.16 → 0.5.0

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 (62) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG +12 -5
  3. data/README.md +1 -1
  4. data/Rakefile +1 -3
  5. data/blather.gemspec +11 -24
  6. data/examples/echo.rb +1 -0
  7. data/examples/execute.rb +1 -0
  8. data/examples/ping_pong.rb +1 -0
  9. data/examples/print_hierarchy.rb +1 -0
  10. data/examples/rosterprint.rb +1 -0
  11. data/examples/stream_only.rb +1 -0
  12. data/examples/xmpp4r/echo.rb +1 -0
  13. data/lib/blather.rb +5 -1
  14. data/lib/blather/client/client.rb +29 -154
  15. data/lib/blather/client/dsl.rb +9 -3
  16. data/lib/blather/client/dsl/pubsub.rb +2 -0
  17. data/lib/blather/core_ext/eventmachine.rb +4 -1
  18. data/lib/blather/core_ext/ipaddr.rb +2 -1
  19. data/lib/blather/core_ext/nokogiri.rb +3 -1
  20. data/lib/blather/errors/sasl_error.rb +1 -0
  21. data/lib/blather/errors/stanza_error.rb +3 -1
  22. data/lib/blather/errors/stream_error.rb +1 -0
  23. data/lib/blather/file_transfer.rb +4 -1
  24. data/lib/blather/file_transfer/s5b.rb +3 -4
  25. data/lib/blather/jid.rb +2 -0
  26. data/lib/blather/roster_item.rb +13 -3
  27. data/lib/blather/stanza.rb +11 -3
  28. data/lib/blather/stanza/disco/capabilities.rb +161 -0
  29. data/lib/blather/stanza/disco/disco_info.rb +3 -1
  30. data/lib/blather/stanza/disco/disco_items.rb +0 -1
  31. data/lib/blather/stanza/iq.rb +8 -2
  32. data/lib/blather/stanza/iq/command.rb +18 -3
  33. data/lib/blather/stanza/iq/ibb.rb +6 -3
  34. data/lib/blather/stanza/iq/s5b.rb +6 -3
  35. data/lib/blather/stanza/iq/si.rb +6 -1
  36. data/lib/blather/stanza/iq/vcard.rb +3 -1
  37. data/lib/blather/stanza/message.rb +5 -0
  38. data/lib/blather/stanza/presence.rb +1 -0
  39. data/lib/blather/stanza/presence/c.rb +1 -0
  40. data/lib/blather/stanza/presence/status.rb +1 -0
  41. data/lib/blather/stanza/pubsub/event.rb +2 -4
  42. data/lib/blather/stanza/pubsub/subscription.rb +1 -0
  43. data/lib/blather/stanza/x.rb +8 -0
  44. data/lib/blather/stream.rb +2 -0
  45. data/lib/blather/stream/client.rb +1 -0
  46. data/lib/blather/stream/component.rb +1 -0
  47. data/lib/blather/stream/features.rb +4 -3
  48. data/lib/blather/stream/features/resource.rb +4 -3
  49. data/lib/blather/stream/features/sasl.rb +9 -6
  50. data/lib/blather/stream/features/session.rb +5 -4
  51. data/lib/blather/stream/features/tls.rb +4 -3
  52. data/lib/blather/stream/parser.rb +4 -5
  53. data/lib/blather/version.rb +2 -1
  54. data/lib/blather/xmpp_node.rb +9 -0
  55. data/spec/blather/client/client_spec.rb +14 -1
  56. data/spec/blather/stanza/iq_spec.rb +16 -0
  57. data/spec/blather/stanza/presence_spec.rb +1 -1
  58. data/spec/blather/stanza_spec.rb +18 -0
  59. data/spec/blather/stream/client_spec.rb +2 -2
  60. metadata +52 -35
  61. data/lib/blather/core_ext/active_support.rb +0 -45
  62. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +0 -117
@@ -121,7 +121,6 @@ class Stanza
121
121
  write_attr :name, name
122
122
  end
123
123
 
124
-
125
124
  # Compare two DiscoItems::Item objects by name, type and category
126
125
  # @param [DiscoItems::Item] o the Identity object to compare against
127
126
  # @return [true, false]
@@ -53,6 +53,7 @@ class Stanza
53
53
  #
54
54
  # @handler :iq
55
55
  class Iq < Stanza
56
+ # @private
56
57
  VALID_TYPES = [:get, :set, :result, :error].freeze
57
58
 
58
59
  register :iq
@@ -124,10 +125,15 @@ class Stanza
124
125
  super
125
126
  end
126
127
 
127
- # Overrides the parent method to ensure the reply is of type :result
128
+ # Overrides the parent method to ensure the reply is of type :result and that
129
+ # all children are removed.
130
+ #
131
+ # @param [Hash] opts options to pass to reply!
132
+ # @option opts [Boolean] :remove_children Wether or not to remove child nodes when replying
128
133
  #
129
134
  # @return [self]
130
- def reply!
135
+ def reply!(opts = {})
136
+ opts = {:remove_children => true}.merge opts
131
137
  super
132
138
  self.type = :result
133
139
  self
@@ -11,8 +11,11 @@ class Iq
11
11
  #
12
12
  # @handler :command
13
13
  class Command < Iq
14
+ # @private
14
15
  VALID_ACTIONS = [:cancel, :execute, :complete, :next, :prev].freeze
16
+ # @private
15
17
  VALID_STATUS = [:executing, :completed, :canceled].freeze
18
+ # @private
16
19
  VALID_NOTE_TYPES = [:info, :warn, :error].freeze
17
20
 
18
21
  register :command, :command, 'http://jabber.org/protocol/commands'
@@ -44,8 +47,11 @@ class Iq
44
47
 
45
48
  # Overrides the parent method to ensure the reply has no action
46
49
  #
50
+ # @param [Hash] opts options to pass to reply!
51
+ # @option opts [Boolean] :remove_children Wether or not to remove child nodes when replying
52
+ #
47
53
  # @return [self]
48
- def reply!
54
+ def reply!(opts = {})
49
55
  super
50
56
  self.action = nil
51
57
  self
@@ -215,17 +221,26 @@ class Iq
215
221
 
216
222
  # Get the command's allowed actions
217
223
  #
218
- # @return [[Symbol]]
224
+ # @return [Array<Symbol>]
219
225
  def allowed_actions
220
226
  ([:execute] + actions.children.map { |action| action.name.to_sym }).uniq
221
227
  end
222
228
 
229
+ # Get the primary allowed action
230
+ #
231
+ # @return [Symbol]
223
232
  def primary_allowed_action
224
233
  (actions[:execute] || :execute).to_sym
225
234
  end
226
235
 
236
+ # Set the primary allowed action
237
+ #
238
+ # This must be one of :prev, :next, :complete or :execute
239
+ #
240
+ # @param [#to_sym] a the primary allowed action
227
241
  def primary_allowed_action=(a)
228
- if a && ![:prev, :next, :complete, :execute].include?(a.to_sym)
242
+ a = a.to_sym
243
+ if a && ![:prev, :next, :complete, :execute].include?(a)
229
244
  raise ArgumentError, "Invalid Action (#{a}), use: #{[:prev, :next, :complete, :execute]*' '}"
230
245
  end
231
246
  actions[:execute] = a
@@ -1,8 +1,6 @@
1
1
  module Blather
2
2
  class Stanza
3
3
  class Iq
4
- NS_IBB = 'http://jabber.org/protocol/ibb'
5
-
6
4
  # # In-Band Bytestreams Stanza
7
5
  #
8
6
  # [XEP-0047: In-Band Bytestreams](http://xmpp.org/extensions/xep-0047.html)
@@ -11,6 +9,8 @@ class Iq
11
9
  # @handler :ibb_data
12
10
  # @handler :ibb_close
13
11
  class Ibb < Iq
12
+ # @private
13
+ NS_IBB = 'http://jabber.org/protocol/ibb'
14
14
 
15
15
  # Overrides the parent method to remove open, close and data nodes
16
16
  #
@@ -23,6 +23,7 @@ class Iq
23
23
  reply
24
24
  end
25
25
 
26
+ # An Open stanza to
26
27
  class Open < Ibb
27
28
  register :ibb_open, :open, NS_IBB
28
29
 
@@ -42,6 +43,7 @@ class Iq
42
43
 
43
44
  end
44
45
 
46
+ # A Data stanza
45
47
  class Data < Ibb
46
48
  register :ibb_data, :data, NS_IBB
47
49
 
@@ -60,6 +62,7 @@ class Iq
60
62
  end
61
63
  end
62
64
 
65
+ # A Close stanza
63
66
  class Close < Ibb
64
67
  register :ibb_close, :close, NS_IBB
65
68
 
@@ -80,4 +83,4 @@ class Iq
80
83
  end
81
84
  end
82
85
  end
83
- end
86
+ end
@@ -1,14 +1,15 @@
1
1
  module Blather
2
2
  class Stanza
3
3
  class Iq
4
- NS_S5B = 'http://jabber.org/protocol/bytestreams'
5
-
6
4
  # # SOCKS5 Bytestreams Stanza
7
5
  #
8
6
  # [XEP-0065: SOCKS5 Bytestreams](http://xmpp.org/extensions/xep-0065.html)
9
7
  #
10
8
  # @handler :s5b_open
11
9
  class S5b < Query
10
+ # @private
11
+ NS_S5B = 'http://jabber.org/protocol/bytestreams'
12
+
12
13
  register :s5b_open, :query, NS_S5B
13
14
 
14
15
  # Overrides the parent method to remove query node
@@ -64,6 +65,7 @@ class Iq
64
65
  end
65
66
  end
66
67
 
68
+ # StreamHost Stanza
67
69
  class StreamHost < XMPPNode
68
70
  register 'streamhost', NS_S5B
69
71
 
@@ -152,6 +154,7 @@ class Iq
152
154
  end
153
155
  end
154
156
 
157
+ # Stream host used stanza
155
158
  class StreamHostUsed < XMPPNode
156
159
  register 'streamhost-used', NS_S5B
157
160
 
@@ -202,4 +205,4 @@ class Iq
202
205
  end
203
206
  end
204
207
  end
205
- end
208
+ end
@@ -33,6 +33,7 @@ class Iq
33
33
  #
34
34
  # @handler :file_transfer
35
35
  class Si < Iq
36
+ # @private
36
37
  NS_SI = 'http://jabber.org/protocol/si'
37
38
  register :file_transfer, :si, NS_SI
38
39
 
@@ -80,6 +81,7 @@ class Iq
80
81
  reply
81
82
  end
82
83
 
84
+ # Si stanza fragment
83
85
  class Si < XMPPNode
84
86
  # Create a new Si::Si object
85
87
  #
@@ -166,6 +168,7 @@ class Iq
166
168
  Feature.find_or_create self
167
169
  end
168
170
 
171
+ # Feature stanza fragment
169
172
  class Feature < XMPPNode
170
173
  register :feature, 'http://jabber.org/protocol/feature-neg'
171
174
 
@@ -206,6 +209,7 @@ class Iq
206
209
  end
207
210
  end
208
211
 
212
+ # File stanza fragment
209
213
  class File < XMPPNode
210
214
  register :file, 'http://jabber.org/protocol/si/profile/file-transfer'
211
215
 
@@ -330,6 +334,7 @@ class Iq
330
334
  end
331
335
  end
332
336
 
337
+ # Range stanza fragment
333
338
  class Range < XMPPNode
334
339
  register :range, 'http://jabber.org/protocol/si/profile/file-transfer'
335
340
 
@@ -407,4 +412,4 @@ class Iq
407
412
  end
408
413
  end
409
414
  end
410
- end
415
+ end
@@ -69,8 +69,10 @@ class Iq
69
69
  Vcard.find_or_create self
70
70
  end
71
71
 
72
+ # Vcard stanza fragment
72
73
  class Vcard < XMPPNode
73
74
 
75
+ # @private
74
76
  VCARD_NS = 'vcard-temp'
75
77
 
76
78
  # Create a new Vcard::Vcard object
@@ -144,4 +146,4 @@ class Iq
144
146
  end
145
147
  end
146
148
  end
147
- end
149
+ end
@@ -157,12 +157,17 @@ class Stanza
157
157
  #
158
158
  # @handler :message
159
159
  class Message < Stanza
160
+ # @private
160
161
  VALID_TYPES = [:chat, :error, :groupchat, :headline, :normal].freeze
161
162
 
163
+ # @private
162
164
  VALID_CHAT_STATES = [:active, :composing, :gone, :inactive, :paused].freeze
165
+ # @private
163
166
  CHAT_STATE_NS = 'http://jabber.org/protocol/chatstates'.freeze
164
167
 
168
+ # @private
165
169
  HTML_NS = 'http://jabber.org/protocol/xhtml-im'.freeze
170
+ # @private
166
171
  HTML_BODY_NS = 'http://www.w3.org/1999/xhtml'.freeze
167
172
 
168
173
  register :message
@@ -70,6 +70,7 @@ class Stanza
70
70
  #
71
71
  # @handler :presence
72
72
  class Presence < Stanza
73
+ # @private
73
74
  VALID_TYPES = [ :unavailable,
74
75
  :subscribe,
75
76
  :subscribed,
@@ -13,6 +13,7 @@ class Presence
13
13
  class C < Presence
14
14
  register :c, :c, 'http://jabber.org/protocol/caps'
15
15
 
16
+ # @private
16
17
  VALID_HASH_TYPES = %w[md2 md5 sha-1 sha-224 sha-256 sha-384 sha-512].freeze
17
18
 
18
19
  def self.new(node = nil, ver = nil, hash = 'sha-1')
@@ -75,6 +75,7 @@ class Presence
75
75
  #
76
76
  # @handler :status
77
77
  class Status < Presence
78
+ # @private
78
79
  VALID_STATES = [:away, :chat, :dnd, :xa].freeze
79
80
 
80
81
  include Comparable
@@ -11,6 +11,7 @@ class PubSub
11
11
  #
12
12
  # @handler :pubsub_event
13
13
  class Event < Message
14
+ # @private
14
15
  SHIM_NS = 'http://jabber.org/protocol/shim'.freeze
15
16
 
16
17
  register :pubsub_event, :event, 'http://jabber.org/protocol/pubsub#event'
@@ -130,10 +131,7 @@ class PubSub
130
131
  def subscription_node
131
132
  event_node.find_first('//ns:subscription', :ns => self.class.registered_ns)
132
133
  end
133
-
134
- def subscription
135
- subscription_node
136
- end
134
+ alias_method :subscription, :subscription_node
137
135
  end # Event
138
136
 
139
137
  end # PubSub
@@ -8,6 +8,7 @@ class PubSub
8
8
  #
9
9
  # @handler :pubsub_subscription
10
10
  class Subscription < PubSub
11
+ # @private
11
12
  VALID_TYPES = [:none, :pending, :subscribed, :unconfigured]
12
13
 
13
14
  register :pubsub_subscription, :subscription, self.registered_ns
@@ -10,6 +10,7 @@ class Stanza
10
10
  class X < XMPPNode
11
11
  register :x, 'jabber:x:data'
12
12
 
13
+ # @private
13
14
  VALID_TYPES = [:cancel, :form, :result, :submit].freeze
14
15
 
15
16
  # Create a new X node
@@ -33,6 +34,10 @@ class Stanza
33
34
  new_node
34
35
  end
35
36
 
37
+ # Find the X node on the parent or create a new one
38
+ #
39
+ # @param [Blather::Stanza] parent the parent node to search under
40
+ # @return [Blather::Stanza::X]
36
41
  def self.find_or_create(parent)
37
42
  if found_x = parent.find_first('//ns:x', :ns => self.registered_ns)
38
43
  x = self.new found_x
@@ -149,8 +154,10 @@ class Stanza
149
154
  end
150
155
  end
151
156
 
157
+ # Field stanza fragment
152
158
  class Field < XMPPNode
153
159
  register :field, 'jabber:x:data'
160
+ # @private
154
161
  VALID_TYPES = [:boolean, :fixed, :hidden, :"jid-multi", :"jid-single", :"list-multi", :"list-single", :"text-multi", :"text-private", :"text-single"].freeze
155
162
 
156
163
  # Create a new X Field
@@ -335,6 +342,7 @@ class Stanza
335
342
  super o, *(fields + [:type, :var, :label, :desc, :required?, :value])
336
343
  end
337
344
 
345
+ # Option stanza fragment
338
346
  class Option < XMPPNode
339
347
  register :option, 'jabber:x:data'
340
348
  # Create a new X Field Option
@@ -48,8 +48,10 @@ module Blather
48
48
  # client = Blather::Stream.start MyClient.new, "jid@domain/res", "pass"
49
49
  # client.write "[pure xml over the wire]"
50
50
  class Stream < EventMachine::Connection
51
+ # Connection not found
51
52
  class NoConnection < RuntimeError; end
52
53
 
54
+ # @private
53
55
  STREAM_NS = 'http://etherx.jabber.org/streams'
54
56
  attr_accessor :password
55
57
  attr_reader :jid
@@ -1,6 +1,7 @@
1
1
  module Blather
2
2
  class Stream
3
3
 
4
+ # @private
4
5
  class Client < Stream
5
6
  LANG = 'en'
6
7
  VERSION = '1.0'
@@ -1,6 +1,7 @@
1
1
  module Blather
2
2
  class Stream
3
3
 
4
+ # @private
4
5
  class Component < Stream
5
6
  NAMESPACE = 'jabber:component:accept'
6
7
 
@@ -1,7 +1,8 @@
1
- module Blather # :nodoc:
2
- class Stream # :nodoc:
1
+ module Blather
2
+ class Stream
3
3
 
4
- class Features # :nodoc:
4
+ # @private
5
+ class Features
5
6
  @@features = {}
6
7
  def self.register(ns)
7
8
  @@features[ns] = self
@@ -1,7 +1,8 @@
1
- module Blather # :nodoc:
2
- class Stream # :nodoc:
1
+ module Blather
2
+ class Stream
3
3
 
4
- class Resource < Features # :nodoc:
4
+ # @private
5
+ class Resource < Features
5
6
  BIND_NS = 'urn:ietf:params:xml:ns:xmpp-bind'.freeze
6
7
  register BIND_NS
7
8
 
@@ -1,7 +1,8 @@
1
- module Blather # :nodoc:
2
- class Stream # :nodoc:
1
+ module Blather
2
+ class Stream
3
3
 
4
- class SASL < Features # :nodoc:
4
+ # @private
5
+ class SASL < Features
5
6
  class UnknownMechanism < BlatherError
6
7
  register :sasl_unknown_mechanism
7
8
  end
@@ -68,7 +69,7 @@ class Stream # :nodoc:
68
69
  when nil then fail!(SASLError.import(@node))
69
70
  else next!
70
71
  end
71
-
72
+
72
73
  if method.is_a?(Module)
73
74
  extend method
74
75
  authenticate
@@ -170,13 +171,15 @@ class Stream # :nodoc:
170
171
  def h(s); Digest::MD5.hexdigest(s); end
171
172
  end #DigestMD5
172
173
 
173
- module Plain # :nodoc:
174
+ # @private
175
+ module Plain
174
176
  def authenticate
175
177
  @stream.send auth_node('PLAIN', b64("#{@jid.stripped}\x00#{@jid.node}\x00#{@pass}"))
176
178
  end
177
179
  end #Plain
178
180
 
179
- module Anonymous # :nodoc:
181
+ # @private
182
+ module Anonymous
180
183
  def authenticate
181
184
  @stream.send auth_node('ANONYMOUS')
182
185
  end