shingara-blather 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +162 -0
  3. data/examples/echo.rb +18 -0
  4. data/examples/execute.rb +16 -0
  5. data/examples/ping_pong.rb +37 -0
  6. data/examples/print_hierarchy.rb +76 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/stream_only.rb +27 -0
  9. data/examples/xmpp4r/echo.rb +35 -0
  10. data/lib/blather/client/client.rb +310 -0
  11. data/lib/blather/client/dsl/pubsub.rb +170 -0
  12. data/lib/blather/client/dsl.rb +264 -0
  13. data/lib/blather/client.rb +87 -0
  14. data/lib/blather/core_ext/nokogiri.rb +40 -0
  15. data/lib/blather/errors/sasl_error.rb +43 -0
  16. data/lib/blather/errors/stanza_error.rb +107 -0
  17. data/lib/blather/errors/stream_error.rb +82 -0
  18. data/lib/blather/errors.rb +69 -0
  19. data/lib/blather/jid.rb +142 -0
  20. data/lib/blather/roster.rb +111 -0
  21. data/lib/blather/roster_item.rb +122 -0
  22. data/lib/blather/stanza/disco/disco_info.rb +176 -0
  23. data/lib/blather/stanza/disco/disco_items.rb +132 -0
  24. data/lib/blather/stanza/disco.rb +25 -0
  25. data/lib/blather/stanza/iq/query.rb +53 -0
  26. data/lib/blather/stanza/iq/roster.rb +179 -0
  27. data/lib/blather/stanza/iq.rb +138 -0
  28. data/lib/blather/stanza/message.rb +332 -0
  29. data/lib/blather/stanza/presence/status.rb +212 -0
  30. data/lib/blather/stanza/presence/subscription.rb +101 -0
  31. data/lib/blather/stanza/presence.rb +163 -0
  32. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  33. data/lib/blather/stanza/pubsub/create.rb +65 -0
  34. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  35. data/lib/blather/stanza/pubsub/event.rb +123 -0
  36. data/lib/blather/stanza/pubsub/items.rb +103 -0
  37. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  38. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  39. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  40. data/lib/blather/stanza/pubsub/subscription.rb +134 -0
  41. data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
  42. data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
  43. data/lib/blather/stanza/pubsub.rb +129 -0
  44. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  45. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  46. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  47. data/lib/blather/stanza.rb +149 -0
  48. data/lib/blather/stream/client.rb +31 -0
  49. data/lib/blather/stream/component.rb +38 -0
  50. data/lib/blather/stream/features/resource.rb +63 -0
  51. data/lib/blather/stream/features/sasl.rb +187 -0
  52. data/lib/blather/stream/features/session.rb +44 -0
  53. data/lib/blather/stream/features/tls.rb +28 -0
  54. data/lib/blather/stream/features.rb +53 -0
  55. data/lib/blather/stream/parser.rb +102 -0
  56. data/lib/blather/stream.rb +231 -0
  57. data/lib/blather/xmpp_node.rb +218 -0
  58. data/lib/blather.rb +78 -0
  59. data/spec/blather/client/client_spec.rb +559 -0
  60. data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
  61. data/spec/blather/client/dsl_spec.rb +143 -0
  62. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  63. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  64. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  65. data/spec/blather/errors/stream_error_spec.rb +108 -0
  66. data/spec/blather/errors_spec.rb +33 -0
  67. data/spec/blather/jid_spec.rb +87 -0
  68. data/spec/blather/roster_item_spec.rb +96 -0
  69. data/spec/blather/roster_spec.rb +103 -0
  70. data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
  71. data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
  72. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  73. data/spec/blather/stanza/iq/roster_spec.rb +140 -0
  74. data/spec/blather/stanza/iq_spec.rb +45 -0
  75. data/spec/blather/stanza/message_spec.rb +132 -0
  76. data/spec/blather/stanza/presence/status_spec.rb +132 -0
  77. data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
  78. data/spec/blather/stanza/presence_spec.rb +66 -0
  79. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  80. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  81. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  82. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  83. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  84. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  85. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  86. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  87. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  88. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  89. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  90. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  92. data/spec/blather/stanza/pubsub_spec.rb +67 -0
  93. data/spec/blather/stanza_spec.rb +116 -0
  94. data/spec/blather/stream/client_spec.rb +1011 -0
  95. data/spec/blather/stream/component_spec.rb +95 -0
  96. data/spec/blather/stream/parser_spec.rb +145 -0
  97. data/spec/blather/xmpp_node_spec.rb +231 -0
  98. data/spec/fixtures/pubsub.rb +311 -0
  99. data/spec/spec_helper.rb +43 -0
  100. metadata +249 -0
