jabber4r-revive 0.9.0 → 0.10.0

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 (45) hide show
  1. data/.gitignore +5 -4
  2. data/.rspec +3 -3
  3. data/.travis.yml +7 -7
  4. data/CHANGELOG +11 -1
  5. data/Gemfile +3 -3
  6. data/README.md +29 -29
  7. data/Rakefile +70 -70
  8. data/jabber4r-revive.gemspec +25 -25
  9. data/lib/jabber4r.rb +38 -33
  10. data/lib/jabber4r/bosh.rb +21 -0
  11. data/lib/jabber4r/bosh/authentication.rb +13 -0
  12. data/lib/jabber4r/bosh/authentication/non_sasl.rb +219 -0
  13. data/lib/jabber4r/bosh/authentication/sasl.rb +239 -0
  14. data/lib/jabber4r/bosh/session.rb +144 -0
  15. data/lib/jabber4r/connection.rb +259 -258
  16. data/lib/jabber4r/debugger.rb +60 -60
  17. data/lib/jabber4r/jid.rb +20 -19
  18. data/lib/jabber4r/protocol.rb +249 -257
  19. data/lib/jabber4r/protocol/authentication.rb +14 -0
  20. data/lib/jabber4r/protocol/authentication/non_sasl.rb +138 -0
  21. data/lib/jabber4r/protocol/authentication/sasl.rb +88 -0
  22. data/lib/jabber4r/protocol/iq.rb +259 -259
  23. data/lib/jabber4r/protocol/message.rb +245 -245
  24. data/lib/jabber4r/protocol/parsed_xml_element.rb +207 -207
  25. data/lib/jabber4r/protocol/presence.rb +160 -160
  26. data/lib/jabber4r/protocol/xml_element.rb +143 -143
  27. data/lib/jabber4r/rexml_1.8_patch.rb +15 -15
  28. data/lib/jabber4r/roster.rb +38 -38
  29. data/lib/jabber4r/session.rb +615 -615
  30. data/lib/jabber4r/version.rb +10 -3
  31. data/spec/lib/jabber4r/bosh/authentication/non_sasl_spec.rb +79 -0
  32. data/spec/lib/jabber4r/bosh/authentication/sasl_spec.rb +42 -0
  33. data/spec/lib/jabber4r/bosh/session_spec.rb +406 -0
  34. data/spec/lib/jabber4r/bosh_spec.rb +0 -0
  35. data/spec/lib/jabber4r/connection_spec.rb +174 -174
  36. data/spec/lib/jabber4r/debugger_spec.rb +35 -35
  37. data/spec/lib/jabber4r/jid_spec.rb +197 -197
  38. data/spec/lib/jabber4r/protocol/authentication/non_sasl_spec.rb +79 -0
  39. data/spec/lib/jabber4r/protocol/authentication/sasl_spec.rb +42 -0
  40. data/spec/spec_helper.rb +11 -11
  41. data/spec/support/mocks/tcp_socket_mock.rb +8 -8
  42. metadata +61 -45
  43. data/Gemfile.lock +0 -45
  44. data/lib/jabber4r/bosh_session.rb +0 -224
  45. data/spec/lib/jabber4r/bosh_session_spec.rb +0 -150
