tp-blather 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.
Files changed (150) hide show
  1. data/.autotest +13 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +8 -0
  6. data/CHANGELOG.md +249 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +5 -0
  9. data/LICENSE +22 -0
  10. data/README.md +413 -0
  11. data/Rakefile +20 -0
  12. data/TODO.md +2 -0
  13. data/blather.gemspec +51 -0
  14. data/examples/certs/README +20 -0
  15. data/examples/certs/ca-bundle.crt +3987 -0
  16. data/examples/echo.rb +19 -0
  17. data/examples/execute.rb +17 -0
  18. data/examples/ping_pong.rb +38 -0
  19. data/examples/print_hierarchy.rb +77 -0
  20. data/examples/rosterprint.rb +15 -0
  21. data/examples/stream_only.rb +28 -0
  22. data/examples/trusted_echo.rb +21 -0
  23. data/examples/xmpp4r/echo.rb +36 -0
  24. data/lib/blather.rb +112 -0
  25. data/lib/blather/cert_store.rb +53 -0
  26. data/lib/blather/client.rb +95 -0
  27. data/lib/blather/client/client.rb +345 -0
  28. data/lib/blather/client/dsl.rb +320 -0
  29. data/lib/blather/client/dsl/pubsub.rb +174 -0
  30. data/lib/blather/core_ext/eventmachine.rb +125 -0
  31. data/lib/blather/core_ext/ipaddr.rb +20 -0
  32. data/lib/blather/errors.rb +69 -0
  33. data/lib/blather/errors/sasl_error.rb +44 -0
  34. data/lib/blather/errors/stanza_error.rb +110 -0
  35. data/lib/blather/errors/stream_error.rb +84 -0
  36. data/lib/blather/file_transfer.rb +107 -0
  37. data/lib/blather/file_transfer/ibb.rb +68 -0
  38. data/lib/blather/file_transfer/s5b.rb +114 -0
  39. data/lib/blather/jid.rb +141 -0
  40. data/lib/blather/roster.rb +118 -0
  41. data/lib/blather/roster_item.rb +146 -0
  42. data/lib/blather/stanza.rb +167 -0
  43. data/lib/blather/stanza/disco.rb +32 -0
  44. data/lib/blather/stanza/disco/capabilities.rb +161 -0
  45. data/lib/blather/stanza/disco/disco_info.rb +205 -0
  46. data/lib/blather/stanza/disco/disco_items.rb +134 -0
  47. data/lib/blather/stanza/iq.rb +144 -0
  48. data/lib/blather/stanza/iq/command.rb +339 -0
  49. data/lib/blather/stanza/iq/ibb.rb +86 -0
  50. data/lib/blather/stanza/iq/ping.rb +50 -0
  51. data/lib/blather/stanza/iq/query.rb +53 -0
  52. data/lib/blather/stanza/iq/roster.rb +185 -0
  53. data/lib/blather/stanza/iq/s5b.rb +208 -0
  54. data/lib/blather/stanza/iq/si.rb +415 -0
  55. data/lib/blather/stanza/iq/vcard.rb +149 -0
  56. data/lib/blather/stanza/message.rb +428 -0
  57. data/lib/blather/stanza/message/muc_user.rb +119 -0
  58. data/lib/blather/stanza/muc/muc_user_base.rb +54 -0
  59. data/lib/blather/stanza/presence.rb +172 -0
  60. data/lib/blather/stanza/presence/c.rb +100 -0
  61. data/lib/blather/stanza/presence/muc.rb +35 -0
  62. data/lib/blather/stanza/presence/muc_user.rb +147 -0
  63. data/lib/blather/stanza/presence/status.rb +218 -0
  64. data/lib/blather/stanza/presence/subscription.rb +100 -0
  65. data/lib/blather/stanza/pubsub.rb +119 -0
  66. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  67. data/lib/blather/stanza/pubsub/create.rb +65 -0
  68. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  69. data/lib/blather/stanza/pubsub/event.rb +139 -0
  70. data/lib/blather/stanza/pubsub/items.rb +103 -0
  71. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  72. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  73. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  74. data/lib/blather/stanza/pubsub/subscription.rb +135 -0
  75. data/lib/blather/stanza/pubsub/subscriptions.rb +83 -0
  76. data/lib/blather/stanza/pubsub/unsubscribe.rb +84 -0
  77. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  78. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  79. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  80. data/lib/blather/stanza/x.rb +416 -0
  81. data/lib/blather/stream.rb +266 -0
  82. data/lib/blather/stream/client.rb +32 -0
  83. data/lib/blather/stream/component.rb +39 -0
  84. data/lib/blather/stream/features.rb +70 -0
  85. data/lib/blather/stream/features/register.rb +38 -0
  86. data/lib/blather/stream/features/resource.rb +63 -0
  87. data/lib/blather/stream/features/sasl.rb +190 -0
  88. data/lib/blather/stream/features/session.rb +45 -0
  89. data/lib/blather/stream/features/tls.rb +29 -0
  90. data/lib/blather/stream/parser.rb +102 -0
  91. data/lib/blather/version.rb +3 -0
  92. data/lib/blather/xmpp_node.rb +94 -0
  93. data/spec/blather/client/client_spec.rb +687 -0
  94. data/spec/blather/client/dsl/pubsub_spec.rb +492 -0
  95. data/spec/blather/client/dsl_spec.rb +266 -0
  96. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  97. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  98. data/spec/blather/errors/stream_error_spec.rb +108 -0
  99. data/spec/blather/errors_spec.rb +33 -0
  100. data/spec/blather/file_transfer_spec.rb +135 -0
  101. data/spec/blather/jid_spec.rb +87 -0
  102. data/spec/blather/roster_item_spec.rb +134 -0
  103. data/spec/blather/roster_spec.rb +107 -0
  104. data/spec/blather/stanza/discos/disco_info_spec.rb +247 -0
  105. data/spec/blather/stanza/discos/disco_items_spec.rb +154 -0
  106. data/spec/blather/stanza/iq/command_spec.rb +206 -0
  107. data/spec/blather/stanza/iq/ibb_spec.rb +124 -0
  108. data/spec/blather/stanza/iq/ping_spec.rb +45 -0
  109. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  110. data/spec/blather/stanza/iq/roster_spec.rb +139 -0
  111. data/spec/blather/stanza/iq/s5b_spec.rb +57 -0
  112. data/spec/blather/stanza/iq/si_spec.rb +98 -0
  113. data/spec/blather/stanza/iq/vcard_spec.rb +93 -0
  114. data/spec/blather/stanza/iq_spec.rb +61 -0
  115. data/spec/blather/stanza/message/muc_user_spec.rb +152 -0
  116. data/spec/blather/stanza/message_spec.rb +282 -0
  117. data/spec/blather/stanza/presence/c_spec.rb +56 -0
  118. data/spec/blather/stanza/presence/muc_spec.rb +37 -0
  119. data/spec/blather/stanza/presence/muc_user_spec.rb +83 -0
  120. data/spec/blather/stanza/presence/status_spec.rb +144 -0
  121. data/spec/blather/stanza/presence/subscription_spec.rb +102 -0
  122. data/spec/blather/stanza/presence_spec.rb +125 -0
  123. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  124. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  125. data/spec/blather/stanza/pubsub/event_spec.rb +98 -0
  126. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  127. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  128. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  129. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  130. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  131. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  132. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +74 -0
  133. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  134. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  135. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  136. data/spec/blather/stanza/pubsub_spec.rb +68 -0
  137. data/spec/blather/stanza/x_spec.rb +231 -0
  138. data/spec/blather/stanza_spec.rb +134 -0
  139. data/spec/blather/stream/client_spec.rb +1090 -0
  140. data/spec/blather/stream/component_spec.rb +108 -0
  141. data/spec/blather/stream/parser_spec.rb +152 -0
  142. data/spec/blather/stream/ssl_spec.rb +32 -0
  143. data/spec/blather/xmpp_node_spec.rb +47 -0
  144. data/spec/blather_spec.rb +34 -0
  145. data/spec/fixtures/pubsub.rb +311 -0
  146. data/spec/spec_helper.rb +17 -0
  147. data/yard/templates/default/class/html/handlers.erb +18 -0
  148. data/yard/templates/default/class/setup.rb +10 -0
  149. data/yard/templates/default/class/text/handlers.erb +1 -0
  150. metadata +459 -0
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blather::Stream::Component do
4
+ class MockServer; end
5
+ module ServerMock
6
+ def receive_data(data)
7
+ @server ||= MockServer.new
8
+ @server.receive_data data, self
9
+ end
10
+ end
11
+
12
+ def mocked_server(times = nil, &block)
13
+ @client ||= mock()
14
+ @client.stubs(:unbind) unless @client.respond_to?(:unbind)
15
+ @client.stubs(:jid=) unless @client.respond_to?(:jid=)
16
+
17
+ port = 50000 - rand(1000)
18
+
19
+ MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
20
+ EventMachine::run {
21
+ # Mocked server
22
+ EventMachine::start_server '127.0.0.1', port, ServerMock
23
+
24
+ # Blather::Stream connection
25
+ EM.connect('127.0.0.1', port, Blather::Stream::Component, @client, @jid || 'comp.id', 'secret') { |c| @stream = c }
26
+ }
27
+ end
28
+
29
+ it 'can be started' do
30
+ client = mock()
31
+ params = [client, 'comp.id', 'secret', 'host', 1234]
32
+ EM.expects(:connect).with do |*parms|
33
+ parms[0] == 'host' &&
34
+ parms[1] == 1234 &&
35
+ parms[3] == client &&
36
+ parms[4] == 'comp.id'
37
+ end
38
+
39
+ Blather::Stream::Component.start *params
40
+ end
41
+
42
+ it 'shakes hands with the server' do
43
+ state = nil
44
+ mocked_server(2) do |val, server|
45
+ case state
46
+ when nil
47
+ state = :started
48
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams' id='12345'>"
49
+ val.should match(/stream:stream/)
50
+
51
+ when :started
52
+ server.send_data '<handshake/>'
53
+ EM.stop
54
+ val.should == "<handshake>#{Digest::SHA1.hexdigest('12345'+"secret")}</handshake>"
55
+
56
+ end
57
+ end
58
+ end
59
+
60
+ it 'raises a NoConnection exception if the connection is unbound before it can be completed' do
61
+ @client = mock
62
+ proc do
63
+ EventMachine::run {
64
+ EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
65
+
66
+ Blather::Stream::Component.start @client, @jid || Blather::JID.new('n@d/r'), 'pass', '127.0.0.1', 50000 - rand(1000)
67
+ }
68
+ end.should raise_error Blather::Stream::ConnectionFailed
69
+ end
70
+
71
+ it 'starts the stream once the connection is complete' do
72
+ mocked_server(1) { |val, _| EM.stop; val.should match(/stream:stream/) }
73
+ end
74
+
75
+ it 'sends stanzas to the client when the stream is ready' do
76
+ @client = mock(:post_init)
77
+ @client.expects(:receive_data).with do |n|
78
+ EM.stop
79
+ n.kind_of? Blather::XMPPNode
80
+ end
81
+
82
+ state = nil
83
+ mocked_server(2) do |val, server|
84
+ case state
85
+ when nil
86
+ state = :started
87
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams' id='12345'>"
88
+ val.should match(/stream:stream/)
89
+
90
+ when :started
91
+ server.send_data '<handshake/>'
92
+ server.send_data "<message to='comp.id' from='d@e/f' type='chat' xml:lang='en'><body>Message!</body></message>"
93
+ val.should == "<handshake>#{Digest::SHA1.hexdigest('12345'+"secret")}</handshake>"
94
+
95
+ end
96
+ end
97
+ end
98
+
99
+ it 'sends stanzas to the wire ensuring "from" is set' do
100
+ client = mock()
101
+ client.stubs(:jid)
102
+ client.stubs(:jid=)
103
+ msg = Blather::Stanza::Message.new 'to@jid.com', 'body'
104
+ comp = Blather::Stream::Component.new nil, client, 'jid.com', 'pass'
105
+ comp.expects(:send_data).with { |s| s.should match(/^<message[^>]*from="jid\.com"/) }
106
+ comp.send msg
107
+ end
108
+ end
@@ -0,0 +1,152 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blather::Stream::Parser do
4
+ let :client do
5
+ Class.new do
6
+ attr_reader :data
7
+ attr_accessor :latch
8
+ def stopped?; false; end
9
+ def receive(node)
10
+ @data ||= []
11
+ @data << node
12
+ latch.countdown!
13
+ end
14
+ end.new
15
+ end
16
+
17
+ subject { Blather::Stream::Parser.new client }
18
+
19
+ def process(*data)
20
+ client.latch = CountDownLatch.new 1
21
+ data.each { |d| subject.receive_data d }
22
+ client.latch.wait(2).should be_true
23
+ end
24
+
25
+ def check_parse(data)
26
+ process data
27
+ client.data.size.should == 1
28
+ client.data[0].to_s.gsub(/\n\s*/,'').should == data
29
+ end
30
+
31
+ it 'handles fragmented parsing' do
32
+ process '<foo>', '<bar/>', '</foo>'
33
+ client.data.size.should == 1
34
+ client.data[0].to_s.gsub(/\n\s*/,'').should == '<foo><bar/></foo>'
35
+ end
36
+
37
+ it 'handles a basic example' do
38
+ check_parse "<foo/>"
39
+ end
40
+
41
+ it 'handles a basic namespace definition' do
42
+ check_parse '<foo xmlns="bar:baz"/>'
43
+ end
44
+
45
+ it 'handles multiple namespace definitions' do
46
+ check_parse '<foo xmlns="bar:baz" xmlns:bar="baz"/>'
47
+ end
48
+
49
+ it 'handles prefix namespacing' do
50
+ check_parse '<bar:foo xmlns="bar:baz" xmlns:bar="baz"/>'
51
+ end
52
+
53
+ it 'handles namespaces with children' do
54
+ check_parse "<foo xmlns=\"bar:baz\"><bar/></foo>"
55
+ end
56
+
57
+ it 'handles multiple namespaces with children' do
58
+ check_parse "<foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><bar/></foo>"
59
+ end
60
+
61
+ it 'handles prefix namespaces with children' do
62
+ check_parse "<bar:foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><bar/></bar:foo>"
63
+ end
64
+
65
+ it 'handles prefix namespaces with children in the namespace' do
66
+ check_parse "<bar:foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><bar:bar/></bar:foo>"
67
+ end
68
+
69
+ it 'handles prefix namespaces with children in the namespace' do
70
+ check_parse "<bar:foo xmlns=\"bar:baz\" xmlns:bar=\"baz\"><baz><bar:buz/></baz></bar:foo>"
71
+ end
72
+
73
+ it 'handles attributes' do
74
+ check_parse '<foo bar="baz"/>'
75
+ end
76
+
77
+ it 'handles attributes with entities properly' do
78
+ check_parse '<a href="http://example.com?a=1&amp;b=2">example</a>'
79
+ end
80
+
81
+ it 'handles character input' do
82
+ check_parse '<foo>bar baz fizbuz</foo>'
83
+ end
84
+
85
+ it 'handles a complex input' do
86
+ data = [
87
+ '<message type="error" id="another-id">',
88
+ '<error type="modify">',
89
+ '<undefined-condition xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>',
90
+ '<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Some special application diagnostic information...</text>',
91
+ '<special-application-condition xmlns="special:application-ns"/>',
92
+ "</error>",
93
+ "</message>"
94
+ ]
95
+ process *data
96
+ client.data.size.should == 1
97
+ Nokogiri::XML(client.data[0].to_s.gsub(/\n\s*/, '')).to_s.should == Nokogiri::XML(data.join).to_s
98
+ client.data[0].xpath('//*[namespace-uri()="urn:ietf:params:xml:ns:xmpp-stanzas"]').size.should == 2
99
+ end
100
+
101
+ it 'handles not absolute namespaces' do
102
+ lambda do
103
+ process '<iq type="result" id="blather0007" to="n@d/r"><vCard xmlns="vcard-temp"/></iq>'
104
+ end.should_not raise_error
105
+ end
106
+
107
+ it 'responds with stream:stream as a separate response' do
108
+ process '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
109
+ '<foo/>'
110
+ client.data.size.should == 2
111
+ client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.should == 1
112
+ client.data[1].to_s.should == '<foo/>'
113
+ end
114
+
115
+ it 'response with stream:end when receiving </stream:stream>' do
116
+ process '<stream:stream xmlns:stream="http://etherx.jabber.org/streams"/>'
117
+ client.data.size.should == 2
118
+ client.data[1].to_s.should == '<stream:end xmlns:stream="http://etherx.jabber.org/streams"/>'
119
+ end
120
+
121
+ it 'raises ParseError when an error is sent' do
122
+ lambda { process "<stream:stream>" }.should raise_error(Blather::ParseError)
123
+ end
124
+
125
+ it 'handles stream stanzas without an issue' do
126
+ process '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="example.com" version="1.0">',
127
+ '<stream:features/>'
128
+ client.data.size.should == 2
129
+ client.data[0].document.xpath('/stream:stream[@to="example.com" and @version="1.0"]', 'xmlns' => 'jabber:client', 'stream' => 'http://etherx.jabber.org/streams').size.should == 1
130
+ client.data[1].to_s.should == '<stream:features xmlns:stream="http://etherx.jabber.org/streams"/>'
131
+ end
132
+
133
+ it 'ignores the client namespace on stanzas' do
134
+ process "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:client'>",
135
+ "<body>exit</body>",
136
+ "<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>exit</body></html>",
137
+ "</message>"
138
+ client.data.size.should == 1
139
+ client.data[0].document.xpath('/message/body[.="exit"]').should_not be_empty
140
+ client.data[0].document.xpath('/message/im:html/xhtml:body[.="exit"]', 'im' => 'http://jabber.org/protocol/xhtml-im', 'xhtml' => 'http://www.w3.org/1999/xhtml').should_not be_empty
141
+ end
142
+
143
+ it 'ignores the component namespace on stanzas' do
144
+ process "<message type='chat' to='n@d' from='n@d/r' id='id1' xmlns='jabber:component:accept'>",
145
+ "<body>exit</body>",
146
+ "<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>exit</body></html>",
147
+ "</message>"
148
+ client.data.size.should == 1
149
+ client.data[0].document.xpath('/message/body[.="exit"]').should_not be_empty
150
+ client.data[0].document.xpath('/message/im:html/xhtml:body[.="exit"]', 'im' => 'http://jabber.org/protocol/xhtml-im', 'xhtml' => 'http://www.w3.org/1999/xhtml').should_not be_empty
151
+ end
152
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blather::CertStore do
4
+ before do
5
+ @pem = "-----BEGIN CERTIFICATE-----\nMIIDszCCApugAwIBAgIETiZC5TANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJV\nUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjEaMBgGA1UECgwR\nVmluZXMgWE1QUCBTZXJ2ZXIxFDASBgNVBAMMC3ZpbmVzLmxvY2FsMB4XDTExMDcx\nOTAyNTIyMVoXDTEyMDcxOTAyNTIyMVowYzELMAkGA1UEBhMCVVMxETAPBgNVBAgM\nCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxGjAYBgNVBAoMEVZpbmVzIFhNUFAg\nU2VydmVyMRQwEgYDVQQDDAt2aW5lcy5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAMyqj4UyXIpLYyIDaqDoN/8yZHDv281lz1UzuhPZ5r4S6teA\n90dXT6MxEoQ5vpRV2lVU21mDOoRPk9qjgGA01zimrX/YvPf2BBedFkvU18ZKiOMD\n7D89Ej2oIPLc6dJMiIx1SbfpdvUtVZFn1/jGvQPv5iajHW5n/zn1KrHOvVa6R5eY\nVGEH3DD3RkzSxWHyiNN8R5SQzyOVX9F4DVFAffPOLbkFsCi2POy3dp+ZWuYKEjBd\nMuRibrt87PCESnyXZx/Y+GBG856wQT8Ny6mmnh5z5YtopvAJh16ps2p6DFgyDtF+\nhaW3WMlStXYQPqSTrreD7qdAxi3rVft2OUJLTJkCAwEAAaNvMG0wDAYDVR0TBAUw\nAwEB/zAdBgNVHQ4EFgQUUCSlixByIPK3s20w4xHhcMax7igwPgYDVR0RBDcwNYIL\ndmluZXMubG9jYWyCJmNocmlzdG9waGVyLWpvaG5zb25zLW1hY2Jvb2stcHJvLmxv\nY2FsMA0GCSqGSIb3DQEBBQUAA4IBAQBOy1nI7H8XpnpVzpRK5RN/MzelQUl1Efo0\nl9wZ73E6EgJinl2AUp1/sYMUWkVlZ4DSflRBxBEp0CAJNoUydBh8O1xEKGTyqlLy\n/daqvNFLnYwFluAWi1xJQZv4AE62ua5wjsrhPuu3aMvPt9hx1X3CVh+8aA24/gAo\nAPJYsfT3T8GCD+MU3Uc2yADnLSUJ6Jal56/okOJA2Pfkr/K4zj1CyfAEWlpgo2Pv\nyrpv4V2WP1SL5fOONNGfOzio1LD6seAl+8SjiCefnMan2aXmna6SpMDzXB8vTDUE\nWmsD9g0621WqNz2x6lY5IYr7azE2C46Tpb9FOeSAAd83Zka4acaL\n-----END CERTIFICATE-----\n"
6
+ @cert = File.open("./test.crt", 'w') {|f| f.write(@pem) }
7
+ @store = Blather::CertStore.new("./")
8
+ end
9
+
10
+ after do
11
+ File.delete("./test.crt")
12
+ end
13
+
14
+ it 'can verify valid cert' do
15
+ @store.trusted?(@pem).tap do |trusted|
16
+ trusted.should == true
17
+ end
18
+ end
19
+
20
+ it 'can verify invalid cert' do
21
+ @store.trusted?(@pem.gsub("L", "a")).tap do |trusted|
22
+ trusted.should == nil
23
+ end
24
+ end
25
+
26
+ it 'can verify without a cert store' do
27
+ @store = Blather::CertStore.new("../")
28
+ @store.trusted?(@pem).tap do |trusted|
29
+ trusted.should == true
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blather::XMPPNode do
4
+ before { @doc = Nokogiri::XML::Document.new }
5
+
6
+ it 'generates a node based on the registered_name' do
7
+ foo = Class.new(Blather::XMPPNode)
8
+ foo.registered_name = 'foo'
9
+ foo.new.element_name.should == 'foo'
10
+ end
11
+
12
+ it 'sets the namespace on creation' do
13
+ foo = Class.new(Blather::XMPPNode)
14
+ foo.registered_ns = 'foo'
15
+ foo.new('foo').namespace.href.should == 'foo'
16
+ end
17
+
18
+ it 'registers sub classes' do
19
+ class RegistersSubClass < Blather::XMPPNode; register 'foo', 'foo:bar'; end
20
+ RegistersSubClass.registered_name.should == 'foo'
21
+ RegistersSubClass.registered_ns.should == 'foo:bar'
22
+ Blather::XMPPNode.class_from_registration('foo', 'foo:bar').should == RegistersSubClass
23
+ end
24
+
25
+ it 'imports another node' do
26
+ class ImportSubClass < Blather::XMPPNode; register 'foo', 'foo:bar'; end
27
+ n = Blather::XMPPNode.new('foo')
28
+ n.namespace = 'foo:bar'
29
+ Blather::XMPPNode.import(n).should be_kind_of ImportSubClass
30
+ end
31
+
32
+ it 'can convert itself into a stanza' do
33
+ class StanzaConvert < Blather::XMPPNode; register 'foo'; end
34
+ n = Blather::XMPPNode.new('foo')
35
+ n.to_stanza.should be_kind_of StanzaConvert
36
+ end
37
+
38
+ it 'can parse a string and import it' do
39
+ class StanzaParse < Blather::XMPPNode; register 'foo'; end
40
+ string = '<foo/>'
41
+ n = Nokogiri::XML(string).root
42
+ i = Blather::XMPPNode.import n
43
+ i.should be_kind_of StanzaParse
44
+ p = Blather::XMPPNode.parse string
45
+ p.should be_kind_of StanzaParse
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blather do
4
+
5
+ describe "while accessing to Logger object" do
6
+ it "should return a Logger instance" do
7
+ Blather.logger.should be_instance_of Logger
8
+ end
9
+
10
+ it "should config log level to info by default" do
11
+ Blather.logger.level.should == 1
12
+ end
13
+ end
14
+
15
+ describe "while using the log method" do
16
+ after do
17
+ Blather.default_log_level = :debug
18
+ end
19
+
20
+ it "should forward to debug by default" do
21
+ Blather.logger.expects(:debug).with("foo bar").once
22
+ Blather.log "foo bar"
23
+ end
24
+
25
+ %w<debug info error fatal>.each do |val|
26
+ it "should forward to #{val} if configured that default level" do
27
+ Blather.logger.expects(val.to_sym).with("foo bar").once
28
+ Blather.default_log_level = val.to_sym
29
+ Blather.log "foo bar"
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,311 @@
1
+ def items_all_nodes_xml
2
+ <<-ITEMS
3
+ <iq type='result'
4
+ from='pubsub.shakespeare.lit'
5
+ to='francisco@denmark.lit/barracks'
6
+ id='items1'>
7
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
8
+ <items node='princely_musings'>
9
+ <item id='368866411b877c30064a5f62b917cffe'>
10
+ <entry xmlns='http://www.w3.org/2005/Atom'>
11
+ <title>The Uses of This World</title>
12
+ <summary>
13
+ O, that this too too solid flesh would melt
14
+ Thaw and resolve itself into a dew!
15
+ </summary>
16
+ <link rel='alternate' type='text/html'
17
+ href='http://denmark.lit/2003/12/13/atom03'/>
18
+ <id>tag:denmark.lit,2003:entry-32396</id>
19
+ <published>2003-12-12T17:47:23Z</published>
20
+ <updated>2003-12-12T17:47:23Z</updated>
21
+ </entry>
22
+ </item>
23
+ <item id='3300659945416e274474e469a1f0154c'>
24
+ <entry xmlns='http://www.w3.org/2005/Atom'>
25
+ <title>Ghostly Encounters</title>
26
+ <summary>
27
+ O all you host of heaven! O earth! what else?
28
+ And shall I couple hell? O, fie! Hold, hold, my heart;
29
+ And you, my sinews, grow not instant old,
30
+ But bear me stiffly up. Remember thee!
31
+ </summary>
32
+ <link rel='alternate' type='text/html'
33
+ href='http://denmark.lit/2003/12/13/atom03'/>
34
+ <id>tag:denmark.lit,2003:entry-32396</id>
35
+ <published>2003-12-12T23:21:34Z</published>
36
+ <updated>2003-12-12T23:21:34Z</updated>
37
+ </entry>
38
+ </item>
39
+ <item id='4e30f35051b7b8b42abe083742187228'>
40
+ <entry xmlns='http://www.w3.org/2005/Atom'>
41
+ <title>Alone</title>
42
+ <summary>
43
+ Now I am alone.
44
+ O, what a rogue and peasant slave am I!
45
+ </summary>
46
+ <link rel='alternate' type='text/html'
47
+ href='http://denmark.lit/2003/12/13/atom03'/>
48
+ <id>tag:denmark.lit,2003:entry-32396</id>
49
+ <published>2003-12-13T11:09:53Z</published>
50
+ <updated>2003-12-13T11:09:53Z</updated>
51
+ </entry>
52
+ </item>
53
+ <item id='ae890ac52d0df67ed7cfdf51b644e901'>
54
+ <entry xmlns='http://www.w3.org/2005/Atom'>
55
+ <title>Soliloquy</title>
56
+ <summary>
57
+ To be, or not to be: that is the question:
58
+ Whether 'tis nobler in the mind to suffer
59
+ The slings and arrows of outrageous fortune,
60
+ Or to take arms against a sea of troubles,
61
+ And by opposing end them?
62
+ </summary>
63
+ <link rel='alternate' type='text/html'
64
+ href='http://denmark.lit/2003/12/13/atom03'/>
65
+ <id>tag:denmark.lit,2003:entry-32397</id>
66
+ <published>2003-12-13T18:30:02Z</published>
67
+ <updated>2003-12-13T18:30:02Z</updated>
68
+ </entry>
69
+ </item>
70
+ </items>
71
+ </pubsub>
72
+ </iq>
73
+ ITEMS
74
+ end
75
+
76
+ def pubsub_items_some_xml
77
+ <<-ITEMS
78
+ <iq type='result'
79
+ from='pubsub.shakespeare.lit'
80
+ to='francisco@denmark.lit/barracks'
81
+ id='items1'>
82
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
83
+ <items node='princely_musings'>
84
+ <item id='368866411b877c30064a5f62b917cffe'>
85
+ <entry xmlns='http://www.w3.org/2005/Atom'>
86
+ <title>The Uses of This World</title>
87
+ <summary>
88
+ O, that this too too solid flesh would melt
89
+ Thaw and resolve itself into a dew!
90
+ </summary>
91
+ <link rel='alternate' type='text/html'
92
+ href='http://denmark.lit/2003/12/13/atom03'/>
93
+ <id>tag:denmark.lit,2003:entry-32396</id>
94
+ <published>2003-12-12T17:47:23Z</published>
95
+ <updated>2003-12-12T17:47:23Z</updated>
96
+ </entry>
97
+ </item>
98
+ <item id='3300659945416e274474e469a1f0154c'>
99
+ <entry xmlns='http://www.w3.org/2005/Atom'>
100
+ <title>Ghostly Encounters</title>
101
+ <summary>
102
+ O all you host of heaven! O earth! what else?
103
+ And shall I couple hell? O, fie! Hold, hold, my heart;
104
+ And you, my sinews, grow not instant old,
105
+ But bear me stiffly up. Remember thee!
106
+ </summary>
107
+ <link rel='alternate' type='text/html'
108
+ href='http://denmark.lit/2003/12/13/atom03'/>
109
+ <id>tag:denmark.lit,2003:entry-32396</id>
110
+ <published>2003-12-12T23:21:34Z</published>
111
+ <updated>2003-12-12T23:21:34Z</updated>
112
+ </entry>
113
+ </item>
114
+ <item id='4e30f35051b7b8b42abe083742187228'>
115
+ <entry xmlns='http://www.w3.org/2005/Atom'>
116
+ <title>Alone</title>
117
+ <summary>
118
+ Now I am alone.
119
+ O, what a rogue and peasant slave am I!
120
+ </summary>
121
+ <link rel='alternate' type='text/html'
122
+ href='http://denmark.lit/2003/12/13/atom03'/>
123
+ <id>tag:denmark.lit,2003:entry-32396</id>
124
+ <published>2003-12-13T11:09:53Z</published>
125
+ <updated>2003-12-13T11:09:53Z</updated>
126
+ </entry>
127
+ </item>
128
+ </items>
129
+ <set xmlns='http://jabber.org/protocol/rsm'>
130
+ <first index='0'>368866411b877c30064a5f62b917cffe</first>
131
+ <last>4e30f35051b7b8b42abe083742187228</last>
132
+ <count>19</count>
133
+ </set>
134
+ </pubsub>
135
+ </iq>
136
+ ITEMS
137
+ end
138
+
139
+ def affiliations_xml
140
+ <<-NODE
141
+ <iq type='result'
142
+ from='pubsub.shakespeare.lit'
143
+ to='francisco@denmark.lit'
144
+ id='affil1'>
145
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
146
+ <affiliations>
147
+ <affiliation node='node1' affiliation='owner'/>
148
+ <affiliation node='node2' affiliation='owner'/>
149
+ <affiliation node='node3' affiliation='publisher'/>
150
+ <affiliation node='node4' affiliation='outcast'/>
151
+ <affiliation node='node5' affiliation='member'/>
152
+ <affiliation node='node6' affiliation='none'/>
153
+ </affiliations>
154
+ </pubsub>
155
+ </iq>
156
+ NODE
157
+ end
158
+
159
+ def subscriptions_xml
160
+ <<-NODE
161
+ <iq type='result'
162
+ from='pubsub.shakespeare.lit'
163
+ to='francisco@denmark.lit'
164
+ id='affil1'>
165
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
166
+ <subscriptions>
167
+ <subscription node='node1' jid='francisco@denmark.lit' subscription='subscribed' subid='fd8237yr872h3f289j2'/>
168
+ <subscription node='node2' jid='francisco@denmark.lit' subscription='subscribed' subid='h8394hf8923ju'/>
169
+ <subscription node='node3' jid='francisco@denmark.lit' subscription='unconfigured'/>
170
+ <subscription node='node4' jid='francisco@denmark.lit' subscription='pending'/>
171
+ <subscription node='node5' jid='francisco@denmark.lit' subscription='none'/>
172
+ </subscriptions>
173
+ </pubsub>
174
+ </iq>
175
+ NODE
176
+ end
177
+
178
+ def event_with_payload_xml
179
+ <<-NODE
180
+ <message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
181
+ <event xmlns='http://jabber.org/protocol/pubsub#event'>
182
+ <items node='princely_musings'>
183
+ <item id='ae890ac52d0df67ed7cfdf51b644e901'>
184
+ <entry xmlns='http://www.w3.org/2005/Atom'>
185
+ <title>Soliloquy</title>
186
+ <summary>
187
+ To be, or not to be: that is the question:
188
+ Whether 'tis nobler in the mind to suffer
189
+ The slings and arrows of outrageous fortune,
190
+ Or to take arms against a sea of troubles,
191
+ And by opposing end them?
192
+ </summary>
193
+ <link rel='alternate' type='text/html'
194
+ href='http://denmark.lit/2003/12/13/atom03'/>
195
+ <id>tag:denmark.lit,2003:entry-32397</id>
196
+ <published>2003-12-13T18:30:02Z</published>
197
+ <updated>2003-12-13T18:30:02Z</updated>
198
+ </entry>
199
+ </item>
200
+ </items>
201
+ </event>
202
+ </message>
203
+ NODE
204
+ end
205
+
206
+ def event_notification_xml
207
+ <<-NODE
208
+ <message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
209
+ <event xmlns='http://jabber.org/protocol/pubsub#event'>
210
+ <items node='princely_musings'>
211
+ <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
212
+ </items>
213
+ </event>
214
+ </message>
215
+ NODE
216
+ end
217
+
218
+ def event_subids_xml
219
+ <<-NODE
220
+ <message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
221
+ <event xmlns='http://jabber.org/protocol/pubsub#event'>
222
+ <items node='princely_musings'>
223
+ <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
224
+ </items>
225
+ </event>
226
+ <headers xmlns='http://jabber.org/protocol/shim'>
227
+ <header name='SubID'>123-abc</header>
228
+ <header name='SubID'>004-yyy</header>
229
+ </headers>
230
+ </message>
231
+ NODE
232
+ end
233
+
234
+ def unsubscribe_xml
235
+ <<-NODE
236
+ <iq type='error'
237
+ from='pubsub.shakespeare.lit'
238
+ to='francisco@denmark.lit/barracks'
239
+ id='unsub1'>
240
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
241
+ <unsubscribe node='princely_musings' jid='francisco@denmark.lit'/>
242
+ </pubsub>
243
+ <error type='modify'>
244
+ <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
245
+ <subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
246
+ </error>
247
+ </iq>
248
+ NODE
249
+ end
250
+
251
+ def subscription_xml
252
+ <<-NODE
253
+ <iq type='result'
254
+ from='pubsub.shakespeare.lit'
255
+ to='francisco@denmark.lit/barracks'
256
+ id='sub1'>
257
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
258
+ <subscription
259
+ node='princely_musings'
260
+ jid='francisco@denmark.lit'
261
+ subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
262
+ subscription='subscribed'/>
263
+ </pubsub>
264
+ </iq>
265
+ NODE
266
+ end
267
+
268
+ def subscribe_xml
269
+ <<-NODE
270
+ <iq type='set'
271
+ from='francisco@denmark.lit/barracks'
272
+ to='pubsub.shakespeare.lit'
273
+ id='sub1'>
274
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
275
+ <subscribe
276
+ node='princely_musings'
277
+ jid='francisco@denmark.lit'/>
278
+ </pubsub>
279
+ </iq>
280
+ NODE
281
+ end
282
+
283
+ def publish_xml
284
+ <<-NODE
285
+ <iq type='result'
286
+ from='pubsub.shakespeare.lit'
287
+ to='hamlet@denmark.lit/blogbot'
288
+ id='publish1'>
289
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
290
+ <publish node='princely_musings'>
291
+ <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
292
+ </publish>
293
+ </pubsub>
294
+ </iq>
295
+ NODE
296
+ end
297
+
298
+ def retract_xml
299
+ <<-NODE
300
+ <iq type='set'
301
+ from='hamlet@denmark.lit/elsinore'
302
+ to='pubsub.shakespeare.lit'
303
+ id='retract1'>
304
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
305
+ <retract node='princely_musings'>
306
+ <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
307
+ </retract>
308
+ </pubsub>
309
+ </iq>
310
+ NODE
311
+ end