blather 0.4.16 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG +12 -5
  3. data/README.md +1 -1
  4. data/Rakefile +1 -3
  5. data/blather.gemspec +11 -24
  6. data/examples/echo.rb +1 -0
  7. data/examples/execute.rb +1 -0
  8. data/examples/ping_pong.rb +1 -0
  9. data/examples/print_hierarchy.rb +1 -0
  10. data/examples/rosterprint.rb +1 -0
  11. data/examples/stream_only.rb +1 -0
  12. data/examples/xmpp4r/echo.rb +1 -0
  13. data/lib/blather.rb +5 -1
  14. data/lib/blather/client/client.rb +29 -154
  15. data/lib/blather/client/dsl.rb +9 -3
  16. data/lib/blather/client/dsl/pubsub.rb +2 -0
  17. data/lib/blather/core_ext/eventmachine.rb +4 -1
  18. data/lib/blather/core_ext/ipaddr.rb +2 -1
  19. data/lib/blather/core_ext/nokogiri.rb +3 -1
  20. data/lib/blather/errors/sasl_error.rb +1 -0
  21. data/lib/blather/errors/stanza_error.rb +3 -1
  22. data/lib/blather/errors/stream_error.rb +1 -0
  23. data/lib/blather/file_transfer.rb +4 -1
  24. data/lib/blather/file_transfer/s5b.rb +3 -4
  25. data/lib/blather/jid.rb +2 -0
  26. data/lib/blather/roster_item.rb +13 -3
  27. data/lib/blather/stanza.rb +11 -3
  28. data/lib/blather/stanza/disco/capabilities.rb +161 -0
  29. data/lib/blather/stanza/disco/disco_info.rb +3 -1
  30. data/lib/blather/stanza/disco/disco_items.rb +0 -1
  31. data/lib/blather/stanza/iq.rb +8 -2
  32. data/lib/blather/stanza/iq/command.rb +18 -3
  33. data/lib/blather/stanza/iq/ibb.rb +6 -3
  34. data/lib/blather/stanza/iq/s5b.rb +6 -3
  35. data/lib/blather/stanza/iq/si.rb +6 -1
  36. data/lib/blather/stanza/iq/vcard.rb +3 -1
  37. data/lib/blather/stanza/message.rb +5 -0
  38. data/lib/blather/stanza/presence.rb +1 -0
  39. data/lib/blather/stanza/presence/c.rb +1 -0
  40. data/lib/blather/stanza/presence/status.rb +1 -0
  41. data/lib/blather/stanza/pubsub/event.rb +2 -4
  42. data/lib/blather/stanza/pubsub/subscription.rb +1 -0
  43. data/lib/blather/stanza/x.rb +8 -0
  44. data/lib/blather/stream.rb +2 -0
  45. data/lib/blather/stream/client.rb +1 -0
  46. data/lib/blather/stream/component.rb +1 -0
  47. data/lib/blather/stream/features.rb +4 -3
  48. data/lib/blather/stream/features/resource.rb +4 -3
  49. data/lib/blather/stream/features/sasl.rb +9 -6
  50. data/lib/blather/stream/features/session.rb +5 -4
  51. data/lib/blather/stream/features/tls.rb +4 -3
  52. data/lib/blather/stream/parser.rb +4 -5
  53. data/lib/blather/version.rb +2 -1
  54. data/lib/blather/xmpp_node.rb +9 -0
  55. data/spec/blather/client/client_spec.rb +14 -1
  56. data/spec/blather/stanza/iq_spec.rb +16 -0
  57. data/spec/blather/stanza/presence_spec.rb +1 -1
  58. data/spec/blather/stanza_spec.rb +18 -0
  59. data/spec/blather/stream/client_spec.rb +2 -2
  60. metadata +52 -35
  61. data/lib/blather/core_ext/active_support.rb +0 -45
  62. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +0 -117
data/.gemtest ADDED
File without changes
data/CHANGELOG CHANGED
@@ -1,9 +1,16 @@
1
+ v0.5.0
2
+ Feature(radsaq): Add a #connected? method on Blather::Client
3
+ Feature(benlangfeld)[API change]: Allow the removal of child nodes from an IQ reply
4
+ Bugfix(zlu): Use rubygems properly in examples
5
+ Bugfix(benlangfeld): Remove code borrowed from ActiveSupport and instead depend on it to avoid version conflicts
6
+ Documentation(sprsquish)
7
+
1
8
  v0.4.16
