blather 0.4.14 → 0.4.15

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 (73) hide show
  1. data/lib/blather.rb +8 -0
  2. data/lib/blather/client/client.rb +9 -1
  3. data/lib/blather/client/dsl/pubsub.rb +2 -2
  4. data/lib/blather/core_ext/active_support.rb +1 -0
  5. data/lib/blather/core_ext/eventmachine.rb +122 -0
  6. data/lib/blather/errors/stanza_error.rb +1 -0
  7. data/lib/blather/file_transfer.rb +100 -0
  8. data/lib/blather/file_transfer/ibb.rb +68 -0
  9. data/lib/blather/file_transfer/s5b.rb +104 -0
  10. data/lib/blather/roster_item.rb +2 -2
  11. data/lib/blather/stanza/disco/disco_info.rb +17 -2
  12. data/lib/blather/stanza/iq/ibb.rb +83 -0
  13. data/lib/blather/stanza/iq/s5b.rb +205 -0
  14. data/lib/blather/stanza/iq/si.rb +410 -0
  15. data/lib/blather/stanza/iq/vcard.rb +147 -0
  16. data/lib/blather/stanza/message.rb +10 -2
  17. data/lib/blather/stanza/presence/status.rb +11 -3
  18. data/lib/blather/stanza/pubsub.rb +3 -1
  19. data/lib/blather/stanza/pubsub/event.rb +18 -0
  20. data/lib/blather/stanza/pubsub/subscriptions.rb +4 -2
  21. data/lib/blather/stanza/pubsub/unsubscribe.rb +17 -1
  22. data/lib/blather/stanza/x.rb +12 -2
  23. data/lib/blather/stream/parser.rb +1 -0
  24. data/lib/test.rb +55 -0
  25. data/spec/blather/client/client_spec.rb +18 -4
  26. data/spec/blather/client/dsl/pubsub_spec.rb +12 -2
  27. data/spec/blather/client/dsl_spec.rb +1 -1
  28. data/spec/blather/core_ext/nokogiri_spec.rb +1 -1
  29. data/spec/blather/errors/sasl_error_spec.rb +1 -1
  30. data/spec/blather/errors/stanza_error_spec.rb +1 -1
  31. data/spec/blather/errors/stream_error_spec.rb +1 -1
  32. data/spec/blather/errors_spec.rb +1 -1
  33. data/spec/blather/file_transfer_spec.rb +100 -0
  34. data/spec/blather/jid_spec.rb +1 -1
  35. data/spec/blather/roster_item_spec.rb +32 -2
  36. data/spec/blather/roster_spec.rb +1 -1
  37. data/spec/blather/stanza/discos/disco_info_spec.rb +12 -3
  38. data/spec/blather/stanza/discos/disco_items_spec.rb +1 -1
  39. data/spec/blather/stanza/iq/command_spec.rb +1 -1
  40. data/spec/blather/stanza/iq/ibb_spec.rb +136 -0
  41. data/spec/blather/stanza/iq/query_spec.rb +1 -1
  42. data/spec/blather/stanza/iq/roster_spec.rb +1 -1
  43. data/spec/blather/stanza/iq/s5b_spec.rb +60 -0
  44. data/spec/blather/stanza/iq/si_spec.rb +101 -0
  45. data/spec/blather/stanza/iq/vcard_spec.rb +96 -0
  46. data/spec/blather/stanza/iq_spec.rb +1 -1
  47. data/spec/blather/stanza/message_spec.rb +48 -2
  48. data/spec/blather/stanza/presence/status_spec.rb +1 -1
  49. data/spec/blather/stanza/presence/subscription_spec.rb +1 -1
  50. data/spec/blather/stanza/presence_spec.rb +1 -1
  51. data/spec/blather/stanza/pubsub/affiliations_spec.rb +2 -2
  52. data/spec/blather/stanza/pubsub/create_spec.rb +2 -2
  53. data/spec/blather/stanza/pubsub/event_spec.rb +16 -2
  54. data/spec/blather/stanza/pubsub/items_spec.rb +2 -2
  55. data/spec/blather/stanza/pubsub/publish_spec.rb +2 -2
  56. data/spec/blather/stanza/pubsub/retract_spec.rb +2 -2
  57. data/spec/blather/stanza/pubsub/subscribe_spec.rb +2 -2
  58. data/spec/blather/stanza/pubsub/subscription_spec.rb +2 -2
  59. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +3 -3
  60. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +15 -2
  61. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +2 -2
  62. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +2 -2
  63. data/spec/blather/stanza/pubsub_owner_spec.rb +2 -2
  64. data/spec/blather/stanza/pubsub_spec.rb +14 -2
  65. data/spec/blather/stanza/x_spec.rb +1 -1
  66. data/spec/blather/stanza_spec.rb +1 -1
  67. data/spec/blather/stream/client_spec.rb +1 -1
  68. data/spec/blather/stream/component_spec.rb +1 -1
  69. data/spec/blather/stream/parser_spec.rb +11 -1
  70. data/spec/blather/xmpp_node_spec.rb +1 -1
  71. data/spec/fixtures/pubsub.rb +2 -2
  72. data/spec/spec_helper.rb +27 -0
  73. metadata +85 -23
