static public string GetStringFromPList(string KeyName) { // Open the .plist and read out the specified key string PListAsString; if (!Utilities.GetSourcePList(out PListAsString)) { Program.Error("Failed to find source PList"); Program.ReturnCode = (int)ErrorCodes.Error_InfoPListNotFound; return("(unknown)"); } PListHelper Helper = new PListHelper(PListAsString); string Result; if (Helper.GetString(KeyName, out Result)) { return(Result); } else { Program.Error("Failed to find a value for {0} in PList", KeyName); Program.ReturnCode = (int)ErrorCodes.Error_KeyNotFoundInPList; return("(unknown)"); } }
/// <summary> /// Clones a dictionary from an existing .plist into a new one. Root should point to the dict key in the source plist. /// </summary> public static PListHelper CloneDictionaryRootedAt(XmlNode Root) { // Create a new empty dictionary PListHelper Result = new PListHelper(); // Copy all of the entries in the source dictionary into the new one XmlNode NewDictRoot = Result.Doc.DocumentElement.SelectSingleNode("/plist/dict"); foreach (XmlNode TheirChild in Root) { NewDictRoot.AppendChild(Result.Doc.ImportNode(TheirChild, true)); } return(Result); }
/// <summary> /// Extracts the dict values for the Entitlements key and creates a new full .plist file /// from them (with outer plist and dict keys as well as doctype, etc...) /// </summary> public string GetEntitlementsString(string CFBundleIdentifier) { PListHelper XCentPList = null; Data.ProcessValueForKey("Entitlements", "dict", delegate(XmlNode ValueNode) { XCentPList = PListHelper.CloneDictionaryRootedAt(ValueNode); }); // Modify the application-identifier to be fully qualified if needed string CurrentApplicationIdentifier; XCentPList.GetString("application-identifier", out CurrentApplicationIdentifier); if (CurrentApplicationIdentifier.Contains("*")) { // Replace the application identifier string NewApplicationIdentifier = String.Format("{0}.{1}", ApplicationIdentifierPrefix, CFBundleIdentifier); XCentPList.SetString("application-identifier", NewApplicationIdentifier); // Replace the keychain access groups // Note: This isn't robust, it ignores the existing value in the wildcard and uses the same value for // each entry. If there is a legitimate need for more than one entry in the access group list, then // don't use a wildcard! List <string> KeyGroups = XCentPList.GetArray("keychain-access-groups", "string"); for (int i = 0; i < KeyGroups.Count; ++i) { string Entry = KeyGroups[i]; if (Entry.Contains("*")) { Entry = NewApplicationIdentifier; } KeyGroups[i] = Entry; } XCentPList.SetValueForKey("keychain-access-groups", KeyGroups); } return(XCentPList.SaveToString()); }
static public string GetStringFromPList(string KeyName) { // Open the .plist and read out the specified key string PListAsString; if (!Utilities.GetSourcePList(out PListAsString)) { Program.Error("Failed to find source PList"); Program.ReturnCode = (int)ErrorCodes.Error_InfoPListNotFound; return "(unknown)"; } PListHelper Helper = new PListHelper(PListAsString); string Result; if (Helper.GetString(KeyName, out Result)) { return Result; } else { Program.Error("Failed to find a value for {0} in PList", KeyName); Program.ReturnCode = (int)ErrorCodes.Error_KeyNotFoundInPList; return "(unknown)"; } }
/// <summary> /// Clones a dictionary from an existing .plist into a new one. Root should point to the dict key in the source plist. /// </summary> public static PListHelper CloneDictionaryRootedAt(XmlNode Root) { // Create a new empty dictionary PListHelper Result = new PListHelper(); // Copy all of the entries in the source dictionary into the new one XmlNode NewDictRoot = Result.Doc.DocumentElement.SelectSingleNode("/plist/dict"); foreach (XmlNode TheirChild in Root) { NewDictRoot.AppendChild(Result.Doc.ImportNode(TheirChild, true)); } return Result; }
public XmlElement ConvertValueToPListFormat(object Value) { XmlElement ValueElement = null; if (Value is string) { ValueElement = Doc.CreateElement("string"); ValueElement.InnerText = Value as string; } else if (Value is Dictionary <string, object> ) { ValueElement = Doc.CreateElement("dict"); foreach (var KVP in Value as Dictionary <string, object> ) { AddKeyValuePair(ValueElement, KVP.Key, KVP.Value); } } else if (Value is PListHelper) { PListHelper PList = Value as PListHelper; ValueElement = Doc.CreateElement("dict"); XmlNode SourceDictionaryNode = PList.Doc.DocumentElement.SelectSingleNode("/plist/dict"); foreach (XmlNode TheirChild in SourceDictionaryNode) { ValueElement.AppendChild(Doc.ImportNode(TheirChild, true)); } } else if (Value is Array) { if (Value is byte[]) { ValueElement = Doc.CreateElement("data"); ValueElement.InnerText = Convert.ToBase64String(Value as byte[]); } else { ValueElement = Doc.CreateElement("array"); foreach (var A in Value as Array) { ValueElement.AppendChild(ConvertValueToPListFormat(A)); } } } else if (Value is IList) { ValueElement = Doc.CreateElement("array"); foreach (var A in Value as IList) { ValueElement.AppendChild(ConvertValueToPListFormat(A)); } } else if (Value is bool) { ValueElement = Doc.CreateElement(((bool)Value) ? "true" : "false"); } else if (Value is double) { ValueElement = Doc.CreateElement("real"); ValueElement.InnerText = ((double)Value).ToString(); } else if (Value is int) { ValueElement = Doc.CreateElement("integer"); ValueElement.InnerText = ((int)Value).ToString(); } else { throw new InvalidDataException(String.Format("Object '{0}' is in an unknown type that cannot be converted to PList format", Value)); } return(ValueElement); }
/// <summary> /// Constructs a MobileProvision from an xml blob extracted from the real ASN.1 file /// </summary> public MobileProvision(string EmbeddedPListText) { Data = new PListHelper(EmbeddedPListText); // Now extract things // Key: ApplicationIdentifierPrefix, Array<String> List <string> PrefixList = Data.GetArray("ApplicationIdentifierPrefix", "string"); if (PrefixList.Count > 1) { UnityEngine.Debug.LogWarning("Found more than one entry for ApplicationIdentifierPrefix in the .mobileprovision, using the first one found"); } if (PrefixList.Count > 0) { ApplicationIdentifierPrefix = PrefixList[0]; } // Key: DeveloperCertificates, Array<Data> (uuencoded) string CertificatePassword = ""; List <string> CertificateList = Data.GetArray("DeveloperCertificates", "data"); foreach (string EncodedCert in CertificateList) { byte[] RawCert = Convert.FromBase64String(EncodedCert); DeveloperCertificates.Add(new X509Certificate2(RawCert, CertificatePassword)); } // Key: Name, String if (!Data.GetString("Name", out ProvisionName)) { ProvisionName = "(unknown)"; } if (!Data.GetString("UUID", out ProvisionUUID)) { ProvisionUUID = "(unknown)"; } PListHelper XCentPList = null; Data.ProcessValueForKey("Entitlements", "dict", delegate(XmlNode ValueNode) { XCentPList = PListHelper.CloneDictionaryRootedAt(ValueNode); }); XCentPList.GetString("application-identifier", out ApplicationIdentifier); ApplicationIdentifier = ApplicationIdentifier.Replace(ApplicationIdentifierPrefix + ".", ""); XCentPList.GetString("aps-environment", out ApsEnvironment); if (string.IsNullOrEmpty(ApsEnvironment)) { UnityEngine.Debug.LogError(">>>>>>>>>>aps-environment is null"); } // Key: ProvisionedDevices, Array<String> ProvisionedDeviceIDs = Data.GetArray("ProvisionedDevices", "string"); string certificates = DeveloperCertificates[0].SubjectName.Decode(X500DistinguishedNameFlags.UseUTF8Encoding); ProvisionDeveloper = JenkinsBuild.GetParam(certificates.Split(','), "CN=", ""); string log = string.Empty; log += string.Format("ProvisionName={0}\n", ProvisionName); log += string.Format("from={0}, to={1}\n", DeveloperCertificates[0].NotBefore, DeveloperCertificates[0].NotAfter); log += string.Format("ProvisionUUID={0}\n", ProvisionUUID); log += string.Format("ProvisionDeveloper={0}\n", ProvisionDeveloper); log += string.Format("aps-environment={0}\n", ApsEnvironment); log += string.Format("certificates={0}\n", certificates); UnityEngine.Debug.Log(log); }