sprsquish-blather 0.4.2 → 0.4.3

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.
data/README.rdoc CHANGED
@@ -20,6 +20,8 @@ RubyForge:: http://rubyforge.org/projects/squishtech
20
20
 
21
21
  RDocs:: http://squishtech.rubyforge.org/blather
22
22
 
23
+ Google Group:: http://groups.google.com/group/xmpp-blather
24
+
23
25
  = Usage
24
26
 
25
27
  == Installation
@@ -78,7 +78,7 @@ module Blather #:nodoc:
78
78
  def run
79
79
  raise 'not setup!' unless setup?
80
80
  klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
81
- @stream = klass.start self, *@setup
81
+ klass.start self, *@setup
82
82
  end
83
83
 
84
84
  ##
@@ -111,7 +111,7 @@ module Blather #:nodoc:
111
111
  ##
112
112
  # Write data to the stream
113
113
  def write(stanza)
114
- @stream.send(stanza) if @stream
114
+ self.stream.send(stanza)
115
115
  end
116
116
 
117
117
  ##
@@ -131,10 +131,12 @@ module Blather #:nodoc:
131
131
  ##
132
132
  # Close the connection
133
133
  def close
134
- @stream.close_connection_after_writing
134
+ self.stream.close_connection_after_writing
135
135
  end
136
136
 
137
- def post_init # :nodoc:
137
+ def post_init(stream, jid = nil) # :nodoc:
138
+ @stream = stream
139
+ @jid = JID.new(jid) if jid
138
140
  self.jid.node ? client_post_init : ready!
139
141
  end
140
142
 
@@ -150,10 +152,6 @@ module Blather #:nodoc:
150
152
  end
151
153
  end
152
154
 
153
- def jid=(new_jid) # :nodoc :
154
- @jid = JID.new new_jid
155
- end
156
-
157
155
  def setup? # :nodoc:
158
156
  @setup.is_a? Array
159
157
  end
@@ -167,6 +165,11 @@ module Blather #:nodoc:
167
165
  end
168
166
 
169
167
  protected
168
+ def stream
169
+ raise 'Stream not ready!' unless @stream
170
+ @stream
171
+ end
172
+
170
173
  def check_handler(type, guards)
171
174
  Blather.logger.warn "Handler for type \"#{type}\" will never be called as it's not a registered type" unless current_handlers.include?(type)
172
175
  check_guards guards
@@ -233,10 +236,11 @@ module Blather #:nodoc:
233
236
  end
234
237
 
235
238
  def call_handler(handler, guards, stanza) # :nodoc:
236
- if guards.first.respond_to?(:to_str) && !(result = stanza.find(*guards)).empty?
237
- handler.call(stanza, result)
238
- elsif !guarded?(guards, stanza)
239
- handler.call(stanza)
239
+ if guards.first.respond_to?(:to_str)
240
+ result = stanza.find(*guards)
241
+ handler.call(stanza, result) unless result.empty?
242
+ else
243
+ handler.call(stanza) unless guarded?(guards, stanza)
240
244
  end
241
245
  end
242
246
 
@@ -256,8 +260,9 @@ module Blather #:nodoc:
256
260
  # return FALSE unless any inequality is found
257
261
  guard.find do |method, test|
258
262
  value = stanza.__send__(method)
263
+ # last_match is the only method found unique to Regexp classes
259
264
  if test.class.respond_to?(:last_match)
260
- !(test =~ value)
265
+ !(test =~ value.to_s)
261
266
  elsif test.is_a?(Array)
262
267
  !test.include? value
263
268
  else
@@ -115,7 +115,7 @@ module Blather
115
115
  stanza.to = who
116
116
  stanza.node = where
117
117
 
118
- client.temporary_handler stanza.id, &callback
118
+ client.register_tmp_handler stanza.id, &callback
119
119
  write stanza
120
120
  end
121
121
 
@@ -98,7 +98,9 @@ class Presence
98
98
  ##
99
99
  # :available if state is nil
100
100
  def state # :nodoc:
101
- (type || content_from(:show) || :available).to_sym
101
+ state = type || content_from(:show)
102
+ state = :available if state.blank?
103
+ state.to_sym
102
104
  end
