blather 0.4.14 → 0.4.15
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/lib/blather.rb +8 -0
- data/lib/blather/client/client.rb +9 -1
- data/lib/blather/client/dsl/pubsub.rb +2 -2
- data/lib/blather/core_ext/active_support.rb +1 -0
- data/lib/blather/core_ext/eventmachine.rb +122 -0
- data/lib/blather/errors/stanza_error.rb +1 -0
- data/lib/blather/file_transfer.rb +100 -0
- data/lib/blather/file_transfer/ibb.rb +68 -0
- data/lib/blather/file_transfer/s5b.rb +104 -0
- data/lib/blather/roster_item.rb +2 -2
- data/lib/blather/stanza/disco/disco_info.rb +17 -2
- data/lib/blather/stanza/iq/ibb.rb +83 -0
- data/lib/blather/stanza/iq/s5b.rb +205 -0
- data/lib/blather/stanza/iq/si.rb +410 -0
- data/lib/blather/stanza/iq/vcard.rb +147 -0
- data/lib/blather/stanza/message.rb +10 -2
- data/lib/blather/stanza/presence/status.rb +11 -3
- data/lib/blather/stanza/pubsub.rb +3 -1
- data/lib/blather/stanza/pubsub/event.rb +18 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +4 -2
- data/lib/blather/stanza/pubsub/unsubscribe.rb +17 -1
- data/lib/blather/stanza/x.rb +12 -2
- data/lib/blather/stream/parser.rb +1 -0
- data/lib/test.rb +55 -0
- data/spec/blather/client/client_spec.rb +18 -4
- data/spec/blather/client/dsl/pubsub_spec.rb +12 -2
- data/spec/blather/client/dsl_spec.rb +1 -1
- data/spec/blather/core_ext/nokogiri_spec.rb +1 -1
- data/spec/blather/errors/sasl_error_spec.rb +1 -1
- data/spec/blather/errors/stanza_error_spec.rb +1 -1
- data/spec/blather/errors/stream_error_spec.rb +1 -1
- data/spec/blather/errors_spec.rb +1 -1
- data/spec/blather/file_transfer_spec.rb +100 -0
- data/spec/blather/jid_spec.rb +1 -1
- data/spec/blather/roster_item_spec.rb +32 -2
- data/spec/blather/roster_spec.rb +1 -1
- data/spec/blather/stanza/discos/disco_info_spec.rb +12 -3
- data/spec/blather/stanza/discos/disco_items_spec.rb +1 -1
- data/spec/blather/stanza/iq/command_spec.rb +1 -1
- data/spec/blather/stanza/iq/ibb_spec.rb +136 -0
- data/spec/blather/stanza/iq/query_spec.rb +1 -1
- data/spec/blather/stanza/iq/roster_spec.rb +1 -1
- data/spec/blather/stanza/iq/s5b_spec.rb +60 -0
- data/spec/blather/stanza/iq/si_spec.rb +101 -0
- data/spec/blather/stanza/iq/vcard_spec.rb +96 -0
- data/spec/blather/stanza/iq_spec.rb +1 -1
- data/spec/blather/stanza/message_spec.rb +48 -2
- data/spec/blather/stanza/presence/status_spec.rb +1 -1
- data/spec/blather/stanza/presence/subscription_spec.rb +1 -1
- data/spec/blather/stanza/presence_spec.rb +1 -1
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/create_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/event_spec.rb +16 -2
- data/spec/blather/stanza/pubsub/items_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/publish_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/retract_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/subscribe_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/subscription_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +3 -3
- data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +15 -2
- data/spec/blather/stanza/pubsub_owner/delete_spec.rb +2 -2
- data/spec/blather/stanza/pubsub_owner/purge_spec.rb +2 -2
- data/spec/blather/stanza/pubsub_owner_spec.rb +2 -2
- data/spec/blather/stanza/pubsub_spec.rb +14 -2
- data/spec/blather/stanza/x_spec.rb +1 -1
- data/spec/blather/stanza_spec.rb +1 -1
- data/spec/blather/stream/client_spec.rb +1 -1
- data/spec/blather/stream/component_spec.rb +1 -1
- data/spec/blather/stream/parser_spec.rb +11 -1
- data/spec/blather/xmpp_node_spec.rb +1 -1
- data/spec/fixtures/pubsub.rb +2 -2
- data/spec/spec_helper.rb +27 -0
- metadata +85 -23
data/lib/blather/roster_item.rb
CHANGED
@@ -90,7 +90,7 @@ module Blather
|
|
90
90
|
#
|
91
91
|
# @param [Blather::Stanza::Status] the new status
|
92
92
|
def status=(presence)
|
93
|
-
@statuses.delete_if { |s| s.from == presence.from }
|
93
|
+
@statuses.delete_if { |s| s.from == presence.from || s.state == :unavailable }
|
94
94
|
@statuses << presence
|
95
95
|
@statuses.sort!
|
96
96
|
end
|
@@ -102,7 +102,7 @@ module Blather
|
|
102
102
|
top = if resource
|
103
103
|
@statuses.detect { |s| s.from.resource == resource }
|
104
104
|
else
|
105
|
-
@statuses.
|
105
|
+
@statuses.last
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
@@ -75,7 +75,7 @@ class Stanza
|
|
75
75
|
# @param [String] name the name of the Identity
|
76
76
|
# @param [String, nil] type the type of the Identity
|
77
77
|
# @param [String, nil] category the category of the Identity
|
78
|
-
def self.new(name, type = nil, category = nil)
|
78
|
+
def self.new(name, type = nil, category = nil, xml_lang = nil)
|
79
79
|
new_node = super :identity
|
80
80
|
|
81
81
|
case name
|
@@ -85,10 +85,12 @@ class Stanza
|
|
85
85
|
new_node.name = name[:name]
|
86
86
|
new_node.type = name[:type]
|
87
87
|
new_node.category = name[:category]
|
88
|
+
new_node.xml_lang = name[:xml_lang]
|
88
89
|
else
|
89
90
|
new_node.name = name
|
90
91
|
new_node.type = type
|
91
92
|
new_node.category = category
|
93
|
+
new_node.xml_lang = xml_lang
|
92
94
|
end
|
93
95
|
new_node
|
94
96
|
end
|
@@ -129,6 +131,18 @@ class Stanza
|
|
129
131
|
write_attr :name, name
|
130
132
|
end
|
131
133
|
|
134
|
+
# The Identity's xml_lang
|
135
|
+
# @return [String]
|
136
|
+
def xml_lang
|
137
|
+
read_attr "lang"
|
138
|
+
end
|
139
|
+
|
140
|
+
# Set the Identity's name
|
141
|
+
# @param [String] name the new name for the identity
|
142
|
+
def xml_lang=(xml_lang)
|
143
|
+
write_attr "xml:lang", xml_lang
|
144
|
+
end
|
145
|
+
|
132
146
|
# Compare two Identity objects by name, type and category
|
133
147
|
# @param [DiscoInfo::Identity] o the Identity object to compare against
|
134
148
|
# @return [true, false]
|
@@ -139,7 +153,8 @@ class Stanza
|
|
139
153
|
|
140
154
|
o.name == self.name &&
|
141
155
|
o.type == self.type &&
|
142
|
-
o.category == self.category
|
156
|
+
o.category == self.category &&
|
157
|
+
o.xml_lang == self.xml_lang
|
143
158
|
end
|
144
159
|
alias_method :==, :eql?
|
145
160
|
end # Identity
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stanza
|
3
|
+
class Iq
|
4
|
+
NS_IBB = 'http://jabber.org/protocol/ibb'
|
5
|
+
|
6
|
+
# # In-Band Bytestreams Stanza
|
7
|
+
#
|
8
|
+
# [XEP-0047: In-Band Bytestreams](http://xmpp.org/extensions/xep-0047.html)
|
9
|
+
#
|
10
|
+
# @handler :ibb_open
|
11
|
+
# @handler :ibb_data
|
12
|
+
# @handler :ibb_close
|
13
|
+
class Ibb < Iq
|
14
|
+
|
15
|
+
# Overrides the parent method to remove open, close and data nodes
|
16
|
+
#
|
17
|
+
# @see Blather::Stanza#reply
|
18
|
+
def reply
|
19
|
+
reply = super
|
20
|
+
reply.remove_children :open
|
21
|
+
reply.remove_children :close
|
22
|
+
reply.remove_children :data
|
23
|
+
reply
|
24
|
+
end
|
25
|
+
|
26
|
+
class Open < Ibb
|
27
|
+
register :ibb_open, :open, NS_IBB
|
28
|
+
|
29
|
+
# Find open node
|
30
|
+
#
|
31
|
+
# @return [Nokogiri::XML::Element]
|
32
|
+
def open
|
33
|
+
find_first('ns:open', :ns => NS_IBB)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get the sid of the file transfer
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def sid
|
40
|
+
open['sid']
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class Data < Ibb
|
46
|
+
register :ibb_data, :data, NS_IBB
|
47
|
+
|
48
|
+
# Find data node
|
49
|
+
#
|
50
|
+
# @return [Nokogiri::XML::Element]
|
51
|
+
def data
|
52
|
+
find_first('ns:data', :ns => NS_IBB)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the sid of the file transfer
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
def sid
|
59
|
+
data['sid']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Close < Ibb
|
64
|
+
register :ibb_close, :close, NS_IBB
|
65
|
+
|
66
|
+
# Find close node
|
67
|
+
#
|
68
|
+
# @return [Nokogiri::XML::Element]
|
69
|
+
def close
|
70
|
+
find_first('ns:close', :ns => NS_IBB)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get the sid of the file transfer
|
74
|
+
#
|
75
|
+
# @return [String]
|
76
|
+
def sid
|
77
|
+
close['sid']
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stanza
|
3
|
+
class Iq
|
4
|
+
NS_S5B = 'http://jabber.org/protocol/bytestreams'
|
5
|
+
|
6
|
+
# # SOCKS5 Bytestreams Stanza
|
7
|
+
#
|
8
|
+
# [XEP-0065: SOCKS5 Bytestreams](http://xmpp.org/extensions/xep-0065.html)
|
9
|
+
#
|
10
|
+
# @handler :s5b_open
|
11
|
+
class S5b < Query
|
12
|
+
register :s5b_open, :query, NS_S5B
|
13
|
+
|
14
|
+
# Overrides the parent method to remove query node
|
15
|
+
#
|
16
|
+
# @see Blather::Stanza#reply
|
17
|
+
def reply
|
18
|
+
reply = super
|
19
|
+
reply.remove_children :query
|
20
|
+
reply
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the sid of the file transfer
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
def sid
|
27
|
+
query['sid']
|
28
|
+
end
|
29
|
+
|
30
|
+
# Get the used streamhost
|
31
|
+
#
|
32
|
+
# @return [S5b::StreamHostUsed]
|
33
|
+
def streamhost_used
|
34
|
+
StreamHostUsed.new query.find_first('.//ns:streamhost-used', :ns => self.class.registered_ns)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set the used streamhost
|
38
|
+
#
|
39
|
+
# @param [Blather::JID, String, nil] jid the jid of the used streamhost
|
40
|
+
def streamhost_used=(jid)
|
41
|
+
query.find('.//ns:streamhost-used', :ns => self.class.registered_ns).remove
|
42
|
+
|
43
|
+
if jid
|
44
|
+
query << StreamHostUsed.new(jid)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get the streamhosts
|
49
|
+
#
|
50
|
+
# @return [Array<S5b::StreamHost>]
|
51
|
+
def streamhosts
|
52
|
+
query.find('.//ns:streamhost', :ns => self.class.registered_ns).map do |s|
|
53
|
+
StreamHost.new s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Set the streamhosts
|
58
|
+
#
|
59
|
+
# @param streamhosts the array of streamhosts, passed directly to StreamHost.new
|
60
|
+
def streamhosts=(streamhosts)
|
61
|
+
query.find('.//ns:streamhost', :ns => self.class.registered_ns).remove
|
62
|
+
if streamhosts
|
63
|
+
[streamhosts].flatten.each { |s| self.query << StreamHost.new(s) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class StreamHost < XMPPNode
|
68
|
+
register 'streamhost', NS_S5B
|
69
|
+
|
70
|
+
# Create a new S5b::StreamHost
|
71
|
+
#
|
72
|
+
# @overload new(node)
|
73
|
+
# Create a new StreamHost by inheriting an existing node
|
74
|
+
# @param [XML::Node] node an XML::Node to inherit from
|
75
|
+
# @overload new(opts)
|
76
|
+
# Create a new StreamHost through a hash of options
|
77
|
+
# @param [Hash] opts a hash options
|
78
|
+
# @option opts [Blather::JID, String] :jid the JID of the StreamHost
|
79
|
+
# @option opts [#to_s] :host the host the StreamHost
|
80
|
+
# @option opts [#to_s] :port the post of the StreamHost
|
81
|
+
# @overload new(jid, host = nil, port = nil)
|
82
|
+
# Create a new StreamHost
|
83
|
+
# @param [Blather::JID, String] jid the JID of the StreamHost
|
84
|
+
# @param [#to_s] host the host the StreamHost
|
85
|
+
# @param [#to_s] port the post of the StreamHost
|
86
|
+
def self.new(jid, host = nil, port = nil)
|
87
|
+
new_node = super 'streamhost'
|
88
|
+
|
89
|
+
case jid
|
90
|
+
when Nokogiri::XML::Node
|
91
|
+
new_node.inherit jid
|
92
|
+
when Hash
|
93
|
+
new_node.jid = jid[:jid]
|
94
|
+
new_node.host = jid[:host]
|
95
|
+
new_node.port = jid[:port]
|
96
|
+
else
|
97
|
+
new_node.jid = jid
|
98
|
+
new_node.host = host
|
99
|
+
new_node.port = port
|
100
|
+
end
|
101
|
+
new_node
|
102
|
+
end
|
103
|
+
|
104
|
+
# Get the jid of the streamhost
|
105
|
+
#
|
106
|
+
# @return [Blather::JID, nil]
|
107
|
+
def jid
|
108
|
+
if j = read_attr(:jid)
|
109
|
+
JID.new(j)
|
110
|
+
else
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Set the jid of the streamhost
|
116
|
+
#
|
117
|
+
# @param [Blather::JID, String, nil]
|
118
|
+
def jid=(j)
|
119
|
+
write_attr :jid, (j ? j.to_s : nil)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Get the host address of the streamhost
|
123
|
+
#
|
124
|
+
# @return [String, nil]
|
125
|
+
def host
|
126
|
+
read_attr :host
|
127
|
+
end
|
128
|
+
|
129
|
+
# Set the host address of the streamhost
|
130
|
+
#
|
131
|
+
# @param [String, nil]
|
132
|
+
def host=(h)
|
133
|
+
write_attr :host, h
|
134
|
+
end
|
135
|
+
|
136
|
+
# Get the port of the streamhost
|
137
|
+
#
|
138
|
+
# @return [Fixnum, nil]
|
139
|
+
def port
|
140
|
+
if p = read_attr(:port)
|
141
|
+
p.to_i
|
142
|
+
else
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Set the port of the streamhost
|
148
|
+
#
|
149
|
+
# @param [String, Fixnum, nil]
|
150
|
+
def port=(p)
|
151
|
+
write_attr :port, p
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class StreamHostUsed < XMPPNode
|
156
|
+
register 'streamhost-used', NS_S5B
|
157
|
+
|
158
|
+
# Create a new S5b::StreamHostUsed
|
159
|
+
#
|
160
|
+
# @overload new(node)
|
161
|
+
# Create a new StreamHostUsed by inheriting an existing node
|
162
|
+
# @param [XML::Node] node an XML::Node to inherit from
|
163
|
+
# @overload new(opts)
|
164
|
+
# Create a new StreamHostUsed through a hash of options
|
165
|
+
# @param [Hash] opts a hash options
|
166
|
+
# @option opts [Blather::JID, String] :jid the JID of the StreamHostUsed
|
167
|
+
# @overload new(jid)
|
168
|
+
# Create a new StreamHostUsed
|
169
|
+
# @param [Blather::JID, String] jid the JID of the StreamHostUsed
|
170
|
+
def self.new(jid)
|
171
|
+
new_node = super 'streamhost-used'
|
172
|
+
|
173
|
+
case jid
|
174
|
+
when Nokogiri::XML::Node
|
175
|
+
new_node.inherit jid
|
176
|
+
when Hash
|
177
|
+
new_node.jid = jid[:jid]
|
178
|
+
else
|
179
|
+
new_node.jid = jid
|
180
|
+
end
|
181
|
+
new_node
|
182
|
+
end
|
183
|
+
|
184
|
+
# Get the jid of the used streamhost
|
185
|
+
#
|
186
|
+
# @return [Blather::JID, nil]
|
187
|
+
def jid
|
188
|
+
if j = read_attr(:jid)
|
189
|
+
JID.new(j)
|
190
|
+
else
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Set the jid of the used streamhost
|
196
|
+
#
|
197
|
+
# @param [Blather::JID, String, nil]
|
198
|
+
def jid=(j)
|
199
|
+
write_attr :jid, (j ? j.to_s : nil)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,410 @@
|
|
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
|
+
NS_SI = 'http://jabber.org/protocol/si'
|
37
|
+
register :file_transfer, :si, NS_SI
|
38
|
+
|
39
|
+
# Overrides the parent method to ensure a si node is created
|
40
|
+
#
|
41
|
+
# @see Blather::Stanza::Iq.new
|
42
|
+
def self.new(type = :set)
|
43
|
+
node = super
|
44
|
+
node.si
|
45
|
+
node
|
46
|
+
end
|
47
|
+
|
48
|
+
# Overrides the parent method to ensure the current si node is destroyed
|
49
|
+
#
|
50
|
+
# @see Blather::Stanza::Iq#inherit
|
51
|
+
def inherit(node)
|
52
|
+
si.remove
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
# Find or create si node
|
57
|
+
#
|
58
|
+
# @return [Si::Si]
|
59
|
+
def si
|
60
|
+
Si.find_or_create self
|
61
|
+
end
|
62
|
+
|
63
|
+
# Replaces si node
|
64
|
+
#
|
65
|
+
# @param [Si::Si, XML::Node] node the stanza's new si node
|
66
|
+
#
|
67
|
+
# @return [Si::Si]
|
68
|
+
def si=(node)
|
69
|
+
si.remove
|
70
|
+
self << node
|
71
|
+
Si.find_or_create self
|
72
|
+
end
|
73
|
+
|
74
|
+
# Overrides the parent method to ensure the current si node is destroyed
|
75
|
+
#
|
76
|
+
# @see Blather::Stanza#reply
|
77
|
+
def reply
|
78
|
+
reply = Stanza::Iq::Si.import super
|
79
|
+
reply.si.remove
|
80
|
+
reply
|
81
|
+
end
|
82
|
+
|
83
|
+
class Si < XMPPNode
|
84
|
+
# Create a new Si::Si object
|
85
|
+
#
|
86
|
+
# @param [XML::Node, nil] node a node to inherit from
|
87
|
+
#
|
88
|
+
# @return [Si::Si]
|
89
|
+
def self.new(node = nil)
|
90
|
+
new_node = super :si
|
91
|
+
new_node.namespace = NS_SI
|
92
|
+
new_node.inherit node if node
|
93
|
+
new_node
|
94
|
+
end
|
95
|
+
|
96
|
+
# Find or create si node in Si Iq and converts it to Si::Si
|
97
|
+
#
|
98
|
+
# @param [Si] parent a Si Iq where to find or create si
|
99
|
+
#
|
100
|
+
# @return [Si::Si]
|
101
|
+
def self.find_or_create(parent)
|
102
|
+
if found_si = parent.find_first('//ns:si', :ns => NS_SI)
|
103
|
+
si = self.new found_si
|
104
|
+
found_si.remove
|
105
|
+
else
|
106
|
+
si = self.new
|
107
|
+
end
|
108
|
+
parent << si
|
109
|
+
|
110
|
+
si
|
111
|
+
end
|
112
|
+
|
113
|
+
# Get the id of the stream
|
114
|
+
#
|
115
|
+
# @return [String, nil]
|
116
|
+
def id
|
117
|
+
read_attr :id
|
118
|
+
end
|
119
|
+
|
120
|
+
# Set the id
|
121
|
+
#
|
122
|
+
# @param [String, nil] id the id of the stream
|
123
|
+
def id=(id)
|
124
|
+
write_attr :id, id
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get the MIME type of the stream
|
128
|
+
#
|
129
|
+
# @return [String, nil]
|
130
|
+
def mime_type
|
131
|
+
read_attr 'mime-type'
|
132
|
+
end
|
133
|
+
|
134
|
+
# Set the MIME type
|
135
|
+
#
|
136
|
+
# @param [String, nil] type the MIME type of the stream
|
137
|
+
def mime_type=(type)
|
138
|
+
write_attr 'mime-type', type
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get the profile of the stream
|
142
|
+
#
|
143
|
+
# @return [String, nil]
|
144
|
+
def profile
|
145
|
+
read_attr :profile
|
146
|
+
end
|
147
|
+
|
148
|
+
# Set the profile
|
149
|
+
#
|
150
|
+
# @param [String, nil] profile the profile of the stream
|
151
|
+
def profile=(profile)
|
152
|
+
write_attr :profile, profile
|
153
|
+
end
|
154
|
+
|
155
|
+
# Find or create file node
|
156
|
+
#
|
157
|
+
# @return [Si::Si::File]
|
158
|
+
def file
|
159
|
+
File.find_or_create self
|
160
|
+
end
|
161
|
+
|
162
|
+
# Find or create feature node
|
163
|
+
#
|
164
|
+
# @return [Si::Si::Feature]
|
165
|
+
def feature
|
166
|
+
Feature.find_or_create self
|
167
|
+
end
|
168
|
+
|
169
|
+
class Feature < XMPPNode
|
170
|
+
register :feature, 'http://jabber.org/protocol/feature-neg'
|
171
|
+
|
172
|
+
# Create a new Si::Si::Feature object
|
173
|
+
#
|
174
|
+
# @param [XML::Node, nil] node a node to inherit from
|
175
|
+
#
|
176
|
+
# @return [Si::Si::Feature]
|
177
|
+
def self.new(node = nil)
|
178
|
+
new_node = super :feature
|
179
|
+
new_node.namespace = self.registered_ns
|
180
|
+
new_node.inherit node if node
|
181
|
+
new_node
|
182
|
+
end
|
183
|
+
|
184
|
+
# Find or create feature node in si node and converts it to Si::Si::Feature
|
185
|
+
#
|
186
|
+
# @param [Si::Si] parent a si node where to find or create feature
|
187
|
+
#
|
188
|
+
# @return [Si::Si::Feature]
|
189
|
+
def self.find_or_create(parent)
|
190
|
+
if found_feature = parent.find_first('//ns:feature', :ns => self.registered_ns)
|
191
|
+
feature = self.new found_feature
|
192
|
+
found_feature.remove
|
193
|
+
else
|
194
|
+
feature = self.new
|
195
|
+
end
|
196
|
+
parent << feature
|
197
|
+
|
198
|
+
feature
|
199
|
+
end
|
200
|
+
|
201
|
+
# Find or create x node
|
202
|
+
#
|
203
|
+
# @return [Stanza::X]
|
204
|
+
def x
|
205
|
+
Stanza::X.find_or_create self
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class File < XMPPNode
|
210
|
+
register :file, 'http://jabber.org/protocol/si/profile/file-transfer'
|
211
|
+
|
212
|
+
# Create a new Si::Si::File object
|
213
|
+
#
|
214
|
+
# @param [XML::Node, nil] node a node to inherit from
|
215
|
+
#
|
216
|
+
# @return [Si::Si::File]
|
217
|
+
def self.new(name = nil, size = nil)
|
218
|
+
new_node = super :file
|
219
|
+
|
220
|
+
case name
|
221
|
+
when Nokogiri::XML::Node
|
222
|
+
new_node.inherit name
|
223
|
+
else
|
224
|
+
new_node.name = name
|
225
|
+
new_node.size = size
|
226
|
+
end
|
227
|
+
new_node
|
228
|
+
end
|
229
|
+
|
230
|
+
# Find or create file node in si node and converts it to Si::Si::File
|
231
|
+
#
|
232
|
+
# @param [Si::Si] parent a si node where to find or create file
|
233
|
+
#
|
234
|
+
# @return [Si::Si::File]
|
235
|
+
def self.find_or_create(parent)
|
236
|
+
if found_file = parent.find_first('//ns:file', :ns => self.registered_ns)
|
237
|
+
file = self.new found_file
|
238
|
+
found_file.remove
|
239
|
+
else
|
240
|
+
file = self.new
|
241
|
+
end
|
242
|
+
parent << file
|
243
|
+
|
244
|
+
file
|
245
|
+
end
|
246
|
+
|
247
|
+
# Get the filename
|
248
|
+
#
|
249
|
+
# @return [String, nil]
|
250
|
+
def name
|
251
|
+
read_attr :name
|
252
|
+
end
|
253
|
+
|
254
|
+
# Set the filename
|
255
|
+
#
|
256
|
+
# @param [String, nil] name the name of the file
|
257
|
+
def name=(name)
|
258
|
+
write_attr :name, name
|
259
|
+
end
|
260
|
+
|
261
|
+
# Get the hash
|
262
|
+
#
|
263
|
+
# @return [String, nil]
|
264
|
+
def hash
|
265
|
+
read_attr :hash
|
266
|
+
end
|
267
|
+
|
268
|
+
# Set the hash
|
269
|
+
#
|
270
|
+
# @param [String, nil] hash the MD5 hash of the file
|
271
|
+
def hash=(hash)
|
272
|
+
write_attr :hash, hash
|
273
|
+
end
|
274
|
+
|
275
|
+
# Get the date
|
276
|
+
#
|
277
|
+
# @return [Time, nil]
|
278
|
+
def date
|
279
|
+
begin
|
280
|
+
Time.xmlschema(read_attr(:date))
|
281
|
+
rescue ArgumentError
|
282
|
+
nil
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Set the date
|
287
|
+
#
|
288
|
+
# @param [Time, nil] date the last modification time of the file
|
289
|
+
def date=(date)
|
290
|
+
write_attr :date, (date ? date.xmlschema : nil)
|
291
|
+
end
|
292
|
+
|
293
|
+
# Get the size
|
294
|
+
#
|
295
|
+
# @return [Fixnum, nil]
|
296
|
+
def size
|
297
|
+
if (s = read_attr(:size)) && (s =~ /^\d+$/)
|
298
|
+
s.to_i
|
299
|
+
else
|
300
|
+
nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Set the size
|
305
|
+
#
|
306
|
+
# @param [Fixnum, nil] size the size, in bytes, of the file
|
307
|
+
def size=(size)
|
308
|
+
write_attr :size, size
|
309
|
+
end
|
310
|
+
|
311
|
+
# Get the desc
|
312
|
+
#
|
313
|
+
# @return [String, nil]
|
314
|
+
def desc
|
315
|
+
content_from 'ns:desc', :ns => self.class.registered_ns
|
316
|
+
end
|
317
|
+
|
318
|
+
# Set the desc
|
319
|
+
#
|
320
|
+
# @param [String, nil] desc the description of the file
|
321
|
+
def desc=(desc)
|
322
|
+
set_content_for :desc, desc
|
323
|
+
end
|
324
|
+
|
325
|
+
# Find or create range node
|
326
|
+
#
|
327
|
+
# @return [Si::Si::File::Range]
|
328
|
+
def range
|
329
|
+
Range.find_or_create self
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
class Range < XMPPNode
|
334
|
+
register :range, 'http://jabber.org/protocol/si/profile/file-transfer'
|
335
|
+
|
336
|
+
# Create a new Si::Si::File::Range object
|
337
|
+
#
|
338
|
+
# @param [XML::Node, nil] node a node to inherit from
|
339
|
+
#
|
340
|
+
# @return [Si::Si::File::Range]
|
341
|
+
def self.new(offset = nil, length = nil)
|
342
|
+
new_node = super :range
|
343
|
+
|
344
|
+
case offset
|
345
|
+
when Nokogiri::XML::Node
|
346
|
+
new_node.inherit offset
|
347
|
+
else
|
348
|
+
new_node.offset = offset
|
349
|
+
new_node.length = length
|
350
|
+
end
|
351
|
+
new_node
|
352
|
+
end
|
353
|
+
# Find or create range node in file node and converts it to Si::Si::File::Range
|
354
|
+
#
|
355
|
+
# @param [Si::Si::File] parent a file node where to find or create range
|
356
|
+
#
|
357
|
+
# @return [Si::Si::File::Range]
|
358
|
+
def self.find_or_create(parent)
|
359
|
+
if found_range = parent.find_first('//ns:range', :ns => self.registered_ns)
|
360
|
+
range = self.new found_range
|
361
|
+
found_range.remove
|
362
|
+
else
|
363
|
+
range = self.new
|
364
|
+
end
|
365
|
+
parent << range
|
366
|
+
|
367
|
+
range
|
368
|
+
end
|
369
|
+
|
370
|
+
# Get the offset
|
371
|
+
#
|
372
|
+
# @return [Fixnum, nil]
|
373
|
+
def offset
|
374
|
+
if (o = read_attr(:offset)) && (o =~ /^\d+$/)
|
375
|
+
o.to_i
|
376
|
+
else
|
377
|
+
nil
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
# Set the offset
|
382
|
+
#
|
383
|
+
# @param [Fixnum, nil] offset the position, in bytes, to start transferring the file data from
|
384
|
+
def offset=(offset)
|
385
|
+
write_attr :offset, offset
|
386
|
+
end
|
387
|
+
|
388
|
+
# Get the length
|
389
|
+
#
|
390
|
+
# @return [Fixnum, nil]
|
391
|
+
def length
|
392
|
+
if (l = read_attr(:length)) && (l =~ /^\d+$/)
|
393
|
+
l.to_i
|
394
|
+
else
|
395
|
+
nil
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# Set the length
|
400
|
+
#
|
401
|
+
# @param [Fixnum, nil] length the number of bytes to retrieve starting at offset
|
402
|
+
def length=(length)
|
403
|
+
write_attr :length, length
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|