xmpp4r 0.5 → 0.5.5

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 (41) hide show
  1. data/CHANGELOG +21 -0
  2. data/README.rdoc +29 -38
  3. data/Rakefile +11 -18
  4. data/data/doc/xmpp4r/examples/advanced/recvfile.rb +5 -4
  5. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +2 -0
  6. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +1 -0
  7. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +1 -1
  8. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +4 -1
  9. data/lib/xmpp4r/caps/helper/generator.rb +2 -2
  10. data/lib/xmpp4r/client.rb +18 -4
  11. data/lib/xmpp4r/connection.rb +8 -5
  12. data/lib/xmpp4r/delay/x/delay.rb +1 -1
  13. data/lib/xmpp4r/entity_time.rb +6 -0
  14. data/lib/xmpp4r/entity_time/iq.rb +45 -0
  15. data/lib/xmpp4r/entity_time/responder.rb +57 -0
  16. data/lib/xmpp4r/httpbinding/client.rb +178 -44
  17. data/lib/xmpp4r/message.rb +46 -0
  18. data/lib/xmpp4r/muc/helper/mucclient.rb +8 -1
  19. data/lib/xmpp4r/observable.rb +9 -0
  20. data/lib/xmpp4r/observable/contact.rb +61 -0
  21. data/lib/xmpp4r/observable/helper.rb +389 -0
  22. data/lib/xmpp4r/observable/observable_thing.rb +191 -0
  23. data/lib/xmpp4r/observable/pubsub.rb +211 -0
  24. data/lib/xmpp4r/observable/subscription.rb +57 -0
  25. data/lib/xmpp4r/observable/thread_store.rb +65 -0
  26. data/lib/xmpp4r/pubsub/children/unsubscribe.rb +16 -1
  27. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +48 -14
  28. data/lib/xmpp4r/rexmladdons.rb +46 -6
  29. data/lib/xmpp4r/roster/helper/roster.rb +19 -9
  30. data/lib/xmpp4r/sasl.rb +1 -1
  31. data/lib/xmpp4r/stream.rb +2 -2
  32. data/lib/xmpp4r/xmpp4r.rb +1 -1
  33. data/test/bytestreams/tc_socks5bytestreams.rb +2 -2
  34. data/test/entity_time/tc_responder.rb +65 -0
  35. data/test/roster/tc_helper.rb +2 -3
  36. data/test/tc_message.rb +52 -1
  37. data/test/tc_stream.rb +2 -2
  38. data/test/tc_streamComponent.rb +11 -1
  39. data/test/ts_xmpp4r.rb +11 -2
  40. data/xmpp4r.gemspec +20 -9
  41. metadata +41 -35