103
105
 
104
106
  ##
@@ -25,7 +25,7 @@ class PubSub
25
25
  end
26
26
 
27
27
  def retractions
28
- items_node.find('ns:retract', :ns => self.class.registered_ns).map { |i| i[:id] }
28
+ items_node.find('//ns:retract', :ns => self.class.registered_ns).map { |i| i[:id] }
29
29
  end
30
30
 
31
31
  def retractions?
@@ -33,7 +33,7 @@ class PubSub
33
33
  end
34
34
 
35
35
  def items
36
- items_node.find('ns:item', :ns => self.class.registered_ns).map { |i| PubSubItem.new(nil,nil,self.document).inherit i }
36
+ items_node.find('//ns:item', :ns => self.class.registered_ns).map { |i| PubSubItem.new(nil,nil,self.document).inherit i }
37
37
  end
38
38
 
39
39
  def items?
@@ -45,8 +45,8 @@ class PubSub
45
45
  end
46
46
 
47
47
  def event_node
48
- node = find_first('ns:event', :ns => self.class.registered_ns)
49
- node = find_first('event', self.class.registered_ns) unless node
48
+ node = find_first('//ns:event', :ns => self.class.registered_ns)
49
+ node = find_first('//event', self.class.registered_ns) unless node
50
50
  unless node
51
51
  (self << (node = XMPPNode.new('event', self.document)))
52
52
  node.namespace = self.class.registered_ns
@@ -55,7 +55,7 @@ class PubSub
55
55
  end
56
56
 
57
57
  def items_node
58
- node = find_first('event/ns:items', :ns => self.class.registered_ns)
58
+ node = find_first('ns:event/ns:items', :ns => self.class.registered_ns)
59
59
  unless node
60
60
  (self.event_node << (node = XMPPNode.new('items', self.document)))
61
61
  node.namespace = event_node.namespace
@@ -64,7 +64,7 @@ class PubSub
64
64
  end
65
65
 
66
66
  def purge_node
67
- event_node.find_first('ns:purge', :ns => self.class.registered_ns)
67
+ event_node.find_first('//ns:purge', :ns => self.class.registered_ns)
68
68
  end
69
69
 
70
70
  def subscription_ids
@@ -4,7 +4,8 @@ module Blather
4
4
  class NoConnection < RuntimeError; end
5
5
 
6
6
  STREAM_NS = 'http://etherx.jabber.org/streams'
7
- attr_accessor :jid, :password
7
+ attr_accessor :password
8
+ attr_reader :jid
8
9
 
9
10
  ##
10
11
  # Start the stream between client and server
@@ -25,9 +26,7 @@ module Blather
25
26
  connect jid.domain, port, self, client, jid, pass
26
27
  else
