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,68 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class PubSub
|
|
4
|
+
|
|
5
|
+
# # PubSub Unsubscribe Stanza
|
|
6
|
+
#
|
|
7
|
+
# [XEP-0060 Section 6.2 - Unsubscribe from a Node](http://xmpp.org/extensions/xep-0060.html#subscriber-unsubscribe)
|
|
8
|
+
#
|
|
9
|
+
# @handler :pubsub_unsubscribe
|
|
10
|
+
class Unsubscribe < PubSub
|
|
11
|
+
register :pubsub_unsubscribe, :unsubscribe, self.registered_ns
|
|
12
|
+
|
|
13
|
+
# Create a new unsubscribe node
|
|
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 node to unsubscribe from
|
|
18
|
+
# @param [Blather::JID, #to_s] jid the JID of the unsubscription
|
|
19
|
+
def self.new(type = :set, host = nil, node = nil, jid = nil)
|
|
20
|
+
new_node = super(type, host)
|
|
21
|
+
new_node.node = node
|
|
22
|
+
new_node.jid = jid
|
|
23
|
+
new_node
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Get the JID of the unsubscription
|
|
27
|
+
#
|
|
28
|
+
# @return [Blather::JID]
|
|
29
|
+
def jid
|
|
30
|
+
JID.new(unsubscribe[:jid])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set the JID of the unsubscription
|
|
34
|
+
#
|
|
35
|
+
# @param [Blather::JID, #to_s] jid
|
|
36
|
+
def jid=(jid)
|
|
37
|
+
unsubscribe[:jid] = jid
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Get the name of the node to unsubscribe from
|
|
41
|
+
#
|
|
42
|
+
# @return [String]
|
|
43
|
+
def node
|
|
44
|
+
unsubscribe[:node]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Set the name of the node to unsubscribe from
|
|
48
|
+
#
|
|
49
|
+
# @param [String] node
|
|
50
|
+
def node=(node)
|
|
51
|
+
unsubscribe[:node] = node
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Get or create the actual unsubscribe node
|
|
55
|
+
#
|
|
56
|
+
# @return [Blather::XMPPNode]
|
|
57
|
+
def unsubscribe
|
|
58
|
+
unless unsubscribe = pubsub.find_first('ns:unsubscribe', :ns => self.class.registered_ns)
|
|
59
|
+
self.pubsub << (unsubscribe = XMPPNode.new('unsubscribe', self.document))
|
|
60
|
+
unsubscribe.namespace = self.pubsub.namespace
|
|
61
|
+
end
|
|
62
|
+
unsubscribe
|
|
63
|
+
end
|
|
64
|
+
end # Unsubscribe
|
|
65
|
+
|
|
66
|
+
end # PubSub
|
|
67
|
+
end # Stanza
|
|
68
|
+
end # Blather
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
|
|
4
|
+
# # Pubsub Stanza
|
|
5
|
+
#
|
|
6
|
+
# [XEP-0060 - Publish-Subscribe](http://xmpp.org/extensions/xep-0060.html)
|
|
7
|
+
#
|
|
8
|
+
# The base class for all PubSub nodes. This provides helper methods common to
|
|
9
|
+
# all PubSub nodes.
|
|
10
|
+
#
|
|
11
|
+
# @handler :pubsub_node
|
|
12
|
+
class PubSub < Iq
|
|
13
|
+
register :pubsub_node, :pubsub, 'http://jabber.org/protocol/pubsub'
|
|
14
|
+
|
|
15
|
+
# @private
|
|
16
|
+
def self.import(node)
|
|
17
|
+
klass = nil
|
|
18
|
+
if pubsub = node.document.find_first('//ns:pubsub', :ns => self.registered_ns)
|
|
19
|
+
pubsub.children.detect do |e|
|
|
20
|
+
ns = e.namespace ? e.namespace.href : nil
|
|
21
|
+
klass = class_from_registration(e.element_name, ns)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
(klass || self).new(node[:type]).inherit(node)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Overwrites the parent constructor to ensure a pubsub node is present.
|
|
28
|
+
# Also allows the addition of a host attribute
|
|
29
|
+
#
|
|
30
|
+
# @param [<Blather::Stanza::Iq::VALID_TYPES>] type the IQ type
|
|
31
|
+
# @param [String, nil] host the host the node should be sent to
|
|
32
|
+
def self.new(type = nil, host = nil)
|
|
33
|
+
new_node = super type
|
|
34
|
+
new_node.to = host
|
|
35
|
+
new_node.pubsub
|
|
36
|
+
new_node
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Overrides the parent to ensure the current pubsub node is destroyed before
|
|
40
|
+
# inheritting the new content
|
|
41
|
+
#
|
|
42
|
+
# @private
|
|
43
|
+
def inherit(node)
|
|
44
|
+
remove_children :pubsub
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Get or create the pubsub node on the stanza
|
|
49
|
+
#
|
|
50
|
+
# @return [Blather::XMPPNode]
|
|
51
|
+
def pubsub
|
|
52
|
+
p = find_first('ns:pubsub', :ns => self.class.registered_ns) ||
|
|
53
|
+
find_first('pubsub', :ns => self.class.registered_ns)
|
|
54
|
+
|
|
55
|
+
unless p
|
|
56
|
+
self << (p = XMPPNode.new('pubsub', self.document))
|
|
57
|
+
p.namespace = self.class.registered_ns
|
|
58
|
+
end
|
|
59
|
+
p
|
|
60
|
+
end
|
|
61
|
+
end # PubSub
|
|
62
|
+
|
|
63
|
+
# # PubSubItem Fragment
|
|
64
|
+
#
|
|
65
|
+
# This fragment is found in many places throughout the pubsub spec
|
|
66
|
+
# This is a convenience class to attach methods to the node
|
|
67
|
+
class PubSubItem < XMPPNode
|
|
68
|
+
ATOM_NS = 'http://www.w3.org/2005/Atom'.freeze
|
|
69
|
+
|
|
70
|
+
# Create a new PubSubItem
|
|
71
|
+
#
|
|
72
|
+
# @param [String, nil] id the id of the stanza
|
|
73
|
+
# @param [#to_s, nil] payload the payload to attach to this item.
|
|
74
|
+
# @param [XML::Document, nil] document the document the node should be
|
|
75
|
+
# attached to. This should be the document of the parent PubSub node.
|
|
76
|
+
def self.new(id = nil, payload = nil, document = nil)
|
|
77
|
+
new_node = super 'item', document
|
|
78
|
+
new_node.id = id
|
|
79
|
+
new_node.payload = payload if payload
|
|
80
|
+
new_node
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Get the item's ID
|
|
84
|
+
#
|
|
85
|
+
# @return [String, nil]
|
|
86
|
+
def id
|
|
87
|
+
read_attr :id
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Set the item's ID
|
|
91
|
+
#
|
|
92
|
+
# @param [#to_s] id the new ID
|
|
93
|
+
def id=(id)
|
|
94
|
+
write_attr :id, id
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Get the item's payload
|
|
98
|
+
#
|
|
99
|
+
# To get the XML representation use #entry
|
|
100
|
+
#
|
|
101
|
+
# @return [String, nil]
|
|
102
|
+
def payload
|
|
103
|
+
self.entry.content.empty? ? nil : content
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Set the item's payload
|
|
107
|
+
#
|
|
108
|
+
# @param [String, nil] payload the payload
|
|
109
|
+
def payload=(payload)
|
|
110
|
+
self.entry.content = payload
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Get or create the entry node
|
|
114
|
+
#
|
|
115
|
+
# @return [Blather::XMPPNode]
|
|
116
|
+
def entry
|
|
117
|
+
e = find_first('ns:entry', :ns => ATOM_NS) ||
|
|
118
|
+
find_first('entry', :ns => ATOM_NS)
|
|
119
|
+
|
|
120
|
+
unless e
|
|
121
|
+
self << (e = XMPPNode.new('entry', self.document))
|
|
122
|
+
e.namespace = ATOM_NS
|
|
123
|
+
end
|
|
124
|
+
e
|
|
125
|
+
end
|
|
126
|
+
end # PubSubItem
|
|
127
|
+
|
|
128
|
+
end # Stanza
|
|
129
|
+
end # Blather
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class PubSubOwner
|
|
4
|
+
|
|
5
|
+
# # PubSubOwner Delete Stanza
|
|
6
|
+
#
|
|
7
|
+
# [XEP-0060 Section 8.4 Delete a Node](http://xmpp.org/extensions/xep-0060.html#owner-delete)
|
|
8
|
+
#
|
|
9
|
+
# @handler :pubsub_delete
|
|
10
|
+
class Delete < PubSubOwner
|
|
11
|
+
register :pubsub_delete, :delete, self.registered_ns
|
|
12
|
+
|
|
13
|
+
# Create a new delete 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 delete
|
|
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
|
+
delete_node[:node]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Set the name of the node to delete
|
|
32
|
+
#
|
|
33
|
+
# @param [String] node
|
|
34
|
+
def node=(node)
|
|
35
|
+
delete_node[:node] = node
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Get or create the actual delete node on the stanza
|
|
39
|
+
#
|
|
40
|
+
# @return [Blather::XMPPNode]
|
|
41
|
+
def delete_node
|
|
42
|
+
unless delete_node = pubsub.find_first('ns:delete', :ns => self.class.registered_ns)
|
|
43
|
+
self.pubsub << (delete_node = XMPPNode.new('delete', self.document))
|
|
44
|
+
delete_node.namespace = self.pubsub.namespace
|
|
45
|
+
end
|
|
46
|
+
delete_node
|
|
47
|
+
end
|
|
48
|
+
end # Retract
|
|
49
|
+
|
|
50
|
+
end # PubSub
|
|
51
|
+
end # Stanza
|
|
52
|
+
end # Blather
|
|
@@ -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,51 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
|
|
4
|
+
# # PubSubOwner Base Class
|
|
5
|
+
#
|
|
6
|
+
# [XEP-0060 - Publish-Subscribe](http://xmpp.org/extensions/xep-0060.html)
|
|
7
|
+
#
|
|
8
|
+
# @handler :pubsub_owner
|
|
9
|
+
class PubSubOwner < Iq
|
|
10
|
+
register :pubsub_owner, :pubsub, 'http://jabber.org/protocol/pubsub#owner'
|
|
11
|
+
|
|
12
|
+
# Creates the proper class from the stana's child
|
|
13
|
+
# @private
|
|
14
|
+
def self.import(node)
|
|
15
|
+
klass = nil
|
|
16
|
+
if pubsub = node.document.find_first('//ns:pubsub', :ns => self.registered_ns)
|
|
17
|
+
pubsub.children.each { |e| break if klass = class_from_registration(e.element_name, (e.namespace.href if e.namespace)) }
|
|
18
|
+
end
|
|
19
|
+
(klass || self).new(node[:type]).inherit(node)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Overrides the parent to ensure a pubsub node is created
|
|
23
|
+
# @private
|
|
24
|
+
def self.new(type = nil, host = nil)
|
|
25
|
+
new_node = super type
|
|
26
|
+
new_node.to = host
|
|
27
|
+
new_node.pubsub
|
|
28
|
+
new_node
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Overrides the parent to ensure the pubsub node is destroyed
|
|
32
|
+
# @private
|
|
33
|
+
def inherit(node)
|
|
34
|
+
remove_children :pubsub
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Get or create the pubsub node on the stanza
|
|
39
|
+
#
|
|
40
|
+
# @return [Blather::XMPPNode]
|
|
41
|
+
def pubsub
|
|
42
|
+
unless p = find_first('ns:pubsub', :ns => self.class.registered_ns)
|
|
43
|
+
self << (p = XMPPNode.new('pubsub', self.document))
|
|
44
|
+
p.namespace = self.class.registered_ns
|
|
45
|
+
end
|
|
46
|
+
p
|
|
47
|
+
end
|
|
48
|
+
end # PubSubOwner
|
|
49
|
+
|
|
50
|
+
end # Stanza
|
|
51
|
+
end # Blather
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
|
|
3
|
+
# # Base XMPP Stanza
|
|
4
|
+
#
|
|
5
|
+
# All stanzas inherit this class. It provides a set of methods and helpers
|
|
6
|
+
# common to all XMPP Stanzas
|
|
7
|
+
#
|
|
8
|
+
# @handler :stanza
|
|
9
|
+
class Stanza < XMPPNode
|
|
10
|
+
# @private
|
|
11
|
+
@@last_id = 0
|
|
12
|
+
# @private
|
|
13
|
+
@@handler_list = []
|
|
14
|
+
|
|
15
|
+
class_inheritable_array :handler_hierarchy
|
|
16
|
+
|
|
17
|
+
# Registers a callback onto the callback stack
|
|
18
|
+
#
|
|
19
|
+
# @param [Symbol] handler the name of the handler
|
|
20
|
+
# @param [Symbol, String, nil] name the name of the first element in the
|
|
21
|
+
# stanza. If nil the inherited name will be used. If that's nil the
|
|
22
|
+
# handler name will be used.
|
|
23
|
+
# @param [String, nil] ns the namespace of the stanza
|
|
24
|
+
def self.register(handler, name = nil, ns = nil)
|
|
25
|
+
@@handler_list << handler
|
|
26
|
+
self.handler_hierarchy ||= [:stanza]
|
|
27
|
+
self.handler_hierarchy.unshift handler
|
|
28
|
+
|
|
29
|
+
name = name || self.registered_name || handler
|
|
30
|
+
super name, ns
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The handler stack for the current stanza class
|
|
34
|
+
#
|
|
35
|
+
# @return [Array<Symbol>]
|
|
36
|
+
def self.handler_list
|
|
37
|
+
@@handler_list
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Helper method that creates a unique ID for stanzas
|
|
41
|
+
#
|
|
42
|
+
# @return [String] a new unique ID
|
|
43
|
+
def self.next_id
|
|
44
|
+
@@last_id += 1
|
|
45
|
+
'blather%04x' % @@last_id
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Check if the stanza is an error stanza
|
|
49
|
+
#
|
|
50
|
+
# @return [true, false]
|
|
51
|
+
def error?
|
|
52
|
+
self.type == :error
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Creates a copy with to and from swapped
|
|
56
|
+
#
|
|
57
|
+
# @return [Blather::Stanza]
|
|
58
|
+
def reply
|
|
59
|
+
self.dup.reply!
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Swaps from and to
|
|
63
|
+
#
|
|
64
|
+
# @return [self]
|
|
65
|
+
def reply!
|
|
66
|
+
self.to, self.from = self.from, self.to
|
|
67
|
+
self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Get the stanza's ID
|
|
71
|
+
#
|
|
72
|
+
# @return [String, nil]
|
|
73
|
+
def id
|
|
74
|
+
read_attr :id
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Set the stanza's ID
|
|
78
|
+
#
|
|
79
|
+
# @param [#to_s] id the new stanza ID
|
|
80
|
+
def id=(id)
|
|
81
|
+
write_attr :id, id
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Get the stanza's to
|
|
85
|
+
#
|
|
86
|
+
# @return [Blather::JID, nil]
|
|
87
|
+
def to
|
|
88
|
+
JID.new(self[:to]) if self[:to]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Set the stanza's to field
|
|
92
|
+
#
|
|
93
|
+
# @param [#to_s] to the new JID for the to field
|
|
94
|
+
def to=(to)
|
|
95
|
+
write_attr :to, to
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Get the stanza's from
|
|
99
|
+
#
|
|
100
|
+
# @return [Blather::JID, nil]
|
|
101
|
+
def from
|
|
102
|
+
JID.new(self[:from]) if self[:from]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Set the stanza's from field
|
|
106
|
+
#
|
|
107
|
+
# @param [#to_s] from the new JID for the from field
|
|
108
|
+
def from=(from)
|
|
109
|
+
write_attr :from, from
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Get the stanza's type
|
|
113
|
+
#
|
|
114
|
+
# @return [Symbol, nil]
|
|
115
|
+
def type
|
|
116
|
+
read_attr :type, :to_sym
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Set the stanza's type
|
|
120
|
+
#
|
|
121
|
+
# @param [#to_s] type the new stanza type
|
|
122
|
+
def type=(type)
|
|
123
|
+
write_attr :type, type
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Create an error stanza from the current stanza
|
|
127
|
+
#
|
|
128
|
+
# @param [String] name the error name
|
|
129
|
+
# @param [<Blather::StanzaError::VALID_TYPES>] type the error type
|
|
130
|
+
# @param [String, nil] text the error text
|
|
131
|
+
# @param [Array<XML::Node>] extras an array of extra nodes to attach to
|
|
132
|
+
# the error
|
|
133
|
+
#
|
|
134
|
+
# @return [Blather::StanzaError]
|
|
135
|
+
def as_error(name, type, text = nil, extras = [])
|
|
136
|
+
StanzaError.new self, name, type, text, extras
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
protected
|
|
140
|
+
# @private
|
|
141
|
+
def reply_if_needed!
|
|
142
|
+
unless @reversed_endpoints
|
|
143
|
+
reply!
|
|
144
|
+
@reversed_endpoints = true
|
|
145
|
+
end
|
|
146
|
+
self
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stream
|
|
3
|
+
|
|
4
|
+
class Client < Stream
|
|
5
|
+
LANG = 'en'
|
|
6
|
+
VERSION = '1.0'
|
|
7
|
+
NAMESPACE = 'jabber:client'
|
|
8
|
+
|
|
9
|
+
def start
|
|
10
|
+
@parser = Parser.new self
|
|
11
|
+
start_stream = <<-STREAM
|
|
12
|
+
<stream:stream
|
|
13
|
+
to='#{@to}'
|
|
14
|
+
xmlns='#{NAMESPACE}'
|
|
15
|
+
xmlns:stream='#{STREAM_NS}'
|
|
16
|
+
version='#{VERSION}'
|
|
17
|
+
xml:lang='#{LANG}'
|
|
18
|
+
>
|
|
19
|
+
STREAM
|
|
20
|
+
send start_stream.gsub(/\s+/, ' ')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def send(stanza)
|
|
24
|
+
stanza.from = self.jid if stanza.is_a?(Stanza) && !stanza.from.nil?
|
|
25
|
+
super stanza
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end #Client
|
|
29
|
+
|
|
30
|
+
end #Stream
|
|
31
|
+
end #Blather
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stream
|
|
3
|
+
|
|
4
|
+
class Component < Stream
|
|
5
|
+
NAMESPACE = 'jabber:component:accept'
|
|
6
|
+
|
|
7
|
+
def receive(node) # :nodoc:
|
|
8
|
+
if node.element_name == 'handshake'
|
|
9
|
+
ready!
|
|
10
|
+
else
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if node.document.find_first('/stream:stream[not(stream:error)]', :xmlns => NAMESPACE, :stream => STREAM_NS)
|
|
15
|
+
send("<handshake>#{Digest::SHA1.hexdigest(@node['id']+@password)}</handshake>")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def send(stanza)
|
|
20
|
+
stanza.from ||= self.jid if stanza.respond_to?(:from) && stanza.respond_to?(:from=)
|
|
21
|
+
super stanza
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def start
|
|
25
|
+
@parser = Parser.new self
|
|
26
|
+
start_stream = <<-STREAM
|
|
27
|
+
<stream:stream
|
|
28
|
+
to='#{@jid}'
|
|
29
|
+
xmlns='#{NAMESPACE}'
|
|
30
|
+
xmlns:stream='#{STREAM_NS}'
|
|
31
|
+
>
|
|
32
|
+
STREAM
|
|
33
|
+
send start_stream.gsub(/\s+/, ' ')
|
|
34
|
+
end
|
|
35
|
+
end #Client
|
|
36
|
+
|
|
37
|
+
end #Stream
|
|
38
|
+
end #Blather
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Blather # :nodoc:
|
|
2
|
+
class Stream # :nodoc:
|
|
3
|
+
|
|
4
|
+
class Resource < Features # :nodoc:
|
|
5
|
+
BIND_NS = 'urn:ietf:params:xml:ns:xmpp-bind'.freeze
|
|
6
|
+
register BIND_NS
|
|
7
|
+
|
|
8
|
+
def initialize(stream, succeed, fail)
|
|
9
|
+
super
|
|
10
|
+
@jid = stream.jid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def receive_data(stanza)
|
|
14
|
+
@node = stanza
|
|
15
|
+
case stanza.element_name
|
|
16
|
+
when 'bind' then bind
|
|
17
|
+
when 'iq' then result
|
|
18
|
+
else fail!(UnknownResponse.new(@node))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
##
|
|
24
|
+
# Respond to the bind request
|
|
25
|
+
# If @jid has a resource set already request it from the server
|
|
26
|
+
def bind
|
|
27
|
+
response = Stanza::Iq.new :set
|
|
28
|
+
@id = response.id
|
|
29
|
+
|
|
30
|
+
response << (binder = XMPPNode.new('bind', response.document))
|
|
31
|
+
binder.namespace = BIND_NS
|
|
32
|
+
|
|
33
|
+
if @jid.resource
|
|
34
|
+
binder << (resource = XMPPNode.new('resource', binder.document))
|
|
35
|
+
resource.content = @jid.resource
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
@stream.send response
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Process the result from the server
|
|
43
|
+
# Sets the sends the JID (now bound to a resource)
|
|
44
|
+
# back to the stream
|
|
45
|
+
def result
|
|
46
|
+
if @node[:type] == 'error'
|
|
47
|
+
fail! StanzaError.import(@node)
|
|
48
|
+
return
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
Blather.logger.debug "RESOURCE NODE #{@node}"
|
|
52
|
+
# ensure this is a response to our original request
|
|
53
|
+
if @id == @node['id']
|
|
54
|
+
@stream.jid = JID.new @node.find_first('bind_ns:bind/bind_ns:jid', :bind_ns => BIND_NS).content
|
|
55
|
+
succeed!
|
|
56
|
+
else
|
|
57
|
+
fail!("BIND result ID mismatch. Expected: #{@id}. Received: #{@node['id']}")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end #Resource
|
|
61
|
+
|
|
62
|
+
end #Stream
|
|
63
|
+
end #Blather
|