xmpp4r 0.3 → 0.3.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 +10 -0
- data/README +12 -4
- data/Rakefile +1 -1
- data/data/doc/xmpp4r/examples/advanced/fileserve.rb +2 -0
- data/data/doc/xmpp4r/examples/advanced/recvfile.rb +2 -0
- data/data/doc/xmpp4r/examples/basic/client.rb +2 -2
- data/data/doc/xmpp4r/examples/basic/mass_sender.rb +1 -0
- data/data/doc/xmpp4r/examples/buggy/miniedgarr_cgi.rb +1 -1
- data/lib/xmpp4r/bytestreams.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +10 -4
- data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +5 -1
- data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +5 -1
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +5 -1
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +20 -6
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +4 -0
- data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +4 -0
- data/lib/xmpp4r/bytestreams/iq/si.rb +4 -0
- data/lib/xmpp4r/component.rb +1 -1
- data/lib/xmpp4r/dataforms.rb +4 -0
- data/lib/xmpp4r/delay.rb +4 -0
- data/lib/xmpp4r/discovery.rb +4 -0
- data/lib/xmpp4r/feature_negotiation.rb +4 -0
- data/lib/xmpp4r/feature_negotiation/iq/feature.rb +4 -0
- data/lib/xmpp4r/iq.rb +1 -1
- data/lib/xmpp4r/message.rb +10 -3
- data/lib/xmpp4r/muc.rb +4 -0
- data/lib/xmpp4r/muc/helper/simplemucclient.rb +4 -0
- data/lib/xmpp4r/presence.rb +9 -5
- data/lib/xmpp4r/rexmladdons.rb +65 -3
- data/lib/xmpp4r/roster.rb +4 -0
- data/lib/xmpp4r/roster/helper/roster.rb +18 -3
- data/lib/xmpp4r/sasl.rb +59 -10
- data/lib/xmpp4r/stream.rb +22 -2
- data/lib/xmpp4r/vcard.rb +4 -0
- data/lib/xmpp4r/vcard/helper/vcard.rb +4 -4
- data/lib/xmpp4r/version.rb +4 -0
- data/lib/xmpp4r/xmpp4r.rb +1 -1
- data/setup.rb +800 -575
- data/test/bytestreams/tc_socks5bytestreams.rb +46 -0
- data/test/tc_iq.rb +1 -1
- data/test/tc_rexml.rb +60 -0
- data/test/ts_xmpp4r.rb +2 -1
- data/test/vcard/tc_helper.rb +49 -0
- metadata +96 -94
- data/test/roster/.tc_helper.rb.swp +0 -0
    
        data/ChangeLog
    CHANGED
    
    | @@ -1,3 +1,13 @@ | |
| 1 | 
            +
            XMPP4R 0.3.1 (23/04/2007)
         | 
| 2 | 
            +
            =========================
         | 
| 3 | 
            +
            * SASL fixes
         | 
| 4 | 
            +
            * Message#x and Presence#x support element selection by namespace
         | 
| 5 | 
            +
            * Proper XML entity escaping for REXML text nodes
         | 
| 6 | 
            +
            * Improvements to FileTransfer::Helper and SOCKS5BytestreamsServer
         | 
| 7 | 
            +
            * Vcard::Helper fixes
         | 
| 8 | 
            +
            * Update Digest module usage to reflect recent Ruby versions
         | 
| 9 | 
            +
            * More documentation
         | 
| 10 | 
            +
             | 
| 1 11 | 
             
            XMPP4R 0.3 (20/07/2006)
         | 
| 2 12 | 
             
            =======================
         | 
| 3 13 | 
             
            * SRV lookup capability in Client#connect
         | 
    
        data/README
    CHANGED
    
    | @@ -1,8 +1,14 @@ | |
| 1 1 | 
             
              XMPP4R
         | 
| 2 2 | 
             
            ----------
         | 
| 3 | 
            -
            by | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 3 | 
            +
            by:
         | 
| 4 | 
            +
              Lucas Nussbaum <lucas@lucas-nussbaum.net>
         | 
