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.
Files changed (110) hide show
  1. data/LICENSE +1 -1
  2. data/README.rdoc +41 -12
  3. data/examples/echo.rb +1 -1
  4. data/examples/execute.rb +0 -5
  5. data/examples/pubsub/cli.rb +64 -0
  6. data/examples/pubsub/ping_pong.rb +18 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/xmpp4r/echo.rb +35 -0
  9. data/lib/blather/client/client.rb +19 -13
  10. data/lib/blather/client/dsl/pubsub.rb +133 -0
  11. data/lib/blather/client/dsl.rb +16 -0
  12. data/lib/blather/client.rb +1 -1
  13. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
  14. data/lib/blather/core_ext/active_support.rb +1 -117
  15. data/lib/blather/core_ext/nokogiri.rb +35 -0
  16. data/lib/blather/errors/sasl_error.rb +3 -1
  17. data/lib/blather/errors/stanza_error.rb +10 -17
  18. data/lib/blather/errors/stream_error.rb +11 -14
  19. data/lib/blather/errors.rb +3 -20
  20. data/lib/blather/jid.rb +1 -0
  21. data/lib/blather/roster.rb +9 -0
  22. data/lib/blather/roster_item.rb +6 -1
  23. data/lib/blather/stanza/disco/disco_info.rb +45 -33
  24. data/lib/blather/stanza/disco/disco_items.rb +32 -21
  25. data/lib/blather/stanza/disco.rb +7 -1
  26. data/lib/blather/stanza/iq/query.rb +16 -8
  27. data/lib/blather/stanza/iq/roster.rb +33 -22
  28. data/lib/blather/stanza/iq.rb +13 -8
  29. data/lib/blather/stanza/message.rb +20 -31
  30. data/lib/blather/stanza/presence/status.rb +13 -21
  31. data/lib/blather/stanza/presence/subscription.rb +11 -16
  32. data/lib/blather/stanza/presence.rb +3 -5
  33. data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
  34. data/lib/blather/stanza/pubsub/create.rb +43 -0
  35. data/lib/blather/stanza/pubsub/errors.rb +9 -0
  36. data/lib/blather/stanza/pubsub/event.rb +77 -0
  37. data/lib/blather/stanza/pubsub/items.rb +63 -0
  38. data/lib/blather/stanza/pubsub/publish.rb +58 -0
  39. data/lib/blather/stanza/pubsub/retract.rb +53 -0
  40. data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
  41. data/lib/blather/stanza/pubsub/subscription.rb +66 -0
  42. data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
  43. data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
  44. data/lib/blather/stanza/pubsub.rb +63 -0
  45. data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
  46. data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
  47. data/lib/blather/stanza/pubsub_owner.rb +41 -0
  48. data/lib/blather/stanza.rb +35 -18
  49. data/lib/blather/stream/client.rb +1 -2
  50. data/lib/blather/stream/component.rb +9 -5
  51. data/lib/blather/stream/features/resource.rb +63 -0
  52. data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
  53. data/lib/blather/stream/features/session.rb +44 -0
  54. data/lib/blather/stream/features/tls.rb +28 -0
  55. data/lib/blather/stream/features.rb +53 -0
  56. data/lib/blather/stream/parser.rb +70 -46
  57. data/lib/blather/stream.rb +76 -168
  58. data/lib/blather/xmpp_node.rb +113 -52
  59. data/lib/blather.rb +35 -12
  60. data/spec/blather/client/client_spec.rb +44 -58
  61. data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
  62. data/spec/blather/client/dsl_spec.rb +19 -6
  63. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  64. data/spec/blather/errors/sasl_error_spec.rb +8 -8
  65. data/spec/blather/errors/stanza_error_spec.rb +25 -33
  66. data/spec/blather/errors/stream_error_spec.rb +21 -16
  67. data/spec/blather/errors_spec.rb +4 -11
  68. data/spec/blather/jid_spec.rb +31 -30
  69. data/spec/blather/roster_item_spec.rb +34 -23
  70. data/spec/blather/roster_spec.rb +27 -12
  71. data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
  72. data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
  73. data/spec/blather/stanza/iq/query_spec.rb +34 -11
  74. data/spec/blather/stanza/iq/roster_spec.rb +47 -30
  75. data/spec/blather/stanza/iq_spec.rb +19 -14
  76. data/spec/blather/stanza/message_spec.rb +30 -17
  77. data/spec/blather/stanza/presence/status_spec.rb +43 -20
  78. data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
  79. data/spec/blather/stanza/presence_spec.rb +34 -21
  80. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  81. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  82. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  83. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  84. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  85. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  86. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  87. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  88. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  89. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  90. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  92. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  93. data/spec/blather/stanza/pubsub_spec.rb +62 -0
  94. data/spec/blather/stanza_spec.rb +53 -38
  95. data/spec/blather/stream/client_spec.rb +231 -88
  96. data/spec/blather/stream/component_spec.rb +14 -5
  97. data/spec/blather/stream/parser_spec.rb +145 -0
  98. data/spec/blather/xmpp_node_spec.rb +192 -96
  99. data/spec/fixtures/pubsub.rb +311 -0
  100. data/spec/spec_helper.rb +5 -4
  101. metadata +53 -17
  102. data/Rakefile +0 -139
  103. data/ext/extconf.rb +0 -65
  104. data/ext/push_parser.c +0 -209
  105. data/lib/blather/core_ext/libxml.rb +0 -28
  106. data/lib/blather/stream/resource.rb +0 -48
  107. data/lib/blather/stream/session.rb +0 -36
  108. data/lib/blather/stream/stream_handler.rb +0 -39
  109. data/lib/blather/stream/tls.rb +0 -33
  110. data/spec/blather/core_ext/libxml_spec.rb +0 -58
