# =XMPP4R - XMPP Library for Ruby # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option. # Website::http://home.gna.org/xmpp4r/ require 'rexml/parsers/sax2parser' require 'rexml/source' require 'nokogiri' require 'xmpp4r/rexmladdons' module Jabber class StreamParser < Nokogiri::XML::SAX::Document # status if the parser is started attr_reader :started ## # Constructs a parser for the supplied stream (socket input) # # stream:: [IO] Socket input stream # listener:: [Object.receive(XMPPStanza)] The listener (usually a Jabber::Protocol::Connection instance) # def initialize(listener) @listener = listener @current = nil @started = false end def start_element(name, attrs = []) e = REXML::Element.new(name) e.add_attributes attrs @current = @current.nil? ? e : @current.add_element(e) # Handling <stream:stream> not only when it is being # received as a top-level tag but also as a child of the # top-level element itself. This way, we handle stream # restarts (ie. after SASL authentication). if @current.name == 'stream' and @current.parent.nil? @started = true @listener.receive(@current) @current = nil end end def end_element(name) if name == 'stream:stream' and @current.nil? @started = false @listener.parser_end else @listener.receive(@current) unless @current.parent @current = @current.parent end end def characters(s) @current.add(REXML::Text.new(s.to_s, @current.whitespace, nil, false)) if @current end def cdata_block(s) @current.add(REXML::CData.new(s)) if @current end def end_document raise Jabber::ServerDisconnected, "Server Disconnected!" end end end