tp-blather 0.8.2

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 (150) hide show
  1. data/.autotest +13 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +8 -0
  6. data/CHANGELOG.md +249 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +5 -0
  9. data/LICENSE +22 -0
  10. data/README.md +413 -0
  11. data/Rakefile +20 -0
  12. data/TODO.md +2 -0
  13. data/blather.gemspec +51 -0
  14. data/examples/certs/README +20 -0
  15. data/examples/certs/ca-bundle.crt +3987 -0
  16. data/examples/echo.rb +19 -0
  17. data/examples/execute.rb +17 -0
  18. data/examples/ping_pong.rb +38 -0
  19. data/examples/print_hierarchy.rb +77 -0
  20. data/examples/rosterprint.rb +15 -0
  21. data/examples/stream_only.rb +28 -0
  22. data/examples/trusted_echo.rb +21 -0
  23. data/examples/xmpp4r/echo.rb +36 -0
  24. data/lib/blather.rb +112 -0
  25. data/lib/blather/cert_store.rb +53 -0
  26. data/lib/blather/client.rb +95 -0
  27. data/lib/blather/client/client.rb +345 -0
  28. data/lib/blather/client/dsl.rb +320 -0
  29. data/lib/blather/client/dsl/pubsub.rb +174 -0
  30. data/lib/blather/core_ext/eventmachine.rb +125 -0
  31. data/lib/blather/core_ext/ipaddr.rb +20 -0
  32. data/lib/blather/errors.rb +69 -0
  33. data/lib/blather/errors/sasl_error.rb +44 -0
  34. data/lib/blather/errors/stanza_error.rb +110 -0
  35. data/lib/blather/errors/stream_error.rb +84 -0
  36. data/lib/blather/file_transfer.rb +107 -0
  37. data/lib/blather/file_transfer/ibb.rb +68 -0
  38. data/lib/blather/file_transfer/s5b.rb +114 -0
  39. data/lib/blather/jid.rb +141 -0
  40. data/lib/blather/roster.rb +118 -0
  41. data/lib/blather/roster_item.rb +146 -0
  42. data/lib/blather/stanza.rb +167 -0
  43. data/lib/blather/stanza/disco.rb +32 -0
  44. data/lib/blather/stanza/disco/capabilities.rb +161 -0
  45. data/lib/blather/stanza/disco/disco_info.rb +205 -0
  46. data/lib/blather/stanza/disco/disco_items.rb +134 -0
  47. data/lib/blather/stanza/iq.rb +144 -0
  48. data/lib/blather/stanza/iq/command.rb +339 -0
  49. data/lib/blather/stanza/iq/ibb.rb +86 -0
  50. data/lib/blather/stanza/iq/ping.rb +50 -0
  51. data/lib/blather/stanza/iq/query.rb +53 -0
  52. data/lib/blather/stanza/iq/roster.rb +185 -0
  53. data/lib/blather/stanza/iq/s5b.rb +208 -0
  54. data/lib/blather/stanza/iq/si.rb +415 -0
  55. data/lib/blather/stanza/iq/vcard.rb +149 -0
  56. data/lib/blather/stanza/message.rb +428 -0
  57. data/lib/blather/stanza/message/muc_user.rb +119 -0
  58. data/lib/blather/stanza/muc/muc_user_base.rb +54 -0
  59. data/lib/blather/stanza/presence.rb +172 -0
  60. data/lib/blather/stanza/presence/c.rb +100 -0
  61. data/lib/blather/stanza/presence/muc.rb +35 -0
  62. data/lib/blather/stanza/presence/muc_user.rb +147 -0
  63. data/lib/blather/stanza/presence/status.rb +218 -0
  64. data/lib/blather/stanza/presence/subscription.rb +100 -0
  65. data/lib/blather/stanza/pubsub.rb +119 -0
  66. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  67. data/lib/blather/stanza/pubsub/create.rb +65 -0
  68. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  69. data/lib/blather/stanza/pubsub/event.rb +139 -0
  70. data/lib/blather/stanza/pubsub/items.rb +103 -0
  71. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  72. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  73. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  74. data/lib/blather/stanza/pubsub/subscription.rb +135 -0
  75. data/lib/blather/stanza/pubsub/subscriptions.rb +83 -0
  76. data/lib/blather/stanza/pubsub/unsubscribe.rb +84 -0
  77. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  78. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  79. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  80. data/lib/blather/stanza/x.rb +416 -0
  81. data/lib/blather/stream.rb +266 -0
  82. data/lib/blather/stream/client.rb +32 -0
  83. data/lib/blather/stream/component.rb +39 -0
  84. data/lib/blather/stream/features.rb +70 -0
  85. data/lib/blather/stream/features/register.rb +38 -0
  86. data/lib/blather/stream/features/resource.rb +63 -0
  87. data/lib/blather/stream/features/sasl.rb +190 -0
  88. data/lib/blather/stream/features/session.rb +45 -0
  89. data/lib/blather/stream/features/tls.rb +29 -0
  90. data/lib/blather/stream/parser.rb +102 -0
  91. data/lib/blather/version.rb +3 -0
  92. data/lib/blather/xmpp_node.rb +94 -0
  93. data/spec/blather/client/client_spec.rb +687 -0
  94. data/spec/blather/client/dsl/pubsub_spec.rb +492 -0
  95. data/spec/blather/client/dsl_spec.rb +266 -0
  96. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  97. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  98. data/spec/blather/errors/stream_error_spec.rb +108 -0
  99. data/spec/blather/errors_spec.rb +33 -0
  100. data/spec/blather/file_transfer_spec.rb +135 -0
  101. data/spec/blather/jid_spec.rb +87 -0
  102. data/spec/blather/roster_item_spec.rb +134 -0
  103. data/spec/blather/roster_spec.rb +107 -0
  104. data/spec/blather/stanza/discos/disco_info_spec.rb +247 -0
  105. data/spec/blather/stanza/discos/disco_items_spec.rb +154 -0
  106. data/spec/blather/stanza/iq/command_spec.rb +206 -0
  107. data/spec/blather/stanza/iq/ibb_spec.rb +124 -0
  108. data/spec/blather/stanza/iq/ping_spec.rb +45 -0
  109. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  110. data/spec/blather/stanza/iq/roster_spec.rb +139 -0
  111. data/spec/blather/stanza/iq/s5b_spec.rb +57 -0
  112. data/spec/blather/stanza/iq/si_spec.rb +98 -0
  113. data/spec/blather/stanza/iq/vcard_spec.rb +93 -0
  114. data/spec/blather/stanza/iq_spec.rb +61 -0
  115. data/spec/blather/stanza/message/muc_user_spec.rb +152 -0
  116. data/spec/blather/stanza/message_spec.rb +282 -0
  117. data/spec/blather/stanza/presence/c_spec.rb +56 -0
  118. data/spec/blather/stanza/presence/muc_spec.rb +37 -0
  119. data/spec/blather/stanza/presence/muc_user_spec.rb +83 -0
  120. data/spec/blather/stanza/presence/status_spec.rb +144 -0
  121. data/spec/blather/stanza/presence/subscription_spec.rb +102 -0
  122. data/spec/blather/stanza/presence_spec.rb +125 -0
  123. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  124. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  125. data/spec/blather/stanza/pubsub/event_spec.rb +98 -0
  126. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  127. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  128. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  129. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  130. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  131. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  132. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +74 -0
  133. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  134. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  135. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  136. data/spec/blather/stanza/pubsub_spec.rb +68 -0
  137. data/spec/blather/stanza/x_spec.rb +231 -0
  138. data/spec/blather/stanza_spec.rb +134 -0
  139. data/spec/blather/stream/client_spec.rb +1090 -0
  140. data/spec/blather/stream/component_spec.rb +108 -0
  141. data/spec/blather/stream/parser_spec.rb +152 -0
  142. data/spec/blather/stream/ssl_spec.rb +32 -0
  143. data/spec/blather/xmpp_node_spec.rb +47 -0
  144. data/spec/blather_spec.rb +34 -0
  145. data/spec/fixtures/pubsub.rb +311 -0
  146. data/spec/spec_helper.rb +17 -0
  147. data/yard/templates/default/class/html/handlers.erb +18 -0
  148. data/yard/templates/default/class/setup.rb +10 -0
  149. data/yard/templates/default/class/text/handlers.erb +1 -0
  150. metadata +459 -0
