ln-xmpp4r 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. data/CHANGELOG +91 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +59 -0
  4. data/README.rdoc +113 -0
  5. data/README_ruby19.txt +43 -0
  6. data/Rakefile +252 -0
  7. data/data/doc/xmpp4r/examples/advanced/adventure/README +56 -0
  8. data/data/doc/xmpp4r/examples/advanced/adventure/adventure.rb +23 -0
  9. data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +136 -0
  10. data/data/doc/xmpp4r/examples/advanced/adventure/cube.xml +15 -0
  11. data/data/doc/xmpp4r/examples/advanced/adventure/tower.xml +69 -0
  12. data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +424 -0
  13. data/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
  14. data/data/doc/xmpp4r/examples/advanced/fileserve.rb +346 -0
  15. data/data/doc/xmpp4r/examples/advanced/getonline.rb +56 -0
  16. data/data/doc/xmpp4r/examples/advanced/gtkmucclient.rb +315 -0
  17. data/data/doc/xmpp4r/examples/advanced/migrate.rb +88 -0
  18. data/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
  19. data/data/doc/xmpp4r/examples/advanced/pep-aggregator/index.xsl +235 -0
  20. data/data/doc/xmpp4r/examples/advanced/pep-aggregator/pep-aggregator.rb +147 -0
  21. data/data/doc/xmpp4r/examples/advanced/recvfile.rb +84 -0
  22. data/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +129 -0
  23. data/data/doc/xmpp4r/examples/advanced/sendfile.conf +10 -0
  24. data/data/doc/xmpp4r/examples/advanced/sendfile.rb +72 -0
  25. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr.rb +51 -0
  26. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_jabber.rb +43 -0
  27. data/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_test.rb +10 -0
  28. data/data/doc/xmpp4r/examples/advanced/versionpoll.rb +109 -0
  29. data/data/doc/xmpp4r/examples/advanced/xmpping.rb +146 -0
  30. data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +14 -0
  31. data/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
  32. data/data/doc/xmpp4r/examples/basic/client.rb +70 -0
  33. data/data/doc/xmpp4r/examples/basic/component.rb +11 -0
  34. data/data/doc/xmpp4r/examples/basic/echo.rb +37 -0
  35. data/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
  36. data/data/doc/xmpp4r/examples/basic/mass_sender.rb +68 -0
  37. data/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +12 -0
  38. data/data/doc/xmpp4r/examples/basic/mucinfo.rb +41 -0
  39. data/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +82 -0
  40. data/data/doc/xmpp4r/examples/basic/register.rb +42 -0
  41. data/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
  42. data/data/doc/xmpp4r/examples/basic/roster.rb +44 -0
  43. data/data/doc/xmpp4r/examples/basic/rosterprint.rb +50 -0
  44. data/data/doc/xmpp4r/examples/basic/rosterrename.rb +34 -0
  45. data/data/doc/xmpp4r/examples/basic/rosterwatch.rb +171 -0
  46. data/data/doc/xmpp4r/examples/basic/send_vcard.rb +67 -0
  47. data/data/doc/xmpp4r/examples/basic/tune_client.rb +56 -0
  48. data/data/doc/xmpp4r/examples/basic/tune_server.rb +58 -0
  49. data/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
  50. data/lib/xmpp4r.rb +116 -0
  51. data/lib/xmpp4r/base64.rb +32 -0
  52. data/lib/xmpp4r/bytestreams.rb +15 -0
  53. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +319 -0
  54. data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +257 -0
  55. data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +31 -0
  56. data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +54 -0
  57. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +152 -0
  58. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +86 -0
  59. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +198 -0
  60. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +65 -0
  61. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +79 -0
  62. data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +170 -0
  63. data/lib/xmpp4r/bytestreams/iq/si.rb +206 -0
  64. data/lib/xmpp4r/callbacks.rb +133 -0
  65. data/lib/xmpp4r/caps.rb +1 -0
  66. data/lib/xmpp4r/caps/c.rb +67 -0
  67. data/lib/xmpp4r/caps/helper/generator.rb +160 -0
  68. data/lib/xmpp4r/caps/helper/helper.rb +84 -0
  69. data/lib/xmpp4r/client.rb +344 -0
  70. data/lib/xmpp4r/command/helper/responder.rb +53 -0
  71. data/lib/xmpp4r/command/iq/command.rb +154 -0
  72. data/lib/xmpp4r/component.rb +103 -0
  73. data/lib/xmpp4r/connection.rb +223 -0
  74. data/lib/xmpp4r/dataforms.rb +5 -0
  75. data/lib/xmpp4r/dataforms/x/data.rb +297 -0
  76. data/lib/xmpp4r/debuglog.rb +63 -0
  77. data/lib/xmpp4r/delay.rb +5 -0
  78. data/lib/xmpp4r/delay/x/delay.rb +99 -0
  79. data/lib/xmpp4r/discovery.rb +8 -0
  80. data/lib/xmpp4r/discovery/helper/helper.rb +58 -0
  81. data/lib/xmpp4r/discovery/helper/responder.rb +165 -0
  82. data/lib/xmpp4r/discovery/iq/discoinfo.rb +211 -0
  83. data/lib/xmpp4r/discovery/iq/discoitems.rb +147 -0
  84. data/lib/xmpp4r/errors.rb +284 -0
  85. data/lib/xmpp4r/feature_negotiation.rb +5 -0
  86. data/lib/xmpp4r/feature_negotiation/iq/feature.rb +28 -0
  87. data/lib/xmpp4r/framework/base.rb +55 -0
  88. data/lib/xmpp4r/framework/bot.rb +148 -0
  89. data/lib/xmpp4r/httpbinding.rb +5 -0
  90. data/lib/xmpp4r/httpbinding/client.rb +275 -0
  91. data/lib/xmpp4r/idgenerator.rb +37 -0
  92. data/lib/xmpp4r/iq.rb +221 -0
  93. data/lib/xmpp4r/jid.rb +167 -0
  94. data/lib/xmpp4r/last.rb +2 -0
  95. data/lib/xmpp4r/last/helper/helper.rb +37 -0
  96. data/lib/xmpp4r/last/iq/last.rb +67 -0
  97. data/lib/xmpp4r/location.rb +2 -0
  98. data/lib/xmpp4r/location/helper/helper.rb +56 -0
  99. data/lib/xmpp4r/location/location.rb +179 -0
  100. data/lib/xmpp4r/message.rb +180 -0
  101. data/lib/xmpp4r/muc.rb +14 -0
  102. data/lib/xmpp4r/muc/helper/mucbrowser.rb +92 -0
  103. data/lib/xmpp4r/muc/helper/mucclient.rb +462 -0
  104. data/lib/xmpp4r/muc/helper/simplemucclient.rb +332 -0
  105. data/lib/xmpp4r/muc/iq/mucadmin.rb +23 -0
  106. data/lib/xmpp4r/muc/iq/mucadminitem.rb +20 -0
  107. data/lib/xmpp4r/muc/iq/mucowner.rb +15 -0
  108. data/lib/xmpp4r/muc/item.rb +143 -0
  109. data/lib/xmpp4r/muc/x/muc.rb +70 -0
  110. data/lib/xmpp4r/muc/x/mucuserinvite.rb +60 -0
  111. data/lib/xmpp4r/muc/x/mucuseritem.rb +36 -0
  112. data/lib/xmpp4r/presence.rb +232 -0
  113. data/lib/xmpp4r/pubsub.rb +8 -0
  114. data/lib/xmpp4r/pubsub/children/configuration.rb +86 -0
  115. data/lib/xmpp4r/pubsub/children/event.rb +49 -0
  116. data/lib/xmpp4r/pubsub/children/item.rb +35 -0
  117. data/lib/xmpp4r/pubsub/children/items.rb +53 -0
  118. data/lib/xmpp4r/pubsub/children/node_config.rb +48 -0
  119. data/lib/xmpp4r/pubsub/children/publish.rb +38 -0
  120. data/lib/xmpp4r/pubsub/children/retract.rb +41 -0
  121. data/lib/xmpp4r/pubsub/children/subscription.rb +62 -0
  122. data/lib/xmpp4r/pubsub/children/subscription_config.rb +67 -0
  123. data/lib/xmpp4r/pubsub/children/unsubscribe.rb +48 -0
  124. data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +129 -0
  125. data/lib/xmpp4r/pubsub/helper/nodehelper.rb +156 -0
  126. data/lib/xmpp4r/pubsub/helper/oauth_service_helper.rb +90 -0
  127. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +456 -0
  128. data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  129. data/lib/xmpp4r/query.rb +15 -0
  130. data/lib/xmpp4r/reliable.rb +168 -0
  131. data/lib/xmpp4r/rexmladdons.rb +157 -0
  132. data/lib/xmpp4r/roster.rb +7 -0
  133. data/lib/xmpp4r/roster/helper/roster.rb +522 -0
  134. data/lib/xmpp4r/roster/iq/roster.rb +215 -0
  135. data/lib/xmpp4r/roster/x/roster.rb +138 -0
  136. data/lib/xmpp4r/rpc.rb +2 -0
  137. data/lib/xmpp4r/rpc/helper/client.rb +123 -0
  138. data/lib/xmpp4r/rpc/helper/server.rb +74 -0
  139. data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +67 -0
  140. data/lib/xmpp4r/rpc/iq/rpc.rb +23 -0
  141. data/lib/xmpp4r/sasl.rb +248 -0
  142. data/lib/xmpp4r/semaphore.rb +38 -0
  143. data/lib/xmpp4r/stream.rb +599 -0
  144. data/lib/xmpp4r/streamparser.rb +85 -0
  145. data/lib/xmpp4r/test/listener_mocker.rb +118 -0
  146. data/lib/xmpp4r/tune.rb +2 -0
  147. data/lib/xmpp4r/tune/helper/helper.rb +58 -0
  148. data/lib/xmpp4r/tune/tune.rb +113 -0
  149. data/lib/xmpp4r/vcard.rb +6 -0
  150. data/lib/xmpp4r/vcard/helper/vcard.rb +84 -0
  151. data/lib/xmpp4r/vcard/iq/vcard.rb +109 -0
  152. data/lib/xmpp4r/version.rb +7 -0
  153. data/lib/xmpp4r/version/helper/responder.rb +72 -0
  154. data/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
  155. data/lib/xmpp4r/version/iq/version.rb +105 -0
  156. data/lib/xmpp4r/x.rb +37 -0
  157. data/lib/xmpp4r/xhtml.rb +1 -0
  158. data/lib/xmpp4r/xhtml/html.rb +115 -0
  159. data/lib/xmpp4r/xmpp4r.rb +20 -0
  160. data/lib/xmpp4r/xmppelement.rb +168 -0
  161. data/lib/xmpp4r/xmppstanza.rb +162 -0
  162. data/setup.rb +1586 -0
  163. data/test/bytestreams/tc_ibb.rb +188 -0
  164. data/test/bytestreams/tc_socks5bytestreams.rb +114 -0
  165. data/test/caps/tc_helper.rb +158 -0
  166. data/test/dataforms/tc_data.rb +81 -0
  167. data/test/delay/tc_xdelay.rb +51 -0
  168. data/test/discovery/tc_responder.rb +91 -0
  169. data/test/last/tc_helper.rb +75 -0
  170. data/test/lib/assert_equal_xml.rb +14 -0
  171. data/test/lib/clienttester.rb +149 -0
  172. data/test/muc/tc_muc_mucclient.rb +834 -0
  173. data/test/muc/tc_muc_simplemucclient.rb +114 -0
  174. data/test/muc/tc_mucowner.rb +50 -0
  175. data/test/pubsub/tc_helper.rb +785 -0
  176. data/test/pubsub/tc_nodeconfig.rb +61 -0
  177. data/test/pubsub/tc_subscriptionconfig.rb +41 -0
  178. data/test/reliable/tc_disconnect_cleanup.rb +334 -0
  179. data/test/reliable/tc_disconnect_exception.rb +37 -0
  180. data/test/reliable/tc_listener_mocked_test.rb +68 -0
  181. data/test/reliable/tc_reliable_connection.rb +31 -0
  182. data/test/roster/tc_helper.rb +524 -0
  183. data/test/roster/tc_iqqueryroster.rb +173 -0
  184. data/test/roster/tc_xroster.rb +73 -0
  185. data/test/rpc/tc_helper.rb +96 -0
  186. data/test/tc_callbacks.rb +129 -0
  187. data/test/tc_class_names.rb +146 -0
  188. data/test/tc_client.rb +30 -0
  189. data/test/tc_errors.rb +146 -0
  190. data/test/tc_idgenerator.rb +30 -0
  191. data/test/tc_iq.rb +113 -0
  192. data/test/tc_iqquery.rb +31 -0
  193. data/test/tc_jid.rb +204 -0
  194. data/test/tc_message.rb +131 -0
  195. data/test/tc_presence.rb +150 -0
  196. data/test/tc_rexml.rb +139 -0
  197. data/test/tc_stream.rb +167 -0
  198. data/test/tc_streamComponent.rb +95 -0
  199. data/test/tc_streamError.rb +129 -0
  200. data/test/tc_streamSend.rb +59 -0
  201. data/test/tc_streamparser.rb +125 -0
  202. data/test/tc_xmppstanza.rb +135 -0
  203. data/test/ts_xmpp4r.rb +44 -0
  204. data/test/tune/tc_helper_recv.rb +82 -0
  205. data/test/tune/tc_helper_send.rb +74 -0
  206. data/test/tune/tc_tune.rb +79 -0
  207. data/test/vcard/tc_helper.rb +49 -0
  208. data/test/vcard/tc_iqvcard.rb +62 -0
  209. data/test/version/tc_helper.rb +60 -0
  210. data/test/version/tc_iqqueryversion.rb +97 -0
  211. data/test/xhtml/tc_html.rb +41 -0
  212. data/tools/gen_requires.bash +31 -0
  213. data/tools/xmpp4r-gemspec-test.rb +11 -0
  214. data/xmpp4r.gemspec +238 -0
  215. metadata +280 -0
