Permalink
Browse files

Allow the parsing of <nil /> tags when they are encountered, even if

$RPC::XML::ALLOW_NIL is not set. Only limit the generation of these tags.
  • Loading branch information...
1 parent 12dc29c commit cd498bd7cabfb6dc453517bc653aa853425e671a @rjray rjray committed Jun 25, 2010
Showing with 112 additions and 22 deletions.
  1. +7 −5 lib/RPC/XML.pm
  2. +4 −6 lib/RPC/XML/Parser/XMLLibXML.pm
  3. +6 −11 lib/RPC/XML/Parser/XMLParser.pm
  4. +95 −0 t/90_rt58065_allow_nil.t
View
@@ -61,7 +61,7 @@ BEGIN
RPC_DATETIME_ISO8601 RPC_BASE64 RPC_NIL) ],
all => [ @EXPORT_OK ]);
-$VERSION = '1.50';
+$VERSION = '1.51';
$VERSION = eval $VERSION; ## no critic (ProhibitStringyEval)
# Global error string
@@ -602,13 +602,15 @@ use base 'RPC::XML::simple_type';
# no value need be passed to this method
sub new
{
- my $class = shift;
- my $value = undef;
+ my ($class, $value, $flag) = @_;
+ # We need $value so we can bless a reference to it. But regardless of
+ # what was passed, it needs to be undef to be a proper "nil".
+ undef $value;
- if (! $RPC::XML::ALLOW_NIL)
+ if (! $RPC::XML::ALLOW_NIL && ! $flag)
{
$RPC::XML::ERROR = "${class}::new: \$RPC::XML::ALLOW_NIL must be set" .
- 'for RPC::XML::nil objects to be supported';
+ ' for RPC::XML::nil objects to be supported';
return;
}
@@ -42,7 +42,7 @@ use base 'RPC::XML::Parser';
use Scalar::Util 'reftype';
use XML::LibXML;
-$VERSION = '0.11';
+$VERSION = '1.12';
$VERSION = eval $VERSION; ## no critic (ProhibitStringyEval)
# This is to identify valid types that don't already have special handling
@@ -452,16 +452,14 @@ sub dom_value ## no critic(ProhibitExcessComplexity)
}
elsif ($nodename eq 'nil')
{
- if (! $RPC::XML::ALLOW_NIL)
- {
- return "$me: The nil tag is only allowed if explicitly enabled";
- }
if ($children[0]->hasChildNodes())
{
return "$me: The nil tag must be empty";
}
- $value = RPC::XML::nil->new();
+ # The string is a flag to force nil creation even if the global flag
+ # isn't set. The undef is just to put the flag in the right place.
+ $value = RPC::XML::nil->new(undef, 'nil is always allowed in parsing');
}
elsif (my $type = $VALIDTYPES{$nodename})
{
@@ -73,7 +73,7 @@ use constant FAULTSTART => 22;
# This is to identify valid types
use constant VALIDTYPES => { map { ($_, 1) } qw(int i4 i8 string double
boolean dateTime.iso8601
- base64) };
+ base64 nil) };
# This maps XML tags to stack-machine tokens
use constant TAG2TOKEN => { methodCall => METHOD,
methodResponse => RESPONSE,
@@ -98,7 +98,7 @@ use XML::Parser;
require RPC::XML;
-$VERSION = '1.21';
+$VERSION = '1.22';
$VERSION = eval $VERSION; ## no critic (ProhibitStringyEval)
###############################################################################
@@ -236,9 +236,7 @@ sub tag_start
{
push @{$robj->[M_STACK]}, TAG2TOKEN->{$elem};
}
- # Note that the <nil /> element is not in VALIDTYPES, as it is only valid
- # when $RPC::XML::ALLOW_NIL is true.
- elsif (VALIDTYPES->{$elem} || ($RPC::XML::ALLOW_NIL && $elem eq 'nil'))
+ elsif (VALIDTYPES->{$elem})
{
# All datatypes are represented on the stack by this generic token
push @{$robj->[M_STACK]}, DATATYPE;
@@ -332,10 +330,7 @@ sub tag_end ## no critic (ProhibitExcessComplexity)
}
# Decide what to do from here
- # Note that the <nil /> element is not in VALIDTYPES, as it is only valid
- # when $RPC::XML::ALLOW_NIL is true.
- if (VALIDTYPES->{$elem} || ## no critic (ProhibitCascadingIfElse)
- ($elem eq 'nil' && $RPC::XML::ALLOW_NIL))
+ if (VALIDTYPES->{$elem}) ## no critic (ProhibitCascadingIfElse)
{
# This is the closing tag of one of the data-types.
$class = $elem;
@@ -363,7 +358,7 @@ sub tag_end ## no critic (ProhibitExcessComplexity)
}
elsif ($class eq 'nil')
{
- # We passed the earlier test, so we know that <nil /> is allowed.
+ # We now allow parsing of <nil/> at all times.
# By definition though, it must be, well... nil.
if ($cdata !~ /^\s*$/)
{
@@ -373,7 +368,7 @@ sub tag_end ## no critic (ProhibitExcessComplexity)
$class = "RPC::XML::$class";
# The string at the end is only seen by the RPC::XML::base64 class
- $obj = $class->new($cdata, 'base64 already encoded');
+ $obj = $class->new($cdata, 'base64 is encoded, nil is allowed');
if (! $obj)
{
return error($robj, $self, 'Error instantiating data object: ' .
View
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+# https://rt.cpan.org/Ticket/Display.html?id=58065
+#
+# Test that the parser-factory instance classes allow the parsing of the
+# <nil /> tag whether $RPC::XML::ALLOW_NIL is set or not. This is to allow
+# liberal acceptance of the tag in what we take in. Production of the tag is
+# still limited to only when the flag is set.
+
+use strict;
+use vars qw($parser $req_message $res_message $parsed);
+
+use Test::More tests => 8;
+
+# Use classes from here directly to create test messages for parsing
+use RPC::XML;
+
+# This factory-class-instance should always be present
+require RPC::XML::Parser::XMLParser;
+# This one may not be present
+my $can_libxml = eval {
+ require RPC::XML::Parser::XMLLibXML;
+ 1;
+};
+
+# Create mock request and response messages that contain nils in them by first
+# setting the flag. We'll then unset the flag for the tests.
+
+$RPC::XML::ALLOW_NIL = 1;
+
+$req_message = RPC::XML::request->new(
+ 'foo',
+ RPC::XML::nil->new()
+);
+$res_message = RPC::XML::response->new(
+ RPC::XML::nil->new()
+);
+
+$RPC::XML::ALLOW_NIL = 0;
+
+# To test this, instantiate each parser then call the ->parse() method with
+# both the request and response message that contain nil tags.
+
+# First test the class we always have, RPC::XML::Parser::XMLParser
+$parser = RPC::XML::Parser::XMLParser->new();
+
+# Test-parse the request message
+$parsed = $parser->parse($req_message->as_string);
+
+isa_ok($parsed, 'RPC::XML::request');
+SKIP: {
+ skip 'Parsed value corrupted, cannot test nil value', 1
+ unless (ref($parsed) eq 'RPC::XML::request');
+ isa_ok($parsed->args->[0], 'RPC::XML::nil');
+}
+
+# Test-parse the response message
+$parsed = $parser->parse($res_message->as_string);
+
+isa_ok($parsed, 'RPC::XML::response');
+SKIP: {
+ skip 'Parsed value corrupted, cannot test nil value', 1
+ unless (ref($parsed) eq 'RPC::XML::response');
+ isa_ok($parsed->value, 'RPC::XML::nil');
+}
+
+# Next, test RPC::XML::Parser::XMLLibXML (which we might not have)
+SKIP: {
+ skip 'XML::LibXML not installed', 4
+ unless $can_libxml;
+
+ $parser = RPC::XML::Parser::XMLLibXML->new();
+
+ # Test-parse the request message
+ $parsed = $parser->parse($req_message->as_string);
+
+ isa_ok($parsed, 'RPC::XML::request');
+ SKIP: {
+ skip 'Parsed value corrupted, cannot test nil value', 1
+ unless (ref($parsed) eq 'RPC::XML::request');
+ isa_ok($parsed->args->[0], 'RPC::XML::nil');
+ }
+
+ # Test-parse the response message
+ $parsed = $parser->parse($res_message->as_string);
+
+ isa_ok($parsed, 'RPC::XML::response');
+ SKIP: {
+ skip 'Parsed value corrupted, cannot test nil value', 1
+ unless (ref($parsed) eq 'RPC::XML::response');
+ isa_ok($parsed->value, 'RPC::XML::nil');
+ }
+}
+
+exit;

0 comments on commit cd498bd

Please sign in to comment.