blather 0.2 → 0.2.1

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.2.1 Upgrade to libxml 0.9.7
2
+
1
3
  v0.2 Overhaul the DSL to look more like Sinatra
2
4
 
3
5
  v0.1 Initial release (birth!)
data/Manifest CHANGED
@@ -3,6 +3,8 @@ examples/drb_client.rb
3
3
  examples/echo.rb
4
4
  lib/autotest/discover.rb
5
5
  lib/autotest/spec.rb
6
+ lib/blather/core_ext/active_support.rb
7
+ lib/blather/core_ext/libxml.rb
6
8
  lib/blather/errors.rb
7
9
  lib/blather/jid.rb
8
10
  lib/blather/roster.rb
@@ -22,7 +24,6 @@ lib/blather/stream/sasl.rb
22
24
  lib/blather/stream/session.rb
23
25
  lib/blather/stream/tls.rb
24
26
  lib/blather/stream.rb
25
- lib/blather/sugar.rb
26
27
  lib/blather/xmpp_node.rb
27
28
  lib/blather.rb
28
29
  LICENSE
data/README.rdoc CHANGED
@@ -46,7 +46,13 @@ This will auto-accept any subscription requests and echo back any chat messages.
46
46
  write(m.reply) if m.chat? && m.body
47
47
  end
48
48
 