@@ -1,61 +1,61 @@
1
- # coding: utf-8
2
-
3
- # License: see LICENSE
4
- # Jabber4R - Jabber Instant Messaging Library for Ruby
5
- # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
- # Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
7
-
8
- require "singleton"
9
- require "logger"
10
-
11
- module Jabber
12
- # Produces debug methods
13
- #
14
- # Example
15
- #
16
- # def warn(message)
17
- # Debug.instance.send(:warn, message)
18
- # end
19
- # module_function m
20
- [:warn, :debug, :info].each do |m|
21
- define_method(m) do |message|
22
- Debugger.send(m, message)
23
- end
24
- module_function m
25
- end
26
-
27
- class Debugger
28
- include Singleton
29
-
30
- attr_accessor :enabled, :logger
31
-
32
- def initialize
33
- @logger = Logger.new(STDOUT)
34
- @enabled = false
35
- end
36
-
37
- class << self
38
- def logger=(logger)
39
- instance.logger = logger
40
- end
41
-
42
- def enable!
43
- instance.enabled = true
44
- end
45
-
46
- def disable!
47
- instance.enabled = false
48
- end
49
-
50
- def enabled?
51
- instance.enabled
52
- end
53
-
54
- [:warn, :debug, :info].each do |m|
55
- define_method(m) do |message|
56
- enabled? && instance.logger.send(m, message)
57
- end
58
- end
59
- end # class << self
60
- end
1
+ # coding: utf-8
2
+
3
+ # License: see LICENSE
4
+ # Jabber4R - Jabber Instant Messaging Library for Ruby
5
+ # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+ # Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
7
+
8
+ require "singleton"
9
+ require "logger"
10
+
11
+ module Jabber
12
+ # Produces debug methods
13
+ #
14
+ # Example
15
+ #
16
+ # def warn(message)
17
+ # Debug.instance.send(:warn, message)
18
+ # end
19
+ # module_function m
20
+ [:warn, :debug, :info].each do |m|
21
+ define_method(m) do |message|
22
+ Debugger.send(m, message)
23
+ end
24
+ module_function m
25
+ end
26
+
27
+ class Debugger
28
+ include Singleton
29
+
30
+ attr_accessor :enabled, :logger
31
+
32
+ def initialize
33
+ @logger = Logger.new(STDOUT)
34
+ @enabled = false
35
+ end
36
+
37
+ class << self
38
+ def logger=(logger)
39
+ instance.logger = logger
40
+ end
41
+
42
+ def enable!
43
+ instance.enabled = true
44
+ end
45
+
46
+ def disable!
47
+ instance.enabled = false
48
+ end
49
+
50
+ def enabled?
51
+ instance.enabled
52
+ end
53
+
54
+ [:warn, :debug, :info].each do |m|
55
+ define_method(m) do |message|
56
+ enabled? && instance.logger.send(m, message)
57
+ end
58
+ end
59
+ end # class << self
60
+ end
61
61
  end
data/lib/jabber4r/jid.rb CHANGED
@@ -3,20 +3,21 @@
3
3
  # License: see LICENSE
4
4
  # Jabber4R - Jabber Instant Messaging Library for Ruby
5
5
  # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+ # Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
6
7
 
7
8
  module Jabber
8
- # The Jabber ID class is used to hold a parsed jabber identifier (account+host+resource)
9
+ # The Jabber ID class is used to hold a parsed jabber identifier (account+domain+resource)
9
10
  class JID
10
- PATTERN = /^(?:(?<node>[^@]*)@)??(?<host>[^@\/]*)(?:\/(?<resource>.*?))?$/.freeze
11
+ PATTERN = /^(?:(?<node>[^@]*)@)??(?<domain>[^@\/]*)(?:\/(?<resource>.*?))?$/.freeze
11
12
 
12
- # The node (account)
13
+ # Public: The node (account)
13
14
  attr_accessor :node
14
15
 
15
- # The resource id
16
+ # Public: The resource id
16
17
  attr_accessor :resource
17
18
 
18
- # The host name (or IP address)
19
- attr_accessor :host
19
+ # Public: The domain indentificator (or IP address)
20
+ attr_accessor :domain
20
21
 
21
22
  # Public: Convert something to Jabber::JID
22
23
  #
@@ -30,34 +31,34 @@ module Jabber
30
31
  end
31
32
 
32
33
  # Constructs a JID from the supplied string of the format:
33
- # node@host[/resource] (e.g. "rich_kilmer@jabber.com/laptop")
34
+ # node@domain[/resource] (e.g. "rich_kilmer@jabber.com/laptop")
34
35
  #
35
36
  # jid - String the jabber id string to parse
36
- # host - String the host of jabber server (optional)
37
+ # domain - String the domain of jabber server (optional)
37
38
  # resource - String the resource of jabber id (optional)
38
39
  #
39
40
  # Examples
40
41
  #
41
42
  # jid = Jabber::JID.new("strech@localhost/attach")
42
43
  # jid.node # => "strech"
43
- # jid.host # => "localhost"
44
+ # jid.domain # => "localhost"
44
45
  # jid.resource # => "attach"
45
46
  #
46
47
  # Raises ArgumentError
47
48
  # Returns nothing
48
- def initialize(jid, host = nil, resource = nil)
49
+ def initialize(jid, domain = nil, resource = nil)
49
50
  raise ArgumentError, "Node can't be empty" if jid.to_s.empty?
50
51
 
51
- @node, @host, @resource = self.class.parse(jid)
52
- @node, @host = @host, nil if @node.nil? && @host
52
+ @node, @domain, @resource = self.class.parse(jid)
53
+ @node, @domain = @domain, nil if @node.nil? && @domain
53
54
 