27
28
  srv.sort! { |a,b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
28
- conn = nil
29
- srv.each { |r| break unless (conn = connect(r.target.to_s, r.port, self, client, jid, pass)) === false }
30
- conn
29
+ srv.each { |r| break unless connect(r.target.to_s, r.port, self, client, jid, pass) === false }
31
30
  end
32
31
  end
33
32
  end
@@ -139,7 +138,6 @@ module Blather
139
138
  def jid=(new_jid) # :nodoc:
140
139
  Blather.logger.debug "NEW JID: #{new_jid}"
141
140
  @jid = JID.new new_jid
142
- @client.jid = @jid
143
141
  end
144
142
 
145
143
  protected
@@ -160,7 +158,7 @@ module Blather
160
158
  def ready!
161
159
  @state = :started
162
160
  @receiver = @client
163
- @client.post_init
161
+ @client.post_init self, @jid
164
162
  end
165
163
  end
166
164
  end
@@ -51,7 +51,7 @@ class Stream # :nodoc:
51
51
  Blather.logger.debug "RESOURCE NODE #{@node}"
52
52
  # ensure this is a response to our original request
53
53
  if @id == @node['id']
54
- @stream.jid = JID.new @node.find_first('//bind/bind_ns:jid', :bind_ns => BIND_NS).content
54
+ @stream.jid = JID.new @node.find_first('bind_ns:bind/bind_ns:jid', :bind_ns => BIND_NS).content
55
55
  succeed!
56
56
  else
57
57
  fail!("BIND result ID mismatch. Expected: #{@id}. Received: #{@node['id']}")
@@ -6,7 +6,7 @@ class Stream # :nodoc:
6
6
  class Parser # :nodoc:
7
7
  NS_TO_IGNORE = %w[jabber:client jabber:component:accept]
8
8
 
9
- @@debug = !false
9
+ @@debug = false
10
10
  def self.debug; @@debug; end
11
11
  def self.debug=(debug); @@debug = debug; end
12
12
 
@@ -27,9 +27,11 @@ class Stream # :nodoc:
27
27
 
28
28
  def start_document; end
29
29
  def end_document; end
30
+ def start_element(*args); end
31
+ def end_element(*args); end
30
32
  def warning(*args); end
31
33
 
32
- def start_element_ns(elem, attrs, prefix, uri, namespaces)
34
+ def start_element_namespace(elem, attrs, prefix, uri, namespaces)
33
35
  Blather.logger.debug "START ELEM: (#{{:elem => elem, :attrs => attrs, :prefix => prefix, :uri => uri, :ns => namespaces}.inspect})" if @@debug
34
36
 
35
37
  args = [elem]
@@ -37,13 +39,17 @@ class Stream # :nodoc:
37
39
  node = XMPPNode.new *args
38
40
  node.document.root = node unless @current
39
41
 
40
- attrs.each { |k,v| node[k] = v if k }
42
+ attrs.each do |attr|
43
+ node[attr.localname] = attr.value
44
+ end
41
45
 
42
46
  if !@receiver.stopped?
43
47
  @current << node if @current
44
48
  @current = node
45
49
  end
46
50
 
51
+
52
+ ns_keys = namespaces.map { |pre, href| pre }
47
53
  namespaces.delete_if { |pre, href| NS_TO_IGNORE.include? href }
48
54
  @namespace_definitions.push []
49
55
  namespaces.each do |pre, href|
@@ -51,7 +57,7 @@ class Stream # :nodoc:
51
57
  ns = node.add_namespace(pre, href)
52
58
  @namespaces[[pre, href]] ||= ns
53
59
  end
54
- @namespaces[[prefix, uri]] ||= node.add_namespace(prefix, uri) if prefix && !namespaces[prefix]
60
+ @namespaces[[prefix, uri]] ||= node.add_namespace(prefix, uri) if prefix && !ns_keys.include?(prefix)
55
61
  node.namespace = @namespaces[[prefix, uri]]
56
62
 
57
63
  deliver(node) if elem == 'stream'
@@ -66,7 +72,7 @@ class Stream # :nodoc:
66
72
  =end
67
73
  end
68
74
 
69
- def end_element_ns(elem, prefix, uri)
75
+ def end_element_namespace(elem, prefix, uri)
70
76
  Blather.logger.debug "END ELEM: #{{:elem => elem, :prefix => prefix, :uri => uri}.inspect}" if @@debug
71
77
 
72
78
  if elem == 'stream'
@@ -251,7 +251,11 @@ module Blather
251
251
  def inherit(stanza)
252
252
  set_namespace stanza.namespace if stanza.namespace
253
253
  inherit_attrs stanza.attributes
254
- stanza.children.each { |c| self << c.dup }
254
+ stanza.children.each do |c|
255
+ self << (n = c.dup)
256
+ ns = n.namespace_definitions.find { |ns| ns.prefix == c.namespace.prefix }
257
+ n.namespace = ns if ns
258
+ end
255
259
  self
256
260
  end
257
261
 
@@ -4,17 +4,15 @@ require 'blather/client/client'
4
4
  describe Blather::Client do
5
5
  before do
6
6
  @client = Blather::Client.new
7
+ @stream = mock()
8
+ @stream.stubs(:send)
9
+ @jid = Blather::JID.new('n@d/r')
10
+ @client.post_init @stream, @jid
7
11
  end
8
12
 
9
- it 'provides a JID accessor' do
13
+ it 'provides a Blather::JID reader' do
10
14
  @client.must_respond_to :jid
11
- @client.jid.must_be_nil
12
-
13
- jid = 'me@me.com/test'
14
- @client.must_respond_to :jid=
15
- @client.jid = jid
16
- @client.jid.must_be_kind_of Blather::JID
17
- @client.jid.must_equal Blather::JID.new(jid)
15
+ @client.jid.must_equal @jid
18
16
  end
19
17
 
20
18
  it 'provides a reader for the roster' do
@@ -61,8 +59,8 @@ describe Blather::Client do
61
59
  it 'writes to the connection the closes when #close is called' do
62
60
  stream = mock()
63
61
  stream.expects(:close_connection_after_writing)
64
- Blather::Stream::Component.stubs(:start).returns stream
65
- @client.setup('me.com', 'secret').run
62
+ @client.setup('me.com', 'secret')
63
+ @client.post_init stream, Blather::JID.new('me.com')
66
64
  @client.close
67
65
  end
68
66
 
@@ -162,8 +160,8 @@ describe 'Blather::Client#write' do
162
160
  stanza = Blather::Stanza::Iq.new
163
161
  stream = mock()
164
162
  stream.expects(:send).with stanza
165
- Blather::Stream::Client.expects(:start).returns stream
166
- @client.setup('me@me.com', 'me').run
163
+ @client.setup('me@me.com', 'me')
164
+ @client.post_init stream, Blather::JID.new('me.com')
167
165
  @client.write stanza
168
166
  end
169
167
  end
@@ -171,15 +169,20 @@ end
171
169
  describe 'Blather::Client#status=' do
172
170
  before do
173
171
  @client = Blather::Client.new
172
+ @stream = mock()
173
+ @stream.stubs(:send)
174
+ @client.post_init @stream, Blather::JID.new('n@d/r')
174
175
  end
175
176
 
176
- it 'updates the state when not sending to a JID' do
177
+ it 'updates the state when not sending to a Blather::JID' do
178
+ @stream.stubs(:write)
177
179
  @client.status.wont_equal :away
178
180
  @client.status = :away, 'message'
179
181
  @client.status.must_equal :away
180
182
  end
181
183
 
182
- it 'does not update the state when sending to a JID' do
184
+ it 'does not update the state when sending to a Blather::JID' do
185
+ @stream.stubs(:write)
183
186
  @client.status.wont_equal :away
184
187
  @client.status = :away, 'message', 'me@me.com'
185
188
  @client.status.wont_equal :away
@@ -188,7 +191,7 @@ describe 'Blather::Client#status=' do
188
191
  it 'writes the new status to the stream' do
189
192
  Blather::Stanza::Presence::Status.stubs(:next_id).returns 0
190
193
  status = [:away, 'message']
191
- @client.expects(:write).with do |s|
194
+ @stream.expects(:send).with do |s|
192
195
  s.must_be_kind_of Blather::Stanza::Presence::Status
193
196
  s.to_s.must_equal Blather::Stanza::Presence::Status.new(*status).to_s
194
197
  end
@@ -199,6 +202,9 @@ end
199
202
  describe 'Blather::Client default handlers' do
200
203
  before do
201
204
  @client = Blather::Client.new
205
+ @stream = mock()
206
+ @stream.stubs(:send)
207
+ @client.post_init @stream, Blather::JID.new('n@d/r')
202
208
  end
203
209
 
204
210
  it 're-raises errors' do
@@ -227,7 +233,7 @@ describe 'Blather::Client default handlers' do
227
233
  @client.receive_data get
228
234
  end
229
235
 
230
- it 'handles status changes by updating the roster if the status is from a JID in the roster' do
236
+ it 'handles status changes by updating the roster if the status is from a Blather::JID in the roster' do
231
237
  jid = 'friend@jabber.local'
232
238
  status = Blather::Stanza::Presence::Status.new :away
233
239
  status.stubs(:from).returns jid
@@ -275,16 +281,17 @@ end
275
281
  describe 'Blather::Client with a Component stream' do
276
282
  before do
277
283
  class MockComponent < Blather::Stream::Component; def initialize(); end; end
284
+ @stream = MockComponent.new('')
285
+ @stream.stubs(:send_data)
278
286
  @client = Blather::Client.new
279
- Blather::Stream::Component.stubs(:start).returns MockComponent.new('')
280
- @client.setup('me.com', 'secret').run
287
+ @client.setup('me.com', 'secret')
281
288
  end
282
289
 
283
290
  it 'calls the ready handler when sent post_init' do
284
291
  ready = mock()
285
292
  ready.expects(:call)
286
293
  @client.register_handler(:ready) { ready.call }
287
- @client.post_init
294
+ @client.post_init @stream
288
295
  end
289
296
  end
290
297
 
@@ -299,7 +306,7 @@ describe 'Blather::Client with a Client stream' do
299
306
 
300
307
  it 'sends a request for the roster when post_init is called' do
301
308
  @stream.expects(:send).with { |stanza| stanza.must_be_kind_of Blather::Stanza::Iq::Roster }
302
- @client.post_init
309
+ @client.post_init @stream, Blather::JID.new('n@d/r')
303
310
  end
304
311
 
305
312
  it 'calls the ready handler after post_init and roster is received' do
@@ -309,13 +316,16 @@ describe 'Blather::Client with a Client stream' do
309
316
  ready = mock()
310
317
  ready.expects(:call)
311
318
  @client.register_handler(:ready) { ready.call }
312
- @client.post_init
319
+ @client.post_init @stream, Blather::JID.new('n@d/r')
313
320
  end
314
321
  end
315
322
 
316
323
  describe 'Blather::Client filters' do
317
324
  before do
318
325
  @client = Blather::Client.new
326
+ @stream = mock()
327
+ @stream.stubs(:send)
328
+ @client.post_init @stream, Blather::JID.new('n@d/r')
319
329
  end
320
330
 
321
331
  it 'raises an error when an invalid filter type is registered' do
@@ -383,7 +393,10 @@ end
383
393
 
384
394
  describe 'Blather::Client guards' do
385
395
  before do
396
+ stream = mock()
397
+ stream.stubs(:send)
386
398
  @client = Blather::Client.new
399
+ @client.post_init stream, Blather::JID.new('n@d/r')
387
400
  @stanza = Blather::Stanza::Iq.new
388
401
  @response = mock()
389
402
  end
@@ -430,6 +443,9 @@ describe 'Blather::Client guards' do
430
443
 
431
444
  @stanza.expects(:body).returns 'keyword not found'
432
445
  @client.receive_data @stanza
446
+
447
+ @stanza.expects(:body).returns nil
448
+ @client.receive_data @stanza
433
449
  end
434
450
 
435
451
  it 'can be a hash with an array' do
@@ -500,6 +516,17 @@ describe 'Blather::Client guards' do
500
516
  @client.receive_data @stanza
501
517
  end
502
518
 
519
+ it 'can be an xpath with namespaces and will send the result to the handler' do
520
+ @stanza = Blather::Stanza.import(parse_stanza('<message><foo xmlns="http://bar.com"></message>').root)
521
+ @response.expects(:call).with do |stanza, xpath|
522
+ xpath.must_be_instance_of Nokogiri::XML::NodeSet
523
+ xpath.wont_be_empty
524
+ stanza.must_equal @stanza
525
+ end
526
+ @client.register_handler(:message, "/message/bar:foo", :bar => 'http://bar.com') { |stanza, xpath| @response.call stanza, xpath }
527
+ @client.receive_data @stanza
528
+ end
529
+
503
530
  it 'raises an error when a bad guard is tried' do
504
531
  lambda { @client.register_handler(:iq, 0) {} }.must_raise RuntimeError
505
532
  end
@@ -274,8 +274,7 @@ describe 'Blather::DSL::PubSub callbacks' do
274
274
  before do
275
275
  @host = 'host.name'
276
276
  @pubsub = Blather::DSL::PubSub.new @host
277
- @client = Blather::Client.new
278
- @client.jid = Blather::JID.new('n@d/r')
277
+ @client = Blather::Client.setup Blather::JID.new('n@d/r'), 'pass'
279
278
  Blather::DSL.stubs(:client).returns @client
280
279
  end
281
280
 
@@ -102,7 +102,7 @@ describe Blather::DSL do
102
102
  it 'provides a disco helper for items' do
103
103
  what, who, where = :items, 'me@me.com', 'my/node'
104
104
  Blather::Stanza::Disco::DiscoItems.stubs(:next_id).returns 0
105
- @client.expects(:temporary_handler).with '0'
105
+ @client.expects(:register_tmp_handler).with '0'
106
106
  expected_stanza = Blather::Stanza::Disco::DiscoItems.new
107
107
  expected_stanza.to = who
108
108
  expected_stanza.node = where
@@ -113,7 +113,7 @@ describe Blather::DSL do
113
113
  it 'provides a disco helper for info' do
114
114
  what, who, where = :info, 'me@me.com', 'my/node'
115
115
  Blather::Stanza::Disco::DiscoInfo.stubs(:next_id).returns 0
116
- @client.expects(:temporary_handler).with '0'
116
+ @client.expects(:register_tmp_handler).with '0'
117
117
  expected_stanza = Blather::Stanza::Disco::DiscoInfo.new
118
118
  expected_stanza.to = who
119
119
  expected_stanza.node = where
@@ -49,6 +49,13 @@ describe Blather::Stanza::Presence::Status do
49
49
  Blather::Stanza::Presence::Status.new.state.must_equal :available
50
50
  end
51
51
 
52
+ it 'returns :available if <show/> is blank' do
53
+ status = Blather::XMPPNode.import(parse_stanza(<<-NODE).root)
54
+ <presence><show/><presence/>
55
+ NODE
56
+ status.state.must_equal :available
57
+ end
58
+
52
59
  it 'returns :unavailable if type is :unavailable' do
53
60
  status = Blather::Stanza::Presence::Status.new
54
61
  status.type = :unavailable
@@ -721,7 +721,7 @@ describe Blather::Stream::Client do
721
721
 
722
722
  when :complete
723
723
  EM.stop
724
- @client.jid.must_equal Blather::JID.new('n@d/server_resource')
724
+ @stream.jid.must_equal Blather::JID.new('n@d/server_resource')
725
725
 
726
726
  else
727
727
  EM.stop
@@ -754,7 +754,7 @@ describe Blather::Stream::Client do
754
754
 
755
755
  when :complete
756
756
  EM.stop
757
- @client.jid.must_equal Blather::JID.new('n@d/r')
757
+ @stream.jid.must_equal Blather::JID.new('n@d/r')
758
758
 
759
759
  else
760
760
  EM.stop
@@ -213,7 +213,7 @@ describe Blather::XMPPNode do
213
213
  n2.element_name.must_equal n.element_name
214
214
  end
215
215
 
216
- it 'provides an inhert mechanism' do
216
+ it 'provides an inherit mechanism' do
217
217
  n = Blather::XMPPNode.new 'foo'
218
218
  n2 = Blather::XMPPNode.new 'foo'
219
219
  n2.content = 'bar'
@@ -222,6 +222,13 @@ describe Blather::XMPPNode do
222
222
  n.inherit(n2)
223
223
  n['foo'].must_equal 'bar'
224
224
  n.content.must_equal 'bar'
225
+ n2.to_s.must_equal n.to_s
226
+ end
227
+
228
+ it 'holds on to namespaces when inheriting content' do
229
+ n = parse_stanza('<message><bar:foo xmlns:bar="http://bar.com"></message>').root
230
+ n2 = Blather::XMPPNode.new('message').inherit n
231
+ n2.to_s.must_equal n.to_s
225
232
  end
226
233
 
227
234
  it 'provides a mechanism to inherit attrs' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sprsquish-blather
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Smick
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-13 00:00:00 -07:00
12
+ date: 2009-07-18 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.3.0
33
+ version: 1.3.2
34
34
  version:
35
35
  description: An XMPP DSL for Ruby written on top of EventMachine and Nokogiri
36
36
  email: sprsquish@gmail.com