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.rb +35 -12
  10. data/lib/blather/client.rb +1 -1
  11. data/lib/blather/client/client.rb +19 -13
  12. data/lib/blather/client/dsl.rb +16 -0
  13. data/lib/blather/client/dsl/pubsub.rb +133 -0
  14. data/lib/blather/core_ext/active_support.rb +1 -117
  15. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
  16. data/lib/blather/core_ext/nokogiri.rb +35 -0
  17. data/lib/blather/errors.rb +3 -20
  18. data/lib/blather/errors/sasl_error.rb +3 -1
  19. data/lib/blather/errors/stanza_error.rb +10 -17
  20. data/lib/blather/errors/stream_error.rb +11 -14
  21. data/lib/blather/jid.rb +1 -0
  22. data/lib/blather/roster.rb +9 -0
  23. data/lib/blather/roster_item.rb +6 -1
  24. data/lib/blather/stanza.rb +35 -18
  25. data/lib/blather/stanza/disco.rb +7 -1
  26. data/lib/blather/stanza/disco/disco_info.rb +45 -33
  27. data/lib/blather/stanza/disco/disco_items.rb +32 -21
  28. data/lib/blather/stanza/iq.rb +13 -8
  29. data/lib/blather/stanza/iq/query.rb +16 -8
  30. data/lib/blather/stanza/iq/roster.rb +33 -22
  31. data/lib/blather/stanza/message.rb +20 -31
  32. data/lib/blather/stanza/presence.rb +3 -5
  33. data/lib/blather/stanza/presence/status.rb +13 -21
  34. data/lib/blather/stanza/presence/subscription.rb +11 -16
  35. data/lib/blather/stanza/pubsub.rb +63 -0
  36. data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
  37. data/lib/blather/stanza/pubsub/create.rb +43 -0
  38. data/lib/blather/stanza/pubsub/errors.rb +9 -0
  39. data/lib/blather/stanza/pubsub/event.rb +77 -0
  40. data/lib/blather/stanza/pubsub/items.rb +63 -0
  41. data/lib/blather/stanza/pubsub/publish.rb +58 -0
  42. data/lib/blather/stanza/pubsub/retract.rb +53 -0
  43. data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
  44. data/lib/blather/stanza/pubsub/subscription.rb +66 -0
  45. data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
  46. data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
  47. data/lib/blather/stanza/pubsub_owner.rb +41 -0
  48. data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
  49. data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
  50. data/lib/blather/stream.rb +76 -168
  51. data/lib/blather/stream/client.rb +1 -2
  52. data/lib/blather/stream/component.rb +9 -5
  53. data/lib/blather/stream/features.rb +53 -0
  54. data/lib/blather/stream/features/resource.rb +63 -0
  55. data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
  56. data/lib/blather/stream/features/session.rb +44 -0
  57. data/lib/blather/stream/features/tls.rb +28 -0
  58. data/lib/blather/stream/parser.rb +70 -46
  59. data/lib/blather/xmpp_node.rb +113 -52
  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 +54 -18
  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,63 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Items < PubSub
6
+ register :pubsub_items, :items, self.registered_ns
7
+
8
+ include Enumerable
9
+ alias_method :find, :xpath
10
+
11
+ def self.request(host, path, list = [], max = nil)
12
+ node = self.new :get, host
13
+
14
+ node.node = path
15
+ node.max_items = max
16
+
17
+ (list || []).each { |id| node.items_node << PubSubItem.new(id, nil, node.document) }
18
+
19
+ node
20
+ end
21
+
22
+ def self.new(type = nil, host = nil)
23
+ new_node = super
24
+ new_node.items
25
+ new_node
26
+ end
27
+
28
+ def node
29
+ items_node[:node]
30
+ end
31
+
32
+ def node=(node)
33
+ items_node[:node] = node
34
+ end
35
+
36
+ def max_items
37
+ items_node[:max_items].to_i if items_node[:max_items]
38
+ end
39
+
40
+ def max_items=(max_items)
41
+ items_node[:max_items] = max_items
42
+ end
43
+
44
+ def each(&block)
45
+ items.each &block
46
+ end
47
+
48
+ def items
49
+ items_node.find('ns:item', :ns => self.class.registered_ns).map { |i| PubSubItem.new(nil,nil,self.document).inherit i }
50
+ end
51
+
52
+ def items_node
53
+ unless node = self.pubsub.find_first('ns:items', :ns => self.class.registered_ns)
54
+ (self.pubsub << (node = XMPPNode.new('items', self.document)))
55
+ node.namespace = self.pubsub.namespace
56
+ end
57
+ node
58
+ end
59
+ end
60
+
61
+ end #PubSub
62
+ end #Stanza
63
+ end #Blather
@@ -0,0 +1,58 @@
1
+ module Blather
2
+ class Stanza
3
+ class PubSub
4
+
5
+ class Publish < PubSub
6
+ register :pubsub_publish, :publish, self.registered_ns
7
+
8
+ include Enumerable
9
+ alias_method :find, :xpath
10
+
11
+ def self.new(host = nil, node = nil, type = :set, payload = nil)
12
+ new_node = super(type, host)
13
+ new_node.node = node
14
+ new_node.payload = payload if payload
15
+ new_node
16
+ end
17
+
18
+ def payload=(payload)
19
+ payload = case payload
20
+ when Hash then payload.to_a
21
+ when Array then payload.map { |v| [nil, v] }
22
+ else [[nil, payload.to_s]]
23
+ end
24
+ payload.each { |id,value| self.publish << PubSubItem.new(id, value, self.document) }
25
+ end
26
+
27
+ def node
28
+ publish[:node]
29
+ end
30
+
31
+ def node=(node)
32
+ publish[:node] = node
33
+ end
34
+
35
+ def publish
36
+ unless publish = pubsub.find_first('ns:publish', :ns => self.class.registered_ns)
37
+ self.pubsub << (publish = XMPPNode.new('publish', self.document))
38
+ publish.namespace = self.pubsub.namespace
39
+ end
40
+ publish
41
+ end
42
+
43
+ def items
44
+ publish.find('ns:item', :ns => self.class.registered_ns).map { |i| PubSubItem.new(nil,nil,self.document).inherit i }
45
+ end
46
+
47
+ def each(&block)
48
+ items.each &block
49
+ end
50
+
51
+ def size
52
+ items.size
53
+ end
54
+ end #Publish
55
+
56
+ end #PubSub
57
+ end #Stanza
58
+ end #Blather
@@ -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,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
@@ -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