/// <summary> /// Export the certificate to a file /// </summary> static public void ExportCertificate() { if (Config.ProvisionFile == null) { Program.Error("Missing -ProvisionFile=... argument"); return; } if (Config.OutputCertificate == null) { Program.Error("Missing -OutputCertificate=... argument"); return; } // export the signing certificate to a file MobileProvision Provision = MobileProvisionParser.ParseFile(Config.ProvisionFile); X509Certificate2 Certificate = CodeSignatureBuilder.FindCertificate(Provision); if (Certificate == null) { Program.Error("Failed to find a valid certificate"); return; } byte[] Data = Certificate.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "A"); File.WriteAllBytes(Config.OutputCertificate, Data); }
/// <summary> /// Export the certificate to a file /// </summary> static public void ExportCertificate() { string ProvisionWithPrefix; if (!FindMobileProvision("", out ProvisionWithPrefix)) { Program.Error("Missing provision"); return; } if (Config.Certificate == null) { Program.Error("Missing -Certificate=... argument"); return; } // export the signing certificate to a file MobileProvision Provision = MobileProvisionParser.ParseFile(ProvisionWithPrefix); var Certificate = CodeSignatureBuilder.FindCertificate(Provision); byte[] Data = Certificate.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "A"); File.WriteAllBytes(Config.Certificate, Data); }
/// <summary> /// Copy the files always needed (even in a stub IPA) /// </summary> static public void CopyFilesNeededForMakeApp() { // Copy Info.plist over (modifiying it as needed) string SourcePListFilename = Utilities.GetPrecompileSourcePListFilename(); Utilities.PListHelper Info = Utilities.PListHelper.CreateFromFile(SourcePListFilename); // Edit the plist CookTime.UpdateVersion(Info); // Write out the <GameName>-Info.plist file to the xcode staging directory string TargetPListFilename = Path.Combine(Config.PCXcodeStagingDir, Program.GameName + "-Info.plist"); Directory.CreateDirectory(Path.GetDirectoryName(TargetPListFilename)); string OutString = Info.SaveToString(); OutString = OutString.Replace("${EXECUTABLE_NAME}", Program.GameName); OutString = OutString.Replace("${BUNDLE_IDENTIFIER}", Program.GameName.Replace("_", "")); // this is a temp way to inject the iphone 6 images without needing to upgrade everyone's plist // eventually we want to generate this based on what the user has set in the project settings string[] IPhoneConfigs = { "Default-IPhone6", "Landscape", "{375, 667}", "Default-IPhone6", "Portrait", "{375, 667}", "Default-IPhone6Plus-Landscape", "Landscape", "{414, 736}", "Default-IPhone6Plus-Portrait", "Portrait", "{414, 736}", "Default", "Landscape", "{320, 480}", "Default", "Portrait", "{320, 480}", "Default-568h", "Landscape", "{320, 568}", "Default-568h", "Portrait", "{320, 568}", "Default-IPhoneX-Landscape", "Landscape", "{375, 812}", "Default-IPhoneX-Portrait", "Portrait", "{375, 812}", }; StringBuilder NewLaunchImagesString = new StringBuilder("<key>UILaunchImages~iphone</key>\n\t\t<array>\n"); for (int ConfigIndex = 0; ConfigIndex < IPhoneConfigs.Length; ConfigIndex += 3) { NewLaunchImagesString.Append("\t\t\t<dict>\n"); NewLaunchImagesString.Append("\t\t\t\t<key>UILaunchImageMinimumOSVersion</key>\n"); NewLaunchImagesString.Append("\t\t\t\t<string>8.0</string>\n"); NewLaunchImagesString.Append("\t\t\t\t<key>UILaunchImageName</key>\n"); NewLaunchImagesString.AppendFormat("\t\t\t\t<string>{0}</string>\n", IPhoneConfigs[ConfigIndex + 0]); NewLaunchImagesString.Append("\t\t\t\t<key>UILaunchImageOrientation</key>\n"); NewLaunchImagesString.AppendFormat("\t\t\t\t<string>{0}</string>\n", IPhoneConfigs[ConfigIndex + 1]); NewLaunchImagesString.Append("\t\t\t\t<key>UILaunchImageSize</key>\n"); NewLaunchImagesString.AppendFormat("\t\t\t\t<string>{0}</string>\n", IPhoneConfigs[ConfigIndex + 2]); NewLaunchImagesString.Append("\t\t\t</dict>\n"); } // close it out NewLaunchImagesString.Append("\t\t\t</array>\n\t\t<key>UILaunchImages~ipad</key>"); OutString = OutString.Replace("<key>UILaunchImages~ipad</key>", NewLaunchImagesString.ToString()); byte[] RawInfoPList = Encoding.UTF8.GetBytes(OutString); File.WriteAllBytes(TargetPListFilename, RawInfoPList); Program.Log("Updating .plist: {0} --> {1}", SourcePListFilename, TargetPListFilename); // look for an entitlements file (optional) string SourceEntitlements = FileOperations.FindPrefixedFile(Config.BuildDirectory, Program.GameName + ".entitlements"); // set where to make the entitlements file ( string TargetEntitlements = Path.Combine(Config.PCXcodeStagingDir, Program.GameName + ".entitlements"); if (File.Exists(SourceEntitlements)) { FileOperations.CopyRequiredFile(SourceEntitlements, TargetEntitlements); } else { // we need to have something so Xcode will compile, so we just set the get-task-allow, since we know the value, // which is based on distribution or not (true means debuggable) File.WriteAllText(TargetEntitlements, string.Format("<plist><dict><key>get-task-allow</key><{0}/></dict></plist>", Config.bForDistribution ? "false" : "true")); } // Copy the mobile provision file over string CFBundleIdentifier = null; Info.GetString("CFBundleIdentifier", out CFBundleIdentifier); bool bNameMatch; string ProvisionWithPrefix = MobileProvision.FindCompatibleProvision(CFBundleIdentifier, out bNameMatch); if (!File.Exists(ProvisionWithPrefix)) { ProvisionWithPrefix = FileOperations.FindPrefixedFile(Config.BuildDirectory, Program.GameName + ".mobileprovision"); if (!File.Exists(ProvisionWithPrefix)) { ProvisionWithPrefix = FileOperations.FindPrefixedFile(Config.BuildDirectory + "/NotForLicensees/", Program.GameName + ".mobileprovision"); if (!File.Exists(ProvisionWithPrefix)) { ProvisionWithPrefix = FileOperations.FindPrefixedFile(Config.EngineBuildDirectory, "UE4Game.mobileprovision"); if (!File.Exists(ProvisionWithPrefix)) { ProvisionWithPrefix = FileOperations.FindPrefixedFile(Config.EngineBuildDirectory + "/NotForLicensees/", "UE4Game.mobileprovision"); } } } } string FinalMobileProvisionFilename = Path.Combine(Config.PCXcodeStagingDir, MacMobileProvisionFilename); FileOperations.CopyRequiredFile(ProvisionWithPrefix, FinalMobileProvisionFilename); // make sure this .mobileprovision file is newer than any other .mobileprovision file on the Mac (this file gets multiple games named the same file, // so the time stamp checking can fail when moving between games, a la the buildmachines!) File.SetLastWriteTime(FinalMobileProvisionFilename, DateTime.UtcNow); string ProjectFile = Config.RootRelativePath + @"Engine\Intermediate\ProjectFiles\UE4.xcodeproj\project.pbxproj"; if (Program.GameName != "UE4Game") { ProjectFile = Path.GetDirectoryName(Config.IntermediateDirectory) + @"\ProjectFiles\" + Program.GameName + @".xcodeproj\project.pbxproj"; } FileOperations.CopyRequiredFile(ProjectFile, Path.Combine(Config.PCXcodeStagingDir, @"project.pbxproj.datecheck")); // copy the signing certificate over // export the signing certificate to a file MobileProvision Provision = MobileProvisionParser.ParseFile(ProvisionWithPrefix); var Certificate = CodeSignatureBuilder.FindCertificate(Provision); byte[] Data = Certificate.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "A"); File.WriteAllBytes(Path.Combine(Config.PCXcodeStagingDir, MacSigningIdentityFilename), Data); Config.CodeSigningIdentity = Certificate.FriendlyName; // since the pipeline will use a temporary keychain that will contain only this certificate, this should be the only identity that will work CurrentBaseXCodeCommandLine = GetBaseXcodeCommandline(); // get the UUID string AllText = File.ReadAllText(FinalMobileProvisionFilename); string UUID = ""; int idx = AllText.IndexOf("<key>UUID</key>"); if (idx > 0) { idx = AllText.IndexOf("<string>", idx); if (idx > 0) { idx += "<string>".Length; UUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx); } } CurrentBaseXCodeCommandLine += String.Format(" PROVISIONING_PROFILE=" + UUID); // needs Mac line endings so it can be executed string SrcPath = @"..\..\..\Build\" + Config.OSString + @"\XcodeSupportFiles\prepackage.sh"; string DestPath = Path.Combine(Config.PCXcodeStagingDir, @"prepackage.sh"); Program.Log(" ... '" + SrcPath + "' -> '" + DestPath + "'"); string SHContents = File.ReadAllText(SrcPath); SHContents = SHContents.Replace("\r\n", "\n"); File.WriteAllText(DestPath, SHContents); CookTime.CopySignedFiles(); }
public static string FindCompatibleProvision(string CFBundleIdentifier, out bool bNameMatch, bool bCheckCert = true, bool bCheckIdentifier = true, bool bCheckDistro = true) { bNameMatch = false; // remap the gamename if necessary string GameName = Program.GameName; if (GameName == "UE4Game") { if (Config.ProjectFile.Length > 0) { GameName = Path.GetFileNameWithoutExtension(Config.ProjectFile); } } // ensure the provision directory exists if (!Directory.Exists(Config.ProvisionDirectory)) { Directory.CreateDirectory(Config.ProvisionDirectory); } if (Config.bProvision) { if (File.Exists(Config.ProvisionDirectory + "/" + Config.Provision)) { return(Config.ProvisionDirectory + "/" + Config.Provision); } } #region remove after we provide an install mechanism CacheMobileProvisions(); #endregion // cache the provision library Dictionary <string, MobileProvision> ProvisionLibrary = new Dictionary <string, MobileProvision>(); foreach (string Provision in Directory.EnumerateFiles(Config.ProvisionDirectory, "*.mobileprovision")) { MobileProvision p = MobileProvisionParser.ParseFile(Provision); ProvisionLibrary.Add(Provision, p); if (p.FileName.Contains(p.UUID) && !File.Exists(Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision"))) { File.Copy(Provision, Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision")); p = MobileProvisionParser.ParseFile(Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision")); ProvisionLibrary.Add(Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision"), p); } } Program.Log("Searching for mobile provisions that match the game '{0}' (distribution: {3}) with CFBundleIdentifier='{1}' in '{2}'", GameName, CFBundleIdentifier, Config.ProvisionDirectory, Config.bForDistribution); // check the cache for a provision matching the app id (com.company.Game) // First checking for a contains match and then for a wildcard match for (int Phase = -1; Phase < 3; ++Phase) { if (Phase == -1 && string.IsNullOrEmpty(Config.ProvisionUUID)) { continue; } foreach (KeyValuePair <string, MobileProvision> Pair in ProvisionLibrary) { string DebugName = Path.GetFileName(Pair.Key); MobileProvision TestProvision = Pair.Value; // make sure the file is not managed by Xcode if (Path.GetFileName(TestProvision.FileName).ToLower().Equals(TestProvision.UUID.ToLower() + ".mobileprovision")) { continue; } Program.LogVerbose(" Phase {0} considering provision '{1}' named '{2}'", Phase, DebugName, TestProvision.ProvisionName); if (TestProvision.ProvisionName == "iOS Team Provisioning Profile: " + CFBundleIdentifier) { Program.LogVerbose(" Failing as provisioning is automatic"); continue; } // check to see if the platform is the same as what we are looking for if (!string.IsNullOrEmpty(TestProvision.Platform) && TestProvision.Platform != Config.OSString && !string.IsNullOrEmpty(Config.OSString)) { //Program.LogVerbose(" Failing platform {0} Config: {1}", TestProvision.Platform, Config.OSString); continue; } // Validate the name bool bPassesNameCheck = false; if (Phase == -1) { bPassesNameCheck = TestProvision.UUID == Config.ProvisionUUID; bNameMatch = bPassesNameCheck; } else if (Phase == 0) { bPassesNameCheck = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1) == CFBundleIdentifier; bNameMatch = bPassesNameCheck; } else if (Phase == 1) { if (TestProvision.ApplicationIdentifier.Contains("*")) { string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1); if (CompanyName != "*") { CompanyName = CompanyName.Substring(0, CompanyName.LastIndexOf(".")); bPassesNameCheck = CFBundleIdentifier.StartsWith(CompanyName); } } } else { if (TestProvision.ApplicationIdentifier.Contains("*")) { string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1); bPassesNameCheck = CompanyName == "*"; } } if (!bPassesNameCheck && bCheckIdentifier) { Program.LogVerbose(" .. Failed phase {0} name check (provision app ID was {1})", Phase, TestProvision.ApplicationIdentifier); continue; } if (Config.bForDistribution) { // Check to see if this is a distribution provision. get-task-allow must be false for distro profiles. // TestProvision.ProvisionedDeviceIDs.Count==0 is not a valid check as ad-hoc distro profiles do list devices. bool bDistroProv = !TestProvision.bDebug; if (!bDistroProv) { Program.LogVerbose(" .. Failed distribution check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count); continue; } } else { if (bCheckDistro) { bool bPassesDebugCheck = TestProvision.bDebug; if (!bPassesDebugCheck) { Program.LogVerbose(" .. Failed debugging check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count); continue; } } else { if (!TestProvision.bDebug) { Config.bForceStripSymbols = true; } } } // Check to see if the provision is in date DateTime CurrentUTCTime = DateTime.UtcNow; bool bPassesDateCheck = (CurrentUTCTime >= TestProvision.CreationDate) && (CurrentUTCTime < TestProvision.ExpirationDate); if (!bPassesDateCheck) { Program.LogVerbose(" .. Failed time period check (valid from {0} to {1}, but UTC time is now {2})", TestProvision.CreationDate, TestProvision.ExpirationDate, CurrentUTCTime); continue; } // check to see if we have a certificate for this provision bool bPassesHasMatchingCertCheck = false; if (bCheckCert) { X509Certificate2 Cert = CodeSignatureBuilder.FindCertificate(TestProvision); bPassesHasMatchingCertCheck = (Cert != null); if (bPassesHasMatchingCertCheck && Config.bCert) { bPassesHasMatchingCertCheck &= (CryptoAdapter.GetFriendlyNameFromCert(Cert) == Config.Certificate); } } else { bPassesHasMatchingCertCheck = true; } if (!bPassesHasMatchingCertCheck) { Program.LogVerbose(" .. Failed to find a matching certificate that was in date"); continue; } // Made it past all the tests Program.LogVerbose(" Picked '{0}' with AppID '{1}' and Name '{2}' as a matching provision for the game '{3}'", DebugName, TestProvision.ApplicationIdentifier, TestProvision.ProvisionName, GameName); return(Pair.Key); } } // check to see if there is already an embedded provision string EmbeddedMobileProvisionFilename = Path.Combine(Config.RepackageStagingDirectory, "embedded.mobileprovision"); Program.Warning("Failed to find a valid matching mobile provision, will attempt to use the embedded mobile provision instead if present"); return(EmbeddedMobileProvisionFilename); }
public static string FindCompatibleProvision(string CFBundleIdentifier, out bool bNameMatch, bool bCheckCert = true, bool bCheckIdentifier = true) { bNameMatch = false; // remap the gamename if necessary string GameName = Program.GameName; if (GameName == "UE4Game") { if (Config.ProjectFile.Length > 0) { GameName = Path.GetFileNameWithoutExtension(Config.ProjectFile); } } // ensure the provision directory exists if (!Directory.Exists(Config.ProvisionDirectory)) { Directory.CreateDirectory(Config.ProvisionDirectory); } if (Config.bProvision) { if (File.Exists(Config.ProvisionDirectory + "/" + Config.Provision)) { return(Config.ProvisionDirectory + "/" + Config.Provision); } } #region remove after we provide an install mechanism // copy all of the provisions from the game directory to the library if (!String.IsNullOrEmpty(Config.ProjectFile)) { var ProjectFileBuildIOSPath = Path.GetDirectoryName(Config.ProjectFile) + "/Build/IOS/"; if (Directory.Exists(ProjectFileBuildIOSPath)) { foreach (string Provision in Directory.EnumerateFiles(ProjectFileBuildIOSPath, "*.mobileprovision", SearchOption.AllDirectories)) { if (!File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision)) || File.GetLastWriteTime(Config.ProvisionDirectory + Path.GetFileName(Provision)) < File.GetLastWriteTime(Provision)) { FileInfo DestFileInfo; if (File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision))) { DestFileInfo = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision)); DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly; } File.Copy(Provision, Config.ProvisionDirectory + Path.GetFileName(Provision), true); DestFileInfo = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision)); DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly; } } } } // copy all of the provisions from the engine directory to the library { if (Directory.Exists(Config.EngineBuildDirectory)) { foreach (string Provision in Directory.EnumerateFiles(Config.EngineBuildDirectory, "*.mobileprovision", SearchOption.AllDirectories)) { if (!File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision)) || File.GetLastWriteTime(Config.ProvisionDirectory + Path.GetFileName(Provision)) < File.GetLastWriteTime(Provision)) { FileInfo DestFileInfo; if (File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision))) { DestFileInfo = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision)); DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly; } File.Copy(Provision, Config.ProvisionDirectory + Path.GetFileName(Provision), true); DestFileInfo = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision)); DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly; } } } } #endregion // cache the provision library Dictionary <string, MobileProvision> ProvisionLibrary = new Dictionary <string, MobileProvision>(); foreach (string Provision in Directory.EnumerateFiles(Config.ProvisionDirectory, "*.mobileprovision")) { MobileProvision p = MobileProvisionParser.ParseFile(Provision); ProvisionLibrary.Add(Provision, p); } Program.Log("Searching for mobile provisions that match the game '{0}' with CFBundleIdentifier='{1}' in '{2}'", GameName, CFBundleIdentifier, Config.ProvisionDirectory); // check the cache for a provision matching the app id (com.company.Game) // First checking for a contains match and then for a wildcard match for (int Phase = 0; Phase < 3; ++Phase) { foreach (KeyValuePair <string, MobileProvision> Pair in ProvisionLibrary) { string DebugName = Path.GetFileName(Pair.Key); MobileProvision TestProvision = Pair.Value; Program.LogVerbose(" Phase {0} considering provision '{1}' named '{2}'", Phase, DebugName, TestProvision.ProvisionName); // Validate the name bool bPassesNameCheck = false; if (Phase == 0) { bPassesNameCheck = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1) == CFBundleIdentifier; bNameMatch = bPassesNameCheck; } else if (Phase == 1) { if (TestProvision.ApplicationIdentifier.Contains("*")) { string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1); if (CompanyName != "*") { CompanyName = CompanyName.Substring(0, CompanyName.LastIndexOf(".")); bPassesNameCheck = CFBundleIdentifier.StartsWith(CompanyName); } } } else { if (TestProvision.ApplicationIdentifier.Contains("*")) { string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1); bPassesNameCheck = CompanyName == "*"; } } if (!bPassesNameCheck && bCheckIdentifier) { Program.LogVerbose(" .. Failed phase {0} name check (provision app ID was {1})", Phase, TestProvision.ApplicationIdentifier); continue; } if (Config.bForDistribution) { // check to see if this is a distribution provision bool bDistroProv = (TestProvision.ProvisionedDeviceIDs.Count == 0) && !TestProvision.bDebug; if (!bDistroProv) { Program.LogVerbose(" .. Failed distribution check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count); continue; } } else { // check to see if we pass the debug check for non-distribution bool bPassesDebugCheck = TestProvision.bDebug; if (!bPassesDebugCheck) { Program.LogVerbose(" .. Failed debugging check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count); continue; } } // Check to see if the provision is in date DateTime CurrentUTCTime = DateTime.UtcNow; bool bPassesDateCheck = (CurrentUTCTime >= TestProvision.CreationDate) && (CurrentUTCTime < TestProvision.ExpirationDate); if (!bPassesDateCheck) { Program.LogVerbose(" .. Failed time period check (valid from {0} to {1}, but UTC time is now {2})", TestProvision.CreationDate, TestProvision.ExpirationDate, CurrentUTCTime); continue; } // check to see if we have a certificate for this provision bool bPassesHasMatchingCertCheck = false; if (bCheckCert) { X509Certificate2 Cert = CodeSignatureBuilder.FindCertificate(TestProvision); bPassesHasMatchingCertCheck = (Cert != null); if (bPassesHasMatchingCertCheck && Config.bCert) { bPassesHasMatchingCertCheck &= (Cert.FriendlyName == Config.Certificate); } } else { bPassesHasMatchingCertCheck = true; } if (!bPassesHasMatchingCertCheck) { Program.LogVerbose(" .. Failed to find a matching certificate that was in date"); continue; } // Made it past all the tests Program.LogVerbose(" Picked '{0}' with AppID '{1}' and Name '{2}' as a matching provision for the game '{3}'", DebugName, TestProvision.ApplicationIdentifier, TestProvision.ProvisionName, GameName); return(Pair.Key); } } // check to see if there is already an embedded provision string EmbeddedMobileProvisionFilename = Path.Combine(Config.RepackageStagingDirectory, "embedded.mobileprovision"); Program.Warning("Failed to find a valid matching mobile provision, will attempt to use the embedded mobile provision instead if present"); return(EmbeddedMobileProvisionFilename); }
/// <summary> /// Makes sure the required files for code signing exist and can be found /// </summary> public static bool FindRequiredFiles(out MobileProvision Provision, out X509Certificate2 Cert, out bool bHasOverridesFile, out bool bNameMatch, bool bNameCheck = true) { Provision = null; Cert = null; bHasOverridesFile = File.Exists(Config.GetPlistOverrideFilename()); bNameMatch = false; string CFBundleIdentifier = Config.OverrideBundleName; if (string.IsNullOrEmpty(CFBundleIdentifier)) { // Load Info.plist, which guides nearly everything else string plistFile = Config.EngineBuildDirectory + "/UE4Game-Info.plist"; if (!string.IsNullOrEmpty(Config.ProjectFile)) { plistFile = Path.GetDirectoryName(Config.ProjectFile) + "/Intermediate/IOS/" + Path.GetFileNameWithoutExtension(Config.ProjectFile) + "-Info.plist"; if (!File.Exists(plistFile)) { plistFile = Config.IntermediateDirectory + "/UE4Game-Info.plist"; if (!File.Exists(plistFile)) { plistFile = Config.EngineBuildDirectory + "/UE4Game-Info.plist"; } } } Utilities.PListHelper Info = null; try { string RawInfoPList = File.ReadAllText(plistFile, Encoding.UTF8); Info = new Utilities.PListHelper(RawInfoPList);; } catch (Exception ex) { Console.WriteLine(ex.Message); } if (Info == null) { return(false); } // Get the name of the bundle Info.GetString("CFBundleIdentifier", out CFBundleIdentifier); if (CFBundleIdentifier == null) { return(false); } else { CFBundleIdentifier = CFBundleIdentifier.Replace("${BUNDLE_IDENTIFIER}", Path.GetFileNameWithoutExtension(Config.ProjectFile)); } } // Check for a mobile provision try { string MobileProvisionFilename = MobileProvision.FindCompatibleProvision(CFBundleIdentifier, out bNameMatch); Provision = MobileProvisionParser.ParseFile(MobileProvisionFilename); } catch (Exception) { } // if we have a null provision see if we can find a compatible provision without checking for a certificate if (Provision == null) { try { string MobileProvisionFilename = MobileProvision.FindCompatibleProvision(CFBundleIdentifier, out bNameMatch, false); Provision = MobileProvisionParser.ParseFile(MobileProvisionFilename); } catch (Exception) { } // if we have a null provision see if we can find a valid provision without checking for name match if (Provision == null && !bNameCheck) { try { string MobileProvisionFilename = MobileProvision.FindCompatibleProvision(CFBundleIdentifier, out bNameMatch, false, false); Provision = MobileProvisionParser.ParseFile(MobileProvisionFilename); } catch (Exception) { } } } // Check for a suitable signature to match the mobile provision if (Provision != null) { Cert = CodeSignatureBuilder.FindCertificate(Provision); } return(true); }