@@ -1,5 +1,5 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
- require File.join(File.dirname(__FILE__), *%w[.. .. .. fixtures pubsub])
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
+ require File.expand_path "../../../../fixtures/pubsub", __FILE__
3
3
  require 'blather/client/dsl'
4
4
 
5
5
  describe Blather::DSL::PubSub do
@@ -238,6 +238,16 @@ describe Blather::DSL::PubSub do
238
238
  @pubsub.unsubscribe '/path/to/node', Blather::JID.new('jid@d/r')
239
239
  end
240
240
 
241
+ it 'can unsubscribe with a particular subscription id' do
242
+ @client.expects(:write_with_handler).with do |n|
243
+ n.must_be_instance_of Blather::Stanza::PubSub::Unsubscribe
244
+ n.find("/iq[@type='set']/ns:pubsub/ns:unsubscribe[@node='/path/to/node' and @jid='jid@d/r' and @subid='subid']", :ns => Blather::Stanza::PubSub.registered_ns).wont_be_empty
245
+ n.subid.must_equal 'subid'
246
+ n.type.must_equal :set
247
+ end
248
+ @pubsub.unsubscribe '/path/to/node', 'jid@d/r', 'subid'
249
+ end
250
+
241
251
  it 'can purge a node' do
242
252
  @client.expects(:write_with_handler).with do |n|
243
253
  n.must_be_instance_of Blather::Stanza::PubSubOwner::Purge
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
1
+ require File.expand_path "../../../spec_helper", __FILE__
2
2
  require 'blather/client/dsl'
3
3
 
4
4
  describe Blather::DSL do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
1
+ require File.expand_path "../../../spec_helper", __FILE__
2
2
 
3
3
  describe 'Nokogiri::XML::Node' do
4
4
  before { @doc = Nokogiri::XML::Document.new }
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
1
+ require File.expand_path "../../../spec_helper", __FILE__
2
2
 
3
3
  def sasl_error_node(err_name = 'aborted')
4
4
  node = Blather::XMPPNode.new 'failure'
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
1
+ require File.expand_path "../../../spec_helper", __FILE__
2
2
 
3
3
  def stanza_error_node(type = 'cancel', error = 'internal-server-error', msg = nil)
4
4
  node = Blather::Stanza::Message.new 'error@jabber.local', 'test message', :error
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
1
+ require File.expand_path "../../../spec_helper", __FILE__
2
2
 
3
3
  def stream_error_node(error = 'internal-server-error', msg = nil)
4
4
  node = Blather::XMPPNode.new('error')
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
1
+ require File.expand_path "../../spec_helper", __FILE__
2
2
 
3
3
  describe Blather::BlatherError do
4
4
  it 'is handled by :error' do
