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.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