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,19 @@
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
+
7
+ module Jabber
8
+ module PubSub
9
+ NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
10
+ class IqPubSub < XMPPElement
11
+ name_xmlns 'pubsub', NS_PUBSUB
12
+ force_xmlns true
13
+ end
14
+ class IqPubSubOwner < XMPPElement
15
+ name_xmlns 'pubsub', NS_PUBSUB + '#owner'
16
+ force_xmlns true
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/xmppelement'
6
+
7
+ module Jabber
8
+ ##
9
+ # A class used to build/parse IQ Query requests/responses
10
+ #
11
+ class IqQuery < XMPPElement
12
+ name_xmlns 'query'
13
+ force_xmlns true
14
+ end
15
+ end
@@ -0,0 +1,151 @@
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 'rexml/document'
6
+ require 'rexml/parsers/xpathparser'
7
+ require 'rexml/source'
8
+
9
+ # Turn $VERBOSE off to suppress warnings about redefinition
10
+ oldverbose = $VERBOSE
11
+ $VERBOSE = false
12
+
13
+ # REXML : Adds custom helper methods to the REXML module.
14
+ #
15
+ module REXML
16
+
17
+ # this class adds a few helper methods to REXML::Element
18
+ class Element
19
+
20
+ ##
21
+ # Replaces or adds a child element of name <tt>e</tt> with text <tt>t</tt>.
22
+ def replace_element_text(e, t)
23
+ el = first_element(e)
24
+ if el.nil?
25
+ el = REXML::Element.new(e)
26
+ add_element(el)
27
+ end
28
+ if t
29
+ el.text = t
30
+ end
31
+ self
32
+ end
33
+
34
+ ##
35
+ # Returns first element of name <tt>e</tt>
36
+ def first_element(e)
37
+ each_element(e) { |el| return el }
38
+ return nil
39
+ end
40
+
41
+ ##
42
+ # Returns text of first element of name <tt>e</tt>
43
+ def first_element_text(e)
44
+ el = first_element(e)
45
+ if el
46
+ return el.text
47
+ else
48
+ return nil
49
+ end
50
+ end
51
+
52
+ # This method does exactly the same thing as add(), but it can be
53
+ # overriden by subclasses to provide on-the-fly object creations.
54
+ # For example, if you import a REXML::Element of name 'plop', and you
55
+ # have a Plop class that subclasses REXML::Element, with typed_add you
56
+ # can get your REXML::Element to be "magically" converted to Plop.
57
+ def typed_add(e)
58
+ add(e)
59
+ end
60
+
61
+ ##
62
+ # import this element's children and attributes
63
+ def import(xmlelement)
64
+ if @name and @name != xmlelement.name
65
+ raise "Trying to import an #{xmlelement.name} to a #{@name} !"
66
+ end
67
+ add_attributes(xmlelement.attributes.clone)
68
+ @context = xmlelement.context
69
+ xmlelement.each do |e|
70
+ if e.kind_of? REXML::Element
71
+ typed_add(e.deep_clone)
72
+ elsif e.kind_of? REXML::Text
73
+ add_text(e.value)
74
+ else
75
+ add(e.clone)
76
+ end
77
+ end
78
+ self
79
+ end
80
+
81
+ def self.import(xmlelement)
82
+ self.new(xmlelement.name).import(xmlelement)
83
+ end
84
+
85
+ ##
86
+ # Deletes one or more children elements,
87
+ # not just one like REXML::Element#delete_element
88
+ def delete_elements(element)
89
+ while(delete_element(element)) do end
90
+ end
91
+
92
+ ##
93
+ # Test for equality of two elements, useful for assert_equal in
94
+ # test cases. Tries to parse String o as XML.
95
+ #
96
+ # See Test::Unit::Assertions
97
+ def ==(o)
98
+ return false unless self.kind_of? REXML::Element
99
+ if o.kind_of? REXML::Element
100
+ # Ok
101
+ elsif o.kind_of? String
102
+ # Parse o
103
+ begin
104
+ o = REXML::Document.new(o).root
105
+ rescue REXML::ParseException
106
+ return false
107
+ end
108
+ else
109
+ # Cannot compare with anything other than Elements or Strings
110
+ return false
111
+ end
112
+
113
+ return false unless name == o.name
114
+
115
+ attributes.each_attribute do |attr|
116
+ return false unless attr.value == o.attributes[attr.name]
117
+ end
118
+
119
+ o.attributes.each_attribute do |attr|
120
+ return false unless attributes[attr.name] == attr.value
121
+ end
122
+
123
+ children.each_with_index do |child,i|
124
+ return false unless child == o.children[i]
125
+ end
126
+
127
+ return true
128
+ end
129
+
130
+ end # class Element
131
+
132
+ # FIXME : Is this still needed now that we're a bit past Ruby 1.8.3??
133
+ # Very dirty fix for the :progress problem in REXML from Ruby 1.8.3
134
+ # http://www.germane-software.com/projects/rexml/ticket/34
135
+ # the fix proposed in REXML changeset 1145 only fixes this for pipes, not for
136
+ # TCP sockets, so we have to keep this.
137
+ class IOSource
138
+ def position
139
+ 0
140
+ end
141
+
142
+ def current_line
143
+ [0, 0, ""]
144
+ end
145
+ end # class IOSource
146
+
147
+ end # module REXML
148
+
149
+ # Restore the old $VERBOSE setting
150
+ $VERBOSE = oldverbose
151
+
@@ -0,0 +1,7 @@
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/roster/iq/roster.rb'
6
+ require 'xmpp4r/roster/helper/roster.rb'
7
+ require 'xmpp4r/roster/x/roster.rb'
@@ -0,0 +1,519 @@
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 'thread'
7
+ require 'xmpp4r/roster/iq/roster'
8
+
9
+ module Jabber
10
+ module Roster
11
+ ##
12
+ # The Roster helper intercepts <tt><iq/></tt> stanzas with Jabber::IqQueryRoster
13
+ # and <tt><presence/></tt> stanzas, but provides cbs which allow the programmer
14
+ # to keep track of updates.
15
+ #
16
+ # A thread for any received stanza is spawned, so the user can invoke
17
+ # accept_subscription et al in the callback blocks, without stopping
18
+ # the current (= parser) thread when waiting for a reply.
19
+ class Helper
20
+ ##
21
+ # All items in your roster
22
+ # items:: [Hash] ([JID] => [Roster::Helper::RosterItem])
23
+ attr_reader :items
24
+
25
+ ##
26
+ # Initialize a new Roster helper
27
+ #
28
+ # Registers its cbs (prio = 120, ref = self)
29
+ #
30
+ # Request a roster
31
+ # (Remember to send initial presence afterwards!)
32
+ #
33
+ # The initialization will not wait for the roster being received,
34
+ # use wait_for_roster.
35
+ #
36
+ # <b>Attention:</b> If you send presence and receive presences
37
+ # before the roster has arrived, the Roster helper will let them
38
+ # pass through and does *not* keep them!
39
+ def initialize(stream)
40
+ @stream = stream
41
+ @items = {}
42
+ @items_lock = Mutex.new
43
+ @roster_wait = Semaphore.new
44
+ @query_cbs = CallbackList.new
45
+ @update_cbs = CallbackList.new
46
+ @presence_cbs = CallbackList.new
47
+ @subscription_cbs = CallbackList.new
48
+ @subscription_request_cbs = CallbackList.new
49
+
50
+ # Register cbs
51
+ stream.add_iq_callback(120, self) { |iq|
52
+ if iq.query.kind_of?(IqQueryRoster)
53
+ Thread.new do
54
+ Thread.current.abort_on_exception = true
55
+ handle_iq_query_roster(iq)
56
+ end
57
+
58
+ true
59
+ else
60
+ false
61
+ end
62
+ }
63
+ stream.add_presence_callback(120, self) { |pres|
64
+ Thread.new do
65
+ Thread.current.abort_on_exception = true
66
+ handle_presence(pres)
67
+ end
68
+ }
69
+
70
+ # Request the roster
71
+ rosterget = Iq.new_rosterget
72
+ stream.send(rosterget)
73
+ end
74
+
75
+ ##
76
+ # Wait for first roster query result to arrive
77
+ def wait_for_roster
78
+ @roster_wait.wait
79
+ @roster_wait.run
80
+ end
81
+
82
+ ##
83
+ # Add a callback to be called when a query has been processed
84
+ #
85
+ # Because update callbacks are called for each roster item,
86
+ # this may be appropriate to notify that *anything* has updated.
87
+ #
88
+ # Arguments for callback block: The received <tt><iq/></tt> stanza
89
+ def add_query_callback(prio = 0, ref = nil, &block)
90
+ @query_cbs.add(prio, ref, block)
91
+ end
92
+
93
+ ##
94
+ # Add a callback for Jabber::Roster::Helper::RosterItem updates
95
+ #
96
+ # Note that this will be called much after initialization
97
+ # for the answer of the initial roster request
98
+ #
99
+ # The block receives two objects:
100
+ # * the old Jabber::Roster::Helper::RosterItem
101
+ # * the new Jabber::Roster::Helper::RosterItem
102
+ def add_update_callback(prio = 0, ref = nil, &block)
103
+ @update_cbs.add(prio, ref, block)
104
+ end
105
+
106
+ ##
107
+ # Add a callback for Jabber::Presence updates
108
+ #
109
+ # This will be called for <tt><presence/></tt> stanzas for known RosterItems.
110
+ # Unknown JIDs may still pass and can be caught via Jabber::Stream#add_presence_callback.
111
+ #
112
+ # The block receives three objects:
113
+ # * the Jabber::Roster::Helper::RosterItem
114
+ # * the old Jabber::Presence (or nil)
115
+ # * the new Jabber::Presence (or nil)
116
+ def add_presence_callback(prio = 0, ref = nil, &block)
117
+ @presence_cbs.add(prio, ref, block)
118
+ end
119
+
120
+ ##
121
+ # Add a callback for subscription updates,
122
+ # which will be called upon receiving a <tt><presence/></tt> stanza
123
+ # with type:
124
+ # * :subscribed
125
+ # * :unsubscribe
126
+ # * :unsubscribed
127
+ #
128
+ # The block receives two objects:
129
+ # * the Jabber::Roster::Helper::RosterItem (or nil)
130
+ # * the <tt><presence/></tt> stanza
131
+ def add_subscription_callback(prio = 0, ref = nil, &block)
132
+ @subscription_cbs.add(prio, ref, block)
133
+ end
134
+
135
+ ##
136
+ # Add a callback for subscription requests,
137
+ # which will be called upon receiving a <tt><presence type='subscribe'/></tt> stanza
138
+ #
139
+ # The block receives two objects:
140
+ # * the Jabber::Roster::Helper::RosterItem (or nil)
141
+ # * the <tt><presence/></tt> stanza
142
+ #
143
+ # Response to this event can be taken with accept_subscription
144
+ # and decline_subscription.
145
+ #
146
+ # Example usage:
147
+ # my_roster.add_subscription_request_callback do |item,presence|
148
+ # if accept_subscription_requests
149
+ # my_roster.accept_subscription(presence.from)
150
+ # else
151
+ # my_roster.decline_subscription(presence.from)
152
+ # end
153
+ # end
154
+ def add_subscription_request_callback(prio = 0, ref = nil, &block)
155
+ @subscription_request_cbs.add(prio, ref, block)
156
+ end
157
+
158
+ private
159
+
160
+ ##
161
+ # Handle received <tt><iq/></tt> stanzas,
162
+ # used internally
163
+ def handle_iq_query_roster(iq)
164
+ # If the <iq/> contains <error/> we just ignore that
165
+ # and assume an empty roster
166
+ iq.query.each_element('item') do |item|
167
+ olditem, newitem = nil, nil
168
+
169
+ @items_lock.synchronize {
170
+ olditem = @items[item.jid]
171
+
172
+ # Handle deletion of item
173
+ if item.subscription == :remove
174
+ @items.delete(item.jid)
175
+ else
176
+ newitem = @items[item.jid] = RosterItem.new(@stream).import(item)
177
+ end
178
+ }
179
+ @update_cbs.process(olditem, newitem)
180
+ end
181
+
182
+ @roster_wait.run
183
+ @query_cbs.process(iq)
184
+ end
185
+
186
+ ##
187
+ # Handle received <tt><presence/></tt> stanzas,
188
+ # used internally
189
+ def handle_presence(pres)
190
+ item = self[pres.from]
191
+
192
+ if [:subscribed, :unsubscribe, :unsubscribed].include?(pres.type)
193
+ @subscription_cbs.process(item, pres)
194
+ true
195
+
196
+ elsif pres.type == :subscribe
197
+ @subscription_request_cbs.process(item, pres)
198
+ true
199
+
200
+ else
201
+ unless item.nil?
202
+ update_presence(item, pres)
203
+ true # Callback consumed stanza
204
+ else
205
+ false # Callback did not consume stanza
206
+ end
207
+ end
208
+ end
209
+
210
+ ##
211
+ # Update the presence of an item,
212
+ # used internally
213
+ #
214
+ # Callbacks are called here
215
+ def update_presence(item, pres)
216
+
217
+ # This requires special handling, to announce all resources offline
218
+ if pres.from.resource.nil? and pres.type == :error
219
+ oldpresences = []
220
+ item.each_presence do |oldpres|
221
+ oldpresences << oldpres
222
+ end
223
+
224
+ item.add_presence(pres)
225
+ oldpresences.each { |oldpres|
226
+ @presence_cbs.process(item, oldpres, pres)
227
+ }
228
+ else
229
+ oldpres = item.presence(pres.from).nil? ?
230
+ nil :
231
+ Presence.new.import(item.presence(pres.from))
232
+
233
+ item.add_presence(pres)
234
+ @presence_cbs.process(item, oldpres, pres)
235
+ end
236
+ end
237
+
238
+ public
239
+
240
+ ##
241
+ # Get an item by jid
242
+ #
243
+ # If not available tries to look for it with the resource stripped
244
+ def [](jid)
245
+ jid = JID.new(jid) unless jid.kind_of? JID
246
+
247
+ @items_lock.synchronize {
248
+ if @items.has_key?(jid)
249
+ @items[jid]
250
+ elsif @items.has_key?(jid.strip)
251
+ @items[jid.strip]
252
+ else
253
+ nil
254
+ end
255
+ }
256
+ end
257
+
258
+ ##
259
+ # Returns the list of RosterItems which, stripped, are equal to the
260
+ # one you are looking for.
261
+ def find(jid)
262
+ jid = JID.new(jid) unless jid.kind_of? JID
263
+
264
+ j = jid.strip
265
+ l = {}
266
+ @items_lock.synchronize {
267
+ @items.each_pair do |k, v|
268
+ l[k] = v if k.strip == j
269
+ end
270
+ }
271
+ l
272
+ end
273
+
274
+ ##
275
+ # Groups in this Roster,
276
+ # sorted by name
277
+ #
278
+ # Contains +nil+ if there are ungrouped items
279
+ # result:: [Array] containing group names (String)
280
+ def groups
281
+ res = []
282
+ @items_lock.synchronize {
283
+ @items.each_pair do |jid,item|
284
+ res += item.groups
285
+ res += [nil] if item.groups == []
286
+ end
287
+ }
288
+ res.uniq.sort { |a,b| a.to_s <=> b.to_s }
289
+ end
290
+
291
+ ##
292
+ # Get items in a group
293
+ #
294
+ # When group is nil, return ungrouped items
295
+ # group:: [String] Group name
296
+ # result:: Array of [RosterItem]
297
+ def find_by_group(group)
298
+ res = []
299
+ @items_lock.synchronize {
300
+ @items.each_pair do |jid,item|
301
+ res.push(item) if item.groups.include?(group)
302
+ res.push(item) if item.groups == [] and group.nil?
303
+ end
304
+ }
305
+ res
306
+ end
307
+
308
+ ##
309
+ # Add a user to your roster
310
+ #
311
+ # Threading is encouraged as the function waits for
312
+ # a result. ServerError is thrown upon error.
313
+ #
314
+ # See Jabber::Roster::Helper::RosterItem#subscribe for details
315
+ # about subscribing. (This method isn't used here but the
316
+ # same functionality applies.)
317
+ #
318
+ # If the item is already in the local roster
319
+ # it will simply send itself
320
+ # jid:: [JID] to add
321
+ # iname:: [String] Optional item name
322
+ # subscribe:: [Boolean] Whether to subscribe to this jid
323
+ def add(jid, iname=nil, subscribe=false)
324
+ if self[jid]
325
+ self[jid].send
326
+ else
327
+ request = Iq.new_rosterset
328
+ request.query.add(Jabber::Roster::RosterItem.new(jid, iname))
329
+ @stream.send_with_id(request)
330
+ # Adding to list is handled by handle_iq_query_roster
331
+ end
332
+
333
+ if subscribe
334
+ # Actually the item *should* already be known now,
335
+ # but we do it manually to exclude conditions.
336
+ pres = Presence.new.set_type(:subscribe).set_to(jid.strip)
337
+ @stream.send(pres)
338
+ end
339
+ end
340
+
341
+ ##
342
+ # Accept a subscription request
343
+ # * Sends a <presence type='subscribed'/> stanza
344
+ # * Adds the contact to your roster
345
+ # jid:: [JID] of contact
346
+ # iname:: [String] Optional roster item name
347
+ def accept_subscription(jid, iname=nil)
348
+ pres = Presence.new.set_type(:subscribed).set_to(jid.strip)
349
+ @stream.send(pres)
350
+
351
+ unless self[jid.strip]
352
+ request = Iq.new_rosterset
353
+ request.query.add(Jabber::Roster::RosterItem.new(jid.strip, iname))
354
+ @stream.send_with_id(request)
355
+ end
356
+ end
357
+
358
+ ##
359
+ # Decline a subscription request
360
+ # * Sends a <presence type='unsubscribed'/> stanza
361
+ def decline_subscription(jid)
362
+ pres = Presence.new.set_type(:unsubscribed).set_to(jid.strip)
363
+ @stream.send(pres)
364
+ end
365
+
366
+ ##
367
+ # These are extensions to RosterItem to carry presence information.
368
+ # This information is *not* stored in XML!
369
+ class RosterItem < Jabber::Roster::RosterItem
370
+ ##
371
+ # Tracked (online) presences of this RosterItem
372
+ attr_reader :presences
373
+
374
+ ##
375
+ # Initialize an empty RosterItem
376
+ def initialize(stream)
377
+ super()
378
+ @stream = stream
379
+ @presences = []
380
+ @presences_lock = Mutex.new
381
+ end
382
+
383
+ ##
384
+ # Send the updated RosterItem to the server,
385
+ # i.e. if you modified iname, groups, ...
386
+ def send
387
+ request = Iq.new_rosterset
388
+ request.query.add(self)
389
+ @stream.send(request)
390
+ end
391
+
392
+ ##
393
+ # Remove item
394
+ #
395
+ # This cancels both subscription *from* the contact to you
396
+ # and from you *to* the contact.
397
+ #
398
+ # The methods waits for a roster push from the server (success)
399
+ # or throws ServerError upon failure.
400
+ def remove
401
+ request = Iq.new_rosterset
402
+ request.query.add(Jabber::Roster::RosterItem.new(jid, nil, :remove))
403
+ @stream.send_with_id(request)
404
+ # Removing from list is handled by Roster#handle_iq_query_roster
405
+ end
406
+
407
+ ##
408
+ # Is any presence of this person on-line?
409
+ #
410
+ # (Or is there any presence? Unavailable presences are
411
+ # deleted.)
412
+ def online?
413
+ @presences_lock.synchronize {
414
+ @presences.select { |pres|
415
+ pres.type.nil?
416
+ }.size > 0
417
+ }
418
+ end
419
+
420
+ ##
421
+ # Iterate through all received <tt><presence/></tt> stanzas
422
+ def each_presence(&block)
423
+ # Don't lock here, we don't know what block does...
424
+ @presences.each { |pres|
425
+ yield(pres)
426
+ }
427
+ end
428
+
429
+ ##
430
+ # Get specific presence
431
+ # jid:: [JID] Full JID
432
+ def presence(jid)
433
+ @presences_lock.synchronize {
434
+ @presences.each { |pres|
435
+ return(pres) if pres.from == jid
436
+ }
437
+ }
438
+ nil
439
+ end
440
+
441
+ ##
442
+ # Add presence and sort presences
443
+ # (unless type is :unavailable or :error)
444
+ #
445
+ # This overwrites previous stanzas with the same destination
446
+ # JID to keep track of resources. Presence stanzas with
447
+ # <tt>type == :unavailable</tt> or <tt>type == :error</tt> will
448
+ # be deleted as this indicates that this resource has gone
449
+ # offline.
450
+ #
451
+ # If <tt>type == :error</tt> and the presence's origin has no
452
+ # specific resource the contact is treated completely offline.
453
+ def add_presence(newpres)
454
+ @presences_lock.synchronize {
455
+ # Delete old presences with the same JID
456
+ @presences.delete_if do |pres|
457
+ pres.from == newpres.from or pres.from.resource.nil?
458
+ end
459
+
460
+ if newpres.type == :error and newpres.from.resource.nil?
461
+ # Replace by single error presence
462
+ @presences = [newpres]
463
+ else
464
+ # Add new presence
465
+ @presences.push(newpres)
466
+ end
467
+
468
+ @presences.sort!
469
+ }
470
+ end
471
+
472
+ ##
473
+ # Send subscription request to the user
474
+ #
475
+ # The block given to Jabber::Roster::Roster#add_update_callback will
476
+ # be called, carrying the RosterItem with ask="subscribe"
477
+ #
478
+ # This function returns immediately after sending the subscription
479
+ # request and will not wait of approval or declination as it may
480
+ # take months for the contact to decide. ;-)
481
+ def subscribe
482
+ pres = Presence.new.set_type(:subscribe).set_to(jid.strip)
483
+ @stream.send(pres)
484
+ end
485
+
486
+ ##
487
+ # Unsubscribe from a contact's presence
488
+ #
489
+ # This method waits for a presence with type='unsubscribed'
490
+ # from the contact. It may throw ServerError upon failure.
491
+ #
492
+ # subscription attribute of the item is *from* or *none*
493
+ # afterwards. As long as you don't remove that item and
494
+ # subscription='from' the contact is subscribed to your
495
+ # presence.
496
+ def unsubscribe
497
+ pres = Presence.new.set_type(:unsubscribe).set_to(jid.strip)
498
+ @stream.send(pres) { |answer|
499
+ answer.type == :unsubscribed and
500
+ answer.from.strip == pres.to
501
+ }
502
+ end
503
+
504
+ ##
505
+ # Deny the contact to see your presence.
506
+ #
507
+ # This method will not wait and returns immediately
508
+ # as you will need no confirmation for this action.
509
+ #
510
+ # Though, you will get a roster update for that item,
511
+ # carrying either subscription='to' or 'none'.
512
+ def cancel_subscription
513
+ pres = Presence.new.set_type(:unsubscribed).set_to(jid)
514
+ @stream.send(pres)
515
+ end
516
+ end
517
+ end #Class Roster
518
+ end #Module Roster
519
+ end #Module Jabber