2
- Feature(benlangfeld): switch from jeweler to bundler
3
- Feature(benlangfeld): add cap support (XEP-0115)
4
- Bugfix(sprsquish): Better equality checking
5
- Bugfix(sprsquish): Fix #to_proc
6
- Bugfix(mironov): Skip private IPs by default
9
+ Feature(benlangfeld): switch from jeweler to bundler
10
+ Feature(benlangfeld): add cap support (XEP-0115)
11
+ Bugfix(sprsquish): Better equality checking
12
+ Bugfix(sprsquish): Fix #to_proc
13
+ Bugfix(mironov): Skip private IPs by default
7
14
 
8
15
  v0.4.15
9
16
  Feature(mironov): Implement XEP-0054: vcard-temp
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Blather
1
+ # Blather [ ![Build status](http://travis-ci.org/sprsquish/blather.png) ](http://travis-ci.org/sprsquish/blather)
2
2
 
3
3
  XMPP DSL (and more) for Ruby written on EventMachine and Nokogiri.
4
4
 
data/Rakefile CHANGED
@@ -23,10 +23,8 @@ require 'yard'
23
23
  YARD::Tags::Library.define_tag 'Blather handler', :handler, :with_name
24
24
  YARD::Templates::Engine.register_template_path 'yard/templates'
25
25
 
26
- YARD::Rake::YardocTask.new do |t|
26
+ YARD::Rake::YardocTask.new(:doc) do |t|
27
27
  t.options = ['--no-private', '-m', 'markdown', '-o', './doc/public/yard']
28
28
  end
29
29
 
30
- desc 'Generate documentation'
31
- task :doc => :yard
32
30
  task :default => :test
data/blather.gemspec CHANGED
@@ -21,29 +21,16 @@ Gem::Specification.new do |s|
21
21
  s.rdoc_options = %w{--charset=UTF-8}
22
22
  s.extra_rdoc_files = %w{LICENSE README.md}
23
23
 
24
- if s.respond_to? :specification_version then
25
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
- s.specification_version = 3
24
+ s.add_dependency("eventmachine", ["~> 0.12.6"])
25
+ s.add_dependency("nokogiri", [">= 1.4.0"])
26
+ s.add_dependency("minitest", [">= 1.7.1"])
27
+ s.add_dependency("activesupport", [">= 3.0.7"])
27
28
 
28
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
- s.add_runtime_dependency(%q<eventmachine>, ["~> 0.12.6"])
30
- s.add_runtime_dependency(%q<nokogiri>, ["~> 1.4.0"])
31
-
32
- s.add_development_dependency(%q<minitest>, ["~> 1.7.1"])
33
- s.add_development_dependency(%q<mocha>, ["~> 0.9.12"])
34
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
35
- s.add_development_dependency(%q<rcov>, ["~> 0.9.9"])
36
- s.add_development_dependency(%q<yard>, ["~> 0.6.1"])
37
- s.add_development_dependency(%q<bluecloth>, ["~> 2.1.0"])
38
- s.add_development_dependency(%q<rake>)
39
- else
40
- s.add_dependency(%q<eventmachine>, [">= 0.12.6"])
41
- s.add_dependency(%q<nokogiri>, [">= 1.4.0"])
42
- s.add_dependency(%q<minitest>, [">= 1.7.1"])
43
- end
44
- else
45
- s.add_dependency(%q<eventmachine>, [">= 0.12.6"])
46
- s.add_dependency(%q<nokogiri>, [">= 1.4.0"])
47
- s.add_dependency(%q<minitest>, [">= 1.7.1"])
48
- end
29
+ s.add_development_dependency("minitest", ["~> 1.7.1"])
30
+ s.add_development_dependency("mocha", ["~> 0.9.12"])
31
+ s.add_development_dependency("bundler", ["~> 1.0.0"])
32
+ s.add_development_dependency("rcov", ["~> 0.9.9"])
33
+ s.add_development_dependency("yard", ["~> 0.6.1"])
34
+ s.add_development_dependency("bluecloth", ["~> 2.1.0"])
35
+ s.add_development_dependency("rake")
49
36
  end
