Consider all ASCIIPropertyLists as UTF8 on opening, instead of considering them ASCII. Fixes #15.

This commit is contained in:
2017-05-20 02:27:53 +01:00
parent 25e2063112
commit 673825548f
4 changed files with 33 additions and 14 deletions

View File

@@ -283,6 +283,16 @@ namespace plistcil.test
return false; return false;
} }
} [Fact]
public static void testAsciiUtf8CharactersInQuotedString()
{
NSObject x = PropertyListParser.Parse(new FileInfo("test-files/test-ascii-utf8.plist"));
NSDictionary d = (NSDictionary)x;
Assert.Equal(2, d.Count);
Assert.Equal("JÔÖú@2x.jpg", d.ObjectForKey("path").ToString());
Assert.Equal("QÔÖú@2x 啕.jpg", d.ObjectForKey("Key QÔÖª@2x 䌡").ToString());
}
}
} }

View File

@@ -90,6 +90,11 @@
<Gettext-ScanForTranslations>False</Gettext-ScanForTranslations> <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="..\test-files\test-ascii-utf8.plist">
<Link>test-files\test-ascii-utf8.plist</Link>
<Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="test-files\ResourceRules.plist"> <None Include="test-files\ResourceRules.plist">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>

View File

@@ -92,7 +92,7 @@ namespace Claunia.PropertyList
/// <exception cref="FormatException">When an error occurs during parsing.</exception> /// <exception cref="FormatException">When an error occurs during parsing.</exception>
public static NSObject Parse(byte[] bytes) public static NSObject Parse(byte[] bytes)
{ {
ASCIIPropertyListParser parser = new ASCIIPropertyListParser(bytes); ASCIIPropertyListParser parser = new ASCIIPropertyListParser(Encoding.UTF8.GetString(bytes).ToCharArray());
return parser.Parse(); return parser.Parse();
} }
@@ -235,7 +235,7 @@ namespace Claunia.PropertyList
/** /**
* Property list source data * Property list source data
*/ */
byte[] data; char[] data;
/** /**
* Current parsing index * Current parsing index
*/ */
@@ -253,7 +253,7 @@ namespace Claunia.PropertyList
/// Creates a new parser for the given property list content. /// Creates a new parser for the given property list content.
/// </summary> /// </summary>
/// <param name="propertyListContent">The content of the property list that is to be parsed.</param> /// <param name="propertyListContent">The content of the property list that is to be parsed.</param>
ASCIIPropertyListParser(byte[] propertyListContent) ASCIIPropertyListParser(char[] propertyListContent)
{ {
data = propertyListContent; data = propertyListContent;
} }
@@ -311,7 +311,7 @@ namespace Claunia.PropertyList
for (int i = 1; i < expectedSymbols.Length; i++) for (int i = 1; i < expectedSymbols.Length; i++)
excString += " or '" + expectedSymbols[i] + "'"; excString += " or '" + expectedSymbols[i] + "'";
excString += " but found '" + (char)data[index] + "'"; excString += " but found '" + data[index] + "'";
throw new FormatException(String.Format("{0} at {1}", excString, index)); throw new FormatException(String.Format("{0} at {1}", excString, index));
} }
} }
@@ -407,7 +407,7 @@ namespace Claunia.PropertyList
string s = ""; string s = "";
while (!Accept(symbols)) while (!Accept(symbols))
{ {
s += (char)data[index]; s += data[index];
Skip(); Skip();
} }
return s; return s;
@@ -423,7 +423,7 @@ namespace Claunia.PropertyList
String s = ""; String s = "";
while (!Accept(symbol)) while (!Accept(symbol))
{ {
s += (char)data[index]; s += data[index];
Skip(); Skip();
} }
return s; return s;
@@ -463,19 +463,19 @@ namespace Claunia.PropertyList
{ {
switch (data[index]) switch (data[index])
{ {
case (byte)ARRAY_BEGIN_TOKEN: case ARRAY_BEGIN_TOKEN:
{ {
return ParseArray(); return ParseArray();
} }
case (byte)DICTIONARY_BEGIN_TOKEN: case DICTIONARY_BEGIN_TOKEN:
{ {
return ParseDictionary(); return ParseDictionary();
} }
case (byte)DATA_BEGIN_TOKEN: case DATA_BEGIN_TOKEN:
{ {
return ParseData(); return ParseData();
} }
case (byte)QUOTEDSTRING_BEGIN_TOKEN: case QUOTEDSTRING_BEGIN_TOKEN:
{ {
string quotedString = ParseQuotedString(); string quotedString = ParseQuotedString();
//apple dates are quoted strings of length 20 and after the 4 year digits a dash is found //apple dates are quoted strings of length 20 and after the 4 year digits a dash is found
@@ -690,7 +690,7 @@ namespace Claunia.PropertyList
//Read from opening quotation marks to closing quotation marks and skip escaped quotation marks //Read from opening quotation marks to closing quotation marks and skip escaped quotation marks
while (data[index] != QUOTEDSTRING_END_TOKEN || (data[index - 1] == QUOTEDSTRING_ESCAPE_TOKEN && unescapedBackslash)) while (data[index] != QUOTEDSTRING_END_TOKEN || (data[index - 1] == QUOTEDSTRING_ESCAPE_TOKEN && unescapedBackslash))
{ {
quotedString += (char)data[index]; quotedString += data[index];
if (Accept(QUOTEDSTRING_ESCAPE_TOKEN)) if (Accept(QUOTEDSTRING_ESCAPE_TOKEN))
{ {
unescapedBackslash = !(data[index - 1] == QUOTEDSTRING_ESCAPE_TOKEN && unescapedBackslash); unescapedBackslash = !(data[index - 1] == QUOTEDSTRING_ESCAPE_TOKEN && unescapedBackslash);
@@ -739,8 +739,7 @@ namespace Claunia.PropertyList
} }
default: default:
{ //a normal ASCII char { //a normal ASCII char
strBytes.Add((byte)0); strBytes.AddRange(Encoding.BigEndianUnicode.GetBytes(new[] { c.Current }));
strBytes.Add((byte)c.Current);
break; break;
} }
} }

View File

@@ -0,0 +1,5 @@
// !$*UTF8*$!
{
path = "JÔÖú@2x.jpg";
"Key QÔÖª@2x \u4321" = "QÔÖú@2x 啕.jpg";
}