@@ -0,0 +1,53 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Retract < PubSub
6
+ register :pubsub_retract, :retract, self.registered_ns
7
+
8
+ include Enumerable
9
+ alias_method :find, :xpath
10
+
11
+ def self.new(host = nil, node = nil, type = :set, retractions = [])
12
+ new_node = super(type, host)
13
+ new_node.node = node
14
+ new_node.retractions = retractions
15
+ new_node
16
+ end
17
+
18
+ def node
19
+ retract[:node]
20
+ end
21
+
22
+ def node=(node)
23
+ retract[:node] = node
24
+ end
25
+
26
+ def retract
27
+ unless retract = pubsub.find_first('ns:retract', :ns => self.class.registered_ns)
28
+ self.pubsub << (retract = XMPPNode.new('retract', self.document))
29
+ retract.namespace = self.pubsub.namespace
30
+ end
31
+ retract
32
+ end
33
+
34
+ def retractions=(retractions = [])
35
+ [retractions].flatten.each { |id| self.retract << PubSubItem.new(id, nil, self.document) }
36
+ end
37
+
38
+ def retractions
39
+ retract.find('ns:item', :ns => self.class.registered_ns).map { |i| i[:id] }
40
+ end
41
+
42
+ def each(&block)
43
+ retractions.each &block
44
+ end
45
+
46
+ def size
47
+ retractions.size
48
+ end
49
+ end #Retract
50
+
51
+ end #PubSub
52
+ end #Stanza
53
+ end #Blather
@@ -0,0 +1,42 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Subscribe < PubSub
6
+ register :pubsub_subscribe, :subscribe, self.registered_ns
7
+
8
+ def self.new(type = :set, host = nil, node = nil, jid = nil)
9
+ new_node = super(type, host)
10
+ new_node.node = node
11
+ new_node.jid = jid
12
+ new_node
13
+ end
14
+
15
+ def jid
16
+ JID.new(subscribe[:jid])
17
+ end
18
+
19
+ def jid=(jid)
20
+ subscribe[:jid] = jid
21
+ end
22
+
23
+ def node
24
+ subscribe[:node]
25
+ end
26
+
27
+ def node=(node)
28
+ subscribe[:node] = node
29
+ end
30
+
31
+ def subscribe
32
+ unless subscribe = pubsub.find_first('ns:subscribe', :ns => self.class.registered_ns)
33
+ self.pubsub << (subscribe = XMPPNode.new('subscribe', self.document))
34
+ subscribe.namespace = self.pubsub.namespace
35
+ end
36
+ subscribe
37
+ end
38
+ end #Subscribe
39
+
40
+ end #PubSub
41
+ end #Stanza
42
+ end #Blather
@@ -0,0 +1,66 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Subscription < PubSub
6
+ VALID_TYPES = [:none, :pending, :subscribed, :unconfigured]
7
+
8
+ register :pubsub_subscription, :subscription, self.registered_ns
9
+
10
+ def self.new(type = :result, host = nil, node = nil, jid = nil, subid = nil, subscription = nil)
11
+ new_node = super(type, host)
12
+ new_node.node = node
13
+ new_node.jid = jid
14
+ new_node.subid = subid
15
+ new_node.subscription = subscription
16
+ new_node
17
+ end
18
+
19
+ attribute_helpers_for :subscription, VALID_TYPES
20
+
21
+ def jid
22
+ JID.new(subscription_node[:jid])
23
+ end
24
+
25
+ def jid=(jid)
26
+ subscription_node[:jid] = jid
27
+ end
28
+
29
+ def node
30
+ subscription_node[:node]
31
+ end
32
+
33
+ def node=(node)
34
+ subscription_node[:node] = node
35
+ end
36
+
37
+ def subid
38
+ subscription_node[:subid]
39
+ end
40
+
41
+ def subid=(subid)
42
+ subscription_node[:subid] = subid
43
+ end
44
+
45
+ def subscription
46
+ s = subscription_node[:subscription]
47
+ s.to_sym if s
48
+ end
49
+
50
+ def subscription=(subscription)
51
+ raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}" if subscription && !VALID_TYPES.include?(subscription.to_sym)
52
+ subscription_node[:subscription] = subscription
53
+ end
54
+
55
+ def subscription_node
56
+ unless subscription = pubsub.find_first('ns:subscription', :ns => self.class.registered_ns)
57
+ self.pubsub << (subscription = XMPPNode.new('subscription', self.document))
58
+ subscription.namespace = self.pubsub.namespace
59
+ end
60
+ subscription
61
+ end
62
+ end #Subscribe
63
+
64
+ end #PubSub
65
+ end #Stanza
66
+ end #Blather
@@ -0,0 +1,55 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Subscriptions < PubSub
6
+ register :pubsub_subscriptions, :subscriptions, self.registered_ns
7
+
8
+ include Enumerable
9
+ alias_method :find, :xpath
10
+
11
+ ##
12
+ # Ensure the namespace is set to the query node
13
+ def self.new(type = nil, host = nil)
14
+ new_node = super type
15
+ new_node.to = host
16
+ new_node.subscriptions
17
+ new_node
18
+ end
19
+
20
+ ##
21
+ # Kill the pubsub node before running inherit
22
+ def inherit(node)
23
+ subscriptions.remove
24
+ super
25
+ end
26
+
27
+ def subscriptions
28
+ aff = pubsub.find_first('subscriptions', self.class.registered_ns)
29
+ (self.pubsub << (aff = XMPPNode.new('subscriptions', self.document))) unless aff
30
+ aff
31
+ end
32
+
33
+ def each(&block)
34
+ list.each &block
35
+ end
36
+
37
+ def size
38
+ list.size
39
+ end
40
+
41
+ def list
42
+ subscriptions.find('//ns:subscription', :ns => self.class.registered_ns).inject({}) do |hash, item|
43
+ hash[item[:subscription].to_sym] ||= []
44
+ hash[item[:subscription].to_sym] << {
45
+ :node => item[:node],
46
+ :jid => item[:jid]
47
+ }
48
+ hash
49
+ end
50
+ end
51
+ end #Subscriptions
52
+
53
+ end #PubSub
54
+ end #Stanza
55
+ end #Blather
@@ -0,0 +1,42 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Unsubscribe < PubSub
6
+ register :pubsub_unsubscribe, :unsubscribe, self.registered_ns
7
+
8
+ def self.new(type = :set, host = nil, node = nil, jid = nil)
9
+ new_node = super(type, host)
10
+ new_node.node = node
11
+ new_node.jid = jid
12
+ new_node
13
+ end
14
+
15
+ def jid
16
+ JID.new(unsubscribe[:jid])
17
+ end
18
+
19
+ def jid=(jid)
20
+ unsubscribe[:jid] = jid
21
+ end
22
+
23
+ def node
24
+ unsubscribe[:node]
25
+ end
26
+
27
+ def node=(node)
28
+ unsubscribe[:node] = node
29
+ end
30
+
31
+ def unsubscribe
32
+ unless unsubscribe = pubsub.find_first('ns:unsubscribe', :ns => self.class.registered_ns)
33
+ self.pubsub << (unsubscribe = XMPPNode.new('unsubscribe', self.document))
34
+ unsubscribe.namespace = self.pubsub.namespace
35
+ end
36
+ unsubscribe
37
+ end
38
+ end #Unsubscribe
39
+
40
+ end #PubSub
41
+ end #Stanza
42
+ end #Blather
@@ -0,0 +1,63 @@
1
+ module Blather
2
+ class Stanza
3
+
4
+ class PubSub < Iq
5
+ register :pubsub_node, :pubsub, 'http://jabber.org/protocol/pubsub'
6
+
7
+ def self.import(node)
8
+ klass = nil
9
+ if pubsub = node.document.find_first('//ns:pubsub', :ns => self.registered_ns)
10
+ pubsub.children.each { |e| break if klass = class_from_registration(e.element_name, (e.namespace.href if e.namespace)) }
11
+ end
12
+ (klass || self).new(node[:type]).inherit(node)
13
+ end
14
+
15
+ ##
16
+ # Ensure the namespace is set to the query node
17
+ def self.new(type = nil, host = nil)
18
+ new_node = super type
19
+ new_node.to = host
20
+ new_node.pubsub
21
+ new_node
22
+ end
23
+
24
+ ##
25
+ # Kill the pubsub node before running inherit
26
+ def inherit(node)
27
+ remove_children :pubsub
28
+ super
29
+ end
30
+
31
+ def pubsub
32
+ p = find_first('ns:pubsub', :ns => self.class.registered_ns) ||
33
+ find_first('pubsub', :ns => self.class.registered_ns)
34
+
35
+ unless p
36
+ self << (p = XMPPNode.new('pubsub', self.document))
37
+ p.namespace = self.class.registered_ns
38
+ end
39
+ p
40
+ end
41
+ end
42
+
43
+ class PubSubItem < XMPPNode
44
+ def self.new(id = nil, payload = nil, document = nil)
45
+ new_node = super 'item', document
46
+ new_node.id = id
47
+ new_node.payload = payload if payload
48
+ new_node
49
+ end
50
+
51
+ attribute_accessor :id
52
+
53
+ def payload=(payload = nil)
54
+ self.content = payload
55
+ end
56
+
57
+ def payload
58
+ content.empty? ? nil : content
59
+ end
60
+ end
61
+
62
+ end #Stanza
63
+ end #Blather
@@ -0,0 +1,34 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSubOwner
4
+
5
+ class Delete < PubSubOwner
6
+
7
+ register :pubsub_delete, :delete, self.registered_ns
8
+
9
+ def self.new(type = :set, host = nil, node = nil)
10
+ new_node = super(type, host)
11
+ new_node.node = node
12
+ new_node
13
+ end
14
+
15
+ def node
16
+ delete_node[:node]
17
+ end
18
+
19
+ def node=(node)
20
+ delete_node[:node] = node
21
+ end
22
+
23
+ def delete_node
24
+ unless delete_node = pubsub.find_first('ns:delete', :ns => self.class.registered_ns)
25
+ self.pubsub << (delete_node = XMPPNode.new('delete', self.document))
26
+ delete_node.namespace = self.pubsub.namespace
27
+ end
28
+ delete_node
29
+ end
30
+ end #Retract
31
+
32
+ end #PubSub
33
+ end #Stanza
34
+ end #Blather
@@ -0,0 +1,34 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSubOwner
4
+
5
+ class Purge < PubSubOwner
6
+
7
+ register :pubsub_purge, :purge, self.registered_ns
8
+
9
+ def self.new(type = :set, host = nil, node = nil)
10
+ new_node = super(type, host)
11
+ new_node.node = node
12
+ new_node
13
+ end
14
+
15
+ def node
16
+ purge_node[:node]
17
+ end
18
+
19
+ def node=(node)
20
+ purge_node[:node] = node
21
+ end
22
+
23
+ def purge_node
24
+ unless purge_node = pubsub.find_first('ns:purge', :ns => self.class.registered_ns)
25
+ self.pubsub << (purge_node = XMPPNode.new('purge', self.document))
26
+ purge_node.namespace = self.pubsub.namespace
27
+ end
28
+ purge_node
29
+ end
30
+ end #Retract
31
+
32
+ end #PubSub
33
+ end #Stanza
34
+ end #Blather
@@ -0,0 +1,41 @@
1
+ module Blather
2
+ class Stanza
3
+
4
+ class PubSubOwner < Iq
5
+ register :pubsub_owner, :pubsub, 'http://jabber.org/protocol/pubsub#owner'
6
+
7
+ def self.import(node)
8
+ klass = nil
9
+ if pubsub = node.document.find_first('//ns:pubsub', :ns => self.registered_ns)
10
+ pubsub.children.each { |e| break if klass = class_from_registration(e.element_name, (e.namespace.href if e.namespace)) }
11
+ end
12
+ (klass || self).new(node[:type]).inherit(node)
13
+ end
14
+
15
+ ##
16
+ # Ensure the namespace is set to the query node
17
+ def self.new(type = nil, host = nil)
18
+ new_node = super type
19
+ new_node.to = host
20
+ new_node.pubsub
21
+ new_node
22
+ end
23
+
24
+ ##
25
+ # Kill the pubsub node before running inherit
26
+ def inherit(node)
27
+ remove_children :pubsub
28
+ super
29
+ end
30
+
31
+ def pubsub
32
+ unless p = find_first('ns:pubsub', :ns => self.class.registered_ns)
33
+ self << (p = XMPPNode.new('pubsub', self.document))
34
+ p.namespace = self.class.registered_ns
35
+ end
36
+ p
37
+ end
38
+ end
39
+
40
+ end #Stanza
41
+ end #Blather
@@ -14,12 +14,12 @@ module Blather
14
14
  # that inherits Stanza can register a callback for itself
