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,415 @@
|
|
|
1
|
+
require 'time' # For Time#xmlschema
|
|
2
|
+
|
|
3
|
+
module Blather
|
|
4
|
+
class Stanza
|
|
5
|
+
class Iq
|
|
6
|
+
|
|
7
|
+
# # Si Stanza
|
|
8
|
+
#
|
|
9
|
+
# [XEP-0096: SI File Transfer](http://xmpp.org/extensions/xep-0096.html)
|
|
10
|
+
#
|
|
11
|
+
# This is a base class for any si based Iq stanzas. It provides a base set
|
|
12
|
+
# of methods for working with si stanzas
|
|
13
|
+
#
|
|
14
|
+
# @example Basic file transfer acceptance
|
|
15
|
+
# client.register_handler :file_transfer do |iq|
|
|
16
|
+
# transfer = Blather::FileTransfer.new(client, iq)
|
|
17
|
+
# transfer.accept(Blather::FileTransfer::SimpleFileReceiver, "/path/to/#{iq.si.file["name"]}", iq.si.file["size"].to_i)
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# @example Basic file transfer refusal
|
|
21
|
+
# client.register_handler :file_transfer do |iq|
|
|
22
|
+
# transfer = Blather::FileTransfer.new(client, iq)
|
|
23
|
+
# transfer.decline
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# @example File transfer acceptance by in-band bytestreams with custom handler
|
|
27
|
+
# client.register_handler :file_transfer do |iq|
|
|
28
|
+
# transfer = Blather::FileTransfer.new(client, iq)
|
|
29
|
+
# transfer.allow_ibb = true
|
|
30
|
+
# transfer.allow_s5b = false
|
|
31
|
+
# transfer.accept(MyFileReceiver, iq)
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# @handler :file_transfer
|
|
35
|
+
class Si < Iq
|
|
36
|
+
# @private
|
|
37
|
+
NS_SI = 'http://jabber.org/protocol/si'
|
|
38
|
+
register :file_transfer, :si, NS_SI
|
|
39
|
+
|
|
40
|
+
# Overrides the parent method to ensure a si node is created
|
|
41
|
+
#
|
|
42
|
+
# @see Blather::Stanza::Iq.new
|
|
43
|
+
def self.new(type = :set)
|
|
44
|
+
node = super
|
|
45
|
+
node.si
|
|
46
|
+
node
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Overrides the parent method to ensure the current si node is destroyed
|
|
50
|
+
#
|
|
51
|
+
# @see Blather::Stanza::Iq#inherit
|
|
52
|
+
def inherit(node)
|
|
53
|
+
si.remove
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Find or create si node
|
|
58
|
+
#
|
|
59
|
+
# @return [Si::Si]
|
|
60
|
+
def si
|
|
61
|
+
Si.find_or_create self
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Replaces si node
|
|
65
|
+
#
|
|
66
|
+
# @param [Si::Si, XML::Node] node the stanza's new si node
|
|
67
|
+
#
|
|
68
|
+
# @return [Si::Si]
|
|
69
|
+
def si=(node)
|
|
70
|
+
si.remove
|
|
71
|
+
self << node
|
|
72
|
+
Si.find_or_create self
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Overrides the parent method to ensure the current si node is destroyed
|
|
76
|
+
#
|
|
77
|
+
# @see Blather::Stanza#reply
|
|
78
|
+
def reply
|
|
79
|
+
reply = Stanza::Iq::Si.import super
|
|
80
|
+
reply.si.remove
|
|
81
|
+
reply
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Si stanza fragment
|
|
85
|
+
class Si < XMPPNode
|
|
86
|
+
# Create a new Si::Si object
|
|
87
|
+
#
|
|
88
|
+
# @param [XML::Node, nil] node a node to inherit from
|
|
89
|
+
#
|
|
90
|
+
# @return [Si::Si]
|
|
91
|
+
def self.new(node = nil)
|
|
92
|
+
new_node = super :si
|
|
93
|
+
new_node.namespace = NS_SI
|
|
94
|
+
new_node.inherit node if node
|
|
95
|
+
new_node
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Find or create si node in Si Iq and converts it to Si::Si
|
|
99
|
+
#
|
|
100
|
+
# @param [Si] parent a Si Iq where to find or create si
|
|
101
|
+
#
|
|
102
|
+
# @return [Si::Si]
|
|
103
|
+
def self.find_or_create(parent)
|
|
104
|
+
if found_si = parent.find_first('//ns:si', :ns => NS_SI)
|
|
105
|
+
si = self.new found_si
|
|
106
|
+
found_si.remove
|
|
107
|
+
else
|
|
108
|
+
si = self.new
|
|
109
|
+
end
|
|
110
|
+
parent << si
|
|
111
|
+
|
|
112
|
+
si
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Get the id of the stream
|
|
116
|
+
#
|
|
117
|
+
# @return [String, nil]
|
|
118
|
+
def id
|
|
119
|
+
read_attr :id
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Set the id
|
|
123
|
+
#
|
|
124
|
+
# @param [String, nil] id the id of the stream
|
|
125
|
+
def id=(id)
|
|
126
|
+
write_attr :id, id
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Get the MIME type of the stream
|
|
130
|
+
#
|
|
131
|
+
# @return [String, nil]
|
|
132
|
+
def mime_type
|
|
133
|
+
read_attr 'mime-type'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Set the MIME type
|
|
137
|
+
#
|
|
138
|
+
# @param [String, nil] type the MIME type of the stream
|
|
139
|
+
def mime_type=(type)
|
|
140
|
+
write_attr 'mime-type', type
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Get the profile of the stream
|
|
144
|
+
#
|
|
145
|
+
# @return [String, nil]
|
|
146
|
+
def profile
|
|
147
|
+
read_attr :profile
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Set the profile
|
|
151
|
+
#
|
|
152
|
+
# @param [String, nil] profile the profile of the stream
|
|
153
|
+
def profile=(profile)
|
|
154
|
+
write_attr :profile, profile
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Find or create file node
|
|
158
|
+
#
|
|
159
|
+
# @return [Si::Si::File]
|
|
160
|
+
def file
|
|
161
|
+
File.find_or_create self
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Find or create feature node
|
|
165
|
+
#
|
|
166
|
+
# @return [Si::Si::Feature]
|
|
167
|
+
def feature
|
|
168
|
+
Feature.find_or_create self
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Feature stanza fragment
|
|
172
|
+
class Feature < XMPPNode
|
|
173
|
+
register :feature, 'http://jabber.org/protocol/feature-neg'
|
|
174
|
+
|
|
175
|
+
# Create a new Si::Si::Feature object
|
|
176
|
+
#
|
|
177
|
+
# @param [XML::Node, nil] node a node to inherit from
|
|
178
|
+
#
|
|
179
|
+
# @return [Si::Si::Feature]
|
|
180
|
+
def self.new(node = nil)
|
|
181
|
+
new_node = super :feature
|
|
182
|
+
new_node.namespace = self.registered_ns
|
|
183
|
+
new_node.inherit node if node
|
|
184
|
+
new_node
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Find or create feature node in si node and converts it to Si::Si::Feature
|
|
188
|
+
#
|
|
189
|
+
# @param [Si::Si] parent a si node where to find or create feature
|
|
190
|
+
#
|
|
191
|
+
# @return [Si::Si::Feature]
|
|
192
|
+
def self.find_or_create(parent)
|
|
193
|
+
if found_feature = parent.find_first('//ns:feature', :ns => self.registered_ns)
|
|
194
|
+
feature = self.new found_feature
|
|
195
|
+
found_feature.remove
|
|
196
|
+
else
|
|
197
|
+
feature = self.new
|
|
198
|
+
end
|
|
199
|
+
parent << feature
|
|
200
|
+
|
|
201
|
+
feature
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Find or create x node
|
|
205
|
+
#
|
|
206
|
+
# @return [Stanza::X]
|
|
207
|
+
def x
|
|
208
|
+
Stanza::X.find_or_create self
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# File stanza fragment
|
|
213
|
+
class File < XMPPNode
|
|
214
|
+
register :file, 'http://jabber.org/protocol/si/profile/file-transfer'
|
|
215
|
+
|
|
216
|
+
# Create a new Si::Si::File object
|
|
217
|
+
#
|
|
218
|
+
# @param [XML::Node, nil] node a node to inherit from
|
|
219
|
+
#
|
|
220
|
+
# @return [Si::Si::File]
|
|
221
|
+
def self.new(name = nil, size = nil)
|
|
222
|
+
new_node = super :file
|
|
223
|
+
|
|
224
|
+
case name
|
|
225
|
+
when Nokogiri::XML::Node
|
|
226
|
+
new_node.inherit name
|
|
227
|
+
else
|
|
228
|
+
new_node.name = name
|
|
229
|
+
new_node.size = size
|
|
230
|
+
end
|
|
231
|
+
new_node
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Find or create file node in si node and converts it to Si::Si::File
|
|
235
|
+
#
|
|
236
|
+
# @param [Si::Si] parent a si node where to find or create file
|
|
237
|
+
#
|
|
238
|
+
# @return [Si::Si::File]
|
|
239
|
+
def self.find_or_create(parent)
|
|
240
|
+
if found_file = parent.find_first('//ns:file', :ns => self.registered_ns)
|
|
241
|
+
file = self.new found_file
|
|
242
|
+
found_file.remove
|
|
243
|
+
else
|
|
244
|
+
file = self.new
|
|
245
|
+
end
|
|
246
|
+
parent << file
|
|
247
|
+
|
|
248
|
+
file
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Get the filename
|
|
252
|
+
#
|
|
253
|
+
# @return [String, nil]
|
|
254
|
+
def name
|
|
255
|
+
read_attr :name
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Set the filename
|
|
259
|
+
#
|
|
260
|
+
# @param [String, nil] name the name of the file
|
|
261
|
+
def name=(name)
|
|
262
|
+
write_attr :name, name
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Get the hash
|
|
266
|
+
#
|
|
267
|
+
# @return [String, nil]
|
|
268
|
+
def hash
|
|
269
|
+
read_attr :hash
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Set the hash
|
|
273
|
+
#
|
|
274
|
+
# @param [String, nil] hash the MD5 hash of the file
|
|
275
|
+
def hash=(hash)
|
|
276
|
+
write_attr :hash, hash
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Get the date
|
|
280
|
+
#
|
|
281
|
+
# @return [Time, nil]
|
|
282
|
+
def date
|
|
283
|
+
begin
|
|
284
|
+
Time.xmlschema(read_attr(:date))
|
|
285
|
+
rescue ArgumentError
|
|
286
|
+
nil
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Set the date
|
|
291
|
+
#
|
|
292
|
+
# @param [Time, nil] date the last modification time of the file
|
|
293
|
+
def date=(date)
|
|
294
|
+
write_attr :date, (date ? date.xmlschema : nil)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Get the size
|
|
298
|
+
#
|
|
299
|
+
# @return [Fixnum, nil]
|
|
300
|
+
def size
|
|
301
|
+
if (s = read_attr(:size)) && (s =~ /^\d+$/)
|
|
302
|
+
s.to_i
|
|
303
|
+
else
|
|
304
|
+
nil
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Set the size
|
|
309
|
+
#
|
|
310
|
+
# @param [Fixnum, nil] size the size, in bytes, of the file
|
|
311
|
+
def size=(size)
|
|
312
|
+
write_attr :size, size
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Get the desc
|
|
316
|
+
#
|
|
317
|
+
# @return [String, nil]
|
|
318
|
+
def desc
|
|
319
|
+
content_from 'ns:desc', :ns => self.class.registered_ns
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# Set the desc
|
|
323
|
+
#
|
|
324
|
+
# @param [String, nil] desc the description of the file
|
|
325
|
+
def desc=(desc)
|
|
326
|
+
set_content_for :desc, desc
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Find or create range node
|
|
330
|
+
#
|
|
331
|
+
# @return [Si::Si::File::Range]
|
|
332
|
+
def range
|
|
333
|
+
Range.find_or_create self
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# Range stanza fragment
|
|
338
|
+
class Range < XMPPNode
|
|
339
|
+
register :range, 'http://jabber.org/protocol/si/profile/file-transfer'
|
|
340
|
+
|
|
341
|
+
# Create a new Si::Si::File::Range object
|
|
342
|
+
#
|
|
343
|
+
# @param [XML::Node, nil] node a node to inherit from
|
|
344
|
+
#
|
|
345
|
+
# @return [Si::Si::File::Range]
|
|
346
|
+
def self.new(offset = nil, length = nil)
|
|
347
|
+
new_node = super :range
|
|
348
|
+
|
|
349
|
+
case offset
|
|
350
|
+
when Nokogiri::XML::Node
|
|
351
|
+
new_node.inherit offset
|
|
352
|
+
else
|
|
353
|
+
new_node.offset = offset
|
|
354
|
+
new_node.length = length
|
|
355
|
+
end
|
|
356
|
+
new_node
|
|
357
|
+
end
|
|
358
|
+
# Find or create range node in file node and converts it to Si::Si::File::Range
|
|
359
|
+
#
|
|
360
|
+
# @param [Si::Si::File] parent a file node where to find or create range
|
|
361
|
+
#
|
|
362
|
+
# @return [Si::Si::File::Range]
|
|
363
|
+
def self.find_or_create(parent)
|
|
364
|
+
if found_range = parent.find_first('//ns:range', :ns => self.registered_ns)
|
|
365
|
+
range = self.new found_range
|
|
366
|
+
found_range.remove
|
|
367
|
+
else
|
|
368
|
+
range = self.new
|
|
369
|
+
end
|
|
370
|
+
parent << range
|
|
371
|
+
|
|
372
|
+
range
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# Get the offset
|
|
376
|
+
#
|
|
377
|
+
# @return [Fixnum, nil]
|
|
378
|
+
def offset
|
|
379
|
+
if (o = read_attr(:offset)) && (o =~ /^\d+$/)
|
|
380
|
+
o.to_i
|
|
381
|
+
else
|
|
382
|
+
nil
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Set the offset
|
|
387
|
+
#
|
|
388
|
+
# @param [Fixnum, nil] offset the position, in bytes, to start transferring the file data from
|
|
389
|
+
def offset=(offset)
|
|
390
|
+
write_attr :offset, offset
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# Get the length
|
|
394
|
+
#
|
|
395
|
+
# @return [Fixnum, nil]
|
|
396
|
+
def length
|
|
397
|
+
if (l = read_attr(:length)) && (l =~ /^\d+$/)
|
|
398
|
+
l.to_i
|
|
399
|
+
else
|
|
400
|
+
nil
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Set the length
|
|
405
|
+
#
|
|
406
|
+
# @param [Fixnum, nil] length the number of bytes to retrieve starting at offset
|
|
407
|
+
def length=(length)
|
|
408
|
+
write_attr :length, length
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class Iq
|
|
4
|
+
|
|
5
|
+
# # Vcard Stanza
|
|
6
|
+
#
|
|
7
|
+
# [XEP-0054 vcard-temp](http://xmpp.org/extensions/xep-0054.html)
|
|
8
|
+
#
|
|
9
|
+
# This is a base class for any vcard based Iq stanzas. It provides a base set
|
|
10
|
+
# of methods for working with vcard stanzas
|
|
11
|
+
#
|
|
12
|
+
# @example Retrieving One's vCard
|
|
13
|
+
# iq = Blather::Stanza::Iq::Vcard.new :get
|
|
14
|
+
# client.write_with_handler iq do |response|
|
|
15
|
+
# puts response.vcard
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# @example Updating One's vCard
|
|
19
|
+
# iq = Blather::Stanza::Iq::Vcard.new :set
|
|
20
|
+
# iq.vcard['NICKNAME'] = 'Romeo'
|
|
21
|
+
# client.write_with_handler iq do |response|
|
|
22
|
+
# puts response
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# @example Viewing Another User's vCard
|
|
26
|
+
# iq = Blather::Stanza::Iq::Vcard.new :get, 'mercutio@example.org'
|
|
27
|
+
# client.write_with_handler iq do |response|
|
|
28
|
+
# puts response.vcard
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# @handler :vcard
|
|
32
|
+
class Vcard < Iq
|
|
33
|
+
|
|
34
|
+
register :vcard, :vCard, 'vcard-temp'
|
|
35
|
+
|
|
36
|
+
# Overrides the parent method to ensure a vcard node is created
|
|
37
|
+
#
|
|
38
|
+
# @see Blather::Stanza::Iq.new
|
|
39
|
+
def self.new(type = nil, to = nil, id = nil)
|
|
40
|
+
node = super
|
|
41
|
+
node.vcard
|
|
42
|
+
node
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Overrides the parent method to ensure the current vcard node is destroyed
|
|
46
|
+
#
|
|
47
|
+
# @see Blather::Stanza::Iq#inherit
|
|
48
|
+
def inherit(node)
|
|
49
|
+
vcard.remove
|
|
50
|
+
super
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Find or create vcard node
|
|
55
|
+
#
|
|
56
|
+
# @return [Vcard::Vcard]
|
|
57
|
+
def vcard
|
|
58
|
+
Vcard.find_or_create self
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Replaces vcard node
|
|
62
|
+
#
|
|
63
|
+
# @param [Vcard::Vcard, XML::Node] info the stanza's new vcard node
|
|
64
|
+
#
|
|
65
|
+
# @return [Vcard::Vcard]
|
|
66
|
+
def vcard=(info)
|
|
67
|
+
vcard.remove
|
|
68
|
+
self << info
|
|
69
|
+
Vcard.find_or_create self
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Vcard stanza fragment
|
|
73
|
+
class Vcard < XMPPNode
|
|
74
|
+
|
|
75
|
+
# @private
|
|
76
|
+
VCARD_NS = 'vcard-temp'
|
|
77
|
+
|
|
78
|
+
# Create a new Vcard::Vcard object
|
|
79
|
+
#
|
|
80
|
+
# @param [XML::Node, nil] node a node to inherit from
|
|
81
|
+
#
|
|
82
|
+
# @return [Vcard::Vcard]
|
|
83
|
+
def self.new(node = nil)
|
|
84
|
+
new_node = super :vCard
|
|
85
|
+
new_node.namespace = VCARD_NS
|
|
86
|
+
new_node.inherit node if node
|
|
87
|
+
new_node
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Find or create vCard node in Vcard Iq and converts it to Vcard::Vcard
|
|
91
|
+
#
|
|
92
|
+
# @param [Vcard] parent a Vcard Iq where to find or create vCard
|
|
93
|
+
#
|
|
94
|
+
# @return [Vcard::Vcard]
|
|
95
|
+
def self.find_or_create(parent)
|
|
96
|
+
if found_vcard = parent.find_first('//ns:vCard', :ns => VCARD_NS)
|
|
97
|
+
vcard = self.new found_vcard
|
|
98
|
+
found_vcard.remove
|
|
99
|
+
else
|
|
100
|
+
vcard = self.new
|
|
101
|
+
end
|
|
102
|
+
parent << vcard
|
|
103
|
+
|
|
104
|
+
vcard
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Find the element's value by name
|
|
108
|
+
#
|
|
109
|
+
# @param [String] name the name of the element
|
|
110
|
+
#
|
|
111
|
+
# @return [String, nil]
|
|
112
|
+
def [](name)
|
|
113
|
+
name = name.split("/").map{|child| "ns:#{child}"}.join("/")
|
|
114
|
+
|
|
115
|
+
if elem = find_first(name, :ns => VCARD_NS)
|
|
116
|
+
elem.content
|
|
117
|
+
else
|
|
118
|
+
nil
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Set the element's value
|
|
123
|
+
#
|
|
124
|
+
# @param [String] name the name of the element
|
|
125
|
+
# @param [String, nil] value the new value of element
|
|
126
|
+
#
|
|
127
|
+
# @return [String, nil]
|
|
128
|
+
def []=(name, value)
|
|
129
|
+
elem = nil
|
|
130
|
+
parent = self
|
|
131
|
+
|
|
132
|
+
name.split("/").each do |child|
|
|
133
|
+
elem = parent.find_first("ns:#{child}", :ns => VCARD_NS)
|
|
134
|
+
unless elem
|
|
135
|
+
elem = XMPPNode.new(child, parent.document)
|
|
136
|
+
parent << elem
|
|
137
|
+
parent = elem
|
|
138
|
+
else
|
|
139
|
+
parent = elem
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
elem.content = value
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|