ln-xmpp4r 0.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 (215) hide show
  1. data/CHANGELOG +91 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +59 -0
  4. data/README.rdoc +113 -0
  5. data/README_ruby19.txt +43 -0
  6. data/Rakefile +252 -0
  7. data/data/doc/xmpp4r/examples/advanced/adventure/README +56 -0
  8. data/data/doc/xmpp4r/examples/advanced/adventure/adventure.rb +23 -0
  9. data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +136 -0
  10. data/data/doc/xmpp4r/examples/advanced/adventure/cube.xml +15 -0
  11. data/data/doc/xmpp4r/examples/advanced/adventure/tower.xml +69 -0
  12. data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +424 -0
  13. data/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
  14. data/data/doc/xmpp4r/examples/advanced/fileserve.rb +346 -0
  15. data/data/doc/xmpp4r/examples/advanced/getonline.rb +56 -0
  16. data/data/doc/xmpp4r/examples/advanced/gtkmucclient.rb +315 -0
  17. data/data/doc/xmpp4r/examples/advanced/migrate.rb +88 -0
  18. data/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
  19. data/data/doc/xmpp4r/examples/advanced/pep-aggregator/index.xsl +235 -0
  20. data/data/doc/xmpp4r/examples/advanced/pep-aggregator/pep-aggregator.rb +147 -0
  21. data/data/doc/xmpp4r/examples/advanced/recvfile.rb +84 -0
  22. data/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +129 -0
  23. data/data/doc/xmpp4r/examples/advanced/sendfile.conf +10 -0
  24. data/data/doc/xmpp4r/examples/advanced/sendfile.rb +72 -0
  25. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr.rb +51 -0
  26. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_jabber.rb +43 -0
  27. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_test.rb +10 -0
  28. data/data/doc/xmpp4r/examples/advanced/versionpoll.rb +109 -0
  29. data/data/doc/xmpp4r/examples/advanced/xmpping.rb +146 -0
  30. data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +14 -0
  31. data/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
  32. data/data/doc/xmpp4r/examples/basic/client.rb +70 -0
  33. data/data/doc/xmpp4r/examples/basic/component.rb +11 -0
  34. data/data/doc/xmpp4r/examples/basic/echo.rb +37 -0
  35. data/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
  36. data/data/doc/xmpp4r/examples/basic/mass_sender.rb +68 -0
  37. data/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +12 -0
  38. data/data/doc/xmpp4r/examples/basic/mucinfo.rb +41 -0
  39. data/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +82 -0
  40. data/data/doc/xmpp4r/examples/basic/register.rb +42 -0
  41. data/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
  42. data/data/doc/xmpp4r/examples/basic/roster.rb +44 -0
  43. data/data/doc/xmpp4r/examples/basic/rosterprint.rb +50 -0
  44. data/data/doc/xmpp4r/examples/basic/rosterrename.rb +34 -0
  45. data/data/doc/xmpp4r/examples/basic/rosterwatch.rb +171 -0
  46. data/data/doc/xmpp4r/examples/basic/send_vcard.rb +67 -0
  47. data/data/doc/xmpp4r/examples/basic/tune_client.rb +56 -0
  48. data/data/doc/xmpp4r/examples/basic/tune_server.rb +58 -0
  49. data/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
  50. data/lib/xmpp4r.rb +116 -0
  51. data/lib/xmpp4r/base64.rb +32 -0
  52. data/lib/xmpp4r/bytestreams.rb +15 -0
  53. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +319 -0
  54. data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +257 -0
  55. data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +31 -0
  56. data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +54 -0
  57. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +152 -0
  58. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +86 -0
  59. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +198 -0
  60. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +65 -0
  61. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +79 -0
  62. data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +170 -0
  63. data/lib/xmpp4r/bytestreams/iq/si.rb +206 -0
  64. data/lib/xmpp4r/callbacks.rb +133 -0
  65. data/lib/xmpp4r/caps.rb +1 -0
  66. data/lib/xmpp4r/caps/c.rb +67 -0
  67. data/lib/xmpp4r/caps/helper/generator.rb +160 -0
  68. data/lib/xmpp4r/caps/helper/helper.rb +84 -0
  69. data/lib/xmpp4r/client.rb +344 -0
  70. data/lib/xmpp4r/command/helper/responder.rb +53 -0
  71. data/lib/xmpp4r/command/iq/command.rb +154 -0
  72. data/lib/xmpp4r/component.rb +103 -0
  73. data/lib/xmpp4r/connection.rb +223 -0
  74. data/lib/xmpp4r/dataforms.rb +5 -0
  75. data/lib/xmpp4r/dataforms/x/data.rb +297 -0
  76. data/lib/xmpp4r/debuglog.rb +63 -0
  77. data/lib/xmpp4r/delay.rb +5 -0
  78. data/lib/xmpp4r/delay/x/delay.rb +99 -0
  79. data/lib/xmpp4r/discovery.rb +8 -0
  80. data/lib/xmpp4r/discovery/helper/helper.rb +58 -0
  81. data/lib/xmpp4r/discovery/helper/responder.rb +165 -0
  82. data/lib/xmpp4r/discovery/iq/discoinfo.rb +211 -0
  83. data/lib/xmpp4r/discovery/iq/discoitems.rb +147 -0
  84. data/lib/xmpp4r/errors.rb +284 -0
  85. data/lib/xmpp4r/feature_negotiation.rb +5 -0
  86. data/lib/xmpp4r/feature_negotiation/iq/feature.rb +28 -0
  87. data/lib/xmpp4r/framework/base.rb +55 -0
  88. data/lib/xmpp4r/framework/bot.rb +148 -0
  89. data/lib/xmpp4r/httpbinding.rb +5 -0
  90. data/lib/xmpp4r/httpbinding/client.rb +275 -0
  91. data/lib/xmpp4r/idgenerator.rb +37 -0
  92. data/lib/xmpp4r/iq.rb +221 -0
  93. data/lib/xmpp4r/jid.rb +167 -0
  94. data/lib/xmpp4r/last.rb +2 -0
  95. data/lib/xmpp4r/last/helper/helper.rb +37 -0
  96. data/lib/xmpp4r/last/iq/last.rb +67 -0
  97. data/lib/xmpp4r/location.rb +2 -0
  98. data/lib/xmpp4r/location/helper/helper.rb +56 -0
  99. data/lib/xmpp4r/location/location.rb +179 -0
  100. data/lib/xmpp4r/message.rb +180 -0
  101. data/lib/xmpp4r/muc.rb +14 -0
  102. data/lib/xmpp4r/muc/helper/mucbrowser.rb +92 -0
  103. data/lib/xmpp4r/muc/helper/mucclient.rb +462 -0
  104. data/lib/xmpp4r/muc/helper/simplemucclient.rb +332 -0
  105. data/lib/xmpp4r/muc/iq/mucadmin.rb +23 -0
  106. data/lib/xmpp4r/muc/iq/mucadminitem.rb +20 -0
  107. data/lib/xmpp4r/muc/iq/mucowner.rb +15 -0
  108. data/lib/xmpp4r/muc/item.rb +143 -0
  109. data/lib/xmpp4r/muc/x/muc.rb +70 -0
  110. data/lib/xmpp4r/muc/x/mucuserinvite.rb +60 -0
  111. data/lib/xmpp4r/muc/x/mucuseritem.rb +36 -0
  112. data/lib/xmpp4r/presence.rb +232 -0
  113. data/lib/xmpp4r/pubsub.rb +8 -0
  114. data/lib/xmpp4r/pubsub/children/configuration.rb +86 -0
  115. data/lib/xmpp4r/pubsub/children/event.rb +49 -0
  116. data/lib/xmpp4r/pubsub/children/item.rb +35 -0
  117. data/lib/xmpp4r/pubsub/children/items.rb +53 -0
  118. data/lib/xmpp4r/pubsub/children/node_config.rb +48 -0
  119. data/lib/xmpp4r/pubsub/children/publish.rb +38 -0
  120. data/lib/xmpp4r/pubsub/children/retract.rb +41 -0
  121. data/lib/xmpp4r/pubsub/children/subscription.rb +62 -0
  122. data/lib/xmpp4r/pubsub/children/subscription_config.rb +67 -0
  123. data/lib/xmpp4r/pubsub/children/unsubscribe.rb +48 -0
  124. data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +129 -0
  125. data/lib/xmpp4r/pubsub/helper/nodehelper.rb +156 -0
  126. data/lib/xmpp4r/pubsub/helper/oauth_service_helper.rb +90 -0
  127. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +456 -0
  128. data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  129. data/lib/xmpp4r/query.rb +15 -0
  130. data/lib/xmpp4r/reliable.rb +168 -0
  131. data/lib/xmpp4r/rexmladdons.rb +157 -0
  132. data/lib/xmpp4r/roster.rb +7 -0
  133. data/lib/xmpp4r/roster/helper/roster.rb +522 -0
  134. data/lib/xmpp4r/roster/iq/roster.rb +215 -0
  135. data/lib/xmpp4r/roster/x/roster.rb +138 -0
  136. data/lib/xmpp4r/rpc.rb +2 -0
  137. data/lib/xmpp4r/rpc/helper/client.rb +123 -0
  138. data/lib/xmpp4r/rpc/helper/server.rb +74 -0
  139. data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +67 -0
  140. data/lib/xmpp4r/rpc/iq/rpc.rb +23 -0
  141. data/lib/xmpp4r/sasl.rb +248 -0
  142. data/lib/xmpp4r/semaphore.rb +38 -0
  143. data/lib/xmpp4r/stream.rb +599 -0
  144. data/lib/xmpp4r/streamparser.rb +85 -0
  145. data/lib/xmpp4r/test/listener_mocker.rb +118 -0
  146. data/lib/xmpp4r/tune.rb +2 -0
  147. data/lib/xmpp4r/tune/helper/helper.rb +58 -0
  148. data/lib/xmpp4r/tune/tune.rb +113 -0
  149. data/lib/xmpp4r/vcard.rb +6 -0
  150. data/lib/xmpp4r/vcard/helper/vcard.rb +84 -0
  151. data/lib/xmpp4r/vcard/iq/vcard.rb +109 -0
  152. data/lib/xmpp4r/version.rb +7 -0
  153. data/lib/xmpp4r/version/helper/responder.rb +72 -0
  154. data/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
  155. data/lib/xmpp4r/version/iq/version.rb +105 -0
  156. data/lib/xmpp4r/x.rb +37 -0
  157. data/lib/xmpp4r/xhtml.rb +1 -0
  158. data/lib/xmpp4r/xhtml/html.rb +115 -0
  159. data/lib/xmpp4r/xmpp4r.rb +20 -0
  160. data/lib/xmpp4r/xmppelement.rb +168 -0
  161. data/lib/xmpp4r/xmppstanza.rb +162 -0
  162. data/setup.rb +1586 -0
  163. data/test/bytestreams/tc_ibb.rb +188 -0
  164. data/test/bytestreams/tc_socks5bytestreams.rb +114 -0
  165. data/test/caps/tc_helper.rb +158 -0
  166. data/test/dataforms/tc_data.rb +81 -0
  167. data/test/delay/tc_xdelay.rb +51 -0
  168. data/test/discovery/tc_responder.rb +91 -0
  169. data/test/last/tc_helper.rb +75 -0
  170. data/test/lib/assert_equal_xml.rb +14 -0
  171. data/test/lib/clienttester.rb +149 -0
  172. data/test/muc/tc_muc_mucclient.rb +834 -0
  173. data/test/muc/tc_muc_simplemucclient.rb +114 -0
  174. data/test/muc/tc_mucowner.rb +50 -0
  175. data/test/pubsub/tc_helper.rb +785 -0
  176. data/test/pubsub/tc_nodeconfig.rb +61 -0
  177. data/test/pubsub/tc_subscriptionconfig.rb +41 -0
  178. data/test/reliable/tc_disconnect_cleanup.rb +334 -0
  179. data/test/reliable/tc_disconnect_exception.rb +37 -0
  180. data/test/reliable/tc_listener_mocked_test.rb +68 -0
  181. data/test/reliable/tc_reliable_connection.rb +31 -0
  182. data/test/roster/tc_helper.rb +524 -0
  183. data/test/roster/tc_iqqueryroster.rb +173 -0
  184. data/test/roster/tc_xroster.rb +73 -0
  185. data/test/rpc/tc_helper.rb +96 -0
  186. data/test/tc_callbacks.rb +129 -0
  187. data/test/tc_class_names.rb +146 -0
  188. data/test/tc_client.rb +30 -0
  189. data/test/tc_errors.rb +146 -0
  190. data/test/tc_idgenerator.rb +30 -0
  191. data/test/tc_iq.rb +113 -0
  192. data/test/tc_iqquery.rb +31 -0
  193. data/test/tc_jid.rb +204 -0
  194. data/test/tc_message.rb +131 -0
  195. data/test/tc_presence.rb +150 -0
  196. data/test/tc_rexml.rb +139 -0
  197. data/test/tc_stream.rb +167 -0
  198. data/test/tc_streamComponent.rb +95 -0
  199. data/test/tc_streamError.rb +129 -0
  200. data/test/tc_streamSend.rb +59 -0
  201. data/test/tc_streamparser.rb +125 -0
  202. data/test/tc_xmppstanza.rb +135 -0
  203. data/test/ts_xmpp4r.rb +44 -0
  204. data/test/tune/tc_helper_recv.rb +82 -0
  205. data/test/tune/tc_helper_send.rb +74 -0
  206. data/test/tune/tc_tune.rb +79 -0
  207. data/test/vcard/tc_helper.rb +49 -0
  208. data/test/vcard/tc_iqvcard.rb +62 -0
  209. data/test/version/tc_helper.rb +60 -0
  210. data/test/version/tc_iqqueryversion.rb +97 -0
  211. data/test/xhtml/tc_html.rb +41 -0
  212. data/tools/gen_requires.bash +31 -0
  213. data/tools/xmpp4r-gemspec-test.rb +11 -0
  214. data/xmpp4r.gemspec +238 -0
  215. metadata +280 -0
