rexml 3.3.7 → 3.4.2

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.
@@ -215,7 +215,7 @@ module REXML
215
215
  else
216
216
  path << yield( parsed )
217
217
  end
218
- return path.squeeze(" ")
218
+ path.squeeze(" ")
219
219
  end
220
220
  # For backward compatibility
221
221
  alias_method :preciate_to_string, :predicate_to_path
@@ -252,7 +252,7 @@ module REXML
252
252
  path = path[1..-1]
253
253
  end
254
254
  end
255
- return RelativeLocationPath( path, parsed ) if path.size > 0
255
+ RelativeLocationPath( path, parsed ) if path.size > 0
256
256
  end
257
257
 
258
258
  #RelativeLocationPath
@@ -388,7 +388,7 @@ module REXML
388
388
  else
389
389
  path = original_path
390
390
  end
391
- return path
391
+ path
392
392
  end
393
393
 
394
394
  # Filters the supplied nodeset on the predicate(s)
@@ -600,7 +600,7 @@ module REXML
600
600
  end
601
601
  rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/
602
602
  parsed.concat(n)
603
- return rest
603
+ rest
604
604
  end
605
605
 
606
606
  #| FilterExpr Predicate
@@ -41,7 +41,7 @@ module REXML
41
41
  else
42
42
  results = filter([element], path)
43
43
  end
44
- return results
44
+ results
45
45
  end
46
46
 
47
47
  # Given an array of nodes it filters the array based on the path. The
@@ -51,18 +51,18 @@ module REXML
51
51
  return elements if path.nil? or path == '' or elements.size == 0
52
52
  case path
53
53
  when /^\/\//u # Descendant
