Package:        libgnustep-base1.19
Version:        > 1.19.1

When loading an XML Property List (plist) which contains leading or
trailing whitespace in a string property, or whitespace surrounding an
XML entity, this whitespace is incorrectly stripped.

eg. <string> A &amp; B </string>
-> "A&B"

This bug specifically affects the game Oolite on systems with these
faulty versions of libgnustep-base.  Oolite is packaged and shipped with
Debian.

This bug has been fixed by GNUstep in their trunk revision #30454 and
they will backport the fix to the 1.20 version of gnustep-base.  They
have indicated they will not backport the fix to 1.19.x
See: https://savannah.gnu.org/bugs/index.php?29955

The bug has also been raised for Ubuntu:
See: https://bugs.launchpad.net/ubuntu/+source/gnustep-base/+bug/585179

Please find attached a backported patch for gnustep-base-1.19.3.  This
patch has been used to build PPA versions of libgnustep-base1.19 for
Ubuntu Lucid and Ubuntu Maverick.
See:
https://launchpad.net/~3-launchpad-micha-michaelwerle-com/+archive/ppa

Please also find attached a test program (supplied by Jens Ayton) which
illustrates this issue.  Specifically, Tests #1, #2, and #6 are
affected.

Many thanks,
 - Micha.
diff -u -r gnustep-base-1.19.3.orig/Source/NSPropertyList.m gnustep-base-1.19.3/Source/NSPropertyList.m
--- gnustep-base-1.19.3.orig/Source/NSPropertyList.m	2009-08-04 09:08:52.000000000 +0100
+++ gnustep-base-1.19.3/Source/NSPropertyList.m	2010-05-29 20:20:02.733659340 +0100
@@ -81,6 +81,7 @@
   NSString				*key;
   BOOL					inArray;
   BOOL					inDictionary;
+  BOOL					inString;
   BOOL					parsed;
   BOOL					success;
   id					plist;
@@ -129,10 +130,15 @@
 }
 
 - (void) parser: (NSXMLParser *)parser
-  foundCharacters: (NSString *)string
+foundCharacters: (NSString *)string
 {
-  string = [string stringByTrimmingSpaces];
-  if ([string length] > 0)
+  [value appendString: string];
+}
+
+- (void) parser: (NSXMLParser *)parser
+foundIgnorableWhitespace: (NSString *)string
+{
+  if (YES == inString)
     {
       [value appendString: string];
     }
@@ -176,6 +182,10 @@
       inArray = YES;
       inDictionary = NO;
     }
+  else if ([elementName isEqualToString: @"string"] == YES)
+    {
+      inString = YES;
+    }
 }
 
 - (void) parser: (NSXMLParser *)parser
@@ -185,11 +195,12 @@
 {
   BOOL	inContainer = NO;
 
+  inString = NO;
   if ([elementName isEqualToString: @"dict"] == YES)
     {
       inContainer = YES;
     }
-  if ([elementName isEqualToString: @"array"] == YES)
+  else if ([elementName isEqualToString: @"array"] == YES)
     {
       inContainer = YES;
     }
diff -u -r gnustep-base-1.19.3.orig/Source/NSXMLParser.m gnustep-base-1.19.3/Source/NSXMLParser.m
--- gnustep-base-1.19.3.orig/Source/NSXMLParser.m	2009-08-04 08:47:58.000000000 +0100
+++ gnustep-base-1.19.3/Source/NSXMLParser.m	2010-05-29 20:16:10.553667187 +0100
@@ -620,6 +620,8 @@
   int line;				// current line (counts from 0)
   int column;				// current column (counts from 0)
   BOOL abort;				// abort parse loop
+  BOOL ignorable;			// whitespace is ignorable
+  BOOL whitespace;			// had only whitespace in current data
   BOOL shouldProcessNamespaces;
   BOOL shouldReportNamespacePrefixes;
   BOOL shouldResolveExternalEntities;
@@ -631,6 +633,7 @@
   IMP	foundCDATA;
   IMP	foundCharacters;
   IMP	foundComment;
+  IMP	foundIgnorable;
   
 } NSXMLParserIvars;
 