data/examples/echo.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
3
4
  require 'blather/client'
4
5
 
5
6
  when_ready { puts "Connected ! send messages to #{jid.stripped}." }
data/examples/execute.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
3
4
  require 'blather/client'
4
5
 
5
6
  message :chat?, :body => 'exit' do |m|
@@ -1,3 +1,4 @@
1
+ require 'rubygems'
1
2
  require 'blather/client/dsl'
2
3
  $stdout.sync = true
3
4
 
@@ -1,3 +1,4 @@
1
+ require 'rubygems'
1
2
  require 'blather'
2
3
 
3
4
  class Object
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Prints out each roster entry
4
4
 
5
+ require 'rubygems'
5
6
  require 'blather/client'
6
7
 
7
8
  when_ready do
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
3
4
  require 'blather'
4
5
 
5
6
  trap(:INT) { EM.stop }
@@ -2,6 +2,7 @@
2
2
 
3
3
  # This bot will reply to every message it receives. To end the game, send 'exit'
4
4
 
5
+ require 'rubygems'
5
6
  require 'xmpp4r/client'
6
7
  include Jabber
7
8
 
data/lib/blather.rb CHANGED
@@ -8,7 +8,9 @@
8
8
  digest/sha1
9
9
  logger
10
10
 
11
- blather/core_ext/active_support
11
+ active_support/core_ext/class/inheritable_attributes
12
+ active_support/core_ext/object/blank
13
+
12
14
  blather/core_ext/eventmachine
13
15
  blather/core_ext/ipaddr
14
16
  blather/core_ext/nokogiri
@@ -37,6 +39,7 @@
37
39
  blather/stanza/disco
38
40
  blather/stanza/disco/disco_info
39
41
  blather/stanza/disco/disco_items
42
+ blather/stanza/disco/capabilities
40
43
  blather/stanza/message
41
44
  blather/stanza/presence
42
45
  blather/stanza/presence/c
@@ -72,6 +75,7 @@
72
75
  blather/stream/features/tls
73
76
  ].each { |r| require r }
74
77
 
78
+ # The core Blather namespace
75
79
  module Blather
76
80
  # @private
77
81
  @@logger = nil
@@ -57,11 +57,16 @@ module Blather
57
57
  @tmp_handlers = {}
58
58
  @filters = {:before => [], :after => []}
59
59
  @roster = Roster.new self
60
- @caps = Caps.new
60
+ @caps = Stanza::Capabilities.new
61
61
 
62
62
  setup_initial_handlers
63
63
  end
64
64
 
65
+ # Check whether the client is currently connected.
66
+ def connected?
67
+ setup? && !@stream.stopped?
68
+ end
69
+
65
70
  # Get the current status. Taken from the `state` attribute of Status
66
71
  def status
67
72
  @status.state
@@ -162,17 +167,20 @@ module Blather
162
167
  self.stream.close_connection_after_writing
163
168
  end
164
169
 
165
- def post_init(stream, jid = nil) # @private
170
+ # @private
171
+ def post_init(stream, jid = nil)
166
172
  @stream = stream
167
173
  @jid = JID.new(jid) if jid
168
174
  self.jid.node ? client_post_init : ready!
169
175
  end
170
176
 
171
- def unbind # @private
177
+ # @private
178
+ def unbind
172
179
  call_handler_for(:disconnected, nil) || (EM.reactor_running? && EM.stop)
173
180
  end
174
181
 
175
- def receive_data(stanza) # @private
182
+ # @private
183
+ def receive_data(stanza)
176
184
  catch(:halt) do
177
185
  run_filters :before, stanza
178
186
  handle_stanza stanza
@@ -180,11 +188,13 @@ module Blather
180
188
  end
181
189
  end
182
190
 
183
- def setup? # @private
191
+ # @private
192
+ def setup?
184
193
  @setup.is_a? Array
185
194
  end
186
195
 
