xmpp4r 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/ChangeLog +12 -0
  2. data/Rakefile +2 -4
  3. data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +6 -6
  4. data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +3 -3
  5. data/data/doc/xmpp4r/examples/advanced/minimuc.rb +5 -5
  6. data/data/doc/xmpp4r/examples/advanced/xmpping.rb +17 -4
  7. data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +5 -0
  8. data/data/doc/xmpp4r/examples/basic/echo_threaded.rb +6 -2
  9. data/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +13 -0
  10. data/lib/xmpp4r.rb +0 -6
  11. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +6 -7
  12. data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +5 -6
  13. data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +3 -5
  14. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +1 -1
  15. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +10 -8
  16. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +3 -5
  17. data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +11 -17
  18. data/lib/xmpp4r/bytestreams/iq/si.rb +13 -32
  19. data/lib/xmpp4r/callbacks.rb +124 -0
  20. data/lib/xmpp4r/client.rb +2 -5
  21. data/lib/xmpp4r/command/helper/responder.rb +53 -0
  22. data/lib/xmpp4r/command/iq/command.rb +154 -0
  23. data/lib/xmpp4r/connection.rb +49 -12
  24. data/lib/xmpp4r/dataforms/x/data.rb +66 -29
  25. data/lib/xmpp4r/delay/x/delay.rb +2 -3
  26. data/lib/xmpp4r/discovery/iq/discoinfo.rb +20 -33
  27. data/lib/xmpp4r/discovery/iq/discoitems.rb +5 -28
  28. data/lib/xmpp4r/error.rb +5 -10
  29. data/lib/xmpp4r/feature_negotiation/iq/feature.rb +2 -20
  30. data/lib/xmpp4r/httpbinding.rb +5 -0
  31. data/lib/xmpp4r/httpbinding/client.rb +285 -0
  32. data/lib/xmpp4r/iq.rb +22 -41
  33. data/lib/xmpp4r/message.rb +8 -38
  34. data/lib/xmpp4r/muc.rb +2 -0
  35. data/lib/xmpp4r/muc/helper/mucclient.rb +50 -1
  36. data/lib/xmpp4r/muc/helper/simplemucclient.rb +2 -2
  37. data/lib/xmpp4r/muc/iq/mucowner.rb +11 -0
  38. data/lib/xmpp4r/muc/x/muc.rb +2 -30
  39. data/lib/xmpp4r/muc/x/mucuserinvite.rb +4 -2
  40. data/lib/xmpp4r/muc/x/mucuseritem.rb +4 -2
  41. data/lib/xmpp4r/presence.rb +7 -35
  42. data/lib/xmpp4r/pubsub.rb +1 -0
  43. data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +174 -0
  44. data/lib/xmpp4r/pubsub/helper/nodehelper.rb +153 -0
  45. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +326 -0
  46. data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  47. data/lib/xmpp4r/pubsub/stanzas/event.rb +49 -0
  48. data/lib/xmpp4r/pubsub/stanzas/item.rb +27 -0
  49. data/lib/xmpp4r/pubsub/stanzas/items.rb +35 -0
  50. data/lib/xmpp4r/pubsub/stanzas/subscription.rb +58 -0
  51. data/lib/xmpp4r/query.rb +4 -32
  52. data/lib/xmpp4r/rexmladdons.rb +7 -772
  53. data/lib/xmpp4r/roster/helper/roster.rb +29 -50
  54. data/lib/xmpp4r/roster/iq/roster.rb +6 -35
  55. data/lib/xmpp4r/roster/x/roster.rb +13 -30
  56. data/lib/xmpp4r/rpc.rb +2 -0
  57. data/lib/xmpp4r/rpc/helper/client.rb +114 -0
  58. data/lib/xmpp4r/rpc/helper/server.rb +75 -0
  59. data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +57 -0
  60. data/lib/xmpp4r/rpc/iq/rpc.rb +24 -0
  61. data/lib/xmpp4r/sasl.rb +1 -1
  62. data/lib/xmpp4r/semaphore.rb +38 -0
  63. data/lib/xmpp4r/stream.rb +104 -165
  64. data/lib/xmpp4r/streamparser.rb +2 -2
  65. data/lib/xmpp4r/vcard/iq/vcard.rb +5 -12
  66. data/lib/xmpp4r/version/helper/responder.rb +2 -1
  67. data/lib/xmpp4r/version/iq/version.rb +6 -18
  68. data/lib/xmpp4r/x.rb +20 -26
  69. data/lib/xmpp4r/xmpp4r.rb +1 -1
  70. data/lib/xmpp4r/xmppelement.rb +152 -0
  71. data/lib/xmpp4r/{xmlstanza.rb → xmppstanza.rb} +17 -29
  72. data/setup.rb +1 -0
  73. data/test/bytestreams/tc_ibb.rb +8 -8
  74. data/test/dataforms/tc_data.rb +81 -0
  75. data/test/lib/clienttester.rb +20 -17
  76. data/test/muc/tc_muc_mucclient.rb +48 -23
  77. data/test/muc/tc_muc_simplemucclient.rb +7 -4
  78. data/test/muc/tc_mucowner.rb +50 -0
  79. data/test/pubsub/tc_helper.rb +227 -0
  80. data/test/roster/tc_helper.rb +181 -55
  81. data/test/roster/tc_iqqueryroster.rb +33 -0
  82. data/test/roster/tc_xroster.rb +6 -3
  83. data/test/rpc/tc_helper.rb +84 -0
  84. data/test/tc_callbacks.rb +2 -1
  85. data/test/tc_class_names.rb +9 -1
  86. data/test/tc_error.rb +1 -0
  87. data/test/tc_iq.rb +13 -12
  88. data/test/tc_message.rb +1 -0
  89. data/test/tc_presence.rb +1 -0
  90. data/test/tc_rexml.rb +1 -1
  91. data/test/tc_stream.rb +147 -102
  92. data/test/tc_streamComponent.rb +94 -0
  93. data/test/tc_streamError.rb +67 -29
  94. data/test/tc_streamSend.rb +1 -1
  95. data/test/tc_xmppstanza.rb +125 -0
  96. data/test/ts_xmpp4r.rb +37 -28
  97. data/test/version/tc_helper.rb +14 -0
  98. data/test/version/tc_iqqueryversion.rb +4 -3
  99. metadata +163 -123
  100. data/data/doc/xmpp4r/examples/basic/echo_nonthreaded.rb +0 -32
  101. data/lib/callbacks.rb +0 -122
  102. data/test/tc_streamThreaded.rb +0 -168
  103. data/test/tc_xmlstanza.rb +0 -76