54
- @host = host unless host.nil?
55
+ @domain = domain unless domain.nil?
55
56
  @resource = resource unless resource.nil?
56
57
 
57
- raise ArgumentError, "Couldn't create JID without host" if @host.to_s.empty?
58
+ raise ArgumentError, "Couldn't create JID without domain" if @domain.to_s.empty?
58
59
  end
59
60
 
60
- # Public: Evalutes whether the node, resource and host are the same
61
+ # Public: Evalutes whether the node, resource and domain are the same
61
62
  #
62
63
  # jid - Jabber::JID the other jabber id
63
64
  #
@@ -74,14 +75,14 @@ module Jabber
74
75
  def same?(jid)
75
76
  other_jid = self.class.to_jid(jid)
76
77
 
77
- other_jid.node == node && other_jid.host == host
78
+ other_jid.node == node && other_jid.domain == domain
78
79
  end
79
80
 
80
81
  # Public: Strip resource from jid and return new object
81
82
  #
82
83
  # Returns Jabber::JID
83
84
  def strip
84
- self.class.new(node, host)
85
+ self.class.new(node, domain)
85
86
  end
86
87
 
87
88
  # Public: Strip resource from jid and return the same object
@@ -97,7 +98,7 @@ module Jabber
97
98
  #
98
99
  # Returns String
99
100
  def to_s
100
- ["#{node}@#{host}", resource].compact.join "/"
101
+ ["#{node}@#{domain}", resource].compact.join "/"
101
102
  end
102
103
 
103
104
  # Public: Override #hash to hash based on the to_s method
@@ -108,7 +109,7 @@ module Jabber
108
109
  end
109
110
 
110
111
  private
111
- # Internal: Parse jid string for node, host, resource
112
+ # Internal: Parse jid string for node, domain, resource
112
113
  #
113
114
  # jid - String jabber id
114
115
  #
