Projects
Mega:24.09
ruby
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:ruby.spec
Changed
@@ -33,7 +33,7 @@ Name: ruby Version: %{ruby_version} -Release: 141 +Release: 142 Summary: Object-oriented scripting language interpreter License: (Ruby or BSD) and Public Domain and MIT and CC0 and zlib and UCD URL: https://www.ruby-lang.org/en/ @@ -97,6 +97,7 @@ Patch6021: backport-0003-CVE-2024-35221.patch Patch6022: backport-0004-CVE-2024-35221.patch Patch6023: backport-0005-CVE-2024-35221.patch +Patch6024: upgrade-lib-rexml-to-3.3.1.patch Provides: %{name}-libs = %{version}-%{release} Obsoletes: %{name}-libs < %{version}-%{release} @@ -882,6 +883,9 @@ %{gem_dir}/specifications/matrix-%{matrix_version}.gemspec %changelog +* Sat Jul 06 2024 shixuantong <shixuantong1@huawei.com> - 3.2.2-142 +- upgrade rexml to fix CVE-2024-35176 + * Tue Jun 18 2024 shixuantong <shixuantong1@huawei.com> - 3.2.2-141 - fix CVE-2024-35221
View file
_service:tar_scm:upgrade-lib-rexml-to-3.3.1.patch
Added
@@ -0,0 +1,1824 @@ +From 20017eea807e8fa386aa5c79ae779004d8b366dd Mon Sep 17 00:00:00 2001 +From: Sutou Kouhei <kou@clear-code.com> +Date: Tue, 25 Jun 2024 11:26:33 +0900 +Subject: PATCH Add 3.3.1 entry + +Backport from https://github.com/ruby/rexml/tree/v3.3.1/lib/rexml + +--- + .../gems/rexml-3.2.5/lib/rexml/attribute.rb | 23 +- + .../gems/rexml-3.2.5/lib/rexml/document.rb | 2 +- + .bundle/gems/rexml-3.2.5/lib/rexml/element.rb | 23 +- + .bundle/gems/rexml-3.2.5/lib/rexml/entity.rb | 40 +- + .../lib/rexml/formatters/pretty.rb | 4 +- + .../gems/rexml-3.2.5/lib/rexml/functions.rb | 3 +- + .../gems/rexml-3.2.5/lib/rexml/namespace.rb | 12 +- + .bundle/gems/rexml-3.2.5/lib/rexml/node.rb | 12 +- + .../rexml-3.2.5/lib/rexml/parseexception.rb | 1 + + .../lib/rexml/parsers/baseparser.rb | 521 ++++++++++-------- + .../lib/rexml/parsers/treeparser.rb | 23 +- + .../lib/rexml/parsers/xpathparser.rb | 222 +++++--- + .bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb | 4 +- + .bundle/gems/rexml-3.2.5/lib/rexml/source.rb | 220 ++++---- + .bundle/gems/rexml-3.2.5/lib/rexml/text.rb | 10 +- + .../rexml-3.2.5/lib/rexml/xpath_parser.rb | 10 +- + 16 files changed, 627 insertions(+), 503 deletions(-) + +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb +index 8933a01..11893a9 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb +@@ -1,4 +1,4 @@ +-# frozen_string_literal: false ++# frozen_string_literal: true + require_relative "namespace" + require_relative 'text' + +@@ -13,9 +13,6 @@ module REXML + + # The element to which this attribute belongs + attr_reader :element +- # The normalized value of this attribute. That is, the attribute with +- # entities intact. +- attr_writer :normalized + PATTERN = /\s*(#{NAME_STR})\s*=\s*("')(.*?)\2/um + + NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:xa-fA-F0-9+)));)?)/um +@@ -122,10 +119,13 @@ module REXML + # b = Attribute.new( "ns:x", "y" ) + # b.to_string # -> "ns:x='y'" + def to_string ++ value = to_s + if @element and @element.context and @element.context:attribute_quote == :quote +- %Q^#@expanded_name="#{to_s().gsub(/"/, '"')}"^ ++ value = value.gsub('"', '"') if value.include?('"') ++ %Q^#@expanded_name="#{value}"^ + else +- "#@expanded_name='#{to_s().gsub(/'/, ''')}'" ++ value = value.gsub("'", ''') if value.include?("'") ++ "#@expanded_name='#{value}'" + end + end + +@@ -141,7 +141,6 @@ module REXML + return @normalized if @normalized + + @normalized = Text::normalize( @unnormalized, doctype ) +- @unnormalized = nil + @normalized + end + +@@ -150,10 +149,16 @@ module REXML + def value + return @unnormalized if @unnormalized + @unnormalized = Text::unnormalize( @normalized, doctype ) +- @normalized = nil + @unnormalized + end + ++ # The normalized value of this attribute. That is, the attribute with ++ # entities intact. ++ def normalized=(new_normalized) ++ @normalized = new_normalized ++ @unnormalized = nil ++ end ++ + # Returns a copy of this attribute + def clone + Attribute.new self +@@ -190,7 +195,7 @@ module REXML + end + + def inspect +- rv = "" ++ rv = +"" + write( rv ) + rv + end +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb +index 2edeb98..b1caa02 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb +@@ -69,7 +69,7 @@ module REXML + # d.to_s # => "<root><foo>Foo</foo><bar>Bar</bar></root>" + # + # When argument +document+ is given, it must be an existing +- # document object, whose context and attributes (but not chidren) ++ # document object, whose context and attributes (but not children) + # are cloned into the new document: + # + # d = REXML::Document.new(xml_string) +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb +index 4c21dbd..a5808d7 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb +@@ -7,14 +7,6 @@ require_relative "xpath" + require_relative "parseexception" + + module REXML +- # An implementation note about namespaces: +- # As we parse, when we find namespaces we put them in a hash and assign +- # them a unique ID. We then convert the namespace prefix for the node +- # to the unique ID. This makes namespace lookup much faster for the +- # cost of extra memory use. We save the namespace prefix for the +- # context node and convert it back when we write it. +- @@namespaces = {} +- + # An \REXML::Element object represents an XML element. + # + # An element: +@@ -989,7 +981,7 @@ module REXML + # :call-seq: + # has_text? -> true or false + # +- # Returns +true if the element has one or more text noded, ++ # Returns +true+ if the element has one or more text noded, + # +false+ otherwise: + # + # d = REXML::Document.new '<a><b/>text<c/></a>' +@@ -1006,7 +998,7 @@ module REXML + # text(xpath = nil) -> text_string or nil + # + # Returns the text string from the first text node child +- # in a specified element, if it exists, # +nil+ otherwise. ++ # in a specified element, if it exists, +nil+ otherwise. + # + # With no argument, returns the text from the first text node in +self+: + # +@@ -1014,7 +1006,7 @@ module REXML + # d.root.text.class # => String + # d.root.text # => "some text " + # +- # With argument +xpath+, returns text from the the first text node ++ # With argument +xpath+, returns text from the first text node + # in the element that matches +xpath+: + # + # d.root.text(1) # => "this is bold!" +@@ -1284,16 +1276,11 @@ module REXML + # document.root.attribute("x", "a") # => a:x='a:x' + # + def attribute( name, namespace=nil ) +- prefix = nil +- if namespaces.respond_to? :key +- prefix = namespaces.key(namespace) if namespace +- else +- prefix = namespaces.index(namespace) if namespace +- end ++ prefix = namespaces.key(namespace) if namespace + prefix = nil if prefix == 'xmlns' + + ret_val = +- attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" ) ++ attributes.get_attribute( prefix ? "#{prefix}:#{name}" : name ) + + return ret_val unless ret_val.nil? + return nil if prefix.nil? +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb +index 89a9e84..573db69 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb +@@ -132,24 +132,34 @@ module REXML + # then: + # doctype.entity('yada').value #-> "nanoo bar nanoo" + def value +- if @value +- matches = @value.scan(PEREFERENCE_RE) +- rv = @value.clone +- if @parent +- sum = 0 +- matches.each do |entity_reference| +- entity_value = @parent.entity( entity_reference0 ) +- if sum + entity_value.bytesize > Security.entity_expansion_text_limit +- raise "entity expansion has grown too large" +- else +- sum += entity_value.bytesize +- end +- rv.gsub!( /%#{entity_reference.join};/um, entity_value ) ++ @resolved_value ||= resolve_value ++ end ++ ++ def parent=(other) ++ @resolved_value = nil ++ super ++ end ++ ++ private ++ def resolve_value ++ return nil if @value.nil? ++ return @value unless @value.match?(PEREFERENCE_RE) ++ ++ matches = @value.scan(PEREFERENCE_RE) ++ rv = @value.clone ++ if @parent ++ sum = 0 ++ matches.each do |entity_reference| ++ entity_value = @parent.entity( entity_reference0 ) ++ if sum + entity_value.bytesize > Security.entity_expansion_text_limit ++ raise "entity expansion has grown too large" ++ else ++ sum += entity_value.bytesize + end ++ rv.gsub!( /%#{entity_reference.join};/um, entity_value ) + end +- return rv + end +- nil ++ rv + end + end + +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +index 562ef94..a1198b7 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +@@ -1,4 +1,4 @@ +-# frozen_string_literal: false ++# frozen_string_literal: true + require_relative 'default' + + module REXML +@@ -58,7 +58,7 @@ module REXML + skip = false + if compact + if node.children.inject(true) {|s,c| s & c.kind_of?(Text)} +- string = "" ++ string = +"" + old_level = @level + @level = 0 + node.children.each { |child| write( child, string ) } +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb +index 77926bf..4c11461 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb +@@ -262,11 +262,10 @@ module REXML + string(string).length + end + +- # UNTESTED + def Functions::normalize_space( string=nil ) + string = string(@@context:node) if string.nil? + if string.kind_of? Array +- string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string} ++ string.collect{|x| x.to_s.strip.gsub(/\s+/um, ' ') if x} + else + string.to_s.strip.gsub(/\s+/um, ' ') + end +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb +index 924edf9..2e67252 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb +@@ -1,4 +1,4 @@ +-# frozen_string_literal: false ++# frozen_string_literal: true + + require_relative 'xmltokens' + +@@ -10,13 +10,17 @@ module REXML + # The expanded name of the object, valid if name is set + attr_accessor :prefix + include XMLTokens ++ NAME_WITHOUT_NAMESPACE = /\A#{NCNAME_STR}\z/ + NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u + + # Sets the name and the expanded name + def name=( name ) + @expanded_name = name +- case name +- when NAMESPLIT ++ if name.match?(NAME_WITHOUT_NAMESPACE) ++ @prefix = "" ++ @namespace = "" ++ @name = name ++ elsif name =~ NAMESPLIT + if $1 + @prefix = $1 + else +@@ -24,7 +28,7 @@ module REXML + @namespace = "" + end + @name = $2 +- when "" ++ elsif name == "" + @prefix = nil + @namespace = nil + @name = nil +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb +index 081caba..c771db7 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb +@@ -52,10 +52,14 @@ module REXML + + # Visit all subnodes of +self+ recursively + def each_recursive(&block) # :yields: node +- self.elements.each {|node| +- block.call(node) +- node.each_recursive(&block) +- } ++ stack = ++ each { |child| stack.unshift child if child.node_type == :element } ++ until stack.empty? ++ child = stack.pop ++ yield child ++ n = stack.size ++ child.each { |grandchild| stack.insert n, grandchild if grandchild.node_type == :element } ++ end + end + + # Find (and return) first subnode (recursively) for which the block +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb +index 7b16cd1..e57d05f 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb +@@ -29,6 +29,7 @@ module REXML + err << "\nLine: #{line}\n" + err << "Position: #{position}\n" + err << "Last 80 unconsumed characters:\n" ++ err.force_encoding("ASCII-8BIT") + err << @source.buffer0..80.force_encoding("ASCII-8BIT").gsub(/\n/, ' ') + end + +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +index 305b120..275372e 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +@@ -1,4 +1,4 @@ +-# frozen_string_literal: false ++# frozen_string_literal: true + require_relative '../parseexception' + require_relative '../undefinednamespaceexception' + require_relative '../source' +@@ -7,6 +7,17 @@ require "strscan" + + module REXML + module Parsers ++ if StringScanner::Version < "3.0.8" ++ module StringScannerCaptures ++ refine StringScanner do ++ def captures ++ values_at(*(1...size)) ++ end ++ end ++ end ++ using StringScannerCaptures ++ end ++ + # = Using the Pull Parser + # <em>This API is experimental, and subject to change.</em> + # parser = PullParser.new( "<a>text<b att='val'/>txet</a>" ) +@@ -96,7 +107,7 @@ module REXML + ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" + PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" + GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" +- ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um ++ ENTITYDECL = /\s*(?:#{GEDECL})|\s*(?:#{PEDECL})/um + + NOTATIONDECL_START = /\A\s*<!NOTATION/um + EXTERNAL_ID_PUBLIC = /\A\s*PUBLIC\s+#{PUBIDLITERAL}\s+#{SYSTEMLITERAL}\s*/um +@@ -112,9 +123,29 @@ module REXML + "apos" => /'/, "'", "'", /'/ + } + ++ module Private ++ INSTRUCTION_END = /#{NAME}(\s+.*?)?\?>/um ++ TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um ++ CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um ++ ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um ++ NAME_PATTERN = /\s*#{NAME}/um ++ GEDECL_PATTERN = "\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" ++ PEDECL_PATTERN = "\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" ++ ENTITYDECL_PATTERN = /(?:#{GEDECL_PATTERN})|(?:#{PEDECL_PATTERN})/um ++ CARRIAGE_RETURN_NEWLINE_PATTERN = /\r\n?/ ++ CHARACTER_REFERENCES = /�*((?:\d+)|(?:xa-fA-F0-9+));/ ++ DEFAULT_ENTITIES_PATTERNS = {} ++ default_entities = 'gt', 'lt', 'quot', 'apos', 'amp' ++ default_entities.each do |term| ++ DEFAULT_ENTITIES_PATTERNSterm = /&#{term};/ ++ end ++ end ++ private_constant :Private ++ + def initialize( source ) + self.stream = source + @listeners = ++ @prefixes = Set.new + end + + def add_listener( listener ) +@@ -180,6 +211,8 @@ module REXML + + # Returns the next event. This is a +PullEvent+ object. + def pull ++ @source.drop_parsed_content ++ + pull_event.tap do |event| + @listeners.each do |listener| + listener.receive event +@@ -192,236 +225,251 @@ module REXML + x, @closed = @closed, nil + return :end_element, x + end +- return :end_document if empty? ++ if empty? ++ if @document_status == :in_doctype ++ raise ParseException.new("Malformed DOCTYPE: unclosed", @source) ++ end ++ return :end_document ++ end + return @stack.shift if @stack.size > 0 + #STDERR.puts @source.encoding + #STDERR.puts "BUFFER = #{@source.buffer.inspect}" ++ ++ @source.ensure_buffer + if @document_status == nil +- word = @source.match( /\A((?:\s+)|(?:<^>*>))/um ) +- word = word1 unless word.nil? +- #STDERR.puts "WORD = #{word.inspect}" +- case word +- when COMMENT_START +- return :comment, @source.match( COMMENT_PATTERN, true )1 +- when XMLDECL_START +- #STDERR.puts "XMLDECL" +- results = @source.match( XMLDECL_PATTERN, true )1 +- version = VERSION.match( results ) +- version = version1 unless version.nil? +- encoding = ENCODING.match(results) +- encoding = encoding1 unless encoding.nil? +- if need_source_encoding_update?(encoding) +- @source.encoding = encoding +- end +- if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding +- encoding = "UTF-16" +- end +- standalone = STANDALONE.match(results) +- standalone = standalone1 unless standalone.nil? +- return :xmldecl, version, encoding, standalone +- when INSTRUCTION_START +- return process_instruction +- when DOCTYPE_START +- base_error_message = "Malformed DOCTYPE" +- @source.match(DOCTYPE_START, true) +- @nsstack.unshift(curr_ns=Set.new) +- name = parse_name(base_error_message) +- if @source.match(/\A\s*\/um, true) +- id = nil, nil, nil +- @document_status = :in_doctype +- elsif @source.match(/\A\s*>/um, true) +- id = nil, nil, nil +- @document_status = :after_doctype +- else +- id = parse_id(base_error_message, +- accept_external_id: true, +- accept_public_id: false) +- if id0 == "SYSTEM" +- # For backward compatibility +- id1, id2 = id2, nil ++ start_position = @source.position ++ if @source.match("<?", true) ++ return process_instruction(start_position) ++ elsif @source.match("<!", true) ++ if @source.match("--", true) ++ md = @source.match(/(.*?)-->/um, true) ++ if md.nil? ++ raise REXML::ParseException.new("Unclosed comment", @source) ++ end ++ if /--|-\z/.match?(md1) ++ raise REXML::ParseException.new("Malformed comment", @source) + end +- if @source.match(/\A\s*\/um, true) ++ return :comment, md1 ++ elsif @source.match("DOCTYPE", true) ++ base_error_message = "Malformed DOCTYPE" ++ unless @source.match(/\s+/um, true) ++ if @source.match(">") ++ message = "#{base_error_message}: name is missing" ++ else ++ message = "#{base_error_message}: invalid name" ++ end ++ @source.position = start_position ++ raise REXML::ParseException.new(message, @source) ++ end ++ @nsstack.unshift(Set.new) ++ name = parse_name(base_error_message) ++ if @source.match(/\s*\/um, true) ++ id = nil, nil, nil + @document_status = :in_doctype +- elsif @source.match(/\A\s*>/um, true) ++ elsif @source.match(/\s*>/um, true) ++ id = nil, nil, nil + @document_status = :after_doctype ++ @source.ensure_buffer + else +- message = "#{base_error_message}: garbage after external ID" +- raise REXML::ParseException.new(message, @source) ++ id = parse_id(base_error_message, ++ accept_external_id: true, ++ accept_public_id: false) ++ if id0 == "SYSTEM" ++ # For backward compatibility ++ id1, id2 = id2, nil ++ end ++ if @source.match(/\s*\/um, true) ++ @document_status = :in_doctype ++ elsif @source.match(/\s*>/um, true) ++ @document_status = :after_doctype ++ @source.ensure_buffer ++ else ++ message = "#{base_error_message}: garbage after external ID" ++ raise REXML::ParseException.new(message, @source) ++ end + end +- end +- args = :start_doctype, name, *id +- if @document_status == :after_doctype +- @source.match(/\A\s*/um, true) +- @stack << :end_doctype +- end +- return args +- when /\A\s+/ +- else +- @document_status = :after_doctype +- if @source.encoding == "UTF-8" +- @source.buffer.force_encoding(::Encoding::UTF_8) ++ args = :start_doctype, name, *id ++ if @document_status == :after_doctype ++ @source.match(/\s*/um, true) ++ @stack << :end_doctype ++ end ++ return args ++ else ++ message = "Invalid XML" ++ raise REXML::ParseException.new(message, @source) + end + end + end + if @document_status == :in_doctype +- md = @source.match(/\A\s*(.*?>)/um) +- case md1 +- when SYSTEMENTITY +- match = @source.match( SYSTEMENTITY, true )1 +- return :externalentity, match +- +- when ELEMENTDECL_START +- return :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )1 +- +- when ENTITY_START +- match = @source.match( ENTITYDECL, true ).to_a.compact +- match0 = :entitydecl +- ref = false +- if match1 == '%' +- ref = true +- match.delete_at 1 +- end +- # Now we have to sort out what kind of entity reference this is +- if match2 == 'SYSTEM' +- # External reference +- match3 = match31..-2 # PUBID +- match.delete_at(4) if match.size > 4 # Chop out NDATA decl +- # match is :entity, name, SYSTEM, pubid(, ndata)? +- elsif match2 == 'PUBLIC' +- # External reference +- match3 = match31..-2 # PUBID +- match4 = match41..-2 # HREF +- match.delete_at(5) if match.size > 5 # Chop out NDATA decl +- # match is :entity, name, PUBLIC, pubid, href(, ndata)? +- else +- match2 = match21..-2 +- match.pop if match.size == 4 +- # match is :entity, name, value +- end +- match << '%' if ref +- return match +- when ATTLISTDECL_START +- md = @source.match( ATTLISTDECL_PATTERN, true ) +- raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil? +- element = md1 +- contents = md0 +- +- pairs = {} +- values = md0.scan( ATTDEF_RE ) +- values.each do |attdef| +- unless attdef3 == "#IMPLIED" +- attdef.compact! +- val = attdef3 +- val = attdef4 if val == "#FIXED " +- pairsattdef0 = val +- if attdef0 =~ /^xmlns:(.*)/ +- @nsstack0 << $1 +- end ++ @source.match(/\s*/um, true) # skip spaces ++ start_position = @source.position ++ if @source.match("<!", true) ++ if @source.match("ELEMENT", true) ++ md = @source.match(/(.*?)>/um, true) ++ raise REXML::ParseException.new( "Bad ELEMENT declaration!", @source ) if md.nil? ++ return :elementdecl, "<!ELEMENT" + md1 ++ elsif @source.match("ENTITY", true) ++ match = :entitydecl, *@source.match(Private::ENTITYDECL_PATTERN, true).captures.compact ++ ref = false ++ if match1 == '%' ++ ref = true ++ match.delete_at 1 + end +- end +- return :attlistdecl, element, pairs, contents +- when NOTATIONDECL_START +- base_error_message = "Malformed notation declaration" +- unless @source.match(/\A\s*<!NOTATION\s+/um, true) +- if @source.match(/\A\s*<!NOTATION\s*>/um) +- message = "#{base_error_message}: name is missing" ++ # Now we have to sort out what kind of entity reference this is ++ if match2 == 'SYSTEM' ++ # External reference ++ match3 = match31..-2 # PUBID ++ match.delete_at(4) if match.size > 4 # Chop out NDATA decl ++ # match is :entity, name, SYSTEM, pubid(, ndata)? ++ elsif match2 == 'PUBLIC' ++ # External reference ++ match3 = match31..-2 # PUBID ++ match4 = match41..-2 # HREF ++ match.delete_at(5) if match.size > 5 # Chop out NDATA decl ++ # match is :entity, name, PUBLIC, pubid, href(, ndata)? + else +- message = "#{base_error_message}: invalid declaration name" ++ match2 = match21..-2 ++ match.pop if match.size == 4 ++ # match is :entity, name, value + end +- raise REXML::ParseException.new(message, @source) +- end +- name = parse_name(base_error_message) +- id = parse_id(base_error_message, +- accept_external_id: true, +- accept_public_id: true) +- unless @source.match(/\A\s*>/um, true) +- message = "#{base_error_message}: garbage before end >" +- raise REXML::ParseException.new(message, @source) ++ match << '%' if ref ++ return match ++ elsif @source.match("ATTLIST", true) ++ md = @source.match(Private::ATTLISTDECL_END, true) ++ raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil? ++ element = md1 ++ contents = md0 ++ ++ pairs = {} ++ values = md0.scan( ATTDEF_RE ) ++ values.each do |attdef| ++ unless attdef3 == "#IMPLIED" ++ attdef.compact! ++ val = attdef3 ++ val = attdef4 if val == "#FIXED " ++ pairsattdef0 = val ++ if attdef0 =~ /^xmlns:(.*)/ ++ @nsstack0 << $1 ++ end ++ end ++ end ++ return :attlistdecl, element, pairs, contents ++ elsif @source.match("NOTATION", true) ++ base_error_message = "Malformed notation declaration" ++ unless @source.match(/\s+/um, true) ++ if @source.match(">") ++ message = "#{base_error_message}: name is missing" ++ else ++ message = "#{base_error_message}: invalid name" ++ end ++ @source.position = start_position ++ raise REXML::ParseException.new(message, @source) ++ end ++ name = parse_name(base_error_message) ++ id = parse_id(base_error_message, ++ accept_external_id: true, ++ accept_public_id: true) ++ unless @source.match(/\s*>/um, true) ++ message = "#{base_error_message}: garbage before end >" ++ raise REXML::ParseException.new(message, @source) ++ end ++ return :notationdecl, name, *id ++ elsif md = @source.match(/--(.*?)-->/um, true) ++ case md1 ++ when /--/, /-\z/ ++ raise REXML::ParseException.new("Malformed comment", @source) ++ end ++ return :comment, md1 if md + end +- return :notationdecl, name, *id +- when DOCTYPE_END ++ elsif match = @source.match(/(%.*?;)\s*/um, true) ++ return :externalentity, match1 ++ elsif @source.match(/\\s*>/um, true) + @document_status = :after_doctype +- @source.match( DOCTYPE_END, true ) + return :end_doctype + end ++ if @document_status == :in_doctype ++ raise ParseException.new("Malformed DOCTYPE: invalid declaration", @source) ++ end + end + if @document_status == :after_doctype +- @source.match(/\A\s*/um, true) ++ @source.match(/\s*/um, true) + end + begin +- @source.read if @source.buffer.size<2 +- if @source.buffer0 == ?< +- if @source.buffer1 == ?/ ++ start_position = @source.position ++ if @source.match("<", true) ++ # :text's read_until may remain only "<" in buffer. In the ++ # case, buffer is empty here. So we need to fill buffer ++ # here explicitly. ++ @source.ensure_buffer ++ if @source.match("/", true) + @nsstack.shift + last_tag = @tags.pop +- md = @source.match( CLOSE_MATCH, true ) ++ md = @source.match(Private::CLOSE_PATTERN, true) + if md and !last_tag + message = "Unexpected top-level end tag (got '#{md1}')" + raise REXML::ParseException.new(message, @source) + end + if md.nil? or last_tag != md1 + message = "Missing end tag for '#{last_tag}'" +- message << " (got '#{md1}')" if md ++ message += " (got '#{md1}')" if md ++ @source.position = start_position if md.nil? + raise REXML::ParseException.new(message, @source) + end + return :end_element, last_tag +- elsif @source.buffer1 == ?! +- md = @source.match(/\A(\s*^>*>)/um) ++ elsif @source.match("!", true) ++ md = @source.match(/(^>*>)/um) + #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}" + raise REXML::ParseException.new("Malformed node", @source) unless md +- if md02 == ?- +- md = @source.match( COMMENT_PATTERN, true ) ++ if md00 == ?- ++ md = @source.match(/--(.*?)-->/um, true) + +- case md1 +- when /--/, /-\z/ ++ if md.nil? || /--|-\z/.match?(md1) + raise REXML::ParseException.new("Malformed comment", @source) + end + +- return :comment, md1 if md ++ return :comment, md1 + else +- md = @source.match( CDATA_PATTERN, true ) ++ md = @source.match(/\CDATA\(.*?)\\>/um, true) + return :cdata, md1 if md + end + raise REXML::ParseException.new( "Declarations can only occur "+ + "in the doctype declaration.", @source) +- elsif @source.buffer1 == ?? +- return process_instruction ++ elsif @source.match("?", true) ++ return process_instruction(start_position) + else + # Get the next tag +- md = @source.match(TAG_MATCH, true) ++ md = @source.match(Private::TAG_PATTERN, true) + unless md ++ @source.position = start_position + raise REXML::ParseException.new("malformed XML: missing tag start", @source) + end ++ tag = md1 + @document_status = :in_element +- prefixes = Set.new +- prefixes << md2 if md2 ++ @prefixes.clear ++ @prefixes << md2 if md2 + @nsstack.unshift(curr_ns=Set.new) +- attributes, closed = parse_attributes(prefixes, curr_ns) ++ attributes, closed = parse_attributes(@prefixes, curr_ns) + # Verify that all of the prefixes have been defined +- for prefix in prefixes ++ for prefix in @prefixes + unless @nsstack.find{|k| k.member?(prefix)} + raise UndefinedNamespaceException.new(prefix,@source,self) + end + end + + if closed +- @closed = md1 ++ @closed = tag + @nsstack.shift + else +- @tags.push( md1 ) ++ @tags.push( tag ) + end +- return :start_element, md1, attributes ++ return :start_element, tag, attributes + end + else +- md = @source.match( TEXT_PATTERN, true ) +- if md0.length == 0 +- @source.match( /(\s+)/, true ) ++ text = @source.read_until("<") ++ if text.chomp!("<") ++ @source.position -= "<".bytesize + end +- #STDERR.puts "GOT #{md1.inspect}" unless md0.length == 0 +- #return :text, "" if md0.length == 0 +- # unnormalized = Text::unnormalize( md1, self ) +- # return PullEvent.new( :text, md1, unnormalized ) +- return :text, md1 ++ return :text, text + end + rescue REXML::UndefinedNamespaceException + raise +@@ -463,11 +511,10 @@ module REXML + + # Unescapes all possible entities + def unnormalize( string, entities=nil, filter=nil ) +- rv = string.clone +- rv.gsub!( /\r\n?/, "\n" ) ++ rv = string.gsub( Private::CARRIAGE_RETURN_NEWLINE_PATTERN, "\n" ) + matches = rv.scan( REFERENCE_RE ) + return rv if matches.size == 0 +- rv.gsub!( /�*((?:\d+)|(?:xa-fA-F0-9+));/ ) { ++ rv.gsub!( Private::CHARACTER_REFERENCES ) { + m=$1 + m = "0#{m}" if m0 == ?x + Integer(m).pack('U*') +@@ -478,7 +525,7 @@ module REXML + unless filter and filter.include?(entity_reference) + entity_value = entity( entity_reference, entities ) + if entity_value +- re = /&#{entity_reference};/ ++ re = Private::DEFAULT_ENTITIES_PATTERNSentity_reference || /&#{entity_reference};/ + rv.gsub!( re, entity_value ) + else + er = DEFAULT_ENTITIESentity_reference +@@ -486,7 +533,7 @@ module REXML + end + end + end +- rv.gsub!( /&/, '&' ) ++ rv.gsub!( Private::DEFAULT_ENTITIES_PATTERNS'amp', '&' ) + end + rv + end +@@ -499,9 +546,9 @@ module REXML + end + + def parse_name(base_error_message) +- md = @source.match(/\A\s*#{NAME}/um, true) ++ md = @source.match(Private::NAME_PATTERN, true) + unless md +- if @source.match(/\A\s*\S/um) ++ if @source.match(/\s*\S/um) + message = "#{base_error_message}: invalid name" + else + message = "#{base_error_message}: name is missing" +@@ -577,97 +624,91 @@ module REXML + end + end + +- def process_instruction +- match_data = @source.match(INSTRUCTION_PATTERN, true) ++ def process_instruction(start_position) ++ match_data = @source.match(Private::INSTRUCTION_END, true) + unless match_data + message = "Invalid processing instruction node" ++ @source.position = start_position + raise REXML::ParseException.new(message, @source) + end ++ if @document_status.nil? and match_data1 == "xml" ++ content = match_data2 ++ version = VERSION.match(content) ++ version = version1 unless version.nil? ++ encoding = ENCODING.match(content) ++ encoding = encoding1 unless encoding.nil? ++ if need_source_encoding_update?(encoding) ++ @source.encoding = encoding ++ end ++ if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding ++ encoding = "UTF-16" ++ end ++ standalone = STANDALONE.match(content) ++ standalone = standalone1 unless standalone.nil? ++ return :xmldecl, version, encoding, standalone ++ end + :processing_instruction, match_data1, match_data2 + end + + def parse_attributes(prefixes, curr_ns) + attributes = {} + closed = false +- match_data = @source.match(/^(.*?)(\/)?>/um, true) +- if match_data.nil? +- message = "Start tag isn't ended" +- raise REXML::ParseException.new(message, @source) +- end +- +- raw_attributes = match_data1 +- closed = !match_data2.nil? +- return attributes, closed if raw_attributes.nil? +- return attributes, closed if raw_attributes.empty? +- +- scanner = StringScanner.new(raw_attributes) +- until scanner.eos? +- if scanner.scan(/\s+/) +- break if scanner.eos? +- end +- +- pos = scanner.pos +- loop do +- break if scanner.scan(ATTRIBUTE_PATTERN) +- unless scanner.scan(QNAME) +- message = "Invalid attribute name: <#{scanner.rest}>" +- raise REXML::ParseException.new(message, @source) +- end +- name = scanner0 +- unless scanner.scan(/\s*=\s*/um) ++ while true ++ if @source.match(">", true) ++ return attributes, closed ++ elsif @source.match("/>", true) ++ closed = true ++ return attributes, closed ++ elsif match = @source.match(QNAME, true) ++ name = match1 ++ prefix = match2 ++ local_part = match3 ++ ++ unless @source.match(/\s*=\s*/um, true) + message = "Missing attribute equal: <#{name}>" + raise REXML::ParseException.new(message, @source) + end +- quote = scanner.scan(/'"/) +- unless quote ++ unless match = @source.match(/('")/, true) + message = "Missing attribute value start quote: <#{name}>" + raise REXML::ParseException.new(message, @source) + end +- unless scanner.scan(/.*#{Regexp.escape(quote)}/um) +- match_data = @source.match(/^(.*?)(\/)?>/um, true) +- if match_data +- scanner << "/" if closed +- scanner << ">" +- scanner << match_data1 +- scanner.pos = pos +- closed = !match_data2.nil? +- next +- end +- message = +- "Missing attribute value end quote: <#{name}>: <#{quote}>" ++ quote = match1 ++ start_position = @source.position ++ value = @source.read_until(quote) ++ unless value.chomp!(quote) ++ @source.position = start_position ++ message = "Missing attribute value end quote: <#{name}>: <#{quote}>" + raise REXML::ParseException.new(message, @source) + end +- end +- name = scanner1 +- prefix = scanner2 +- local_part = scanner3 +- # quote = scanner4 +- value = scanner5 +- if prefix == "xmlns" +- if local_part == "xml" +- if value != "http://www.w3.org/XML/1998/namespace" +- msg = "The 'xml' prefix must not be bound to any other namespace "+ ++ @source.match(/\s*/um, true) ++ if prefix == "xmlns" ++ if local_part == "xml" ++ if value != "http://www.w3.org/XML/1998/namespace" ++ msg = "The 'xml' prefix must not be bound to any other namespace "+ ++ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" ++ raise REXML::ParseException.new( msg, @source, self ) ++ end ++ elsif local_part == "xmlns" ++ msg = "The 'xmlns' prefix must not be declared "+ + "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" +- raise REXML::ParseException.new( msg, @source, self ) ++ raise REXML::ParseException.new( msg, @source, self) + end +- elsif local_part == "xmlns" +- msg = "The 'xmlns' prefix must not be declared "+ +- "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" +- raise REXML::ParseException.new( msg, @source, self) ++ curr_ns << local_part ++ elsif prefix ++ prefixes << prefix unless prefix == "xml" + end +- curr_ns << local_part +- elsif prefix +- prefixes << prefix unless prefix == "xml" +- end + +- if attributes.has_key?(name) +- msg = "Duplicate attribute #{name.inspect}" +- raise REXML::ParseException.new(msg, @source, self) +- end ++ if attributesname ++ msg = "Duplicate attribute #{name.inspect}" ++ raise REXML::ParseException.new(msg, @source, self) ++ end + +- attributesname = value ++ attributesname = value ++ else ++ message = "Invalid attribute name: <#{@source.buffer.split(%r{/>\s}).first}>" ++ raise REXML::ParseException.new(message, @source) ++ end + end +- return attributes, closed + end + end + end +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb +index bf9a425..0cb6f7c 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb +@@ -16,7 +16,6 @@ module REXML + + def parse + tag_stack = +- in_doctype = false + entities = nil + begin + while true +@@ -39,17 +38,15 @@ module REXML + tag_stack.pop + @build_context = @build_context.parent + when :text +- if not in_doctype +- if @build_context-1.instance_of? Text +- @build_context-1 << event1 +- else +- @build_context.add( +- Text.new(event1, @build_context.whitespace, nil, true) +- ) unless ( +- @build_context.ignore_whitespace_nodes and +- event1.strip.size==0 +- ) +- end ++ if @build_context-1.instance_of? Text ++ @build_context-1 << event1 ++ else ++ @build_context.add( ++ Text.new(event1, @build_context.whitespace, nil, true) ++ ) unless ( ++ @build_context.ignore_whitespace_nodes and ++ event1.strip.size==0 ++ ) + end + when :comment + c = Comment.new( event1 ) +@@ -60,14 +57,12 @@ module REXML + when :processing_instruction + @build_context.add( Instruction.new( event1, event2 ) ) + when :end_doctype +- in_doctype = false + entities.each { |k,v| entitiesk = @build_context.entitiesk.value } + @build_context = @build_context.parent + when :start_doctype + doctype = DocType.new( event1..-1, @build_context ) + @build_context = doctype + entities = {} +- in_doctype = true + when :attlistdecl + n = AttlistDecl.new( event1..-1 ) + @build_context.add( n ) +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb +index d92678f..bd3b685 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb +@@ -1,4 +1,5 @@ + # frozen_string_literal: false ++ + require_relative '../namespace' + require_relative '../xmltokens' + +@@ -38,108 +39,143 @@ module REXML + parsed + end + +- def abbreviate( path ) +- path = path.kind_of?(String) ? parse( path ) : path +- string = "" +- document = false +- while path.size > 0 +- op = path.shift ++ def abbreviate(path_or_parsed) ++ if path_or_parsed.kind_of?(String) ++ parsed = parse(path_or_parsed) ++ else ++ parsed = path_or_parsed ++ end ++ components = ++ component = nil ++ while parsed.size > 0 ++ op = parsed.shift + case op + when :node ++ component << "node()" + when :attribute +- string << "/" if string.size > 0 +- string << "@" ++ component = "@" ++ components << component + when :child +- string << "/" if string.size > 0 ++ component = "" ++ components << component + when :descendant_or_self +- string << "/" ++ next_op = parsed0 ++ if next_op == :node ++ parsed.shift ++ component = "" ++ components << component ++ else ++ component = "descendant-or-self::" ++ components << component ++ end + when :self +- string << "." ++ next_op = parsed0 ++ if next_op == :node ++ parsed.shift ++ components << "." ++ else ++ component = "self::" ++ components << component ++ end + when :parent +- string << ".." ++ next_op = parsed0 ++ if next_op == :node ++ parsed.shift ++ components << ".." ++ else ++ component = "parent::" ++ components << component ++ end + when :any +- string << "*" ++ component << "*" + when :text +- string << "text()" ++ component << "text()" + when :following, :following_sibling, + :ancestor, :ancestor_or_self, :descendant, + :namespace, :preceding, :preceding_sibling +- string << "/" unless string.size == 0 +- string << op.to_s.tr("_", "-") +- string << "::" ++ component = op.to_s.tr("_", "-") << "::" ++ components << component + when :qname +- prefix = path.shift +- name = path.shift +- string << prefix+":" if prefix.size > 0 +- string << name ++ prefix = parsed.shift ++ name = parsed.shift ++ component << prefix+":" if prefix.size > 0 ++ component << name + when :predicate +- string << '' +- string << predicate_to_string( path.shift ) {|x| abbreviate( x ) } +- string << '' ++ component << '' ++ component << predicate_to_path(parsed.shift) {|x| abbreviate(x)} ++ component << '' + when :document +- document = true ++ components << "" + when :function +- string << path.shift +- string << "( " +- string << predicate_to_string( path.shift0 ) {|x| abbreviate( x )} +- string << " )" ++ component << parsed.shift ++ component << "( " ++ component << predicate_to_path(parsed.shift0) {|x| abbreviate(x)} ++ component << " )" + when :literal +- string << %Q{ "#{path.shift}" } ++ component << quote_literal(parsed.shift) + else +- string << "/" unless string.size == 0 +- string << "UNKNOWN(" +- string << op.inspect +- string << ")" ++ component << "UNKNOWN(" ++ component << op.inspect ++ component << ")" + end + end +- string = "/"+string if document +- return string ++ case components ++ when "" ++ "/" ++ when "", "" ++ "//" ++ else ++ components.join("/") ++ end + end + +- def expand( path ) +- path = path.kind_of?(String) ? parse( path ) : path +- string = "" ++ def expand(path_or_parsed) ++ if path_or_parsed.kind_of?(String) ++ parsed = parse(path_or_parsed) ++ else ++ parsed = path_or_parsed ++ end ++ path = "" + document = false +- while path.size > 0 +- op = path.shift ++ while parsed.size > 0 ++ op = parsed.shift + case op + when :node +- string << "node()" ++ path << "node()" + when :attribute, :child, :following, :following_sibling, + :ancestor, :ancestor_or_self, :descendant, :descendant_or_self, + :namespace, :preceding, :preceding_sibling, :self, :parent +- string << "/" unless string.size == 0 +- string << op.to_s.tr("_", "-") +- string << "::" ++ path << "/" unless path.size == 0 ++ path << op.to_s.tr("_", "-") ++ path << "::" + when :any +- string << "*" ++ path << "*" + when :qname +- prefix = path.shift +- name = path.shift +- string << prefix+":" if prefix.size > 0 +- string << name ++ prefix = parsed.shift ++ name = parsed.shift ++ path << prefix+":" if prefix.size > 0 ++ path << name + when :predicate +- string << '' +- string << predicate_to_string( path.shift ) { |x| expand(x) } +- string << '' ++ path << '' ++ path << predicate_to_path( parsed.shift ) { |x| expand(x) } ++ path << '' + when :document + document = true + else +- string << "/" unless string.size == 0 +- string << "UNKNOWN(" +- string << op.inspect +- string << ")" ++ path << "UNKNOWN(" ++ path << op.inspect ++ path << ")" + end + end +- string = "/"+string if document +- return string ++ path = "/"+path if document ++ path + end + +- def predicate_to_string( path, &block ) +- string = "" +- case path0 ++ def predicate_to_path(parsed, &block) ++ path = "" ++ case parsed0 + when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union +- op = path.shift ++ op = parsed.shift + case op + when :eq + op = "=" +@@ -156,36 +192,50 @@ module REXML + when :union + op = "|" + end +- left = predicate_to_string( path.shift, &block ) +- right = predicate_to_string( path.shift, &block ) +- string << " " +- string << left +- string << " " +- string << op.to_s +- string << " " +- string << right +- string << " " ++ left = predicate_to_path( parsed.shift, &block ) ++ right = predicate_to_path( parsed.shift, &block ) ++ path << left ++ path << " " ++ path << op.to_s ++ path << " " ++ path << right + when :function +- path.shift +- name = path.shift +- string << name +- string << "( " +- string << predicate_to_string( path.shift, &block ) +- string << " )" ++ parsed.shift ++ name = parsed.shift ++ path << name ++ path << "(" ++ parsed.shift.each_with_index do |argument, i| ++ path << ", " if i > 0 ++ path << predicate_to_path(argument, &block) ++ end ++ path << ")" + when :literal +- path.shift +- string << " " +- string << path.shift.inspect +- string << " " ++ parsed.shift ++ path << quote_literal(parsed.shift) + else +- string << " " +- string << yield( path ) +- string << " " ++ path << yield( parsed ) + end +- return string.squeeze(" ") ++ return path.squeeze(" ") + end ++ # For backward compatibility ++ alias_method :preciate_to_string, :predicate_to_path + + private ++ def quote_literal( literal ) ++ case literal ++ when String ++ # XPath 1.0 does not support escape characters. ++ # Assumes literal does not contain both single and double quotes. ++ if literal.include?("'") ++ "\"#{literal}\"" ++ else ++ "'#{literal}'" ++ end ++ else ++ literal.inspect ++ end ++ end ++ + #LocationPath + # | RelativeLocationPath + # | '/' RelativeLocationPath? +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb +index 8a01f0e..573d0a1 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb +@@ -26,10 +26,12 @@ + # - REXML::Document. + # - REXML::Element. + # ++# There's also an {REXML tutorial}doc/rexml/tutorial_rdoc.html. ++# + module REXML + COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser@germane-software.com>" + DATE = "2008/019" +- VERSION = "3.2.5" ++ VERSION = "3.3.1" + REVISION = "" + + Copyright = COPYRIGHT +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb +index 90b370b..5715c35 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb +@@ -1,8 +1,28 @@ + # coding: US-ASCII + # frozen_string_literal: false ++ ++require "strscan" ++ + require_relative 'encoding' + + module REXML ++ if StringScanner::Version < "1.0.0" ++ module StringScannerCheckScanString ++ refine StringScanner do ++ def check(pattern) ++ pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String) ++ super(pattern) ++ end ++ ++ def scan(pattern) ++ pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String) ++ super(pattern) ++ end ++ end ++ end ++ using StringScannerCheckScanString ++ end ++ + # Generates Source-s. USE THIS CLASS. + class SourceFactory + # Generates a Source object +@@ -30,18 +50,27 @@ module REXML + # objects and provides consumption of text + class Source + include Encoding +- # The current buffer (what we're going to read next) +- attr_reader :buffer + # The line number of the last consumed text + attr_reader :line + attr_reader :encoding + ++ module Private ++ SCANNER_RESET_SIZE = 100000 ++ PRE_DEFINED_TERM_PATTERNS = {} ++ pre_defined_terms = "'", '"', "<" ++ pre_defined_terms.each do |term| ++ PRE_DEFINED_TERM_PATTERNSterm = /#{Regexp.escape(term)}/ ++ end ++ end ++ private_constant :Private ++ + # Constructor + # @param arg must be a String, and should be a valid XML document + # @param encoding if non-null, sets the encoding of the source to this + # value, overriding all encoding detection + def initialize(arg, encoding=nil) +- @orig = @buffer = arg ++ @orig = arg ++ @scanner = StringScanner.new(@orig) + if encoding + self.encoding = encoding + else +@@ -50,6 +79,20 @@ module REXML + @line = 0 + end + ++ # The current buffer (what we're going to read next) ++ def buffer ++ @scanner.rest ++ end ++ ++ def drop_parsed_content ++ if @scanner.pos > Private::SCANNER_RESET_SIZE ++ @scanner.string = @scanner.rest ++ end ++ end ++ ++ def buffer_encoding=(encoding) ++ @scanner.string.force_encoding(encoding) ++ end + + # Inherited from Encoding + # Overridden to support optimized en/decoding +@@ -58,98 +101,78 @@ module REXML + encoding_updated + end + +- # Scans the source for a given pattern. Note, that this is not your +- # usual scan() method. For one thing, the pattern argument has some +- # requirements; for another, the source can be consumed. You can easily +- # confuse this method. Originally, the patterns were easier +- # to construct and this method more robust, because this method +- # generated search regexps on the fly; however, this was +- # computationally expensive and slowed down the entire REXML package +- # considerably, since this is by far the most commonly called method. +- # @param pattern must be a Regexp, and must be in the form of +- # /^\s*(#{your pattern, with no groups})(.*)/. The first group +- # will be returned; the second group is used if the consume flag is +- # set. +- # @param consume if true, the pattern returned will be consumed, leaving +- # everything after it in the Source. +- # @return the pattern, if found, or nil if the Source is empty or the +- # pattern is not found. +- def scan(pattern, cons=false) +- return nil if @buffer.nil? +- rv = @buffer.scan(pattern) +- @buffer = $' if cons and rv.size>0 +- rv ++ def read(term = nil) + end + +- def read ++ def read_until(term) ++ pattern = Private::PRE_DEFINED_TERM_PATTERNSterm || /#{Regexp.escape(term)}/ ++ data = @scanner.scan_until(pattern) ++ unless data ++ data = @scanner.rest ++ @scanner.pos = @scanner.string.bytesize ++ end ++ data + end + +- def consume( pattern ) +- @buffer = $' if pattern.match( @buffer ) ++ def ensure_buffer + end + +- def match_to( char, pattern ) +- return pattern.match(@buffer) ++ def match(pattern, cons=false) ++ if cons ++ @scanner.scan(pattern).nil? ? nil : @scanner ++ else ++ @scanner.check(pattern).nil? ? nil : @scanner ++ end + end + +- def match_to_consume( char, pattern ) +- md = pattern.match(@buffer) +- @buffer = $' +- return md ++ def position ++ @scanner.pos + end + +- def match(pattern, cons=false) +- md = pattern.match(@buffer) +- @buffer = $' if cons and md +- return md ++ def position=(pos) ++ @scanner.pos = pos + end + + # @return true if the Source is exhausted + def empty? +- @buffer == "" +- end +- +- def position +- @orig.index( @buffer ) ++ @scanner.eos? + end + + # @return the current line in the source + def current_line + lines = @orig.split +- res = lines.grep @buffer0..30 ++ res = lines.grep @scanner.rest0..30 + res = res-1 if res.kind_of? Array + lines.index( res ) if res + end + + private ++ + def detect_encoding +- buffer_encoding = @buffer.encoding ++ scanner_encoding = @scanner.rest.encoding + detected_encoding = "UTF-8" + begin +- @buffer.force_encoding("ASCII-8BIT") +- if @buffer0, 2 == "\xfe\xff" +- @buffer0, 2 = "" ++ @scanner.string.force_encoding("ASCII-8BIT") ++ if @scanner.scan(/\xfe\xff/n) + detected_encoding = "UTF-16BE" +- elsif @buffer0, 2 == "\xff\xfe" +- @buffer0, 2 = "" ++ elsif @scanner.scan(/\xff\xfe/n) + detected_encoding = "UTF-16LE" +- elsif @buffer0, 3 == "\xef\xbb\xbf" +- @buffer0, 3 = "" ++ elsif @scanner.scan(/\xef\xbb\xbf/n) + detected_encoding = "UTF-8" + end + ensure +- @buffer.force_encoding(buffer_encoding) ++ @scanner.string.force_encoding(scanner_encoding) + end + self.encoding = detected_encoding + end + + def encoding_updated + if @encoding != 'UTF-8' +- @buffer = decode(@buffer) ++ @scanner.string = decode(@scanner.rest) + @to_utf = true + else + @to_utf = false +- @buffer.force_encoding ::Encoding::UTF_8 ++ @scanner.string.force_encoding(::Encoding::UTF_8) + end + end + end +@@ -172,7 +195,7 @@ module REXML + end + + if !@to_utf and +- @buffer.respond_to?(:force_encoding) and ++ @orig.respond_to?(:force_encoding) and + @source.respond_to?(:external_encoding) and + @source.external_encoding != ::Encoding::UTF_8 + @force_utf8 = true +@@ -181,65 +204,62 @@ module REXML + end + end + +- def scan(pattern, cons=false) +- rv = super +- # You'll notice that this next section is very similar to the same +- # section in match(), but just a liiittle different. This is +- # because it is a touch faster to do it this way with scan() +- # than the way match() does it; enough faster to warrant duplicating +- # some code +- if rv.size == 0 +- until @buffer =~ pattern or @source.nil? +- begin +- @buffer << readline +- rescue Iconv::IllegalSequence +- raise +- rescue +- @source = nil +- end +- end +- rv = super +- end +- rv.taint if RUBY_VERSION < '2.7' +- rv +- end +- +- def read ++ def read(term = nil) ++ term = encode(term) if term + begin +- @buffer << readline ++ @scanner << readline(term) ++ true + rescue Exception, NameError + @source = nil ++ false ++ end ++ end ++ ++ def read_until(term) ++ pattern = Private::PRE_DEFINED_TERM_PATTERNSterm || /#{Regexp.escape(term)}/ ++ term = encode(term) ++ until str = @scanner.scan_until(pattern) ++ break if @source.nil? ++ break if @source.eof? ++ @scanner << readline(term) ++ end ++ if str ++ read if @scanner.eos? and !@source.eof? ++ str ++ else ++ rest = @scanner.rest ++ @scanner.pos = @scanner.string.bytesize ++ rest + end + end + +- def consume( pattern ) +- match( pattern, true ) ++ def ensure_buffer ++ read if @scanner.eos? && @source + end + ++ # Note: When specifying a string for 'pattern', it must not include '>' except in the following formats: ++ # - ">" ++ # - "XXX>" (X is any string excluding '>') + def match( pattern, cons=false ) +- rv = pattern.match(@buffer) +- @buffer = $' if cons and rv +- while !rv and @source +- begin +- @buffer << readline +- rv = pattern.match(@buffer) +- @buffer = $' if cons and rv +- rescue +- @source = nil ++ while true ++ if cons ++ md = @scanner.scan(pattern) ++ else ++ md = @scanner.check(pattern) + end ++ break if md ++ return nil if pattern.is_a?(String) ++ return nil if @source.nil? ++ return nil unless read + end +- rv.taint if RUBY_VERSION < '2.7' +- rv ++ ++ md.nil? ? nil : @scanner + end + + def empty? + super and ( @source.nil? || @source.eof? ) + end + +- def position +- @er_source.pos rescue 0 +- end +- + # @return the current line in the source + def current_line + begin +@@ -263,8 +283,8 @@ module REXML + end + + private +- def readline +- str = @source.readline(@line_break) ++ def readline(term = nil) ++ str = @source.readline(term || @line_break) + if @pending_buffer + if str.nil? + str = @pending_buffer +@@ -290,7 +310,7 @@ module REXML + @source.set_encoding(@encoding, @encoding) + end + @line_break = encode(">") +- @pending_buffer, @buffer = @buffer, "" ++ @pending_buffer, @scanner.string = @scanner.rest, "" + @pending_buffer.force_encoding(@encoding) + super + end +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb +index 050b09c..b47bad3 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb +@@ -1,4 +1,4 @@ +-# frozen_string_literal: false ++# frozen_string_literal: true + require_relative 'security' + require_relative 'entity' + require_relative 'doctype' +@@ -131,7 +131,7 @@ module REXML + def Text.check string, pattern, doctype + + # illegal anywhere +- if string !~ VALID_XML_CHARS ++ if !string.match?(VALID_XML_CHARS) + if String.method_defined? :encode + string.chars.each do |c| + case c.ord +@@ -371,7 +371,7 @@ module REXML + copy = input.to_s + # Doing it like this rather than in a loop improves the speed + #copy = copy.gsub( EREFERENCE, '&' ) +- copy = copy.gsub( "&", "&" ) ++ copy = copy.gsub( "&", "&" ) if copy.include?("&") + if doctype + # Replace all ampersands that aren't part of an entity + doctype.entities.each_value do |entity| +@@ -382,7 +382,9 @@ module REXML + else + # Replace all ampersands that aren't part of an entity + DocType::DEFAULT_ENTITIES.each_value do |entity| +- copy = copy.gsub(entity.value, "&#{entity.name};" ) ++ if copy.include?(entity.value) ++ copy = copy.gsub(entity.value, "&#{entity.name};" ) ++ end + end + end + copy +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb +index d8b88e7..5eb1e5a 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb +@@ -590,6 +590,7 @@ module REXML + + def evaluate_predicate(expression, nodesets) + enter(:predicate, expression, nodesets) if @debug ++ new_nodeset_count = 0 + new_nodesets = nodesets.collect do |nodeset| + new_nodeset = + subcontext = { :size => nodeset.size } +@@ -606,17 +607,20 @@ module REXML + result = result0 if result.kind_of? Array and result.length == 1 + if result.kind_of? Numeric + if result == node.position +- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) ++ new_nodeset_count += 1 ++ new_nodeset << XPathNode.new(node, position: new_nodeset_count) + end + elsif result.instance_of? Array + if result.size > 0 and result.inject(false) {|k,s| s or k} + if result.size > 0 +- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) ++ new_nodeset_count += 1 ++ new_nodeset << XPathNode.new(node, position: new_nodeset_count) + end + end + else + if result +- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) ++ new_nodeset_count += 1 ++ new_nodeset << XPathNode.new(node, position: new_nodeset_count) + end + end + end +-- +2.27.0 +
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/ruby.git</param> - <param name="revision">master</param> + <param name="revision">openEuler-24.09</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2