diff --git a/.travis.yml b/.travis.yml index 001a68e..a683991 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ mono: - alpha - beta - weekly + - 4.2.3 + - 4.0.5 - 3.10.0 - 3.8.0 - 3.2.8 diff --git a/README.md b/README.md index 51ab944..5309491 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ The provided API mimics the Cocoa/NeXTSTEP API, and where applicable, the .NET A | GNUstep ASCII | yes | yes | ###Requirements -.NET Framework 4.0 or Mono. +.NET Framework 4.0, Mono or .NET Core. ###Download diff --git a/plist-cil.test/ParseTest.cs b/plist-cil.test/ParseTest.cs index 3adfea7..ddbf860 100644 --- a/plist-cil.test/ParseTest.cs +++ b/plist-cil.test/ParseTest.cs @@ -112,7 +112,11 @@ namespace plistcil.test Assert.True(d.Count == 5); Assert.True(((NSString)d.ObjectForKey("keyA")).ToString().Equals("valueA")); Assert.True(((NSString)d.ObjectForKey("key&B")).ToString().Equals("value&B")); - Assert.True(((NSDate)d.ObjectForKey("date")).Date.Equals(new DateTime(2011, 11, 28, 9, 21, 30, DateTimeKind.Utc))); + + var actualDate = (NSDate)d.ObjectForKey("date"); + var expectedDate = new DateTime(2011, 11, 28, 9, 21, 30, DateTimeKind.Utc).ToLocalTime(); + + Assert.AreEqual(actualDate.Date, expectedDate); Assert.True(ArrayEquals(((NSData)d.ObjectForKey("data")).Bytes, new byte[]{ 0x00, 0x00, 0x00, 0x04, 0x10, 0x41, 0x08, 0x20, (byte)0x82 })); NSArray a = (NSArray)d.ObjectForKey("array"); @@ -182,7 +186,6 @@ namespace plistcil.test DateTime date = new DateTime(); string strg = "Hello World"; byte[] bytes = new byte[] { (byte)0x00, (byte)0xAF, (byte)0xAF }; - DirectoryInfo netObject = new DirectoryInfo(Environment.CurrentDirectory); Object[] array = new Object[] { bl, byt, shrt, i, lng, flt, dbl, date, strg, bytes }; int[] array2 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3000 }; List list = new List(array); @@ -249,8 +252,6 @@ namespace plistcil.test objArray = (Object[])WrappedO.ToObject(); Assert.True(objArray.Length == array.Length); - Assert.True(NSObject.Wrap((Object)netObject).GetType().Equals(typeof(NSData))); - WrappedO = NSObject.Wrap((Object)map); Assert.True(WrappedO.GetType().Equals(typeof(NSDictionary))); NSDictionary dict = (NSDictionary)WrappedO; diff --git a/plist-cil/ASCIIPropertyListParser.cs b/plist-cil/ASCIIPropertyListParser.cs index 9ce7abd..65f9c9e 100644 --- a/plist-cil/ASCIIPropertyListParser.cs +++ b/plist-cil/ASCIIPropertyListParser.cs @@ -79,7 +79,8 @@ namespace Claunia.PropertyList public static NSObject Parse(Stream fs) { byte[] buf = PropertyListParser.ReadAll(fs); - fs.Close(); + // Don't close the stream - that would be the responisibility of code that class + // Parse return Parse(buf); } @@ -718,11 +719,12 @@ namespace Claunia.PropertyList /// The escaped string according to the ASCII property list format, without leading and trailing quotation marks. /// If the en-/decoder for the UTF-8 or ASCII encoding could not be loaded /// If the string is encoded neither in ASCII nor in UTF-8 - [MethodImpl(MethodImplOptions.Synchronized)] public static string ParseQuotedString(string s) { List strBytes = new List(); - CharEnumerator c = s.GetEnumerator(); + + var characters = (IEnumerable)s.ToCharArray(); + var c = characters.GetEnumerator(); while (c.MoveNext()) { @@ -768,7 +770,7 @@ namespace Claunia.PropertyList /// The unescaped character as a string. /// The string character iterator pointing to the first character after the backslash /// If an invalid Unicode or ASCII escape sequence is found. - private static string ParseEscapedSequence(CharEnumerator iterator) + private static string ParseEscapedSequence(IEnumerator iterator) { iterator.MoveNext(); char c = iterator.Current; diff --git a/plist-cil/BinaryPropertyListParser.cs b/plist-cil/BinaryPropertyListParser.cs index 454d997..867bdcb 100644 --- a/plist-cil/BinaryPropertyListParser.cs +++ b/plist-cil/BinaryPropertyListParser.cs @@ -154,7 +154,8 @@ namespace Claunia.PropertyList { //Read all bytes into a list byte[] buf = PropertyListParser.ReadAll(fs); - fs.Close(); + // Don't close the stream - that would be the responisibility of code that class + // Parse return Parse(buf); } diff --git a/plist-cil/BinaryPropertyListWriter.cs b/plist-cil/BinaryPropertyListWriter.cs index 8f42e6d..e2f430e 100644 --- a/plist-cil/BinaryPropertyListWriter.cs +++ b/plist-cil/BinaryPropertyListWriter.cs @@ -117,9 +117,10 @@ namespace Claunia.PropertyList /// public static void Write(FileInfo file, NSObject root) { - FileStream fous = file.OpenWrite(); - Write(fous, root); - fous.Close(); + using (FileStream fous = file.OpenWrite()) + { + Write(fous, root); + } } /// diff --git a/plist-cil/NSData.cs b/plist-cil/NSData.cs index 12ea615..9a4020b 100644 --- a/plist-cil/NSData.cs +++ b/plist-cil/NSData.cs @@ -65,9 +65,10 @@ namespace Claunia.PropertyList public NSData(FileInfo file) { bytes = new byte[(int)file.Length]; - FileStream raf = file.OpenRead(); - raf.Read(bytes, 0, (int)file.Length); - raf.Close(); + using (FileStream raf = file.OpenRead()) + { + raf.Read(bytes, 0, (int)file.Length); + } } /// @@ -121,7 +122,7 @@ namespace Claunia.PropertyList /// The Base64 encoded data as a string. public string GetBase64EncodedData() { - return Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks); + return Convert.ToBase64String(bytes); } /// diff --git a/plist-cil/NSObject.cs b/plist-cil/NSObject.cs index ad216e1..515ad69 100644 --- a/plist-cil/NSObject.cs +++ b/plist-cil/NSObject.cs @@ -25,8 +25,8 @@ using System; using System.Text; using System.Collections.Generic; -using System.Runtime.Serialization.Formatters.Binary; using System.IO; +using System.Reflection; namespace Claunia.PropertyList { @@ -350,31 +350,8 @@ namespace Claunia.PropertyList } if (typeof(List).IsAssignableFrom(c)) return Wrap(((List)o).ToArray()); - return WrapSerialized(o); - } - /// - /// Serializes the given object using Java's default object serialization - /// and wraps the serialized object in a NSData object. - /// - /// The object to serialize and wrap. - /// A NSData object - /// When the object could not be serialized. - public static NSData WrapSerialized(Object o) - { - try - { - BinaryFormatter bf = new BinaryFormatter(); - using (MemoryStream ms = new MemoryStream()) - { - bf.Serialize(ms, o); - return new NSData(ms.ToArray()); - } - } - catch (IOException) - { - throw new SystemException("The given object of class " + o.GetType() + " could not be serialized and stored in a NSData object."); - } + throw new PropertyListException(string.Format("Cannot wrap an object of type {0}.", o.GetType().Name)); } /// diff --git a/plist-cil/NSString.cs b/plist-cil/NSString.cs index f2b7230..5e50103 100644 --- a/plist-cil/NSString.cs +++ b/plist-cil/NSString.cs @@ -163,7 +163,7 @@ namespace Claunia.PropertyList } catch (Exception ex) { - throw new SystemException("Could not encode the NSString into UTF-8: " + ex.Message); + throw new PropertyListException("Could not encode the NSString into UTF-8: " + ex.Message); } } diff --git a/plist-cil/PropertyListException.cs b/plist-cil/PropertyListException.cs new file mode 100644 index 0000000..75085d5 --- /dev/null +++ b/plist-cil/PropertyListException.cs @@ -0,0 +1,77 @@ +// plist-cil - An open source library to parse and generate property lists for .NET +// Copyright (C) 2015 Natalia Portillo +// Copyright (C) 2016 Quamotion +// +// This code is based on: +// plist - An open source library to parse and generate property lists +// Copyright (C) 2014 Daniel Dreibrodt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +using System; +using System.Runtime.Serialization; + +namespace Claunia.PropertyList +{ + /// + /// The exception that is thrown when an property list file could not be processed correctly. + /// + [Serializable] + public class PropertyListException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public PropertyListException() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// + public PropertyListException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// + /// + /// The exception that is the cause of the current exception, or + /// if no inner exception is specified. + /// + public PropertyListException(string message, Exception inner) + : base(message, inner) + { + } + +#if !NETCORE + protected PropertyListException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } +#endif + } +} diff --git a/plist-cil/PropertyListFormatException.cs b/plist-cil/PropertyListFormatException.cs index 3a8ff50..c7377d7 100644 --- a/plist-cil/PropertyListFormatException.cs +++ b/plist-cil/PropertyListFormatException.cs @@ -32,7 +32,7 @@ namespace Claunia.PropertyList /// /// @author Daniel Dreibrodt /// @author Natalia Portillo - public class PropertyListFormatException : Exception + public class PropertyListFormatException : PropertyListException { /// /// Creates a new exception with the given message. diff --git a/plist-cil/PropertyListParser.cs b/plist-cil/PropertyListParser.cs index a9e2c8b..93e6d62 100644 --- a/plist-cil/PropertyListParser.cs +++ b/plist-cil/PropertyListParser.cs @@ -158,9 +158,13 @@ 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) { - FileStream fis = f.OpenRead(); - int type = DetermineType(fis); - fis.Close(); + int type; + + using (FileStream fis = f.OpenRead()) + { + type = DetermineType(fis); + } + switch (type) { case TYPE_BINARY: @@ -215,9 +219,10 @@ namespace Claunia.PropertyList string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); - Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); - SaveAsXml(root, fous); - fous.Close(); + using (Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { + SaveAsXml(root, fous); + } } /// @@ -228,9 +233,18 @@ namespace Claunia.PropertyList /// When an error occurs during the writing process. public static void SaveAsXml(NSObject root, Stream outStream) { +#if NET40 + // The StreamWriter constructor which takes a "leaveOpen" parameter is + // not available on .NET 4.0 StreamWriter w = new StreamWriter(outStream, Encoding.UTF8); w.Write(root.ToXmlPropertyList()); w.Close(); +#else + using (StreamWriter w = new StreamWriter(outStream, Encoding.UTF8, bufferSize: 1024, leaveOpen: true)) + { + w.Write(root.ToXmlPropertyList()); + } +#endif } /// @@ -291,11 +305,11 @@ namespace Claunia.PropertyList string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); - Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); - StreamWriter w = new StreamWriter(fous, Encoding.ASCII); - w.Write(root.ToASCIIPropertyList()); - w.Close(); - fous.Close(); + using (Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) + using (StreamWriter w = new StreamWriter(fous, Encoding.ASCII)) + { + w.Write(root.ToASCIIPropertyList()); + } } /// @@ -309,11 +323,11 @@ namespace Claunia.PropertyList string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); - Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); - StreamWriter w = new StreamWriter(fous, Encoding.ASCII); - w.Write(root.ToASCIIPropertyList()); - w.Close(); - fous.Close(); + using (Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) + using (StreamWriter w = new StreamWriter(fous, Encoding.ASCII)) + { + w.Write(root.ToASCIIPropertyList()); + } } /// @@ -350,11 +364,11 @@ namespace Claunia.PropertyList string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); - Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); - StreamWriter w = new StreamWriter(fous, Encoding.ASCII); - w.Write(root.ToGnuStepASCIIPropertyList()); - w.Close(); - fous.Close(); + using (Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) + using (StreamWriter w = new StreamWriter(fous, Encoding.ASCII)) + { + w.Write(root.ToGnuStepASCIIPropertyList()); + } } /// @@ -368,11 +382,11 @@ namespace Claunia.PropertyList string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); - Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); - StreamWriter w = new StreamWriter(fous, Encoding.ASCII); - w.Write(root.ToGnuStepASCIIPropertyList()); - w.Close(); - fous.Close(); + using (Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) + using (StreamWriter w = new StreamWriter(fous, Encoding.ASCII)) + { + w.Write(root.ToGnuStepASCIIPropertyList()); + } } /// diff --git a/plist-cil/XmlPropertyListParser.cs b/plist-cil/XmlPropertyListParser.cs index 8ef077a..85f07b7 100644 --- a/plist-cil/XmlPropertyListParser.cs +++ b/plist-cil/XmlPropertyListParser.cs @@ -25,6 +25,7 @@ using System.Xml; using System.Collections.Generic; using System.IO; +using System.Linq; namespace Claunia.PropertyList { @@ -79,7 +80,10 @@ namespace Claunia.PropertyList /// The XML document. static NSObject ParseDocument(XmlDocument doc) { - XmlDocumentType docType = doc.DocumentType; + var docType = doc.ChildNodes + .OfType() + .SingleOrDefault(n => n.NodeType == XmlNodeType.DocumentType); + if (docType == null) { if (!doc.DocumentElement.Name.Equals("plist")) diff --git a/plist-cil/plist-cil.csproj b/plist-cil/plist-cil.csproj index d7faccb..16d5497 100644 --- a/plist-cil/plist-cil.csproj +++ b/plist-cil/plist-cil.csproj @@ -8,16 +8,19 @@ Claunia.PropertyList plist-cil 1.14 + v4.0 + true full false bin\Debug - DEBUG; + DEBUG;NET40 prompt 4 false + false true @@ -37,6 +40,8 @@ + false + NET40 true @@ -55,6 +60,7 @@ +