brontes3d-xmpp4r 0.4

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 (211) hide show
  1. data/CHANGELOG +83 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +59 -0
  4. data/README.rdoc +112 -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/message.rb +180 -0
  98. data/lib/xmpp4r/muc.rb +14 -0
  99. data/lib/xmpp4r/muc/helper/mucbrowser.rb +92 -0
  100. data/lib/xmpp4r/muc/helper/mucclient.rb +462 -0
  101. data/lib/xmpp4r/muc/helper/simplemucclient.rb +332 -0
  102. data/lib/xmpp4r/muc/iq/mucadmin.rb +23 -0
  103. data/lib/xmpp4r/muc/iq/mucadminitem.rb +20 -0
  104. data/lib/xmpp4r/muc/iq/mucowner.rb +15 -0
  105. data/lib/xmpp4r/muc/item.rb +143 -0
  106. data/lib/xmpp4r/muc/x/muc.rb +70 -0
  107. data/lib/xmpp4r/muc/x/mucuserinvite.rb +60 -0
  108. data/lib/xmpp4r/muc/x/mucuseritem.rb +36 -0
  109. data/lib/xmpp4r/presence.rb +232 -0
  110. data/lib/xmpp4r/pubsub.rb +8 -0
  111. data/lib/xmpp4r/pubsub/children/configuration.rb +86 -0
  112. data/lib/xmpp4r/pubsub/children/event.rb +49 -0
  113. data/lib/xmpp4r/pubsub/children/item.rb +35 -0
  114. data/lib/xmpp4r/pubsub/children/items.rb +53 -0
  115. data/lib/xmpp4r/pubsub/children/node_config.rb +48 -0
  116. data/lib/xmpp4r/pubsub/children/publish.rb +38 -0
  117. data/lib/xmpp4r/pubsub/children/retract.rb +41 -0
  118. data/lib/xmpp4r/pubsub/children/subscription.rb +62 -0
  119. data/lib/xmpp4r/pubsub/children/subscription_config.rb +67 -0
  120. data/lib/xmpp4r/pubsub/children/unsubscribe.rb +48 -0
  121. data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +129 -0
  122. data/lib/xmpp4r/pubsub/helper/nodehelper.rb +156 -0
  123. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +456 -0
  124. data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  125. data/lib/xmpp4r/query.rb +15 -0
  126. data/lib/xmpp4r/reliable.rb +105 -0
  127. data/lib/xmpp4r/rexmladdons.rb +157 -0
  128. data/lib/xmpp4r/roster.rb +7 -0
  129. data/lib/xmpp4r/roster/helper/roster.rb +522 -0
  130. data/lib/xmpp4r/roster/iq/roster.rb +215 -0
  131. data/lib/xmpp4r/roster/x/roster.rb +138 -0
  132. data/lib/xmpp4r/rpc.rb +2 -0
  133. data/lib/xmpp4r/rpc/helper/client.rb +123 -0
  134. data/lib/xmpp4r/rpc/helper/server.rb +74 -0
  135. data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +67 -0
  136. data/lib/xmpp4r/rpc/iq/rpc.rb +23 -0
  137. data/lib/xmpp4r/sasl.rb +243 -0
  138. data/lib/xmpp4r/semaphore.rb +38 -0
  139. data/lib/xmpp4r/stream.rb +599 -0
  140. data/lib/xmpp4r/streamparser.rb +85 -0
  141. data/lib/xmpp4r/tune.rb +2 -0
  142. data/lib/xmpp4r/tune/helper/helper.rb +58 -0
  143. data/lib/xmpp4r/tune/tune.rb +113 -0
  144. data/lib/xmpp4r/vcard.rb +6 -0
  145. data/lib/xmpp4r/vcard/helper/vcard.rb +84 -0
  146. data/lib/xmpp4r/vcard/iq/vcard.rb +109 -0
  147. data/lib/xmpp4r/version.rb +7 -0
  148. data/lib/xmpp4r/version/helper/responder.rb +72 -0
  149. data/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
  150. data/lib/xmpp4r/version/iq/version.rb +105 -0
  151. data/lib/xmpp4r/x.rb +37 -0
  152. data/lib/xmpp4r/xhtml.rb +1 -0
  153. data/lib/xmpp4r/xhtml/html.rb +115 -0
  154. data/lib/xmpp4r/xmpp4r.rb +19 -0
  155. data/lib/xmpp4r/xmppelement.rb +168 -0
  156. data/lib/xmpp4r/xmppstanza.rb +162 -0
  157. data/setup.rb +1586 -0
  158. data/test/bytestreams/tc_ibb.rb +188 -0
  159. data/test/bytestreams/tc_socks5bytestreams.rb +114 -0
  160. data/test/caps/tc_helper.rb +158 -0
  161. data/test/dataforms/tc_data.rb +81 -0
  162. data/test/delay/tc_xdelay.rb +51 -0
  163. data/test/discovery/tc_responder.rb +91 -0
  164. data/test/last/tc_helper.rb +75 -0
  165. data/test/lib/assert_equal_xml.rb +14 -0
  166. data/test/lib/clienttester.rb +149 -0
  167. data/test/muc/tc_muc_mucclient.rb +834 -0
  168. data/test/muc/tc_muc_simplemucclient.rb +114 -0
  169. data/test/muc/tc_mucowner.rb +50 -0
  170. data/test/pubsub/tc_helper.rb +722 -0
  171. data/test/pubsub/tc_nodeconfig.rb +54 -0
  172. data/test/pubsub/tc_subscriptionconfig.rb +41 -0
  173. data/test/reliable/listener_mocker.rb +90 -0
  174. data/test/reliable/tc_disconnect_cleanup.rb +334 -0
  175. data/test/reliable/tc_disconnect_exception.rb +37 -0
  176. data/test/reliable/tc_listener_mocked_test.rb +40 -0
  177. data/test/reliable/tc_reliable_connection.rb +32 -0
  178. data/test/roster/tc_helper.rb +524 -0
  179. data/test/roster/tc_iqqueryroster.rb +173 -0
  180. data/test/roster/tc_xroster.rb +73 -0
  181. data/test/rpc/tc_helper.rb +96 -0
  182. data/test/tc_callbacks.rb +129 -0
  183. data/test/tc_class_names.rb +146 -0
  184. data/test/tc_client.rb +30 -0
  185. data/test/tc_errors.rb +146 -0
  186. data/test/tc_idgenerator.rb +30 -0
  187. data/test/tc_iq.rb +113 -0
  188. data/test/tc_iqquery.rb +31 -0
  189. data/test/tc_jid.rb +204 -0
  190. data/test/tc_message.rb +131 -0
  191. data/test/tc_presence.rb +150 -0
  192. data/test/tc_rexml.rb +139 -0
  193. data/test/tc_stream.rb +167 -0
  194. data/test/tc_streamComponent.rb +95 -0
  195. data/test/tc_streamError.rb +129 -0
  196. data/test/tc_streamSend.rb +59 -0
  197. data/test/tc_streamparser.rb +125 -0
  198. data/test/tc_xmppstanza.rb +135 -0
  199. data/test/ts_xmpp4r.rb +53 -0
  200. data/test/tune/tc_helper_recv.rb +82 -0
  201. data/test/tune/tc_helper_send.rb +74 -0
  202. data/test/tune/tc_tune.rb +79 -0
  203. data/test/vcard/tc_helper.rb +49 -0
  204. data/test/vcard/tc_iqvcard.rb +62 -0
  205. data/test/version/tc_helper.rb +60 -0
  206. data/test/version/tc_iqqueryversion.rb +97 -0
  207. data/test/xhtml/tc_html.rb +41 -0
  208. data/tools/gen_requires.bash +31 -0
  209. data/tools/xmpp4r-gemspec-test.rb +11 -0
  210. data/xmpp4r.gemspec +307 -0
  211. metadata +349 -0
