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,284 @@
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
+ # CUSTOM ERROR CLASSES
8
+
9
+ # All of our custom errors are superclassed by JabberError < StandardError
10
+ class JabberError < StandardError; end
11
+
12
+ # A client-side only argument error
13
+ class ArgumentError < JabberError; end
14
+
15
+ # Server disconnected us
16
+ class ServerDisconnected < JabberError; end
17
+
18
+ ##
19
+ # An error returned from the server
20
+ #
21
+ # e.g. This exception can be raised by helpers when they
22
+ # receive a server reply with <tt>type='error'</tt>
23
+ #
24
+ # The ServerError carries a Jabber::ErrorResponse element
25
+ #
26
+ class ServerError < JabberError #:nodoc:
27
+
28
+ ##
29
+ # The error element which caused this exception
30
+ attr_reader :error
31
+
32
+ ##
33
+ # Initialize a ServerError by passing an ErrorResponse instance
34
+ # error:: [Error]
35
+ def initialize(error)
36
+ @error = error
37
+ end
38
+
39
+ ##
40
+ # Sample output:
41
+ # 'subscription-required: Please subscribe first'
42
+ def to_s
43
+ "#{@error.error}: #{@error.text}"
44
+ end
45
+ end
46
+
47
+ class ClientAuthenticationFailure < JabberError; end
48
+
49
+ class ComponentAuthenticationFailure < JabberError; end
50
+
51
+ class NoNameXmlnsRegistered < JabberError
52
+ def initialize(klass)
53
+ super "Class #{klass} has not set name and xmlns"
54
+ end
55
+ end
56
+
57
+ class SOCKS5Error < JabberError; end
58
+
59
+ class InvalidChatState < JabberError; end
60
+
61
+ ##
62
+ # A class used to build/parse <error/> elements.
63
+ # Look at XEP-0086 for explanation:
64
+ # http://www.xmpp.org/extensions/xep-0086.html
65
+ #
66
+ # FIXME : XEP-0086 is officially deprecated. What effect does that have on this class? Any?
67
+ #
68
+ class ErrorResponse < XMPPElement
69
+ name_xmlns 'error'
70
+
71
+ ##
72
+ # errorcondition:: [nil] or [String] of the following:
73
+ # * "bad-request"
74
+ # * "conflict"
75
+ # * "feature-not-implemented"
76
+ # * "forbidden"
77
+ # * "gone"
78
+ # * "internal-server-error"
79
+ # * "item-not-found"
80
+ # * "jid-malformed"
81
+ # * "not-acceptable"
82
+ # * "not-allowed"
83
+ # * "not-authorized"
84
+ # * "payment-required"
85
+ # * "recipient-unavailable"
86
+ # * "redirect"
87
+ # * "registration-required"
88
+ # * "remote-server-not-found"
89
+ # * "remote-server-timeout"
90
+ # * "resource-constraint"
91
+ # * "service-unavailable"
92
+ # * "subscription-required"
93
+ # * "undefined-condition"
94
+ # * "unexpected-request"
95
+ # Will raise an [Exception] if not [nil] and none of the above
96
+ #
97
+ # Also sets type and code to appropriate values according to errorcondition
98
+ #
99
+ # text: [nil] or [String] ErrorResponse text
100
+ def initialize(errorcondition=nil, text=nil)
101
+ if errorcondition.nil?
102
+ super()
103
+ set_text(text) unless text.nil?
104
+ else
105
+ errortype = nil
106
+ errorcode = nil
107
+ @@Errors.each { |cond,type,code|
108
+ if errorcondition == cond
109
+ errortype = type
110
+ errorcode = code
111
+ end
112
+ }
113
+
114
+ if errortype.nil? || errorcode.nil?
115
+ raise ArgumentError, "Unknown error condition when initializing ErrorReponse"
116
+ end
117
+
118
+ super()
119
+ set_error(errorcondition)
120
+ set_type(errortype)
121
+ set_code(errorcode)
122
+ set_text(text) unless text.nil?
123
+ end
124
+ end
125
+
126
+ ##
127
+ # Get the 'Legacy error code' or nil
128
+ # result:: [Integer] Error code
129
+ def code
130
+ if attributes['code']
131
+ attributes['code'].to_i
132
+ else
133
+ nil
134
+ end
135
+ end
136
+
137
+ ##
138
+ # Set the 'Legacy error code' or nil
139
+ # i:: [Integer] Error code
140
+ def code=(i)
141
+ if i.nil?
142
+ attributes['code'] = nil
143
+ else
144
+ attributes['code'] = i.to_s
145
+ end
146
+ end
147
+
148
+ ##
149
+ # Set the 'Legacy error code' (chaining-friendly)
150
+ def set_code(i)
151
+ self.code = i
152
+ self
153
+ end
154
+
155
+ ##
156
+ # Get the 'XMPP error condition'
157
+ #
158
+ # This can be anything that possess the specific namespace,
159
+ # checks don't apply here
160
+ def error
161
+ name = nil
162
+ each_element { |e| name = e.name if (e.namespace == 'urn:ietf:params:xml:ns:xmpp-stanzas') && (e.name != 'text') }
163
+ name
164
+ end
165
+
166
+ ##
167
+ # Set the 'XMPP error condition'
168
+ #
169
+ # One previous element with that namespace will be deleted before
170
+ #
171
+ # s:: [String] Name of the element to be added,
172
+ # namespace will be added automatically, checks don't apply here
173
+ def error=(s)
174
+ xe = nil
175
+ each_element { |e| xe = e if (e.namespace == 'urn:ietf:params:xml:ns:xmpp-stanzas') && (e.name != 'text') }
176
+ unless xe.nil?
177
+ delete_element(xe)
178
+ end
179
+
180
+ add_element(s).add_namespace('urn:ietf:params:xml:ns:xmpp-stanzas')
181
+ end
182
+
183
+ ##
184
+ # Set the 'XMPP error condition' (chaining-friendly)
185
+ def set_error(s)
186
+ self.error = s
187
+ self
188
+ end
189
+
190
+ ##
191
+ # Get the errors <text/> element text
192
+ # result:: [String] or nil
193
+ def text
194
+ first_element_text('text') || super
195
+ end
196
+
197
+ ##
198
+ # Set the errors <text/> element text
199
+ # (Previous <text/> elements will be deleted first)
200
+ # s:: [String] <text/> content or [nil] if no <text/> element
201
+ def text=(s)
202
+ delete_elements('text')
203
+
204
+ unless s.nil?
205
+ e = add_element('text')
206
+ e.add_namespace('urn:ietf:params:xml:ns:xmpp-stanzas')
207
+ e.text = s
208
+ end
209
+ end
210
+
211
+ ##
212
+ # Set the errors <text/> element text (chaining-friendly)
213
+ def set_text(s)
214
+ self.text = s
215
+ self
216
+ end
217
+
218
+ ##
219
+ # Get the type of error
220
+ # (meaning how to proceed)
221
+ # result:: [Symbol] or [nil] as following:
222
+ # * :auth
223
+ # * :cancel
224
+ # * :continue
225
+ # * :modify
226
+ # * :wait
227
+ def type
228
+ case attributes['type']
229
+ when 'auth' then :auth
230
+ when 'cancel' then :cancel
231
+ when 'continue' then :continue
232
+ when 'modify' then :modify
233
+ when 'wait' then :wait
234
+ else nil
235
+ end
236
+ end
237
+
238
+ ##
239
+ # Set the type of error (see ErrorResponse#type)
240
+ def type=(t)
241
+ case t
242
+ when :auth then attributes['type'] = 'auth'
243
+ when :cancel then attributes['type'] = 'cancel'
244
+ when :continue then attributes['type'] = 'continue'
245
+ when :modify then attributes['type'] = 'modify'
246
+ when :wait then attributes['type'] = 'wait'
247
+ else attributes['type'] = nil
248
+ end
249
+ end
250
+
251
+ ##
252
+ # Set the type of error (chaining-friendly)
253
+ def set_type(t)
254
+ self.type = t
255
+ self
256
+ end
257
+
258
+ ##
259
+ # Possible XMPP error conditions, types and codes (XEP-0086)
260
+ @@Errors = [['bad-request', :modify, 400],
261
+ ['conflict', :cancel, 409],
262
+ ['feature-not-implemented', :cancel, 501],
263
+ ['forbidden', :auth, 403],
264
+ ['gone', :modify, 302],
265
+ ['internal-server-error', :wait, 500],
266
+ ['item-not-found', :cancel, 404],
267
+ ['jid-malformed', :modify, 400],
268
+ ['not-acceptable', :modify, 406],
269
+ ['not-allowed', :cancel, 405],
270
+ ['not-authorized', :auth, 401],
271
+ ['payment-required', :auth, 402],
272
+ ['recipient-unavailable', :wait, 404],
273
+ ['redirect', :modify, 302],
274
+ ['registration-required', :auth, 407],
275
+ ['remote-server-not-found', :cancel, 404],
276
+ ['remote-server-timeout', :wait, 504],
277
+ ['resource-constraint', :wait, 500],
278
+ ['service-unavailable', :cancel, 503],
279
+ ['subscription-required', :auth, 407],
280
+ ['undefined-condition', nil, 500],
281
+ ['unexpected-request', :wait, 400]]
282
+ end
283
+
284
+ end
@@ -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/feature_negotiation/iq/feature.rb'
@@ -0,0 +1,28 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/iq'
6
+ require 'xmpp4r/dataforms/x/data'
7
+
8
+ module Jabber
9
+ module FeatureNegotiation
10
+ ##
11
+ # Feature negotiation,
12
+ # can appear as direct child to Iq
13
+ # or as child of IqSi
14
+ class IqFeature < XMPPElement
15
+ name_xmlns 'feature', 'http://jabber.org/protocol/feature-neg'
16
+
17
+ ##
18
+ # First <x/> child with xmlns='jabber:x:data'
19
+ def x
20
+ res = nil
21
+ each_element('x') { |e|
22
+ res = e if e.namespace == 'jabber:x:data'
23
+ }
24
+ res
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ require 'thread'
2
+
3
+ module Jabber
4
+ module Framework
5
+ class Base
6
+
7
+ def self.helper(name, klass=nil, &factory)
8
+ if klass.nil? and factory.nil?
9
+ raise "helper #{name} needs a class or factory"
10
+ end
11
+
12
+ define_method(name) do
13
+ @helpers_lock.synchronize do
14
+ if @helpers[name]
15
+ @helpers[name]
16
+ else
17
+ if factory
18
+ @helpers[name] = instance_eval { factory.call(@stream) }
19
+ elsif klass
20
+ @helpers[name] = klass.new(@stream)
21
+ else
22
+ raise
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ attr_accessor :stream
30
+
31
+ def initialize(stream)
32
+ @stream = stream
33
+ @helpers = {}
34
+ @helpers_lock = Mutex.new
35
+
36
+ # Catch all unhandled iq stanzas (lowest priority)
37
+ @stream.add_iq_callback(-1000, self, &method(:on_unhandled_iq))
38
+ end
39
+
40
+ def on_unhandled_iq(iq)
41
+ if iq.type == :get or iq.type == :set
42
+ answer = iq.answer(true)
43
+ answer.type = :error
44
+ answer.add(ErrorResponse.new('feature-not-implemented'))
45
+ @stream.send(answer)
46
+
47
+ true
48
+ else
49
+ false
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,148 @@
1
+ require 'xmpp4r/framework/base'
2
+
3
+ require 'xmpp4r'
4
+ require 'xmpp4r/roster'
5
+ require 'xmpp4r/caps/c'
6
+ require 'xmpp4r/discovery'
7
+ require 'xmpp4r/xhtml'
8
+
9
+ module Jabber
10
+ module Framework
11
+ ##
12
+ # Abstract handler methods that *may* be implemented by a deriving class:
13
+ # * on_message(text)
14
+ # * on_message_xhtml(html_body, text)
15
+ class Bot < Base
16
+ helper :roster, Roster::Helper
17
+ helper(:disco_default) { |cl|
18
+ Discovery::Responder.new(cl,
19
+ nil,
20
+ [Jabber::Discovery::Identity.new('client', 'XMPP4R Bot', 'bot')]
21
+ )
22
+ }
23
+ helper(:disco_caps) { |cl|
24
+ Discovery::Responder.new(cl,
25
+ "http://home.gna.org/xmpp4r/#{Jabber::XMPP4R_VERSION}",
26
+ [Jabber::Discovery::Identity.new('client', 'XMPP4R Bot', 'bot')]
27
+ )
28
+ }
29
+
30
+ def initialize(jid, password)
31
+ cl = Jabber::Client.new(jid)
32
+ cl.connect
33
+ cl.auth(password)
34
+
35
+ super(cl)
36
+
37
+ roster.add_subscription_request_callback do |item,presence|
38
+ if accept_subscription_from?(presence.from.strip)
39
+ roster.accept_subscription(presence.from.strip)
40
+ else
41
+ roster.decline_subscription(presence.from.strip)
42
+ end
43
+ end
44
+
45
+ @pep_notifications = []
46
+ cl.add_message_callback do |msg|
47
+ if msg.type != :error and msg.body
48
+ if (html = msg.first_element('html')) and respond_to? :on_message_xhtml
49
+ on_message_xhtml(html.body, msg.body)
50
+ elsif respond_to? :on_message
51
+ on_message(msg.body)
52
+ end
53
+ elsif msg.type != :error and (event = msg.first_element('event'))
54
+ event.each_element('items') do |items|
55
+ node = items.attributes['node']
56
+ items.each_element('item') do |item|
57
+ @pep_notifications.each { |notification_node,callback|
58
+ if node == notification_node
59
+ callback.call(msg.from, item)
60
+ end
61
+ }
62
+ end
63
+ end
64
+ else
65
+ false
66
+ end
67
+ end
68
+
69
+ add_cap('presence')
70
+ add_cap(Caps::NS_CAPS)
71
+ add_cap('message') if respond_to? :on_message
72
+ add_cap(XHTML::NS_XHTML_IM) if respond_to? :on_message_xhtml
73
+
74
+ @presence_show = nil
75
+ @presence_status = nil
76
+ end
77
+
78
+ ##
79
+ # Add feature namespace to Capabilities Discovery
80
+ def add_cap(capability)
81
+ disco_default.add_feature(capability)
82
+ disco_caps.add_feature(capability)
83
+ end
84
+
85
+ ##
86
+ # Front-end for Roster::Helper#add_subscription_request_callback
87
+ #
88
+ # Can be overwritten, must return true or false
89
+ def accept_subscription_from?(jid)
90
+ true
91
+ end
92
+
93
+ ##
94
+ # Send a simple text chat message
95
+ def send_message(to, text)
96
+ msg = Message.new
97
+ msg.type = :chat
98
+ msg.to = to
99
+ msg.body = text
100
+ @stream.send(msg)
101
+ end
102
+
103
+ ##
104
+ # Send an XHTML chat message
105
+ # text:: [String] alternate plain text body, generated from xhtml_contents if nil
106
+ def send_message_xhtml(to, xhtml_contents, text=nil)
107
+ msg = Message.new
108
+ msg.type = :chat
109
+ msg.to = to
110
+ html = msg.add(XHTML::HTML.new(xhtml_contents))
111
+ msg.body = text ? text : html.to_text
112
+ @stream.send(msg)
113
+ end
114
+
115
+ ##
116
+ # Set and send a Presence
117
+ def set_presence(show=nil, status=nil)
118
+ @presence_show = show
119
+ @presence_status = status
120
+ send_presence
121
+ end
122
+
123
+ private
124
+
125
+ def send_presence
126
+ roster.wait_for_roster
127
+
128
+ # TODO: vcard photo hash
129
+ if @presence_show == :unavailable
130
+ presence = Presence.new(nil, @presence_status)
131
+ presence.type = :unavailable
132
+ else
133
+ presence = Presence.new(@presence_show, @presence_status)
134
+ end
135
+ presence.add(disco_caps.generate_caps)
136
+ @stream.send(presence)
137
+ end
138
+
139
+ public
140
+
141
+ def add_pep_notification(node, &callback)
142
+ add_cap("#{node}+notify")
143
+ @pep_notifications << [node, callback]
144
+ end
145
+ end
146
+
147
+ end
148
+ end