| 5 | 
            +
              Stephan Maka <stephan@spaceboyz.net>
         | 
| 6 | 
            +
              Kirill A. Shutemov <k.shutemov@gmail.com>
         | 
| 7 | 
            +
              Yuki Mitsui
         | 
| 8 | 
            +
              Peter Schrammel
         | 
| 9 | 
            +
              Olli
         | 
| 10 | 
            +
              Vojtech Vobr
         | 
| 11 | 
            +
              Andreas Wiese
         | 
| 6 12 |  | 
| 7 13 | 
             
            Currently, all the information is provided on
         | 
| 8 14 |  | 
| @@ -13,7 +19,9 @@ The integrated HTML documentation can be built with | |
| 13 19 | 
             
                   rake rdoc
         | 
| 14 20 |  | 
| 15 21 | 
             
            If you need to ask questions, feel free to ask them on the
         | 
| 16 | 
            -
            xmpp4r-devel@gna.org mailing list.
         | 
| 22 | 
            +
            xmpp4r-devel@gna.org mailing list. When reporting problems,
         | 
| 23 | 
            +
            please include a protocol dump which can be enabled with:
         | 
| 24 | 
            +
              Jabber::debug = true
         | 
| 17 25 |  | 
| 18 26 | 
             
            XMPP4R is released under the Ruby license (see the LICENSE file), which is
         | 
| 19 27 | 
             
            compatible with the GNU GPL (see the COPYING file) via an explicit
         | 
    
        data/Rakefile
    CHANGED
    
    
| @@ -22,7 +22,7 @@ class BasicClient | |
| 22 22 | 
             
                  quit = true if line.nil?
         | 
| 23 23 | 
             
                  if not quit
         | 
| 24 24 | 
             
                    command, args = line.split(' ', 2)
         | 
| 25 | 
            -
                    args.chomp | 
| 25 | 
            +
                    args = args.to_s.chomp
         | 
| 26 26 | 
             
                    # main case
         | 
| 27 27 | 
             
                    case command
         | 
| 28 28 | 
             
                    when 'exit'
         | 
| @@ -52,7 +52,7 @@ class BasicClient | |
| 52 52 | 
             
              ##
         | 
| 53 53 | 
             
              # connect <jid> <password>
         | 
| 54 54 | 
             
              def do_connect(args)
         | 