@@ -1,257 +1,249 @@
1
- # coding: utf-8
2
-
3
- # License: see LICENSE
4
- # Jabber4R - Jabber Instant Messaging Library for Ruby
5
- # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
-
7
- require "singleton"
8
- require "socket"
9
-
10
- module Jabber
11
- class JabberConnectionException < RuntimeError
12
- attr_reader :data
13
-
14
- def initialize(writing, data)
15
- @writing = writing
16
- @data = data
17
- end
18
-
19
- def writing?
20
- @writing
21
- end
22
- end
23
-
24
- ##
25
- # The Protocol module contains helper methods for constructing
26
- # Jabber protocol elements and classes that implement protocol
27
- # elements.
28
- #
29
- module Protocol
30
-
31
- USE_PARSER = :rexml # either :rexml or :xmlparser
32
-
33
- ##
34
- # The parser to use for stream processing. The current
35
- # available parsers are:
36
- #
37
- # * Jabber::Protocol::ExpatJabberParser uses XMLParser
38
- # * Jabber::Protocol::REXMLJabberParser uses REXML
39
- #
40
- # return:: [Class] The parser class
41
- #
42
- def Protocol.Parser
43
- if USE_PARSER==:xmlparser
44
- Jabber::Protocol::ExpatJabberParser
45
- else
46
- Jabber::Protocol::REXMLJabberParser
47
- end
48
- end
49
-
50
- ##
51
- # Generates an open stream XML element
52
- #
53
- # host:: [String] The host being connected to
54
- # return:: [String] The XML data to send
55
- #
56
- def self.gen_open_stream(host)
57
- return ('<?xml version="1.0" encoding="UTF-8" ?><stream:stream to="'+host+'" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">')
58
- end
59
-
60
- ##
61
- # Generates an close stream XML element
62
- #
63
- # return:: [String] The XML data to send
64
- #
65
- def self.gen_close_stream
66
- return "</stream:stream>"
67
- end
68
-
69
- if USE_PARSER == :xmlparser
70
- require 'xmlparser'
71
- ##
72
- # The ExpatJabberParser uses XMLParser (expat) to parse the incoming XML stream
73
- # of the Jabber protocol and fires ParsedXMLElements at the Connection
74
- # instance.
75
- #
76
- class ExpatJabberParser
77
-
78
- # status if the parser is started
79
- attr_reader :started
80
-
81
- ##
82
- # Constructs a parser for the supplied stream (socket input)
83
- #
84
- # stream:: [IO] Socket input stream
85
- # listener:: [#receive(ParsedXMLElement)] The listener (usually a Jabber::Protocol::Connection instance
86
- #
87
- def initialize(stream, listener)
88
- @stream = stream
89
- def @stream.gets
90
- super(">")
91
- end
92
- @listener = listener
93
- end
94
-
95
- ##
96
- # Begins parsing the XML stream and does not return until
97
- # the stream closes.
98
- #
99
- def parse
100
- @started = false
101
-
102
- parser = XMLParser.new("UTF-8")
103
- def parser.unknownEncoding(e)
104
- raise "Unknown encoding #{e.to_s}"
105
- end
106
- def parser.default
107
- end
108
-
109
- begin
110
- parser.parse(@stream) do |type, name, data|
111
- begin
112
- case type
113
- when XMLParser::START_ELEM
114
- case name
115
- when "stream:stream"
116
- openstream = ParsedXMLElement.new(name)
117
- data.each {|key, value| openstream.add_attribute(key, value)}
118
- @listener.receive(openstream)
119
- @started = true
120
- else
121
- if @current.nil?
122
- @current = ParsedXMLElement.new(name.clone)
123
- else
124
- @current = @current.add_child(name.clone)
125
- end
126
- data.each {|key, value| @current.add_attribute(key.clone, value.clone)}
127
- end
128
- when XMLParser::CDATA
129
- @current.append_data(data.clone) if @current
130
- when XMLParser::END_ELEM
131
- case name
132
- when "stream:stream"
133
- @started = false
134
- else
135
- @listener.receive(@current) unless @current.element_parent
136
- @current = @current.element_parent
137
- end
138
- end
139
- rescue
140
- puts "Error #{$!}"
141
- end
142
- end
143
- rescue XMLParserError
144
- line = parser.line
145
- print "XML Parsing error(#{line}): #{$!}\n"
146
- end
147
- end
148
- end
149
- else # USE REXML
150
- require 'rexml/document'
151
- require 'rexml/parsers/sax2parser'
152
- require 'rexml/source'
153
-
154
- ##
155
- # The REXMLJabberParser uses REXML to parse the incoming XML stream
156
- # of the Jabber protocol and fires ParsedXMLElements at the Connection
157
- # instance.
158
- #
159
- class REXMLJabberParser
160
- # status if the parser is started
161
- attr_reader :started
162
-
163
- ##
164
- # Constructs a parser for the supplied stream (socket input)
165
- #
166
- # stream:: [IO] Socket input stream
167
- # listener:: [Object.receive(ParsedXMLElement)] The listener (usually a Jabber::Protocol::Connection instance
168
- #
169
- def initialize(stream, listener)
170
- @stream = stream
171
-
172
- # this hack fixes REXML version "2.7.3" and "2.7.4"
173
- if REXML::Version=="2.7.3" || REXML::Version=="2.7.4"
174
- def @stream.read(len=nil)
175
- len = 100 unless len
176
- super(len)
177
- end
178
- def @stream.gets(char=nil)
179
- super(">")
180
- end
181
- def @stream.readline(char=nil)
182
- super(">")
183
- end
184
- def @stream.readlines(char=nil)
185
- super(">")
186
- end
187
- end
188
-
189
- @listener = listener
190
- @current = nil
191
- end
192
-
193
- ##
194
- # Begins parsing the XML stream and does not return until
195
- # the stream closes.
196
- #
197
- def parse
198
- #puts "PARSE"
199
- @started = false
200
- begin
201
- parser = REXML::Parsers::SAX2Parser.new @stream
202
-
203
- parser.listen(:end_document) do
204
- raise Jabber::ConnectionForceCloseError
205
- end
206
-
207
- parser.listen( :start_element ) do |uri, localname, qname, attributes|
208
- puts "START ELEMENT"
209
- case qname
210
- when "stream:stream"
211
- openstream = ParsedXMLElement.new(qname)
212
- attributes.each { |attr, value| openstream.add_attribute(attr, value) }
213
- @listener.receive(openstream)
214
- @started = true
215
- else
216
- if @current.nil?
217
- @current = ParsedXMLElement.new(qname)
218
- else
219
- @current = @current.add_child(qname)
220
- end
221
- attributes.each { |attr, value| @current.add_attribute(attr, value) }
222
- end
223
- end
224
- parser.listen( :end_element ) do |uri, localname, qname|
225
- puts "END ELEMENT"
226
- case qname
227
- when "stream:stream"
228
- @started = false
229
- else
230
- @listener.receive(@current) unless @current.element_parent
231
- @current = @current.element_parent
232
- end
233
- end
234
- parser.listen( :characters ) do | text |
235
- puts "CHARACTERS"
236
- @current.append_data(text) if @current
237
- end
238
- parser.listen( :cdata ) do | text |
239
- puts "CDATA"
240
- @current.append_data(text) if @current
241
- end
242
- parser.parse
243
- rescue REXML::ParseException => e
244
- puts "FAIL"
245
-
246
- puts e.backtrace.join "\n"
247
- puts e.message
248
- @listener.parse_failure
249
- rescue Jabber::ConnectionForceCloseError => e
250
- @listener.parse_failure(e)
251
- end
252
- end
253
- end
254
- end # USE_PARSER
255
- end
256
- end
257
-
1
+ # coding: utf-8
2
+
3
+ # License: see LICENSE
4
+ # Jabber4R - Jabber Instant Messaging Library for Ruby
5
+ # Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
6
+
7
+ require "singleton"
8
+ require "socket"
9
+
10
+ module Jabber
11
+ class JabberConnectionException < RuntimeError
12
+ attr_reader :data
13
+
14
+ def initialize(writing, data)
15
+ @writing = writing
16
+ @data = data
17
+ end
18
+
19
+ def writing?
20
+ @writing
21
+ end
22
+ end
23
+
24
+ ##
25
+ # The Protocol module contains helper methods for constructing
26
+ # Jabber protocol elements and classes that implement protocol
27
+ # elements.
28
+ #
29
+ module Protocol
30
+
31
+ USE_PARSER = :rexml # either :rexml or :xmlparser
32
+
33
+ ##
34
+ # The parser to use for stream processing. The current
35
+ # available parsers are:
36
+ #
37
+ # * Jabber::Protocol::ExpatJabberParser uses XMLParser
38
+ # * Jabber::Protocol::REXMLJabberParser uses REXML
39
+ #
40
+ # return:: [Class] The parser class
41
+ #
42
+ def Protocol.Parser
43
+ if USE_PARSER==:xmlparser
44
+ Jabber::Protocol::ExpatJabberParser
45
+ else
46
+ Jabber::Protocol::REXMLJabberParser
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Generates an open stream XML element
52
+ #
53
+ # domain:: [String] The domain being connected to
54
+ # return:: [String] The XML data to send
55
+ #
56
+ def self.gen_open_stream(domain)
57
+ return ('<?xml version="1.0" encoding="UTF-8" ?><stream:stream to="'+domain+'" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">')
58
+ end
59
+
60
+ ##
61
+ # Generates an close stream XML element
62
+ #
63
+ # return:: [String] The XML data to send
64
+ #
65
+ def self.gen_close_stream
66
+ return "</stream:stream>"
67
+ end
68
+
69
+ if USE_PARSER == :xmlparser
70
+ require 'xmlparser'
71
+ ##
72
+ # The ExpatJabberParser uses XMLParser (expat) to parse the incoming XML stream
73
+ # of the Jabber protocol and fires ParsedXMLElements at the Connection
74
+ # instance.
75
+ #
76
+ class ExpatJabberParser
77
+
78
+ # status if the parser is started
79
+ attr_reader :started
80
+
81
+ ##
82
+ # Constructs a parser for the supplied stream (socket input)
83
+ #
84
+ # stream:: [IO] Socket input stream
85
+ # listener:: [#receive(ParsedXMLElement)] The listener (usually a Jabber::Protocol::Connection instance
86
+ #
87
+ def initialize(stream, listener)
88
+ @stream = stream
89
+ def @stream.gets
90
+ super(">")
91
+ end
92
+ @listener = listener
93
+ end
94
+
95
+ ##
96
+ # Begins parsing the XML stream and does not return until
97
+ # the stream closes.
98
+ #
99
+ def parse
100
+ @started = false
101
+
102
+ parser = XMLParser.new("UTF-8")
103
+ def parser.unknownEncoding(e)
104
+ raise "Unknown encoding #{e.to_s}"
105
+ end
106
+ def parser.default
107
+ end
108
+
109
+ begin
110
+ parser.parse(@stream) do |type, name, data|
111
+ begin
112
+ case type
113
+ when XMLParser::START_ELEM
114
+ case name
115
+ when "stream:stream"
116
+ openstream = ParsedXMLElement.new(name)
117
+ data.each {|key, value| openstream.add_attribute(key, value)}
118
+ @listener.receive(openstream)
119
+ @started = true
120
+ else
121
+ if @current.nil?
122
+ @current = ParsedXMLElement.new(name.clone)
123
+ else
124
+ @current = @current.add_child(name.clone)
125
+ end
126
+ data.each {|key, value| @current.add_attribute(key.clone, value.clone)}
127
+ end
128
+ when XMLParser::CDATA
129
+ @current.append_data(data.clone) if @current
130
+ when XMLParser::END_ELEM
131
+ case name
132
+ when "stream:stream"
133
+ @started = false
134
+ else
135
+ @listener.receive(@current) unless @current.element_parent
136
+ @current = @current.element_parent
137
+ end
138
+ end
139
+ rescue
140
+ puts "Error #{$!}"
141
+ end
142
+ end
143
+ rescue XMLParserError
144
+ line = parser.line
145
+ print "XML Parsing error(#{line}): #{$!}\n"
146
+ end
147
+ end
148
+ end
149
+ else # USE REXML
150
+ require 'rexml/document'
151
+ require 'rexml/parsers/sax2parser'
152
+ require 'rexml/source'
153
+
154
+ ##
155
+ # The REXMLJabberParser uses REXML to parse the incoming XML stream
156
+ # of the Jabber protocol and fires ParsedXMLElements at the Connection
157
+ # instance.
158
+ #
159
+ class REXMLJabberParser
160
+ # status if the parser is started
161
+ attr_reader :started
162
+
163
+ ##
164
+ # Constructs a parser for the supplied stream (socket input)
165
+ #
166
+ # stream:: [IO] Socket input stream
167
+ # listener:: [Object.receive(ParsedXMLElement)] The listener (usually a Jabber::Protocol::Connection instance
168
+ #
169
+ def initialize(stream, listener)
170
+ @stream = stream
171
+
172
+ # this hack fixes REXML version "2.7.3" and "2.7.4"
173
+ if REXML::Version=="2.7.3" || REXML::Version=="2.7.4"
174
+ def @stream.read(len=nil)
175
+ len = 100 unless len
176
+ super(len)
177
+ end
178
+ def @stream.gets(char=nil)
179
+ super(">")
180
+ end
181
+ def @stream.readline(char=nil)
182
+ super(">")
183
+ end
184
+ def @stream.readlines(char=nil)
185
+ super(">")
186
+ end
187
+ end
188
+
189
+ @listener = listener
190
+ @current = nil
191
+ end
192
+
193
+ ##
194
+ # Begins parsing the XML stream and does not return until
195
+ # the stream closes.
196
+ #
197
+ def parse
198
+ #puts "PARSE"
199
+ @started = false
200
+ begin
201
+ parser = REXML::Parsers::SAX2Parser.new @stream
202
+
203
+ parser.listen(:end_document) do
204
+ raise Jabber::ConnectionForceCloseError
205
+ end
206
+
207
+ parser.listen( :start_element ) do |uri, localname, qname, attributes|
208
+ case qname
209
+ when "stream:stream"
210
+ openstream = ParsedXMLElement.new(qname)
211
+ attributes.each { |attr, value| openstream.add_attribute(attr, value) }
212
+ @listener.receive(openstream)
213
+ @started = true
214
+ else
215
+ if @current.nil?
216
+ @current = ParsedXMLElement.new(qname)
217
+ else
218
+ @current = @current.add_child(qname)
219
+ end
220
+ attributes.each { |attr, value| @current.add_attribute(attr, value) }
221
+ end
222
+ end
223
+ parser.listen( :end_element ) do |uri, localname, qname|
224
+ case qname
225
+ when "stream:stream"
226
+ @started = false
227
+ else
228
+ @listener.receive(@current) unless @current.element_parent
229
+ @current = @current.element_parent
230
+ end
231
+ end
232
+ parser.listen( :characters ) do | text |
233
+ @current.append_data(text) if @current
234
+ end
235
+ parser.listen( :cdata ) do | text |
236
+ @current.append_data(text) if @current
237
+ end
238
+ parser.parse
239
+ rescue REXML::ParseException => e
240
+ @listener.parse_failure
241
+ rescue Jabber::ConnectionForceCloseError => e
242
+ @listener.parse_failure(e)
243
+ end
244
+ end
245
+ end
246
+ end # USE_PARSER
247
+ end
248
+ end
249
+