shingara-blather 0.4.8

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