@@ -0,0 +1,218 @@
1
+ module Blather
2
+
3
+ # Base XML Node
4
+ # All XML classes subclass XMPPNode it allows the addition of helpers
5
+ class XMPPNode < Nokogiri::XML::Node
6
+ # @private
7
+ BASE_NAMES = %w[presence message iq].freeze
8
+
9
+ # @private
10
+ @@registrations = {}
11
+
12
+ class_inheritable_accessor :registered_ns,
13
+ :registered_name
14
+
15
+ # Register a new stanza class to a name and/or namespace
16
+ #
17
+ # This registers a namespace that is used when looking
18
+ # up the class name of the object to instantiate when a new
19
+ # stanza is received
20
+ #
21
+ # @param [#to_s] name the name of the node
22
+ # @param [String, nil] ns the namespace the node belongs to
23
+ def self.register(name, ns = nil)
24
+ self.registered_name = name.to_s
25
+ self.registered_ns = ns
26
+ @@registrations[[self.registered_name, self.registered_ns]] = self
27
+ end
28
+
29
+ # Find the class to use given the name and namespace of a stanza
30
+ #
31
+ # @param [#to_s] name the name to lookup
32
+ # @param [String, nil] xmlns the namespace the node belongs to
33
+ # @return [Class, nil] the class appropriate for the name/ns combination
34
+ def self.class_from_registration(name, ns = nil)
35
+ name = name.to_s
36
+ @@registrations[[name, ns]] || @@registrations[[name, nil]]
37
+ end
38
+
39
+ # Import an XML::Node to the appropriate class
40
+ #
41
+ # Looks up the class the node should be then creates it based on the
42
+ # elements of the XML::Node
43
+ # @param [XML::Node] node the node to import
44
+ # @return the appropriate object based on the node name and namespace
45
+ def self.import(node)
46
+ ns = (node.namespace.href if node.namespace)
47
+ klass = class_from_registration(node.element_name, ns)
48
+ if klass && klass != self
49
+ klass.import(node)
50
+ else
51
+ new(node.element_name).inherit(node)
52
+ end
53
+ end
54
+
55
+ # Create a new Node object
56
+ #
57
+ # @param [String, nil] name the element name
58
+ # @param [XML::Document, nil] doc the document to attach the node to. If
59
+ # not provided one will be created
60
+ # @return a new object with the registered name and namespace
61
+ def self.new(name = nil, doc = nil)
62
+ name ||= self.registered_name
63
+
64
+ node = super name.to_s, (doc || Nokogiri::XML::Document.new)
65
+ node.document.root = node unless doc
66
+ node.namespace = self.registered_ns unless BASE_NAMES.include?(name.to_s)
67
+ node
68
+ end
69
+
70
+ # Helper method to read an attribute
71
+ #
72
+ # @param [#to_sym] attr_name the name of the attribute
73
+ # @param [String, Symbol, nil] to_call the name of the method to call on
74
+ # the returned value
75
+ # @return nil or the value
76
+ def read_attr(attr_name, to_call = nil)
77
+ val = self[attr_name.to_sym]
78
+ val && to_call ? val.__send__(to_call) : val
79
+ end
80
+
81
+ # Helper method to write a value to an attribute
82
+ #
83
+ # @param [#to_sym] attr_name the name of the attribute
84
+ # @param [#to_s] value the value to set the attribute to
85
+ def write_attr(attr_name, value)
86
+ self[attr_name.to_sym] = value
87
+ end
88
+
89
+ # Helper method to read the content of a node
90
+ #
91
+ # @param [#to_sym] node the name of the node
92
+ # @param [String, Symbol, nil] to_call the name of the method to call on
93
+ # the returned value
94
+ # @return nil or the value
95
+ def read_content(node, to_call = nil)
96
+ val = content_from node.to_sym
97
+ val && to_call ? val.__send__(to_call) : val
98
+ end
99
+
100
+ # Turn the object into a proper stanza
101
+ #
102
+ # @return a stanza object
103
+ def to_stanza
104
+ self.class.import self
105
+ end
106
+
107
+ # @private
108
+ alias_method :nokogiri_namespace=, :namespace=
109
+ # Attach a namespace to the node
110
+ #
111
+ # @overload namespace=(ns)
112
+ # Attach an already created XML::Namespace
113
+ # @param [XML::Namespace] ns the namespace object
114
+ # @overload namespace=(ns)
115
+ # Create a new namespace and attach it
116
+ # @param [String] ns the namespace uri
117
+ # @overload namespace=(namespaces)
118
+ # Createa and add new namespaces from a hash
119
+ # @param [Hash] namespaces a hash of prefix => uri pairs
120
+ def namespace=(namespaces)
121
+ case namespaces
122
+ when Nokogiri::XML::Namespace
123
+ self.nokogiri_namespace = namespaces
124
+ when String
125
+ self.add_namespace nil, namespaces
126
+ when Hash
127
+ if ns = namespaces.delete(nil)
128
+ self.add_namespace nil, ns
129
+ end
130
+ namespaces.each do |p, n|
131
+ ns = self.add_namespace p, n
132
+ self.nokogiri_namespace = ns
133
+ end
134
+ end
135
+ end
136
+
137
+ # Helper method to get the node's namespace
138
+ #
139
+ # @return [XML::Namespace, nil] The node's namespace object if it exists
140
+ def namespace_href
141
+ namespace.href if namespace
142
+ end
143
+
144
+ # Remove a child with the name and (optionally) namespace given
145
+ #
146
+ # @param [String] name the name or xpath of the node to remove
147
+ # @param [String, nil] ns the namespace the node is in
148
+ def remove_child(name, ns = nil)
149
+ child = xpath(name, ns).first
150
+ child.remove if child
151
+ end
152
+
153
+ # Remove all children with a given name regardless of namespace
154
+ #
155
+ # @param [String] name the name of the nodes to remove
156
+ def remove_children(name)
157
+ xpath("./*[local-name()='#{name}']").remove
158
+ end
159
+
160
+ # The content of the named node
161
+ #
162
+ # @param [String] name the name or xpath of the node
163
+ # @param [String, nil] ns the namespace the node is in
164
+ # @return [String, nil] the content of the node
165
+ def content_from(name, ns = nil)
166
+ child = xpath(name, ns).first
167
+ child.content if child
168
+ end
169
+
170
+ # Sets the content for the specified node.
171
+ # If the node exists it is updated. If not a new node is created
172
+ # If the node exists and the content is nil, the node will be removed
173
+ # entirely
174
+ #
175
+ # @param [String] node the name of the node to update/create
176
+ # @param [String, nil] content the content to set within the node
177
+ def set_content_for(node, content = nil)
178
+ if content
179
+ child = xpath(node).first
180
+ self << (child = XMPPNode.new(node, self.document)) unless child
181
+ child.content = content
182
+ else
183
+ remove_child node
184
+ end
185
+ end
186
+
187
+ alias_method :copy, :dup
188
+
189
+ # Inherit the attributes and children of an XML::Node
190
+ #
191
+ # @param [XML::Node] stanza the node to inherit
192
+ # @return [self]
193
+ def inherit(stanza)
194
+ set_namespace stanza.namespace if stanza.namespace
195
+ inherit_attrs stanza.attributes
196
+ stanza.children.each do |c|
197
+ self << (n = c.dup)
198
+ ns = n.namespace_definitions.find { |ns| ns.prefix == c.namespace.prefix }
199
+ n.namespace = ns if ns
200
+ end
201
+ self
202
+ end
203
+
204
+ # Inherit a set of attributes
205
+ #
206
+ # @param [Hash] attrs a hash of attributes to set on the node
207
+ # @return [self]
208
+ def inherit_attrs(attrs)
209
+ attrs.each { |name, value| self[name] = value }
210
+ self
211
+ end
212
+
213
+ def inspect
214
+ self.to_xml
215
+ end
216
+ end # XMPPNode
217
+
218
+ end # Blather
data/lib/blather.rb ADDED
@@ -0,0 +1,78 @@
1
+ # Require the necessary files
2
+ %w[
3
+ rubygems
4
+ eventmachine
5
+ nokogiri
6
+ digest/md5
7
+ logger
8
+ active_support/core_ext/class/inheritable_attributes
9
+ active_support/core_ext/object/blank
10
+
11
+ blather/core_ext/nokogiri
12
+
13
+ blather/errors
14
+ blather/errors/sasl_error
15
+ blather/errors/stanza_error
16
+ blather/errors/stream_error
17
+ blather/jid
18
+ blather/roster
19
+ blather/roster_item
20
+ blather/xmpp_node
21
+
22
+ blather/stanza
23
+ blather/stanza/iq
24
+ blather/stanza/iq/query
25
+ blather/stanza/iq/roster
26
+ blather/stanza/disco
27
+ blather/stanza/disco/disco_info
28
+ blather/stanza/disco/disco_items
29
+ blather/stanza/message
30
+ blather/stanza/presence
31
+ blather/stanza/presence/status
32
+ blather/stanza/presence/subscription
33
+
34
+ blather/stanza/pubsub
35
+ blather/stanza/pubsub/affiliations
36
+ blather/stanza/pubsub/create
37
+ blather/stanza/pubsub/event
38
+ blather/stanza/pubsub/items
39
+ blather/stanza/pubsub/publish
40
+ blather/stanza/pubsub/retract
41
+ blather/stanza/pubsub/subscribe
42
+ blather/stanza/pubsub/subscription
43
+ blather/stanza/pubsub/subscriptions
44
+ blather/stanza/pubsub/unsubscribe
45
+
46
+ blather/stanza/pubsub_owner
47
+ blather/stanza/pubsub_owner/delete
48
+ blather/stanza/pubsub_owner/purge
49
+
50
+ blather/stream
51
+ blather/stream/client
52
+ blather/stream/component
53
+ blather/stream/parser
54
+ blather/stream/features
55
+ blather/stream/features/resource
56
+ blather/stream/features/sasl
57
+ blather/stream/features/session
58
+ blather/stream/features/tls
59
+ ].each { |r| require r }
60
+
61
+ module Blather
62
+ # @private
63
+ @@logger = nil
64
+
65
+ # Get or create an instance of Logger
66
+ def self.logger
67
+ unless @@logger
68
+ self.logger = Logger.new($stdout)
69
+ self.logger.level = Logger::INFO
70
+ end
71
+ @@logger
72
+ end
73
+
74
+ # Set the Logger
75
+ def self.logger=(logger)
76
+ @@logger = logger
77
+ end
78
+ end