@@ -0,0 +1,191 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ #
3
+ # This file's copyright (c) 2009 by Pablo Lorenzzoni <pablo@propus.com.br>
4
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
5
+ # Website::http://home.gna.org/xmpp4r/
6
+ #
7
+ # This was based on Observable module from Ruby.
8
+ module ObservableThing
9
+ require 'xmpp4r/observable/thread_store'
10
+
11
+ # Adds an observer for some "thing".
12
+ #
13
+ # thing:: what will be observed.
14
+ # observer:: the observer.
15
+ # func:: the observer method that will be called (default: :update).
16
+ def add_observer(thing, observer, func = :update)
17
+ @things = {} unless defined? @things
18
+ @things[thing] = {} unless ! @things[thing].nil?
19
+ unless observer.respond_to? func
20
+ raise NoMethodError, "observer does not respond to `#{func.to_s}'"
21
+ end
22
+ @things[thing][observer] = func unless @things[thing].include?(observer)
23
+ end
24
+
25
+ # Deletes an observer for some "thing".
26
+ #
27
+ # thing:: what has been observed.
28
+ # observer:: the observer.
29
+ def delete_observer(thing, observer)
30
+ @things[thing].delete observer if defined? @things and ! @things[thing].nil?
31
+ end
32
+
33
+ # Delete observers for some "thing".
34
+ #
35
+ # thing:: what has been observed (if nil, deletes all observers).
36
+ def delete_observers(thing = nil)
37
+ if thing.nil?
38
+ @things.clear if defined? @things
39
+ else
40
+ @things[thing].clear if defined? @things and ! @things[thing].nil?
41
+ end
42
+ end
43
+
44
+ # Count the number of observers for some "thing".
45
+ #
46
+ # thing:: what has been observed (if nil, count all observers).
47
+ def count_observers(thing = nil)
48
+ return 0 if ! defined? @things
49
+ size = 0
50
+ if thing.nil?
51
+ @things.each { |thing, hash|
52
+ size += hash.size
53
+ }
54
+ else
55
+ size = @things[thing].size unless @things[thing].nil?
56
+ end
57
+ size
58
+ end
59
+
60
+ # Count the number of notifications for some "thing".
61
+ #
62
+ # thing:: what has been observed.
63
+ def count_notifications(thing)
64
+ return 0 if (! defined?(@things_counter)) or (! @things_counter.include?(thing))
65
+ @things_counter[thing]
66
+ end
67
+
68
+ # Change the state of some "thing".
69
+ #
70
+ # thing:: what will have the state changed.
71
+ # state:: the state (default = true).
72
+ def changed(thing, state = true)
73
+ @things_state = {} unless defined? @things_state
74
+ @things_state[thing] = state
75
+ end
76
+
77
+ # Check the state of some "thing".
78
+ #
79
+ # thing: what to have its state checked.
80
+ def changed?(thing)
81
+ if defined? @things_state and @things_state[thing]
82
+ true
83
+ else
84
+ false
85
+ end
86
+ end
87
+
88
+ # Notify all observers of "thing" about something. This will only be
89
+ # enforced if the state of that "thing" is true. Also, if the observer
90
+ # returns the Symbol :delete_me, it will be deleted after being notified.
91
+ #
92
+ # thing:: what has been observed.
93
+ # args:: notification to be sent to the observers of "thing".
94
+ def notify_observers(thing, *arg)
95
+ if changed?(thing)
96
+ if defined? @things and ! @things[thing].nil?
97
+ @things[thing].each { |observer, func|
98
+ increase_counter(thing)
99
+ @thread_store = ThreadStore.new if ! defined? @thread_store
100
+ @thread_store.add Thread.new {
101
+ if observer.send(func, thing, *arg) == :delete_me
102
+ delete_observer(thing, observer)
103
+ end
104
+ }
105
+ }
106
+ end
107
+ changed(thing, false)
108
+ end
109
+ end
110
+
111
+ # Is there pending notifications?
112
+ def pending_notifications?
113
+ return false if ! defined? @thread_store
114
+ @thread_store.size > 0
115
+ end
116
+
117
+ # Wait all notifications
118
+ def wait_notifications
119
+ sleep 1 while pending_notifications?
120
+ end
121
+
122
+ private
123
+ def increase_counter(thing)
124
+ @things_counter = {} unless defined? @things_counter
125
+ @things_counter[thing] = 0 unless @things_counter.include?(thing)
126
+ @things_counter[thing] += 1
127
+ end
128
+ end
129
+
130
+ # QObserver - simple observer-to-queue class
131
+ class QObserver
132
+ require 'thread'
133
+
134
+ def initialize
135
+ @queues = Hash.new
136
+ end
137
+
138
+ def inspect
139
+ h = {}
140
+ @queues.each do |q, queue|
141
+ h[q] = queue.size
142
+ end
143
+ if h.length > 0
144
+ sprintf("#<%s:0x%x size=%s>", self.class.name, __id__, h.inspect)
145
+ else
146
+ sprintf("#<%s:0x%x>", self.class.name, __id__)
147
+ end
148
+ end
149
+
150
+ # Return the queues we have registered
151
+ def queues
152
+ @queues.keys
153
+ end
154
+
155
+ # Received something in this queue?
156
+ #
157
+ # q:: queue
158
+ def received?(q)
159
+ @queues.include?(q) and ! @queues[q].empty?
160
+ end
161
+
162
+ # Get the contents of the queue in an array (or pass each item to the
163
+ # given block.
164
+ #
165
+ # q:: queue
166
+ def received(q)
167
+ return nil if ! @queues.include?(q)
168
+ if block_given?
169
+ yield @queues[q].deq while ! @queues[q].empty?
170
+ else
171
+ a = []
172
+ a << @queues[q].deq while ! @queues[q].empty?
173
+ return a
174
+ end
175
+ end
176
+
177
+ # Get the size of a given queue
178
+ #
179
+ # q:: queue
180
+ def size(q)
181
+ @queues[q].size rescue 0
182
+ end
183
+
184
+ # update method for our Observer
185
+ #
186
+ # thing:: what to be updated
187
+ def update(thing, *args)
188
+ @queues[thing] = Queue.new if ! @queues.include?(thing)
189
+ @queues[thing].enq args
190
+ end
191
+ end
@@ -0,0 +1,211 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ #
3
+ # This file's copyright (c) 2009 by Pablo Lorenzzoni <pablo@propus.com.br>
4
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
5
+ # Website::http://home.gna.org/xmpp4r/
6
+
7
+ require 'xmpp4r/pubsub'
8
+ require 'xmpp4r/pubsub/helper/servicehelper'
9
+ require 'xmpp4r/pubsub/helper/nodebrowser'
10
+ require 'xmpp4r/pubsub/helper/nodehelper'
11
+
12
+ module Jabber
13
+ class Observable
14
+ # Jabber::Observable::PubSub - Convenience subclass to deal with PubSub
15
+ class PubSub
16
+ class NoService < StandardError; end #:nodoc:
17
+
18
+ class AlreadySet < StandardError; end #:nodoc:
19
+
20
+ # Creates a new PubSub object
21
+ #
22
+ # observable:: points a Jabber::Observable object
23
+ def initialize(observable)
24
+ @observable = observable
25
+
26
+ @helper = @service_jid = nil
27
+ @disco = Jabber::Discovery::Helper.new(@observable.client)
28
+ attach!
29
+ end
30
+
31
+ def attach!
32
+ begin
33
+ domain = Jabber::JID.new(@observable.jid).domain
34
+ @service_jid = "pubsub." + domain
35
+ set_service(@service_jid)
36
+ rescue
37
+ @helper = @service_jid = nil
38
+ end
39
+ return has_service?
40
+ end
41
+
42
+ def inspect #:nodoc:
43
+ if has_service?
44
+ sprintf("#<%s:0x%x @service_jid=%s>", self.class.name, __id__, @service_jid)
45
+ else
46
+ sprintf("#<%s:0x%x @has_service?=false>", self.class.name, __id__)
47
+ end
48
+ end
49
+
50
+ # Checks if the PubSub service is set
51
+ def has_service?
52
+ ! @helper.nil?
53
+ end
54
+
55
+ # Sets the PubSub service. Just one service is allowed. If nil, reset.
56
+ def set_service(service)
57
+ if service.nil?
58
+ @helper = @service_jid = nil
59
+ else
60
+ raise NotConnected, "You are not connected" if ! @observable.connected?
61
+ raise AlreadySet, "You already have a PubSub service (#{@service_jid})." if has_service?
62
+ @helper = Jabber::PubSub::ServiceHelper.new(@observable.client, service)
63
+ @service_jid = service
64
+
65
+ @helper.add_event_callback do |event|
66
+ @observable.changed(:event)
67
+ @observable.notify_observers(:event, event)
68
+ end
69
+ end
70
+ end
71
+
72
+ # Subscribe to a node.
73
+ def subscribe_to(node)
74
+ raise_noservice if ! has_service?
75
+ @helper.subscribe_to(node) unless is_subscribed_to?(node)
76
+ end
77
+
78
+ # Unsubscribe from a node.
79
+ def unsubscribe_from(node)
80
+ raise_noservice if ! has_service?
81
+ @helper.unsubscribe_from(node)
82
+ end
83
+
84
+ # Return the subscriptions we have in the configured PubSub service.
85
+ def subscriptions
86
+ raise_noservice if ! has_service?
87
+ @helper.get_subscriptions_from_all_nodes()
88
+ end
89
+
90
+ # Create a PubSub node (Lots of options still have to be encoded!)
91
+ def create_node(node)
92
+ raise_noservice if ! has_service?
93
+ begin
94
+ @helper.create_node(node)
95
+ rescue => e
96
+ raise e
97
+ return nil
98
+ end
99
+ @my_nodes << node if defined? @my_nodes
100
+ node
101
+ end
102
+
103
+ # Return an array of nodes I own
104
+ def my_nodes
105
+ if ! defined? @my_nodes
106
+ ret = []
107
+ subscriptions.each do |sub|
108
+ ret << sub.node if sub.attributes['affiliation'] == 'owner'
109
+ end
110
+ @my_nodes = ret
111
+ end
112
+ return @my_nodes
113
+ end
114
+
115
+ # Return true if a given node exists
116
+ def node_exists?(node)
117
+ ret = []
118
+ if ! defined? @existing_nodes or ! @existing_nodes.include?(node)
119
+ # We'll renew @existing_nodes if we haven't got it the first time
120
+ reply = @disco.get_items_for(@service_jid)
121
+ reply.items.each do |item|
122
+ ret << item.node
123
+ end
124
+ @existing_nodes = ret
125
+ end
126
+ return @existing_nodes.include?(node)
127
+ end
128
+
129
+ # Returns an array of nodes I am subscribed to
130
+ def subscribed_nodes
131
+ ret = []
132
+ subscriptions.each do |sub|
133
+ next if sub.node.nil?
134
+ ret << sub.node if sub.attributes['subscription'] == 'subscribed' and ! my_nodes.include?(sub.node)
135
+ end
136
+ return ret
137
+ end
138
+
139
+ # Return true if we're subscribed to that node
140
+ def is_subscribed_to?(node)
141
+ ret = false
142
+ subscriptions.each do |sub|
143
+ ret = true if sub.node == node and sub.attributes['subscription'] == 'subscribed'
144
+ end
145
+ return ret
146
+ end
147
+
148
+ # Delete a PubSub node (Lots of options still have to be encoded!)
149
+ def delete_node(node)
150
+ raise_noservice if ! has_service?
151
+ begin
152
+ @helper.delete_node(node)
153
+ rescue => e
154
+ raise e
155
+ return nil
156
+ end
157
+ @my_nodes.delete(node) if defined? @my_nodes
158
+ node
159
+ end
160
+
161
+ # Publish an Item. This infers an item of Jabber::PubSub::Item kind is passed
162
+ def publish_item(node, item)
163
+ raise_noservice if ! has_service?
164
+ @helper.publish_item_to(node, item)
165
+ end
166
+
167
+ # Publish Simple Item. This is an item with one element and some text to it.
168
+ def publish_simple_item(node, text)
169
+ raise_noservice if ! has_service?
170
+
171
+ item = Jabber::PubSub::Item.new
172
+ xml = REXML::Element.new('value')
173
+ xml.text = text
174
+ item.add(xml)
175
+ publish_item(node, item)
176
+ end
177
+
178
+ # Publish atom Item. This is an item with one atom entry with title, body and time.
179
+ def publish_atom_item(node, title, body, time = Time.now)
180
+ raise_noservice if ! has_service?
181
+
182
+ item = Jabber::PubSub::Item.new
183
+ entry = REXML::Element.new('entry')
184
+ entry.add_namespace("http://www.w3.org/2005/Atom")
185
+ mytitle = REXML::Element.new('title')
186
+ mytitle.text = title
187
+ entry.add(mytitle)
188
+ mybody = REXML::Element.new('body')
189
+ mybody.text = body
190
+ entry.add(mybody)
191
+ published = REXML::Element.new("published")
192
+ published.text = time.utc.iso8601
193
+ entry.add(published)
194
+ item.add(entry)
195
+ publish_item(node, item)
196
+ end
197
+
198
+ # Get items from a node
199
+ def get_items_from(node, count = nil)
200
+ raise_noservice if ! has_service?
201
+ @helper.get_items_from(node, count)
202
+ end
203
+
204
+ private
205
+
206
+ def raise_noservice #:nodoc:
207
+ raise NoService, "Have you forgot to call #set_service ?"
208
+ end
209
+ end # of class PubSub
210
+ end # of class Observable
211
+ end # of module Jabber
@@ -0,0 +1,57 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ #
3
+ # This file's copyright (c) 2009 by Pablo Lorenzzoni <pablo@propus.com.br>
4
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
5
+ # Website::http://home.gna.org/xmpp4r/
6
+ module Jabber
7
+ class Observable
8
+ # Jabber::Observable::Subscriptions - convenience class to deal with
9
+ # Presence subscriptions
10
+ #
11
+ # observable:: points to a Jabber::Observable object
12
+ class Subscriptions
13
+ def initialize(observable)
14
+ @observable = observable
15
+ @accept = true
16
+ end
17
+
18
+ # Ask the users specified by jids for authorization (i.e., ask them to add
19
+ # you to their contact list), unless already in the contact list.
20
+ #
21
+ # Because the authorization process depends on the other user accepting your
22
+ # request, results are notified to observers of :new_subscription.
23
+ def add(*jids)
24
+ @observable.contacts(*jids).each do |contact|
25
+ next if subscribed_to?(contact)
26
+ contact.ask_for_authorization!
27
+ end
28
+ end
29
+
30
+ # Remove the jabber users specified by jids from the contact list.
31
+ def remove(*jids)
32
+ @observable.contacts(*jids).each do |contact|
33
+ contact.unsubscribe!
34
+ end
35
+ end
36
+
37
+ # Returns true if this Jabber account is subscribed to status updates for
38
+ # the jabber user jid, false otherwise.
39
+ def subscribed_to?(jid)
40
+ @observable.contacts(jid).each do |contact|
41
+ return contact.subscribed?
42
+ end
43
+ end
44
+
45
+ # Returns true if auto-accept subscriptions is enabled (default), false otherwise.
46
+ def accept?
47
+ @accept
48
+ end
49
+
50
+ # Change whether or not subscriptions are automatically accepted.
51
+ def accept=(accept_status)
52
+ @accept = accept_status
53
+ end
54
+ end # of class Subscription
55
+ end # of class Observable
56
+ end # of module Jabber
57
+