Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions perl-libxml-mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1227,11 +1227,20 @@ nodeSv2C( SV * scalar, xmlNodePtr refnode )
if ( PmmNodeEncoding(real_dom) == XML_CHAR_ENCODING_NONE ) {
SetPmmNodeEncoding(real_dom, XML_CHAR_ENCODING_UTF8);
}
/* the following allocates a new string (by xmlStrdup if no conversion is done) */
string= PmmFastEncodeString( PmmNodeEncoding(real_dom),
(xmlChar*) t_pv,
(const xmlChar*)real_dom->encoding,
len);
if ( PmmNodeEncoding(real_dom) == XML_CHAR_ENCODING_UTF8 ) {
/* When the document is UTF-8, non-UTF8 Perl SVs
hold Latin-1 bytes — encode from Latin-1 to
UTF-8, not a no-op UTF-8 copy. */
string= PmmFastEncodeString( XML_CHAR_ENCODING_8859_1,
(xmlChar*) t_pv,
(const xmlChar*)"ISO-8859-1",
len);
} else {
string= PmmFastEncodeString( PmmNodeEncoding(real_dom),
(xmlChar*) t_pv,
(const xmlChar*)real_dom->encoding,
len);
}
xs_warn( "nodeSv2C: done!\n" );
#ifdef HAVE_UTF8
} else {
Expand All @@ -1257,6 +1266,21 @@ nodeSv2C( SV * scalar, xmlNodePtr refnode )
}
xs_warn("nodeSv2C: no encoding !!\n");

#ifdef HAVE_UTF8
if ( scalar != NULL && scalar != &PL_sv_undef && !DO_UTF8(scalar) ) {
dTHX;
STRLEN len = 0;
char * t_pv = SvPV(scalar, len);
if ( t_pv && len > 0 ) {
xmlChar *string = PmmFastEncodeString( XML_CHAR_ENCODING_8859_1,
(xmlChar*) t_pv,
(const xmlChar*)"ISO-8859-1",
len);
if (string != NULL)
return string;
}
}
#endif
return Sv2C( scalar, NULL );
}

Expand Down
99 changes: 99 additions & 0 deletions t/49unicode_bug_rt115190.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use strict;
use warnings;
use Test::More tests => 8;
use XML::LibXML;

sub _u { my $s = shift; utf8::upgrade($s); $s }
sub _d { my $s = shift; utf8::downgrade($s, 1); $s }

sub gen_text_node {
my ($encoding, $text) = @_;
my $doc = XML::LibXML::Document->new("1.0", $encoding);
my $root = $doc->createElement("root");
$doc->setDocumentElement($root);
$root->appendText($text);
return $doc->toString();
}

sub parse_text_node {
my ($xml) = @_;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($xml);
return $doc->documentElement->textContent();
}

sub gen_attr_node {
my ($encoding, $text) = @_;
my $doc = XML::LibXML::Document->new("1.0", $encoding);
my $root = $doc->createElement("root");
$doc->setDocumentElement($root);
$root->setAttribute('attr', $text);
return $doc->toString();
}

sub parse_attr_node {
my ($xml) = @_;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($xml);
return $doc->documentElement->getAttribute('attr');
}

{
my $text = "\xC9\xE9";
my $text_u = _u($text);
my $text_d = _d($text);

# TEST
is($text_d, $text_u, "upgraded and downgraded are equal");

for my $encoding (qw( UTF-8 )) {
{
my $xml_u = gen_text_node($encoding, $text_u);
my $xml_d = gen_text_node($encoding, $text_d);

# TEST
is($xml_d, $xml_u,
"gen_text_node produces identical XML for upgraded/downgraded ($encoding)");

my $got = parse_text_node($xml_u);
# TEST
is(sprintf("%vX", $got), sprintf("%vX", $text),
"round-trip upgraded text node ($encoding)");

$got = parse_text_node($xml_d);
# TEST
is(sprintf("%vX", $got), sprintf("%vX", $text),
"round-trip downgraded text node ($encoding)");
}

{
my $xml_u = gen_attr_node($encoding, $text_u);
my $xml_d = gen_attr_node($encoding, $text_d);

# TEST
is($xml_d, $xml_u,
"gen_attr_node produces identical XML for upgraded/downgraded ($encoding)");

my $got = parse_attr_node($xml_u);
# TEST
is(sprintf("%vX", $got), sprintf("%vX", $text),
"round-trip upgraded attribute ($encoding)");

$got = parse_attr_node($xml_d);
# TEST
is(sprintf("%vX", $got), sprintf("%vX", $text),
"round-trip downgraded attribute ($encoding)");
}
}

{
my $doc = XML::LibXML::Document->new("1.0");
my $root = $doc->createElement("root");
$doc->setDocumentElement($root);
$root->appendText($text_d);
my $got = $doc->documentElement->textContent();
# TEST
is(sprintf("%vX", $got), sprintf("%vX", $text),
"appendText on doc without encoding, downgraded string");
}
}
Loading