@@ -0,0 +1,74 @@
1
+ require 'xmlrpc/server'
2
+ require 'xmlrpc/parser'
3
+ require 'xmlrpc/create'
4
+ require 'xmlrpc/config'
5
+ require 'xmlrpc/utils' # ParserWriterChooseMixin
6
+
7
+ require 'xmpp4r/dataforms/x/data'
8
+ require 'xmpp4r/rpc/iq/rpc'
9
+ require 'xmpp4r/rpc/helper/xmlrpcaddons'
10
+
11
+ module Jabber
12
+ module RPC
13
+
14
+ ##
15
+ # XMLRPC Server
16
+ class Server < XMLRPC::BasicServer
17
+
18
+ include XMLRPC::ParserWriterChooseMixin
19
+ include XMLRPC::ParseContentType
20
+
21
+ ##
22
+ # new - creates a new server
23
+ #
24
+ def initialize(stream,class_delim=".")
25
+ super(class_delim)
26
+ @stream = stream
27
+ @stream.add_iq_callback(120,"Helpers::RPCServer") { |iq|
28
+ if iq.type == :set and iq.type != :result
29
+ handle_iq(iq)
30
+ true
31
+ else
32
+ false
33
+ end
34
+ }
35
+ end
36
+
37
+ ##
38
+ # handles incoming iqs
39
+ # iq:: [Jabber::IQ] - the jabber iq
40
+ def handle_iq(iq)
41
+ if iq.type == :set
42
+ if iq.query.kind_of?(IqQueryRPC)
43
+ data = iq.query
44
+ response = IqQueryRPC.new
45
+ data.elements.each { |rpc|
46
+ if rpc
47
+ response.typed_add(handle_rpc_requests(rpc))
48
+ end
49
+ }
50
+
51
+ respiq = iq.answer(false)
52
+ respiq.type = :result
53
+ respiq.add(response)
54
+ @stream.send(respiq)
55
+ end
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ ##
62
+ # handles the rpc requests
63
+ # takes rpcdata:: [String]
64
+ def handle_rpc_requests(rpcdata)
65
+ resp = process(rpcdata.to_s)
66
+ if resp == nil or resp.size <= 0
67
+ raise Jabber::ErrorResponse.new(:forbidden)
68
+ else
69
+ return resp
70
+ end
71
+ end
72
+ end # RPCServer
73
+ end # Helpers
74
+ end # Jabber
@@ -0,0 +1,67 @@
1
+ require "xmlrpc/parser"
2
+ require "xmlrpc/create"
3
+ require "xmlrpc/config"
4
+ require "xmlrpc/utils" # ParserWriterChooseMixin
5
+
6
+
7
+ module XMLRPC
8
+ class Create
9
+
10
+ # Avoids warnings
11
+ remove_method(:methodCall)
12
+ remove_method(:methodResponse)
13
+
14
+ ##
15
+ # create a Method Call
16
+ # name:: [String] name of the method
17
+ # params:: [Array] params of the method as a array
18
+ def methodCall(name, *params)
19
+ name = name.to_s
20
+
21
+ if name !~ /[a-zA-Z0-9_.:\/]+/
22
+ raise ArgumentError, "Wrong XML-RPC method-name"
23
+ end
24
+
25
+ parameter = params.collect { |param|
26
+ @writer.ele("param", conv2value(param))
27
+ }
28
+
29
+ tree = @writer.document(
30
+ @writer.ele("methodCall",
31
+ @writer.tag("methodName", name),
32
+ @writer.ele("params", *parameter)
33
+ )
34
+ )
35
+
36
+ @writer.document_to_str(tree) + "\n"
37
+ end
38
+ ##
39
+ # create a response to a method call
40
+ # is_ret:: [TrueClass] is this a return (true) or a error (false)
41
+ # params:: [Array] a array of params
42
+
43
+ def methodResponse(is_ret, *params)
44
+
45
+ if is_ret
46
+ begin
47
+ resp = params.collect do |param|
48
+ @writer.ele("param", conv2value(param))
49
+ end
50
+
51
+ resp = [@writer.ele("params", *resp)]
52
+ rescue Exception => e
53
+ error = XMLRPC::FaultException.new(XMLRPC::BasicServer::ERR_UNCAUGHT_EXCEPTION, "Uncaught exception '#{e.message}' serialising params into response")
54
+ resp = @writer.ele("fault", conv2value(error.to_h))
55
+ end
56
+ else
57
+ if params.size != 1 or params[0] === XMLRPC::FaultException
58
+ raise ArgumentError, "no valid fault-structure given"
59
+ end
60
+ resp = @writer.ele("fault", conv2value(params[0].to_h))
61
+ end
62
+
63
+ tree = @writer.document(@writer.ele("methodResponse", resp))
64
+ @writer.document_to_str(tree) + "\n"
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,23 @@
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/query'
6
+
7
+ module Jabber
8
+ module RPC
9
+ class IqQueryRPC < IqQuery
10
+ NS_RPC = 'jabber:iq:rpc'
11
+ name_xmlns 'query', NS_RPC
12
+
13
+ # TODO: Is typed_add with a String right here?
14
+ def typed_add(e)
15
+ if e.kind_of? String
16
+ typed_add(REXML::Document.new(e).root)
17
+ else
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,243 @@
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 'digest/md5'
6
+ require 'xmpp4r/base64'
7
+
8
+ module Jabber
9
+ ##
10
+ # Helpers for SASL authentication (RFC2222)
11
+ #
12
+ # You might not need to use them directly, they are
13
+ # invoked by Jabber::Client#auth
14
+ module SASL
15
+ NS_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl'
16
+
17
+ ##
18
+ # Factory function to obtain a SASL helper for the specified mechanism
19
+ def SASL.new(stream, mechanism)
20
+ case mechanism
21
+ when 'DIGEST-MD5'
22
+ DigestMD5.new(stream)
23
+ when 'PLAIN'
24
+ Plain.new(stream)
25
+ when 'ANONYMOUS'
26
+ Anonymous.new(stream)
27
+ else
28
+ raise "Unknown SASL mechanism: #{mechanism}"
29
+ end
30
+ end
31
+
32
+ ##
33
+ # SASL mechanism base class (stub)
34
+ class Base
35
+ def initialize(stream)
36
+ @stream = stream
37
+ end
38
+
39
+ private
40
+
41
+ def generate_auth(mechanism, text=nil)
42
+ auth = REXML::Element.new 'auth'
43
+ auth.add_namespace NS_SASL
44
+ auth.attributes['mechanism'] = mechanism
45
+ auth.text = text
46
+ auth
47
+ end
48
+
49
+ def generate_nonce
50
+ Digest::MD5.hexdigest(Time.new.to_f.to_s)
51
+ end
52
+ end
53
+
54
+ ##
55
+ # SASL PLAIN authentication helper (RFC2595)
56
+ class Plain < Base
57
+ ##
58
+ # Authenticate via sending password in clear-text
59
+ def auth(password)
60
+ auth_text = "#{@stream.jid.strip}\x00#{@stream.jid.node}\x00#{password}"
61
+ error = nil
62
+ @stream.send(generate_auth('PLAIN', Base64::encode64(auth_text).gsub(/\s/, ''))) { |reply|
63
+ if reply.name != 'success'
64
+ error = reply.first_element(nil).name
65
+ end
66
+ true
67
+ }
68
+
69
+ raise error if error
70
+ end
71
+ end
72
+
73
+ ##
74
+ # SASL Anonymous authentication helper
75
+ class Anonymous < Base
76
+ ##
77
+ # Authenticate by sending nothing with the ANONYMOUS token
78
+ def auth(password)
79
+ auth_text = "#{@stream.jid.node}"
80
+ error = nil
81
+ @stream.send(generate_auth('ANONYMOUS', Base64::encode64(auth_text).gsub(/\s/, ''))) { |reply|
82
+ if reply.name != 'success'
83
+ error = reply.first_element(nil).name
84
+ end
85
+ true
86
+ }
87
+
88
+ raise error if error
89
+ end
90
+ end
91
+
92
+ ##
93
+ # SASL DIGEST-MD5 authentication helper (RFC2831)
94
+ class DigestMD5 < Base
95
+ ##
96
+ # Sends the wished auth mechanism and wait for a challenge
97
+ #
98
+ # (proceed with DigestMD5#auth)
99
+ def initialize(stream)
100
+ super
101
+
102
+ challenge = {}
103
+ error = nil
104
+ @stream.send(generate_auth('DIGEST-MD5')) { |reply|
105
+ if reply.name == 'challenge' and reply.namespace == NS_SASL
106
+ challenge = decode_challenge(reply.text)
107
+ else
108
+ error = reply.first_element(nil).name
109
+ end
110
+ true
111
+ }
112
+ raise error if error
113
+
114
+ @nonce = challenge['nonce']
115
+ @realm = challenge['realm']
116
+ end
117
+
118
+ def decode_challenge(challenge)
119
+ text = Base64::decode64(challenge)
120
+ res = {}
121
+
122
+ state = :key
123
+ key = ''
124
+ value = ''
125
+
126
+ text.scan(/./) do |ch|
127
+ if state == :key
128
+ if ch == '='
129
+ state = :value
130
+ else
131
+ key += ch
132
+ end
133
+
134
+ elsif state == :value
135
+ if ch == ','
136
+ res[key] = value
137
+ key = ''
138
+ value = ''
139
+ state = :key
140
+ elsif ch == '"' and value == ''
141
+ state = :quote
142
+ else
143
+ value += ch
144
+ end
145
+
146
+ elsif state == :quote
147
+ if ch == '"'
148
+ state = :value
149
+ else
150
+ value += ch
151
+ end
152
+ end
153
+ end
154
+ res[key] = value unless key == ''
155
+
156
+ Jabber::debuglog("SASL DIGEST-MD5 challenge:\n#{text}\n#{res.inspect}")
157
+
158
+ res
159
+ end
160
+
161
+ ##
162
+ # * Send a response
163
+ # * Wait for the server's challenge (which aren't checked)
164
+ # * Send a blind response to the server's challenge
165
+ def auth(password)
166
+ response = {}
167
+ response['nonce'] = @nonce
168
+ response['charset'] = 'utf-8'
169
+ response['username'] = @stream.jid.node
170
+ response['realm'] = @realm || @stream.jid.domain
171
+ response['cnonce'] = generate_nonce
172
+ response['nc'] = '00000001'
173
+ response['qop'] = 'auth'
174
+ response['digest-uri'] = "xmpp/#{@stream.jid.domain}"
175
+ response['response'] = response_value(@stream.jid.node, @stream.jid.domain, response['digest-uri'], password, @nonce, response['cnonce'], response['qop'], response['authzid'])
176
+ response.each { |key,value|
177
+ unless %w(nc qop response charset).include? key
178
+ response[key] = "\"#{value}\""
179
+ end
180
+ }
181
+
182
+ response_text = response.collect { |k,v| "#{k}=#{v}" }.join(',')
183
+ Jabber::debuglog("SASL DIGEST-MD5 response:\n#{response_text}\n#{response.inspect}")
184
+
185
+ r = REXML::Element.new('response')
186
+ r.add_namespace NS_SASL
187
+ r.text = Base64::encode64(response_text).gsub(/\s/, '')
188
+
189
+ success_already = false
190
+ error = nil
191
+ @stream.send(r) { |reply|
192
+ if reply.name == 'success'
193
+ success_already = true
194
+ elsif reply.name != 'challenge'
195
+ error = reply.first_element(nil).name
196
+ end
197
+ true
198
+ }
199
+
200
+ return if success_already
201
+ raise error if error
202
+
203
+ # TODO: check the challenge from the server
204
+
205
+ r.text = nil
206
+ @stream.send(r) { |reply|
207
+ if reply.name != 'success'
208
+ error = reply.first_element(nil).name
209
+ end
210
+ true
211
+ }
212
+
213
+ raise error if error
214
+ end
215
+
216
+ private
217
+
218
+ ##
219
+ # Function from RFC2831
220
+ def h(s); Digest::MD5.digest(s); end
221
+ ##
222
+ # Function from RFC2831
223
+ def hh(s); Digest::MD5.hexdigest(s); end
224
+
225
+ ##
226
+ # Calculate the value for the response field
227
+ def response_value(username, realm, digest_uri, passwd, nonce, cnonce, qop, authzid)
228
+ a1_h = h("#{username}:#{realm}:#{passwd}")
229
+ a1 = "#{a1_h}:#{nonce}:#{cnonce}"
230
+ if authzid
231
+ a1 += ":#{authzid}"
232
+ end
233
+ if qop == 'auth-int' || qop == 'auth-conf'
234
+ a2 = "AUTHENTICATE:#{digest_uri}:00000000000000000000000000000000"
235
+ else
236
+ a2 = "AUTHENTICATE:#{digest_uri}"
237
+ end
238
+ hh("#{hh(a1)}:#{nonce}:00000001:#{cnonce}:#{qop}:#{hh(a2)}")
239
+ end
240
+ end
241
+ end
242
+ end
243
+
@@ -0,0 +1,38 @@
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
+ module Jabber
6
+ ##
7
+ # This class implements semaphore for threads synchronization.
8
+ class Semaphore
9
+
10
+ ##
11
+ # Initialize new semaphore
12
+ #
13
+ # val:: [Integer] number of threads, that can enter to section
14
+ def initialize(val=0)
15
+ @tickets = val
16
+ @lock = Mutex.new
17
+ @cond = ConditionVariable.new
18
+ end
19
+
20
+ ##
21
+ # Waits until are available some free tickets
22
+ def wait
23
+ @lock.synchronize {
24
+ @cond.wait(@lock) while !(@tickets > 0)
25
+ @tickets -= 1
26
+ }
27
+ end
28
+
29
+ ##
30
+ # Unlocks guarded section, increments number of free tickets
31
+ def run
32
+ @lock.synchronize {
33
+ @tickets += 1
34
+ @cond.signal
35
+ }
36
+ end
37
+ end
38
+ end