shingara-blather 0.4.8
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 +22 -0
- data/README.md +162 -0
- data/examples/echo.rb +18 -0
- data/examples/execute.rb +16 -0
- data/examples/ping_pong.rb +37 -0
- data/examples/print_hierarchy.rb +76 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/stream_only.rb +27 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/lib/blather/client/client.rb +310 -0
- data/lib/blather/client/dsl/pubsub.rb +170 -0
- data/lib/blather/client/dsl.rb +264 -0
- data/lib/blather/client.rb +87 -0
- data/lib/blather/core_ext/nokogiri.rb +40 -0
- data/lib/blather/errors/sasl_error.rb +43 -0
- data/lib/blather/errors/stanza_error.rb +107 -0
- data/lib/blather/errors/stream_error.rb +82 -0
- data/lib/blather/errors.rb +69 -0
- data/lib/blather/jid.rb +142 -0
- data/lib/blather/roster.rb +111 -0
- data/lib/blather/roster_item.rb +122 -0
- data/lib/blather/stanza/disco/disco_info.rb +176 -0
- data/lib/blather/stanza/disco/disco_items.rb +132 -0
- data/lib/blather/stanza/disco.rb +25 -0
- data/lib/blather/stanza/iq/query.rb +53 -0
- data/lib/blather/stanza/iq/roster.rb +179 -0
- data/lib/blather/stanza/iq.rb +138 -0
- data/lib/blather/stanza/message.rb +332 -0
- data/lib/blather/stanza/presence/status.rb +212 -0
- data/lib/blather/stanza/presence/subscription.rb +101 -0
- data/lib/blather/stanza/presence.rb +163 -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 +123 -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 +134 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
- data/lib/blather/stanza/pubsub.rb +129 -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/pubsub_owner.rb +51 -0
- data/lib/blather/stanza.rb +149 -0
- data/lib/blather/stream/client.rb +31 -0
- data/lib/blather/stream/component.rb +38 -0
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/features/sasl.rb +187 -0
- 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 +102 -0
- data/lib/blather/stream.rb +231 -0
- data/lib/blather/xmpp_node.rb +218 -0
- data/lib/blather.rb +78 -0
- data/spec/blather/client/client_spec.rb +559 -0
- data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
- data/spec/blather/client/dsl_spec.rb +143 -0
- data/spec/blather/core_ext/nokogiri_spec.rb +83 -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/jid_spec.rb +87 -0
- data/spec/blather/roster_item_spec.rb +96 -0
- data/spec/blather/roster_spec.rb +103 -0
- data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
- data/spec/blather/stanza/iq/query_spec.rb +64 -0
- data/spec/blather/stanza/iq/roster_spec.rb +140 -0
- data/spec/blather/stanza/iq_spec.rb +45 -0
- data/spec/blather/stanza/message_spec.rb +132 -0
- data/spec/blather/stanza/presence/status_spec.rb +132 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
- data/spec/blather/stanza/presence_spec.rb +66 -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 +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 +67 -0
- data/spec/blather/stanza_spec.rb +116 -0
- data/spec/blather/stream/client_spec.rb +1011 -0
- data/spec/blather/stream/component_spec.rb +95 -0
- data/spec/blather/stream/parser_spec.rb +145 -0
- data/spec/blather/xmpp_node_spec.rb +231 -0
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +43 -0
- metadata +249 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
|
|
3
|
+
# Base XML Node
|
|
4
|
+
# All XML classes subclass XMPPNode it allows the addition of helpers
|
|
5
|
+
class XMPPNode < Nokogiri::XML::Node
|
|
6
|
+
# @private
|
|
7
|
+
BASE_NAMES = %w[presence message iq].freeze
|
|
8
|
+
|
|
9
|
+
# @private
|
|
10
|
+
@@registrations = {}
|
|
11
|
+
|
|
12
|
+
class_inheritable_accessor :registered_ns,
|
|
13
|
+
:registered_name
|
|
14
|
+
|
|
15
|
+
# Register a new stanza class to a name and/or namespace
|
|
16
|
+
#
|
|
17
|
+
# This registers a namespace that is used when looking
|
|
18
|
+
# up the class name of the object to instantiate when a new
|
|
19
|
+
# stanza is received
|
|
20
|
+
#
|
|
21
|
+
# @param [#to_s] name the name of the node
|
|
22
|
+
# @param [String, nil] ns the namespace the node belongs to
|
|
23
|
+
def self.register(name, ns = nil)
|
|
24
|
+
self.registered_name = name.to_s
|
|
25
|
+
self.registered_ns = ns
|
|
26
|
+
@@registrations[[self.registered_name, self.registered_ns]] = self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Find the class to use given the name and namespace of a stanza
|
|
30
|
+
#
|
|
31
|
+
# @param [#to_s] name the name to lookup
|
|
32
|
+
# @param [String, nil] xmlns the namespace the node belongs to
|
|
33
|
+
# @return [Class, nil] the class appropriate for the name/ns combination
|
|
34
|
+
def self.class_from_registration(name, ns = nil)
|
|
35
|
+
name = name.to_s
|
|
36
|
+
@@registrations[[name, ns]] || @@registrations[[name, nil]]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Import an XML::Node to the appropriate class
|
|
40
|
+
#
|
|
41
|
+
# Looks up the class the node should be then creates it based on the
|
|
42
|
+
# elements of the XML::Node
|
|
43
|
+
# @param [XML::Node] node the node to import
|
|
44
|
+
# @return the appropriate object based on the node name and namespace
|
|
45
|
+
def self.import(node)
|
|
46
|
+
ns = (node.namespace.href if node.namespace)
|
|
47
|
+
klass = class_from_registration(node.element_name, ns)
|
|
48
|
+
if klass && klass != self
|
|
49
|
+
klass.import(node)
|
|
50
|
+
else
|
|
51
|
+
new(node.element_name).inherit(node)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Create a new Node object
|
|
56
|
+
#
|
|
57
|
+
# @param [String, nil] name the element name
|
|
58
|
+
# @param [XML::Document, nil] doc the document to attach the node to. If
|
|
59
|
+
# not provided one will be created
|
|
60
|
+
# @return a new object with the registered name and namespace
|
|
61
|
+
def self.new(name = nil, doc = nil)
|
|
62
|
+
name ||= self.registered_name
|
|
63
|
+
|
|
64
|
+
node = super name.to_s, (doc || Nokogiri::XML::Document.new)
|
|
65
|
+
node.document.root = node unless doc
|
|
66
|
+
node.namespace = self.registered_ns unless BASE_NAMES.include?(name.to_s)
|
|
67
|
+
node
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Helper method to read an attribute
|
|
71
|
+
#
|
|
72
|
+
# @param [#to_sym] attr_name the name of the attribute
|
|
73
|
+
# @param [String, Symbol, nil] to_call the name of the method to call on
|
|
74
|
+
# the returned value
|
|
75
|
+
# @return nil or the value
|
|
76
|
+
def read_attr(attr_name, to_call = nil)
|
|
77
|
+
val = self[attr_name.to_sym]
|
|
78
|
+
val && to_call ? val.__send__(to_call) : val
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Helper method to write a value to an attribute
|
|
82
|
+
#
|
|
83
|
+
# @param [#to_sym] attr_name the name of the attribute
|
|
84
|
+
# @param [#to_s] value the value to set the attribute to
|
|
85
|
+
def write_attr(attr_name, value)
|
|
86
|
+
self[attr_name.to_sym] = value
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Helper method to read the content of a node
|
|
90
|
+
#
|
|
91
|
+
# @param [#to_sym] node the name of the node
|
|
92
|
+
# @param [String, Symbol, nil] to_call the name of the method to call on
|
|
93
|
+
# the returned value
|
|
94
|
+
# @return nil or the value
|
|
95
|
+
def read_content(node, to_call = nil)
|
|
96
|
+
val = content_from node.to_sym
|
|
97
|
+
val && to_call ? val.__send__(to_call) : val
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Turn the object into a proper stanza
|
|
101
|
+
#
|
|
102
|
+
# @return a stanza object
|
|
103
|
+
def to_stanza
|
|
104
|
+
self.class.import self
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# @private
|
|
108
|
+
alias_method :nokogiri_namespace=, :namespace=
|
|
109
|
+
# Attach a namespace to the node
|
|
110
|
+
#
|
|
111
|
+
# @overload namespace=(ns)
|
|
112
|
+
# Attach an already created XML::Namespace
|
|
113
|
+
# @param [XML::Namespace] ns the namespace object
|
|
114
|
+
# @overload namespace=(ns)
|
|
115
|
+
# Create a new namespace and attach it
|
|
116
|
+
# @param [String] ns the namespace uri
|
|
117
|
+
# @overload namespace=(namespaces)
|
|
118
|
+
# Createa and add new namespaces from a hash
|
|
119
|
+
# @param [Hash] namespaces a hash of prefix => uri pairs
|
|
120
|
+
def namespace=(namespaces)
|
|
121
|
+
case namespaces
|
|
122
|
+
when Nokogiri::XML::Namespace
|
|
123
|
+
self.nokogiri_namespace = namespaces
|
|
124
|
+
when String
|
|
125
|
+
self.add_namespace nil, namespaces
|
|
126
|
+
when Hash
|
|
127
|
+
if ns = namespaces.delete(nil)
|
|
128
|
+
self.add_namespace nil, ns
|
|
129
|
+
end
|
|
130
|
+
namespaces.each do |p, n|
|
|
131
|
+
ns = self.add_namespace p, n
|
|
132
|
+
self.nokogiri_namespace = ns
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Helper method to get the node's namespace
|
|
138
|
+
#
|
|
139
|
+
# @return [XML::Namespace, nil] The node's namespace object if it exists
|
|
140
|
+
def namespace_href
|
|
141
|
+
namespace.href if namespace
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Remove a child with the name and (optionally) namespace given
|
|
145
|
+
#
|
|
146
|
+
# @param [String] name the name or xpath of the node to remove
|
|
147
|
+
# @param [String, nil] ns the namespace the node is in
|
|
148
|
+
def remove_child(name, ns = nil)
|
|
149
|
+
child = xpath(name, ns).first
|
|
150
|
+
child.remove if child
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Remove all children with a given name regardless of namespace
|
|
154
|
+
#
|
|
155
|
+
# @param [String] name the name of the nodes to remove
|
|
156
|
+
def remove_children(name)
|
|
157
|
+
xpath("./*[local-name()='#{name}']").remove
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# The content of the named node
|
|
161
|
+
#
|
|
162
|
+
# @param [String] name the name or xpath of the node
|
|
163
|
+
# @param [String, nil] ns the namespace the node is in
|
|
164
|
+
# @return [String, nil] the content of the node
|
|
165
|
+
def content_from(name, ns = nil)
|
|
166
|
+
child = xpath(name, ns).first
|
|
167
|
+
child.content if child
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Sets the content for the specified node.
|
|
171
|
+
# If the node exists it is updated. If not a new node is created
|
|
172
|
+
# If the node exists and the content is nil, the node will be removed
|
|
173
|
+
# entirely
|
|
174
|
+
#
|
|
175
|
+
# @param [String] node the name of the node to update/create
|
|
176
|
+
# @param [String, nil] content the content to set within the node
|
|
177
|
+
def set_content_for(node, content = nil)
|
|
178
|
+
if content
|
|
179
|
+
child = xpath(node).first
|
|
180
|
+
self << (child = XMPPNode.new(node, self.document)) unless child
|
|
181
|
+
child.content = content
|
|
182
|
+
else
|
|
183
|
+
remove_child node
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
alias_method :copy, :dup
|
|
188
|
+
|
|
189
|
+
# Inherit the attributes and children of an XML::Node
|
|
190
|
+
#
|
|
191
|
+
# @param [XML::Node] stanza the node to inherit
|
|
192
|
+
# @return [self]
|
|
193
|
+
def inherit(stanza)
|
|
194
|
+
set_namespace stanza.namespace if stanza.namespace
|
|
195
|
+
inherit_attrs stanza.attributes
|
|
196
|
+
stanza.children.each do |c|
|
|
197
|
+
self << (n = c.dup)
|
|
198
|
+
ns = n.namespace_definitions.find { |ns| ns.prefix == c.namespace.prefix }
|
|
199
|
+
n.namespace = ns if ns
|
|
200
|
+
end
|
|
201
|
+
self
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Inherit a set of attributes
|
|
205
|
+
#
|
|
206
|
+
# @param [Hash] attrs a hash of attributes to set on the node
|
|
207
|
+
# @return [self]
|
|
208
|
+
def inherit_attrs(attrs)
|
|
209
|
+
attrs.each { |name, value| self[name] = value }
|
|
210
|
+
self
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def inspect
|
|
214
|
+
self.to_xml
|
|
215
|
+
end
|
|
216
|
+
end # XMPPNode
|
|
217
|
+
|
|
218
|
+
end # Blather
|
data/lib/blather.rb
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Require the necessary files
|
|
2
|
+
%w[
|
|
3
|
+
rubygems
|
|
4
|
+
eventmachine
|
|
5
|
+
nokogiri
|
|
6
|
+
digest/md5
|
|
7
|
+
logger
|
|
8
|
+
active_support/core_ext/class/inheritable_attributes
|
|
9
|
+
active_support/core_ext/object/blank
|
|
10
|
+
|
|
11
|
+
blather/core_ext/nokogiri
|
|
12
|
+
|
|
13
|
+
blather/errors
|
|
14
|
+
blather/errors/sasl_error
|
|
15
|
+
blather/errors/stanza_error
|
|
16
|
+
blather/errors/stream_error
|
|
17
|
+
blather/jid
|
|
18
|
+
blather/roster
|
|
19
|
+
blather/roster_item
|
|
20
|
+
blather/xmpp_node
|
|
21
|
+
|
|
22
|
+
blather/stanza
|
|
23
|
+
blather/stanza/iq
|
|
24
|
+
blather/stanza/iq/query
|
|
25
|
+
blather/stanza/iq/roster
|
|
26
|
+
blather/stanza/disco
|
|
27
|
+
blather/stanza/disco/disco_info
|
|
28
|
+
blather/stanza/disco/disco_items
|
|
29
|
+
blather/stanza/message
|
|
30
|
+
blather/stanza/presence
|
|
31
|
+
blather/stanza/presence/status
|
|
32
|
+
blather/stanza/presence/subscription
|
|
33
|
+
|
|
34
|
+
blather/stanza/pubsub
|
|
35
|
+
blather/stanza/pubsub/affiliations
|
|
36
|
+
blather/stanza/pubsub/create
|
|
37
|
+
blather/stanza/pubsub/event
|
|
38
|
+
blather/stanza/pubsub/items
|
|
39
|
+
blather/stanza/pubsub/publish
|
|
40
|
+
blather/stanza/pubsub/retract
|
|
41
|
+
blather/stanza/pubsub/subscribe
|
|
42
|
+
blather/stanza/pubsub/subscription
|
|
43
|
+
blather/stanza/pubsub/subscriptions
|
|
44
|
+
blather/stanza/pubsub/unsubscribe
|
|
45
|
+
|
|
46
|
+
blather/stanza/pubsub_owner
|
|
47
|
+
blather/stanza/pubsub_owner/delete
|
|
48
|
+
blather/stanza/pubsub_owner/purge
|
|
49
|
+
|
|
50
|
+
blather/stream
|
|
51
|
+
blather/stream/client
|
|
52
|
+
blather/stream/component
|
|
53
|
+
blather/stream/parser
|
|
54
|
+
blather/stream/features
|
|
55
|
+
blather/stream/features/resource
|
|
56
|
+
blather/stream/features/sasl
|
|
57
|
+
blather/stream/features/session
|
|
58
|
+
blather/stream/features/tls
|
|
59
|
+
].each { |r| require r }
|
|
60
|
+
|
|
61
|
+
module Blather
|
|
62
|
+
# @private
|
|
63
|
+
@@logger = nil
|
|
64
|
+
|
|
65
|
+
# Get or create an instance of Logger
|
|
66
|
+
def self.logger
|
|
67
|
+
unless @@logger
|
|
68
|
+
self.logger = Logger.new($stdout)
|
|
69
|
+
self.logger.level = Logger::INFO
|
|
70
|
+
end
|
|
71
|
+
@@logger
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Set the Logger
|
|
75
|
+
def self.logger=(logger)
|
|
76
|
+
@@logger = logger
|
|
77
|
+
end
|
|
78
|
+
end
|