@@ -0,0 +1,5 @@
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/httpbinding/client'
@@ -0,0 +1,275 @@
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
+ # TODO: eval <body type='terminate' condition=
6
+
7
+ require 'xmpp4r/client'
8
+ require 'xmpp4r/semaphore'
9
+ require 'net/http'
10
+
11
+ module Jabber
12
+ module HTTPBinding
13
+ ##
14
+ # This class implements an alternative Client
15
+ # using HTTP Binding (JEP0124).
16
+ #
17
+ # This class is designed to be a drop-in replacement
18
+ # for Jabber::Client, except for the
19
+ # Jabber::HTTP::Client#connect method which takes an URI
20
+ # as argument.
21
+ #
22
+ # HTTP requests are buffered to not exceed the negotiated
23
+ # 'polling' and 'requests' parameters.
24
+ #
25
+ # Stanzas in HTTP resonses may be delayed to arrive in the
26
+ # order defined by 'rid' parameters.
27
+ #
28
+ # =Debugging
29
+ # Turning Jabber::debug to true will make debug output
30
+ # not only spit out stanzas but HTTP request/response
31
+ # bodies, too.
32
+ class Client < Jabber::Client
33
+
34
+ # Content-Type to be used for communication
35
+ # (you can set this to "text/html")
36
+ attr_accessor :http_content_type
37
+ # The server should wait this value seconds if
38
+ # there is no stanza to be received
39
+ attr_accessor :http_wait
40
+ # The server may hold this amount of stanzas
41
+ # to reduce number of HTTP requests
42
+ attr_accessor :http_hold
43
+
44
+ ##
45
+ # Initialize
46
+ # jid:: [JID or String]
47
+ def initialize(jid)
48
+ super
49
+
50
+ @lock = Mutex.new
51
+ @pending_requests = 0
52
+ @last_send = Time.at(0)
53
+ @send_buffer = ''
54
+
55
+ @http_requests = 1
56
+ @http_wait = 20
57
+ @http_hold = 1
58
+ @http_content_type = 'text/xml; charset=utf-8'
59
+ end
60
+
61
+ ##
62
+ # Set up the stream using uri as the HTTP Binding URI
63
+ #
64
+ # You may optionally pass host and port parameters
65
+ # to make use of the JEP0124 'route' feature.
66
+ #
67
+ # uri:: [URI::Generic or String]
68
+ # host:: [String] Optional host to route to
69
+ # port:: [Fixnum] Port for route feature
70
+ def connect(uri, host=nil, port=5222)
71
+ uri = URI::parse(uri) unless uri.kind_of? URI::Generic
72
+ @uri = uri
73
+
74
+ @allow_tls = false # Shall be done at HTTP level
75
+ @stream_mechanisms = []
76
+ @stream_features = {}
77
+ @http_rid = IdGenerator.generate_id.to_i
78
+ @pending_rid = @http_rid
79
+ @pending_rid_lock = Semaphore.new
80
+
81
+ req_body = REXML::Element.new('body')
82
+ req_body.attributes['rid'] = @http_rid
83
+ req_body.attributes['content'] = @http_content_type
84
+ req_body.attributes['hold'] = @http_hold.to_s
85
+ req_body.attributes['wait'] = @http_wait.to_s
86
+ req_body.attributes['to'] = @jid.domain
87
+ if host
88
+ req_body.attributes['route'] = "xmpp:#{host}:#{port}"
89
+ end
90
+ req_body.attributes['secure'] = 'true'
91
+ req_body.attributes['xmlns'] = 'http://jabber.org/protocol/httpbind'
92
+ res_body = post(req_body)
93
+ unless res_body.name == 'body'
94
+ raise 'Response body is no <body/> element'
95
+ end
96
+
97
+ @streamid = res_body.attributes['authid']
98
+ @status = CONNECTED
99
+ @http_sid = res_body.attributes['sid']
100
+ @http_wait = res_body.attributes['wait'].to_i if res_body.attributes['wait']
101
+ @http_hold = res_body.attributes['hold'].to_i if res_body.attributes['hold']
102
+ @http_inactivity = res_body.attributes['inactivity'].to_i
103
+ @http_polling = res_body.attributes['polling'].to_i
104
+ @http_polling = 5 if @http_polling == 0
105
+ @http_requests = res_body.attributes['requests'].to_i
106
+ @http_requests = 1 if @http_requests == 0
107
+
108
+ receive_elements_with_rid(@http_rid, res_body.children)
109
+
110
+ @features_sem.run
111
+ end
112
+
113
+ ##
114
+ # Ensure that there is one pending request
115
+ #
116
+ # Will be automatically called if you've sent
117
+ # a stanza.
118
+ def ensure_one_pending_request
119
+ return if is_disconnected?
120
+
121
+ if @lock.synchronize { @pending_requests } < 1
122
+ send_data('')
123
+ end
124
+ end
125
+
126
+ ##
127
+ # Close the session by sending
128
+ # <presence type='unavailable'/>
129
+ def close
130
+ @status = DISCONNECTED
131
+ send(Jabber::Presence.new.set_type(:unavailable))
132
+ end
133
+
134
+ private
135
+
136
+ ##
137
+ # Receive stanzas ensuring that the 'rid' order is kept
138
+ # result:: [REXML::Element]
139
+ def receive_elements_with_rid(rid, elements)
140
+ while rid > @pending_rid
141
+ @pending_rid_lock.wait
142
+ end
143
+ @pending_rid = rid + 1
144
+
145
+ elements.each { |e|
146
+ receive(e)
147
+ }
148
+
149
+ @pending_rid_lock.run
150
+ end
151
+
152
+ ##
153
+ # Do a POST request
154
+ def post(body)
155
+ body = body.to_s
156
+ request = Net::HTTP::Post.new(@uri.path)
157
+ request.content_length = body.size
158
+ request.body = body
159
+ request['Content-Type'] = @http_content_type
160
+ Jabber::debuglog("HTTP REQUEST (#{@pending_requests + 1}/#{@http_requests}):\n#{request.body}")
161
+ response = Net::HTTP.start(@uri.host, @uri.port) { |http|
162
+ http.use_ssl = true if @uri.kind_of? URI::HTTPS
163
+ http.request(request)
164
+ }
165
+ Jabber::debuglog("HTTP RESPONSE (#{@pending_requests + 1}/#{@http_requests}): #{response.class}\n#{response.body}")
166
+
167
+ unless response.kind_of? Net::HTTPSuccess
168
+ # Unfortunately, HTTPResponses aren't exceptions
169
+ # TODO: rescue'ing code should be able to distinguish
170
+ raise Net::HTTPBadResponse, "#{response.class}"
171
+ end
172
+
173
+ body = REXML::Document.new(response.body).root
174
+ if body.name != 'body' and body.namespace != 'http://jabber.org/protocol/httpbind'
175
+ raise REXML::ParseException.new('Malformed body')
176
+ end
177
+ body
178
+ end
179
+
180
+ ##
181
+ # Prepare data to POST and
182
+ # handle the result
183
+ def post_data(data)
184
+ req_body = nil
185
+ current_rid = nil
186
+
187
+ begin
188
+ begin
189
+ @lock.synchronize {
190
+ # Do not send unneeded requests
191
+ if data.size < 1 and @pending_requests > 0
192
+ return
193
+ end
194
+
195
+ req_body = "<body"
196
+ req_body += " rid='#{@http_rid += 1}'"
197
+ req_body += " sid='#{@http_sid}'"
198
+ req_body += " xmlns='http://jabber.org/protocol/httpbind'"
199
+ req_body += ">"
200
+ req_body += data
201
+ req_body += "</body>"
202
+ current_rid = @http_rid
203
+
204
+ @pending_requests += 1
205
+ @last_send = Time.now
206
+ }
207
+
208
+ res_body = post(req_body)
209
+
210
+ ensure
211
+ @lock.synchronize { @pending_requests -= 1 }
212
+ end
213
+
214
+ receive_elements_with_rid(current_rid, res_body.children)
215
+ ensure_one_pending_request
216
+
217
+ rescue REXML::ParseException
218
+ if @exception_block
219
+ Thread.new do
220
+ Thread.current.abort_on_exception = true
221
+ close; @exception_block.call(e, self, :parser)
222
+ end
223
+ else
224
+ Jabber::debuglog "Exception caught when parsing HTTP response!"
225
+ close
226
+ raise
227
+ end
228
+
229
+ rescue StandardError => e
230
+ Jabber::debuglog("POST error (will retry): #{e.class}: #{e}")
231
+ receive_elements_with_rid(current_rid, [])
232
+ # It's not good to resend on *any* exception,
233
+ # but there are too many cases (Timeout, 404, 502)
234
+ # where resending is appropriate
235
+ # TODO: recognize these conditions and act appropriate
236
+ send_data(data)
237
+ end
238
+ end
239
+
240
+ ##
241
+ # Send data,
242
+ # buffered and obeying 'polling' and 'requests' limits
243
+ def send_data(data)
244
+ @lock.synchronize do
245
+
246
+ @send_buffer += data
247
+ limited_by_polling = (@last_send + @http_polling >= Time.now)
248
+ limited_by_requests = (@pending_requests + 1 > @http_requests)
249
+
250
+ # Can we send?
251
+ if !limited_by_polling and !limited_by_requests
252
+ data = @send_buffer
253
+ @send_buffer = ''
254
+
255
+ Thread.new do
256
+ Thread.current.abort_on_exception = true
257
+ post_data(data)
258
+ end
259
+
260
+ elsif !limited_by_requests
261
+ Thread.new do
262
+ Thread.current.abort_on_exception = true
263
+ # Defer until @http_polling has expired
264
+ wait = @last_send + @http_polling - Time.now
265
+ sleep(wait) if wait > 0
266
+ # Ignore locking, it's already threaded ;-)
267
+ send_data('')
268
+ end
269
+ end
270
+
271
+ end
272
+ end
273
+ end
274
+ end
275
+ end
@@ -0,0 +1,37 @@
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 'singleton'
6
+
7
+ module Jabber
8
+ ##
9
+ # The Jabber::IdGenerator class generates unique IDs for use
10
+ # in XMMP stanzas. Jabber::IdGenerator includes the Singleton
11
+ # Mixin, usage as following:
12
+ # Jabber::IdGenerator.generate_id
13
+ # => "23"
14
+ class IdGenerator
15
+ include Singleton
16
+
17
+ def initialize
18
+ @last_id = 0
19
+ end
20
+
21
+ ##
22
+ # Generate an unique ID.
23
+ #
24
+ # This is kind of boring this way, as it just counts up
25
+ # a number. Maybe something more random somewhen...
26
+ def IdGenerator.generate_id
27
+ IdGenerator.instance.generate_id
28
+ end
29
+
30
+ def generate_id
31
+ @last_id += 1
32
+ timefrac = Time.new.to_f.to_s.split(/\./, 2).last[-3..-1]
33
+
34
+ "#{@last_id}#{timefrac}"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,221 @@
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/xmppstanza'
6
+ require 'xmpp4r/jid'
7
+ require 'digest/sha1'
8
+
9
+ require 'xmpp4r/query'
10
+ require 'xmpp4r/vcard/iq/vcard'
11
+
12
+ module Jabber
13
+ ##
14
+ # IQ: Information/Query
15
+ # (see RFC3920 - 9.2.3
16
+ #
17
+ # A class used to build/parse IQ requests/responses
18
+ class Iq < XMPPStanza
19
+ name_xmlns 'iq', 'jabber:client'
20
+ force_xmlns true
21
+
22
+ @@element_classes = {}
23
+
24
+ ##
25
+ # Build a new <iq/> stanza
26
+ # type:: [Symbol] or nil, see Iq#type
27
+ # to:: [JID] Recipient
28
+ def initialize(type = nil, to = nil)
29
+ super()
30
+
31
+ if not to.nil?
32
+ set_to(to)
33
+ end
34
+ if not type.nil?
35
+ set_type(type)
36
+ end
37
+ end
38
+
39
+ ##
40
+ # Get the type of the Iq stanza
41
+ #
42
+ # The following values are allowed:
43
+ # * :get
44
+ # * :set
45
+ # * :result
46
+ # * :error
47
+ # result:: [Symbol] or nil
48
+ def type
49
+ case super
50
+ when 'get' then :get
51
+ when 'set' then :set
52
+ when 'result' then :result
53
+ when 'error' then :error
54
+ else nil
55
+ end
56
+ end
57
+
58
+ ##
59
+ # Set the type of the Iq stanza (see Iq#type)
60
+ # v:: [Symbol] or nil
61
+ def type=(v)
62
+ case v
63
+ when :get then super('get')
64
+ when :set then super('set')
65
+ when :result then super('result')
66
+ when :error then super('error')
67
+ else super(nil)
68
+ end
69
+ end
70
+
71
+ ##
72
+ # Set the type of the Iq stanza (chaining-friendly)
73
+ # v:: [Symbol] or nil
74
+ def set_type(v)
75
+ self.type = v
76
+ self
77
+ end
78
+
79
+ ##
80
+ # Returns the iq's query child, or nil
81
+ # result:: [IqQuery]
82
+ def query
83
+ first_element('query')
84
+ end
85
+
86
+ ##
87
+ # Delete old elements named newquery.name
88
+ #
89
+ # newquery:: [REXML::Element] will be added
90
+ def query=(newquery)
91
+ delete_elements(newquery.name)
92
+ add(newquery)
93
+ end
94
+
95
+ ##
96
+ # Returns the iq's query's namespace, or nil
97
+ # result:: [String]
98
+ def queryns
99
+ e = first_element('query')
100
+ if e
101
+ return e.namespace
102
+ else
103
+ return nil
104
+ end
105
+ end
106
+
107
+ ##
108
+ # Returns the iq's <vCard/> child, or nil
109
+ # result:: [IqVcard]
110
+ def vcard
111
+ first_element('vCard')
112
+ end
113
+
114
+ ##
115
+ # Returns the iq's <pubsub/> child, or nil
116
+ # result:: [IqVcard]
117
+ def pubsub
118
+ first_element('pubsub')
119
+ end
120
+
121
+ ##
122
+ # Returns the iq's <command/> child, or nil
123
+ # resulte:: [IqCommand]
124
+ def command
125
+ first_element("command")
126
+ end
127
+
128
+ ##
129
+ # Create a new Iq stanza with an unspecified query child
130
+ # (<query/> has no namespace)
131
+ def Iq.new_query(type = nil, to = nil)
132
+ iq = Iq.new(type, to)
133
+ query = IqQuery.new
134
+ iq.add(query)
135
+ iq
136
+ end
137
+
138
+ ##
139
+ # Create a new jabber:iq:auth set Stanza.
140
+ def Iq.new_authset(jid, password)
141
+ iq = Iq.new(:set)
142
+ query = IqQuery.new
143
+ query.add_namespace('jabber:iq:auth')
144
+ query.add(REXML::Element.new('username').add_text(jid.node))
145
+ query.add(REXML::Element.new('password').add_text(password))
146
+ query.add(REXML::Element.new('resource').add_text(jid.resource)) if not jid.resource.nil?
147
+ iq.add(query)
148
+ iq
149
+ end
150
+
151
+ ##
152
+ # Create a new jabber:iq:auth set Stanza for Digest authentication
153
+ def Iq.new_authset_digest(jid, session_id, password)
154
+ iq = Iq.new(:set)
155
+ query = IqQuery.new
156
+ query.add_namespace('jabber:iq:auth')
157
+ query.add(REXML::Element.new('username').add_text(jid.node))
158
+ query.add(REXML::Element.new('digest').add_text(Digest::SHA1.hexdigest(session_id + password)))
159
+ query.add(REXML::Element.new('resource').add_text(jid.resource)) if not jid.resource.nil?
160
+ iq.add(query)
161
+ iq
162
+ end
163
+
164
+ ##
165
+ # Create a new jabber:iq:register set stanza for service/server registration
166
+ # username:: [String] (Element will be ommited if unset)
167
+ # password:: [String] (Element will be ommited if unset)
168
+ def Iq.new_register(username=nil, password=nil)
169
+ iq = Iq.new(:set)
170
+ query = IqQuery.new
171
+ query.add_namespace('jabber:iq:register')
172
+ query.add(REXML::Element.new('username').add_text(username)) if username
173
+ query.add(REXML::Element.new('password').add_text(password)) if password
174
+ iq.add(query)
175
+ iq
176
+ end
177
+
178
+ ##
179
+ # Create a new jabber:iq:register get stanza for retrieval
180
+ # of accepted registration information
181
+ def Iq.new_registerget
182
+ iq = Iq.new(:get)
183
+ query = IqQuery.new
184
+ query.add_namespace('jabber:iq:register')
185
+ iq.add(query)
186
+ iq
187
+ end
188
+
189
+ ##
190
+ # Create a new jabber:iq:roster get Stanza.
191
+ #
192
+ # IqQueryRoster is unused here because possibly not require'd
193
+ def Iq.new_rosterget
194
+ iq = Iq.new(:get)
195
+ query = IqQuery.new
196
+ query.add_namespace('jabber:iq:roster')
197
+ iq.add(query)
198
+ iq
199
+ end
200
+
201
+ ##
202
+ # Create a new jabber:iq:roster get Stanza.
203
+ def Iq.new_browseget
204
+ iq = Iq.new(:get)
205
+ query = IqQuery.new
206
+ query.add_namespace('jabber:iq:browse')
207
+ iq.add(query)
208
+ iq
209
+ end
210
+
211
+ ##
212
+ # Create a new jabber:iq:roster set Stanza.
213
+ def Iq.new_rosterset
214
+ iq = Iq.new(:set)
215
+ query = IqQuery.new
216
+ query.add_namespace('jabber:iq:roster')
217
+ iq.add(query)
218
+ iq
219
+ end
220
+ end
221
+ end