| 55 | 
            -
                @jid, @password = args.split(' ',  | 
| 55 | 
            +
                @jid, @password = args.split(' ', 2)
         | 
| 56 56 | 
             
                @jid = JID::new(@jid)
         | 
| 57 57 | 
             
                @cl = Client::new(@jid)
         | 
| 58 58 | 
             
                @cl.connect
         | 
| @@ -34,7 +34,7 @@ doc.root.each_element { |e| | |
| 34 34 | 
             
              elsif e.name == 'presence'
         | 
| 35 35 | 
             
                pres = Jabber::Presence.new.import(e)
         | 
| 36 36 |  | 
| 37 | 
            -
                if (pres.from.strip == jid) || (Digest::MD5. | 
| 37 | 
            +
                if (pres.from.strip == jid) || (Digest::MD5.hexdigest(pres.from.strip.to_s) == jidhash)
         | 
| 38 38 | 
             
                  if (jid == '') && !jidhash.nil?
         | 
| 39 39 | 
             
                    jid = pres.from.strip
         | 
| 40 40 | 
             
                  end
         | 
    
        data/lib/xmpp4r/bytestreams.rb
    CHANGED
    
    | @@ -1,3 +1,7 @@ | |
| 1 | 
            +
            # =XMPP4R - XMPP Library for Ruby
         | 
| 2 | 
            +
            # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
         | 
| 3 | 
            +
            # Website::http://home.gna.org/xmpp4r/
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            require 'xmpp4r/bytestreams/iq/si.rb'
         | 
| 2 6 | 
             
            require 'xmpp4r/bytestreams/iq/bytestreams.rb'
         | 
| 3 7 | 
             
            require 'xmpp4r/bytestreams/helper/ibb/base.rb'
         | 
| @@ -1,3 +1,7 @@ | |
| 1 | 
            +
            # =XMPP4R - XMPP Library for Ruby
         | 
| 2 | 
            +
            # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
         | 
| 3 | 
            +
            # Website::http://home.gna.org/xmpp4r/
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            require 'callbacks'
         | 
| 2 6 |  | 
| 3 7 | 
             
            require 'xmpp4r/bytestreams/iq/si'
         | 
| @@ -242,8 +246,10 @@ module Jabber | |
| 242 246 | 
             
                  # jid:: [JID] to send the file to
         | 
| 243 247 | 
             
                  # source:: File-transfer source, implementing the FileSource interface
         | 
| 244 248 | 
             
                  # desc:: [String] or [nil] Optional file description
         | 
| 249 | 
            +
                  # from:: [String] or [nil] Optional jid for components
         | 
| 245 250 | 
             
                  # result:: [Bytestreams::SOCKS5BytestreamsInitiator] or [Bytestreams::IBBInitiator] or [nil]
         | 
| 246 | 
            -
                  def offer(jid, source, desc=nil)
         | 
| 251 | 
            +
                  def offer(jid, source, desc=nil, from=nil)
         | 
| 252 | 
            +
                    from = from || @my_jid || @stream.jid
         | 
| 247 253 | 
             
                    session_id = Jabber::IdGenerator.instance.generate_id
         | 
| 248 254 |  | 
| 249 255 | 
             
                    offered_methods = {}
         | 
| @@ -255,7 +261,7 @@ module Jabber | |
| 255 261 | 
             
                    end
         | 
| 256 262 |  | 
| 257 263 | 
             
                    iq = Iq::new(:set, jid)
         | 
| 258 | 
            -
                    iq.from =  | 
| 264 | 
            +
                    iq.from = from
         | 
| 259 265 | 
             
                    si = iq.add(Bytestreams::IqSi.new(session_id, Bytestreams::IqSi::PROFILE_FILETRANSFER, source.mime))
         | 
| 260 266 |  | 
| 261 267 | 
             
                    file = si.add(Bytestreams::IqSiFile.new(source.filename, source.size))
         | 
| @@ -299,9 +305,9 @@ module Jabber | |
| 299 305 | 
             
                    end
         | 
| 300 306 |  | 
| 301 307 | 
             
                    if stream_method == Bytestreams::IqQueryBytestreams::NS_BYTESTREAMS and @allow_bytestreams
         | 
| 302 | 
            -
                      Bytestreams::SOCKS5BytestreamsInitiator.new(@stream, session_id,  | 
| 308 | 
            +
                      Bytestreams::SOCKS5BytestreamsInitiator.new(@stream, session_id, from, jid)
         | 
| 303 309 | 
             
                    elsif stream_method == Bytestreams::IBB::NS_IBB and @allow_ibb
         | 
| 304 | 
            -
                      Bytestreams::IBBInitiator.new(@stream, session_id,  | 
| 310 | 
            +
                      Bytestreams::IBBInitiator.new(@stream, session_id, from, jid)
         | 
| 305 311 | 
             
                    else  # Target responded with a stream_method we didn't offer
         | 
| 306 312 | 
             
                      eanswer = response.answer
         | 
| 307 313 | 
             
                      eanswer.type = :error
         | 
| @@ -1,3 +1,7 @@ | |
| 1 | 
            +
            # =XMPP4R - XMPP Library for Ruby
         | 
| 2 | 
            +
            # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
         | 
| 3 | 
            +
            # Website::http://home.gna.org/xmpp4r/
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            module Jabber
         | 
| 2 6 | 
             
              module Bytestreams
         | 
| 3 7 | 
             
                ##
         | 
| @@ -5,7 +9,7 @@ module Jabber | |
| 5 9 | 
             
                class IBBInitiator < IBB
         | 
| 6 10 | 
             
                  # You may set the block-size before open
         | 
| 7 11 | 
             
                  attr_accessor :block_size
         | 
| 8 | 
            -
             | 
| 12 | 
            +
             | 
| 9 13 | 
             
                  ##
         | 
| 10 14 | 
             
                  # Open the stream to the peer,
         | 
| 11 15 | 
             
                  # waits for successful result
         | 
| @@ -1,3 +1,7 @@ | |
| 1 | 
            +
            # =XMPP4R - XMPP Library for Ruby
         | 
| 2 | 
            +
            # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
         | 
| 3 | 
            +
            # Website::http://home.gna.org/xmpp4r/
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            module Jabber
         | 
| 2 6 | 
             
              module Bytestreams
         | 
| 3 7 | 
             
                ##
         | 
| @@ -28,7 +32,7 @@ module Jabber | |
| 28 32 | 
             
                        reply = iq.answer(false)
         | 
| 29 33 | 
             
                        reply.type = :result
         | 
| 30 34 | 
             
                        @stream.send(reply)
         | 
| 31 | 
            -
             | 
| 35 | 
            +
             | 
| 32 36 | 
             
                        connect_lock.unlock
         | 
| 33 37 | 
             
                        true
         | 
| 34 38 | 
             
                      else
         | 
| @@ -1,3 +1,7 @@ | |
| 1 | 
            +
            # =XMPP4R - XMPP Library for Ruby
         | 
| 2 | 
            +
            # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
         | 
| 3 | 
            +
            # Website::http://home.gna.org/xmpp4r/
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            require 'socket'
         | 
| 2 6 | 
             
            require 'thread'
         | 
| 3 7 | 
             
            require 'timeout'
         | 
| @@ -122,7 +126,7 @@ module Jabber | |
| 122 126 | 
             
                  # initiator_jid and target_jid.
         | 
| 123 127 | 
             
                  # result:: [String] SHA1 hash
         | 
| 124 128 | 
             
                  def stream_address
         | 
| 125 | 
            -
                    Digest::SHA1. | 
| 129 | 
            +
                    Digest::SHA1.hexdigest("#{@session_id}#{@initiator_jid}#{@target_jid}")
         | 
| 126 130 | 
             
                  end
         | 
| 127 131 |  | 
| 128 132 | 
             
                  ##
         | 
| @@ -1,3 +1,7 @@ | |
| 1 | 
            +
            # =XMPP4R - XMPP Library for Ruby
         | 
| 2 | 
            +
            # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
         | 
| 3 | 
            +
            # Website::http://home.gna.org/xmpp4r/
         | 
| 4 | 
            +
             | 
| 1 5 | 
             
            module Jabber
         | 
| 2 6 | 
             
              module Bytestreams
         | 
| 3 7 | 
             
                ##
         | 
| @@ -19,12 +23,17 @@ module Jabber | |
| 19 23 | 
             
                  # Will start to listen on the given TCP port and
         | 
| 20 24 | 
             
                  # accept new peers
         | 
| 21 25 | 
             
                  # port:: [Fixnum] TCP port to listen on
         | 
| 22 | 
            -
                   | 
| 26 | 
            +
                  # listen_on:: [String] Optional address for the server socket to listen on (i.e. '0.0.0.0' or '::')
         | 
| 27 | 
            +
                  def initialize(port, listen_on=nil)
         | 
| 23 28 | 
             
                    @port = port
         | 
| 24 29 | 
             
                    @addresses = []
         | 
| 25 30 | 
             
                    @peers = []
         | 
| 26 31 | 
             
                    @peers_lock = Mutex.new
         | 
| 27 | 
            -
                     | 
| 32 | 
            +
                    if listen_on
         | 
| 33 | 
            +
                      socket = TCPServer.new(listen_on, port)
         | 
| 34 | 
            +
                    else
         | 
| 35 | 
            +
                      socket = TCPServer.new(port)
         | 
| 36 | 
            +
                    end
         | 
| 28 37 |  | 
| 29 38 | 
             
                    Thread.new {
         | 
| 30 39 | 
             
                      loop {
         | 
| @@ -45,6 +54,9 @@ module Jabber | |
| 45 54 |  | 
| 46 55 | 
             
                  ##
         | 
| 47 56 | 
             
                  # Find the socket a peer is associated to
         | 
| 57 | 
            +
                  #
         | 
| 58 | 
            +
                  # This method also performs some housekeeping, ie. removing
         | 
| 59 | 
            +
                  # peers with closed sockets.
         | 
| 48 60 | 
             
                  # addr:: [String] Address like SOCKS5Bytestreams#stream_address
         | 
| 49 61 | 
             
                  # result:: [TCPSocker] or [nil]
         | 
| 50 62 | 
             
                  def peer_sock(addr)
         | 
| @@ -58,11 +70,13 @@ module Jabber | |
| 58 70 | 
             
                          removes << peer
         | 
| 59 71 | 
             
                        elsif peer.address == addr and res.nil?
         | 
| 60 72 | 
             
                          res = peer.socket
         | 
| 61 | 
            -
                        else
         | 
| 62 | 
            -
                          # If we sent multiple addresses of our own, clients may
         | 
| 63 | 
            -
                          # connect multiple times. Close these connections here.
         | 
| 64 | 
            -
                          removes << peer
         | 
| 65 73 | 
             
                        end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        # If we sent multiple addresses of our own, clients may
         | 
| 76 | 
            +
                        # connect multiple times. DO NOT close any other connections
         | 
| 77 | 
            +
                        # here. These may belong to other concurrent bytestreams,
         | 
| 78 | 
            +
                        # believe that the peer will close any unneeded sockets
         | 
| 79 | 
            +
                        # which will then be picked up by the next call to peer_sock.
         | 
| 66 80 | 
             
                      }
         | 
| 67 81 |  | 
| 68 82 | 
             
                      # If we sent multiple addresses of our own, clients may
         | 
    
        data/lib/xmpp4r/component.rb
    CHANGED
    
    | @@ -83,7 +83,7 @@ module Jabber | |
| 83 83 | 
             
                # Throws AuthenticationFailure
         | 
| 84 84 | 
             
                # secret:: [String] the shared secret 
         | 
| 85 85 | 
             
                def auth(secret)
         | 
| 86 | 
            -
                  hash = Digest::SHA1:: | 
| 86 | 
            +
                  hash = Digest::SHA1::hexdigest(@streamid.to_s + secret)
         | 
| 87 87 | 
             
                  authenticated = false
         | 
| 88 88 | 
             
                  send("<handshake>#{hash}</handshake>") { |r|
         | 
| 89 89 | 
             
                    if r.prefix == 'stream' and r.name == 'error'
         | 
    
        data/lib/xmpp4r/dataforms.rb
    CHANGED
    
    
    
        data/lib/xmpp4r/delay.rb
    CHANGED
    
    
    
        data/lib/xmpp4r/discovery.rb
    CHANGED
    
    
    
        data/lib/xmpp4r/iq.rb
    CHANGED
    
    | @@ -156,7 +156,7 @@ module Jabber | |
| 156 156 | 
             
                  query = IqQuery::new
         | 
| 157 157 | 
             
                  query.add_namespace('jabber:iq:auth')
         | 
| 158 158 | 
             
                  query.add(REXML::Element::new('username').add_text(jid.node))
         | 
| 159 | 
            -
                  query.add(REXML::Element::new('digest').add_text(Digest::SHA1. | 
| 159 | 
            +
                  query.add(REXML::Element::new('digest').add_text(Digest::SHA1.hexdigest(session_id + password)))
         | 
| 160 160 | 
             
                  query.add(REXML::Element::new('resource').add_text(jid.resource)) if not jid.resource.nil?
         | 
| 161 161 | 
             
                  iq.add(query)
         | 
| 162 162 | 
             
                  iq
         | 
    
        data/lib/xmpp4r/message.rb
    CHANGED
    
    | @@ -82,9 +82,16 @@ module Jabber | |
| 82 82 | 
             
                end
         | 
| 83 83 |  | 
| 84 84 | 
             
                ##
         | 
| 85 | 
            -
                # Get the first <x/> element  | 
| 86 | 
            -
                 | 
| 87 | 
            -
             | 
| 85 | 
            +
                # Get the first <x/> element in this stanza, or nil if none found.
         | 
| 86 | 
            +
                # namespace:: [String] Optional, find the first <x/> element having this xmlns
         | 
| 87 | 
            +
                # result:: [REXML::Element] or nil
         | 
| 88 | 
            +
                def x(namespace=nil)
         | 
| 89 | 
            +
                  each_element('x') { |x|
         | 
| 90 | 
            +
                    if namespace.nil? or namespace == x.namespace
         | 
| 91 | 
            +
                      return x
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
                  }
         | 
| 94 | 
            +
                  nil
         | 
| 88 95 | 
             
                end
         | 
| 89 96 |  | 
| 90 97 | 
             
                ##
         | 
    
        data/lib/xmpp4r/muc.rb
    CHANGED
    
    
    
        data/lib/xmpp4r/presence.rb
    CHANGED
    
    | @@ -94,12 +94,16 @@ module Jabber | |
| 94 94 | 
             
                end
         | 
| 95 95 |  | 
| 96 96 | 
             
                ##
         | 
| 97 | 
            -
                # Get the first <x/> element  | 
| 97 | 
            +
                # Get the first <x/> element in this stanza, or nil if none found.
         | 
| 98 | 
            +
                # namespace:: [String] Optional, find the first <x/> element having this xmlns
         | 
| 98 99 | 
             
                # result:: [REXML::Element] or nil
         | 
| 99 | 
            -
                def x
         | 
| 100 | 
            -
                   | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 100 | 
            +
                def x(namespace=nil)
         | 
| 101 | 
            +
                  each_element('x') { |x|
         | 
| 102 | 
            +
                    if namespace.nil? or namespace == x.namespace
         | 
| 103 | 
            +
                      return x
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  }
         | 
| 106 | 
            +
                  nil
         | 
| 103 107 | 
             
                end
         | 
| 104 108 |  | 
| 105 109 | 
             
                ##
         | 
    
        data/lib/xmpp4r/rexmladdons.rb
    CHANGED
    
    | @@ -10,8 +10,23 @@ require 'rexml/source' | |
| 10 10 | 
             
            oldverbose = $VERBOSE
         | 
| 11 11 | 
             
            $VERBOSE = false
         | 
| 12 12 |  | 
| 13 | 
            -
            # REXML module. This file only adds  | 
| 14 | 
            -
            # ease the coding | 
| 13 | 
            +
            # REXML module. This file only adds the following methods to the REXML module, to
         | 
| 14 | 
            +
            # ease the coding:
         | 
| 15 | 
            +
            # * replace_element_text
         | 
| 16 | 
            +
            # * first_element
         | 
| 17 | 
            +
            # * first_element_text
         | 
| 18 | 
            +
            # * typed_add
         | 
| 19 | 
            +
            # * import
         | 
| 20 | 
            +
            # * self.import
         | 
| 21 | 
            +
            # * delete_elements
         | 
| 22 | 
            +
            #
         | 
| 23 | 
            +
            # Further definitions are just copied from REXML out of Ruby-1.8.4 to solve issues
         | 
| 24 | 
            +
            # with REXML in Ruby-1.8.2.
         | 
| 25 | 
            +
            #
         | 
| 26 | 
            +
            # The redefinitions of Text::normalize and Attribute#initialize address an issue
         | 
| 27 | 
            +
            # where entities in element texts and attributes were not escaped. This modifies
         | 
| 28 | 
            +
            # the behavious of REXML a bit but Sean Russell intends a similar behaviour for
         | 
| 29 | 
            +
            # the future of REXML.
         | 
| 15 30 | 
             
            module REXML
         | 
| 16 31 | 
             
              # this class adds a few helper methods to REXML::Element
         | 
| 17 32 | 
             
              class Element
         | 
| @@ -116,7 +131,8 @@ module REXML | |
| 116 131 | 
             
                  @variables = {}
         | 
| 117 132 | 
             
                end
         | 
| 118 133 |  | 
| 119 | 
            -
                def namespaces=( namespaces | 
| 134 | 
            +
                def namespaces=( namespaces )
         | 
| 135 | 
            +
                  namespaces ||= {}
         | 
| 120 136 | 
             
                  Functions::namespace_context = namespaces
         | 
| 121 137 | 
             
                  @namespaces = namespaces
         | 
| 122 138 | 
             
                end
         | 
| @@ -819,6 +835,52 @@ module REXML | |
| 819 835 |  | 
| 820 836 |  | 
| 821 837 | 
             
            ############################################################################
         | 
| 838 | 
            +
             
         | 
| 839 | 
            +
              class Text
         | 
| 840 | 
            +
                # Escapes all possible entities
         | 
| 841 | 
            +
                def Text::normalize( input, doctype=nil, entity_filter=nil )
         | 
| 842 | 
            +
                  copy = input
         | 
| 843 | 
            +
                  # Doing it like this rather than in a loop improves the speed
         | 
| 844 | 
            +
                  if doctype
         | 
| 845 | 
            +
                    # Replace all ampersands that aren't part of an entity
         | 
| 846 | 
            +
                    copy = copy.gsub( EREFERENCE, '&' )
         | 
| 847 | 
            +
                    doctype.entities.each_value do |entity|
         | 
| 848 | 
            +
                      copy = copy.gsub( entity.value, 
         | 
| 849 | 
            +
                        "&#{entity.name};" ) if entity.value and 
         | 
| 850 | 
            +
                          not( entity_filter and entity_filter.include?(entity) )
         | 
| 851 | 
            +
                    end
         | 
| 852 | 
            +
                  else
         | 
| 853 | 
            +
                    # Replace all ampersands
         | 
| 854 | 
            +
                    copy = copy.gsub( '&', '&' )
         | 
| 855 | 
            +
                    DocType::DEFAULT_ENTITIES.each_value do |entity|
         | 
| 856 | 
            +
                      copy = copy.gsub(entity.value, "&#{entity.name};" )
         | 
| 857 | 
            +
                    end
         | 
| 858 | 
            +
                  end
         | 
| 859 | 
            +
                  copy
         | 
| 860 | 
            +
                end
         | 
| 861 | 
            +
              end
         | 
| 862 | 
            +
             | 
| 863 | 
            +
            	class Attribute
         | 
| 864 | 
            +
            		def initialize( first, second=nil, parent=nil )
         | 
| 865 | 
            +
            			@normalized = @unnormalized = @element = nil
         | 
| 866 | 
            +
            			if first.kind_of? Attribute
         | 
| 867 | 
            +
            				self.name = first.expanded_name
         | 
| 868 | 
            +
            				@value = first.value
         | 
| 869 | 
            +
            				if second.kind_of? Element
         | 
| 870 | 
            +
            					@element = second
         | 
| 871 | 
            +
            				else
         | 
| 872 | 
            +
            					@element = first.element
         | 
| 873 | 
            +
            				end
         | 
| 874 | 
            +
            			elsif first.kind_of? String
         | 
| 875 | 
            +
            				@element = parent if parent.kind_of? Element
         | 
| 876 | 
            +
            				self.name = first
         | 
| 877 | 
            +
            				@value = Text::normalize(second.to_s)
         | 
| 878 | 
            +
            			else
         | 
| 879 | 
            +
            				raise "illegal argument #{first.class.name} to Attribute constructor"
         | 
| 880 | 
            +
            			end
         | 
| 881 | 
            +
            		end
         | 
| 882 | 
            +
              end
         | 
| 883 | 
            +
             | 
| 822 884 | 
             
            end
         | 
| 823 885 |  | 
| 824 886 | 
             
            # Restore the old $VERBOSE setting
         |