shingara-blather 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|