using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
namespace ImaginationOverflow.UniversalDeepLinking.Editor.External
{
///
/// Represents an Apple's plist document.
///
public class PlistDocument
{
///
/// The root element of the plist document.
///
public PlistElementDict root;
///
/// The version of the plist document. At the moment Apple uses '1.0' for all plist files.
///
public string version;
///
/// Creates a new plist document instance.
///
public PlistDocument()
{
this.root = new PlistElementDict();
this.version = "1.0";
}
internal static XDocument ParseXmlNoDtd(string text)
{
return XDocument.Load(XmlReader.Create((TextReader)new StringReader(text), new XmlReaderSettings()
{
ProhibitDtd = false,
XmlResolver = (XmlResolver)null
}));
}
internal static string CleanDtdToString(XDocument doc)
{
if (doc.DocumentType != null)
{
XDocument xdocument = new XDocument(new XDeclaration("1.0", "utf-8", (string)null), new object[2]
{
(object) new XDocumentType(doc.DocumentType.Name, doc.DocumentType.PublicId, doc.DocumentType.SystemId, (string) null),
(object) new XElement(doc.Root.Name)
});
return "" + (object)xdocument.Declaration + "\n" + (object)xdocument.DocumentType + "\n" + (object)doc.Root;
}
return "" + (object)new XDocument(new XDeclaration("1.0", "utf-8", (string)null), new object[1]
{
(object) new XElement(doc.Root.Name)
}).Declaration + Environment.NewLine + (object)doc.Root;
}
private static string GetText(XElement xml)
{
return string.Join("", xml.Nodes().OfType().Select((Func)(x => x.Value)).ToArray());
}
private static PlistElement ReadElement(XElement xml)
{
switch (xml.Name.LocalName)
{
case "dict":
List list1 = xml.Elements().ToList();
PlistElementDict plistElementDict = new PlistElementDict();
if (list1.Count % 2 == 1)
throw new Exception("Malformed plist file");
for (int index1 = 0; index1 < list1.Count - 1; ++index1)
{
if (list1[index1].Name != (XName)"key")
throw new Exception("Malformed plist file");
string index2 = PlistDocument.GetText(list1[index1]).Trim();
PlistElement plistElement = PlistDocument.ReadElement(list1[index1 + 1]);
if ((object)plistElement != null)
{
++index1;
plistElementDict[index2] = plistElement;
}
}
return (PlistElement)plistElementDict;
case "array":
List list2 = xml.Elements().ToList();
PlistElementArray plistElementArray = new PlistElementArray();
foreach (XElement xml1 in list2)
{
PlistElement plistElement = PlistDocument.ReadElement(xml1);
if ((object)plistElement != null)
plistElementArray.values.Add(plistElement);
}
return (PlistElement)plistElementArray;
case "string":
return (PlistElement)new PlistElementString(PlistDocument.GetText(xml));
case "integer":
int result;
if (int.TryParse(PlistDocument.GetText(xml), out result))
return (PlistElement)new PlistElementInteger(result);
return (PlistElement)null;
case "true":
return (PlistElement)new PlistElementBoolean(true);
case "false":
return (PlistElement)new PlistElementBoolean(false);
default:
return (PlistElement)null;
}
}
///
/// Reads the document from a file identified by the given path.
///
/// Path of the file.
public void ReadFromFile(string path)
{
this.ReadFromString(File.ReadAllText(path));
}
///
/// Reads the project from the given text reader.
///
/// The project contents.
public void ReadFromStream(TextReader tr)
{
this.ReadFromString(tr.ReadToEnd());
}
///
/// Reads the document from the given string.
///
/// The project contents.
public void ReadFromString(string text)
{
XDocument xmlNoDtd = PlistDocument.ParseXmlNoDtd(text);
this.version = (string)xmlNoDtd.Root.Attribute((XName)"version");
PlistElement plistElement = PlistDocument.ReadElement(xmlNoDtd.XPathSelectElement("plist/dict"));
if (plistElement == null)
throw new Exception("Error parsing plist file");
this.root = plistElement as PlistElementDict;
if (this.root == null)
throw new Exception("Malformed plist file");
}
private static XElement WriteElement(PlistElement el)
{
if (el is PlistElementBoolean)
return new XElement((XName)(!(el as PlistElementBoolean).value ? "false" : "true"));
if (el is PlistElementInteger)
return new XElement((XName)"integer", (object)(el as PlistElementInteger).value.ToString());
if (el is PlistElementString)
return new XElement((XName)"string", (object)(el as PlistElementString).value);
if (el is PlistElementDict)
{
PlistElementDict plistElementDict = el as PlistElementDict;
XElement xelement1 = new XElement((XName)"dict");
foreach (KeyValuePair keyValuePair in (IEnumerable>)plistElementDict.values)
{
XElement xelement2 = new XElement((XName)"key", (object)keyValuePair.Key);
XElement xelement3 = PlistDocument.WriteElement(keyValuePair.Value);
if (xelement3 != null)
{
xelement1.Add((object)xelement2);
xelement1.Add((object)xelement3);
}
}
return xelement1;
}
if (!(el is PlistElementArray))
return (XElement)null;
PlistElementArray plistElementArray = el as PlistElementArray;
XElement xelement4 = new XElement((XName)"array");
foreach (PlistElement el1 in plistElementArray.values)
{
XElement xelement1 = PlistDocument.WriteElement(el1);
if (xelement1 != null)
xelement4.Add((object)xelement1);
}
return xelement4;
}
///
/// Writes the project contents to the specified file.
///
/// Path to write the document contents to.
public void WriteToFile(string path)
{
File.WriteAllText(path, this.WriteToString());
}
///
/// Writes the document contents to the specified text writer.
///
/// Text writer to write to.
public void WriteToStream(TextWriter tw)
{
tw.Write(this.WriteToString());
}
///
/// Writes the document contents to a string.
///
///
/// The project contents converted to string.
///
public string WriteToString()
{
XElement xelement1 = PlistDocument.WriteElement((PlistElement)this.root);
XElement xelement2 = new XElement((XName)"plist");
xelement2.Add((object)new XAttribute((XName)"version", (object)this.version));
xelement2.Add((object)xelement1);
XDocument doc = new XDocument();
doc.Add((object)xelement2);
return PlistDocument.CleanDtdToString(doc);
}
}
}