187
- def setup(jid, password, host = nil, port = nil) # @private
196
+ # @private
197
+ def setup(jid, password, host = nil, port = nil)
188
198
  @jid = JID.new(jid)
189
199
  @setup = [@jid, password]
190
200
  @setup << host if host
@@ -192,21 +202,22 @@ module Blather
192
202
  self
193
203
  end
194
204
 
195
- protected
196
- def stream # @private
205
+ protected
206
+
207
+ def stream
197
208
  @stream || raise('Stream not ready!')
198
209
  end
199
210
 
200
- def check_handler(type, guards) # @private
211
+ def check_handler(type, guards)
201
212
  Blather.logger.warn "Handler for type \"#{type}\" will never be called as it's not a registered type" unless current_handlers.include?(type)
202
213
  check_guards guards
203
214
  end
204
215
 
205
- def current_handlers # @private
216
+ def current_handlers
206
217
  [:ready, :disconnected] + Stanza.handler_list + BlatherError.handler_list
207
218
  end
208
219
 
209
- def setup_initial_handlers # @private
220
+ def setup_initial_handlers
210
221
  register_handler :error do |err|
211
222
  raise err
212
223
  end
@@ -225,12 +236,12 @@ module Blather
225
236
  end
226
237
  end
227
238
 
228
- def ready! # @private
239
+ def ready!
229
240
  @state = :ready
230
241
  call_handler_for :ready, nil
231
242
  end
232
243
 
233
- def client_post_init # @private
244
+ def client_post_init
234
245
  write_with_handler Stanza::Iq::Roster.new do |node|
235
246
  roster.process node
236
247
  write @status
@@ -238,14 +249,14 @@ module Blather
238
249
  end
239
250
  end
240
251
 
241
- def run_filters(type, stanza) # @private
252
+ def run_filters(type, stanza)
242
253
  @filters[type].each do |guards, handler, filter|
243
254
  next if handler && !stanza.handler_hierarchy.include?(handler)
244
255
  catch(:pass) { call_handler filter, guards, stanza }
245
256
  end
246
257
  end
247
258
 
248
- def handle_stanza(stanza) # @private
259
+ def handle_stanza(stanza)
249
260
  if handler = @tmp_handlers.delete(stanza.id)
250
261
  handler.call stanza
251
262
  else
@@ -255,14 +266,14 @@ module Blather
255
266
  end
256
267
  end
257
268
 
258
- def call_handler_for(type, stanza) # @private
269
+ def call_handler_for(type, stanza)
259
270
  return unless handler = @handlers[type]
260
271
  handler.find do |guards, handler|
261
272
  catch(:pass) { call_handler handler, guards, stanza }
262
273
  end
263
274
  end
264
275
 
265
- def call_handler(handler, guards, stanza) # @private
276
+ def call_handler(handler, guards, stanza)
266
277
  if guards.first.respond_to?(:to_str)
267
278
  result = stanza.find(*guards)
268
279
  handler.call(stanza, result) unless result.empty?
@@ -303,7 +314,7 @@ module Blather
303
314
  end
304
315
  end
305
316
 
306
- def check_guards(guards) # @private
317
+ def check_guards(guards)
307
318
  guards.each do |guard|
308
319
  case guard
309
320
  when Array
@@ -315,142 +326,6 @@ module Blather
315
326
  end
316
327
  end
317
328
  end