@@ -641,6 +644,7 @@
 static SEL	foundCDATASel;
 static SEL	foundCharactersSel;
 static SEL	foundCommentSel;
+static SEL	foundIgnorableSel;
 
 @implementation SloppyXMLParser
 
@@ -674,6 +678,8 @@
 	= @selector(parser:foundCharacters:);
       foundCommentSel
 	= @selector(parser:foundComment:);
+      foundIgnorableSel
+	= @selector(parser:foundIgnorableWhitespace:);
     }
 }
 
@@ -813,6 +819,16 @@
 	{
 	  this->foundComment = 0;
 	}
+
+      if ([_del respondsToSelector: foundIgnorableSel])
+	{
+	  this->foundIgnorable
+	    = [_del methodForSelector: foundIgnorableSel];
+	}
+      else
+	{
+	  this->foundIgnorable = 0;
+	}
     }
 }
 
@@ -1220,6 +1236,10 @@
       return [self _parseError: @"missing <?xml > preamble"
 	code: NSXMLParserDocumentStartError];
     }
+  /* Start by accumulating ignorable whitespace.
+   */
+  this->ignorable = YES;
+  this->whitespace = YES;
   c = cget();  // get first character
   while (!this->abort)
     {
@@ -1237,26 +1257,55 @@
             this->column = 0;
 	    break;
 
+          case '<':
+	    /* Whitespace immediately before an element is always ignorable.
+	     */
+	    this->ignorable = YES; /* Fall through to push out data */
           case EOF: 
-          case '<': 
           case '&': 
             {
               /* push out any characters that have been collected so far
                */
               if (this->cp - vp > 1)
                 {
-                  /* check for whitespace only - might set/reset
-                   * a flag to indicate so
-                   */
-                  if (this->foundCharacters != 0)
-                    {
-		      NSString	*s;
+		  const unsigned char	*p;
+		  NSString		*s;
 
-		      s = NewUTF8STR(vp, this->cp - vp - 1);
+		  p = this->cp - 1;
+		  if (YES == this->ignorable)
+		    {
+		      if (YES == this->whitespace)
+			{
+			  p = vp;	// all whitespace
+			}
+		      else
+			{
+			  /* step through trailing whitespace (if any)
+			   */
+			  while (p > vp && isspace(p[-1]))
+			    {
+			      p--;
+			    }
+			}
+		    }
+                  if (p - vp > 0 && this->foundCharacters != 0)
+                    {
+		      /* Process initial data as characters
+		       */
+		      s = NewUTF8STR(vp, p - vp);
                       (*this->foundCharacters)(_del,
 			foundCharactersSel, self, s);
 		      [s release];
                     }
+		  if (p < this->cp - 1 && this->foundIgnorable != 0)
+		    {
+		      /* Process data as ignorable whitespace
+		       */
+		      s = NewUTF8STR(p, this->cp - p - 1);
+		      (*this->foundIgnorable)(_del,
+			foundIgnorableSel, self, s);
+		      [s release];
+		    }
                   vp = this->cp;
                 }
             }
@@ -1265,6 +1314,30 @@
       switch(c)
         {
           default: 
+	    if (YES == this->whitespace && !isspace(c))
+	      {
+		if (YES == this->ignorable && this->cp - vp > 1)
+		  {
+		    /* We have accumulated ignorable whitespace ...
+		     * push it out.
+		     */
+		    if (this->foundIgnorable != 0)
+		      {
+			NSString	*s;
+
+			s = NewUTF8STR(vp, this->cp - vp - 1);
+			(*this->foundIgnorable)(_del,
+			  foundIgnorableSel, self, s);
+			[s release];
+		      }
+		    vp = this->cp - 1;
+		  }
+		/* We have read non-space data, so whitespace is no longer
+		 * ignorable, and the buffer no loinger contains only space.
+		 */
+		this->ignorable = NO;
+		this->whitespace = NO;
+	      }
             c = cget();  // just collect until we push out (again)
             continue;
 
@@ -1306,6 +1379,12 @@
             {
               NSString  *entity;
 
+	      /* After any entity, whitespace is no longer ignorable, but
+	       * we will have an empty buffer to accumulate it.
+	       */
+	      this->ignorable = NO;
+	      this->whitespace = YES;
+
               if ([self _parseEntity: &entity] == NO)
                 {
                   return [self _parseError: @"empty entity name"
@@ -1329,6 +1408,12 @@
               NSString                  *arg;
               const unsigned char       *tp = this->cp;  // tag pointer
 
+	      /* After processing a tag, whitespace will be ignorable and
+	       * we can start accumulating it in our buffer.
+	       */
+	      this->ignorable = YES;
+	      this->whitespace = YES;
+
               if (this->cp < this->cend-3
                 && strncmp((char *)this->cp, "!--", 3) == 0)
                 {
#import <Foundation/Foundation.h>


#define kTestCaseCount		(6)

typedef struct
{
	const char			*plist;
	size_t				plistLength;
	const char			*text;
	size_t				textLength;
} TestCase;


static const TestCase sTestCases[kTestCaseCount];


static void RunTestCase(const TestCase *testCase, unsigned idx);


int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	unsigned i;
	for (i = 0; i < kTestCaseCount; i++)
	{
		RunTestCase(&sTestCases[i], i + 1);
	}
	
    [pool release];
    return 0;
}


static void RunTestCase(const TestCase *testCase, unsigned idx)
{
	NSData			*data = nil;
	NSString		*errorDesc = nil;
	id				plist = nil;
	NSString		*plistValue = nil;
	NSString		*expectedValue = nil;
	
	NS_DURING
	
	data = [NSData dataWithBytes:testCase->plist length:testCase->plistLength];
	if (data == nil)
	{
		NSLog(@"Test case %u FAILED: could not construct plist data.", idx);
		NS_VOIDRETURN;
	}
	
	plist = [NSPropertyListSerialization propertyListFromData:data
											 mutabilityOption:NSPropertyListImmutable
													   format:NULL
											 errorDescription:&errorDesc];
	
	if (plist == nil)
	{
		NSLog(@"Test case %u FAILED: could not parse property list. Error string: %@", idx, errorDesc);
		NS_VOIDRETURN;
	}
	
	if (![plist isKindOfClass:[NSArray class]] || [plist count] != 1)
	{
		NSLog(@"Test case %u FAILED: plist content is not array with one member.", idx);
		NS_VOIDRETURN;
	}
	
	plistValue = [plist objectAtIndex:0];
	if (![plistValue isKindOfClass:[NSString class]])
	{
		NSLog(@"Test case %u FAILED: plist content is not an array with one string.", idx);
		NS_VOIDRETURN;
	}
	
	data = [NSData dataWithBytes:testCase->text length:testCase->textLength];
	if (data == nil)
	{
		NSLog(@"Test case %u FAILED: could not construct string data.", idx);
		NS_VOIDRETURN;
	}
	
	expectedValue = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
	[expectedValue autorelease];
	if (expectedValue == nil)
	{
		NSLog(@"Test case %u FAILED: could not construct string from data (must be UTF-8).", idx);
		NS_VOIDRETURN;
	}
	
	if ([plistValue compare:expectedValue options:0] != NSOrderedSame)
	{
		NSLog(@"Test case %u FAILED: read string is wrong (expected \"%...@\", got \"%...@\").", idx, expectedValue, plistValue);
		NS_VOIDRETURN;
	}
	
	NS_HANDLER
	
	NSLog(@"Test case %u FAILED: exception thrown - %@ : %@", idx, [localException name], [localException reason]);
	return;
	
	NS_ENDHANDLER
	
	NSLog(@"Test case %u succeeded.", idx);
}


/*	Test data follows. Data entries are UTF-8 strings, expressed as byte
	arrays to minimize risk of encoding problems.
*/

// Cyrillic string.
static const char sTestPlist1[] =
{
	0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73,
	0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
	0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22,
	0x55, 0x54, 0x46, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49,
	0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x47, 0x4E, 0x55, 0x73,
	0x74, 0x65, 0x70, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x30, 0x2E, 0x39, 0x2F, 0x2F,
	0x45, 0x4E, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A,
	0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x6E, 0x75, 0x73,
	0x74, 0x65, 0x70, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x6C,
	0x69, 0x73, 0x74, 0x2D, 0x30, 0x5F, 0x39, 0x2E, 0x78, 0x6D,
	0x6C, 0x22, 0x3E, 0x0A, 0x3C, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22,
	0x30, 0x2E, 0x39, 0x22, 0x3E, 0x0A, 0x3C, 0x61, 0x72, 0x72,
	0x61, 0x79, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0xD0, 0x93, 0xD0, 0xBE, 0xD0, 0xB2, 0xD0,
	0xBE, 0xD1, 0x80, 0xD0, 0xB8, 0xD1, 0x82, 0x20, 0xD1, 0x81,
	0xD1, 0x82, 0xD0, 0xB0, 0xD0, 0xBD, 0xD1, 0x86, 0xD0, 0xB8,
	0xD1, 0x8F, 0x20, 0x4C, 0x61, 0x65, 0x6E, 0x69, 0x6E, 0x2E,
	0x20, 0xD0, 0x9C, 0xD1, 0x8B, 0x20, 0xD0, 0xB7, 0xD0, 0xB0,
	0xD0, 0xB3, 0xD1, 0x80, 0xD1, 0x83, 0xD0, 0xB7, 0xD0, 0xB8,
	0xD0, 0xBB, 0xD0, 0xB8, 0x20, 0xD1, 0x81, 0xD1, 0x82, 0xD1,
	0x8B, 0xD0, 0xBA, 0xD0, 0xBE, 0xD0, 0xB2, 0xD0, 0xBE, 0xD1,
	0x87, 0xD0, 0xBD, 0xD1, 0x8B, 0xD0, 0xB5, 0x20, 0xD0, 0xB8,
	0xD0, 0xBD, 0xD1, 0x81, 0xD1, 0x82, 0xD1, 0x80, 0xD1, 0x83,
	0xD0, 0xBA, 0xD1, 0x86, 0xD0, 0xB8, 0xD0, 0xB8, 0x20, 0xD0,
	0xBD, 0xD0, 0xB0, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0x0A, 0x3C, 0x2F, 0x61, 0x72, 0x72, 0x61,
	0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x3E, 0x0A
};
static const char sTestText1[] =
{
	0xD0, 0x93, 0xD0, 0xBE, 0xD0, 0xB2, 0xD0, 0xBE, 0xD1, 0x80,
	0xD0, 0xB8, 0xD1, 0x82, 0x20, 0xD1, 0x81, 0xD1, 0x82, 0xD0,
	0xB0, 0xD0, 0xBD, 0xD1, 0x86, 0xD0, 0xB8, 0xD1, 0x8F, 0x20,
	0x4C, 0x61, 0x65, 0x6E, 0x69, 0x6E, 0x2E, 0x20, 0xD0, 0x9C,
	0xD1, 0x8B, 0x20, 0xD0, 0xB7, 0xD0, 0xB0, 0xD0, 0xB3, 0xD1,
	0x80, 0xD1, 0x83, 0xD0, 0xB7, 0xD0, 0xB8, 0xD0, 0xBB, 0xD0,
	0xB8, 0x20, 0xD1, 0x81, 0xD1, 0x82, 0xD1, 0x8B, 0xD0, 0xBA,
	0xD0, 0xBE, 0xD0, 0xB2, 0xD0, 0xBE, 0xD1, 0x87, 0xD0, 0xBD,
	0xD1, 0x8B, 0xD0, 0xB5, 0x20, 0xD0, 0xB8, 0xD0, 0xBD, 0xD1,
	0x81, 0xD1, 0x82, 0xD1, 0x80, 0xD1, 0x83, 0xD0, 0xBA, 0xD1,
	0x86, 0xD0, 0xB8, 0xD0, 0xB8, 0x20, 0xD0, 0xBD, 0xD0, 0xB0,
	0x20
};


// "A & B", using &amp;
static const char sTestPlist2[] =
{
	0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73,
	0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
	0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22,
	0x55, 0x54, 0x46, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49,
	0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x47, 0x4E, 0x55, 0x73,
	0x74, 0x65, 0x70, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x30, 0x2E, 0x39, 0x2F, 0x2F,
	0x45, 0x4E, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A,
	0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x6E, 0x75, 0x73,
	0x74, 0x65, 0x70, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x6C,
	0x69, 0x73, 0x74, 0x2D, 0x30, 0x5F, 0x39, 0x2E, 0x78, 0x6D,
	0x6C, 0x22, 0x3E, 0x0A, 0x3C, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22,
	0x30, 0x2E, 0x39, 0x22, 0x3E, 0x0A, 0x3C, 0x61, 0x72, 0x72,
	0x61, 0x79, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0x41, 0x20, 0x26, 0x61, 0x6D, 0x70, 0x3B,
	0x20, 0x42, 0x3C, 0x2F, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
	0x3E, 0x0A, 0x3C, 0x2F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3E,
	0x0A, 0x3C, 0x2F, 0x70, 0x6C, 0x69, 0x73, 0x74, 0x3E, 0x0A
};
static const char sTestText2[] =
{
	0x41, 0x20, 0x26, 0x20, 0x42
};


// Euro symbol (U+20AC), literal
static const char sTestPlist3[] =
{
	0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73,
	0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
	0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22,
	0x55, 0x54, 0x46, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49,
	0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x47, 0x4E, 0x55, 0x73,
	0x74, 0x65, 0x70, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x30, 0x2E, 0x39, 0x2F, 0x2F,
	0x45, 0x4E, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A,
	0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x6E, 0x75, 0x73,
	0x74, 0x65, 0x70, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x6C,
	0x69, 0x73, 0x74, 0x2D, 0x30, 0x5F, 0x39, 0x2E, 0x78, 0x6D,
	0x6C, 0x22, 0x3E, 0x0A, 0x3C, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22,
	0x30, 0x2E, 0x39, 0x22, 0x3E, 0x0A, 0x3C, 0x61, 0x72, 0x72,
	0x61, 0x79, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0xE2, 0x82, 0xAC, 0x3C, 0x2F, 0x73, 0x74,
	0x72, 0x69, 0x6E, 0x67, 0x3E, 0x0A, 0x3C, 0x2F, 0x61, 0x72,
	0x72, 0x61, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x70, 0x6C, 0x69,
	0x73, 0x74, 0x3E, 0x0A
};
static const char sTestText3[] =
{
	0xE2, 0x82, 0xAC
};


// Euro symbol (U+20AC), escaped as &#8364;
static const char sTestPlist4[] =
{
	0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73,
	0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
	0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22,
	0x55, 0x54, 0x46, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49,
	0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x47, 0x4E, 0x55, 0x73,
	0x74, 0x65, 0x70, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x30, 0x2E, 0x39, 0x2F, 0x2F,
	0x45, 0x4E, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A,
	0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x6E, 0x75, 0x73,
	0x74, 0x65, 0x70, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x6C,
	0x69, 0x73, 0x74, 0x2D, 0x30, 0x5F, 0x39, 0x2E, 0x78, 0x6D,
	0x6C, 0x22, 0x3E, 0x0A, 0x3C, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22,
	0x30, 0x2E, 0x39, 0x22, 0x3E, 0x0A, 0x3C, 0x61, 0x72, 0x72,
	0x61, 0x79, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0xE2, 0x82, 0xAC, 0x3C, 0x2F, 0x73, 0x74,
	0x72, 0x69, 0x6E, 0x67, 0x3E, 0x0A, 0x3C, 0x2F, 0x61, 0x72,
	0x72, 0x61, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x70, 0x6C, 0x69,
	0x73, 0x74, 0x3E, 0x0A
};
static const char sTestText4[] =
{
	0xE2, 0x82, 0xAC
};


// Cruzeiro symbol (U+20A2), literal
static const char sTestPlist5[] =
{
	0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73,
	0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
	0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22,
	0x55, 0x54, 0x46, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49,
	0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x47, 0x4E, 0x55, 0x73,
	0x74, 0x65, 0x70, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x30, 0x2E, 0x39, 0x2F, 0x2F,
	0x45, 0x4E, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A,
	0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x6E, 0x75, 0x73,
	0x74, 0x65, 0x70, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x6C,
	0x69, 0x73, 0x74, 0x2D, 0x30, 0x5F, 0x39, 0x2E, 0x78, 0x6D,
	0x6C, 0x22, 0x3E, 0x0A, 0x3C, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22,
	0x30, 0x2E, 0x39, 0x22, 0x3E, 0x0A, 0x3C, 0x61, 0x72, 0x72,
	0x61, 0x79, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0xE2, 0x82, 0xA2, 0x3C, 0x2F, 0x73, 0x74,
	0x72, 0x69, 0x6E, 0x67, 0x3E, 0x0A, 0x3C, 0x2F, 0x61, 0x72,
	0x72, 0x61, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x70, 0x6C, 0x69,
	0x73, 0x74, 0x3E, 0x0A
};
static const char sTestText5[] =
{
	0xE2, 0x82, 0xA2
};


// "test " with trailing space
static const char sTestPlist6[] =
{
	0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73,
	0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
	0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22,
	0x55, 0x54, 0x46, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49,
	0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x47, 0x4E, 0x55, 0x73,
	0x74, 0x65, 0x70, 0x2F, 0x2F, 0x44, 0x54, 0x44, 0x20, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x20, 0x30, 0x2E, 0x39, 0x2F, 0x2F,
	0x45, 0x4E, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A,
	0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x67, 0x6E, 0x75, 0x73,
	0x74, 0x65, 0x70, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x6C,
	0x69, 0x73, 0x74, 0x2D, 0x30, 0x5F, 0x39, 0x2E, 0x78, 0x6D,
	0x6C, 0x22, 0x3E, 0x0A, 0x3C, 0x70, 0x6C, 0x69, 0x73, 0x74,
	0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22,
	0x30, 0x2E, 0x39, 0x22, 0x3E, 0x0A, 0x3C, 0x61, 0x72, 0x72,
	0x61, 0x79, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x74, 0x72, 0x69,
	0x6E, 0x67, 0x3E, 0x74, 0x65, 0x73, 0x74, 0x20, 0x3C, 0x2F,
	0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3E, 0x0A, 0x3C, 0x2F,
	0x61, 0x72, 0x72, 0x61, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x70,
	0x6C, 0x69, 0x73, 0x74, 0x3E, 0x0A
};
static const char sTestText6[] =
{
	0x74, 0x65, 0x73, 0x74, 0x20
};


static const TestCase sTestCases[kTestCaseCount] =
{
	{
		sTestPlist1, sizeof sTestPlist1,
		sTestText1, sizeof sTestText1
	},
	{
		sTestPlist2, sizeof sTestPlist2,
		sTestText2, sizeof sTestText2
	},
	{
		sTestPlist3, sizeof sTestPlist3,
		sTestText3, sizeof sTestText3
	},
	{
		sTestPlist4, sizeof sTestPlist4,
		sTestText4, sizeof sTestText4
	},
	{
		sTestPlist5, sizeof sTestPlist5,
		sTestText5, sizeof sTestText5
	},
	{
		sTestPlist6, sizeof sTestPlist6,
		sTestText6, sizeof sTestText6
	}
};

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to