15
15
  # which is added to a list and iterated over when looking for
16
16
  # a callback to use
17
- def self.register(type, name = nil, ns = nil)
18
- @@handler_list << type
17
+ def self.register(handler, name = nil, ns = nil)
18
+ @@handler_list << handler
19
19
  self.handler_heirarchy ||= []
20
- self.handler_heirarchy.unshift type
20
+ self.handler_heirarchy.unshift handler
21
21
 
22
- name = name || self.name || type
22
+ name = name || self.registered_name || handler
23
23
  super name, ns
24
24
  end
25
25
 
@@ -44,24 +44,32 @@ module Blather
44
44
  ##
45
45
  # Automatically set the stanza's ID
46
46
  # and attach it to a document so XPath searching works
47
- def initialize(name = nil)
48
- super
49
- XML::Document.new.root = self
50
- self.name = name.to_s if name
51
- self.id = self.class.next_id
47
+ def self.new(name = nil)
48
+ node = super
49
+ node.name = name.to_s if name
50
+ node
52
51
  end
53
52
 
54
53
  ##
55
- # Helper method to ask the object if it's an error
56
- def error?
57
- self.type == :error
54
+ # Helper method to generate stanza guard methods
55
+ #
56
+ # attribute_helpers_for(:type, [:subscribe, :unsubscribe])
57
+ #
58
+ # This generates "subscribe?" and "unsubscribe?" methods that return
59
+ # true if self.type == :subscribe or :unsubscribe, respectively.
60
+ def self.attribute_helpers_for(attr, values)
61
+ [values].flatten.each do |v|
62
+ define_method("#{v}?") { __send__(attr) == v }
63
+ end
58
64
  end