@@ -0,0 +1,65 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ # # PubSub Create Stanza
6
+ #
7
+ # [XEP-0060 Section 8.1 - Create a Node](http://xmpp.org/extensions/xep-0060.html#owner-create)
8
+ #
9
+ # @handler :pubsub_create
10
+ class Create < PubSub
11
+ register :pubsub_create, :create, self.registered_ns
12
+
13
+ # Create a new Create Stanza
14
+ #
15
+ # @param [<Blather::Stanza::Iq::VALID_TYPES>] type the node type
16
+ # @param [String, nil] host the host to send the request to
17
+ # @param [String, nil] node the name of the node to create
18
+ def self.new(type = :set, host = nil, node = nil)
19
+ new_node = super(type, host)
20
+ new_node.create_node
21
+ new_node.configure_node
22
+ new_node.node = node
23
+ new_node
24
+ end
25
+
26
+ # Get the name of the node to create
27
+ #
28
+ # @return [String, nil]
29
+ def node
30
+ create_node[:node]
31
+ end
32
+
33
+ # Set the name of the node to create
34
+ #
35
+ # @param [String, nil] node
36
+ def node=(node)
37
+ create_node[:node] = node
38
+ end
39
+
40
+ # Get or create the actual create node on the stanza
41
+ #
42
+ # @return [Blather::XMPPNode]
43
+ def create_node
44
+ unless create_node = pubsub.find_first('ns:create', :ns => self.class.registered_ns)
45
+ self.pubsub << (create_node = XMPPNode.new('create', self.document))
46
+ create_node.namespace = self.pubsub.namespace
47
+ end
48
+ create_node
49
+ end
50
+
51
+ # Get or create the actual configure node on the stanza
52
+ #
53
+ # @return [Blather::XMPPNode]
54
+ def configure_node
55
+ unless configure_node = pubsub.find_first('ns:configure', :ns => self.class.registered_ns)
56
+ self.pubsub << (configure_node = XMPPNode.new('configure', self.document))
57
+ configure_node.namespace = self.pubsub.namespace
58
+ end
59
+ configure_node
60
+ end
61
+ end # Create
62
+
63
+ end # PubSub
64
+ end # Stanza
65
+ end # Blather
@@ -0,0 +1,18 @@
1
+ module Blather
2
+ class Stanza
3
+
4
+ # # PusSub Error Stanza
5
+ #
6
+ # @private
7
+ class PubSubErrors < PubSub
8
+ def node
9
+ read_attr :node
10
+ end
11
+
12
+ def node=(node)
13
+ write_attr :node, node
14
+ end
15
+ end # PubSubErrors
16
+
17
+ end # Stanza
18
+ end # Blather
@@ -0,0 +1,139 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ # # PubSub Event Stanza
6
+ #
7
+ # [XEP-0060](http://xmpp.org/extensions/xep-0060.html)
8
+ #
9
+ # The PubSub Event stanza is used in many places. Please see the XEP for more
10
+ # information.
11
+ #
12
+ # @handler :pubsub_event
13
+ class Event < Message
14
+ # @private
15
+ SHIM_NS = 'http://jabber.org/protocol/shim'.freeze
16
+
17
+ register :pubsub_event, :event, 'http://jabber.org/protocol/pubsub#event'
18
+
19
+ # Ensures the event_node is created
20
+ # @private
21
+ def self.new(type = nil)
22
+ node = super
23
+ node.event_node
24
+ node
25
+ end
26
+
27
+ # Kill the event_node node before running inherit
28
+ # @private
29
+ def inherit(node)
30
+ event_node.remove
31
+ super
32
+ end
33
+
34
+ # Get the name of the node
35
+ #
36
+ # @return [String, nil]
37
+ def node
38
+ !purge? ? items_node[:node] : purge_node[:node]
39
+ end
40
+
41
+ # Get a list of retractions
42
+ #
43
+ # @return [Array<String>]
44
+ def retractions
45
+ items_node.find('//ns:retract', :ns => self.class.registered_ns).map do |i|
46
+ i[:id]
47
+ end
48
+ end
49
+
50
+ # Check if this is a retractions stanza
51
+ #
52
+ # @return [Boolean]
53
+ def retractions?
54
+ !retractions.empty?
55
+ end
56
+
57
+ # Get the list of items attached to this event
58
+ #
59
+ # @return [Array<Blather::Stanza::PubSub::PubSubItem>]
60
+ def items
61
+ items_node.find('//ns:item', :ns => self.class.registered_ns).map do |i|
62
+ PubSubItem.new(nil,nil,self.document).inherit i
63
+ end
64
+ end
65
+
66
+ # Check if this stanza has items
67
+ #
68
+ # @return [Boolean]
69
+ def items?
70
+ !items.empty?
71
+ end
72
+
73
+ # Check if this is a purge stanza
74
+ #
75
+ # @return [XML::Node, nil]
76
+ def purge?
77
+ purge_node
78
+ end
79
+
80
+ # Get or create the actual event node
81
+ #
82
+ # @return [Blather::XMPPNode]
83
+ def event_node
84
+ node = find_first('//ns:event', :ns => self.class.registered_ns)
85
+ node = find_first('//event', self.class.registered_ns) unless node
86
+ unless node
87
+ (self << (node = XMPPNode.new('event', self.document)))
88
+ node.namespace = self.class.registered_ns
89
+ end
90
+ node
91
+ end
92
+
93
+ # Get or create the actual items node
94
+ #
95
+ # @return [Blather::XMPPNode]
96
+ def items_node
97
+ node = find_first('ns:event/ns:items', :ns => self.class.registered_ns)
98
+ unless node
99
+ (self.event_node << (node = XMPPNode.new('items', self.document)))
100
+ node.namespace = event_node.namespace
101
+ end
102
+ node
103
+ end
104
+
105
+ # Get the actual purge node
106
+ #
107
+ # @return [Blather::XMPPNode]
108
+ def purge_node
109
+ event_node.find_first('//ns:purge', :ns => self.class.registered_ns)
110
+ end
111
+
112
+ # Get the subscription IDs associated with this event
113
+ #
114
+ # @return [Array<String>]
115
+ def subscription_ids
116
+ find('//ns:header[@name="SubID"]', :ns => SHIM_NS).map do |n|
117
+ n.content
118
+ end
119
+ end
120
+
121
+ # Check if this is a subscription stanza
122
+ #
123
+ # @return [XML::Node, nil]
124
+ def subscription?
125
+ subscription_node
126
+ end
127
+
128
+ # Get the actual subscription node
129
+ #
130
+ # @return [Blather::XMPPNode]
131
+ def subscription_node
132
+ event_node.find_first('//ns:subscription', :ns => self.class.registered_ns)
133
+ end
134
+ alias_method :subscription, :subscription_node
135
+ end # Event
136
+
137
+ end # PubSub
138
+ end # Stanza
139
+ end # Blather
@@ -0,0 +1,103 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ # # PubSub Items Stanza
6
+ #
7
+ # [XEP-0060 Section 6.5 - Retrieve Items from a Node](http://xmpp.org/extensions/xep-0060.html#subscriber-retrieve)
8
+ #
9
+ # @handler :pubsub_items
10
+ class Items < PubSub
11
+ register :pubsub_items, :items, self.registered_ns
12
+
13
+ include Enumerable
14
+ alias_method :find, :xpath
15
+
16
+ # Create a new Items request
17
+ #
18
+ # @param [String] host the pubsub host to send the request to
19
+ # @param [String] path the path of the node
20
+ # @param [Array<String>] list an array of IDs to request
21
+ # @param [#to_s] max the maximum number of items to return
22
+ #
23
+ # @return [Blather::Stanza::PubSub::Items]
24
+ def self.request(host, path, list = [], max = nil)
25
+ node = self.new :get, host
26
+
27
+ node.node = path
28
+ node.max_items = max
29
+
30
+ (list || []).each do |id|
31
+ node.items_node << PubSubItem.new(id, nil, node.document)
32
+ end
33
+
34
+ node
35
+ end
36
+
37
+ # Overrides the parent to ensure an items node is created
38
+ # @private
39
+ def self.new(type = nil, host = nil)
40
+ new_node = super
41
+ new_node.items
42
+ new_node
43
+ end
44
+
45
+ # Get the node name
46
+ #
47
+ # @return [String]
48
+ def node
49
+ items_node[:node]
50
+ end
51
+
52
+ # Set the node name
53
+ #
54
+ # @param [String, nil] node
55
+ def node=(node)
56
+ items_node[:node] = node
57
+ end
58
+
59
+ # Get the max number of items requested
60
+ #
61
+ # @return [Fixnum, nil]
62
+ def max_items
63
+ items_node[:max_items].to_i if items_node[:max_items]
64
+ end
65
+
66
+ # Set the max number of items requested
67
+ #
68
+ # @param [Fixnum, nil] max_items
69
+ def max_items=(max_items)
70
+ items_node[:max_items] = max_items
71
+ end
72
+
73
+ # Iterate over the list of items
74
+ #
75
+ # @yieldparam [Blather::Stanza::PubSub::PubSubItem] item
76
+ def each(&block)
77
+ items.each &block
78
+ end
79
+
80
+ # Get the list of items on this stanza
81
+ #
82
+ # @return [Array<Blather::Stanza::PubSub::PubSubItem>]
83
+ def items
84
+ items_node.find('ns:item', :ns => self.class.registered_ns).map do |i|
85
+ PubSubItem.new(nil,nil,self.document).inherit i
86
+ end
87
+ end
88
+
89
+ # Get or create the actual items node
90
+ #
91
+ # @return [Blather::XMPPNode]
92
+ def items_node
93
+ unless node = self.pubsub.find_first('ns:items', :ns => self.class.registered_ns)
94
+ (self.pubsub << (node = XMPPNode.new('items', self.document)))
95
+ node.namespace = self.pubsub.namespace
96
+ end
97
+ node
98
+ end
99
+ end # Items
100
+
101
+ end # PubSub
102
+ end # Stanza
103
+ end # Blather
@@ -0,0 +1,103 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ # # PubSub Publish Stanza
6
+ #
7
+ # [XEP-0060 Section 7.1 - Publish an Item to a Node](http://xmpp.org/extensions/xep-0060.html#publisher-publish)
8
+ #
9
+ # @handler :pubsub_publish
10
+ class Publish < PubSub
11
+ register :pubsub_publish, :publish, self.registered_ns
12
+
13
+ include Enumerable
14
+ alias_method :find, :xpath
15
+
16
+ # Create a new publish node
17
+ #
18
+ # @param [String, nil] host the host to pushlish the node to
19
+ # @param [String, nil] node the name of the node to publish to
20
+ # @param [Blather::Stanza::Iq::VALID_TYPES] type the node type
21
+ # @param [#to_s] payload the payload to publish see {#payload=}
22
+ def self.new(host = nil, node = nil, type = :set, payload = nil)
23
+ new_node = super(type, host)
24
+ new_node.node = node
25
+ new_node.payload = payload if payload
26
+ new_node
27
+ end
28
+
29
+ # Set the payload to publish
30
+ #
31
+ # @overload payload=(hash)
32
+ # Set the payload as a set of ID => payload entries
33
+ # @param [Hash<id => payload>] hash
34
+ # @overload payload=(array)
35
+ # Set the list of payloads all at once
36
+ # @param [Array<#to_s>] array
37
+ # @overload payload=(string)
38
+ # Set the payload as a string
39
+ # @param [#to_s] string
40
+ def payload=(payload)
41
+ payload = case payload
42
+ when Hash then payload.to_a
43
+ when Array then payload.map { |v| [nil, v] }
44
+ else [[nil, payload]]
45
+ end
46
+ payload.each do |id, value|
47
+ self.publish << PubSubItem.new(id, value, self.document)
48
+ end
49
+ end
50
+
51
+ # Get the name of the node to publish to
52
+ #
53
+ # @return [String, nil]
54
+ def node
55
+ publish[:node]
56
+ end
57
+
58
+ # Set the name of the node to publish to
59
+ #
60
+ # @param [String, nil] node
61
+ def node=(node)
62
+ publish[:node] = node
63
+ end
64
+
65
+ # Get or create the actual publish node
66
+ #
67
+ # @return [Blather::XMPPNode]
68
+ def publish
69
+ unless publish = pubsub.find_first('ns:publish', :ns => self.class.registered_ns)
70
+ self.pubsub << (publish = XMPPNode.new('publish', self.document))
71
+ publish.namespace = self.pubsub.namespace
72
+ end
73
+ publish
74
+ end
75
+
76
+ # Get the list of items
77
+ #
78
+ # @return [Array<Blather::Stanza::PubSub::PubSubItem>]
79
+ def items
80
+ publish.find('ns:item', :ns => self.class.registered_ns).map do |i|
81
+ PubSubItem.new(nil,nil,self.document).inherit i
82
+ end
83
+ end
84
+
85
+ # Iterate over the list of items
86
+ #
87
+ # @yield [item] a block to accept each item
88
+ # @yieldparam [Blather::Stanza::PubSub::PubSubItem]
89
+ def each(&block)
90
+ items.each &block
91
+ end
92
+
93
+ # Get the size of the items list
94
+ #
95
+ # @return [Fixnum]
96
+ def size
97
+ items.size
98
+ end
99
+ end # Publish
100
+
101
+ end # PubSub
102
+ end # Stanza
103
+ end # Blather
@@ -0,0 +1,92 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ # # PubSub Retract Stanza
6
+ #
7
+ # [XEP-0060 Section 7.2 - Delete an Item from a Node](http://xmpp.org/extensions/xep-0060.html#publisher-delete)
8
+ #
9
+ # @handler :pubsub_retract
10
+ class Retract < PubSub
11
+ register :pubsub_retract, :retract, self.registered_ns
12
+
13
+ include Enumerable
14
+ alias_method :find, :xpath
15
+
16
+ # Createa new Retraction stanza
17
+ #
18
+ # @param [String] host the host to send the request to
19
+ # @param [String] node the node to retract items from
20
+ # @param [Blather::Stanza::Iq::VALID_TYPES] type the IQ stanza type
21
+ # @param [Array<String>] retractions an array of ids to retract
22
+ def self.new(host = nil, node = nil, type = :set, retractions = [])
23
+ new_node = super(type, host)
24
+ new_node.node = node
25
+ new_node.retractions = retractions
26
+ new_node
27
+ end
28
+
29
+ # Get the name of the node to retract from
30
+ #
31
+ # @return [String]
32
+ def node
33
+ retract[:node]
34
+ end
35
+
36
+ # Set the name of the node to retract from
37
+ #
38
+ # @param [String] node
39
+ def node=(node)
40
+ retract[:node] = node
41
+ end
42
+
43
+ # Get or create the actual retract node
44
+ #
45
+ # @return [Blather::XMPPNode]
46
+ def retract
47
+ unless retract = pubsub.find_first('ns:retract', :ns => self.class.registered_ns)
48
+ self.pubsub << (retract = XMPPNode.new('retract', self.document))
49
+ retract.namespace = self.pubsub.namespace
50
+ end
51
+ retract
52
+ end
53
+
54
+ # Set the retraction ids
55
+ #
56
+ # @overload retractions=(id)
57
+ # @param [String] id an ID to retract
58
+ # @overload retractions=(ids)
59
+ # @param [Array<String>] ids an array of IDs to retract
60
+ def retractions=(retractions = [])
61
+ [retractions].flatten.each do |id|
62
+ self.retract << PubSubItem.new(id, nil, self.document)
63
+ end
64
+ end
65
+
66
+ # Get the list of item IDs to retract
67
+ #
68
+ # @return [Array<String>]
69
+ def retractions
70
+ retract.find('ns:item', :ns => self.class.registered_ns).map do |i|
71
+ i[:id]
72
+ end
73
+ end
74
+
75
+ # Iterate over each retraction ID
76
+ #
77
+ # @yieldparam [String] id an ID to retract
78
+ def each(&block)
79
+ retractions.each &block
80
+ end
81
+
82
+ # The size of the retractions array
83
+ #
84
+ # @return [Fixnum]
85
+ def size
86
+ retractions.size
87
+ end
88
+ end # Retract
89
+
90
+ end # PubSub
91
+ end # Stanza
92
+ end # Blather