2015-12-16 00:07:31 -05:00
|
|
|
# frozen_string_literal: false
|
2010-09-17 09:14:14 -04:00
|
|
|
require "test/unit/testcase"
|
|
|
|
|
2011-02-19 07:43:27 -05:00
|
|
|
require 'rexml/document'
|
2010-09-17 09:14:14 -04:00
|
|
|
require 'rexml/entity'
|
|
|
|
require 'rexml/source'
|
|
|
|
|
2014-05-27 08:07:40 -04:00
|
|
|
module REXMLTests
|
2014-05-27 09:10:55 -04:00
|
|
|
class EntityTester < Test::Unit::TestCase
|
|
|
|
def test_parse_general_decl
|
|
|
|
simple = "<!ENTITY foo 'bar'>"
|
|
|
|
simple =~ /#{REXML::Entity::GEDECL}/
|
|
|
|
assert $&
|
|
|
|
assert_equal simple, $&
|
|
|
|
|
|
|
|
REXML::Entity::ENTITYDECL =~ simple
|
|
|
|
assert REXML::Entity::matches?(simple)
|
|
|
|
match = REXML::Entity::ENTITYDECL.match(simple)
|
|
|
|
assert_equal 'foo', match[1]
|
|
|
|
assert_equal "'bar'", match[2]
|
|
|
|
|
|
|
|
simple = '<!ENTITY Pub-Status
|
|
|
|
"This is a pre-release of the specification.">'
|
|
|
|
assert REXML::Entity::matches?(simple)
|
|
|
|
match = REXML::Entity::ENTITYDECL.match(simple)
|
|
|
|
assert_equal 'Pub-Status', match[1]
|
|
|
|
assert_equal '"This is a pre-release of the specification."', match[2]
|
|
|
|
|
|
|
|
txt = '"This is a
|
|
|
|
pre-release of <the> specification."'
|
|
|
|
simple = "<!ENTITY Pub-Status
|
|
|
|
#{txt}>"
|
|
|
|
assert REXML::Entity::matches?(simple)
|
|
|
|
match = REXML::Entity::ENTITYDECL.match(simple)
|
|
|
|
assert_equal 'Pub-Status', match[1]
|
|
|
|
assert_equal txt, match[2]
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_parse_external_decl
|
|
|
|
zero = '<!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml" >'
|
|
|
|
one = '<!ENTITY open-hatch
|
|
|
|
SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">'
|
|
|
|
two = '<!ENTITY open-hatch
|
|
|
|
PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
|
|
|
|
"http://www.textuality.com/boilerplate/OpenHatch.xml">'
|
|
|
|
three = '<!ENTITY hatch-pic
|
|
|
|
SYSTEM "../grafix/OpenHatch.gif"
|
|
|
|
NDATA gif >'
|
|
|
|
assert REXML::Entity::matches?(zero)
|
|
|
|
assert REXML::Entity::matches?(one)
|
|
|
|
assert REXML::Entity::matches?(two)
|
|
|
|
assert REXML::Entity::matches?(three)
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_parse_entity
|
|
|
|
one = %q{<!ENTITY % YN '"Yes"'>}
|
|
|
|
two = %q{<!ENTITY WhatHeSaid "He said %YN;">}
|
|
|
|
assert REXML::Entity::matches?(one)
|
|
|
|
assert REXML::Entity::matches?(two)
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_constructor
|
|
|
|
one = [ %q{<!ENTITY % YN '"Yes"'>},
|
|
|
|
%q{<!ENTITY % YN2 "Yes">},
|
|
|
|
%q{<!ENTITY WhatHeSaid "He said %YN;">},
|
|
|
|
'<!ENTITY open-hatch
|
|
|
|
SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">',
|
|
|
|
'<!ENTITY open-hatch2
|
|
|
|
PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
|
|
|
|
"http://www.textuality.com/boilerplate/OpenHatch.xml">',
|
|
|
|
'<!ENTITY hatch-pic
|
|
|
|
SYSTEM "../grafix/OpenHatch.gif"
|
|
|
|
NDATA gif>' ]
|
|
|
|
source = %q{<!DOCTYPE foo [
|
|
|
|
<!ENTITY % YN '"Yes"'>
|
|
|
|
<!ENTITY % YN2 "Yes">
|
|
|
|
<!ENTITY WhatHeSaid "He said %YN;">
|
|
|
|
<!ENTITY open-hatch
|
|
|
|
SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
|
|
|
|
<!ENTITY open-hatch2
|
|
|
|
PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
|
|
|
|
"http://www.textuality.com/boilerplate/OpenHatch.xml">
|
|
|
|
<!ENTITY hatch-pic
|
|
|
|
SYSTEM "../grafix/OpenHatch.gif"
|
|
|
|
NDATA gif>
|
|
|
|
]>}
|
|
|
|
|
|
|
|
d = REXML::Document.new( source )
|
|
|
|
dt = d.doctype
|
|
|
|
c = 0
|
|
|
|
dt.each do |child|
|
|
|
|
if child.kind_of? REXML::Entity
|
|
|
|
str = one[c].tr("\r\n\t", ' ').squeeze(" ")
|
|
|
|
assert_equal str, child.to_s
|
|
|
|
c+=1
|
|
|
|
end
|
2010-09-17 09:46:56 -04:00
|
|
|
end
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_replace_entities
|
|
|
|
source = "<!DOCTYPE blah [\n<!ENTITY foo \"bar\">\n]><a>&foo;</a>"
|
|
|
|
doc = REXML::Document.new(source)
|
|
|
|
assert_equal 'bar', doc.root.text
|
|
|
|
out = ''
|
|
|
|
doc.write out
|
|
|
|
assert_equal source, out
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_entity_string_limit
|
|
|
|
template = '<!DOCTYPE bomb [ <!ENTITY a "^" > ]> <bomb>$</bomb>'
|
|
|
|
len = 5120 # 5k per entity
|
|
|
|
template.sub!(/\^/, "B" * len)
|
|
|
|
|
|
|
|
# 10k is OK
|
|
|
|
entities = '&a;' * 2 # 5k entity * 2 = 10k
|
|
|
|
xmldoc = REXML::Document.new(template.sub(/\$/, entities))
|
|
|
|
assert_equal(len * 2, xmldoc.root.text.bytesize)
|
|
|
|
|
|
|
|
# above 10k explodes
|
|
|
|
entities = '&a;' * 3 # 5k entity * 2 = 15k
|
|
|
|
xmldoc = REXML::Document.new(template.sub(/\$/, entities))
|
2015-06-01 22:18:44 -04:00
|
|
|
assert_raise(RuntimeError) do
|
2014-05-27 09:10:55 -04:00
|
|
|
xmldoc.root.text
|
|
|
|
end
|
2013-02-22 04:35:46 -05:00
|
|
|
end
|
|
|
|
|
2014-10-27 07:18:02 -04:00
|
|
|
def test_entity_string_limit_for_parameter_entity
|
|
|
|
template = '<!DOCTYPE bomb [ <!ENTITY % a "^" > <!ENTITY bomb "$" > ]><root/>'
|
|
|
|
len = 5120 # 5k per entity
|
|
|
|
template.sub!(/\^/, "B" * len)
|
|
|
|
|
|
|
|
# 10k is OK
|
|
|
|
entities = '%a;' * 2 # 5k entity * 2 = 10k
|
|
|
|
REXML::Document.new(template.sub(/\$/, entities))
|
|
|
|
|
|
|
|
# above 10k explodes
|
|
|
|
entities = '%a;' * 3 # 5k entity * 2 = 15k
|
2015-06-01 22:18:44 -04:00
|
|
|
assert_raise(REXML::ParseException) do
|
2014-10-27 07:18:02 -04:00
|
|
|
REXML::Document.new(template.sub(/\$/, entities))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_raw
|
|
|
|
source = '<!DOCTYPE foo [
|
2010-09-17 09:14:14 -04:00
|
|
|
<!ENTITY ent "replace">
|
|
|
|
]><a>replace &ent;</a>'
|
2014-05-27 09:10:55 -04:00
|
|
|
doc = REXML::Document.new( source, {:raw=>:all})
|
|
|
|
assert_equal('replace &ent;', doc.root.get_text.to_s)
|
|
|
|
assert_equal(source, doc.to_s)
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_lazy_evaluation
|
|
|
|
source = '<!DOCTYPE foo [
|
2010-09-17 09:14:14 -04:00
|
|
|
<!ENTITY ent "replace">
|
|
|
|
]><a>replace &ent;</a>'
|
2014-05-27 09:10:55 -04:00
|
|
|
doc = REXML::Document.new( source )
|
|
|
|
assert_equal(source, doc.to_s)
|
|
|
|
assert_equal("replace replace", doc.root.text)
|
|
|
|
assert_equal(source, doc.to_s)
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
# Contributed (not only test, but bug fix!!) by Kouhei Sutou
|
|
|
|
def test_entity_replacement
|
|
|
|
source = %q{<!DOCTYPE foo [
|
|
|
|
<!ENTITY % YN '"Yes"'>
|
|
|
|
<!ENTITY WhatHeSaid "He said %YN;">]>
|
|
|
|
<a>&WhatHeSaid;</a>}
|
|
|
|
|
|
|
|
d = REXML::Document.new( source )
|
|
|
|
dt = d.doctype
|
|
|
|
assert_equal( '"Yes"', dt.entities[ "YN" ].value )
|
|
|
|
assert_equal( 'He said "Yes"', dt.entities[ "WhatHeSaid" ].value )
|
|
|
|
assert_equal( 'He said "Yes"', d.elements[1].text )
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
# More unit tests from Kouhei. I looove users who give me unit tests.
|
|
|
|
def test_entity_insertions
|
|
|
|
assert_equal("&", REXML::Text.new("&", false, nil, true).to_s)
|
|
|
|
#assert_equal("&", REXML::Text.new("&", false, false).to_s)
|
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_single_pass_unnormalization # ticket 123
|
|
|
|
assert_equal '&&', REXML::Text::unnormalize('&amp;&')
|
|
|
|
end
|
2013-04-26 10:36:30 -04:00
|
|
|
|
2014-05-27 09:10:55 -04:00
|
|
|
def test_entity_filter
|
|
|
|
document = REXML::Document.new(<<-XML)
|
2013-04-26 10:36:30 -04:00
|
|
|
<!DOCTYPE root [
|
|
|
|
<!ENTITY copy "(c)">
|
|
|
|
<!ENTITY release-year "2013">
|
|
|
|
]>
|
|
|
|
<root/>
|
|
|
|
XML
|
2014-05-27 09:10:55 -04:00
|
|
|
respect_whitespace = false
|
|
|
|
parent = document.root
|
|
|
|
raw = false
|
|
|
|
entity_filter = ["copy"]
|
|
|
|
assert_equal("(c) &release-year;",
|
|
|
|
REXML::Text.new("(c) 2013",
|
|
|
|
respect_whitespace,
|
|
|
|
parent,
|
|
|
|
raw,
|
|
|
|
entity_filter).to_s)
|
|
|
|
end
|
2013-04-26 10:36:30 -04:00
|
|
|
end
|
2010-09-17 09:14:14 -04:00
|
|
|
end
|