59
65
 
66
+ attribute_helpers_for(:type, :error)
67
+
60
68
  ##
61
69
  # Copies itself then swaps from and to
62
70
  # then returns the new stanza
63
71
  def reply
64
- self.copy(true).reply!
72
+ self.dup.reply!
65
73
  end
66
74
 
67
75
  ##
@@ -71,23 +79,23 @@ module Blather
71
79
  self
72
80
  end
73
81
 
74
- attribute_accessor :id, :to_sym => false
82
+ attribute_accessor :id
75
83
 
76
84
  attribute_writer :to, :from
77
85
 
78
86
  ##
79
87
  # returns:: JID created from the "to" value of the stanza
80
88
  def to
81
- JID.new(attributes[:to]) if attributes[:to]
89
+ JID.new(self[:to]) if self[:to]
82
90
  end
83
91
 
84
92
  ##
85
93
  # returns:: JID created from the "from" value of the stanza
86
94
  def from
87
- JID.new(attributes[:from]) if attributes[:from]
95
+ JID.new(self[:from]) if self[:from]
88
96
  end
89
97
 
90
- attribute_accessor :type
98
+ attribute_accessor :type, :call => :to_sym
91
99
 
92
100
  ##
93
101
  # Transform the stanza into a stanza error
@@ -96,5 +104,14 @@ module Blather
96
104
  def as_error(name, type, text = nil, extras = [])
