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.
- data/.autotest +13 -0
- data/.gemtest +0 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +249 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +22 -0
- data/README.md +413 -0
- data/Rakefile +20 -0
- data/TODO.md +2 -0
- data/blather.gemspec +51 -0
- data/examples/certs/README +20 -0
- data/examples/certs/ca-bundle.crt +3987 -0
- data/examples/echo.rb +19 -0
- data/examples/execute.rb +17 -0
- data/examples/ping_pong.rb +38 -0
- data/examples/print_hierarchy.rb +77 -0
- data/examples/rosterprint.rb +15 -0
- data/examples/stream_only.rb +28 -0
- data/examples/trusted_echo.rb +21 -0
- data/examples/xmpp4r/echo.rb +36 -0
- data/lib/blather.rb +112 -0
- data/lib/blather/cert_store.rb +53 -0
- data/lib/blather/client.rb +95 -0
- data/lib/blather/client/client.rb +345 -0
- data/lib/blather/client/dsl.rb +320 -0
- data/lib/blather/client/dsl/pubsub.rb +174 -0
- data/lib/blather/core_ext/eventmachine.rb +125 -0
- data/lib/blather/core_ext/ipaddr.rb +20 -0
- data/lib/blather/errors.rb +69 -0
- data/lib/blather/errors/sasl_error.rb +44 -0
- data/lib/blather/errors/stanza_error.rb +110 -0
- data/lib/blather/errors/stream_error.rb +84 -0
- data/lib/blather/file_transfer.rb +107 -0
- data/lib/blather/file_transfer/ibb.rb +68 -0
- data/lib/blather/file_transfer/s5b.rb +114 -0
- data/lib/blather/jid.rb +141 -0
- data/lib/blather/roster.rb +118 -0
- data/lib/blather/roster_item.rb +146 -0
- data/lib/blather/stanza.rb +167 -0
- data/lib/blather/stanza/disco.rb +32 -0
- data/lib/blather/stanza/disco/capabilities.rb +161 -0
- data/lib/blather/stanza/disco/disco_info.rb +205 -0
- data/lib/blather/stanza/disco/disco_items.rb +134 -0
- data/lib/blather/stanza/iq.rb +144 -0
- data/lib/blather/stanza/iq/command.rb +339 -0
- data/lib/blather/stanza/iq/ibb.rb +86 -0
- data/lib/blather/stanza/iq/ping.rb +50 -0
- data/lib/blather/stanza/iq/query.rb +53 -0
- data/lib/blather/stanza/iq/roster.rb +185 -0
- data/lib/blather/stanza/iq/s5b.rb +208 -0
- data/lib/blather/stanza/iq/si.rb +415 -0
- data/lib/blather/stanza/iq/vcard.rb +149 -0
- data/lib/blather/stanza/message.rb +428 -0
- data/lib/blather/stanza/message/muc_user.rb +119 -0
- data/lib/blather/stanza/muc/muc_user_base.rb +54 -0
- data/lib/blather/stanza/presence.rb +172 -0
- data/lib/blather/stanza/presence/c.rb +100 -0
- data/lib/blather/stanza/presence/muc.rb +35 -0
- data/lib/blather/stanza/presence/muc_user.rb +147 -0
- data/lib/blather/stanza/presence/status.rb +218 -0
- data/lib/blather/stanza/presence/subscription.rb +100 -0
- data/lib/blather/stanza/pubsub.rb +119 -0
- data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
- data/lib/blather/stanza/pubsub/create.rb +65 -0
- data/lib/blather/stanza/pubsub/errors.rb +18 -0
- data/lib/blather/stanza/pubsub/event.rb +139 -0
- data/lib/blather/stanza/pubsub/items.rb +103 -0
- data/lib/blather/stanza/pubsub/publish.rb +103 -0
- data/lib/blather/stanza/pubsub/retract.rb +92 -0
- data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
- data/lib/blather/stanza/pubsub/subscription.rb +135 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +83 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +84 -0
- data/lib/blather/stanza/pubsub_owner.rb +51 -0
- data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
- data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
- data/lib/blather/stanza/x.rb +416 -0
- data/lib/blather/stream.rb +266 -0
- data/lib/blather/stream/client.rb +32 -0
- data/lib/blather/stream/component.rb +39 -0
- data/lib/blather/stream/features.rb +70 -0
- data/lib/blather/stream/features/register.rb +38 -0
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/features/sasl.rb +190 -0
- data/lib/blather/stream/features/session.rb +45 -0
- data/lib/blather/stream/features/tls.rb +29 -0
- data/lib/blather/stream/parser.rb +102 -0
- data/lib/blather/version.rb +3 -0
- data/lib/blather/xmpp_node.rb +94 -0
- data/spec/blather/client/client_spec.rb +687 -0
- data/spec/blather/client/dsl/pubsub_spec.rb +492 -0
- data/spec/blather/client/dsl_spec.rb +266 -0
- data/spec/blather/errors/sasl_error_spec.rb +33 -0
- data/spec/blather/errors/stanza_error_spec.rb +129 -0
- data/spec/blather/errors/stream_error_spec.rb +108 -0
- data/spec/blather/errors_spec.rb +33 -0
- data/spec/blather/file_transfer_spec.rb +135 -0
- data/spec/blather/jid_spec.rb +87 -0
- data/spec/blather/roster_item_spec.rb +134 -0
- data/spec/blather/roster_spec.rb +107 -0
- data/spec/blather/stanza/discos/disco_info_spec.rb +247 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +154 -0
- data/spec/blather/stanza/iq/command_spec.rb +206 -0
- data/spec/blather/stanza/iq/ibb_spec.rb +124 -0
- data/spec/blather/stanza/iq/ping_spec.rb +45 -0
- data/spec/blather/stanza/iq/query_spec.rb +64 -0
- data/spec/blather/stanza/iq/roster_spec.rb +139 -0
- data/spec/blather/stanza/iq/s5b_spec.rb +57 -0
- data/spec/blather/stanza/iq/si_spec.rb +98 -0
- data/spec/blather/stanza/iq/vcard_spec.rb +93 -0
- data/spec/blather/stanza/iq_spec.rb +61 -0
- data/spec/blather/stanza/message/muc_user_spec.rb +152 -0
- data/spec/blather/stanza/message_spec.rb +282 -0
- data/spec/blather/stanza/presence/c_spec.rb +56 -0
- data/spec/blather/stanza/presence/muc_spec.rb +37 -0
- data/spec/blather/stanza/presence/muc_user_spec.rb +83 -0
- data/spec/blather/stanza/presence/status_spec.rb +144 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +102 -0
- data/spec/blather/stanza/presence_spec.rb +125 -0
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
- data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
- data/spec/blather/stanza/pubsub/event_spec.rb +98 -0
- data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
- data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
- data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
- data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
- data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +74 -0
- data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
- data/spec/blather/stanza/pubsub_spec.rb +68 -0
- data/spec/blather/stanza/x_spec.rb +231 -0
- data/spec/blather/stanza_spec.rb +134 -0
- data/spec/blather/stream/client_spec.rb +1090 -0
- data/spec/blather/stream/component_spec.rb +108 -0
- data/spec/blather/stream/parser_spec.rb +152 -0
- data/spec/blather/stream/ssl_spec.rb +32 -0
- data/spec/blather/xmpp_node_spec.rb +47 -0
- data/spec/blather_spec.rb +34 -0
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +17 -0
- data/yard/templates/default/class/html/handlers.erb +18 -0
- data/yard/templates/default/class/setup.rb +10 -0
- data/yard/templates/default/class/text/handlers.erb +1 -0
- metadata +459 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class PubSubOwner
|
|
4
|
+
|
|
5
|
+
# # PubSubOwner Purge Stanza
|
|
6
|
+
#
|
|
7
|
+
# [XEP-0060 Section 8.5 - Purge All Node Items](http://xmpp.org/extensions/xep-0060.html#owner-purge)
|
|
8
|
+
#
|
|
9
|
+
# @handler :pubsub_purge
|
|
10
|
+
class Purge < PubSubOwner
|
|
11
|
+
register :pubsub_purge, :purge, self.registered_ns
|
|
12
|
+
|
|
13
|
+
# Create a new purge stanza
|
|
14
|
+
#
|
|
15
|
+
# @param [Blather::Stanza::Iq::VALID_TYPES] type the IQ stanza type
|
|
16
|
+
# @param [String] host the host to send the request to
|
|
17
|
+
# @param [String] node the name of the node to purge
|
|
18
|
+
def self.new(type = :set, host = nil, node = nil)
|
|
19
|
+
new_node = super(type, host)
|
|
20
|
+
new_node.node = node
|
|
21
|
+
new_node
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Get the name of the node to delete
|
|
25
|
+
#
|
|
26
|
+
# @return [String]
|
|
27
|
+
def node
|
|
28
|
+
purge_node[:node]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Set the name of the node to delete
|
|
32
|
+
#
|
|
33
|
+
# @param [String] node
|
|
34
|
+
def node=(node)
|
|
35
|
+
purge_node[:node] = node
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Get or create the actual purge node on the stanza
|
|
39
|
+
#
|
|
40
|
+
# @return [Blather::XMPPNode]
|
|
41
|
+
def purge_node
|
|
42
|
+
unless purge_node = pubsub.find_first('ns:purge', :ns => self.class.registered_ns)
|
|
43
|
+
self.pubsub << (purge_node = XMPPNode.new('purge', self.document))
|
|
44
|
+
purge_node.namespace = self.pubsub.namespace
|
|
45
|
+
end
|
|
46
|
+
purge_node
|
|
47
|
+
end
|
|
48
|
+
end # Retract
|
|
49
|
+
|
|
50
|
+
end # PubSub
|
|
51
|
+
end # Stanza
|
|
52
|
+
end # Blather
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
# # X Stanza
|
|
4
|
+
#
|
|
5
|
+
# [XEP-0004 Data Forms](http://xmpp.org/extensions/xep-0004.html)
|
|
6
|
+
#
|
|
7
|
+
# Data Form node that allows for semi-structured data exchange
|
|
8
|
+
#
|
|
9
|
+
# @handler :x
|
|
10
|
+
class X < XMPPNode
|
|
11
|
+
register :x, 'jabber:x:data'
|
|
12
|
+
|
|
13
|
+
# @private
|
|
14
|
+
VALID_TYPES = [:cancel, :form, :result, :submit].freeze
|
|
15
|
+
|
|
16
|
+
# Create a new X node
|
|
17
|
+
# @param [:cancel, :form, :result, :submit, nil] type the x:form type
|
|
18
|
+
# @param [Array<Array, X::Field>, nil] fields a list of fields.
|
|
19
|
+
# These are passed directly to X::Field.new
|
|
20
|
+
# @return [X] a new X stanza
|
|
21
|
+
def self.new(type = nil, fields = [])
|
|
22
|
+
new_node = super :x
|
|
23
|
+
|
|
24
|
+
case type
|
|
25
|
+
when Nokogiri::XML::Node
|
|
26
|
+
new_node.inherit type
|
|
27
|
+
when Hash
|
|
28
|
+
new_node.type = type[:type]
|
|
29
|
+
new_node.fields = type[:fields]
|
|
30
|
+
else
|
|
31
|
+
new_node.type = type
|
|
32
|
+
new_node.fields = fields
|
|
33
|
+
end
|
|
34
|
+
new_node
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Find the X node on the parent or create a new one
|
|
38
|
+
#
|
|
39
|
+
# @param [Blather::Stanza] parent the parent node to search under
|
|
40
|
+
# @return [Blather::Stanza::X]
|
|
41
|
+
def self.find_or_create(parent)
|
|
42
|
+
if found_x = parent.find_first('//ns:x', :ns => self.registered_ns)
|
|
43
|
+
x = self.new found_x
|
|
44
|
+
found_x.remove
|
|
45
|
+
else
|
|
46
|
+
x = self.new
|
|
47
|
+
end
|
|
48
|
+
parent << x
|
|
49
|
+
x
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The Form's type
|
|
53
|
+
# @return [Symbol]
|
|
54
|
+
def type
|
|
55
|
+
read_attr :type, :to_sym
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Set the Form's type
|
|
59
|
+
# @param [:cancel, :form, :result, :submit] type the new type for the form
|
|
60
|
+
def type=(type)
|
|
61
|
+
if type && !VALID_TYPES.include?(type.to_sym)
|
|
62
|
+
raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}"
|
|
63
|
+
end
|
|
64
|
+
write_attr :type, type
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# List of field objects
|
|
68
|
+
# @return [Blather::Stanza::X::Field]
|
|
69
|
+
def fields
|
|
70
|
+
self.find('ns:field', :ns => self.class.registered_ns).map do |field|
|
|
71
|
+
Field.new(field)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Find a field by var
|
|
76
|
+
# @param var the var for the field you wish to find
|
|
77
|
+
def field(var)
|
|
78
|
+
fields.detect { |f| f.var == var }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Add an array of fields to form
|
|
82
|
+
# @param fields the array of fields, passed directly to Field.new
|
|
83
|
+
def fields=(fields)
|
|
84
|
+
remove_children :field
|
|
85
|
+
[fields].flatten.each do |field|
|
|
86
|
+
self << (f = Field.new(field))
|
|
87
|
+
f.namespace = self.namespace
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Check if the x is of type :cancel
|
|
92
|
+
#
|
|
93
|
+
# @return [true, false]
|
|
94
|
+
def cancel?
|
|
95
|
+
self.type == :cancel
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Check if the x is of type :form
|
|
99
|
+
#
|
|
100
|
+
# @return [true, false]
|
|
101
|
+
def form?
|
|
102
|
+
self.type == :form
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Check if the x is of type :result
|
|
106
|
+
#
|
|
107
|
+
# @return [true, false]
|
|
108
|
+
def result?
|
|
109
|
+
self.type == :result
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Check if the x is of type :submit
|
|
113
|
+
#
|
|
114
|
+
# @return [true, false]
|
|
115
|
+
def submit?
|
|
116
|
+
self.type == :submit
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Retrieve the form's instructions
|
|
120
|
+
#
|
|
121
|
+
# @return [String]
|
|
122
|
+
def instructions
|
|
123
|
+
content_from 'ns:instructions', :ns => self.registered_ns
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Set the form's instructions
|
|
127
|
+
#
|
|
128
|
+
# @param [String] instructions the form's instructions
|
|
129
|
+
def instructions=(instructions)
|
|
130
|
+
self.remove_children :instructions
|
|
131
|
+
if instructions
|
|
132
|
+
self << (i = XMPPNode.new(:instructions, self.document))
|
|
133
|
+
i.namespace = self.namespace
|
|
134
|
+
i << instructions
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Retrieve the form's title
|
|
139
|
+
#
|
|
140
|
+
# @return [String]
|
|
141
|
+
def title
|
|
142
|
+
content_from 'ns:title', :ns => self.registered_ns
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Set the form's title
|
|
146
|
+
#
|
|
147
|
+
# @param [String] title the form's title
|
|
148
|
+
def title=(title)
|
|
149
|
+
self.remove_children :title
|
|
150
|
+
if title
|
|
151
|
+
self << (t = XMPPNode.new(:title))
|
|
152
|
+
t.namespace = self.namespace
|
|
153
|
+
t << title
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Field stanza fragment
|
|
158
|
+
class Field < XMPPNode
|
|
159
|
+
register :field, 'jabber:x:data'
|
|
160
|
+
# @private
|
|
161
|
+
VALID_TYPES = [:boolean, :fixed, :hidden, :"jid-multi", :"jid-single", :"list-multi", :"list-single", :"text-multi", :"text-private", :"text-single"].freeze
|
|
162
|
+
|
|
163
|
+
# Create a new X Field
|
|
164
|
+
# @overload new(node)
|
|
165
|
+
# Imports the XML::Node to create a Field object
|
|
166
|
+
# @param [XML::Node] node the node object to import
|
|
167
|
+
# @overload new(opts = {})
|
|
168
|
+
# Creates a new Field using a hash of options
|
|
169
|
+
# @param [Hash] opts a hash of options
|
|
170
|
+
# @option opts [String] :var the variable for the field
|
|
171
|
+
# @option opts [:boolean, :fixed, :hidden, :"jid-multi", :"jid-single", :"list-multi", :"list-single", :"text-multi", :"text-private", :"text-single"] :type the type of the field
|
|
172
|
+
# @option opts [String] :label the label for the field
|
|
173
|
+
# @option [String, nil] :value the value for the field
|
|
174
|
+
# @option [String, nil] :description the description for the field
|
|
175
|
+
# @option [true, false, nil] :required the required flag for the field
|
|
176
|
+
# @param [Array<Array, X::Field::Option>, nil] :options a list of field options.
|
|
177
|
+
# These are passed directly to X::Field::Option.new
|
|
178
|
+
# @overload new(type, var = nil, label = nil)
|
|
179
|
+
# Create a new Field by name
|
|
180
|
+
# @param [String, nil] var the variable for the field
|
|
181
|
+
# @param [:boolean, :fixed, :hidden, :"jid-multi", :"jid-single", :"list-multi", :"list-single", :"text-multi", :"text-private", :"text-single"] type the type of the field
|
|
182
|
+
# @param [String, nil] label the label for the field
|
|
183
|
+
# @param [String, nil] value the value for the field
|
|
184
|
+
# @param [String, nil] description the description for the field
|
|
185
|
+
# @param [true, false, nil] required the required flag for the field
|
|
186
|
+
# @param [Array<Array, X::Field::Option>, nil] options a list of field options.
|
|
187
|
+
# These are passed directly to X::Field::Option.new
|
|
188
|
+
def self.new(var, type = nil, label = nil, value = nil, description = nil, required = false, options = [])
|
|
189
|
+
new_node = super :field
|
|
190
|
+
|
|
191
|
+
case var
|
|
192
|
+
when Nokogiri::XML::Node
|
|
193
|
+
new_node.inherit var
|
|
194
|
+
when Hash
|
|
195
|
+
new_node.var = var[:var]
|
|
196
|
+
new_node.type = var[:type]
|
|
197
|
+
new_node.label = var[:label]
|
|
198
|
+
new_node.value = var[:value]
|
|
199
|
+
new_node.desc = var[:description]
|
|
200
|
+
new_node.required = var[:required]
|
|
201
|
+
new_node.options = var[:options]
|
|
202
|
+
else
|
|
203
|
+
new_node.var = var
|
|
204
|
+
new_node.type = type
|
|
205
|
+
new_node.label = label
|
|
206
|
+
new_node.value = value
|
|
207
|
+
new_node.desc = description
|
|
208
|
+
new_node.required = required
|
|
209
|
+
new_node.options = options
|
|
210
|
+
end
|
|
211
|
+
new_node
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# The Field's type
|
|
215
|
+
# @return [String]
|
|
216
|
+
def type
|
|
217
|
+
read_attr :type
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Set the Field's type
|
|
221
|
+
# @param [#to_sym] type the new type for the field
|
|
222
|
+
def type=(type)
|
|
223
|
+
if type && !VALID_TYPES.include?(type.to_sym)
|
|
224
|
+
raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}"
|
|
225
|
+
end
|
|
226
|
+
write_attr :type, type
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# The Field's var
|
|
230
|
+
# @return [String]
|
|
231
|
+
def var
|
|
232
|
+
read_attr :var
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Set the Field's var
|
|
236
|
+
# @param [String] var the new var for the field
|
|
237
|
+
def var=(var)
|
|
238
|
+
write_attr :var, var
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# The Field's label
|
|
242
|
+
# @return [String]
|
|
243
|
+
def label
|
|
244
|
+
read_attr :label
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Set the Field's label
|
|
248
|
+
# @param [String] label the new label for the field
|
|
249
|
+
def label=(label)
|
|
250
|
+
write_attr :label, label
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Get the field's value
|
|
254
|
+
#
|
|
255
|
+
# @param [String]
|
|
256
|
+
def value
|
|
257
|
+
if self.namespace
|
|
258
|
+
content_from 'ns:value', :ns => self.namespace.href
|
|
259
|
+
else
|
|
260
|
+
content_from :value
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Set the field's value
|
|
265
|
+
#
|
|
266
|
+
# @param [String] value the field's value
|
|
267
|
+
def value=(value)
|
|
268
|
+
self.remove_children :value
|
|
269
|
+
if value
|
|
270
|
+
self << (v = XMPPNode.new(:value))
|
|
271
|
+
v.namespace = self.namespace
|
|
272
|
+
v << value
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Get the field's description
|
|
277
|
+
#
|
|
278
|
+
# @param [String]
|
|
279
|
+
def desc
|
|
280
|
+
if self.namespace
|
|
281
|
+
content_from 'ns:desc', :ns => self.namespace.href
|
|
282
|
+
else
|
|
283
|
+
content_from :desc
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Set the field's description
|
|
288
|
+
#
|
|
289
|
+
# @param [String] description the field's description
|
|
290
|
+
def desc=(description)
|
|
291
|
+
self.remove_children :desc
|
|
292
|
+
if description
|
|
293
|
+
self << (d = XMPPNode.new(:desc))
|
|
294
|
+
d.namespace = self.namespace
|
|
295
|
+
d << description
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Get the field's required flag
|
|
300
|
+
#
|
|
301
|
+
# @param [true, false]
|
|
302
|
+
def required?
|
|
303
|
+
!!if self.namespace
|
|
304
|
+
self.find_first 'ns:required', :ns => self.namespace.href
|
|
305
|
+
else
|
|
306
|
+
self.find_first 'required'
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Set the field's required flag
|
|
311
|
+
#
|
|
312
|
+
# @param [true, false] required the field's required flag
|
|
313
|
+
def required=(required)
|
|
314
|
+
return self.remove_children(:required) unless required
|
|
315
|
+
|
|
316
|
+
self << (r = XMPPNode.new(:required))
|
|
317
|
+
r.namespace = self.namespace
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Extract list of option objects
|
|
321
|
+
#
|
|
322
|
+
# @return [Blather::Stanza::X::Field::Option]
|
|
323
|
+
def options
|
|
324
|
+
if self.namespace
|
|
325
|
+
self.find('ns:option', :ns => self.namespace.href)
|
|
326
|
+
else
|
|
327
|
+
self.find('option')
|
|
328
|
+
end.map { |f| Option.new(f) }
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Add an array of options to field
|
|
332
|
+
# @param options the array of options, passed directly to Option.new
|
|
333
|
+
def options=(options)
|
|
334
|
+
remove_children :option
|
|
335
|
+
if options
|
|
336
|
+
Array(options).each { |o| self << Option.new(o) }
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# Compare two Field objects by type, var and label
|
|
341
|
+
# @param [X::Field] o the Field object to compare against
|
|
342
|
+
# @return [true, false]
|
|
343
|
+
def eql?(o, *fields)
|
|
344
|
+
super o, *(fields + [:type, :var, :label, :desc, :required?, :value])
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Option stanza fragment
|
|
348
|
+
class Option < XMPPNode
|
|
349
|
+
register :option, 'jabber:x:data'
|
|
350
|
+
# Create a new X Field Option
|
|
351
|
+
# @overload new(node)
|
|
352
|
+
# Imports the XML::Node to create a Field option object
|
|
353
|
+
# @param [XML::Node] node the node object to import
|
|
354
|
+
# @overload new(opts = {})
|
|
355
|
+
# Creates a new Field option using a hash of options
|
|
356
|
+
# @param [Hash] opts a hash of options
|
|
357
|
+
# @option opts [String] :value the value of the field option
|
|
358
|
+
# @option opts [String] :label the human readable label for the field option
|
|
359
|
+
# @overload new(value, label = nil)
|
|
360
|
+
# Create a new Field option by name
|
|
361
|
+
# @param [String] value the value of the field option
|
|
362
|
+
# @param [String, nil] label the human readable label for the field option
|
|
363
|
+
def self.new(value, label = nil)
|
|
364
|
+
new_node = super :option
|
|
365
|
+
|
|
366
|
+
case value
|
|
367
|
+
when Nokogiri::XML::Node
|
|
368
|
+
new_node.inherit value
|
|
369
|
+
when Hash
|
|
370
|
+
new_node.value = value[:value]
|
|
371
|
+
new_node.label = value[:label]
|
|
372
|
+
else
|
|
373
|
+
new_node.value = value
|
|
374
|
+
new_node.label = label
|
|
375
|
+
end
|
|
376
|
+
new_node
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# The Field Option's value
|
|
380
|
+
# @return [String]
|
|
381
|
+
def value
|
|
382
|
+
if self.namespace
|
|
383
|
+
content_from 'ns:value', :ns => self.namespace.href
|
|
384
|
+
else
|
|
385
|
+
content_from :value
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# Set the Field Option's value
|
|
390
|
+
# @param [String] value the new value for the field option
|
|
391
|
+
def value=(value)
|
|
392
|
+
self.remove_children :value
|
|
393
|
+
if value
|
|
394
|
+
self << (v = XMPPNode.new(:value))
|
|
395
|
+
v.namespace = self.namespace
|
|
396
|
+
v << value
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# The Field Option's label
|
|
401
|
+
# @return [String]
|
|
402
|
+
def label
|
|
403
|
+
read_attr :label
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Set the Field Option's label
|
|
407
|
+
# @param [String] label the new label for the field option
|
|
408
|
+
def label=(label)
|
|
409
|
+
write_attr :label, label
|
|
410
|
+
end
|
|
411
|
+
end # Option
|
|
412
|
+
end # Field
|
|
413
|
+
end # X
|
|
414
|
+
|
|
415
|
+
end #Stanza
|
|
416
|
+
end
|