cerberus 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
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