sprsquish-blather 0.3.4 → 0.4.0

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