54
- return axe( elements, "descendant-or-self", $' )
54
+ axe( elements, "descendant-or-self", $' )
55
55
  when /^\/?\b(\w[-\w]*)\b::/u # Axe
56
- return axe( elements, $1, $' )
56
+ axe( elements, $1, $' )
57
57
  when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
58
58
  rest = $'
59
59
  results = []
60
60
  elements.each do |element|
61
61
  results |= filter( element.to_a, rest )
62
62
  end
63
- return results
63
+ results
64
64
  when /^\/?(\w[-\w]*)\(/u # / Function
65
- return function( elements, $1, $' )
65
+ function( elements, $1, $' )
66
66
  when Namespace::NAMESPLIT # Element name
67
67
  name = $2
68
68
  ns = $1
@@ -73,21 +73,21 @@ module REXML
73
73
  (element.name == name and
74
74
  element.namespace == Functions.namespace_context[ns])))
75
75
  end
76
- return filter( elements, rest )
76
+ filter( elements, rest )
77
77
  when /^\/\[/u
78
78
  matches = []
79
79
  elements.each do |element|
80
80
  matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
81
81
  end
82
- return matches
82
+ matches
83
83
  when /^\[/u # Predicate
84
- return predicate( elements, path )
84
+ predicate( elements, path )
85
85
  when /^\/?\.\.\./u # Ancestor
86
- return axe( elements, "ancestor", $' )
86
+ axe( elements, "ancestor", $' )
87
87
  when /^\/?\.\./u # Parent
88
- return filter( elements.collect{|e|e.parent}, $' )
88
+ filter( elements.collect{|e|e.parent}, $' )
89
89
  when /^\/?\./u # Self
90
- return filter( elements, $' )
90
+ filter( elements, $' )
91
91
  when /^\*/u # Any
92
92
  results = []
93
93
  elements.each do |element|
@@ -98,9 +98,10 @@ module REXML
98
98
  # results |= filter( children, $' )
99
99
  #end
100
100
  end
101
- return results
101
+ results
102
+ else
103
+ []
102
104
  end
103
- return []
104
105
  end
105
106
 
106
107
  def QuickPath::axe( elements, axe_name, rest )
@@ -138,7 +139,7 @@ module REXML
138
139
  matches = filter(elements.collect{|element|
139
140
  element.previous_sibling}.uniq, rest )
140
141
  end
141
- return matches.uniq
142
+ matches.uniq
142
143
  end
143
144
 
144
145
  OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)'
@@ -200,15 +201,15 @@ module REXML
200
201
  results << element
201
202
  end
202
203
  end
203
- return filter( results, rest )
204
+ filter( results, rest )
204
205
  end
205
206
 
206
207
  def QuickPath::attribute( name )
207
- return Functions.node.attributes[name] if Functions.node.kind_of? Element
208
+ Functions.node.attributes[name] if Functions.node.kind_of? Element
208
209
  end
209
210
 
210
211
  def QuickPath::name()
211
- return Functions.node.name if Functions.node.kind_of? Element
212
+ Functions.node.name if Functions.node.kind_of? Element
212
213
  end
213
214
 
214
215
  def QuickPath::method_missing( id, *args )
@@ -234,7 +235,7 @@ module REXML
234
235
  results << element if Functions.pair[0] == res
235
236
  end
236
237
  end
237
- return results
238
+ results
238
239
  end
239
240
 
240
241
  def QuickPath::parse_args( element, string )
data/lib/rexml/rexml.rb CHANGED
@@ -31,7 +31,7 @@
31
31
  module REXML
32
32
  COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser@germane-software.com>"
33
33
  DATE = "2008/019"
34
- VERSION = "3.3.7"
34
+ VERSION = "3.4.2"
35
35
  REVISION = ""
36
36
 
37
37
  Copyright = COPYRIGHT
@@ -10,7 +10,7 @@ module REXML
10
10
 
11
11
  # Get the entity expansion limit. By default the limit is set to 10000.
12
12
  def self.entity_expansion_limit
13
- return @@entity_expansion_limit
13
+ @@entity_expansion_limit
14
14
  end
15
15
 
16
16
  @@entity_expansion_text_limit = 10_240
@@ -22,7 +22,7 @@ module REXML
22
22
 
23
23
  # Get the entity expansion limit. By default the limit is set to 10240.
24
24
  def self.entity_expansion_text_limit
25
- return @@entity_expansion_text_limit
25
+ @@entity_expansion_text_limit
26
26
  end
27
27
  end
28
28
  end
data/lib/rexml/source.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # coding: US-ASCII
2
2
  # frozen_string_literal: false
3
3
 
4
+ require "stringio"
4
5
  require "strscan"
5
6
 
6
7
  require_relative 'encoding'
@@ -18,6 +19,16 @@ module REXML
18
19
  pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String)
19
20
  super(pattern)
20
21
  end
22
+
23
+ def match?(pattern)
24
+ pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String)
25
+ super(pattern)
26
+ end
27
+
28
+ def skip(pattern)
29
+ pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String)
30
+ super(pattern)
31
+ end
21
32
  end
22
33
  end
23
34
  using StringScannerCheckScanString
@@ -35,7 +46,6 @@ module REXML
35
46
  arg.respond_to? :eof?
36
47
  IOSource.new(arg)
37
48
  elsif arg.respond_to? :to_str
38
- require 'stringio'
39
49
  IOSource.new(StringIO.new(arg))
40
50
  elsif arg.kind_of? Source
41
51
  arg
@@ -55,11 +65,18 @@ module REXML
55
65
  attr_reader :encoding
56
66
 
57
67
  module Private
68
+ SPACES_PATTERN = /\s+/um
58
69
  SCANNER_RESET_SIZE = 100000
59
70
  PRE_DEFINED_TERM_PATTERNS = {}
60
- pre_defined_terms = ["'", '"', "<"]
61
- pre_defined_terms.each do |term|
62
- PRE_DEFINED_TERM_PATTERNS[term] = /#{Regexp.escape(term)}/
71
+ pre_defined_terms = ["'", '"', "<", "]]>", "?>"]
72
+ if StringScanner::Version < "3.1.1"
73
+ pre_defined_terms.each do |term|
74
+ PRE_DEFINED_TERM_PATTERNS[term] = /#{Regexp.escape(term)}/
75
+ end
76
+ else
77
+ pre_defined_terms.each do |term|
78
+ PRE_DEFINED_TERM_PATTERNS[term] = term
79
+ end
63
80
  end
64
81
  end
65
82
  private_constant :Private
@@ -77,6 +94,7 @@ module REXML
77
94
  detect_encoding
78
95
  end
79
96
  @line = 0
97
+ @encoded_terms = {}
80
98
  end
81
99
 
82
100
  # The current buffer (what we're going to read next)
@@ -125,6 +143,18 @@ module REXML
125
143
  end
126
144
  end
127
145
 
146
+ def match?(pattern, cons=false)
147
+ if cons
148
+ !@scanner.skip(pattern).nil?
149
+ else
150
+ !@scanner.match?(pattern).nil?
151
+ end
152
+ end
153
+
154
+ def skip_spaces
155
+ @scanner.skip(Private::SPACES_PATTERN) ? true : false
156
+ end
157
+
128
158
  def position
129
159
  @scanner.pos
130
160
  end
@@ -133,6 +163,14 @@ module REXML
133
163
  @scanner.pos = pos
134
164
  end
135
165
 
166
+ def peek_byte
167
+ @scanner.peek_byte
168
+ end
169
+
170
+ def scan_byte
171
+ @scanner.scan_byte
172
+ end
173
+
136
174
  # @return true if the Source is exhausted
137
175
  def empty?
138
176
  @scanner.eos?
@@ -227,7 +265,7 @@ module REXML
227
265
 
228
266
  def read_until(term)
229
267
  pattern = Private::PRE_DEFINED_TERM_PATTERNS[term] || /#{Regexp.escape(term)}/
230
- term = encode(term)
268
+ term = @encoded_terms[term] ||= encode(term)
231
269
  until str = @scanner.scan_until(pattern)
232
270
  break if @source.nil?
233
271
  break if @source.eof?
@@ -266,6 +304,23 @@ module REXML
266
304
  md.nil? ? nil : @scanner
267
305
  end
268
306
 
307
+ def match?( pattern, cons=false )
308
+ # To avoid performance issue, we need to increase bytes to read per scan
309
+ min_bytes = 1
310
+ while true
311
+ if cons
312
+ n_matched_bytes = @scanner.skip(pattern)
313
+ else
314
+ n_matched_bytes = @scanner.match?(pattern)
315
+ end
316
+ return true if n_matched_bytes
317
+ return false if pattern.is_a?(String)
318
+ return false if @source.nil?
319
+ return false unless read(nil, min_bytes)
320
+ min_bytes *= 2
321
+ end
322
+ end
323
+
269
324
  def empty?
270
325
  super and ( @source.nil? || @source.eof? )
271
326
  end
@@ -285,7 +340,7 @@ module REXML
285
340
  rescue
286
341
  end
287
342
  @er_source.seek(pos)
288
- rescue IOError
343
+ rescue IOError, SystemCallError
289
344
  pos = -1
290
345
  line = -1
291
346
  end
@@ -294,14 +349,19 @@ module REXML
294
349
 
295
350
  private
296
351
  def readline(term = nil)
297
- str = @source.readline(term || @line_break)
298
352
  if @pending_buffer
353
+ begin
354
+ str = @source.readline(term || @line_break)
355
+ rescue IOError
356
+ end
299
357
  if str.nil?
300
358
  str = @pending_buffer
301
359
  else
302
360
  str = @pending_buffer + str
303
361
  end
304
362
  @pending_buffer = nil
363
+ else
364
+ str = @source.readline(term || @line_break)
305
365
  end
306
366
  return nil if str.nil?
307
367
 
data/lib/rexml/text.rb CHANGED
@@ -29,31 +29,16 @@ module REXML
29
29
  (0x10000..0x10FFFF)
30
30
  ]
31
31
 
32
- if String.method_defined? :encode
33
- VALID_XML_CHARS = Regexp.new('^['+
34
- VALID_CHAR.map { |item|
35
- case item
36
- when Integer
37
- [item].pack('U').force_encoding('utf-8')
38
- when Range
39
- [item.first, '-'.ord, item.last].pack('UUU').force_encoding('utf-8')
40
- end
41
- }.join +
42
- ']*$')
43
- else
44
- VALID_XML_CHARS = /^(
45
- [\x09\x0A\x0D\x20-\x7E] # ASCII
46
- | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
47
- | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
48
- | [\xE1-\xEC\xEE][\x80-\xBF]{2} # straight 3-byte
49
- | \xEF[\x80-\xBE]{2} #
50
- | \xEF\xBF[\x80-\xBD] # excluding U+fffe and U+ffff
51
- | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
52
- | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
53
- | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
54
- | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
55
- )*$/nx;
56
- end
32
+ VALID_XML_CHARS = Regexp.new('^['+
33
+ VALID_CHAR.map { |item|
34
+ case item
35
+ when Integer
36
+ [item].pack('U').force_encoding('utf-8')
37
+ when Range
38
+ [item.first, '-'.ord, item.last].pack('UUU').force_encoding('utf-8')
39
+ end
40
+ }.join +
41
+ ']*$')
57
42
 
58
43
  # Constructor
59
44
  # +arg+ if a String, the content is set to the String. If a Text,
@@ -119,34 +104,24 @@ module REXML
119
104
  @entity_filter = entity_filter if entity_filter
120
105
  clear_cache
121
106
 
122
- Text.check(@string, illegal, doctype) if @raw
107
+ Text.check(@string, illegal) if @raw
123
108
  end
124
109
 
125
110
  def parent= parent
126
111
  super(parent)
127
- Text.check(@string, NEEDS_A_SECOND_CHECK, doctype) if @raw and @parent
112
+ Text.check(@string, NEEDS_A_SECOND_CHECK) if @raw and @parent
128
113
  end
129
114
 
130
115
  # check for illegal characters
131
- def Text.check string, pattern, doctype
116
+ def Text.check string, pattern, doctype = nil
132
117
 
133
118
  # illegal anywhere
134
119
  if !string.match?(VALID_XML_CHARS)
135
- if String.method_defined? :encode
136
- string.chars.each do |c|
137
- case c.ord
138
- when *VALID_CHAR
139
- else
140
- raise "Illegal character #{c.inspect} in raw string #{string.inspect}"
141
- end
142
- end
143
- else
144
- string.scan(/[\x00-\x7F]|[\x80-\xBF][\xC0-\xF0]*|[\xC0-\xF0]/n) do |c|
145
- case c.unpack('U')
146
- when *VALID_CHAR
147
- else
148
- raise "Illegal character #{c.inspect} in raw string #{string.inspect}"
149
- end
120
+ string.chars.each do |c|
121
+ case c.ord
122
+ when *VALID_CHAR
123
+ else
124
+ raise "Illegal character #{c.inspect} in raw string #{string.inspect}"
150
125
  end
151
126
  end
152
127
  end
@@ -202,7 +177,7 @@ module REXML
202
177
 
203
178
 
204
179
  def clone
205
- return Text.new(self, true)
180
+ Text.new(self, true)
206
181
  end
207
182
 
208
183
 
@@ -225,10 +200,7 @@ module REXML
225
200
  end
226
201
 
227
202
  def doctype
228
- if @parent
229
- doc = @parent.document
230
- doc.doctype if doc
231
- end
203
+ @parent&.document&.doctype
232
204
  end
233
205
 
234
206
  REFERENCE = /#{Entity::REFERENCE}/
@@ -289,30 +261,32 @@ module REXML
289
261
  # Recursively wrap string at width.
290
262
  return string if string.length <= width
291
263
  place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
292
- if addnewline then
293
- return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
264
+ if addnewline
265
+ "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
294
266
  else
295
- return string[0,place] + "\n" + wrap(string[place+1..-1], width)
267
+ string[0,place] + "\n" + wrap(string[place+1..-1], width)
296
268
  end
297
269
  end
298
270
 
299
271
  def indent_text(string, level=1, style="\t", indentfirstline=true)
272
+ Kernel.warn("#{self.class.name}#indent_text is deprecated. See REXML::Formatters", uplevel: 1)
300
273
  return string if level < 0
301
- new_string = ''
274
+
275
+ new_string = +''
302
276
  string.each_line { |line|
303
277
  indent_string = style * level
304
278
  new_line = (indent_string + line).sub(/[\s]+$/,'')
305
279
  new_string << new_line
306
280
  }
307
281
  new_string.strip! unless indentfirstline
308
- return new_string
282
+ new_string
309
283
  end
310
284
 
311
285
  # == DEPRECATED
312
286
  # See REXML::Formatters
313
287
  #
314
288
  def write( writer, indent=-1, transitive=false, ie_hack=false )
315
- Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters", uplevel: 1)
289
+ Kernel.warn("#{self.class.name}#write is deprecated. See REXML::Formatters", uplevel: 1)
316
290
  formatter = if indent > -1
317
291
  REXML::Formatters::Pretty.new( indent )
318
292
  else
@@ -324,9 +298,7 @@ module REXML
324
298
  # FIXME
325
299
  # This probably won't work properly
326
300
  def xpath
327
- path = @parent.xpath
328
- path += "/text()"
329
- return path
301
+ @parent.xpath + "/text()"
330
302
  end
331
303
 
332
304
  # Writes out text, substituting special characters beforehand.
@@ -157,16 +157,16 @@ module REXML
157
157
  if ( @events[@current].matches?(event) )
158
158
  @current += 1
159
159
  if @events[@current].nil?
160
- return @previous.pop
160
+ @previous.pop
161
161
  elsif @events[@current].kind_of? State
162
162
  @current += 1
163
163
  @events[@current-1].previous = self
164
- return @events[@current-1]
164
+ @events[@current-1]
165
165
  else
166
- return self
166
+ self
167
167
  end
168
168
  else
169
- return nil
169
+ nil
170
170
  end
171
171
  end
172
172
 
@@ -186,7 +186,7 @@ module REXML
186
186
  end
187
187
 
188
188
  def expected
189
- return [@events[@current]]
189
+ [@events[@current]]
190
190
  end
191
191
 
192
192
  def <<( event )
@@ -244,7 +244,7 @@ module REXML
244
244
  evt = :end_attribute
245
245
  end
246
246
  end
247
- return Event.new( evt, arg )
247
+ Event.new( evt, arg )
248
248
  end
249
249
  end
250
250
 
@@ -262,9 +262,10 @@ module REXML
262
262
  rv = super
263
263
  return rv if rv
264
264
  @prior = @previous.pop
265
- return @prior.next( event )
265
+ @prior.next( event )
266
+ else
267
+ super
266
268
  end
267
- super
268
269
  end
269
270
 
270
271
  def matches?(event)
@@ -274,7 +275,7 @@ module REXML
274
275
 
275
276
  def expected
276
277
  return [ @prior.expected, @events[0] ].flatten if @current == 0
277
- return [@events[@current]]
278
+ [@events[@current]]
278
279
  end
279
280
  end
280
281
 
@@ -286,24 +287,24 @@ module REXML
286
287
  @current += 1
287
288
  if @events[@current].nil?
288
289
  @current = 0
289
- return self
290
+ self
290
291
  elsif @events[@current].kind_of? State
291
292
  @current += 1
292
293
  @events[@current-1].previous = self
293
- return @events[@current-1]
294
+ @events[@current-1]
294
295
  else
295
- return self
296
+ self
296
297
  end
297
298
  else
298
299
  @prior = @previous.pop
299
300
  return @prior.next( event ) if @current == 0
300
- return nil
301
+ nil
301
302
  end
302
303
  end
303
304
 
304
305
  def expected
305
306
  return [ @prior.expected, @events[0] ].flatten if @current == 0
306
- return [@events[@current]]
307
+ [@events[@current]]
307
308
  end
308
309
  end
309
310
 
@@ -326,17 +327,17 @@ module REXML
326
327
  @ord += 1
327
328
  if @events[@current].nil?
328
329
  @current = 0
329
- return self
330
+ self
330
331
  elsif @events[@current].kind_of? State
331
332
  @current += 1
332
333
  @events[@current-1].previous = self
333
- return @events[@current-1]
334
+ @events[@current-1]
334
335
  else
335
- return self
336
+ self
336
337
  end
337
338
  else
338
339
  return @previous.pop.next( event ) if @current == 0 and @ord > 0
339
- return nil
340
+ nil
340
341
  end
341
342
  end
342
343
 
@@ -347,9 +348,9 @@ module REXML
347
348
 
348
349
  def expected
349
350
  if @current == 0 and @ord > 0
350
- return [@previous[-1].expected, @events[0]].flatten
351
+ [@previous[-1].expected, @events[0]].flatten
351
352
  else
352
- return [@events[@current]]
353
+ [@events[@current]]
353
354
  end
354
355
  end
355
356
  end
@@ -403,7 +404,7 @@ module REXML
403
404
 
404
405
  def expected
405
406
  return [@events[@current]] if @events.size > 0
406
- return @choices.collect do |x|
407
+ @choices.collect do |x|
407
408
  if x[0].kind_of? State
408
409
  x[0].expected
409
410
  else
@@ -490,16 +491,16 @@ module REXML
490
491
  @current += 1
491
492
  if @events[@current].nil?
492
493
  return self unless @choices[@choice].nil?
493
- return @previous.pop
494
+ @previous.pop
494
495
  elsif @events[@current].kind_of? State
495
496
  @current += 1
496
497
  @events[@current-1].previous = self
497
- return @events[@current-1]
498
+ @events[@current-1]
498
499
  else
499
- return self
500
+ self
500
501
  end
501
502
  else
502
- return nil
503
+ nil
503
504
  end
504
505
  end
505
506
 
@@ -510,7 +511,7 @@ module REXML
510
511
 
511
512
  def expected
512
513
  return [@events[@current]] if @events[@current]
513
- return @choices[@choice..-1].collect do |x|
514
+ @choices[@choice..-1].collect do |x|
514
515
  if x[0].kind_of? State
515
516
  x[0].expected
516
517
  else
@@ -80,26 +80,26 @@ module REXML
80
80
  end
81
81
 
82
82
  def single?
83
- return (@event_type != :start_element and @event_type != :start_attribute)
83
+ (@event_type != :start_element and @event_type != :start_attribute)
84
84
  end
85
85
 
86
86
  def matches?( event )
87
87
  return false unless event[0] == @event_type
88
88
  case event[0]
89
89
  when nil
90
- return true
90
+ true
91
91
  when :start_element
92
- return true if event[1] == @event_arg
92
+ event[1] == @event_arg
93
93
  when :end_element
94
- return true
94
+ true
95
95
  when :start_attribute
96
- return true if event[1] == @event_arg
96
+ event[1] == @event_arg
97
97
  when :end_attribute
98
- return true
98
+ true
99
99
  when :end_document
100
- return true
100
+ true
101
101
  when :text
102
- return (@event_arg.nil? or @event_arg == event[1])
102
+ @event_arg.nil? || @event_arg == event[1]
103
103
  =begin
104
104
  when :processing_instruction
105
105
  false