sprsquish-blather 0.3.4 → 0.4.0
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/LICENSE +1 -1
- data/README.rdoc +41 -12
- data/examples/echo.rb +1 -1
- data/examples/execute.rb +0 -5
- data/examples/pubsub/cli.rb +64 -0
- data/examples/pubsub/ping_pong.rb +18 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/lib/blather/client/client.rb +19 -13
- data/lib/blather/client/dsl/pubsub.rb +133 -0
- data/lib/blather/client/dsl.rb +16 -0
- data/lib/blather/client.rb +1 -1
- data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
- data/lib/blather/core_ext/active_support.rb +1 -117
- data/lib/blather/core_ext/nokogiri.rb +35 -0
- data/lib/blather/errors/sasl_error.rb +3 -1
- data/lib/blather/errors/stanza_error.rb +10 -17
- data/lib/blather/errors/stream_error.rb +11 -14
- data/lib/blather/errors.rb +3 -20
- data/lib/blather/jid.rb +1 -0
- data/lib/blather/roster.rb +9 -0
- data/lib/blather/roster_item.rb +6 -1
- data/lib/blather/stanza/disco/disco_info.rb +45 -33
- data/lib/blather/stanza/disco/disco_items.rb +32 -21
- data/lib/blather/stanza/disco.rb +7 -1
- data/lib/blather/stanza/iq/query.rb +16 -8
- data/lib/blather/stanza/iq/roster.rb +33 -22
- data/lib/blather/stanza/iq.rb +13 -8
- data/lib/blather/stanza/message.rb +20 -31
- data/lib/blather/stanza/presence/status.rb +13 -21
- data/lib/blather/stanza/presence/subscription.rb +11 -16
- data/lib/blather/stanza/presence.rb +3 -5
- data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
- data/lib/blather/stanza/pubsub/create.rb +43 -0
- data/lib/blather/stanza/pubsub/errors.rb +9 -0
- data/lib/blather/stanza/pubsub/event.rb +77 -0
- data/lib/blather/stanza/pubsub/items.rb +63 -0
- data/lib/blather/stanza/pubsub/publish.rb +58 -0
- data/lib/blather/stanza/pubsub/retract.rb +53 -0
- data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
- data/lib/blather/stanza/pubsub/subscription.rb +66 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
- data/lib/blather/stanza/pubsub.rb +63 -0
- data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
- data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
- data/lib/blather/stanza/pubsub_owner.rb +41 -0
- data/lib/blather/stanza.rb +35 -18
- data/lib/blather/stream/client.rb +1 -2
- data/lib/blather/stream/component.rb +9 -5
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
- data/lib/blather/stream/features/session.rb +44 -0
- data/lib/blather/stream/features/tls.rb +28 -0
- data/lib/blather/stream/features.rb +53 -0
- data/lib/blather/stream/parser.rb +70 -46
- data/lib/blather/stream.rb +76 -168
- data/lib/blather/xmpp_node.rb +113 -52
- data/lib/blather.rb +35 -12
- data/spec/blather/client/client_spec.rb +44 -58
- data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
- data/spec/blather/client/dsl_spec.rb +19 -6
- data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
- data/spec/blather/errors/sasl_error_spec.rb +8 -8
- data/spec/blather/errors/stanza_error_spec.rb +25 -33
- data/spec/blather/errors/stream_error_spec.rb +21 -16
- data/spec/blather/errors_spec.rb +4 -11
- data/spec/blather/jid_spec.rb +31 -30
- data/spec/blather/roster_item_spec.rb +34 -23
- data/spec/blather/roster_spec.rb +27 -12
- data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
- data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
- data/spec/blather/stanza/iq/query_spec.rb +34 -11
- data/spec/blather/stanza/iq/roster_spec.rb +47 -30
- data/spec/blather/stanza/iq_spec.rb +19 -14
- data/spec/blather/stanza/message_spec.rb +30 -17
- data/spec/blather/stanza/presence/status_spec.rb +43 -20
- data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
- data/spec/blather/stanza/presence_spec.rb +34 -21
- 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 +84 -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 +61 -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 +62 -0
- data/spec/blather/stanza_spec.rb +53 -38
- data/spec/blather/stream/client_spec.rb +231 -88
- data/spec/blather/stream/component_spec.rb +14 -5
- data/spec/blather/stream/parser_spec.rb +145 -0
- data/spec/blather/xmpp_node_spec.rb +192 -96
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +5 -4
- metadata +53 -17
- data/Rakefile +0 -139
- data/ext/extconf.rb +0 -65
- data/ext/push_parser.c +0 -209
- data/lib/blather/core_ext/libxml.rb +0 -28
- data/lib/blather/stream/resource.rb +0 -48
- data/lib/blather/stream/session.rb +0 -36
- data/lib/blather/stream/stream_handler.rb +0 -39
- data/lib/blather/stream/tls.rb +0 -33
- data/spec/blather/core_ext/libxml_spec.rb +0 -58
@@ -1,120 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
|
4
|
-
# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
|
5
|
-
# to, for example, an array without those additions being shared with either their parent, siblings, or
|
6
|
-
# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
|
7
|
-
class Class # :nodoc:
|
8
|
-
def class_inheritable_reader(*syms)
|
9
|
-
syms.each do |sym|
|
10
|
-
next if sym.is_a?(Hash)
|
11
|
-
class_eval <<-EOS
|
12
|
-
def self.#{sym}
|
13
|
-
read_inheritable_attribute(:#{sym})
|
14
|
-
end
|
15
|
-
|
16
|
-
def #{sym}
|
17
|
-
self.class.#{sym}
|
18
|
-
end
|
19
|
-
EOS
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def class_inheritable_writer(*syms)
|
24
|
-
syms.each do |sym|
|
25
|
-
class_eval <<-EOS
|
26
|
-
def self.#{sym}=(obj)
|
27
|
-
write_inheritable_attribute(:#{sym}, obj)
|
28
|
-
end
|
29
|
-
EOS
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def class_inheritable_array_writer(*syms)
|
34
|
-
syms.each do |sym|
|
35
|
-
class_eval <<-EOS
|
36
|
-
def self.#{sym}=(obj)
|
37
|
-
write_inheritable_array(:#{sym}, obj)
|
38
|
-
end
|
39
|
-
EOS
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def class_inheritable_hash_writer(*syms)
|
44
|
-
syms.each do |sym|
|
45
|
-
class_eval <<-EOS
|
46
|
-
def self.#{sym}=(obj)
|
47
|
-
write_inheritable_hash(:#{sym}, obj)
|
48
|
-
end
|
49
|
-
EOS
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def class_inheritable_accessor(*syms)
|
54
|
-
class_inheritable_reader(*syms)
|
55
|
-
class_inheritable_writer(*syms)
|
56
|
-
end
|
57
|
-
|
58
|
-
def class_inheritable_array(*syms)
|
59
|
-
class_inheritable_reader(*syms)
|
60
|
-
class_inheritable_array_writer(*syms)
|
61
|
-
end
|
62
|
-
|
63
|
-
def class_inheritable_hash(*syms)
|
64
|
-
class_inheritable_reader(*syms)
|
65
|
-
class_inheritable_hash_writer(*syms)
|
66
|
-
end
|
67
|
-
|
68
|
-
def inheritable_attributes
|
69
|
-
@inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
|
70
|
-
end
|
71
|
-
|
72
|
-
def write_inheritable_attribute(key, value)
|
73
|
-
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
74
|
-
@inheritable_attributes = {}
|
75
|
-
end
|
76
|
-
inheritable_attributes[key] = value
|
77
|
-
end
|
78
|
-
|
79
|
-
def write_inheritable_array(key, elements)
|
80
|
-
write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
|
81
|
-
write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
|
82
|
-
end
|
83
|
-
|
84
|
-
def write_inheritable_hash(key, hash)
|
85
|
-
write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
|
86
|
-
write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
|
87
|
-
end
|
88
|
-
|
89
|
-
def read_inheritable_attribute(key)
|
90
|
-
inheritable_attributes[key]
|
91
|
-
end
|
92
|
-
|
93
|
-
def reset_inheritable_attributes
|
94
|
-
@inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
95
|
-
end
|
96
|
-
|
97
|
-
private
|
98
|
-
# Prevent this constant from being created multiple times
|
99
|
-
EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
|
100
|
-
|
101
|
-
def inherited_with_inheritable_attributes(child)
|
102
|
-
inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
|
103
|
-
|
104
|
-
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
105
|
-
new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
106
|
-
else
|
107
|
-
new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)|
|
108
|
-
memo.update(key => value.duplicable? ? value.dup : value)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
|
113
|
-
end
|
114
|
-
|
115
|
-
alias inherited_without_inheritable_attributes inherited
|
116
|
-
alias inherited inherited_with_inheritable_attributes
|
117
|
-
end #Class
|
1
|
+
require File.join(File.dirname(__FILE__), 'active_support', 'inheritable_attributes')
|
118
2
|
|
119
3
|
class Object # :nodoc:
|
120
4
|
def duplicable?; true; end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Nokogiri # :nodoc:
|
2
|
+
module XML
|
3
|
+
|
4
|
+
class Node
|
5
|
+
alias_method :element_name, :name
|
6
|
+
alias_method :element_name=, :name=
|
7
|
+
|
8
|
+
alias_method :attr_set, :[]=
|
9
|
+
def []=(name, value)
|
10
|
+
name = name.to_s
|
11
|
+
value.nil? ? remove_attribute(name) : attr_set(name, value.to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
# alias_method :attr_get, :[]
|
15
|
+
# def [](name)
|
16
|
+
# attr_get name.to_s
|
17
|
+
# end
|
18
|
+
|
19
|
+
alias_method :nokogiri_xpath, :xpath
|
20
|
+
def xpath(*paths)
|
21
|
+
paths[0] = paths[0].to_s
|
22
|
+
if paths.size > 1 && (namespaces = paths.pop).is_a?(Hash)
|
23
|
+
paths << namespaces.inject({}) { |h,v| h[v[0].to_s] = v[1]; h }
|
24
|
+
end
|
25
|
+
nokogiri_xpath *paths
|
26
|
+
end
|
27
|
+
alias_method :find, :xpath
|
28
|
+
|
29
|
+
def find_first(*paths)
|
30
|
+
xpath(*paths).first
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end #XML
|
35
|
+
end #Blather
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Blather
|
2
2
|
|
3
3
|
class SASLError < BlatherError
|
4
|
+
SASL_ERR_NS = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
5
|
+
|
4
6
|
class_inheritable_accessor :err_name
|
5
7
|
@@registrations = {}
|
6
8
|
|
@@ -16,7 +18,7 @@ class SASLError < BlatherError
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def name
|
19
|
-
@node.
|
21
|
+
@node.find_first('err_ns:*', :err_ns => SASL_ERR_NS).element_name.gsub('-', '_').to_sym if @node
|
20
22
|
end
|
21
23
|
end #SASLError
|
22
24
|
|
@@ -4,6 +4,7 @@ module Blather
|
|
4
4
|
# Stanza errors
|
5
5
|
# RFC3920 Section 9.3 (http://xmpp.org/rfcs/rfc3920.html#stanzas-error)
|
6
6
|
class StanzaError < BlatherError
|
7
|
+
STANZA_ERR_NS = 'urn:ietf:params:xml:ns:xmpp-stanzas'
|
7
8
|
VALID_TYPES = [:cancel, :continue, :modify, :auth, :wait]
|
8
9
|
|
9
10
|
register :stanza_error
|
@@ -19,9 +20,9 @@ class StanzaError < BlatherError
|
|
19
20
|
|
20
21
|
error_node = node.find_first '//*[local-name()="error"]'
|
21
22
|
|
22
|
-
name = error_node.find_first('child::*[name()!="text"]',
|
23
|
+
name = error_node.find_first('child::*[name()!="text"]', STANZA_ERR_NS).element_name
|
23
24
|
type = error_node['type']
|
24
|
-
text = node.find_first '
|
25
|
+
text = node.find_first 'descendant::*[name()="text"]', STANZA_ERR_NS
|
25
26
|
text = text.content if text
|
26
27
|
|
27
28
|
extras = error_node.find("descendant::*[name()!='text' and name()!='#{name}']").map { |n| n }
|
@@ -59,27 +60,19 @@ class StanzaError < BlatherError
|
|
59
60
|
# Creates an XML node from the error
|
60
61
|
def to_node
|
61
62
|
node = self.original.reply
|
63
|
+
node.type = 'error'
|
64
|
+
node << (error_node = XMPPNode.new('error'))
|
62
65
|
|
63
|
-
error_node = XMPPNode.new
|
64
|
-
err = XMPPNode.new(@name)
|
66
|
+
error_node << (err = XMPPNode.new(@name, error_node.document))
|
65
67
|
err.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
|
66
|
-
error_node << err
|
67
68
|
|
68
69
|
if self.text
|
69
|
-
text = XMPPNode.new('text')
|
70
|
+
error_node << (text = XMPPNode.new('text', error_node.document))
|
70
71
|
text.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
|
71
|
-
text
|
72
|
-
error_node << text
|
73
|
-
end
|
74
|
-
|
75
|
-
self.extras.each do |extra|
|
76
|
-
extra_copy = extra.copy
|
77
|
-
extra_copy.namespace = extra.namespace
|
78
|
-
error_node << extra_copy
|
72
|
+
text.content = self.text
|
79
73
|
end
|
80
74
|
|
81
|
-
|
82
|
-
node.type = 'error'
|
75
|
+
self.extras.each { |extra| error_node << extra.dup }
|
83
76
|
node
|
84
77
|
end
|
85
78
|
|
@@ -90,7 +83,7 @@ class StanzaError < BlatherError
|
|
90
83
|
end
|
91
84
|
|
92
85
|
def inspect # :nodoc:
|
93
|
-
"Stanza Error (#{@name}): #{self.text}"
|
86
|
+
"Stanza Error (#{@name}): #{self.text} [#{self.extras}]"
|
94
87
|
end
|
95
88
|
alias_method :to_s, :inspect # :nodoc:
|
96
89
|
end #StanzaError
|
@@ -4,6 +4,8 @@ module Blather
|
|
4
4
|
# Stream Errors
|
5
5
|
# RFC3920 Section 9.3 (http://xmpp.org/rfcs/rfc3920.html#streams-error-rules)
|
6
6
|
class StreamError < BlatherError
|
7
|
+
STREAM_ERR_NS = 'urn:ietf:params:xml:ns:xmpp-streams'
|
8
|
+
|
7
9
|
register :stream_error
|
8
10
|
|
9
11
|
attr_reader :text, :extras
|
@@ -12,11 +14,12 @@ class StreamError < BlatherError
|
|
12
14
|
# Factory method for instantiating the proper class
|
13
15
|
# for the error
|
14
16
|
def self.import(node)
|
15
|
-
name = node.find_first('descendant::*[name()!="text"]',
|
16
|
-
|
17
|
+
name = node.find_first('descendant::*[name()!="text"]', STREAM_ERR_NS).element_name
|
18
|
+
|
19
|
+
text = node.find_first 'descendant::*[name()="text"]', STREAM_ERR_NS
|
17
20
|
text = text.content if text
|
18
21
|
|
19
|
-
extras = node.find("descendant::*[
|
22
|
+
extras = node.find("descendant::*[namespace-uri()!='#{STREAM_ERR_NS}']").map { |n| n }
|
20
23
|
|
21
24
|
self.new name, text, extras
|
22
25
|
end
|
@@ -41,22 +44,16 @@ class StreamError < BlatherError
|
|
41
44
|
def to_node
|
42
45
|
node = XMPPNode.new('stream:error')
|
43
46
|
|
44
|
-
err = XMPPNode.new(@name)
|
47
|
+
node << (err = XMPPNode.new(@name, node.document))
|
45
48
|
err.namespace = 'urn:ietf:params:xml:ns:xmpp-streams'
|
46
|
-
node << err
|
47
49
|
|
48
50
|
if self.text
|
49
|
-
text = XMPPNode.new('text')
|
51
|
+
node << (text = XMPPNode.new('text', node.document))
|
50
52
|
text.namespace = 'urn:ietf:params:xml:ns:xmpp-streams'
|
51
|
-
text
|
52
|
-
node << text
|
53
|
+
text.content = self.text
|
53
54
|
end
|
54
55
|
|
55
|
-
self.extras.each
|
56
|
-
extra_copy = extra.copy
|
57
|
-
extra_copy.namespace = extra.namespace
|
58
|
-
node << extra_copy
|
59
|
-
end
|
56
|
+
self.extras.each { |extra| node << extra.dup }
|
60
57
|
node
|
61
58
|
end
|
62
59
|
|
@@ -67,7 +64,7 @@ class StreamError < BlatherError
|
|
67
64
|
end
|
68
65
|
|
69
66
|
def inspect # :nodoc:
|
70
|
-
"Stream Error (#{@name}): #{self.text}"
|
67
|
+
"Stream Error (#{@name}): #{self.text}" + (self.extras.empty? ? '' : " [#{self.extras}]")
|
71
68
|
end
|
72
69
|
alias_method :to_s, :inspect # :nodoc:
|
73
70
|
end #StreamError
|
data/lib/blather/errors.rb
CHANGED
@@ -34,31 +34,14 @@ module Blather
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
##
|
38
|
-
# TLS negotiations broke down
|
39
|
-
class TLSFailure < BlatherError
|
40
|
-
register :tls_failure
|
41
|
-
end
|
42
|
-
|
43
|
-
class ParseWarning < BlatherError
|
44
|
-
register :parse_warning
|
45
|
-
attr_reader :libxml_error, :message
|
46
|
-
|
47
|
-
def initialize(err)
|
48
|
-
@libxml_error = err
|
49
|
-
@message = err.to_s
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
37
|
##
|
54
38
|
# Something bad happened while parsing the incoming stream
|
55
39
|
class ParseError < BlatherError
|
56
40
|
register :parse_error
|
57
|
-
attr_reader :
|
41
|
+
attr_reader :message
|
58
42
|
|
59
|
-
def initialize(
|
60
|
-
@
|
61
|
-
@message = err.to_s
|
43
|
+
def initialize(msg)
|
44
|
+
@message = msg.to_s
|
62
45
|
end
|
63
46
|
end
|
64
47
|
end
|
data/lib/blather/jid.rb
CHANGED
data/lib/blather/roster.rb
CHANGED
@@ -71,6 +71,15 @@ module Blather
|
|
71
71
|
@items.dup
|
72
72
|
end
|
73
73
|
|
74
|
+
##
|
75
|
+
# A hash of items keyed by group
|
76
|
+
def grouped
|
77
|
+
self.inject(Hash.new{|h,k|h[k]=[]}) do |hash, item|
|
78
|
+
item[1].groups.each { |group| hash[group] << item[1] }
|
79
|
+
hash
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
74
83
|
private
|
75
84
|
def self.key(jid)
|
76
85
|
JID.new(jid).stripped.to_s
|
data/lib/blather/roster_item.rb
CHANGED
@@ -13,6 +13,11 @@ module Blather
|
|
13
13
|
attr_accessor :name,
|
14
14
|
:groups
|
15
15
|
|
16
|
+
def self.new(item)
|
17
|
+
return item if item.is_a?(self)
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
16
21
|
##
|
17
22
|
# item:: can be a JID, String (a@b) or a Stanza
|
18
23
|
def initialize(item)
|
@@ -29,7 +34,7 @@ module Blather
|
|
29
34
|
self.name = item[:name]
|
30
35
|
self.subscription = item[:subscription]
|
31
36
|
self.ask = item[:ask]
|
32
|
-
item.groups.each { |g|
|
37
|
+
item.groups.each { |g| @groups << g }
|
33
38
|
end
|
34
39
|
|
35
40
|
@groups = [nil] if @groups.empty?
|
@@ -7,64 +7,76 @@ class Stanza
|
|
7
7
|
class DiscoInfo < Disco
|
8
8
|
register :disco_info, nil, 'http://jabber.org/protocol/disco#info'
|
9
9
|
|
10
|
-
def
|
11
|
-
super type
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
query << (id.is_a?(Identity) ? id : Identity.new(id[:name], id[:type], id[:category]))
|
17
|
-
end
|
18
|
-
|
19
|
-
[features].flatten.each do |feature|
|
20
|
-
query << (feature.is_a?(Feature) ? feature : Feature.new(feature))
|
21
|
-
end
|
10
|
+
def self.new(type = nil, node = nil, identities = [], features = [])
|
11
|
+
new_node = super type
|
12
|
+
new_node.node = node
|
13
|
+
[identities].flatten.each { |id| new_node.query << Identity.new(id) }
|
14
|
+
[features].flatten.each { |feature| new_node.query << Feature.new(feature) }
|
15
|
+
new_node
|
22
16
|
end
|
23
17
|
|
24
18
|
##
|
25
19
|
# List of identity objects
|
26
20
|
def identities
|
27
|
-
|
28
|
-
identities = query.find('query_ns:identity', :query_ns => self.class.ns) if identities.empty?
|
29
|
-
identities.map { |i| Identity.new i }
|
21
|
+
query.find('//query_ns:identity', :query_ns => self.class.registered_ns).map { |i| Identity.new i }
|
30
22
|
end
|
31
23
|
|
32
24
|
##
|
33
25
|
# List of feature objects
|
34
26
|
def features
|
35
|
-
|
36
|
-
features = query.find('query_ns:feature', :query_ns => self.class.ns) if features.empty?
|
37
|
-
features.map { |i| Feature.new i }
|
27
|
+
query.find('//query_ns:feature', :query_ns => self.class.registered_ns).map { |i| Feature.new i }
|
38
28
|
end
|
39
29
|
|
40
30
|
class Identity < XMPPNode
|
41
|
-
attribute_accessor :category, :type
|
42
|
-
attribute_accessor :name
|
31
|
+
attribute_accessor :category, :type, :call => :to_sym
|
32
|
+
attribute_accessor :name
|
43
33
|
|
44
|
-
def
|
45
|
-
super :identity
|
34
|
+
def self.new(name, type = nil, category = nil)
|
35
|
+
new_node = super :identity
|
46
36
|
|
47
|
-
|
48
|
-
|
37
|
+
case name
|
38
|
+
when Nokogiri::XML::Node
|
39
|
+
new_node.inherit name
|
40
|
+
when Hash
|
41
|
+
new_node.name = name[:name]
|
42
|
+
new_node.type = name[:type]
|
43
|
+
new_node.category = name[:category]
|
49
44
|
else
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
new_node.name = name
|
46
|
+
new_node.type = type
|
47
|
+
new_node.category = category
|
53
48
|
end
|
49
|
+
new_node
|
54
50
|
end
|
51
|
+
|
52
|
+
def eql?(o)
|
53
|
+
raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
|
54
|
+
o.name == self.name &&
|
55
|
+
o.type == self.type &&
|
56
|
+
o.category == self.category
|
57
|
+
end
|
58
|
+
alias_method :==, :eql?
|
55
59
|
end
|
56
60
|
|
57
61
|
class Feature < XMPPNode
|
58
|
-
attribute_accessor :var
|
62
|
+
attribute_accessor :var
|
59
63
|
|
60
|
-
def
|
61
|
-
super :feature
|
62
|
-
|
63
|
-
|
64
|
+
def self.new(var)
|
65
|
+
new_node = super :feature
|
66
|
+
case var
|
67
|
+
when Nokogiri::XML::Node
|
68
|
+
new_node.inherit var
|
64
69
|
else
|
65
|
-
|
70
|
+
new_node.var = var
|
66
71
|
end
|
72
|
+
new_node
|
73
|
+
end
|
74
|
+
|
75
|
+
def eql?(o)
|
76
|
+
raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
|
77
|
+
o.var == self.var
|
67
78
|
end
|
79
|
+
alias_method :==, :eql?
|
68
80
|
end
|
69
81
|
end
|
70
82
|
|
@@ -4,47 +4,58 @@ class Stanza
|
|
4
4
|
class DiscoItems < Disco
|
5
5
|
register :disco_items, nil, 'http://jabber.org/protocol/disco#items'
|
6
6
|
|
7
|
-
def
|
8
|
-
super type
|
9
|
-
|
10
|
-
[items].flatten.each
|
11
|
-
|
12
|
-
end
|
7
|
+
def self.new(type = nil, node = nil, items = [])
|
8
|
+
new_node = super type
|
9
|
+
new_node.node = node
|
10
|
+
[items].flatten.each { |item| new_node.query << Item.new(item) }
|
11
|
+
new_node
|
13
12
|
end
|
14
13
|
|
15
14
|
def items
|
16
|
-
|
17
|
-
items = query.find('query_ns:item', :query_ns => self.class.ns) if items.empty?
|
18
|
-
items.map { |i| Item.new i }
|
15
|
+
query.find('//query_ns:item', :query_ns => self.class.registered_ns).map { |i| Item.new i }
|
19
16
|
end
|
20
17
|
|
21
18
|
def node=(node)
|
22
|
-
query
|
19
|
+
query[:node] = node
|
23
20
|
end
|
24
21
|
|
25
22
|
def node
|
26
|
-
query
|
23
|
+
query[:node]
|
27
24
|
end
|
28
25
|
|
29
26
|
class Item < XMPPNode
|
30
|
-
def
|
31
|
-
super :item
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
def self.new(jid, node = nil, name = nil)
|
28
|
+
new_node = super :item
|
29
|
+
|
30
|
+
case jid
|
31
|
+
when Nokogiri::XML::Node
|
32
|
+
new_node.inherit jid
|
33
|
+
when Hash
|
34
|
+
new_node.jid = jid[:jid]
|
35
|
+
new_node.node = jid[:node]
|
36
|
+
new_node.name = jid[:name]
|
35
37
|
else
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
new_node.jid = jid
|
39
|
+
new_node.node = node
|
40
|
+
new_node.name = name
|
39
41
|
end
|
42
|
+
new_node
|
40
43
|
end
|
41
44
|
|
42
45
|
def jid
|
43
|
-
(j =
|
46
|
+
(j = self[:jid]) ? JID.new(j) : nil
|
44
47
|
end
|
45
48
|
attribute_writer :jid
|
46
49
|
|
47
|
-
attribute_accessor :node, :name
|
50
|
+
attribute_accessor :node, :name
|
51
|
+
|
52
|
+
def eql?(o)
|
53
|
+
raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
|
54
|
+
o.jid == self.jid &&
|
55
|
+
o.node == self.node &&
|
56
|
+
o.name == self.name
|
57
|
+
end
|
58
|
+
alias_method :==, :eql?
|
48
59
|
end
|
49
60
|
end
|
50
61
|
|
data/lib/blather/stanza/disco.rb
CHANGED
@@ -6,16 +6,17 @@ class Iq
|
|
6
6
|
register :query, :query
|
7
7
|
|
8
8
|
##
|
9
|
-
# Ensure the
|
10
|
-
def
|
11
|
-
super
|
12
|
-
query
|
9
|
+
# Ensure the query node is created
|
10
|
+
def self.new(type = nil)
|
11
|
+
node = super
|
12
|
+
node.query
|
13
|
+
node
|
13
14
|
end
|
14
15
|
|
15
16
|
##
|
16
17
|
# Kill the query node before running inherit
|
17
18
|
def inherit(node)
|
18
|
-
query.remove
|
19
|
+
query.remove
|
19
20
|
super
|
20
21
|
end
|
21
22
|
|
@@ -23,9 +24,16 @@ class Iq
|
|
23
24
|
# Query node accessor
|
24
25
|
# This will ensure there actually is a query node
|
25
26
|
def query
|
26
|
-
q =
|
27
|
-
|
28
|
-
|
27
|
+
q = if self.class.registered_ns
|
28
|
+
find_first('query_ns:query', :query_ns => self.class.registered_ns)
|
29
|
+
else
|
30
|
+
find_first('query')
|
31
|
+
end
|
32
|
+
|
33
|
+
unless q
|
34
|
+
(self << (q = XMPPNode.new('query', self.document)))
|
35
|
+
q.namespace = self.class.registered_ns
|
36
|
+
end
|
29
37
|
q
|
30
38
|
end
|
31
39
|
|