49
-
49
+ = TODO
50
+
51
+ * Cleanup API
52
+ * Better Documentation
53
+ * Service Discovery (XEP-0030: http://xmpp.org/extensions/xep-0030.html)
54
+ * PubSub (XEP-0060: http://xmpp.org/extensions/xep-0060.html)
55
+ * ?? (suggestions)
50
56
 
51
57
  = License
52
58
 
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ Echoe.new('blather') do |p|
9
9
  p.project = 'squishtech'
10
10
  p.summary = 'An evented XMPP library written on EventMachine and libxml-ruby'
11
11
 
12
- p.runtime_dependencies = ['eventmachine', 'libxml-ruby >=0.9.2']
12
+ p.runtime_dependencies = ['eventmachine', 'libxml-ruby >=0.9.7']
13
13
  p.rdoc_options += %w[-S -T hanna --main README.rdoc --exclude autotest]
14
14
 
15
15
  p.test_pattern = 'spec/**/*_spec.rb'
data/blather.gemspec CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{blather}
5
- s.version = "0.2"
5
+ s.version = "0.2.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Jeff Smick"]
9
- s.date = %q{2008-12-19}
9
+ s.date = %q{2008-12-21}
10
10
  s.description = %q{An evented XMPP library written on EventMachine and libxml-ruby}
11
11
  s.email = %q{sprsquish@gmail.com}
12
- s.extra_rdoc_files = ["CHANGELOG", "lib/autotest/discover.rb", "lib/autotest/spec.rb", "lib/blather/errors.rb", "lib/blather/jid.rb", "lib/blather/roster.rb", "lib/blather/roster_item.rb", "lib/blather/stanza/error.rb", "lib/blather/stanza/iq/query.rb", "lib/blather/stanza/iq/roster.rb", "lib/blather/stanza/iq.rb", "lib/blather/stanza/message.rb", "lib/blather/stanza/presence/status.rb", "lib/blather/stanza/presence/subscription.rb", "lib/blather/stanza/presence.rb", "lib/blather/stanza.rb", "lib/blather/stream/parser.rb", "lib/blather/stream/resource.rb", "lib/blather/stream/sasl.rb", "lib/blather/stream/session.rb", "lib/blather/stream/tls.rb", "lib/blather/stream.rb", "lib/blather/sugar.rb", "lib/blather/xmpp_node.rb", "lib/blather.rb", "LICENSE", "README.rdoc"]
13
- s.files = ["CHANGELOG", "examples/drb_client.rb", "examples/echo.rb", "lib/autotest/discover.rb", "lib/autotest/spec.rb", "lib/blather/errors.rb", "lib/blather/jid.rb", "lib/blather/roster.rb", "lib/blather/roster_item.rb", "lib/blather/stanza/error.rb", "lib/blather/stanza/iq/query.rb", "lib/blather/stanza/iq/roster.rb", "lib/blather/stanza/iq.rb", "lib/blather/stanza/message.rb", "lib/blather/stanza/presence/status.rb", "lib/blather/stanza/presence/subscription.rb", "lib/blather/stanza/presence.rb", "lib/blather/stanza.rb", "lib/blather/stream/parser.rb", "lib/blather/stream/resource.rb", "lib/blather/stream/sasl.rb", "lib/blather/stream/session.rb", "lib/blather/stream/tls.rb", "lib/blather/stream.rb", "lib/blather/sugar.rb", "lib/blather/xmpp_node.rb", "lib/blather.rb", "LICENSE", "Manifest", "Rakefile", "README.rdoc", "spec/blather/jid_spec.rb", "spec/blather/roster_item_spec.rb", "spec/blather/roster_spec.rb", "spec/blather/stanza/iq/query_spec.rb", "spec/blather/stanza/iq/roster_spec.rb", "spec/blather/stanza/iq_spec.rb", "spec/blather/stanza/message_spec.rb", "spec/blather/stanza/presence/status_spec.rb", "spec/blather/stanza/presence/subscription_spec.rb", "spec/blather/stanza/presence_spec.rb", "spec/blather/stanza_spec.rb", "spec/blather/stream_spec.rb", "spec/blather/xmpp_node_spec.rb", "spec/build_safe.rb", "spec/spec_helper.rb", "blather.gemspec"]
12
+ s.extra_rdoc_files = ["CHANGELOG", "lib/autotest/discover.rb", "lib/autotest/spec.rb", "lib/blather/core_ext/active_support.rb", "lib/blather/core_ext/libxml.rb", "lib/blather/errors.rb", "lib/blather/jid.rb", "lib/blather/roster.rb", "lib/blather/roster_item.rb", "lib/blather/stanza/error.rb", "lib/blather/stanza/iq/query.rb", "lib/blather/stanza/iq/roster.rb", "lib/blather/stanza/iq.rb", "lib/blather/stanza/message.rb", "lib/blather/stanza/presence/status.rb", "lib/blather/stanza/presence/subscription.rb", "lib/blather/stanza/presence.rb", "lib/blather/stanza.rb", "lib/blather/stream/parser.rb", "lib/blather/stream/resource.rb", "lib/blather/stream/sasl.rb", "lib/blather/stream/session.rb", "lib/blather/stream/tls.rb", "lib/blather/stream.rb", "lib/blather/xmpp_node.rb", "lib/blather.rb", "LICENSE", "README.rdoc"]
13
+ s.files = ["CHANGELOG", "examples/drb_client.rb", "examples/echo.rb", "lib/autotest/discover.rb", "lib/autotest/spec.rb", "lib/blather/core_ext/active_support.rb", "lib/blather/core_ext/libxml.rb", "lib/blather/errors.rb", "lib/blather/jid.rb", "lib/blather/roster.rb", "lib/blather/roster_item.rb", "lib/blather/stanza/error.rb", "lib/blather/stanza/iq/query.rb", "lib/blather/stanza/iq/roster.rb", "lib/blather/stanza/iq.rb", "lib/blather/stanza/message.rb", "lib/blather/stanza/presence/status.rb", "lib/blather/stanza/presence/subscription.rb", "lib/blather/stanza/presence.rb", "lib/blather/stanza.rb", "lib/blather/stream/parser.rb", "lib/blather/stream/resource.rb", "lib/blather/stream/sasl.rb", "lib/blather/stream/session.rb", "lib/blather/stream/tls.rb", "lib/blather/stream.rb", "lib/blather/xmpp_node.rb", "lib/blather.rb", "LICENSE", "Manifest", "Rakefile", "README.rdoc", "spec/blather/jid_spec.rb", "spec/blather/roster_item_spec.rb", "spec/blather/roster_spec.rb", "spec/blather/stanza/iq/query_spec.rb", "spec/blather/stanza/iq/roster_spec.rb", "spec/blather/stanza/iq_spec.rb", "spec/blather/stanza/message_spec.rb", "spec/blather/stanza/presence/status_spec.rb", "spec/blather/stanza/presence/subscription_spec.rb", "spec/blather/stanza/presence_spec.rb", "spec/blather/stanza_spec.rb", "spec/blather/stream_spec.rb", "spec/blather/xmpp_node_spec.rb", "spec/build_safe.rb", "spec/spec_helper.rb", "blather.gemspec"]
14
14
  s.has_rdoc = true
15
15
  s.homepage = %q{http://github.com/sprsquish/blather/tree/master}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Blather", "--main", "README.rdoc", "-S", "-T", "hanna", "--main", "README.rdoc", "--exclude", "autotest"]
@@ -26,16 +26,16 @@ Gem::Specification.new do |s|
26
26
 
27
27
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
28
  s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
29
- s.add_runtime_dependency(%q<libxml-ruby>, [">= 0.9.2"])
29
+ s.add_runtime_dependency(%q<libxml-ruby>, [">= 0.9.7"])
30
30
  s.add_development_dependency(%q<echoe>, [">= 0"])
31
31
  else
32
32
  s.add_dependency(%q<eventmachine>, [">= 0"])
33
- s.add_dependency(%q<libxml-ruby>, [">= 0.9.2"])
33
+ s.add_dependency(%q<libxml-ruby>, [">= 0.9.7"])
34
34
  s.add_dependency(%q<echoe>, [">= 0"])
35
35
  end
36
36
  else
37
37
  s.add_dependency(%q<eventmachine>, [">= 0"])
38
- s.add_dependency(%q<libxml-ruby>, [">= 0.9.2"])
38
+ s.add_dependency(%q<libxml-ruby>, [">= 0.9.7"])
39
39
  s.add_dependency(%q<echoe>, [">= 0"])
40
40
  end
41
41
  end
data/lib/blather.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
+ # Require the necessary files
3
4
  %w[
4
5
  rubygems
5
6
  xml/libxml
@@ -7,11 +8,13 @@ $:.unshift File.dirname(__FILE__)
7
8
  digest/md5
8
9
  logger
9
10
 
11
+ blather/core_ext/active_support
12
+ blather/core_ext/libxml
13
+
10
14
  blather/errors
11
15
  blather/jid
12
16
  blather/roster
13
17
  blather/roster_item
14
- blather/sugar
15
18
  blather/xmpp_node
16
19
 
17
20
  blather/stanza
@@ -36,6 +39,8 @@ XML.indent_tree_output = false
36
39
 
37
40
  module Blather
38
41
  LOG = Logger.new(STDOUT)
42
+ Stream::Parser.debug = true
43
+ # LOG.level = Logger::INFO
39
44
 
40
45
  class Client
41
46
  attr_accessor :jid,
@@ -1,22 +1,9 @@
1
- module LibXML # :nodoc:
2
- module XML # :nodoc:
1
+ # Thanks to Rails ActiveSupport for everything in this file
3
2
 
4
- class Node
5
- alias_method :element_name, :name
6
- end
7
-
8
- class Attributes
9
- # Helper method for removing attributes
10
- def remove(name)
11
- name = name.to_s
12
- self.each { |a| a.remove! or break if a.name == name }
13
- end
14
- end #Attributes
15
-
16
- end #XML
17
- end #LibXML
18
-
19
- ## Thanks to ActiveSupport for everything below this line
3
+ # Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
4
+ # their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
5
+ # to, for example, an array without those additions being shared with either their parent, siblings, or
6
+ # children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
20
7
  class Class # :nodoc:
21
8
  def class_inheritable_reader(*syms)
22
9
  syms.each do |sym|
@@ -131,18 +118,35 @@ end #Class
131
118
 
132
119
  class Object # :nodoc:
133
120
  def duplicable?; true; end
121
+ def blank?; respond_to?(:empty?) ? empty? : !self; end
122
+ def present?; !blank?; end
123
+ end
124
+
125
+ class Array #:nodoc:
126
+ alias_method :blank?, :empty?
127
+ end
128
+
129
+ class Hash #:nodoc:
130
+ alias_method :blank?, :empty?
131
+ end
132
+
133
+ class String #:nodoc:
134
+ def blank?; self !~ /\S/; end
134
135
  end
135
136
 
136
137
  class NilClass #:nodoc:
137
138
  def duplicable?; false; end
139
+ def blank?; true; end
138
140
  end
139
141
 
140
142
  class FalseClass #:nodoc:
141
143
  def duplicable?; false; end
144
+ def blank?; true; end
142
145
  end
143
146
 
144
147
  class TrueClass #:nodoc:
145
148
  def duplicable?; false; end
149
+ def blank?; false; end
146
150
  end
147
151
 
148
152
  class Symbol #:nodoc:
@@ -151,4 +155,5 @@ end
151
155
 
152
156
  class Numeric #:nodoc:
153
157
  def duplicable?; false; end
158
+ def blank?; false; end
154
159
  end
@@ -0,0 +1,22 @@
1
+ module LibXML # :nodoc:
2
+ module XML # :nodoc:
3
+
4
+ class Node
5
+ alias_method :element_name, :name
6
+ end
7
+
8
+ class Attributes
9
+ # Helper method for removing attributes
10
+ def remove(name)
11
+ attribute = get_attribute(name.to_s)
12
+ attribute.remove! if attribute
13
+ end
14
+
15
+ alias_method :old_hash_set, :[]=
16
+ def []=(name, val)
17
+ val.nil? ? remove(name.to_s) : old_hash_set(name.to_s, val.to_s)
18
+ end
19
+ end #Attributes
20
+
21
+ end #XML
22
+ end #LibXML
@@ -2,6 +2,9 @@ module Blather
2
2
  # Main error class
3
3
  class BlatherError < StandardError; end
4
4
 
5
+ #Parse Errors
6
+ class ParseError < BlatherError; end
7
+
5
8
  # Stream errors
6
9
  class StreamError < BlatherError
7
10
  attr_accessor :type, :text
@@ -2,6 +2,8 @@ module Blather
2
2
  ##
3
3
  # Base XMPP Stanza
4
4
  class Stanza < XMPPNode
5
+ @@last_id = 0
6
+
5
7
  class_inheritable_array :handler_heirarchy
6
8
 
7
9
  ##
@@ -22,7 +24,6 @@ module Blather
22
24
  ##
23
25
  # Helper method that creates a unique ID for stanzas
24
26
  def self.next_id
25
- @@last_id ||= 0
26
27
  @@last_id += 1
27
28
  'blather%04x' % @@last_id
28
29
  end
@@ -35,15 +36,17 @@ module Blather
35
36
  end
36
37
 
37
38
  ##
38
- # Creates a new Stanza with the name given
39
- # then attaches an ID and document (to enable searching)
40
- def self.new(elem_name = nil)
41
- elem = super
42
- elem.id = next_id
43
- XML::Document.new.root = elem
44
- elem
39
+ # Automatically set the stanza's ID
40
+ # and attach it to a document so XPath searching works
41
+ def initialize(name = nil)
42
+ super
43
+ XML::Document.new.root = self
44
+ self.name = name.to_s if name
45
+ self.id = self.class.next_id
45
46
  end
46
47
 
48
+ ##
49
+ # Helper method to ask the object if it's an error
47
50
  def error?
48
51
  self.type == :error
49
52
  end
@@ -63,45 +66,41 @@ module Blather
63
66
  end
64
67
 
65
68
  def id=(id)
66
- attributes.remove :id
67
- self['id'] = id if id
69
+ attributes['id'] = id
68
70
  end
69
71
 
70
72
  def id
71
- self['id']
73
+ attributes['id']
72
74
  end
73
75
 
74
76
  def to=(to)
75
- attributes.remove :to
76
- self['to'] = to.to_s if to
77
+ attributes['to'] = to
77
78
  end
78
79
 
79
80
  ##
80
81
  # returns:: JID created from the "to" value of the stanza
81
82
  def to
82
- JID.new(self['to']) if self['to']
83
+ JID.new(attributes['to']) if attributes['to']
83
84
  end
84
85
 
85
86
  def from=(from)
86
- attributes.remove :from
87
- self['from'] = from.to_s if from
87
+ attributes['from'] = from
88
88
  end
89
89
 
90
90
  ##
91
91
  # returns:: JID created from the "from" value of the stanza
92
92
  def from
93
- JID.new(self['from']) if self['from']
93
+ JID.new(attributes['from']) if attributes['from']
94
94
  end
95
95
 
96
96
  def type=(type)
97
- attributes.remove :type
98
- self['type'] = type.to_s
97
+ attributes['type'] = type
99
98
  end
100
99
 
101
100
  ##
102
101
  # returns:: a symbol of the type
103
102
  def type
104
- self['type'].to_sym unless self['type'].nil? || self['type'].empty?
103
+ attributes['type'].to_sym unless attributes['type'].blank?
105
104
  end
106
105
 
107
106
  end
@@ -13,13 +13,12 @@ class Stanza
13
13
  (klass || self).new(node['type']).inherit(node)
14
14
  end
15
15
 
16
- def self.new(type = nil, to = nil, id = nil)
17
- elem = super :iq
18
- elem.xmlns = nil
19
- elem.type = type || :get
20
- elem.to = to
21
- elem.id = id if id
22
- elem
16
+ def initialize(type = nil, to = nil, id = nil)
17
+ super :iq
18
+ self.xmlns = nil
19
+ self.type = type || :get
20
+ self.to = to
21
+ self.id = id if id
23
22
  end
24
23
  end
25
24
 
@@ -7,10 +7,9 @@ class Iq
7
7
 
8
8
  ##
9
9
  # Ensure the namespace is set to the query node
10
- def self.new(type = nil)
11
- elem = super
12
- elem.query.xmlns = self.xmlns
13
- elem
10
+ def initialize(type = nil)
11
+ super
12
+ query.xmlns = self.class.xmlns
14
13
  end
15
14
 
16
15
  ##
@@ -5,10 +5,9 @@ class Iq
5
5
  class Roster < Query
6
6
  register :roster, nil, 'jabber:iq:roster'
7
7
 
8
- def self.new(type = nil, item = nil)
9
- elem = super(type)
10
- elem.query << item if item
11
- elem
8
+ def initialize(type = nil, item = nil)
9
+ super(type)
10
+ query << item if item
12
11
  end
13
12
 
14
13
  def inherit(node)
@@ -25,53 +24,48 @@ class Iq
25
24
  end
26
25
 
27
26
  class RosterItem < XMPPNode
28
- def self.new(jid = nil, name = nil, subscription = nil, ask = nil)
29
- elem = super('item')
27
+ def initialize(jid = nil, name = nil, subscription = nil, ask = nil)
28
+ super('item')
30
29
  if jid.is_a?(XML::Node)
31
- elem.inherit jid
30
+ self.inherit jid
32
31
  else
33
- elem.jid = jid
34
- elem.name = name
35
- elem.subscription = subscription
36
- elem.ask = ask
32
+ self.jid = jid
33
+ self.name = name
34
+ self.subscription = subscription
35
+ self.ask = ask
37
36
  end
38
- elem
39
37
  end
40
38
 
41
39
  def jid
42
- (j = self['jid']) ? JID.new(j) : nil
40
+ (j = attributes['jid']) ? JID.new(j) : nil
43
41
  end
44
42
 
45
43
  def jid=(jid)
46
- attributes.remove :jid
47
- self['jid'] = jid.to_s if jid
44
+ attributes['jid'] = jid
48
45
  end
49
46
 
50
47
  def name
51
- self['name']
48
+ attributes['name']
52
49
  end
53
50
 
54
51
  def name=(name)
55
- attributes.remove :name
56
- self['name'] = name if name
52
+ attributes['name'] = name
57
53
  end
58
54
 
59
55
  def subscription
60
- self['subscription'].to_sym if self['subscription']
56
+ attributes['subscription'].to_sym if attributes['subscription']
61
57
  end
62
58
 
63
59
  def subscription=(subscription)
64
- attributes.remove :subscription
65
- self['subscription'] = subscription.to_s if subscription
60
+ attributes['subscription'] = subscription
66
61
  end
67
62
 
68
63
  def ask
69
- self['ask'].to_sym if self['ask']
64
+ attributes['ask'].to_sym if attributes['ask']
70
65
  end
71
66
 
72
67
  def ask=(ask)
73
- attributes.remove :ask
74
- self['ask'] = ask if ask
68
+ attributes['ask'] = ask
75
69
  end
76
70
 
77
71
  def groups
@@ -82,7 +76,7 @@ class Iq
82
76
  find('group').each { |g| g.remove! }
83
77
  @groups = nil
84
78
 
85
- grps.uniq.each { |g| add_node XML::Node.new('group', g.to_s) } if grps
79
+ grps.uniq.each { |g| add_node XMPPNode.new('group', g.to_s) } if grps
86
80
  end
87
81
 
88
82
  def to_stanza
@@ -8,12 +8,11 @@ class Stanza
8
8
 
9
9
  register :message
10
10
 
11
- def self.new(to = nil, body = nil, type = :chat)
12
- elem = super()
13
- elem.to = to
14
- elem.type = type
15
- elem.body = body
16
- elem
11
+ def initialize(to = nil, body = nil, type = :chat)
12
+ super()
13
+ self.to = to
14
+ self.type = type
15
+ self.body = body
17
16
  end
18
17
 
19
18
  VALID_TYPES.each do |valid_type|
@@ -8,12 +8,6 @@ class Stanza
8
8
 
9
9
  register :presence
10
10
 
11
- ##
12
- # Ensure element_name is "presence" for all subclasses
13
- def self.new
14
- super :presence
15
- end
16
-
17
11
  ##
18
12
  # Creates a class based on the presence type
19
13
  # either a Status or Subscription object is created based
@@ -28,6 +22,12 @@ class Stanza
28
22
  klass.new.inherit(node)
29
23
  end
30
24
 
25
+ ##
26
+ # Ensure element_name is "presence" for all subclasses
27
+ def initialize
28
+ super :presence
29
+ end
30
+
31
31
  VALID_TYPES.each do |valid_type|
32
32
  define_method("#{valid_type}?") { self.type == valid_type }
33
33
  end
@@ -9,11 +9,10 @@ class Presence
9
9
 
10
10
  register :status, :status
11
11
 
12
- def self.new(state = nil, message = nil)
13
- elem = super()
14
- elem.state = state
15
- elem.message = message
16
- elem
12
+ def initialize(state = nil, message = nil)
13
+ super()
14
+ self.state = state
15
+ self.message = message
17
16
  end
18
17
 
19
18
  ##
@@ -5,11 +5,10 @@ class Presence
5
5
  class Subscription < Presence
6
6
  register :subscription, :subscription
7
7
 
8
- def self.new(to = nil, type = nil)
9
- elem = super()
10
- elem.to = to
11
- elem.type = type
12
- elem
8
+ def initialize(to = nil, type = nil)
9
+ super()
10
+ self.to = to
11
+ self.type = type
13
12
  end
14
13
 
15
14
  def inherit(node)
@@ -3,6 +3,7 @@ module Stream # :nodoc:
3
3
 
4
4
  class Parser # :nodoc:
5
5
  STREAM_REGEX = %r{(/)?stream:stream}.freeze
6
+ ERROR_REGEX = /^<(stream:[a-z]+)/.freeze
6
7
 
7
8
  @@debug = false
8
9
  def self.debug; @@debug; end
@@ -15,6 +16,7 @@ module Stream # :nodoc:
15
16
  @current = nil
16
17
 
17
18
  @parser = XML::SaxParser.new
19
+ @parser.io = StringIO.new
18
20
  @parser.callbacks = self
19
21
  end
20
22
 
@@ -24,16 +26,19 @@ module Stream # :nodoc:
24
26
  @receiver.receive XMPPNode.new('stream:end')
25
27
  else
26
28
  string << "</stream:stream>" if string =~ STREAM_REGEX && !$1
29
+ string.gsub!(ERROR_REGEX, "<\\1 xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'")
27
30
 
28
31
  @parser.string = string
29
32
  @parser.parse
30
33
  end
31
34
  end
32
35
 
33
- def on_start_element(elem, attrs)
34
- LOG.debug "START ELEM: (#{[elem, attrs].inspect})" if @@debug
36
+ NON_ATTRS = [nil, 'stream'].freeze
37
+ def on_start_element_ns(elem, attrs, prefix, uri, namespaces)
38
+ LOG.debug "START ELEM: (#{{:elem => elem, :attrs => attrs, :prefix => prefix, :ns => namespaces}.inspect})" if @@debug
39
+ elem = "#{"#{prefix}:" if prefix}#{elem}"
35
40
  e = XMPPNode.new elem
36
- attrs.each { |n,v| e[n] = v }
41
+ attrs.each { |n,v| n = "xmlns#{":#{n}" if n}" if NON_ATTRS.include?(n); e.attributes[n] = v }
37
42
 
38
43
  if elem == 'stream:stream'
39
44
  @receiver.receive e
@@ -50,10 +55,12 @@ module Stream # :nodoc:
50
55
  @current << XML::Node.new_text(chars) if @current
51
56
  end
52
57
 
53
- def on_end_element(elem)
58
+ def on_end_element_ns(elem, prefix, uri)
59
+ LOG.debug "END ELEM: #{{:elem => elem, :prefix => prefix, :uri => uri, :current => @current}.inspect}" if @@debug
60
+
61
+ elem = "#{"#{prefix}:" if prefix}#{elem}"
54
62
  return if elem =~ STREAM_REGEX
55
63
 
56
- LOG.debug "END ELEM: (#{@current}) #{elem}" if @@debug
57
64
  if @current.parent?
58
65
  @current = @current.parent
59
66
 
@@ -62,6 +69,10 @@ module Stream # :nodoc:
62
69
  @receiver.receive c
63
70
 
64
71
  end
72
+
73
+ def on_error(msg)
74
+ raise Blather::ParseError, msg.to_s
75
+ end
65
76
  end
66
77
  end #Parser
67
78
 
@@ -18,7 +18,11 @@ module Stream # :nodoc:
18
18
  end
19
19
 
20
20
  def init_callbacks
21
- @callbacks['mechanisms'] = proc { @mechanisms = @node.children; set_mechanism; authenticate }
21
+ @callbacks['mechanisms'] = proc {
22
+ @mechanisms = @node.children
23
+ set_mechanism
24
+ authenticate
25
+ }
22
26
  end
23
27
 
24
28
  def set_mechanism
@@ -10,20 +10,6 @@ module Blather
10
10
  class_inheritable_accessor :xmlns,
11
11
  :name
12
12
 
13
- ##
14
- # Automatically sets the namespace registered by the subclass
15
- def self.new(name = nil, content = nil)
16
- name ||= self.name
17
-
18
- args = []
19
- args << name.to_s if name
20
- args << content if content
21
-
22
- elem = super *args
23
- elem.xmlns = xmlns
24
- elem
25
- end
26
-
27
13
  ##
28
14
  # Lets a subclass register itself
29
15
  #
@@ -56,6 +42,16 @@ module Blather
56
42
  end
57
43
  end
58
44
 
45
+ ##
46
+ # Automatically sets the namespace registered by the subclass
47
+ def initialize(name = nil, content = nil)
48
+ name ||= self.class.name
49
+ content = content.to_s if content
50
+
51
+ super name.to_s, content
52
+ self.xmlns = self.class.xmlns
53
+ end
54
+
59
55
  ##
60
56
  # Quickway of turning itself into a proper object
61
57
  def to_stanza
@@ -63,12 +59,11 @@ module Blather
63
59
  end
64
60
 
65
61
  def xmlns=(ns)
66
- attributes.remove :xmlns
67
- self['xmlns'] = ns if ns
62
+ attributes['xmlns'] = ns
68
63
  end
69
64
 
70
65
  def xmlns
71
- self['xmlns']
66
+ attributes['xmlns']
72
67
  end
73
68
 
74
69
  ##
@@ -52,7 +52,7 @@ describe 'Blather::Stream' do
52
52
 
53
53
  stream.expects(:send_data).with do |val|
54
54
  val.must_match(/stream:stream/)
55
- stream.receive_data "<stream:stream><message to='a@b/c' from='d@e/f' type='chat' xml:lang='en'><body>Message!</body></message>"
55
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><message to='a@b/c' from='d@e/f' type='chat' xml:lang='en'><body>Message!</body></message>"
56
56
  end
57
57
  stream.connection_completed
58
58
  end
@@ -60,7 +60,7 @@ describe 'Blather::Stream' do
60
60
  it 'puts itself in the stopped state when unbound' do
61
61
  stream = mock_stream do |val|
62
62
  val.must_match(/stream:stream/)
63
- stream.receive_data "<stream:stream>"
63
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
64
64
 
65
65
  stream.stopped?.wont_equal true
66
66
  stream.unbind
@@ -94,7 +94,7 @@ describe 'Blather::Stream' do
94
94
  end
95
95
  end
96
96
  stream.connection_completed
97
- stream.receive_data "<stream:stream><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
97
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
98
98
  end
99
99
 
100
100
  it 'raises an error when it receives stream:error' do
@@ -123,7 +123,7 @@ describe 'Blather::Stream' do
123
123
  end
124
124
  end
125
125
  stream.connection_completed
126
- stream.receive_data "<stream:stream><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
126
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
127
127
  end.must_raise(StreamError)
128
128
  end
129
129
 
@@ -145,7 +145,7 @@ describe 'Blather::Stream' do
145
145
  end
146
146
  end
147
147
  stream.connection_completed
148
- stream.receive_data "<stream:stream><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
148
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
149
149
  end
150
150
 
151
151
  it 'connects via SASL MD5 when asked' do
@@ -161,7 +161,7 @@ describe 'Blather::Stream' do
161
161
  when nil
162
162
  val.must_match(/stream:stream/)
163
163
  state = :started
164
- stream.receive_data "<stream:stream><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>"
164
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>"
165
165
  true
166
166
 
167
167
  when :started
@@ -206,7 +206,7 @@ describe 'Blather::Stream' do
206
206
  when nil
207
207
  val.must_match(/stream:stream/)
208
208
  state = :started
209
- stream.receive_data "<stream:stream><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms></stream:features>"
209
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms></stream:features>"
210
210
  true
211
211
 
212
212
  when :started
@@ -239,7 +239,7 @@ describe 'Blather::Stream' do
239
239
  when nil
240
240
  val.must_match(/stream:stream/)
241
241
  state = :started
242
- stream.receive_data "<stream:stream><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
242
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
243
243
  true
244
244
 
245
245
  when :started
@@ -272,7 +272,7 @@ describe 'Blather::Stream' do
272
272
  when nil
273
273
  val.must_match(/stream:stream/)
274
274
  state = :started
275
- stream.receive_data "<stream:stream><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
275
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
276
276
  true
277
277
 
278
278
  when :started
@@ -317,7 +317,7 @@ describe 'Blather::Stream' do
317
317
  when nil
318
318
  val.must_match(/stream:stream/)
319
319
  state = :started
320
- stream.receive_data "<stream:stream><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
320
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
321
321
  true
322
322
 
323
323
  when :started
@@ -356,7 +356,7 @@ describe 'Blather::Stream' do
356
356
  state = :started
357
357
  val.must_match(/stream:stream/)
358
358
  lambda do
359
- stream.receive_data "<stream:stream><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>UNKNOWN</mechanism></mechanisms></stream:features>"
359
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>UNKNOWN</mechanism></mechanisms></stream:features>"
360
360
  end.must_raise(Stream::SASL::UnknownMechanism)
361
361
 
362
362
  else
@@ -380,11 +380,11 @@ describe 'Blather::Stream' do
380
380
  when nil
381
381
  val.must_match(/stream:stream/)
382
382
  state = :started
383
- stream.receive_data "<stream:stream><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></stream:features>"
383
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></stream:features>"
384
384
  true
385
385
 
386
386
  when :started
387
- val.must_match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"\s*/>})
387
+ val.must_match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>})
388
388
  val =~ %r{<iq[^>]+id="([^"]+)"}
389
389
  state = :complete
390
390
  stream.receive_data "<iq type='result' id='#{$1}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{jid}/server_resource</jid></bind></iq>"
@@ -412,7 +412,7 @@ describe 'Blather::Stream' do
412
412
  when nil
413
413
  val.must_match(/stream:stream/)
414
414
  state = :started
415
- stream.receive_data "<stream:stream><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></stream:features>"
415
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></stream:features>"
416
416
  true
417
417
 
418
418
  when :started
@@ -443,7 +443,7 @@ describe 'Blather::Stream' do
443
443
  when nil
444
444
  val.must_match(/stream:stream/)
445
445
  state = :started
446
- stream.receive_data "<stream:stream><stream:features><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></stream:features>"
446
+ stream.receive_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></stream:features>"
447
447
  true
448
448
 
449
449
  when :started
data/spec/spec_helper.rb CHANGED
@@ -33,9 +33,7 @@ end
33
33
 
34
34
  class Object
35
35
  def must_change *args, &block
36
- return MiniTest::Spec.current.assert_change(*args, &self) if Proc === self
37
- return MiniTest::Spec.current.assert_change(args.first, self) if args.size == 1
38
- return MiniTest::Spec.current.assert_change(self, *args)
36
+ return MiniTest::Spec.current.assert_change(*args, &self)
39
37
  end
40
38
  end
41
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blather
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.2"
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Smick
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-19 00:00:00 -08:00
12
+ date: 2008-12-21 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.9.2
33
+ version: 0.9.7
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: echoe
@@ -52,6 +52,8 @@ extra_rdoc_files:
52
52
  - CHANGELOG
53
53
  - lib/autotest/discover.rb
54
54
  - lib/autotest/spec.rb
55
+ - lib/blather/core_ext/active_support.rb
56
+ - lib/blather/core_ext/libxml.rb
55
57
  - lib/blather/errors.rb
56
58
  - lib/blather/jid.rb
57
59
  - lib/blather/roster.rb
@@ -71,7 +73,6 @@ extra_rdoc_files:
71
73
  - lib/blather/stream/session.rb
72
74
  - lib/blather/stream/tls.rb
73
75
  - lib/blather/stream.rb
74
- - lib/blather/sugar.rb
75
76
  - lib/blather/xmpp_node.rb
76
77
  - lib/blather.rb
77
78
  - LICENSE
@@ -82,6 +83,8 @@ files:
82
83
  - examples/echo.rb
83
84
  - lib/autotest/discover.rb
84
85
  - lib/autotest/spec.rb
86
+ - lib/blather/core_ext/active_support.rb
87
+ - lib/blather/core_ext/libxml.rb
85
88
  - lib/blather/errors.rb
86
89
  - lib/blather/jid.rb
87
90
  - lib/blather/roster.rb
@@ -101,7 +104,6 @@ files:
101
104
  - lib/blather/stream/session.rb
102
105
  - lib/blather/stream/tls.rb
103
106
  - lib/blather/stream.rb
104
- - lib/blather/sugar.rb
105
107
  - lib/blather/xmpp_node.rb
106
108
  - lib/blather.rb
107
109
  - LICENSE