@@ -0,0 +1,100 @@
1
+ require File.expand_path "../../spec_helper", __FILE__
2
+ require 'blather/client/dsl'
3
+
4
+ module MockFileReceiver
5
+ def post_init
6
+ end
7
+ def receive_data(data)
8
+ end
9
+ def unbind
10
+ end
11
+ end
12
+
13
+ def si_xml
14
+ <<-XML
15
+ <iq type='set' id='offer1' to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard'>
16
+ <si xmlns='http://jabber.org/protocol/si'
17
+ id='a0'
18
+ mime-type='text/plain'
19
+ profile='http://jabber.org/protocol/si/profile/file-transfer'>
20
+ <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'
21
+ name='test.txt'
22
+ size='1022'>
23
+ <range/>
24
+ </file>
25
+ <feature xmlns='http://jabber.org/protocol/feature-neg'>
26
+ <x xmlns='jabber:x:data' type='form'>
27
+ <field var='stream-method' type='list-single'>
28
+ <option><value>http://jabber.org/protocol/bytestreams</value></option>
29
+ <option><value>http://jabber.org/protocol/ibb</value></option>
30
+ </field>
31
+ </x>
32
+ </feature>
33
+ </si>
34
+ </iq>
35
+ XML
36
+ end
37
+
38
+ describe Blather::FileTransfer do
39
+ before do
40
+ @host = 'host.name'
41
+ @client = Blather::Client.setup Blather::JID.new('n@d/r'), 'pass'
42
+ end
43
+
44
+ it 'can select ibb' do
45
+ iq = Blather::XMPPNode.import(parse_stanza(si_xml).root)
46
+
47
+ @client.stubs(:write).with do |answer|
48
+ answer.si.feature.x.field('stream-method').value.must_equal Blather::Stanza::Iq::Ibb::NS_IBB
49
+ true
50
+ end
51
+
52
+ transfer = Blather::FileTransfer.new(@client, iq)
53
+ transfer.allow_s5b = false
54
+ transfer.allow_ibb = true
55
+ transfer.accept(MockFileReceiver)
56
+ end
57
+
58
+ it 'can select s5b' do
59
+ iq = Blather::XMPPNode.import(parse_stanza(si_xml).root)
60
+
61
+ @client.stubs(:write).with do |answer|
62
+ answer.si.feature.x.field('stream-method').value.must_equal Blather::Stanza::Iq::S5b::NS_S5B
63
+ true
64
+ end
65
+
66
+ transfer = Blather::FileTransfer.new(@client, iq)
67
+ transfer.allow_s5b = true
68
+ transfer.allow_ibb = false
69
+ transfer.accept(MockFileReceiver)
70
+ end
71
+
72
+ it 'can response no-valid-streams' do
73
+ iq = Blather::XMPPNode.import(parse_stanza(si_xml).root)
74
+
75
+ @client.stubs(:write).with do |answer|
76
+ answer.find_first('error')['type'].must_equal "cancel"
77
+ answer.find_first('.//ns:no-valid-streams', :ns => 'http://jabber.org/protocol/si').wont_be_nil
78
+ true
79
+ end
80
+
81
+ transfer = Blather::FileTransfer.new(@client, iq)
82
+ transfer.allow_s5b = false
83
+ transfer.allow_ibb = false
84
+ transfer.accept(MockFileReceiver)
85
+ end
86
+
87
+ it 'can decline transfer' do
88
+ iq = Blather::XMPPNode.import(parse_stanza(si_xml).root)
89
+
90
+ @client.stubs(:write).with do |answer|
91
+ answer.find_first('error')['type'].must_equal "cancel"
92
+ answer.find_first('.//ns:forbidden', :ns => 'urn:ietf:params:xml:ns:xmpp-stanzas').wont_be_nil
93
+ answer.find_first('.//ns:text', :ns => 'urn:ietf:params:xml:ns:xmpp-stanzas').content.must_equal "Offer declined"
94
+ true
95
+ end
96
+
97
+ transfer = Blather::FileTransfer.new(@client, iq)
98
+ transfer.decline
99
+ end
100
+ end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
1
+ require File.expand_path "../../spec_helper", __FILE__
2
2
 
3
3
  describe Blather::JID do
4
4
  it 'does nothing if creaded from Blather::JID' do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
1
+ require File.expand_path "../../spec_helper", __FILE__
2
2
 
3
3
  describe Blather::RosterItem do
4
4
  it 'can be initialized with Blather::JID' do
@@ -65,7 +65,19 @@ describe Blather::RosterItem do
65
65
 
66
66
  it 'returns status based on priority' do
67
67
  setup_item_with_presences
68
- @i.status.must_equal @p2
68
+ @i.status.must_equal @p3
69
+ end
70
+
71
+ it 'returns status based on priority and state' do
72
+ setup_item_with_presences
73
+
74
+ @p4 = Blather::Stanza::Presence::Status.new
75
+ @p4.type = :unavailable
76
+ @p4.from = 'n@d/d'
77
+ @p4.priority = 15
78
+ @i.status = @p4
79
+
80
+ @i.status.must_equal @p3
69
81
  end
70
82
 
71
83
  it 'returns status based on resource' do
@@ -85,8 +97,26 @@ describe Blather::RosterItem do
85
97
  @p2.from = 'n@d/b'
86
98
  @p2.priority = -1
87
99
 
100
+ @p3 = Blather::Stanza::Presence::Status.new(:dnd)
101
+ @p3.from = 'n@d/c'
102
+ @p3.priority = 10
103
+
88
104
  @i.status = @p
89
105
  @i.status = @p2