@@ -0,0 +1,129 @@
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/discovery'
6
+
7
+ module Jabber
8
+ module PubSub
9
+ class NodeBrowser
10
+ ##
11
+ # Initialize a new NodeBrowser
12
+ # new(stream,pubsubservice)
13
+ # stream:: [Jabber::Stream]
14
+ def initialize(stream)
15
+ @stream = stream
16
+ end
17
+
18
+ ##
19
+ # Retrieve the nodes
20
+ # Throws an ServerError when receiving
21
+ # <tt><iq type='error'/></tt>
22
+ # jid:: [JID] Target entity (set only domain!)
23
+ # return:: [Array] of [String] or [nil]
24
+ def nodes(jid)
25
+ iq = Iq.new(:get,jid)
26
+ iq.from = @stream.jid
27
+ iq.add(Discovery::IqQueryDiscoItems.new)
28
+ nodes = []
29
+ @stream.send_with_id(iq) do |answer|
30
+ answer.query.each_element('item') { |item|
31
+ nodes.push(item.node)
32
+ }
33
+ end
34
+ nodes
35
+ end
36
+
37
+ ##
38
+ # Retrieve the nodes with names
39
+ # Throws a ServerError when receiving
40
+ # <tt><iq type='error'/></tt>
41
+ # jid:: [Jabber::JID] Target entity (set only domain!)
42
+ # return:: [Array] of [Hash] with keys 'node' => [String] and 'name' => [String] or [nil]
43
+ def nodes_names(jid)
44
+ iq = Iq.new(:get,jid)
45
+ iq.from = @stream.jid
46
+ iq.add(Discovery::IqQueryDiscoItems.new)
47
+ nodes = []
48
+ @stream.send_with_id(iq) do |answer|
49
+ answer.query.each_element('item') do |item|
50
+ nodes.push( {'node' => item.node,'name' => item.iname } )
51
+ end
52
+ end
53
+ nodes
54
+ end
55
+
56
+
57
+ ##
58
+ # Retrieve the items from a node
59
+ # Throws an ServerError when receiving
60
+ # <tt><iq type='error'/></tt>
61
+ # jid:: [Jabber::JID] Target entity (set only domain!)
62
+ # node:: [String]
63
+ # return:: [Array] of [Hash] with keys 'name' => [String] and 'jid' => [Jabber::JID]
64
+ def items(jid,node)
65
+ iq = Iq.new(:get,jid)
66
+ iq.from = @stream.jid
67
+ discoitems = Discovery::IqQueryDiscoItems.new
68
+ discoitems.node = node
69
+ iq.add(discoitems)
70
+ items = []
71
+ err = nil
72
+ @stream.send_with_id(iq) do |answer|
73
+ answer.query.each_element('item') { |item|
74
+ items.push( {'jid' => item.jid,'name' => item.iname } )
75
+ }
76
+ end
77
+ items
78
+ end
79
+
80
+ ##
81
+ # get disco info for a node
82
+ # jid:: [Jabber::JID]
83
+ # node:: [String]
84
+ # return:: [Hash] with possible keys type:: [String] ,category:: [String],features:: [Array] of feature, nodeinformation:: [Jabber::XData]
85
+ # check http://www.xmpp.org/extensions/xep-0060.html#entity for more infos
86
+ def get_info(jid,node)
87
+ iq = Iq.new(:get,jid)
88
+ iq.from = @stream.jid
89
+ discoinfo = Discovery::IqQueryDiscoInfo.new
90
+ discoinfo.node = node
91
+ iq.add(discoinfo)
92
+ info = {}
93
+ @stream.send_with_id(iq) do |answer|
94
+ identity = answer.query.identity
95
+ info['type'] = identity.type
96
+ info['category'] = identity.category
97
+ info['features'] = answer.query.features
98
+ answer.query.each_element('x') { |x|
99
+ info['nodeinformation'] = x
100
+ }
101
+ end
102
+ info
103
+ end
104
+ # this is only for a xep <-> nodebrowser.rb understanding
105
+ alias get_metadata get_info
106
+
107
+ ##
108
+ # get type of node
109
+ # jid:: [Jabber::JID]
110
+ # node:: [String]
111
+ #
112
+ def type(jid,node)
113
+ info = get_info(jid,node)
114
+ return info['type']
115
+ end
116
+
117
+ ##
118
+ # get category of node
119
+ # jid:: [Jabber::JID]
120
+ # node:: [String]
121
+ #
122
+ def category(jid,node)
123
+ info = get_info(jid,node)
124
+ return info['category']
125
+ end
126
+
127
+ end #class
128
+ end #module
129
+ end #module
@@ -0,0 +1,156 @@
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
+ # For documentation of the return values please see [Jabber::PubSub::ServiceHelper]
6
+ # This class is only a wrapper around [Jabber::PubSub::ServiceHelper]
7
+ #
8
+
9
+
10
+ require 'xmpp4r/pubsub/helper/servicehelper'
11
+ require 'xmpp4r/pubsub/helper/nodebrowser'
12
+
13
+ module Jabber
14
+ module PubSub
15
+ class NodeHelper < ServiceHelper
16
+
17
+ attr_reader :nodename
18
+ attr_reader :name
19
+ attr_reader :jid
20
+ attr_reader :my_subscriptions
21
+ ##
22
+ # creates a new node
23
+ # new(client,service,nodename)
24
+ # stream:: [Jabber::Stream]
25
+ # jid:: [String] (jid of the pubsub service)
26
+ # nodename:: [String]
27
+ def initialize(stream, jid, nodename = nil, create_if_not_exist = true)
28
+ super(stream,jid)
29
+ @nodename = nodename
30
+ @jid = jid
31
+ @stream = stream
32
+
33
+ if create_if_not_exist and !node_exist?
34
+ # if no nodename is given a instant node will created
35
+ # (if the service supports instant nodes)
36
+ @nodename = create_node
37
+ else
38
+ get_subscriptions
39
+ end
40
+ end
41
+
42
+ ##
43
+ # creates the node
44
+ # create(configuration=nil)
45
+ # configuration:: [Jabber::XData]
46
+ def create_node(configuration = Jabber::PubSub::NodeConfig.new)
47
+ unless node_exist?
48
+ super(@nodename,configuration)
49
+ else
50
+ false
51
+ end
52
+ end
53
+
54
+ ##
55
+ # get the configuration of the node
56
+ # get_configuration(configuration=nil)
57
+ # configuration:: [Jabber::XData]
58
+ def get_configuration(subid = nil)
59
+ get_options(@nodename, subid)
60
+ end
61
+
62
+ ##
63
+ # set the configuration of the node
64
+ # set_configuration(configuration=nil)
65
+ # configuration:: [Jabber::XData]
66
+ # subid:: [String] default is nil
67
+ def set_configuration(configuration,subid = nil)
68
+ set_options(@nodename, configuration, subid)
69
+ end
70
+
71
+ ##
72
+ # deletes the node
73
+ # delete
74
+ def delete_node
75
+ delete(@nodename)
76
+ end
77
+
78
+ ##
79
+ # publishing content on this node
80
+ # publish_content(items)
81
+ # items:: [REXML::Element]
82
+ def publish_content(items)
83
+ publish_item_to(@nodename,items)
84
+ end
85
+
86
+ ##
87
+ # gets all items from the node
88
+ # get_all_items
89
+ def get_all_items
90
+ get_items_from(@nodename)
91
+ end
92
+
93
+ ##
94
+ # get a count of items
95
+ # get_items(count)
96
+ # count:: [Fixnum]
97
+ def get_items(count)
98
+ get_items_from(@nodename,count)
99
+ end
100
+
101
+ ##
102
+ # get all node affiliations
103
+ # get_affiliations
104
+ def get_affiliations
105
+ affiliations
106
+ end
107
+
108
+ ##
109
+ # get all subscriptions on this node
110
+ # get_subscriptions
111
+ def get_subscriptions
112
+ get_subscriptions_from(@nodename)
113
+ end
114
+
115
+ ##
116
+ # get all subscribers subscribed on this node
117
+ # get_subscribers
118
+ def get_subscribers
119
+ @subscriptions = subscribers(@nodename)
120
+ end
121
+
122
+ ##
123
+ # subscribe to this node
124
+ # do_subscribe
125
+ def do_subscribe
126
+ subscribe_to(@nodename)
127
+ get_subscriptions
128
+ end
129
+
130
+ ##
131
+ # unsubscribe from this node
132
+ # do_unsubscribe(subid = nil)
133
+ # subid:: [String]
134
+ def do_unsubscribe(subid)
135
+ unsubscribe(@nodename,subid)
136
+ end
137
+
138
+ ##
139
+ # purge all items from this node
140
+ # purge_items
141
+ def purge_items
142
+ purge(@nodename)
143
+ end
144
+
145
+ private
146
+
147
+ def node_exist?
148
+ nodebrowser = PubSub::NodeBrowser.new(@stream)
149
+ nodebrowser.nodes(@jid).include?(@nodename)
150
+ end
151
+ def disco_info
152
+ end
153
+
154
+ end #class
155
+ end #module
156
+ end #module
@@ -0,0 +1,90 @@
1
+ module Jabber
2
+ module PubSub
3
+ # Jabber::Stream helper that will transparently sign PubSub requests
4
+ module OAuthPubSubStreamHelper
5
+ attr_accessor :pubsubjid, :oauth_consumer, :oauth_token, :oauth_options
6
+
7
+ # enhanced #send_with_id method that signs stanzas
8
+ def send_with_id(iq)
9
+ if iq.first_element("pubsub")
10
+ oauth = OAuthServiceHelper.create_oauth_node(self.jid, self.pubsubjid, self.oauth_consumer, self.oauth_token, self.oauth_options)
11
+ iq.pubsub.add(oauth)
12
+ end
13
+
14
+ super(iq)
15
+ end
16
+ end
17
+
18
+ # PubSub service helper for use with OAuth-authenticated nodes
19
+ class OAuthServiceHelper < ServiceHelper
20
+ def initialize(stream, pubsubjid, oauth_consumer, oauth_token, options = {})
21
+ # imbue the stream with magical OAuth signing powers
22
+ stream.extend(OAuthPubSubStreamHelper)
23
+ stream.oauth_consumer = oauth_consumer
24
+ stream.oauth_token = oauth_token
25
+ stream.oauth_options = options
26
+ stream.pubsubjid = pubsubjid
27
+
28
+ super(stream, pubsubjid)
29
+ end
30
+
31
+ # add the OAuth sauce (XEP-0235)
32
+ # The `options` hash may contain the following parameters:
33
+ # :oauth_nonce => nonce (one will be generated otherwise)
34
+ # :oauth_timestamp => timestamp (one will be generated otherwise)
35
+ # :oauth_signature_method => signature method (defaults to HMAC-SHA1)
36
+ # :oauth_version => OAuth version (defaults to "1.0")
37
+ def self.create_oauth_node(jid, pubsubjid, oauth_consumer, oauth_token, options = {})
38
+ require 'oauth'
39
+
40
+ request = OAuth::RequestProxy.proxy \
41
+ "method" => "iq",
42
+ "uri" => [jid.strip.to_s, pubsubjid.strip.to_s] * "&",
43
+ "parameters" => {
44
+ "oauth_consumer_key" => oauth_consumer.key,
45
+ "oauth_nonce" => options[:oauth_nonce] || OAuth::Helper.generate_nonce,
46
+ "oauth_timestamp" => options[:oauth_timestamp] || OAuth::Helper.generate_timestamp,
47
+ "oauth_token" => oauth_token.token,
48
+ "oauth_signature_method" => options[:oauth_signature_method] || "HMAC-SHA1",
49
+ "oauth_version" => options[:oauth_version] || "1.0"
50
+ }
51
+
52
+ request.sign!(:consumer => oauth_consumer, :token => oauth_token)
53
+
54
+ # TODO create XMPPElements for OAuth elements
55
+ oauth = REXML::Element.new("oauth")
56
+ oauth.attributes['xmlns'] = 'urn:xmpp:oauth:0'
57
+
58
+ oauth_consumer_key = REXML::Element.new("oauth_consumer_key")
59
+ oauth_consumer_key.text = request.oauth_consumer_key
60
+ oauth.add(oauth_consumer_key)
61
+
62
+ oauth_token_node = REXML::Element.new("oauth_token")
63
+ oauth_token_node.text = request.oauth_token
64
+ oauth.add(oauth_token_node)
65
+
66
+ oauth_signature_method = REXML::Element.new("oauth_signature_method")
67
+ oauth_signature_method.text = request.oauth_signature_method
68
+ oauth.add(oauth_signature_method)
69
+
70
+ oauth_signature = REXML::Element.new("oauth_signature")
71
+ oauth_signature.text = request.oauth_signature
72
+ oauth.add(oauth_signature)
73
+
74
+ oauth_timestamp = REXML::Element.new("oauth_timestamp")
75
+ oauth_timestamp.text = request.oauth_timestamp
76
+ oauth.add(oauth_timestamp)
77
+
78
+ oauth_nonce = REXML::Element.new("oauth_nonce")
79
+ oauth_nonce.text = request.oauth_nonce
80
+ oauth.add(oauth_nonce)
81
+
82
+ oauth_version = REXML::Element.new("oauth_version")
83
+ oauth_version.text = request.oauth_version
84
+ oauth.add(oauth_version)
85
+
86
+ oauth
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,456 @@
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
+ # It's recommented to read the XEP-0060 before you use this Helper. (Maybe its
6
+ # better not use the helper for now ) ;)
7
+ # The whole code is getting better, but may still contain bugs - be careful!
8
+ #
9
+ # Maybe the following structure is good
10
+ # ( taken from the xep-0060 )
11
+ #
12
+ # entity usecases
13
+ # retrieve all subscriptions
14
+ # retrieve all affiliations
15
+ # NOTE: the disco stuff will done by the nodebrowserhelper
16
+ # subscriber usecases
17
+ # subscribe
18
+ # unsubscribe
19
+ # configure subscription options
20
+ # retrieve items from a node
21
+ # publisher usecases
22
+ # publish a item to a node
23
+ # delete a item from a node
24
+ # owner usecases
25
+ # create a node
26
+ # configure a node
27
+ # request default configuration options
28
+ # delete a node
29
+ # purge all node items
30
+ # manage subscription requests
31
+ # process pending subscriptions
32
+ # manage subscriptions
33
+ # manage affiliations
34
+ #
35
+ # collection nodes
36
+ #
37
+ # If someone want to implement something i think its better to do this in
38
+ # this order because everyone who reads the xep-0060 do know where to search in the file
39
+ #
40
+ require 'xmpp4r/pubsub/iq/pubsub'
41
+ require 'xmpp4r/pubsub/children/event'
42
+ require 'xmpp4r/pubsub/children/item'
43
+ require 'xmpp4r/pubsub/children/items'
44
+ require 'xmpp4r/pubsub/children/subscription'
45
+ require 'xmpp4r/pubsub/children/unsubscribe'
46
+ require 'xmpp4r/pubsub/children/node_config'
47
+ require 'xmpp4r/pubsub/children/subscription_config'
48
+ require 'xmpp4r/pubsub/children/retract'
49
+ require 'xmpp4r/dataforms'
50
+
51
+ module Jabber
52
+ module PubSub
53
+ ##
54
+ # A Helper representing a PubSub Service
55
+ class ServiceHelper
56
+
57
+ ##
58
+ # Creates a new representation of a pubsub service
59
+ # stream:: [Jabber::Stream]
60
+ # pubsubjid:: [String] or [Jabber::JID]
61
+ def initialize(stream, pubsubjid)
62
+ @stream = stream
63
+ @pubsubjid = pubsubjid
64
+ @event_cbs = CallbackList.new
65
+ @stream.add_message_callback(200,self) { |message|
66
+ handle_message(message)
67
+ }
68
+ end
69
+
70
+ ##
71
+ # get all subscriptions on a pubsub component
72
+ # return:: [Hash] of [PubSub::Subscription]
73
+ def get_subscriptions_from_all_nodes
74
+ iq = basic_pubsub_query(:get)
75
+ entities = iq.pubsub.add(REXML::Element.new('subscriptions'))
76
+ res = nil
77
+ @stream.send_with_id(iq) { |reply|
78
+ if reply.pubsub.first_element('subscriptions')
79
+ res = []
80
+ reply.pubsub.first_element('subscriptions').each_element('subscription') { |subscription|
81
+ res << Jabber::PubSub::Subscription.import(subscription)
82
+ }
83
+ end
84
+ }
85
+
86
+ res
87
+ end
88
+ ##
89
+ # subscribe to a node
90
+ # node:: [String]
91
+ # return:: [Hash] of { attributename => value }
92
+ def subscribe_to(node)
93
+ iq = basic_pubsub_query(:set)
94
+ sub = REXML::Element.new('subscribe')
95
+ sub.attributes['node'] = node
96
+ sub.attributes['jid'] = @stream.jid.strip.to_s
97
+ iq.pubsub.add(sub)
98
+ res = nil
99
+ @stream.send_with_id(iq) do |reply|
100
+ pubsubanswer = reply.pubsub
101
+ if pubsubanswer.first_element('subscription')
102
+ res = PubSub::Subscription.import(pubsubanswer.first_element('subscription'))
103
+ end
104
+ end # @stream.send_with_id(iq)
105
+ res
106
+ end
107
+
108
+ ##
109
+ # Unsubscribe from a node with an optional subscription id
110
+ #
111
+ # May raise ServerError
112
+ # node:: [String]
113
+ # subid:: [String] or nil (not supported)
114
+ # return:: true
115
+ def unsubscribe_from(node, subid=nil)
116
+ iq = basic_pubsub_query(:set)
117
+ unsub = PubSub::Unsubscribe.new
118
+ unsub.node = node
119
+ unsub.jid = @stream.jid.strip
120
+ iq.pubsub.add(unsub)
121
+ ret = false
122
+ @stream.send_with_id(iq) { |reply|
123
+ ret = reply.kind_of?(Jabber::Iq) and reply.type == :result
124
+ } # @stream.send_with_id(iq)
125
+ ret
126
+ end
127
+
128
+ ##
129
+ # gets all items from a pubsub node
130
+ # node:: [String]
131
+ # count:: [Fixnum]
132
+ # return:: [Hash] { id => [Jabber::PubSub::Item] }
133
+ def get_items_from(node, count=nil)
134
+ iq = basic_pubsub_query(:get)
135
+ items = Jabber::PubSub::Items.new
136
+ items.max_items = count
137
+ items.node = node
138
+ iq.pubsub.add(items)
139
+ res = nil
140
+ @stream.send_with_id(iq) { |reply|
141
+ if reply.kind_of?(Iq) and reply.pubsub and reply.pubsub.first_element('items')
142
+ res = {}
143
+ reply.pubsub.first_element('items').each_element('item') do |item|
144
+ res[item.attributes['id']] = item.children.first if item.children.first
145
+ end
146
+ end
147
+ true
148
+ }
149
+ res
150
+ end
151
+
152
+ ##
153
+ # NOTE: this method sends only one item per publish request because some services
154
+ # may not allow batch processing. Maybe this will changed in the future?
155
+ # node:: [String]
156
+ # item:: [Jabber::PubSub::Item]
157
+ # return:: true
158
+ def publish_item_to(node,item)
159
+ iq = basic_pubsub_query(:set)
160
+ publish = iq.pubsub.add(REXML::Element.new('publish'))
161
+ publish.attributes['node'] = node
162
+
163
+ if item.kind_of?(Jabber::PubSub::Item)
164
+ publish.add(item)
165
+ @stream.send_with_id(iq)
166
+ end
167
+ end
168
+
169
+ ##
170
+ # node:: [String]
171
+ # item:: [REXML::Element]
172
+ # id:: [String]
173
+ # return:: true
174
+ def publish_item_with_id_to(node,item,id)
175
+ iq = basic_pubsub_query(:set)
176
+ publish = iq.pubsub.add(REXML::Element.new('publish'))
177
+ publish.attributes['node'] = node
178
+
179
+ if item.kind_of?(REXML::Element)
180
+ xmlitem = Jabber::PubSub::Item.new
181
+ xmlitem.id = id
182
+ xmlitem.import(item)
183
+ publish.add(xmlitem)
184
+ else
185
+ raise "given item is not a proper xml document or Jabber::PubSub::Item"
186
+ end
187
+ @stream.send_with_id(iq)
188
+ end
189
+
190
+ ##
191
+ # deletes an item from a persistent node
192
+ # node:: [String]
193
+ # item_id:: [String] or [Array] of [String]
194
+ # return:: true
195
+ def delete_item_from(node, item_id)
196
+ iq = basic_pubsub_query(:set)
197
+ retract = iq.pubsub.add(Jabber::PubSub::Retract.new)
198
+ retract.node = node
199
+
200
+ if item_id.kind_of? Array
201
+ item_id.each { |id|
202
+ xmlitem = Jabber::PubSub::Item.new
203
+ xmlitem.id = id
204
+ retract.add(xmlitem)
205
+ }
206
+ else
207
+ xmlitem = Jabber::PubSub::Item.new
208
+ xmlitem.id = item_id
209
+ retract.add(xmlitem)
210
+ end
211
+
212
+ @stream.send_with_id(iq)
213
+ end
214
+
215
+
216
+ ##
217
+ # purges all items on a persistent node
218
+ # node:: [String]
219
+ # return:: true
220
+ def purge_items_from(node)
221
+ iq = basic_pubsub_query(:set)
222
+ purge = REXML::Element.new('purge')
223
+ purge.attributes['node'] = node
224
+ iq.pubsub.add(purge)
225
+ @stream.send_with_id(iq)
226
+ end
227
+
228
+ ##
229
+ # Create a new node on the pubsub service
230
+ # node:: [String] the node name - otherwise you get a automatically generated one (in most cases)
231
+ # configure:: [Jabber::PubSub::NodeConfig] if you want to configure your node (default nil)
232
+ # return:: [String]
233
+ def create_node(node = nil, configure = Jabber::PubSub::NodeConfig.new)
234
+ rnode = nil
235
+ iq = basic_pubsub_query(:set)
236
+ iq.pubsub.add(REXML::Element.new('create')).attributes['node'] = node
237
+ if configure
238
+ if configure.kind_of?(Jabber::PubSub::NodeConfig)
239
+ iq.pubsub.add(configure)
240
+ end
241
+ end
242
+
243
+ @stream.send_with_id(iq) do |reply|
244
+ if reply.kind_of?(Jabber::Iq) and reply.type == :result
245
+ rnode = node
246
+ end
247
+ end
248
+
249
+ rnode
250
+ end
251
+
252
+ ##
253
+ # Create a new collection node on the pubsub service
254
+ # node:: [String] the node name - otherwise you get an automatically generated one (in most cases)
255
+ # configure:: [Jabber::PubSub::NodeConfig] if you want to configure your node (default nil)
256
+ # return:: [String]
257
+ def create_collection_node(node = nil, configure = Jabber::PubSub::NodeConfig.new)
258
+ if configure.options['pubsub#node_type'] && configure.options['pubsub#node_type'] != 'collection'
259
+ raise Jabber::ArgumentError, "Invalid node_type specified in node configuration. Either do not specify one, or use 'collection'"
260
+ end
261
+ configure.options = configure.options.merge({'pubsub#node_type' => 'collection'})
262
+ create_node(node, configure)
263
+ end
264
+
265
+ ##
266
+ # get configuration from a node
267
+ # node:: [String]
268
+ # return:: [Jabber::PubSub::Configure]
269
+ def get_config_from(node)
270
+ iq = basic_pubsub_query(:get, true)
271
+ iq.pubsub.add(Jabber::PubSub::OwnerNodeConfig.new(node))
272
+ ret = nil
273
+ @stream.send_with_id(iq) do |reply|
274
+ ret = reply.pubsub.first_element('configure')
275
+ end
276
+ ret
277
+ end
278
+
279
+ ##
280
+ # set configuration for a node
281
+ # node:: [String]
282
+ # options:: [Jabber::PubSub::NodeConfig]
283
+ # return:: true on success
284
+ def set_config_for(node, config)
285
+ iq = basic_pubsub_query(:set, true)
286
+ iq.pubsub.add(config)
287
+ @stream.send_with_id(iq)
288
+ end
289
+
290
+ ##
291
+ # Delete a pubsub node
292
+ # node:: [String]
293
+ # return:: true
294
+ def delete_node(node)
295
+ iq = basic_pubsub_query(:set,true)
296
+ iq.pubsub.add(REXML::Element.new('delete')).attributes['node'] = node
297
+ @stream.send_with_id(iq)
298
+ end
299
+
300
+ def set_affiliations(node, jid, role = 'publisher')
301
+ iq = basic_pubsub_query(:set, true)
302
+ affiliations = iq.pubsub.add(REXML::Element.new('affiliations'))
303
+ affiliations.attributes['node'] = node
304
+ affiliation = affiliations.add(REXML::Element.new('affiliation'))
305
+ affiliation.attributes['jid'] = jid.to_s
306
+ affiliation.attributes['affiliation'] = role.to_s
307
+ res = nil
308
+ @stream.send_with_id(iq) { |reply|
309
+ true
310
+ }
311
+ res
312
+ end
313
+
314
+ ##
315
+ # shows the affiliations on a pubsub service
316
+ # node:: [String]
317
+ # return:: [Hash] of { node => symbol }
318
+ def get_affiliations(node = nil)
319
+ iq = basic_pubsub_query(:get)
320
+ affiliations = iq.pubsub.add(REXML::Element.new('affiliations'))
321
+ affiliations.attributes['node'] = node
322
+ res = nil
323
+ @stream.send_with_id(iq) { |reply|
324
+ if reply.pubsub.first_element('affiliations')
325
+ res = {}
326
+ reply.pubsub.first_element('affiliations').each_element('affiliation') do |affiliation|
327
+ # TODO: This should be handled by an affiliation element class
328
+ aff = case affiliation.attributes['affiliation']
329
+ when 'owner' then :owner
330
+ when 'publisher' then :publisher
331
+ when 'none' then :none
332
+ when 'outcast' then :outcast
333
+ else nil
334
+ end
335
+ res[affiliation.attributes['node']] = aff
336
+ end
337
+ end
338
+ true
339
+ }
340
+ res
341
+ end
342
+
343
+ ##
344
+ # shows all subscriptions on the given node
345
+ # node:: [String]
346
+ # return:: [Array] of [Jabber::Pubsub::Subscription]
347
+ def get_subscriptions_from(node)
348
+ iq = basic_pubsub_query(:get)
349
+ entities = iq.pubsub.add(REXML::Element.new('subscriptions'))
350
+ entities.attributes['node'] = node
351
+ res = nil
352
+ @stream.send_with_id(iq) { |reply|
353
+ if reply.pubsub.first_element('subscriptions')
354
+ res = []
355
+ if reply.pubsub.first_element('subscriptions').attributes['node'] == node
356
+ reply.pubsub.first_element('subscriptions').each_element('subscription') { |subscription|
357
+ res << PubSub::Subscription.import(subscription)
358
+ }
359
+ end
360
+ end
361
+ true
362
+ }
363
+ res
364
+ end
365
+
366
+ ##
367
+ # shows all jids of subscribers of a node
368
+ # node:: [String]
369
+ # return:: [Array] of [String]
370
+ def get_subscribers_from(node)
371
+ res = []
372
+ get_subscriptions_from(node).each { |sub|
373
+ res << sub.jid
374
+ }
375
+ res
376
+ end
377
+
378
+
379
+ ##
380
+ # get options from a subscription
381
+ # node:: [String]
382
+ # jid:: [Jabber::JID] or [String]
383
+ # subid:: [String] or nil
384
+ # return:: [Jabber::PubSub::OwnerConfigure]
385
+ def get_options_from(node, jid, subid = nil)
386
+ iq = basic_pubsub_query(:get)
387
+ iq.pubsub.add(Jabber::PubSub::SubscriptionConfig.new(node, jid.kind_of?(String) ? Jabber::JID.new(jid).strip: jid.strip, subid))
388
+ ret = nil
389
+ @stream.send_with_id(iq) do |reply|
390
+ ret = reply.pubsub.first_element('options')
391
+ end
392
+ ret
393
+ end
394
+
395
+ ##
396
+ # set options for a subscription
397
+ # node:: [String]
398
+ # jid:: [Jabber::JID] or [String]
399
+ # options:: [Jabber::PubSub::SubscriptionConfig} specifying configuration options
400
+ # subid:: [String] or nil
401
+ # return:: true
402
+ def set_options_for(node, jid, options, subid = nil)
403
+ iq = basic_pubsub_query(:set)
404
+ iq.pubsub.add(Jabber::PubSub::SubscriptionConfig.new(node, jid.kind_of?(String) ? Jabber::JID.new(jid).strip: jid.strip, options, subid))
405
+ ret = false
406
+ @stream.send_with_id(iq) do |reply|
407
+ ret = ( reply.type == :result )
408
+ end
409
+
410
+ ret
411
+ end
412
+
413
+ ##
414
+ # String representation
415
+ # result:: [String] The PubSub service's JID
416
+ def to_s
417
+ @pubsubjid.to_s
418
+ end
419
+
420
+ ##
421
+ # Register callbacks for incoming events
422
+ # (i.e. Message stanzas containing) PubSub notifications
423
+ def add_event_callback(prio = 200, ref = nil, &block)
424
+ @event_cbs.add(prio, ref, block)
425
+ end
426
+
427
+ private
428
+
429
+ ##
430
+ # creates a basic pubsub iq
431
+ # basic_pubsub_query(type)
432
+ # type:: [Symbol]
433
+ def basic_pubsub_query(type,ownerusecase = false)
434
+ iq = Jabber::Iq.new(type,@pubsubjid)
435
+ if ownerusecase
436
+ iq.add(IqPubSubOwner.new)
437
+ else
438
+ iq.add(IqPubSub.new)
439
+ end
440
+ iq.from = @stream.jid #.strip
441
+ iq
442
+ end
443
+
444
+ ##
445
+ # handling incoming events
446
+ # handle_message(message)
447
+ # message:: [Jabber::Message]
448
+ def handle_message(message)
449
+ if message.from == @pubsubjid and message.first_element('event').kind_of?(Jabber::PubSub::Event)
450
+ event = message.first_element('event')
451
+ @event_cbs.process(event)
452
+ end
453
+ end
454
+ end
455
+ end
456
+ end