cerberus 0.6 → 0.7

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 (290) hide show
  1. data/Authors.txt +4 -0
  2. data/Changelog.txt +11 -0
  3. data/Copyright.txt +16 -0
  4. data/Rakefile +16 -25
  5. data/Readme.markdown +1 -3
  6. data/bin/cerberus +5 -0
  7. data/lib/cerberus/builder/bjam.rb +1 -3
  8. data/lib/cerberus/builder/maven2.rb +0 -1
  9. data/lib/cerberus/builder/rake.rb +1 -1
  10. data/lib/cerberus/builder/rspec.rb +0 -1
  11. data/lib/cerberus/builder/ruby_base.rb +0 -1
  12. data/lib/cerberus/component_lazy_loader.rb +6 -2
  13. data/lib/cerberus/config.example.yml +1 -0
  14. data/lib/cerberus/constants.rb +2 -2
  15. data/lib/cerberus/manager.rb +7 -1
  16. data/lib/cerberus/publisher/mail.rb +4 -4
  17. data/lib/cerberus/publisher/twitter.rb +0 -1
  18. data/lib/cerberus/scm/base.rb +19 -0
  19. data/lib/cerberus/scm/bzr.rb +62 -0
  20. data/lib/cerberus/scm/cvs.rb +2 -7
  21. data/lib/cerberus/scm/darcs.rb +2 -11
  22. data/lib/cerberus/scm/git.rb +6 -14
  23. data/lib/cerberus/scm/perforce.rb +4 -4
  24. data/lib/cerberus/scm/svn.rb +2 -7
  25. data/lib/cerberus/utils.rb +5 -0
  26. data/lib/vendor/irc/README +23 -0
  27. data/lib/vendor/irc/lib/IRC.rb +164 -0
  28. data/lib/vendor/irc/lib/IRCChannel.rb +33 -0
  29. data/lib/vendor/irc/lib/IRCConnection.rb +134 -0
  30. data/lib/vendor/irc/lib/IRCEvent.rb +91 -0
  31. data/lib/vendor/irc/lib/IRCUser.rb +23 -0
  32. data/lib/vendor/irc/lib/IRCUtil.rb +49 -0
  33. data/lib/vendor/irc/lib/eventmap.yml +247 -0
  34. data/lib/vendor/twitter/CHANGES +129 -0
  35. data/lib/vendor/twitter/MIT-LICENSE +20 -0
  36. data/lib/vendor/twitter/README +37 -0
  37. data/lib/vendor/twitter/TODO +7 -0
  38. data/lib/vendor/twitter/lib/twitter.rb +34 -0
  39. data/lib/vendor/twitter/lib/twitter/client.rb +24 -0
  40. data/lib/vendor/twitter/lib/twitter/client/account.rb +24 -0
  41. data/lib/vendor/twitter/lib/twitter/client/auth.rb +27 -0
  42. data/lib/vendor/twitter/lib/twitter/client/base.rb +93 -0
  43. data/lib/vendor/twitter/lib/twitter/client/blocks.rb +35 -0
  44. data/lib/vendor/twitter/lib/twitter/client/favorites.rb +53 -0
  45. data/lib/vendor/twitter/lib/twitter/client/friendship.rb +35 -0
  46. data/lib/vendor/twitter/lib/twitter/client/graph.rb +37 -0
  47. data/lib/vendor/twitter/lib/twitter/client/messaging.rb +79 -0
  48. data/lib/vendor/twitter/lib/twitter/client/profile.rb +29 -0
  49. data/lib/vendor/twitter/lib/twitter/client/search.rb +27 -0
  50. data/lib/vendor/twitter/lib/twitter/client/status.rb +51 -0
  51. data/lib/vendor/twitter/lib/twitter/client/timeline.rb +72 -0
  52. data/lib/vendor/twitter/lib/twitter/client/user.rb +65 -0
  53. data/lib/vendor/twitter/lib/twitter/config.rb +77 -0
  54. data/lib/vendor/twitter/lib/twitter/console.rb +31 -0
  55. data/lib/vendor/twitter/lib/twitter/core.rb +137 -0
  56. data/lib/vendor/twitter/lib/twitter/ext.rb +2 -0
  57. data/lib/vendor/twitter/lib/twitter/ext/stdlib.rb +52 -0
  58. data/lib/vendor/twitter/lib/twitter/extras.rb +39 -0
  59. data/lib/vendor/twitter/lib/twitter/meta.rb +56 -0
  60. data/lib/vendor/twitter/lib/twitter/model.rb +360 -0
  61. data/lib/vendor/twitter/lib/twitter/version.rb +19 -0
  62. data/lib/vendor/twitter/spec/twitter/client/account_spec.rb +28 -0
  63. data/lib/vendor/twitter/spec/twitter/client/auth_spec.rb +34 -0
  64. data/lib/vendor/twitter/spec/twitter/client/base_spec.rb +242 -0
  65. data/lib/vendor/twitter/spec/twitter/client/blocks_spec.rb +76 -0
  66. data/lib/vendor/twitter/spec/twitter/client/favorites_spec.rb +183 -0
  67. data/lib/vendor/twitter/spec/twitter/client/friendship_spec.rb +76 -0
  68. data/lib/vendor/twitter/spec/twitter/client/graph_spec.rb +67 -0
  69. data/lib/vendor/twitter/spec/twitter/client/messaging_spec.rb +135 -0
  70. data/lib/vendor/twitter/spec/twitter/client/profile_spec.rb +91 -0
  71. data/lib/vendor/twitter/spec/twitter/client/search_spec.rb +68 -0
  72. data/lib/vendor/twitter/spec/twitter/client/status_spec.rb +119 -0
  73. data/lib/vendor/twitter/spec/twitter/client/timeline_spec.rb +79 -0
  74. data/lib/vendor/twitter/spec/twitter/client/user_spec.rb +203 -0
  75. data/lib/vendor/twitter/spec/twitter/client_spec.rb +2 -0
  76. data/lib/vendor/twitter/spec/twitter/config_spec.rb +86 -0
  77. data/lib/vendor/twitter/spec/twitter/console_spec.rb +15 -0
  78. data/lib/vendor/twitter/spec/twitter/core_spec.rb +127 -0
  79. data/lib/vendor/twitter/spec/twitter/ext/stdlib_spec.rb +59 -0
  80. data/lib/vendor/twitter/spec/twitter/extras_spec.rb +46 -0
  81. data/lib/vendor/twitter/spec/twitter/meta_spec.rb +90 -0
  82. data/lib/vendor/twitter/spec/twitter/model_spec.rb +508 -0
  83. data/lib/vendor/twitter/spec/twitter/version_spec.rb +19 -0
  84. data/lib/vendor/xmpp4r/CHANGELOG +83 -0
  85. data/lib/vendor/xmpp4r/COPYING +340 -0
  86. data/lib/vendor/xmpp4r/LICENSE +59 -0
  87. data/lib/vendor/xmpp4r/README.rdoc +110 -0
  88. data/lib/vendor/xmpp4r/README_ruby19.txt +43 -0
  89. data/lib/vendor/xmpp4r/Rakefile +262 -0
  90. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/README +56 -0
  91. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/adventure.rb +23 -0
  92. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +136 -0
  93. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/cube.xml +15 -0
  94. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/tower.xml +69 -0
  95. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/world.rb +424 -0
  96. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
  97. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/fileserve.rb +346 -0
  98. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/getonline.rb +56 -0
  99. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/gtkmucclient.rb +315 -0
  100. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/migrate.rb +88 -0
  101. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
  102. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/pep-aggregator/index.xsl +235 -0
  103. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/pep-aggregator/pep-aggregator.rb +147 -0
  104. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/recvfile.rb +84 -0
  105. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +129 -0
  106. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/sendfile.conf +10 -0
  107. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/sendfile.rb +72 -0
  108. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr.rb +51 -0
  109. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_jabber.rb +43 -0
  110. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_test.rb +10 -0
  111. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/versionpoll.rb +90 -0
  112. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/xmpping.rb +146 -0
  113. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +14 -0
  114. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
  115. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/client.rb +70 -0
  116. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/component.rb +11 -0
  117. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/echo.rb +37 -0
  118. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
  119. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/mass_sender.rb +68 -0
  120. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +12 -0
  121. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/mucinfo.rb +41 -0
  122. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +82 -0
  123. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/register.rb +42 -0
  124. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
  125. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/roster.rb +44 -0
  126. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/rosterprint.rb +50 -0
  127. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/rosterrename.rb +34 -0
  128. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/rosterwatch.rb +171 -0
  129. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/send_vcard.rb +67 -0
  130. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/tune_client.rb +56 -0
  131. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/tune_server.rb +58 -0
  132. data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
  133. data/lib/vendor/xmpp4r/lib/xmpp4r.rb +116 -0
  134. data/lib/vendor/xmpp4r/lib/xmpp4r/base64.rb +32 -0
  135. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams.rb +15 -0
  136. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/filetransfer.rb +319 -0
  137. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/ibb/base.rb +257 -0
  138. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +31 -0
  139. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/ibb/target.rb +47 -0
  140. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +152 -0
  141. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +86 -0
  142. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +198 -0
  143. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +65 -0
  144. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +73 -0
  145. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb.orig +62 -0
  146. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/iq/bytestreams.rb +170 -0
  147. data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/iq/si.rb +206 -0
  148. data/lib/vendor/xmpp4r/lib/xmpp4r/callbacks.rb +124 -0
  149. data/lib/vendor/xmpp4r/lib/xmpp4r/caps.rb +1 -0
  150. data/lib/vendor/xmpp4r/lib/xmpp4r/caps/c.rb +53 -0
  151. data/lib/vendor/xmpp4r/lib/xmpp4r/caps/helper/generator.rb +160 -0
  152. data/lib/vendor/xmpp4r/lib/xmpp4r/caps/helper/helper.rb +87 -0
  153. data/lib/vendor/xmpp4r/lib/xmpp4r/client.rb +317 -0
  154. data/lib/vendor/xmpp4r/lib/xmpp4r/command/helper/responder.rb +53 -0
  155. data/lib/vendor/xmpp4r/lib/xmpp4r/command/iq/command.rb +154 -0
  156. data/lib/vendor/xmpp4r/lib/xmpp4r/component.rb +103 -0
  157. data/lib/vendor/xmpp4r/lib/xmpp4r/connection.rb +219 -0
  158. data/lib/vendor/xmpp4r/lib/xmpp4r/dataforms.rb +5 -0
  159. data/lib/vendor/xmpp4r/lib/xmpp4r/dataforms/x/data.rb +297 -0
  160. data/lib/vendor/xmpp4r/lib/xmpp4r/debuglog.rb +42 -0
  161. data/lib/vendor/xmpp4r/lib/xmpp4r/delay.rb +5 -0
  162. data/lib/vendor/xmpp4r/lib/xmpp4r/delay/x/delay.rb +99 -0
  163. data/lib/vendor/xmpp4r/lib/xmpp4r/discovery.rb +7 -0
  164. data/lib/vendor/xmpp4r/lib/xmpp4r/discovery/helper/responder.rb +165 -0
  165. data/lib/vendor/xmpp4r/lib/xmpp4r/discovery/iq/discoinfo.rb +211 -0
  166. data/lib/vendor/xmpp4r/lib/xmpp4r/discovery/iq/discoitems.rb +147 -0
  167. data/lib/vendor/xmpp4r/lib/xmpp4r/errors.rb +281 -0
  168. data/lib/vendor/xmpp4r/lib/xmpp4r/feature_negotiation.rb +5 -0
  169. data/lib/vendor/xmpp4r/lib/xmpp4r/feature_negotiation/iq/feature.rb +28 -0
  170. data/lib/vendor/xmpp4r/lib/xmpp4r/framework/base.rb +55 -0
  171. data/lib/vendor/xmpp4r/lib/xmpp4r/framework/bot.rb +148 -0
  172. data/lib/vendor/xmpp4r/lib/xmpp4r/httpbinding.rb +5 -0
  173. data/lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb +285 -0
  174. data/lib/vendor/xmpp4r/lib/xmpp4r/idgenerator.rb +37 -0
  175. data/lib/vendor/xmpp4r/lib/xmpp4r/iq.rb +221 -0
  176. data/lib/vendor/xmpp4r/lib/xmpp4r/jid.rb +167 -0
  177. data/lib/vendor/xmpp4r/lib/xmpp4r/message.rb +148 -0
  178. data/lib/vendor/xmpp4r/lib/xmpp4r/muc.rb +14 -0
  179. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/helper/mucbrowser.rb +92 -0
  180. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/helper/mucclient.rb +462 -0
  181. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/helper/simplemucclient.rb +332 -0
  182. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/iq/mucadmin.rb +23 -0
  183. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/iq/mucadminitem.rb +20 -0
  184. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/iq/mucowner.rb +15 -0
  185. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/item.rb +143 -0
  186. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/x/muc.rb +70 -0
  187. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/x/mucuserinvite.rb +60 -0
  188. data/lib/vendor/xmpp4r/lib/xmpp4r/muc/x/mucuseritem.rb +36 -0
  189. data/lib/vendor/xmpp4r/lib/xmpp4r/presence.rb +232 -0
  190. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub.rb +8 -0
  191. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/configuration.rb +86 -0
  192. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/event.rb +49 -0
  193. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/item.rb +35 -0
  194. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/items.rb +44 -0
  195. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/node_config.rb +48 -0
  196. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/publish.rb +24 -0
  197. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/subscription.rb +62 -0
  198. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/subscription_config.rb +67 -0
  199. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/unsubscribe.rb +48 -0
  200. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/helper/nodebrowser.rb +130 -0
  201. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/helper/nodehelper.rb +156 -0
  202. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/helper/servicehelper.rb +417 -0
  203. data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  204. data/lib/vendor/xmpp4r/lib/xmpp4r/query.rb +15 -0
  205. data/lib/vendor/xmpp4r/lib/xmpp4r/rexmladdons.rb +151 -0
  206. data/lib/vendor/xmpp4r/lib/xmpp4r/roster.rb +7 -0
  207. data/lib/vendor/xmpp4r/lib/xmpp4r/roster/helper/roster.rb +519 -0
  208. data/lib/vendor/xmpp4r/lib/xmpp4r/roster/iq/roster.rb +215 -0
  209. data/lib/vendor/xmpp4r/lib/xmpp4r/roster/x/roster.rb +138 -0
  210. data/lib/vendor/xmpp4r/lib/xmpp4r/rpc.rb +2 -0
  211. data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/helper/client.rb +123 -0
  212. data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/helper/server.rb +74 -0
  213. data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +67 -0
  214. data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/iq/rpc.rb +23 -0
  215. data/lib/vendor/xmpp4r/lib/xmpp4r/sasl.rb +237 -0
  216. data/lib/vendor/xmpp4r/lib/xmpp4r/semaphore.rb +38 -0
  217. data/lib/vendor/xmpp4r/lib/xmpp4r/stream.rb +497 -0
  218. data/lib/vendor/xmpp4r/lib/xmpp4r/streamparser.rb +77 -0
  219. data/lib/vendor/xmpp4r/lib/xmpp4r/tune.rb +2 -0
  220. data/lib/vendor/xmpp4r/lib/xmpp4r/tune/helper/helper.rb +58 -0
  221. data/lib/vendor/xmpp4r/lib/xmpp4r/tune/tune.rb +113 -0
  222. data/lib/vendor/xmpp4r/lib/xmpp4r/vcard.rb +6 -0
  223. data/lib/vendor/xmpp4r/lib/xmpp4r/vcard/helper/vcard.rb +84 -0
  224. data/lib/vendor/xmpp4r/lib/xmpp4r/vcard/iq/vcard.rb +109 -0
  225. data/lib/vendor/xmpp4r/lib/xmpp4r/version.rb +7 -0
  226. data/lib/vendor/xmpp4r/lib/xmpp4r/version/helper/responder.rb +72 -0
  227. data/lib/vendor/xmpp4r/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
  228. data/lib/vendor/xmpp4r/lib/xmpp4r/version/iq/version.rb +105 -0
  229. data/lib/vendor/xmpp4r/lib/xmpp4r/x.rb +37 -0
  230. data/lib/vendor/xmpp4r/lib/xmpp4r/xhtml.rb +1 -0
  231. data/lib/vendor/xmpp4r/lib/xmpp4r/xhtml/html.rb +115 -0
  232. data/lib/vendor/xmpp4r/lib/xmpp4r/xmpp4r.rb +18 -0
  233. data/lib/vendor/xmpp4r/lib/xmpp4r/xmppelement.rb +168 -0
  234. data/lib/vendor/xmpp4r/lib/xmpp4r/xmppstanza.rb +162 -0
  235. data/lib/vendor/xmpp4r/setup.rb +1586 -0
  236. data/lib/vendor/xmpp4r/test/bytestreams/tc_ibb.rb +186 -0
  237. data/lib/vendor/xmpp4r/test/bytestreams/tc_socks5bytestreams.rb +113 -0
  238. data/lib/vendor/xmpp4r/test/caps/tc_helper.rb +156 -0
  239. data/lib/vendor/xmpp4r/test/dataforms/tc_data.rb +81 -0
  240. data/lib/vendor/xmpp4r/test/delay/tc_xdelay.rb +51 -0
  241. data/lib/vendor/xmpp4r/test/discovery/tc_responder.rb +91 -0
  242. data/lib/vendor/xmpp4r/test/lib/assert_equal_xml.rb +14 -0
  243. data/lib/vendor/xmpp4r/test/lib/clienttester.rb +120 -0
  244. data/lib/vendor/xmpp4r/test/muc/tc_muc_mucclient.rb +830 -0
  245. data/lib/vendor/xmpp4r/test/muc/tc_muc_simplemucclient.rb +114 -0
  246. data/lib/vendor/xmpp4r/test/muc/tc_mucowner.rb +50 -0
  247. data/lib/vendor/xmpp4r/test/pubsub/tc_helper.rb +662 -0
  248. data/lib/vendor/xmpp4r/test/pubsub/tc_nodeconfig.rb +54 -0
  249. data/lib/vendor/xmpp4r/test/pubsub/tc_subscriptionconfig.rb +41 -0
  250. data/lib/vendor/xmpp4r/test/roster/tc_helper.rb +514 -0
  251. data/lib/vendor/xmpp4r/test/roster/tc_iqqueryroster.rb +173 -0
  252. data/lib/vendor/xmpp4r/test/roster/tc_xroster.rb +73 -0
  253. data/lib/vendor/xmpp4r/test/rpc/tc_helper.rb +96 -0
  254. data/lib/vendor/xmpp4r/test/tc_callbacks.rb +129 -0
  255. data/lib/vendor/xmpp4r/test/tc_class_names.rb +146 -0
  256. data/lib/vendor/xmpp4r/test/tc_client.rb +30 -0
  257. data/lib/vendor/xmpp4r/test/tc_errors.rb +146 -0
  258. data/lib/vendor/xmpp4r/test/tc_idgenerator.rb +30 -0
  259. data/lib/vendor/xmpp4r/test/tc_iq.rb +113 -0
  260. data/lib/vendor/xmpp4r/test/tc_iqquery.rb +31 -0
  261. data/lib/vendor/xmpp4r/test/tc_jid.rb +204 -0
  262. data/lib/vendor/xmpp4r/test/tc_message.rb +116 -0
  263. data/lib/vendor/xmpp4r/test/tc_presence.rb +150 -0
  264. data/lib/vendor/xmpp4r/test/tc_rexml.rb +139 -0
  265. data/lib/vendor/xmpp4r/test/tc_stream.rb +229 -0
  266. data/lib/vendor/xmpp4r/test/tc_streamComponent.rb +95 -0
  267. data/lib/vendor/xmpp4r/test/tc_streamError.rb +131 -0
  268. data/lib/vendor/xmpp4r/test/tc_streamSend.rb +59 -0
  269. data/lib/vendor/xmpp4r/test/tc_streamparser.rb +112 -0
  270. data/lib/vendor/xmpp4r/test/tc_xmppstanza.rb +135 -0
  271. data/lib/vendor/xmpp4r/test/ts_xmpp4r.rb +53 -0
  272. data/lib/vendor/xmpp4r/test/tune/tc_helper_recv.rb +84 -0
  273. data/lib/vendor/xmpp4r/test/tune/tc_helper_send.rb +74 -0
  274. data/lib/vendor/xmpp4r/test/tune/tc_tune.rb +79 -0
  275. data/lib/vendor/xmpp4r/test/vcard/tc_helper.rb +49 -0
  276. data/lib/vendor/xmpp4r/test/vcard/tc_iqvcard.rb +62 -0
  277. data/lib/vendor/xmpp4r/test/version/tc_helper.rb +60 -0
  278. data/lib/vendor/xmpp4r/test/version/tc_iqqueryversion.rb +97 -0
  279. data/lib/vendor/xmpp4r/test/xhtml/tc_html.rb +41 -0
  280. data/lib/vendor/xmpp4r/tools/gen_requires.bash +31 -0
  281. data/lib/vendor/xmpp4r/tools/xmpp4r-gemspec-test.rb +11 -0
  282. data/lib/vendor/xmpp4r/xmpp4r.gemspec +291 -0
  283. data/test/jabber_publisher_test.rb +1 -1
  284. data/test/mail_publisher_test.rb +2 -2
  285. data/test/mock/twitter.rb +0 -1
  286. data/test/rspec_builder_test.rb +39 -2
  287. data/test/rss_publisher_test.rb +1 -1
  288. data/test/twitter_publisher_test.rb +1 -1
  289. metadata +268 -53
  290. data/lib/cerberus/publisher/gmailer.rb +0 -17