106
+ @i.status = @p3
107
+ end
108
+
109
+ it 'removes old unavailable presences' do
110
+ setup_item_with_presences
111
+
112
+ 50.times do |i|
113
+ p = Blather::Stanza::Presence::Status.new
114
+ p.type = :unavailable
115
+ p.from = "n@d/#{i}"
116
+ @i.status = p
117
+ end
118
+
119
+ @i.statuses.size.must_equal 4
90
120
  end
91
121
 
92
122
  it 'initializes groups to [nil] if the item is not part of a group' do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
1
+ require File.expand_path "../../spec_helper", __FILE__
2
2
 
3
3
  describe Blather::Roster do
4
4
  before do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
2
 
3
3
  def disco_info_xml
4
4
  <<-XML
@@ -10,7 +10,8 @@ def disco_info_xml
10
10
  <identity
11
11
  category='client'
12
12
  type='pc'
13
- name='Gabber'/>
13
+ name='Gabber'
14
+ xml:lang='en'/>
14
15
  <feature var='jabber:iq:time'/>
15
16
  <feature var='jabber:iq:version'/>
16
17
  </query>
@@ -182,11 +183,12 @@ end
182
183
 
183
184
  describe Blather::Stanza::Iq::DiscoInfo::Identity do
184
185
  it 'will auto-inherit nodes' do
185
- n = parse_stanza "<identity name='Personal Events' type='pep' category='pubsub' node='publish' />"
186
+ n = parse_stanza "<identity name='Personal Events' type='pep' category='pubsub' node='publish' xml:lang='en' />"
186
187
  i = Blather::Stanza::Iq::DiscoInfo::Identity.new n.root
187
188
  i.name.must_equal 'Personal Events'
188
189
  i.type.must_equal :pep
189
190
  i.category.must_equal :pubsub
191
+ i.xml_lang.must_equal 'en'
190
192
  end
191
193
 
192
194
  it 'has a category attribute' do
@@ -210,6 +212,13 @@ describe Blather::Stanza::Iq::DiscoInfo::Identity do
210
212
  n.name.must_equal 'foo'
211
213
  end
212
214
 
215
+ it 'has an xml:lang attribute' do
216
+ n = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat en])
217
+ n.xml_lang.must_equal 'en'
218
+ n.xml_lang = 'de'
219
+ n.xml_lang.must_equal 'de'
220
+ end
221
+
213
222
  it 'raises an error if equality is sent a non DiscoInfo::Identity object' do
214
223
  a = Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type cat])
215
224
  lambda { a == 'foo' }.must_raise RuntimeError
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
2
 
3
3
  def disco_items_xml
4
4
  <<-XML
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
2
 
3
3
  def command_xml
4
4
  <<-XML
