|
| 1 | +require 'rexml/rexml' |
1 | 2 | require 'rexml/entity'
|
2 | 3 | require 'rexml/doctype'
|
3 | 4 | require 'rexml/child'
|
@@ -308,37 +309,35 @@ def Text::normalize( input, doctype=nil, entity_filter=nil )
|
308 | 309 |
|
309 | 310 | # Unescapes all possible entities
|
310 | 311 | def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil )
|
311 |
| - rv = string.clone |
312 |
| - rv.gsub!( /\r\n?/, "\n" ) |
313 |
| - matches = rv.scan( REFERENCE ) |
314 |
| - return rv if matches.size == 0 |
315 |
| - rv.gsub!( NUMERICENTITY ) {|m| |
316 |
| - m=$1 |
317 |
| - m = "0#{m}" if m[0] == ?x |
318 |
| - [Integer(m)].pack('U*') |
| 312 | + sum = 0 |
| 313 | + string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) { |
| 314 | + s = Text.expand($&, doctype, filter) |
| 315 | + if sum + s.bytesize > REXML.entity_expansion_text_limit |
| 316 | + raise "entity expansion has grown too large" |
| 317 | + else |
| 318 | + sum += s.bytesize |
| 319 | + end |
| 320 | + s |
319 | 321 | }
|
320 |
| - matches.collect!{|x|x[0]}.compact! |
321 |
| - if matches.size > 0 |
322 |
| - if doctype |
323 |
| - matches.each do |entity_reference| |
324 |
| - unless filter and filter.include?(entity_reference) |
325 |
| - entity_value = doctype.entity( entity_reference ) |
326 |
| - re = /&#{entity_reference};/ |
327 |
| - rv.gsub!( re, entity_value ) if entity_value |
328 |
| - end |
329 |
| - end |
| 322 | + end |
| 323 | + |
| 324 | + def Text.expand(ref, doctype, filter) |
| 325 | + if ref[1] == ?# |
| 326 | + if ref[2] == ?x |
| 327 | + [ref[3...-1].to_i(16)].pack('U*') |
330 | 328 | else
|
331 |
| - matches.each do |entity_reference| |
332 |
| - unless filter and filter.include?(entity_reference) |
333 |
| - entity_value = DocType::DEFAULT_ENTITIES[ entity_reference ] |
334 |
| - re = /&#{entity_reference};/ |
335 |
| - rv.gsub!( re, entity_value.value ) if entity_value |
336 |
| - end |
337 |
| - end |
| 329 | + [ref[2...-1].to_i].pack('U*') |
338 | 330 | end
|
339 |
| - rv.gsub!( /&/, '&' ) |
| 331 | + elsif ref == '&' |
| 332 | + '&' |
| 333 | + elsif filter and filter.include?( ref[1...-1] ) |
| 334 | + ref |
| 335 | + elsif doctype |
| 336 | + doctype.entity( ref[1...-1] ) or ref |
| 337 | + else |
| 338 | + entity_value = DocType::DEFAULT_ENTITIES[ ref[1...-1] ] |
| 339 | + entity_value ? entity_value.value : ref |
340 | 340 | end
|
341 |
| - rv |
342 | 341 | end
|
343 | 342 | end
|
344 | 343 | end
|
0 commit comments