@@ -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,237 @@
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.inspect}\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'])
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}")
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)
228
+ a1_h = h("#{username}:#{realm}:#{passwd}")
229
+ a1 = "#{a1_h}:#{nonce}:#{cnonce}"
230
+ #a2 = "AUTHENTICATE:#{digest_uri}#{(qop == 'auth') ? '' : ':00000000000000000000000000000000'}"
231
+ a2 = "AUTHENTICATE:#{digest_uri}"
232
+
233
+ hh("#{hh(a1)}:#{nonce}:00000001:#{cnonce}:#{qop}:#{hh(a2)}")
234
+ end
235
+ end
236
+ end
237
+ end
@@ -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
@@ -0,0 +1,497 @@
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/callbacks'
6
+ require 'socket'
7
+ require 'thread'
8
+ require 'xmpp4r/semaphore'
9
+ require 'xmpp4r/streamparser'
10
+ require 'xmpp4r/presence'
11
+ require 'xmpp4r/message'
12
+ require 'xmpp4r/iq'
13
+ require 'xmpp4r/debuglog'
14
+ require 'xmpp4r/idgenerator'
15
+
16
+ module Jabber
17
+ ##
18
+ # The stream class manages a connection stream (a file descriptor using which
19
+ # XML messages are read and sent)
20
+ #
21
+ # You may register callbacks for the three Jabber stanzas
22
+ # (message, presence and iq) and use the send and send_with_id
23
+ # methods.
24
+ #
25
+ # To ensure the order of received stanzas, callback blocks are
26
+ # launched in the parser thread. If further blocking operations
27
+ # are intended in those callbacks, run your own thread there.
28
+ class Stream
29
+ DISCONNECTED = 1
30
+ CONNECTED = 2
31
+
32
+ # file descriptor used
33
+ attr_reader :fd
34
+
35
+ # connection status
36
+ attr_reader :status
37
+
38
+ ##
39
+ # Initialize a new stream
40
+ def initialize
41
+ @fd = nil
42
+ @status = DISCONNECTED
43
+ @xmlcbs = CallbackList.new
44
+ @stanzacbs = CallbackList.new
45
+ @messagecbs = CallbackList.new
46
+ @iqcbs = CallbackList.new
47
+ @presencecbs = CallbackList.new
48
+ @send_lock = Mutex.new
49
+ @last_send = Time.now
50
+ @exception_block = nil
51
+ @threadblocks = []
52
+ @wakeup_thread = nil
53
+ @streamid = nil
54
+ @streamns = 'jabber:client'
55
+ @features_sem = Semaphore.new
56
+ @parser_thread = nil
57
+ end
58
+
59
+ ##
60
+ # Start the XML parser on the fd
61
+ def start(fd)
62
+ @stream_mechanisms = []
63
+ @stream_features = {}
64
+
65
+ @fd = fd
66
+ @parser = StreamParser.new(@fd, self)
67
+ @parser_thread = Thread.new do
68
+ Thread.current.abort_on_exception = true
69
+ begin
70
+ @parser.parse
71
+ Jabber::debuglog("DISCONNECTED\n")
72
+
73
+ if @exception_block
74
+ Thread.new { close!; @exception_block.call(nil, self, :disconnected) }
75
+ else
76
+ close!
77
+ end
78
+ rescue Exception => e
79
+ Jabber::debuglog("EXCEPTION:\n#{e.class}\n#{e.message}\n#{e.backtrace.join("\n")}")
80
+
81
+ if @exception_block
82
+ Thread.new do
83
+ Thread.current.abort_on_exception = true
84
+ close
85
+ @exception_block.call(e, self, :start)
86
+ end
87
+ else
88
+ Jabber::debuglog "Exception caught in Parser thread! (#{e.class})\n#{e.backtrace.join("\n")}"
89
+ close!
90
+ raise
91
+ end
92
+ end
93
+ end
94
+
95
+ @status = CONNECTED
96
+ end
97
+
98
+ def stop
99
+ @parser_thread.kill
100
+ @parser = nil
101
+ end
102
+
103
+ ##
104
+ # Mounts a block to handle exceptions if they occur during the
105
+ # poll send. This will likely be the first indication that
106
+ # the socket dropped in a Jabber Session.
107
+ #
108
+ # The block has to take three arguments:
109
+ # * the Exception
110
+ # * the Jabber::Stream object (self)
111
+ # * a symbol where it happened, namely :start, :parser, :sending and :end
112
+ def on_exception(&block)
113
+ @exception_block = block
114
+ end
115
+
116
+ ##
117
+ # This method is called by the parser when a failure occurs
118
+ def parse_failure(e)
119
+ Jabber::debuglog("EXCEPTION:\n#{e.class}\n#{e.message}\n#{e.backtrace.join("\n")}")
120
+
121
+ # A new thread has to be created because close will cause the thread
122
+ # to commit suicide(???)
123
+ if @exception_block
124
+ # New thread, because close will kill the current thread
125
+ Thread.new do
126
+ Thread.current.abort_on_exception = true
127
+ close
128
+ @exception_block.call(e, self, :parser)
129
+ end
130
+ else
131
+ Jabber::debuglog "Stream#parse_failure was called by XML parser. Dumping " +
132
+ "backtrace...\n" + e.exception + "\n#{e.backtrace.join("\n")}"
133
+ close
134
+ raise
135
+ end
136
+ end
137
+
138
+ ##
139
+ # This method is called by the parser upon receiving <tt></stream:stream></tt>
140
+ def parser_end
141
+ if @exception_block
142
+ Thread.new do
143
+ Thread.current.abort_on_exception = true
144
+ close
145
+ @exception_block.call(nil, self, :close)
146
+ end
147
+ else
148
+ close
149
+ end
150
+ end
151
+
152
+ ##
153
+ # Returns if this connection is connected to a Jabber service
154
+ # return:: [Boolean] Connection status
155
+ def is_connected?
156
+ return @status == CONNECTED
157
+ end
158
+
159
+ ##
160
+ # Returns if this connection is NOT connected to a Jabber service
161
+ #
162
+ # return:: [Boolean] Connection status
163
+ def is_disconnected?
164
+ return @status == DISCONNECTED
165
+ end
166
+
167
+ ##
168
+ # Processes a received REXML::Element and executes
169
+ # registered thread blocks and filters against it.
170
+ #
171
+ # element:: [REXML::Element] The received element
172
+ def receive(element)
173
+ Jabber::debuglog("RECEIVED:\n#{element.to_s}")
174
+
175
+ if element.namespace('').to_s == '' # REXML namespaces are always strings
176
+ element.add_namespace(@streamns)
177
+ end
178
+
179
+ case element.prefix
180
+ when 'stream'
181
+ case element.name
182
+ when 'stream'
183
+ stanza = element
184
+ @streamid = element.attributes['id']
185
+ @streamns = element.namespace('') if element.namespace('')
186
+
187
+ # Hack: component streams are basically client streams.
188
+ # Someday we may want to create special stanza classes
189
+ # for components/s2s deriving from normal stanzas but
190
+ # posessing these namespaces
191
+ @streamns = 'jabber:client' if @streamns == 'jabber:component:accept'
192
+
193
+ unless element.attributes['version'] # isn't XMPP compliant, so
194
+ Jabber::debuglog("FEATURES: server not XMPP compliant, will not wait for features")
195
+ @features_sem.run # don't wait for <stream:features/>
196
+ end
197
+ when 'features'
198
+ stanza = element
199
+ element.each { |e|
200
+ if e.name == 'mechanisms' and e.namespace == 'urn:ietf:params:xml:ns:xmpp-sasl'
201
+ e.each_element('mechanism') { |mech|
202
+ @stream_mechanisms.push(mech.text)
203
+ }
204
+ else
205
+ @stream_features[e.name] = e.namespace
206
+ end
207
+ }
208
+ Jabber::debuglog("FEATURES: received")
209
+ @features_sem.run
210
+ else
211
+ stanza = element
212
+ end
213
+ else
214
+ # Any stanza, classes are registered by XMPPElement::name_xmlns
215
+ begin
216
+ stanza = XMPPStanza::import(element)
217
+ rescue NoNameXmlnsRegistered
218
+ stanza = element
219
+ end
220
+ end
221
+
222
+ # Iterate through blocked threads (= waiting for an answer)
223
+ #
224
+ # We're dup'ping the @threadblocks here, so that we won't end up in an
225
+ # endless loop if Stream#send is being nested. That means, the nested
226
+ # threadblock won't receive the stanza currently processed, but the next
227
+ # one.
228
+ threadblocks = @threadblocks.dup
229
+ threadblocks.each { |threadblock|
230
+ exception = nil
231
+ r = false
232
+ begin
233
+ r = threadblock.call(stanza)
234
+ rescue Exception => e
235
+ exception = e
236
+ end
237
+
238
+ if r == true
239
+ @threadblocks.delete(threadblock)
240
+ threadblock.wakeup
241
+ return
242
+ elsif exception
243
+ @threadblocks.delete(threadblock)
244
+ threadblock.raise(exception)
245
+ end
246
+ }
247
+
248
+ Jabber::debuglog("PROCESSING:\n#{stanza.to_s} (#{stanza.class})")
249
+ return true if @xmlcbs.process(stanza)
250
+ return true if @stanzacbs.process(stanza)
251
+ case stanza
252
+ when Message
253
+ return true if @messagecbs.process(stanza)
254
+ when Iq
255
+ return true if @iqcbs.process(stanza)
256
+ when Presence
257
+ return true if @presencecbs.process(stanza)
258
+ end
259
+ end
260
+
261
+ ##
262
+ # This is used by Jabber::Stream internally to
263
+ # keep track of any blocks which were passed to
264
+ # Stream#send.
265
+ class ThreadBlock
266
+ def initialize(block)
267
+ @block = block
268
+ @waiter = Semaphore.new
269
+ @exception = nil
270
+ end
271
+ def call(*args)
272
+ @block.call(*args)
273
+ end
274
+ def wait
275
+ @waiter.wait
276
+ raise @exception if @exception
277
+ end
278
+ def wakeup
279
+ # TODO: Handle threadblock removal if !alive?
280
+ @waiter.run
281
+ end
282
+ def raise(exception)
283
+ @exception = exception
284
+ @waiter.run
285
+ end
286
+ end
287
+
288
+ def send_data(data)
289
+ @send_lock.synchronize do
290
+ @last_send = Time.now
291
+ @fd << data
292
+ @fd.flush
293
+ end
294
+ end
295
+
296
+ ##
297
+ # Sends XML data to the socket and (optionally) waits
298
+ # to process received data.
299
+ #
300
+ # Do not invoke this in a callback but in a seperate thread
301
+ # because we may not suspend the parser-thread (in whose
302
+ # context callbacks are executed).
303
+ #
304
+ # xml:: [String] The xml data to send
305
+ # &block:: [Block] The optional block
306
+ def send(xml, &block)
307
+ Jabber::debuglog("SENDING:\n#{xml}")
308
+ @threadblocks.unshift(threadblock = ThreadBlock.new(block)) if block
309
+ begin
310
+ # Temporarily remove stanza's namespace to
311
+ # reduce bandwidth consumption
312
+ if xml.kind_of? XMPPStanza and xml.namespace == 'jabber:client'
313
+ xml.delete_namespace
314
+ send_data(xml.to_s)
315
+ xml.add_namespace(@streamns)
316
+ else
317
+ send_data(xml.to_s)
318
+ end
319
+ rescue Exception => e
320
+ Jabber::debuglog("EXCEPTION:\n#{e.class}\n#{e.message}\n#{e.backtrace.join("\n")}")
321
+
322
+ if @exception_block
323
+ Thread.new do
324
+ Thread.current.abort_on_exception = true
325
+ close!
326
+ @exception_block.call(e, self, :sending)
327
+ end
328
+ else
329
+ Jabber::debuglog "Exception caught while sending! (#{e.class})\n#{e.backtrace.join("\n")}"
330
+ close!
331
+ raise
332
+ end
333
+ end
334
+ # The parser thread might be running this (think of a callback running send())
335
+ # If this is the case, we mustn't stop (or we would cause a deadlock)
336
+ if block and Thread.current != @parser_thread
337
+ threadblock.wait
338
+ elsif block
339
+ Jabber::debuglog("WARNING:\nCannot stop current thread in Jabber::Stream#send because it is the parser thread!")
340
+ end
341
+ end
342
+
343
+ ##
344
+ # Send an XMMP stanza with an Jabber::XMPPStanza#id. The id will be
345
+ # generated by Jabber::IdGenerator if not already set.
346
+ #
347
+ # The block will be called once: when receiving a stanza with the
348
+ # same Jabber::XMPPStanza#id. There is no need to return true to
349
+ # complete this! Instead the return value of the block will be
350
+ # returned. This is a direct result of unique request/response
351
+ # stanza identification via the id attribute.
352
+ #
353
+ # The block may be omitted. Then, the result will be the response
354
+ # stanza.
355
+ #
356
+ # Be aware that if a stanza with <tt>type='error'</tt> is received
357
+ # the function does not yield but raises an ServerError with
358
+ # the corresponding error element.
359
+ #
360
+ # Please see Stream#send for some implementational details.
361
+ #
362
+ # Please read the note about nesting at Stream#send
363
+ # xml:: [XMPPStanza]
364
+ def send_with_id(xml, &block)
365
+ if xml.id.nil?
366
+ xml.id = Jabber::IdGenerator.instance.generate_id
367
+ end
368
+
369
+ res = nil
370
+ error = nil
371
+ send(xml) do |received|
372
+ if received.kind_of? XMPPStanza and received.id == xml.id
373
+ if received.type == :error
374
+ error = (received.error ? received.error : ErrorResponse.new)
375
+ true
376
+ elsif block_given?
377
+ res = yield(received)
378
+ true
379
+ else
380
+ res = received
381
+ true
382
+ end
383
+ else
384
+ false
385
+ end
386
+ end
387
+
388
+ unless error.nil?
389
+ raise ServerError.new(error)
390
+ end
391
+
392
+ res
393
+ end
394
+
395
+ ##
396
+ # Adds a callback block to process received XML messages
397
+ #
398
+ # priority:: [Integer] The callback's priority, the higher, the sooner
399
+ # ref:: [String] The callback's reference
400
+ # &block:: [Block] The optional block
401
+ def add_xml_callback(priority = 0, ref = nil, &block)
402
+ @xmlcbs.add(priority, ref, block)
403
+ end
404
+
405
+ ##
406
+ # Delete an XML-messages callback
407
+ #
408
+ # ref:: [String] The reference of the callback to delete
409
+ def delete_xml_callback(ref)
410
+ @xmlcbs.delete(ref)
411
+ end
412
+
413
+ ##
414
+ # Adds a callback block to process received Messages
415
+ #
416
+ # priority:: [Integer] The callback's priority, the higher, the sooner
417
+ # ref:: [String] The callback's reference
418
+ # &block:: [Block] The optional block
419
+ def add_message_callback(priority = 0, ref = nil, &block)
420
+ @messagecbs.add(priority, ref, block)
421
+ end
422
+
423
+ ##
424
+ # Delete an Message callback
425
+ #
426
+ # ref:: [String] The reference of the callback to delete
427
+ def delete_message_callback(ref)
428
+ @messagecbs.delete(ref)
429
+ end
430
+
431
+ ##
432
+ # Adds a callback block to process received Stanzas
433
+ #
434
+ # priority:: [Integer] The callback's priority, the higher, the sooner
435
+ # ref:: [String] The callback's reference
436
+ # &block:: [Block] The optional block
437
+ def add_stanza_callback(priority = 0, ref = nil, &block)
438
+ @stanzacbs.add(priority, ref, block)
439
+ end
440
+
441
+ ##
442
+ # Delete a Stanza callback
443
+ #
444
+ # ref:: [String] The reference of the callback to delete
445
+ def delete_stanza_callback(ref)
446
+ @stanzacbs.delete(ref)
447
+ end
448
+
449
+ ##
450
+ # Adds a callback block to process received Presences
451
+ #
452
+ # priority:: [Integer] The callback's priority, the higher, the sooner
453
+ # ref:: [String] The callback's reference
454
+ # &block:: [Block] The optional block
455
+ def add_presence_callback(priority = 0, ref = nil, &block)
456
+ @presencecbs.add(priority, ref, block)
457
+ end
458
+
459
+ ##
460
+ # Delete a Presence callback
461
+ #
462
+ # ref:: [String] The reference of the callback to delete
463
+ def delete_presence_callback(ref)
464
+ @presencecbs.delete(ref)
465
+ end
466
+
467
+ ##
468
+ # Adds a callback block to process received Iqs
469
+ #
470
+ # priority:: [Integer] The callback's priority, the higher, the sooner
471
+ # ref:: [String] The callback's reference
472
+ # &block:: [Block] The optional block
473
+ def add_iq_callback(priority = 0, ref = nil, &block)
474
+ @iqcbs.add(priority, ref, block)
475
+ end
476
+
477
+ ##
478
+ # Delete an Iq callback
479
+ #
480
+ # ref:: [String] The reference of the callback to delete
481
+ #
482
+ def delete_iq_callback(ref)
483
+ @iqcbs.delete(ref)
484
+ end
485
+ ##
486
+ # Closes the connection to the Jabber service
487
+ def close
488
+ close!
489
+ end
490
+
491
+ def close!
492
+ @parser_thread.kill if @parser_thread
493
+ @fd.close if @fd and !@fd.closed?
494
+ @status = DISCONNECTED
495
+ end
496
+ end
497
+ end