@@ -0,0 +1,136 @@
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
+
3
+ def ibb_open_xml
4
+ <<-XML
5
+ <iq from='romeo@montague.net/orchard'
6
+ id='jn3h8g65'
7
+ to='juliet@capulet.com/balcony'
8
+ type='set'>
9
+ <open xmlns='http://jabber.org/protocol/ibb'
10
+ block-size='4096'
11
+ sid='i781hf64'
12
+ stanza='iq'/>
13
+ </iq>
14
+ XML
15
+ end
16
+
17
+ def ibb_data_xml
18
+ <<-XML
19
+ <iq from='romeo@montague.net/orchard'
20
+ id='kr91n475'
21
+ to='juliet@capulet.com/balcony'
22
+ type='set'>
23
+ <data xmlns='http://jabber.org/protocol/ibb' seq='0' sid='i781hf64'>
24
+ qANQR1DBwU4DX7jmYZnncmUQB/9KuKBddzQH+tZ1ZywKK0yHKnq57kWq+RFtQdCJ
25
+ WpdWpR0uQsuJe7+vh3NWn59/gTc5MDlX8dS9p0ovStmNcyLhxVgmqS8ZKhsblVeu
26
+ IpQ0JgavABqibJolc3BKrVtVV1igKiX/N7Pi8RtY1K18toaMDhdEfhBRzO/XB0+P
27
+ AQhYlRjNacGcslkhXqNjK5Va4tuOAPy2n1Q8UUrHbUd0g+xJ9Bm0G0LZXyvCWyKH
28
+ kuNEHFQiLuCY6Iv0myq6iX6tjuHehZlFSh80b5BVV9tNLwNR5Eqz1klxMhoghJOA
29
+ </data>
30
+ </iq>
31
+ XML
32
+ end
33
+
34
+ def ibb_close_xml
35
+ <<-XML
36
+ <iq from='romeo@montague.net/orchard'
37
+ id='us71g45j'
38
+ to='juliet@capulet.com/balcony'
39
+ type='set'>
40
+ <close xmlns='http://jabber.org/protocol/ibb' sid='i781hf64'/>
41
+ </iq>
42
+ XML
43
+ end
44
+
45
+ describe Blather::Stanza::Iq::Ibb::Open do
46
+ it 'registers itself' do
47
+ Blather::XMPPNode.class_from_registration(:open, 'http://jabber.org/protocol/ibb').must_equal Blather::Stanza::Iq::Ibb::Open
48
+ end
49
+
50
+ it 'can be imported' do
51
+ doc = parse_stanza ibb_open_xml
52
+ node = Blather::XMPPNode.import(doc.root)
53
+ node.must_be_instance_of Blather::Stanza::Iq::Ibb::Open
54
+ end
55
+
56
+ it 'has open node' do
57
+ doc = parse_stanza ibb_open_xml
58
+ node = Blather::XMPPNode.import(doc.root)
59
+ node.open.must_be_kind_of Nokogiri::XML::Element
60
+ end
61
+
62
+ it 'can get sid' do
63
+ doc = parse_stanza ibb_open_xml
64
+ node = Blather::XMPPNode.import(doc.root)
65
+ node.sid.must_equal 'i781hf64'
66
+ end
67
+
68
+ it 'deleted open node on reply' do
69
+ doc = parse_stanza ibb_open_xml
70
+ node = Blather::XMPPNode.import(doc.root)
71
+ reply = node.reply
72
+ reply.open.must_be_nil
73
+ end
74
+ end
75
+
76
+ describe Blather::Stanza::Iq::Ibb::Data do
77
+ it 'registers itself' do
78
+ Blather::XMPPNode.class_from_registration(:data, 'http://jabber.org/protocol/ibb').must_equal Blather::Stanza::Iq::Ibb::Data
79
+ end
80
+
81
+ it 'can be imported' do
82
+ doc = parse_stanza ibb_data_xml
83
+ node = Blather::XMPPNode.import(doc.root)
84
+ node.must_be_instance_of Blather::Stanza::Iq::Ibb::Data
85
+ end
86
+
87
+ it 'has data node' do
88
+ doc = parse_stanza ibb_data_xml
89
+ node = Blather::XMPPNode.import(doc.root)
90
+ node.data.must_be_kind_of Nokogiri::XML::Element
91
+ end
92
+
93
+ it 'can get sid' do
94
+ doc = parse_stanza ibb_data_xml
95
+ node = Blather::XMPPNode.import(doc.root)
96
+ node.sid.must_equal 'i781hf64'
97
+ end
98
+
99
+ it 'deleted data node on reply' do
100
+ doc = parse_stanza ibb_data_xml
101
+ node = Blather::XMPPNode.import(doc.root)
102
+ reply = node.reply
103
+ reply.data.must_be_nil
104
+ end
105
+ end
106
+
107
+ describe Blather::Stanza::Iq::Ibb::Close do
108
+ it 'registers itself' do
109
+ Blather::XMPPNode.class_from_registration(:close, 'http://jabber.org/protocol/ibb').must_equal Blather::Stanza::Iq::Ibb::Close
110
+ end
111
+
112
+ it 'can be imported' do
113
+ doc = parse_stanza ibb_close_xml
114
+ node = Blather::XMPPNode.import(doc.root)
115
+ node.must_be_instance_of Blather::Stanza::Iq::Ibb::Close
116
+ end
117
+
118
+ it 'has close node' do
119
+ doc = parse_stanza ibb_close_xml
120
+ node = Blather::XMPPNode.import(doc.root)
121
+ node.close.must_be_kind_of Nokogiri::XML::Element
122
+ end
123
+
124
+ it 'can get sid' do
125
+ doc = parse_stanza ibb_close_xml
126
+ node = Blather::XMPPNode.import(doc.root)
127
+ node.sid.must_equal 'i781hf64'
128
+ end
129
+
130
+ it 'deleted close node on reply' do
131
+ doc = parse_stanza ibb_close_xml
132
+ node = Blather::XMPPNode.import(doc.root)
133
+ reply = node.reply
134
+ reply.close.must_be_nil
135
+ end
136
+ end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
2
 
3
3
  describe Blather::Stanza::Iq::Query do
4
4
  it 'registers itself' do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
1
+ require File.expand_path "../../../../spec_helper", __FILE__
2
2
 
3
3
  def roster_xml
4
4
  <<-XML