@@ -0,0 +1,326 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+ #
5
+ # It's recommented to read the XEP-0066 before you use this Helper.
6
+ #
7
+
8
+ require 'xmpp4r/pubsub/iq/pubsub'
9
+ require 'xmpp4r/pubsub/stanzas/event'
10
+ require 'xmpp4r/pubsub/stanzas/item'
11
+ require 'xmpp4r/pubsub/stanzas/items'
12
+ require 'xmpp4r/pubsub/stanzas/subscription'
13
+ require 'xmpp4r/dataforms'
14
+
15
+ module Jabber
16
+ module PubSub
17
+ ##
18
+ # A Helper representing a PubSub Service
19
+ class ServiceHelper
20
+
21
+ ##
22
+ # Creates a new representation of a pubsub service
23
+ # client:: [Jabber::Stream]
24
+ # pubsubjid:: [String] or [Jabber::JID]
25
+ def initialize(client, pubsubjid)
26
+ @client = client
27
+ @pubsubjid = pubsubjid
28
+ @event_cbs = CallbackList.new
29
+ @client.add_message_callback(200,self) { |message|
30
+ handle_message(message)
31
+ }
32
+ end
33
+
34
+ ##
35
+ # Create a new node on the pubsub service
36
+ # node:: [String] you node name - otherwise you get a automaticly generated one (in most cases)
37
+ # configure:: [Jabber::XMLStanza] if you want to configure you node (default nil)
38
+ # return:: [String]
39
+ def create(node=nil, configure=nil)
40
+ rnode = nil
41
+ iq = basic_pubsub_query(:set)
42
+ iq.pubsub.add(REXML::Element.new('create')).attributes['node'] = node
43
+ if configure
44
+ confele = REXML::Element.new('configure')
45
+
46
+ if configure.type_of?(XMLStanza)
47
+ confele << configure
48
+ end
49
+ iq.pubsub.add(confele)
50
+ end
51
+
52
+ @client.send_with_id(iq) do |reply|
53
+ if (create = reply.first_element('pubsub/create'))
54
+ rnode = create.attributes['node']
55
+ end
56
+ true
57
+ end
58
+
59
+ rnode
60
+ end
61
+
62
+ ##
63
+ # Delete a pubsub node
64
+ # node:: [String]
65
+ # return:: true
66
+ def delete(node)
67
+ iq = basic_pubsub_query(:set,true)
68
+ iq.pubsub.add(REXML::Element.new('delete')).attributes['node'] = node
69
+ @client.send_with_id(iq) { |reply|
70
+ true
71
+ }
72
+ end
73
+
74
+ ##
75
+ # NOTE: this method sends only one item per publish request because some services may not
76
+ # allow batch processing
77
+ # maybe this will changed in the future
78
+ # node:: [String]
79
+ # item:: [Jabber::PubSub::Item]
80
+ # return:: true
81
+ def publish(node,item)
82
+ iq = basic_pubsub_query(:set)
83
+ publish = iq.pubsub.add(REXML::Element.new('publish'))
84
+ publish.attributes['node'] = node
85
+ if item.kind_of?(Jabber::PubSub::Item)
86
+ publish.add(item)
87
+ @client.send_with_id(iq) { |reply| true }
88
+ end
89
+ end
90
+
91
+ ##
92
+ # node:: [String]
93
+ # item:: [REXML::Element]
94
+ # id:: [String]
95
+ # return:: true
96
+ def publish_with_id(node,item,id)
97
+ if item.kind_of?(REXML::Element)
98
+ xmlitem = Jabber::PubSub::Item.new
99
+ xmlitem.id = id
100
+ xmlitem.add(item)
101
+ publish(node,xmlitem)
102
+ else
103
+ raise "given item is not a proper xml document or Jabber::PubSub::Item"
104
+ end
105
+ end
106
+
107
+ ##
108
+ # gets all items from a pubsub node
109
+ # node:: [String]
110
+ # count:: [Fixnum]
111
+ # return:: [Hash] { id => [Jabber::PubSub::Item] }
112
+ def items(node,count=nil)
113
+ iq = basic_pubsub_query(:get)
114
+ items = Jabber::PubSub::Items.new
115
+ items.node = node
116
+ iq.pubsub.add(items)
117
+ res = nil
118
+ @client.send_with_id(iq) { |reply|
119
+ if reply.kind_of?(Iq) and reply.pubsub and reply.pubsub.first_element('items')
120
+ res = {}
121
+ reply.pubsub.first_element('items').each_element('item') do |item|
122
+ res[item.attributes['id']] = item.children.first if item.children.first
123
+ end
124
+ end
125
+ true
126
+ }
127
+ res
128
+ end
129
+
130
+ ##
131
+ # shows the affiliations on a pubsub service
132
+ # return:: [Hash] of { node => symbol }
133
+ def affiliations
134
+ iq = basic_pubsub_query(:get)
135
+ iq.pubsub.add(REXML::Element.new('affiliations'))
136
+ res = nil
137
+ @client.send_with_id(iq) { |reply|
138
+ if reply.pubsub.first_element('affiliations')
139
+ res = {}
140
+ reply.pubsub.first_element('affiliations').each_element('affiliation') do |affiliation|
141
+ # TODO: This should be handled by an affiliation element class
142
+ aff = case affiliation.attributes['affiliation']
143
+ when 'owner' then :owner
144
+ when 'publisher' then :publisher
145
+ when 'none' then :none
146
+ when 'outcast' then :outcast
147
+ else nil
148
+ end
149
+ res[affiliation.attributes['node']] = aff
150
+ end
151
+ end
152
+ true
153
+ }
154
+ res
155
+ end
156
+
157
+ ##
158
+ # shows all subscriptions on the given node
159
+ # node:: [String], or nil for all
160
+ # return:: [Array] of [REXML::Element]
161
+ def subscriptions(node=nil)
162
+ iq = basic_pubsub_query(:get)
163
+ entities = iq.pubsub.add(REXML::Element.new('subscriptions'))
164
+ entities.attributes['node'] = node
165
+ res = nil
166
+ @client.send_with_id(iq) { |reply|
167
+ if reply.pubsub.first_element('subscriptions')
168
+ res = []
169
+ reply.pubsub.first_element('subscriptions').each_element('subscription') { |subscription|
170
+ res << REXML::Element.new(subscription)
171
+ }
172
+ end
173
+ true
174
+ }
175
+ res
176
+ end
177
+
178
+ ##
179
+ # shows all jids of subscribers of a node
180
+ # node:: [String]
181
+ # return:: [Array] of [String]
182
+ def subscribers(node)
183
+ res = []
184
+ subscriptions(node).each { |sub|
185
+ res << sub.attributes['jid']
186
+ }
187
+ res
188
+ end
189
+
190
+ ##
191
+ # subscribe to a node
192
+ # node:: [String]
193
+ # return:: [Hash] of { attributename => value }
194
+ def subscribe(node)
195
+ iq = basic_pubsub_query(:set)
196
+ sub = REXML::Element.new('subscribe')
197
+ sub.attributes['node'] = node
198
+ sub.attributes['jid'] = @client.jid.strip
199
+ iq.pubsub.add(sub)
200
+ res = {}
201
+ @client.send_with_id(iq) do |reply|
202
+ pubsubanswer = reply.pubsub
203
+ if pubsubanswer.first_element('subscription')
204
+ pubsubanswer.each_element('subscription') { |element|
205
+ element.attributes.each { |name,value| res[name] = value }
206
+ }
207
+ end
208
+ true
209
+ end # @client.send_with_id(iq)
210
+ res
211
+ end
212
+
213
+ ##
214
+ # Unsubscibe from a node with an optional subscription id
215
+ #
216
+ # May raise ErrorException
217
+ # node:: [String]
218
+ # subid:: [String] or nil
219
+ # return:: true
220
+ def unsubscribe(node,subid=nil)
221
+ iq = basic_pubsub_query(:set)
222
+ unsub = REXML::Element.new('unsubscribe')
223
+ unsub.attributes['node'] = node
224
+ unsub.attributes['jid'] = @client.jid.strip
225
+ unsub.attributes['subid'] = subid
226
+ iq.pubsub.add(unsub)
227
+ @client.send_with_id(iq) { |reply| true } # @client.send_with_id(iq)
228
+ end
229
+
230
+ ##
231
+ # get options of a node
232
+ # node:: [String]
233
+ # subid:: [String] or nil
234
+ # return:: [Jabber::XData]
235
+ def get_options(node,subid=nil)
236
+ iq = basic_pubsub_query(:get)
237
+ opt = REXML::Element.new('options')
238
+ opt.attributes['node'] = node
239
+ opt.attributes['jid'] = @client.jid.strip
240
+ opt.attributes['subid'] = subid
241
+ iq.pubsub.add(opt)
242
+ ret = nil
243
+ @client.send_with_id(iq) { |reply|
244
+ reply.pubsub.options.first_element('x') { |xdata|
245
+
246
+ ret = xdata if xdata.kind_of?(Jabber::XData)
247
+
248
+ }
249
+ true
250
+ }
251
+ return ret
252
+ end
253
+
254
+ ##
255
+ # set options for a node
256
+ # node:: [String]
257
+ # options:: [Jabber::XData]
258
+ # subid:: [String] or nil
259
+ # return:: true
260
+ def set_options(node,options,subid=nil)
261
+ iq = basic_pubsub_query(:set)
262
+ opt = REXML::Element.new('options')
263
+ opt.attributes['node'] = node
264
+ opt.attributes['jid'] = @client.jid.strip
265
+ opt.attributes['subid'] = subid
266
+ iq.pubsub.add(opt)
267
+ iq.pubsub.options.add(options)
268
+ @client.send_with_id(iq) { |reply| true }
269
+ end
270
+
271
+ ##
272
+ # purges all items on a persist node
273
+ # node:: [String]
274
+ # return:: true
275
+ def purge(node)
276
+ iq = basic_pubsub_query(:set)
277
+ purge = REXML::Element.new('purge')
278
+ purge.attributes['node'] = node
279
+ iq.pubsub.add(purge)
280
+ @client.send_with_id(iq) { |reply| true }
281
+ end
282
+
283
+ ##
284
+ # String representation
285
+ # result:: [String] The PubSub service's JID
286
+ def to_s
287
+ @pubsubjid.to_s
288
+ end
289
+
290
+ ##
291
+ # Register callbacks for incoming events
292
+ # (i.e. Message stanzas containing) PubSub notifications
293
+ def add_event_callback(prio = 200, ref = nil, &block)
294
+ @event_cbs.add(prio, ref, block)
295
+ end
296
+
297
+ private
298
+
299
+ ##
300
+ # creates a basic pubsub iq
301
+ # basic_pubsub_query(type)
302
+ # type:: [Symbol]
303
+ def basic_pubsub_query(type,ownerusecase = false)
304
+ iq = Jabber::Iq::new(type,@pubsubjid)
305
+ if ownerusecase
306
+ iq.add(IqPubSubOwner.new)
307
+ else
308
+ iq.add(IqPubSub.new)
309
+ end
310
+ iq
311
+ end
312
+
313
+ ##
314
+ # handling incoming events
315
+ # handle_message(message)
316
+ # message:: [Jabber::Message]
317
+ def handle_message(message)
318
+ if message.from == @pubsubjid and message.first_element('event').kind_of?(Jabber::PubSub::Event)
319
+ event = message.first_element('event')
320
+ @event_cbs.process(event)
321
+ end
322
+ end
323
+
324
+ end
325
+ end
326
+ end
@@ -0,0 +1,19 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/iq'
6
+
7
+ module Jabber
8
+ module PubSub
9
+ NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
10
+ class IqPubSub < XMPPElement
11
+ name_xmlns 'pubsub', NS_PUBSUB
12
+ force_xmlns true
13
+ end
14
+ class IqPubSubOwner < XMPPElement
15
+ name_xmlns 'pubsub', NS_PUBSUB + '#owner'
16
+ force_xmlns true
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/iq'
6
+
7
+ module Jabber
8
+ module PubSub
9
+
10
+ ##
11
+ # Event
12
+ # a publishing event
13
+ class Event < XMPPElement
14
+ name_xmlns 'event', NS_PUBSUB + '#event'
15
+ force_xmlns true
16
+
17
+ ##
18
+ # return payload
19
+ def payload
20
+ elements
21
+ end
22
+
23
+ ##
24
+ # add payload
25
+ # payload:: [REXML::Element]
26
+ def payload=(pl)
27
+ add_element = pl
28
+ end
29
+
30
+ ##
31
+ # return the payload type
32
+ def event_type?
33
+ # each child of event
34
+ # this should interate only one time
35
+ each_element('./event/*') { |plelement|
36
+ case plelement.name
37
+ when 'collection' then return :collection
38
+ when 'configuration' then return :configuration
39
+ when 'delete' then return :delete
40
+ when 'items' then return :items
41
+ when 'purge' then return :purge
42
+ when 'subscription' then return :subscription
43
+ else return nil
44
+ end
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/iq'
6
+
7
+ module Jabber
8
+ module PubSub
9
+ ##
10
+ # Item
11
+ # One PubSub Item
12
+ class Item < XMPPElement
13
+ name_xmlns 'item', NS_PUBSUB
14
+ force_xmlns true
15
+ def initialize(id=nil)
16
+ super()
17
+ attributes['id'] = id
18
+ end
19
+ def id
20
+ attributes['id']
21
+ end
22
+ def id=(myid)
23
+ attributes['id'] = myid
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/iq'
6
+
7
+ module Jabber
8
+ module PubSub
9
+ ##
10
+ # Items
11
+ # a collection of Items
12
+ class Items < XMPPElement
13
+ name_xmlns 'items', NS_PUBSUB
14
+ force_xmlns true
15
+ def node
16
+ attributes['node']
17
+ end
18
+ def node=(mynodename)
19
+ attributes['node'] = mynodename
20
+ end
21
+ def subid
22
+ attributes['subid']
23
+ end
24
+ def subid=(mysubid)
25
+ attributes['subid'] = mysubid
26
+ end
27
+ def max_items
28
+ attributes['max_items']
29
+ end
30
+ def max_items=(mymaxitems)
31
+ attributes['max_items'] = mymaxitems
32
+ end
33
+ end
34
+ end
35
+ end