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,206 @@
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 'time' # For Time#xmlschema
6
+
7
+ require 'xmpp4r/feature_negotiation/iq/feature'
8
+
9
+ module Jabber
10
+ module Bytestreams
11
+ PROFILE_FILETRANSFER = 'http://jabber.org/protocol/si/profile/file-transfer'
12
+
13
+ ##
14
+ # Iq child 'si' for Stream-Initiation
15
+ class IqSi < XMPPElement
16
+ name_xmlns 'si', 'http://jabber.org/protocol/si'
17
+ force_xmlns true
18
+
19
+ def initialize(id=nil, profile=nil, mime_type=nil)
20
+ super()
21
+
22
+ self.id = id
23
+ self.profile = profile
24
+ self.mime_type = mime_type
25
+ end
26
+
27
+ ##
28
+ # Session ID of this stream
29
+ def id
30
+ attributes['id']
31
+ end
32
+
33
+ ##
34
+ # Set Session ID of this stream
35
+ def id=(s)
36
+ attributes['id'] = s
37
+ end
38
+
39
+ ##
40
+ # MIME type of this stream
41
+ def mime_type
42
+ attributes['mime-type']
43
+ end
44
+
45
+ ##
46
+ # Set MIME type of this stream
47
+ def mime_type=(s)
48
+ attributes['mime-type'] = s
49
+ end
50
+
51
+ ##
52
+ # Stream profile, can indicate file-transfer
53
+ def profile
54
+ attributes['profile']
55
+ end
56
+
57
+ ##
58
+ # Set stream profile
59
+ def profile=(s)
60
+ attributes['profile'] = s
61
+ end
62
+
63
+ ##
64
+ # <file/> child
65
+ # result:: [IqSiFile]
66
+ def file
67
+ first_element('file')
68
+ end
69
+
70
+ ##
71
+ # <feature/> child
72
+ # result:: [IqFeature]
73
+ def feature
74
+ first_element('feature')
75
+ end
76
+ end
77
+
78
+
79
+ ##
80
+ # File-transfer meta-information,
81
+ # may appear as <file/> in IqSi
82
+ class IqSiFile < XMPPElement
83
+ name_xmlns 'file', PROFILE_FILETRANSFER
84
+
85
+ def initialize(fname=nil, size=nil)
86
+ super()
87
+ self.fname = fname
88
+ self.size = size
89
+ end
90
+
91
+ ##
92
+ # Get filename (attribute 'name')
93
+ def fname
94
+ attributes['name']
95
+ end
96
+
97
+ ##
98
+ # Set filename (attribute 'name')
99
+ def fname=(s)
100
+ attributes['name'] = s
101
+ end
102
+
103
+ ##
104
+ # Get MD5 hash
105
+ def hash
106
+ attributes['hash']
107
+ end
108
+
109
+ ##
110
+ # Set MD5 hash
111
+ def hash=(s)
112
+ attributes['hash'] = s
113
+ end
114
+
115
+ ##
116
+ # Get file date
117
+ # result:: [Time] or nil
118
+ def date
119
+ begin
120
+ Time.xmlschema(attributes['date'])
121
+ rescue ArgumentError
122
+ nil
123
+ end
124
+ end
125
+
126
+ ##
127
+ # Set file date
128
+ # d:: [Time] or nil
129
+ def date=(d)
130
+ attributes['date'] = (d ? d.xmlschema : nil)
131
+ end
132
+
133
+ ##
134
+ # File size in bytes
135
+ # result:: [Fixnum]
136
+ def size
137
+ (attributes['size'] =~ /^\d+$/) ? attributes['size'].to_i : nil
138
+ end
139
+
140
+ ##
141
+ # Set file size
142
+ def size=(s)
143
+ attributes['size'] = s ? s.to_s : nil
144
+ end
145
+
146
+ ##
147
+ # File description
148
+ def description
149
+ first_element_text('desc')
150
+ end
151
+
152
+ ##
153
+ # Set file description
154
+ def description=(s)
155
+ replace_element_text('desc', s)
156
+ end
157
+
158
+ ##
159
+ # <range/> child
160
+ #
161
+ # A file-transfer offer may contain this with
162
+ # no attributes set, indicating the ability to
163
+ # do ranged transfers.
164
+ # result:: [IqSiFileRange]
165
+ def range
166
+ first_element('range')
167
+ end
168
+ end
169
+
170
+ ##
171
+ # Information for ranged transfers
172
+ class IqSiFileRange < XMPPElement
173
+ name_xmlns 'range', PROFILE_FILETRANSFER
174
+ def initialize(offset=nil, length=nil)
175
+ super()
176
+
177
+ self.offset = offset
178
+ self.length = length
179
+ end
180
+
181
+ ##
182
+ # File offset (for continuing an interrupted transfer)
183
+ def offset
184
+ (attributes['offset'] =~ /^\d+$/) ? attributes['offset'].to_i : nil
185
+ end
186
+
187
+ ##
188
+ # Set file offset
189
+ def offset=(o)
190
+ attributes['offset'] = (o ? o.to_s : nil)
191
+ end
192
+
193
+ ##
194
+ # File length (if not to transfer whole file)
195
+ def length
196
+ (attributes['length'] =~ /^\d+$/) ? attributes['length'].to_i : nil
197
+ end
198
+
199
+ ##
200
+ # Set file length
201
+ def length=(o)
202
+ attributes['length'] = (o ? o.to_s : nil)
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,133 @@
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 manages a list of callbacks.
8
+ #
9
+ # ==Callbacks management and priority
10
+ #
11
+ # Callbacks are managed by the class CallbackList. When they are added, a
12
+ # priority (just a number or anything Comparable with other priorities) is
13
+ # specified. The biggest the priority is, the earliest the callback will be
14
+ # considered.
15
+ #
16
+ # Callbacks are processed for a given set of objects as long as they return
17
+ # false. If you want to stop processing, you must return true. Example :
18
+ # cbl = CallbackList.new
19
+ # c1 = false
20
+ # c2 = false
21
+ # c3 = false
22
+ # cbl.add(10) { c1 = true; 1 }
23
+ # cbl.add(5) { c2 = true; true }
24
+ # cbl.add(0) { c3 = true }
25
+ # cbl.process('aa')
26
+ # puts "#{c1} #{c2} #{c3}"
27
+ # This example would display "true true false" as callbacks processing was
28
+ # stopped after the second callback returned true.
29
+ #
30
+ # In XMPP4R, callbacks' priorities are quite normalized since we want to be
31
+ # able to "cascade" callbacks in a clean way. Here are values your code should
32
+ # take into account :
33
+ #
34
+ # >= 200:: logging & debugging callbacks. Those callbacks should not consume
35
+ # elements.
36
+ # 100-199:: Where Helpers register their callbacks. The normal value is 100,
37
+ # and Helpers shouldn't register something else unless there's a
38
+ # very good reason to.
39
+ # < 100:: all those numbers are normally available for your application.
40
+ # That's enough, don't you think ?
41
+ class CallbackList
42
+ include Enumerable
43
+
44
+ # Create a new list of callbacks
45
+ def initialize
46
+ @list = []
47
+ end
48
+
49
+ ##
50
+ # Add a callback to the list
51
+ #
52
+ # List will be sorted afterwards
53
+ #
54
+ # prio:: [Integer] the callback's priority, the higher, the sooner.
55
+ # ref:: [String] the callback's reference
56
+ # block:: [Block] a block to execute
57
+ # return:: [Jabber::CallbackList] The list, for chaining
58
+ def add(prio = 0, ref = nil, proc = nil, &block)
59
+ block = proc if proc
60
+ @list.push(Callback.new(prio, ref, block))
61
+ @list.sort! { |a, b| b.priority <=> a.priority }
62
+ self
63
+ end
64
+
65
+ ##
66
+ # Delete a callback by reference
67
+ # ref:: [String] the reference of the callback to delete
68
+ # return:: [CallBackList] The list, for chaining
69
+ def delete(ref)
70
+ @list.delete_if { |item| item.ref == ref }
71
+ self
72
+ end
73
+
74
+ def each(&block)
75
+ @list.each(&block)
76
+ end
77
+
78
+ ##
79
+ # Number of elements in the list
80
+ # return:: [Integer] The number of elements
81
+ def length
82
+ @list.length
83
+ end
84
+
85
+ ##
86
+ # Process an element through all my callbacks. returns e.consumed?
87
+ # e:: [Object] The elements to pass to the callback. You can pass
88
+ # several, but of course, you block must know how to handle them.
89
+ # return:: [Boolean] true if the element has been consumed
90
+ def process(*e)
91
+ # If somebody adds a new callback the list will get modified
92
+ # and sorted(!) while still iterating through it. So we use a
93
+ # local copy of @list. Any freshly added callback will receive
94
+ # the next stanzas, not the current.
95
+ list = @list.dup
96
+
97
+ # process through callbacks
98
+ list.each do |item|
99
+ return true if item.block.call(*e) == true
100
+ end
101
+ false
102
+ end
103
+ end
104
+
105
+ # This class is used to store callbacks inside CallbackList. See the
106
+ # CallbackList class for more detailed explanations.
107
+ class Callback
108
+
109
+ # The Callback's priority
110
+ attr_reader :priority
111
+
112
+ # The Callback's reference, using for deleting purposes
113
+ attr_reader :ref
114
+
115
+ # The Callback's block to execute
116
+ attr_reader :block
117
+
118
+ ##
119
+ # Create a new callback
120
+ # priority:: [Integer] the callback's priority. The higher, the sooner it
121
+ # will be executed
122
+ # ref:: [String] The callback's reference
123
+ def initialize(priority = 0, ref = nil, block = Proc.new {})
124
+ @priority = priority
125
+ @ref = ref
126
+ @block = block
127
+ end
128
+
129
+ def to_s
130
+ "#<#{[self.class, priority, ref].compact * " "}>"
131
+ end
132
+ end
133
+ end
@@ -0,0 +1 @@
1
+ require 'xmpp4r/caps/helper/helper'
@@ -0,0 +1,67 @@
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/xmppelement'
6
+
7
+ module Jabber
8
+ module Caps
9
+ NS_CAPS='http://jabber.org/protocol/caps'
10
+
11
+ ##
12
+ # The <c/> XMPP element, used to advertise entity capabilities.
13
+ #
14
+ # See http://www.xmpp.org/extensions/xep-0115.html#protocol.
15
+ #
16
+ # You should not need to construct this element directly, see
17
+ # Jabber::Caps::Helper.
18
+ class C < XMPPElement
19
+ name_xmlns 'c', NS_CAPS
20
+ force_xmlns true
21
+
22
+ def initialize(node = nil, ver = nil)
23
+ super()
24
+ add_attribute('node', node) if node
25
+ if ver
26
+ add_attribute('ver', ver)
27
+ add_attribute('hash', 'sha-1')
28
+ end
29
+ end
30
+
31
+ ##
32
+ # Get the value of this element's 'ver' attribute,
33
+ # an opaque hash representing this entity's capabilities.
34
+ def ver
35
+ attributes['ver']
36
+ end
37
+
38
+ ##
39
+ # Get the value of this element's 'node' attribute,
40
+ # a 'unique identifier for the software underlying the entity'
41
+ def node
42
+ attributes['node']
43
+ end
44
+
45
+ ##
46
+ # Get the value of this element's 'hash' attribute,
47
+ # the algorithm used in generating the 'ver' attribute
48
+ def hash
49
+ attributes['hash']
50
+ end
51
+
52
+ ##
53
+ # Get the value of this element's 'ext' attribute,
54
+ # the list of extensions for legacy clients.
55
+ def ext
56
+ attributes['ext']
57
+ end
58
+
59
+ ##
60
+ # Is this a legacy caps response, as defined by version 1.3 of
61
+ # the XEP-0115 specification?
62
+ def legacy?
63
+ hash.nil? || hash.empty?
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,160 @@
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'
6
+ require 'xmpp4r/discovery'
7
+ require 'xmpp4r/dataforms'
8
+ require 'xmpp4r/caps/c'
9
+ require 'digest'
10
+ require 'xmpp4r/base64'
11
+
12
+ module Jabber
13
+ module Caps
14
+ def self.generate_ver_str(identities, features, forms=[])
15
+ # 1. Initialize an empty string S.
16
+ s = ''
17
+
18
+ # 2. Sort the service discovery identities [14] by category and
19
+ # then by type (if it exists) and then by xml:lang (if it
20
+ # exists), formatted as CATEGORY '/' [TYPE] '/' [LANG] '/'
21
+ # [NAME]. Note that each slash is included even if the TYPE,
22
+ # LANG, or NAME is not included.
23
+ identities.sort! do |identity1,identity2|
24
+ cmp_result = nil
25
+ [:category, :type, :xml_lang, :iname].each do |field|
26
+ value1 = identity1.send(field)
27
+ value2 = identity2.send(field)
28
+
29
+ if value1 != value2
30
+ cmp_result = value1 <=> value2
31
+ break
32
+ end
33
+ end
34
+
35
+
36
+ cmp_result
37
+ end
38
+
39
+ # 3. For each identity, append the 'category/type/lang/name' to
40
+ # S, followed by the '<' character.
41
+ s += identities.collect do |identity|
42
+ [:category, :type, :xml_lang, :iname].collect do |field|
43
+ identity.send(field).to_s
44
+ end.join('/') + '<'
45
+ end.join
46
+
47
+ # 4. Sort the supported service discovery features. [15]
48
+ features.sort! do |feature1,feature2|
49
+ feature1.var <=> feature2.var
50
+ end
51
+
52
+ # 5. For each feature, append the feature to S, followed by the
53
+ # '<' character.
54
+ s += features.collect do |feature|
55
+ feature.var.to_s + '<'
56
+ end.join
57
+
58
+ # 6. If the service discovery information response includes
59
+ # XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., by
60
+ # the XML character data of the <value/> element).
61
+ forms.sort! do |form1,form2|
62
+ fform_type1 = form1.field('FORM_TYPE')
63
+ fform_type2 = form2.field('FORM_TYPE')
64
+ form_type1 = fform_type1 ? fform_type1.values.to_s : nil
65
+ form_type2 = fform_type2 ? fform_type2.values.to_s : nil
66
+ form_type1 <=> form_type2
67
+ end
68
+
69
+ # 7. For each extended service discovery information form:
70
+ forms.each do |form|
71
+ # 7.1. Append the XML character data of the FORM_TYPE field's
72
+ # <value/> element, followed by the '<' character.
73
+ fform_type = form.field('FORM_TYPE')
74
+ form_type = fform_type ? fform_type.values.to_s : nil
75
+ s += "#{form_type}<"
76
+
77
+ # 7.2. Sort the fields by the value of the "var" attribute.
78
+ fields = form.fields(false).sort do |field1,field2|
79
+ field1.var <=> field2.var
80
+ end
81
+
82
+ # 7.3. For each field:
83
+
84
+ fields.each do |field|
85
+ # 7.3.1. Append the value of the "var" attribute, followed by
86
+ # the '<' character.
87
+ s += "#{field.var}<"
88
+
89
+ # 7.3.2. Sort values by the XML character data of the <value/>
90
+ # element.
91
+ values = field.values.sort do |value1,value2|
92
+ value1 <=> value2
93
+ end
94
+
95
+ # 7.3.3. For each <value/> element, append the XML character
96
+ # data, followed by the '<' character.
97
+ s += values.collect do |value|
98
+ "#{value}<"
99
+ end.join
100
+ end
101
+ end
102
+
103
+ # 8. Ensure that S is encoded according to the UTF-8 encoding
104
+ # (RFC 3269 [16]).
105
+
106
+ # (given in XMPP4R)
107
+
108
+ s
109
+ end
110
+
111
+ ##
112
+ # Implementation of the algorithm defined at:
113
+ # http://www.xmpp.org/extensions/xep-0115.html#ver-gen
114
+ def self.generate_ver(identities, features, forms=[], hash='sha-1')
115
+ s = generate_ver_str(identities, features, forms)
116
+
117
+ # 9. Compute the verification string by hashing S using the
118
+ # algorithm specified in the 'hash' attribute (e.g., SHA-1 as
119
+ # defined in RFC 3174 [17]). The hashed data MUST be generated
120
+ # with binary output and encoded using Base64 as specified in
121
+ # Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT
122
+ # include whitespace and MUST set padding bits to zero). [19]
123
+
124
+ # See http://www.iana.org/assignments/hash-function-text-names
125
+ hash_klass = case hash
126
+ when 'md2' then nil
127
+ when 'md5' then Digest::MD5
128
+ when 'sha-1' then Digest::SHA1
129
+ when 'sha-224' then nil
130
+ when 'sha-256' then Digest::SHA256
131
+ when 'sha-384' then Digest::SHA384
132
+ when 'sha-512' then Digest::SHA512
133
+ end
134
+ if hash_klass
135
+ Base64::encode64(hash_klass::digest(s)).strip
136
+ else
137
+ nil
138
+ end
139
+ end
140
+
141
+ ##
142
+ # Generate a ver hash from a Jabber::Discovery::IqQueryDiscoInfo result
143
+ # query:: [Jabber::Discovery::IqQueryDiscoInfo]
144
+ def self.generate_ver_from_discoinfo(query, hash='sha-1')
145
+ identities = []
146
+ features = []
147
+ forms = []
148
+ query.each_element do |element|
149
+ if element.kind_of? Discovery::Identity
150
+ identities << element
151
+ elsif element.kind_of? Discovery::Feature
152
+ features << element
153
+ elsif element.kind_of? Dataforms::XData
154
+ forms << element
155
+ end
156
+ end
157
+ generate_ver(identities, features, forms, hash)
158
+ end
159
+ end
160
+ end