97
105
  StanzaError.new self, name, type, text, extras
98
106
  end
107
+
108
+ protected
109
+ def reply_if_needed!
110
+ unless @reversed_endpoints
111
+ reply!
112
+ @reversed_endpoints = true
113
+ end
114
+ self
115
+ end
99
116
  end
100
- end
117
+ end
@@ -6,14 +6,13 @@ class Stream
6
6
  VERSION = '1.0'
7
7
  NAMESPACE = 'jabber:client'
8
8
 
9
- protected
10
9
  def start
11
10
  @parser = Parser.new self
12
11
  start_stream = <<-STREAM
13
12
  <stream:stream
14
13
  to='#{@to}'
15
14
  xmlns='#{NAMESPACE}'
16
- xmlns:stream='http://etherx.jabber.org/streams'
15
+ xmlns:stream='#{STREAM_NS}'
17
16
  version='#{VERSION}'
18
17
  xml:lang='#{LANG}'
19
18
  >
@@ -6,24 +6,28 @@ class Stream
6
6
 
7
7
  def receive(node) # :nodoc:
8
8
  if node.element_name == 'handshake'
9
- @client.post_init
9
+ ready!
10
10
  else
11
11
  super
12
12
  end
13
13
 
14
- if node.namespaces.find_by_href('http://etherx.jabber.org/streams') && node.find_first('/stream:stream[not(stream:error)]')
15
- send("<handshake>#{Digest::SHA1.hexdigest(@node['id']+@pass)}</handshake>")
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
16
  end
17
17
  end
18
18
 
19
- protected
19
+ def send(stanza)
20
+ stanza.from ||= self.jid if stanza.respond_to?(:from) && stanza.respond_to?(:from=)
21
+ super stanza
22
+ end
23
+
20
24
  def start
21
25
  @parser = Parser.new self
22
26
  start_stream = <<-STREAM
23
27
  <stream:stream
24
28
  to='#{@jid}'
25
29
  xmlns='#{NAMESPACE}'
26
- xmlns:stream='http://etherx.jabber.org/streams'
30
+ xmlns:stream='#{STREAM_NS}'
27
31
  >
28
32
  STREAM
29
33
  send start_stream.gsub(/\s+/, ' ')
@@ -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/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