318
-
319
- class Caps < Blather::Stanza::DiscoInfo
320
- def self.new
321
- super :result
322
- end
323
-
324
- def ver
325
- generate_ver identities, features
326
- end
327
-
328
- def node=(node)
329
- @bare_node = node
330
- super "#{node}##{ver}"
331
- end
332
-
333
- def identities=(identities)
334
- super identities
335
- regenerate_full_node
336
- end
337
-
338
- def features=(features)
339
- super features
340
- regenerate_full_node
341
- end
342
-
343
- def c
344
- Blather::Stanza::Presence::C.new @bare_node, ver
345
- end
346
-
347
- private
348
-
349
- def regenerate_full_node
350
- self.node = @bare_node
351
- end
352
-
353
- def generate_ver_str(identities, features, forms = [])
354
- # 1. Initialize an empty string S.
355
- s = ''
356
-
357
- # 2. Sort the service discovery identities by category and
358
- # then by type (if it exists) and then by xml:lang (if it
359
- # exists), formatted as CATEGORY '/' [TYPE] '/' [LANG] '/'
360
- # [NAME]. Note that each slash is included even if the TYPE,
361
- # LANG, or NAME is not included.
362
- identities.sort! do |identity1, identity2|
363
- cmp_result = nil
364
- [:category, :type, :xml_lang, :name].each do |field|
365
- value1 = identity1.send(field)
366
- value2 = identity2.send(field)
367
-
368
- if value1 != value2
369
- cmp_result = value1 <=> value2
370
- break
371
- end
372
- end
373
- cmp_result
374
- end
375
-
376
- # 3. For each identity, append the 'category/type/lang/name' to
377
- # S, followed by the '<' character.
378
- s += identities.collect do |identity|
379
- [:category, :type, :xml_lang, :name].collect do |field|
380
- identity.send(field).to_s
381
- end.join('/') + '<'
382
- end.join
383
-
384
- # 4. Sort the supported service discovery features.
385
- features.sort! { |feature1, feature2| feature1.var <=> feature2.var }
386
-
387
- # 5. For each feature, append the feature to S, followed by the
388
- # '<' character.
389
- s += features.collect { |feature| feature.var.to_s + '<' }.join
390
-
391
- # 6. If the service discovery information response includes
392
- # XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., by
393
- # the XML character data of the <value/> element).
394
- forms.sort! do |form1, form2|
395
- fform_type1 = form1.field 'FORM_TYPE'
396
- fform_type2 = form2.field 'FORM_TYPE'
397
- form_type1 = fform_type1 ? fform_type1.values.to_s : nil
398
- form_type2 = fform_type2 ? fform_type2.values.to_s : nil
399
- form_type1 <=> form_type2
400
- end
401
-
402
- # 7. For each extended service discovery information form:
403
- forms.each do |form|
404
- # 7.1. Append the XML character data of the FORM_TYPE field's
405
- # <value/> element, followed by the '<' character.
406
- fform_type = form.field 'FORM_TYPE'
407
- form_type = fform_type ? fform_type.values.to_s : nil
408
- s += "#{form_type}<"
409
-
410
- # 7.2. Sort the fields by the value of the "var" attribute
411
- fields = form.fields.sort { |field1, field2| field1.var <=> field2.var }
412
-
413
- # 7.3. For each field:
414
- fields.each do |field|
415
- # 7.3.1. Append the value of the "var" attribute, followed by
416
- # the '<' character.
417
- s += "#{field.var}<"
418
-
419
- # 7.3.2. Sort values by the XML character data of the <value/> element
420
- # values = field.values.sort { |value1, value2| value1 <=> value2 }
421
-
422
- # 7.3.3. For each <value/> element, append the XML character
423
- # data, followed by the '<' character.
424
- # s += values.collect { |value| "#{value}<" }.join
425
- s += "#{field.value}<"
426
- end
427
- end
428
- s
429
- end
430
-
431
- def generate_ver(identities, features, forms = [], hash = 'sha-1')
432
- s = generate_ver_str identities, features, forms
433
-
434
- # 9. Compute the verification string by hashing S using the
435
- # algorithm specified in the 'hash' attribute (e.g., SHA-1 as
436
- # defined in RFC 3174). The hashed data MUST be generated
437
- # with binary output and encoded using Base64 as specified in
438
- # Section 4 of RFC 4648 (note: the Base64 output MUST NOT
439
- # include whitespace and MUST set padding bits to zero).
440
-
441
- # See http://www.iana.org/assignments/hash-function-text-names
442
- hash_klass = case hash
443
- when 'md2' then nil
444
- when 'md5' then Digest::MD5
445
- when 'sha-1' then Digest::SHA1
446
- when 'sha-224' then nil
447
- when 'sha-256' then Digest::SHA256
448
- when 'sha-384' then Digest::SHA384
449
- when 'sha-512' then Digest::SHA512
450
- end
451
- hash_klass ? [hash_klass::digest(s)].pack('m').strip : nil
452
- end
453
- end # Caps
454
329
  end # Client
455
330
 
456
331
  end # Blather