diff --git a/plist-cil/PropertyListParser.cs b/plist-cil/PropertyListParser.cs index 984a7f5..c24b02b 100644 --- a/plist-cil/PropertyListParser.cs +++ b/plist-cil/PropertyListParser.cs @@ -74,6 +74,9 @@ namespace Claunia.PropertyList /// The type of the property list static int DetermineType(byte[] bytes) { + if (bytes.Length == 0) + return TYPE_ERROR_BLANK; + //Skip any possible whitespace at the beginning of the file int offset = 0; if (bytes.Length >= 3 && (bytes[0] & 0xFF) == 0xEF && (bytes[1] & 0xFF) == 0xBB && (bytes[2] & 0xFF) == 0xBF) @@ -95,30 +98,42 @@ namespace Claunia.PropertyList /// An input stream pointing to the beginning of the property list data. /// The stream will be reset to the beginning of the property /// list data after the type has been determined. - static int DetermineType(Stream fs) + static int DetermineType(Stream fs, long offset = 0) { - //Skip any possible whitespace at the beginning of the file - byte[] magicBytes = new byte[8]; + if (fs.Length == 0) + return TYPE_ERROR_BLANK; + + long index = offset; + long readLimit = index + 1024; + long mark = readLimit; + fs.Seek(offset, SeekOrigin.Current); int b; - long index = -1; bool bom = false; - long mark; + + //Skip any possible whitespace at the beginning of the file do { - mark = fs.Position; + if(++index > readLimit) + { + fs.Seek(mark, SeekOrigin.Begin); + return DetermineType(fs, readLimit); + } b = fs.ReadByte(); - index++; + //Check if we are reading the Unicode byte order mark (BOM) and skip it bom = index < 3 && ((index == 0 && b == 0xEF) || (bom && ((index == 1 && b == 0xBB) || (index == 2 && b == 0xBF)))); } - while(b != -1 && b == ' ' || b == '\t' || b == '\r' || b == '\n' || b == '\f' || bom); + while(b != -1 && (b == ' ' || b == '\t' || b == '\r' || b == '\n' || b == '\f' || bom)); + + if(b==-1) + return TYPE_ERROR_BLANK; + + byte[] magicBytes = new byte[8]; magicBytes[0] = (byte)b; int read = fs.Read(magicBytes, 1, 7); int type = DetermineType(Encoding.ASCII.GetString(magicBytes, 0, read)); fs.Seek(mark, SeekOrigin.Begin); - //if(fs.markSupported()) - // fs.reset(); return type; } @@ -153,23 +168,9 @@ namespace Claunia.PropertyList /// The root object in the property list. This is usually a NSDictionary but can also be a NSArray. public static NSObject Parse(FileInfo f) { - int type; - using (FileStream fis = f.OpenRead()) { - type = DetermineType(fis); - } - - switch (type) - { - case TYPE_BINARY: - return BinaryPropertyListParser.Parse(f); - case TYPE_XML: - return XmlPropertyListParser.Parse(f); - case TYPE_ASCII: - return ASCIIPropertyListParser.Parse(f); - default: - throw new PropertyListFormatException("The given file is not a property list of a supported format."); + return Parse(fis); } }