blather 0.8.1 → 0.8.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.
- data/.gitignore +1 -0
- data/.travis.yml +3 -2
- data/CHANGELOG.md +6 -0
- data/Guardfile +1 -1
- data/README.md +2 -2
- data/blather.gemspec +6 -5
- data/lib/blather/cert_store.rb +17 -15
- data/lib/blather/client.rb +2 -2
- data/lib/blather/file_transfer.rb +1 -1
- data/lib/blather/file_transfer/ibb.rb +1 -1
- data/lib/blather/file_transfer/s5b.rb +1 -1
- data/lib/blather/stanza/disco/disco_info.rb +1 -1
- data/lib/blather/stanza/iq/query.rb +1 -1
- data/lib/blather/stanza/iq/roster.rb +1 -1
- data/lib/blather/stream.rb +21 -19
- data/lib/blather/stream/client.rb +1 -11
- data/lib/blather/stream/component.rb +2 -10
- data/lib/blather/stream/features.rb +1 -3
- data/lib/blather/stream/parser.rb +8 -8
- data/lib/blather/version.rb +1 -1
- data/spec/blather/client/client_spec.rb +450 -484
- data/spec/blather/stanza/message_spec.rb +3 -2
- data/spec/blather/stream/client_spec.rb +174 -201
- data/spec/blather/stream/component_spec.rb +17 -21
- data/spec/blather/stream/parser_spec.rb +2 -0
- data/spec/blather/stream/ssl_spec.rb +9 -17
- data/spec/blather_spec.rb +1 -1
- data/spec/fixtures/certificate.crt +13 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/support/mock_server.rb +8 -0
- metadata +40 -16
- data/.autotest +0 -13
- data/.gemtest +0 -0
- data/TODO.md +0 -2
@@ -178,10 +178,11 @@ describe Blather::Stanza::Message do
|
|
178
178
|
end
|
179
179
|
|
180
180
|
it 'sets valid xhtml even if the input is not valid' do
|
181
|
+
pending "Nokogiri doesn't handle invalid HTML on JRuby" if jruby?
|
181
182
|
msg = Blather::Stanza::Message.new
|
182
183
|
xhtml = "<some>xhtml"
|
183
184
|
msg.xhtml = xhtml
|
184
|
-
msg.xhtml_node.inner_html.strip.should ==
|
185
|
+
msg.xhtml_node.inner_html.strip.should == "<some>xhtml</some>"
|
185
186
|
end
|
186
187
|
|
187
188
|
it 'sets xhtml with more than one root node' do
|
@@ -200,7 +201,7 @@ describe Blather::Stanza::Message do
|
|
200
201
|
|
201
202
|
it 'finds xhtml body when html wrapper has wrong namespace' do
|
202
203
|
msg = Blather::XMPPNode.parse(ichat_message_xml)
|
203
|
-
msg.xhtml.should == "<span style=\"font-family: 'Arial';font-size: 12px;color: #262626;\">Hello</span>\n <img alt=\"f5ad3a04d218d7160fa02415e02d41b3.jpg\" src=\"message-attachments:1\" width=\"30\" height=\"30\"></img>"
|
204
|
+
Nokogiri::XML(msg.xhtml).to_xml.should == Nokogiri::XML("<span style=\"font-family: 'Arial';font-size: 12px;color: #262626;\">Hello</span>\n <img alt=\"f5ad3a04d218d7160fa02415e02d41b3.jpg\" src=\"message-attachments:1\" width=\"30\" height=\"30\"></img>").to_xml
|
204
205
|
end
|
205
206
|
|
206
207
|
it 'has a chat state setter' do
|
@@ -2,37 +2,34 @@ require 'resolv'
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe Blather::Stream::Client do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
let(:client) { mock 'Client' }
|
6
|
+
let(:server_port) { 50000 - rand(1000) }
|
7
|
+
let(:jid) { Blather::JID.new 'n@d/r' }
|
8
|
+
|
9
|
+
before do
|
10
|
+
[:unbind, :post_init, :jid=].each do |m|
|
11
|
+
client.stubs(m) unless client.respond_to?(m)
|
10
12
|
end
|
13
|
+
client.stubs(:jid).returns jid
|
14
|
+
EM.stubs(:next_tick).yields
|
11
15
|
end
|
12
16
|
|
13
17
|
def mocked_server(times = nil, &block)
|
14
|
-
@client ||= mock()
|
15
|
-
@client.stubs(:unbind) unless @client.respond_to?(:unbind)
|
16
|
-
@client.stubs(:post_init) unless @client.respond_to?(:post_init)
|
17
|
-
@client.stubs(:jid=) unless @client.respond_to?(:jid=)
|
18
|
-
|
19
|
-
port = 50000 - rand(1000)
|
20
|
-
|
21
18
|
MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
|
22
19
|
EventMachine::run {
|
23
20
|
EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
|
24
21
|
|
25
22
|
# Mocked server
|
26
|
-
EventMachine::start_server '127.0.0.1',
|
23
|
+
EventMachine::start_server '127.0.0.1', server_port, ServerMock
|
27
24
|
|
28
25
|
# Blather::Stream connection
|
29
|
-
EM.connect('127.0.0.1',
|
26
|
+
EM.connect('127.0.0.1', server_port, Blather::Stream::Client, client, jid, 'pass') { |c| @stream = c }
|
30
27
|
}
|
31
28
|
end
|
32
29
|
|
30
|
+
after { sleep 0.1; @stream.cleanup if @stream }
|
33
31
|
|
34
32
|
it 'can be started' do
|
35
|
-
client = mock()
|
36
33
|
params = [client, 'n@d/r', 'pass', 'host', 1234]
|
37
34
|
EM.expects(:connect).with do |*parms|
|
38
35
|
parms[0].should == 'host'
|
@@ -118,7 +115,7 @@ describe Blather::Stream::Client do
|
|
118
115
|
EventMachine::run {
|
119
116
|
EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
|
120
117
|
|
121
|
-
Blather::Stream::Client.start
|
118
|
+
Blather::Stream::Client.start client, jid, 'pass', '127.0.0.1', 50000 - rand(1000)
|
122
119
|
}
|
123
120
|
end.should raise_error Blather::Stream::ConnectionFailed
|
124
121
|
end
|
@@ -128,8 +125,7 @@ describe Blather::Stream::Client do
|
|
128
125
|
end
|
129
126
|
|
130
127
|
it 'sends stanzas to the client when the stream is ready' do
|
131
|
-
|
132
|
-
@client.expects(:receive_data).with do |n|
|
128
|
+
client.expects(:receive_data).with do |n|
|
133
129
|
EM.stop
|
134
130
|
n.should be_kind_of Blather::Stanza::Message
|
135
131
|
end
|
@@ -138,12 +134,12 @@ describe Blather::Stream::Client do
|
|
138
134
|
val.should match(/stream:stream/)
|
139
135
|
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
140
136
|
server.send_data "<message to='a@b/c' from='d@e/f' type='chat' xml:lang='en'><body>Message!</body></message>"
|
137
|
+
true
|
141
138
|
end
|
142
139
|
end
|
143
140
|
|
144
141
|
it 'puts itself in the stopped state and calls @client.unbind when unbound' do
|
145
|
-
|
146
|
-
@client.expects(:unbind).at_least_once
|
142
|
+
client.expects(:unbind).at_least_once
|
147
143
|
|
148
144
|
started = false
|
149
145
|
mocked_server(2) do |val, server|
|
@@ -155,9 +151,9 @@ describe Blather::Stream::Client do
|
|
155
151
|
|
156
152
|
else
|
157
153
|
EM.stop
|
158
|
-
@stream.
|
154
|
+
@stream.should_not be_stopped
|
159
155
|
@stream.unbind
|
160
|
-
@stream.
|
156
|
+
@stream.should be_stopped
|
161
157
|
|
162
158
|
end
|
163
159
|
end
|
@@ -165,10 +161,11 @@ describe Blather::Stream::Client do
|
|
165
161
|
|
166
162
|
it 'will be in the negotiating state during feature negotiations' do
|
167
163
|
state = nil
|
168
|
-
|
169
|
-
|
164
|
+
|
165
|
+
client.expects(:receive_data).with do |n|
|
170
166
|
EM.stop
|
171
|
-
state.should ==
|
167
|
+
state.should == :negotiated
|
168
|
+
@stream.negotiating?.should == false
|
172
169
|
end
|
173
170
|
|
174
171
|
mocked_server(2) do |val, server|
|
@@ -223,8 +220,7 @@ describe Blather::Stream::Client do
|
|
223
220
|
end
|
224
221
|
|
225
222
|
it 'sends client an error on stream:error' do
|
226
|
-
|
227
|
-
@client.expects(:receive_data).with do |v|
|
223
|
+
client.expects(:receive_data).with do |v|
|
228
224
|
v.name.should == :conflict
|
229
225
|
v.text.should == 'Already signed in'
|
230
226
|
v.to_s.should == "Stream Error (conflict): #{v.text}"
|
@@ -243,6 +239,7 @@ describe Blather::Stream::Client do
|
|
243
239
|
state = :stopped
|
244
240
|
server.send_data "<stream:error><conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams' />"
|
245
241
|
server.send_data "<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'>Already signed in</text></stream:error>"
|
242
|
+
val.should match(/bind/)
|
246
243
|
|
247
244
|
when :stopped
|
248
245
|
EM.stop
|
@@ -258,7 +255,7 @@ describe Blather::Stream::Client do
|
|
258
255
|
|
259
256
|
it 'skips features it is unable to handle' do
|
260
257
|
state = nil
|
261
|
-
mocked_server
|
258
|
+
mocked_server do |val, server|
|
262
259
|
case state
|
263
260
|
when nil
|
264
261
|
state = :started
|
@@ -307,9 +304,9 @@ describe Blather::Stream::Client do
|
|
307
304
|
end
|
308
305
|
|
309
306
|
it 'will fail if TLS negotiation fails' do
|
307
|
+
client.expects(:receive_data).with { |v| v.should be_kind_of Blather::Stream::TLS::TLSFailure }
|
308
|
+
|
310
309
|
state = nil
|
311
|
-
@client = mock()
|
312
|
-
@client.expects(:receive_data).with { |v| v.should be_kind_of Blather::Stream::TLS::TLSFailure }
|
313
310
|
mocked_server(3) do |val, server|
|
314
311
|
case state
|
315
312
|
when nil
|
@@ -336,11 +333,11 @@ describe Blather::Stream::Client do
|
|
336
333
|
end
|
337
334
|
|
338
335
|
it 'will fail if a bad node comes through TLS negotiations' do
|
339
|
-
|
340
|
-
@client = mock()
|
341
|
-
@client.expects(:receive_data).with do |v|
|
336
|
+
client.expects(:receive_data).with do |v|
|
342
337
|
v.should be_kind_of Blather::Stream::TLS::TLSFailure
|
343
338
|
end
|
339
|
+
|
340
|
+
state = nil
|
344
341
|
mocked_server(3) do |val, server|
|
345
342
|
case state
|
346
343
|
when nil
|
@@ -369,8 +366,8 @@ describe Blather::Stream::Client do
|
|
369
366
|
|
370
367
|
it 'connects via SASL MD5 when asked' do
|
371
368
|
Time.any_instance.stubs(:to_f).returns(1.1)
|
372
|
-
state = nil
|
373
369
|
|
370
|
+
state = nil
|
374
371
|
mocked_server(5) do |val, server|
|
375
372
|
case state
|
376
373
|
when nil
|
@@ -418,7 +415,7 @@ describe Blather::Stream::Client do
|
|
418
415
|
when :started
|
419
416
|
state = :auth_sent
|
420
417
|
server.send_data "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"
|
421
|
-
val.should ==('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>')
|
418
|
+
Nokogiri::XML(val).to_xml.should == Nokogiri::XML('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>').to_xml
|
422
419
|
|
423
420
|
when :auth_sent
|
424
421
|
EM.stop
|
@@ -435,7 +432,6 @@ describe Blather::Stream::Client do
|
|
435
432
|
|
436
433
|
it 'will connect via SSL ANONYMOUS when asked' do
|
437
434
|
state = nil
|
438
|
-
|
439
435
|
mocked_server(3) do |val, server|
|
440
436
|
case state
|
441
437
|
when nil
|
@@ -446,7 +442,7 @@ describe Blather::Stream::Client do
|
|
446
442
|
when :started
|
447
443
|
state = :auth_sent
|
448
444
|
server.send_data "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"
|
449
|
-
val.should ==('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="ANONYMOUS"/>')
|
445
|
+
Nokogiri::XML(val).to_xml.should == Nokogiri::XML('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="ANONYMOUS"/>').to_xml
|
450
446
|
|
451
447
|
when :auth_sent
|
452
448
|
EM.stop
|
@@ -461,69 +457,68 @@ describe Blather::Stream::Client do
|
|
461
457
|
end
|
462
458
|
end
|
463
459
|
|
464
|
-
|
465
|
-
|
466
|
-
@jid = Blather::JID.new '@d'
|
460
|
+
context "if the JID node is blank" do
|
461
|
+
let(:jid) { Blather::JID.new '@d' }
|
467
462
|
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
state
|
472
|
-
|
473
|
-
|
463
|
+
it 'connects via ANONYMOUS if the Blather::JID has a blank node' do
|
464
|
+
state = nil
|
465
|
+
mocked_server(3) do |val, server|
|
466
|
+
case state
|
467
|
+
when nil
|
468
|
+
state = :started
|
469
|
+
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
|
470
|
+
val.should match(/stream:stream/)
|
474
471
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
472
|
+
when :started
|
473
|
+
state = :auth_sent
|
474
|
+
server.send_data "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"
|
475
|
+
Nokogiri::XML(val).to_xml.should == Nokogiri::XML('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="ANONYMOUS"/>').to_xml
|
479
476
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
477
|
+
when :auth_sent
|
478
|
+
EM.stop
|
479
|
+
state = :complete
|
480
|
+
val.should match(/stream:stream/)
|
484
481
|
|
485
|
-
|
486
|
-
|
487
|
-
|
482
|
+
else
|
483
|
+
EM.stop
|
484
|
+
false
|
488
485
|
|
486
|
+
end
|
489
487
|
end
|
490
488
|
end
|
491
|
-
end
|
492
489
|
|
493
|
-
|
494
|
-
|
495
|
-
@jid = Blather::JID.new '@d'
|
496
|
-
@client = mock()
|
497
|
-
@client.expects(:receive_data).with { |s| s.should be_instance_of Blather::BlatherError }
|
490
|
+
it 'fails if asked to connect via ANONYMOUS but the server does not support it' do
|
491
|
+
client.expects(:receive_data).with { |s| s.should be_instance_of Blather::BlatherError }
|
498
492
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
493
|
+
state = nil
|
494
|
+
mocked_server(2) do |val, server|
|
495
|
+
case state
|
496
|
+
when nil
|
497
|
+
state = :started
|
498
|
+
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
499
|
+
server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism></mechanisms></stream:features>"
|
500
|
+
val.should match(/stream:stream/)
|
506
501
|
|
507
|
-
|
508
|
-
|
509
|
-
|
502
|
+
when :started
|
503
|
+
EM.stop
|
504
|
+
val.should match(/stream:stream/)
|
510
505
|
|
511
|
-
|
512
|
-
|
513
|
-
|
506
|
+
else
|
507
|
+
EM.stop
|
508
|
+
false
|
514
509
|
|
510
|
+
end
|
515
511
|
end
|
516
512
|
end
|
517
513
|
end
|
518
514
|
|
519
515
|
it 'tries each possible mechanism until it fails completely' do
|
520
|
-
|
521
|
-
@client = mock()
|
522
|
-
@client.expects(:receive_data).with do |n|
|
516
|
+
client.expects(:receive_data).with do |n|
|
523
517
|
n.should be_kind_of(Blather::SASLError)
|
524
518
|
n.name.should == :not_authorized
|
525
519
|
end
|
526
520
|
|
521
|
+
state = nil
|
527
522
|
mocked_server(5) do |val, server|
|
528
523
|
case state
|
529
524
|
when nil
|
@@ -604,7 +599,7 @@ describe Blather::Stream::Client do
|
|
604
599
|
when :started
|
605
600
|
state = :auth_sent
|
606
601
|
server.send_data "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"
|
607
|
-
val.should ==('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>')
|
602
|
+
Nokogiri::XML(val).to_xml.should == Nokogiri::XML('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>').to_xml
|
608
603
|
|
609
604
|
when :auth_sent
|
610
605
|
EM.stop
|
@@ -618,26 +613,7 @@ describe Blather::Stream::Client do
|
|
618
613
|
end
|
619
614
|
end
|
620
615
|
end
|
621
|
-
=begin
|
622
|
-
it 'sends client an error when an unknown mechanism is sent' do
|
623
|
-
@client = mock()
|
624
|
-
@client.expects(:receive_data).with { |v| v.should be_kind_of(Blather::Stream::SASL::UnknownMechanism) }
|
625
|
-
started = false
|
626
|
-
mocked_server(2) do |val, server|
|
627
|
-
if !started
|
628
|
-
started = true
|
629
|
-
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
630
|
-
server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>UNKNOWN</mechanism></mechanisms></stream:features>"
|
631
|
-
val.should match(/stream:stream/)
|
632
|
-
|
633
|
-
else
|
634
|
-
EM.stop
|
635
|
-
val.should match(/failure(.*)invalid\-mechanism/)
|
636
616
|
|
637
|
-
end
|
638
|
-
end
|
639
|
-
end
|
640
|
-
=end
|
641
617
|
%w[ aborted
|
642
618
|
incorrect-encoding
|
643
619
|
invalid-authzid
|
@@ -647,10 +623,10 @@ describe Blather::Stream::Client do
|
|
647
623
|
temporary-auth-failure
|
648
624
|
].each do |error_type|
|
649
625
|
it "fails on #{error_type}" do
|
650
|
-
|
651
|
-
@client.expects(:receive_data).with do |n|
|
626
|
+
client.expects(:receive_data).with do |n|
|
652
627
|
n.name.should == error_type.gsub('-','_').to_sym
|
653
628
|
end
|
629
|
+
|
654
630
|
state = nil
|
655
631
|
mocked_server(3) do |val, server|
|
656
632
|
case state
|
@@ -662,7 +638,7 @@ describe Blather::Stream::Client do
|
|
662
638
|
when :started
|
663
639
|
state = :auth_sent
|
664
640
|
server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><#{error_type} /></failure>"
|
665
|
-
val.should ==('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>')
|
641
|
+
Nokogiri::XML(val).to_xml.should == Nokogiri::XML('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>').to_xml
|
666
642
|
|
667
643
|
when :auth_sent
|
668
644
|
EM.stop
|
@@ -679,11 +655,11 @@ describe Blather::Stream::Client do
|
|
679
655
|
end
|
680
656
|
|
681
657
|
it 'fails when an unknown node comes through during SASL negotiation' do
|
682
|
-
|
683
|
-
@client.expects(:receive_data).with do |n|
|
658
|
+
client.expects(:receive_data).with do |n|
|
684
659
|
n.should be_instance_of Blather::UnknownResponse
|
685
660
|
n.node.element_name.should == 'foo-bar'
|
686
661
|
end
|
662
|
+
|
687
663
|
state = nil
|
688
664
|
mocked_server(3) do |val, server|
|
689
665
|
case state
|
@@ -695,7 +671,7 @@ describe Blather::Stream::Client do
|
|
695
671
|
when :started
|
696
672
|
state = :auth_sent
|
697
673
|
server.send_data "<foo-bar />"
|
698
|
-
val.should ==('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>')
|
674
|
+
Nokogiri::XML(val).to_xml.should == Nokogiri::XML('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>').to_xml
|
699
675
|
|
700
676
|
when :auth_sent
|
701
677
|
EM.stop
|
@@ -710,95 +686,90 @@ describe Blather::Stream::Client do
|
|
710
686
|
end
|
711
687
|
end
|
712
688
|
|
713
|
-
|
714
|
-
|
715
|
-
class Client; attr_accessor :jid; end
|
716
|
-
@client = Client.new
|
717
|
-
@jid = Blather::JID.new('n@d')
|
689
|
+
context "when the JID doesn't set a resource" do
|
690
|
+
let(:jid) { Blather::JID.new 'n@d' }
|
718
691
|
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
state
|
723
|
-
|
724
|
-
|
725
|
-
|
692
|
+
it 'will bind to a resource set by the server' do
|
693
|
+
state = nil
|
694
|
+
mocked_server(3) do |val, server|
|
695
|
+
case state
|
696
|
+
when nil
|
697
|
+
state = :started
|
698
|
+
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
699
|
+
server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
700
|
+
val.should match(/stream:stream/)
|
726
701
|
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
702
|
+
when :started
|
703
|
+
state = :complete
|
704
|
+
val =~ %r{<iq[^>]+id="([^"]+)"}
|
705
|
+
server.send_data "<iq type='result' id='#{$1}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{jid}/server_resource</jid></bind></iq>"
|
706
|
+
server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
707
|
+
val.should match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"\s?/>})
|
733
708
|
|
734
|
-
|
735
|
-
|
736
|
-
|
709
|
+
when :complete
|
710
|
+
EM.stop
|
711
|
+
@stream.jid.should == Blather::JID.new('n@d/server_resource')
|
737
712
|
|
738
|
-
|
739
|
-
|
740
|
-
|
713
|
+
else
|
714
|
+
EM.stop
|
715
|
+
false
|
741
716
|
|
717
|
+
end
|
742
718
|
end
|
743
719
|
end
|
744
|
-
end
|
745
720
|
|
746
|
-
|
747
|
-
|
748
|
-
class Client; attr_accessor :jid; end
|
749
|
-
@client = Client.new
|
750
|
-
@jid = Blather::JID.new('n@d/r')
|
751
|
-
|
752
|
-
mocked_server(3) do |val, server|
|
753
|
-
case state
|
754
|
-
when nil
|
755
|
-
state = :started
|
756
|
-
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
757
|
-
val.should match(/stream:stream/)
|
721
|
+
it 'will error out if the bind ID mismatches' do
|
722
|
+
state = nil
|
758
723
|
|
759
|
-
|
760
|
-
state
|
761
|
-
|
762
|
-
|
724
|
+
mocked_server(3) do |val, server|
|
725
|
+
case state
|
726
|
+
when nil
|
727
|
+
state = :started
|
728
|
+
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
729
|
+
server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
730
|
+
val.should match(/stream:stream/)
|
763
731
|
|
764
|
-
|
765
|
-
|
732
|
+
when :started
|
733
|
+
state = :complete
|
734
|
+
val =~ %r{<iq[^>]+id="([^"]+)"}
|
735
|
+
client.expects(:receive_data).with("BIND result ID mismatch. Expected: #{$1}. Received: #{$1}-bad")
|
736
|
+
server.send_data "<iq type='result' id='#{$1}-bad'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{jid}/server_resource</jid></bind></iq>"
|
737
|
+
val.should match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"\s?/>})
|
766
738
|
|
767
|
-
|
768
|
-
|
769
|
-
|
739
|
+
when :complete
|
740
|
+
EM.stop
|
741
|
+
true
|
770
742
|
|
771
|
-
|
772
|
-
|
773
|
-
|
743
|
+
else
|
744
|
+
EM.stop
|
745
|
+
false
|
774
746
|
|
747
|
+
end
|
775
748
|
end
|
776
749
|
end
|
777
750
|
end
|
778
751
|
|
779
|
-
it 'will
|
752
|
+
it 'will bind to a resource set by the client' do
|
780
753
|
state = nil
|
781
|
-
@jid = Blather::JID.new('n@d')
|
782
|
-
@client = mock()
|
783
|
-
|
784
754
|
mocked_server(3) do |val, server|
|
785
755
|
case state
|
786
756
|
when nil
|
787
757
|
state = :started
|
788
|
-
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
789
|
-
server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
758
|
+
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
790
759
|
val.should match(/stream:stream/)
|
791
760
|
|
792
761
|
when :started
|
793
762
|
state = :complete
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
763
|
+
doc = parse_stanza val
|
764
|
+
doc.xpath('/iq/bind_ns:bind/bind_ns:resource[.="r"]', :bind_ns => Blather::Stream::Resource::BIND_NS).should_not be_empty
|
765
|
+
|
766
|
+
server.send_data "<iq type='result' id='#{doc.find_first('iq')['id']}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{jid}</jid></bind></iq>"
|
767
|
+
server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
768
|
+
true
|
798
769
|
|
799
770
|
when :complete
|
800
771
|
EM.stop
|
801
|
-
|
772
|
+
@stream.jid.should == Blather::JID.new('n@d/r')
|
802
773
|
|
803
774
|
else
|
804
775
|
EM.stop
|
@@ -809,11 +780,11 @@ describe Blather::Stream::Client do
|
|
809
780
|
end
|
810
781
|
|
811
782
|
it 'will return an error if resource binding errors out' do
|
812
|
-
|
813
|
-
@client = mock()
|
814
|
-
@client.expects(:receive_data).with do |n|
|
783
|
+
client.expects(:receive_data).with do |n|
|
815
784
|
n.name.should == :bad_request
|
816
785
|
end
|
786
|
+
|
787
|
+
state = nil
|
817
788
|
mocked_server(3) do |val, server|
|
818
789
|
case state
|
819
790
|
when nil
|
@@ -826,6 +797,7 @@ describe Blather::Stream::Client do
|
|
826
797
|
doc = parse_stanza val
|
827
798
|
doc.xpath('/iq/bind_ns:bind/bind_ns:resource[.="r"]', :bind_ns => Blather::Stream::Resource::BIND_NS).should_not be_empty
|
828
799
|
server.send_data "<iq type='error' id='#{doc.find_first('iq')['id']}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>r</resource></bind><error type='modify'><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
|
800
|
+
true
|
829
801
|
|
830
802
|
when :complete
|
831
803
|
EM.stop
|
@@ -840,12 +812,12 @@ describe Blather::Stream::Client do
|
|
840
812
|
end
|
841
813
|
|
842
814
|
it 'will return an error if an unknown node comes through during resouce binding' do
|
843
|
-
|
844
|
-
@client = mock()
|
845
|
-
@client.expects(:receive_data).with do |n|
|
815
|
+
client.expects(:receive_data).with do |n|
|
846
816
|
n.should be_instance_of Blather::UnknownResponse
|
847
817
|
n.node.element_name.should == 'foo-bar'
|
848
818
|
end
|
819
|
+
|
820
|
+
state = nil
|
849
821
|
mocked_server(3) do |val, server|
|
850
822
|
case state
|
851
823
|
when nil
|
@@ -859,6 +831,7 @@ describe Blather::Stream::Client do
|
|
859
831
|
doc = parse_stanza val
|
860
832
|
doc.xpath('/iq/bind_ns:bind/bind_ns:resource[.="r"]', :bind_ns => Blather::Stream::Resource::BIND_NS).should_not be_empty
|
861
833
|
server.send_data "<foo-bar />"
|
834
|
+
true
|
862
835
|
|
863
836
|
when :complete
|
864
837
|
EM.stop
|
@@ -873,10 +846,9 @@ describe Blather::Stream::Client do
|
|
873
846
|
end
|
874
847
|
|
875
848
|
it 'will establish a session if requested' do
|
876
|
-
|
877
|
-
@client = mock()
|
878
|
-
@client.expects(:post_init)
|
849
|
+
client.expects(:post_init)
|
879
850
|
|
851
|
+
state = nil
|
880
852
|
mocked_server(3) do |val, server|
|
881
853
|
case state
|
882
854
|
when nil
|
@@ -891,6 +863,7 @@ describe Blather::Stream::Client do
|
|
891
863
|
doc.find('/iq[@type="set" and @to="d"]/sess_ns:session', :sess_ns => Blather::Stream::Session::SESSION_NS).should_not be_empty
|
892
864
|
server.send_data "<iq from='d' type='result' id='#{doc.find_first('iq')['id']}' />"
|
893
865
|
server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
|
866
|
+
true
|
894
867
|
|
895
868
|
when :completed
|
896
869
|
EM.stop
|
@@ -905,11 +878,11 @@ describe Blather::Stream::Client do
|
|
905
878
|
end
|
906
879
|
|
907
880
|
it 'will return an error if session establishment errors out' do
|
908
|
-
|
909
|
-
@client = mock()
|
910
|
-
@client.expects(:receive_data).with do |n|
|
881
|
+
client.expects(:receive_data).with do |n|
|
911
882
|
n.name.should == :internal_server_error
|
912
883
|
end
|
884
|
+
|
885
|
+
state = nil
|
913
886
|
mocked_server(3) do |val, server|
|
914
887
|
case state
|
915
888
|
when nil
|
@@ -923,6 +896,7 @@ describe Blather::Stream::Client do
|
|
923
896
|
doc = parse_stanza val
|
924
897
|
doc.find('/iq[@type="set" and @to="d"]/sess_ns:session', :sess_ns => Blather::Stream::Session::SESSION_NS).should_not be_empty
|
925
898
|
server.send_data "<iq from='d' type='error' id='#{doc.find_first('iq')['id']}'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/><error type='wait'><internal-server-error xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
|
899
|
+
true
|
926
900
|
|
927
901
|
when :completed
|
928
902
|
EM.stop
|
@@ -937,12 +911,12 @@ describe Blather::Stream::Client do
|
|
937
911
|
end
|
938
912
|
|
939
913
|
it 'will return an error if an unknown node come through during session establishment' do
|
940
|
-
|
941
|
-
@client = mock()
|
942
|
-
@client.expects(:receive_data).with do |n|
|
914
|
+
client.expects(:receive_data).with do |n|
|
943
915
|
n.should be_instance_of Blather::UnknownResponse
|
944
916
|
n.node.element_name.should == 'foo-bar'
|
945
917
|
end
|
918
|
+
|
919
|
+
state = nil
|
946
920
|
mocked_server(3) do |val, server|
|
947
921
|
case state
|
948
922
|
when nil
|
@@ -956,6 +930,7 @@ describe Blather::Stream::Client do
|
|
956
930
|
doc = parse_stanza val
|
957
931
|
doc.find('/iq[@type="set" and @to="d"]/sess_ns:session', :sess_ns => Blather::Stream::Session::SESSION_NS).should_not be_empty
|
958
932
|
server.send_data '<foo-bar />'
|
933
|
+
true
|
959
934
|
|
960
935
|
when :completed
|
961
936
|
EM.stop
|
@@ -970,11 +945,11 @@ describe Blather::Stream::Client do
|
|
970
945
|
end
|
971
946
|
|
972
947
|
it 'sends client an error and reply to the server on parse error' do
|
973
|
-
|
974
|
-
@client.expects(:receive_data).with do |v|
|
948
|
+
client.expects(:receive_data).with do |v|
|
975
949
|
v.should be_kind_of Blather::ParseError
|
976
|
-
v.message.should match(/
|
950
|
+
v.message.should match(/match/)
|
977
951
|
end
|
952
|
+
|
978
953
|
state = nil
|
979
954
|
mocked_server(3) do |val, server|
|
980
955
|
case state
|
@@ -986,7 +961,9 @@ describe Blather::Stream::Client do
|
|
986
961
|
|
987
962
|
when :started
|
988
963
|
state = :parse_error
|
964
|
+
val.should match(/bind/)
|
989
965
|
server.send_data "</generate-parse-error>"
|
966
|
+
true
|
990
967
|
|
991
968
|
when :parse_error
|
992
969
|
EM.stop
|
@@ -1001,9 +978,6 @@ describe Blather::Stream::Client do
|
|
1001
978
|
end
|
1002
979
|
|
1003
980
|
it 'sends stanzas to the wire ensuring "from" is the full JID if set' do
|
1004
|
-
client = mock()
|
1005
|
-
client.stubs(:jid)
|
1006
|
-
client.stubs(:jid=)
|
1007
981
|
msg = Blather::Stanza::Message.new 'to@jid.com', 'body'
|
1008
982
|
msg.from = 'node@jid.com'
|
1009
983
|
comp = Blather::Stream::Client.new nil, client, 'node@jid.com/resource', 'pass'
|
@@ -1012,9 +986,6 @@ describe Blather::Stream::Client do
|
|
1012
986
|
end
|
1013
987
|
|
1014
988
|
it 'sends stanzas to the wire leaving "from" nil if not set' do
|
1015
|
-
client = mock()
|
1016
|
-
client.stubs(:jid)
|
1017
|
-
client.stubs(:jid=)
|
1018
989
|
msg = Blather::Stanza::Message.new 'to@jid.com', 'body'
|
1019
990
|
comp = Blather::Stream::Client.new nil, client, 'node@jid.com/resource', 'pass'
|
1020
991
|
comp.expects(:send_data).with { |s| s.should_not match(/^<message[^>]*from=/); true }
|
@@ -1022,10 +993,6 @@ describe Blather::Stream::Client do
|
|
1022
993
|
end
|
1023
994
|
|
1024
995
|
it 'sends xml without formatting' do
|
1025
|
-
client = mock()
|
1026
|
-
client.stubs(:jid)
|
1027
|
-
client.stubs(:jid=)
|
1028
|
-
|
1029
996
|
msg = Blather::Stanza::Message.new 'to@jid.com', 'body'
|
1030
997
|
msg.xhtml = '<i>xhtml</i> body'
|
1031
998
|
|
@@ -1036,14 +1003,17 @@ describe Blather::Stream::Client do
|
|
1036
1003
|
|
1037
1004
|
it 'tries to register if initial authentication failed but in-band registration enabled' do
|
1038
1005
|
state = nil
|
1039
|
-
mocked_server(
|
1006
|
+
mocked_server(5) do |val, server|
|
1040
1007
|
case state
|
1041
1008
|
when nil
|
1042
|
-
state = :
|
1009
|
+
state = :sasl_attempted
|
1043
1010
|
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
1044
1011
|
server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms><register xmlns='http://jabber.org/features/iq-register'/></stream:features>"
|
1045
|
-
server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized /></failure>"
|
1046
1012
|
val.should match(/stream:stream/)
|
1013
|
+
when :sasl_attempted
|
1014
|
+
state = :sasl_failed
|
1015
|
+
server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized /></failure>"
|
1016
|
+
val.should match(/auth/)
|
1047
1017
|
when :sasl_failed
|
1048
1018
|
state = :registered
|
1049
1019
|
server.send_data "<iq type='result'/>"
|
@@ -1063,17 +1033,20 @@ describe Blather::Stream::Client do
|
|
1063
1033
|
end
|
1064
1034
|
|
1065
1035
|
it 'fails when in-band registration failed' do
|
1036
|
+
client.expects(:receive_data).with { |n| n.should be_instance_of Blather::BlatherError }
|
1037
|
+
|
1066
1038
|
state = nil
|
1067
|
-
|
1068
|
-
@client.expects(:receive_data).with { |n| n.should be_instance_of Blather::BlatherError }
|
1069
|
-
mocked_server(3) do |val, server|
|
1039
|
+
mocked_server(4) do |val, server|
|
1070
1040
|
case state
|
1071
1041
|
when nil
|
1072
|
-
state = :
|
1042
|
+
state = :sasl_attempted
|
1073
1043
|
server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
|
1074
1044
|
server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms><register xmlns='http://jabber.org/features/iq-register'/></stream:features>"
|
1075
|
-
server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized /></failure>"
|
1076
1045
|
val.should match(/stream:stream/)
|
1046
|
+
when :sasl_attempted
|
1047
|
+
state = :sasl_failed
|
1048
|
+
server.send_data "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized /></failure>"
|
1049
|
+
val.should match(/auth/)
|
1077
1050
|
when :sasl_failed
|
1078
1051
|
state = :registration_failed
|
1079
1052
|
server.send_data "<iq type='error'><query /><error code='409' type='cancel'><conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
|