예제 #1
0
        private void ResignButton_Click(object sender, EventArgs e)
        {
            saveFileDialog1.DefaultExt = "ipa";
            saveFileDialog1.FileName   = "";
            saveFileDialog1.Filter     = ToolsHub.IpaFilter;
            saveFileDialog1.Title      = "Choose a filename for the re-signed IPA";

            string CWD = Directory.GetCurrentDirectory();
            bool   bDialogSucceeded = (saveFileDialog1.ShowDialog() == DialogResult.OK);

            Directory.SetCurrentDirectory(CWD);

            if (bDialogSucceeded)
            {
                bool bSavedVerbose = Config.bVerbose;
                Config.bVerbose = true;
                Program.ProgressDialog.OnBeginBackgroundWork = delegate
                {
                    string SrcFilename  = IPAFilenameEdit.Text;
                    string DestFilename = saveFileDialog1.FileName;

                    // Delete the target location and copy the source there
                    FileOperations.DeleteFile(DestFilename);
                    FileOperations.CopyRequiredFile(SrcFilename, DestFilename);

                    // Open the file
                    FileOperations.ZipFileSystem FileSystem = new FileOperations.ZipFileSystem(DestFilename);
                    FileSystem.SetCompression(CBCompressModifiedFiles.Checked ? Ionic.Zlib.CompressionLevel.BestCompression : Ionic.Zlib.CompressionLevel.None);

                    // Resign and save the file
                    ResignIPA(FileSystem);
                    FileSystem.Close();
                };
                Config.bVerbose = bSavedVerbose;

                Program.ProgressDialog.ShowDialog();
            }
        }
예제 #2
0
        /**
         * Using the stub IPA previously compiled on the Mac, create a new IPA with assets
         */
        static public void RepackageIPAFromStub()
        {
            if (string.IsNullOrEmpty(Config.RepackageStagingDirectory) || !Directory.Exists(Config.RepackageStagingDirectory))
            {
                Program.Error("Directory specified with -stagedir could not be found!");
                return;
            }


            DateTime             StartTime  = DateTime.Now;
            CodeSignatureBuilder CodeSigner = null;

            // Clean the staging directory
            Program.ExecuteCommand("Clean", null);

            // Create a copy of the IPA so as to not trash the original
            ZipFile Zip = SetupWorkIPA();

            if (Zip == null)
            {
                return;
            }

            string ZipWorkingDir = String.Format("Payload/{0}{1}.app/", Program.GameName, Program.Architecture);

            FileOperations.ZipFileSystem FileSystem = new FileOperations.ZipFileSystem(Zip, ZipWorkingDir);

            // Check for a staged plist that needs to be merged into the main one
            {
                // Determine if there is a staged one we should try to use instead
                string PossiblePList = Path.Combine(Config.RepackageStagingDirectory, "Info.plist");
                if (File.Exists(PossiblePList))
                {
                    if (Config.bPerformResignWhenRepackaging)
                    {
                        Program.Log("Found Info.plist ({0}) in stage, which will be merged in with stub plist contents", PossiblePList);

                        // Merge the two plists, using the staged one as the authority when they conflict
                        byte[] StagePListBytes = File.ReadAllBytes(PossiblePList);
                        string StageInfoString = Encoding.UTF8.GetString(StagePListBytes);

                        byte[] StubPListBytes          = FileSystem.ReadAllBytes("Info.plist");
                        Utilities.PListHelper StubInfo = new Utilities.PListHelper(Encoding.UTF8.GetString(StubPListBytes));

                        StubInfo.MergePlistIn(StageInfoString);

                        // Write it back to the cloned stub, where it will be used for all subsequent actions
                        byte[] MergedPListBytes = Encoding.UTF8.GetBytes(StubInfo.SaveToString());
                        FileSystem.WriteAllBytes("Info.plist", MergedPListBytes);
                    }
                    else
                    {
                        Program.Warning("Found Info.plist ({0}) in stage that will be ignored; IPP cannot combine it with the stub plist since -sign was not specified", PossiblePList);
                    }
                }
            }

            // Get the name of the executable file
            string CFBundleExecutable;

            {
                // Load the .plist from the stub
                byte[] RawInfoPList = FileSystem.ReadAllBytes("Info.plist");

                Utilities.PListHelper Info = new Utilities.PListHelper(Encoding.UTF8.GetString(RawInfoPList));

                // Get the name of the executable file
                if (!Info.GetString("CFBundleExecutable", out CFBundleExecutable))
                {
                    throw new InvalidDataException("Info.plist must contain the key CFBundleExecutable");
                }
            }

            // Tell the file system about the executable file name so that we can set correct attributes on
            // the file when zipping it up
            FileSystem.ExecutableFileName = CFBundleExecutable;

            // Prepare for signing if requested
            if (Config.bPerformResignWhenRepackaging)
            {
                // Start the resign process (load the mobileprovision and info.plist, find the cert, etc...)
                CodeSigner            = new CodeSignatureBuilder();
                CodeSigner.FileSystem = FileSystem;

                CodeSigner.PrepareForSigning();

                // Merge in any user overrides that exist
                UpdateVersion(CodeSigner.Info);
            }

            // Empty the current staging directory
            FileOperations.DeleteDirectory(new DirectoryInfo(Config.PCStagingRootDir));

            // we will zip files in the pre-staged payload dir
            string ZipSourceDir = Config.RepackageStagingDirectory;

            // Save the zip
            Program.Log("Saving IPA ...");

            FilesBeingModifiedToPrintOut.Clear();
            Zip.SaveProgress += UpdateSaveProgress;

            Zip.CompressionLevel = (Ionic.Zlib.CompressionLevel)Config.RecompressionSetting;

            // Add all of the payload files, replacing existing files in the stub IPA if necessary (should only occur for icons)
            {
                string   SourceDir    = Path.GetFullPath(ZipSourceDir);
                string[] PayloadFiles = Directory.GetFiles(SourceDir, "*.*", SearchOption.AllDirectories);
                foreach (string Filename in PayloadFiles)
                {
                    // Get the relative path to the file (this implementation only works because we know the files are all
                    // deeper than the base dir, since they were generated from a search)
                    string AbsoluteFilename = Path.GetFullPath(Filename);
                    string RelativeFilename = AbsoluteFilename.Substring(SourceDir.Length + 1).Replace('\\', '/');

                    string ZipAbsolutePath = String.Format("Payload/{0}{1}.app/{1}",
                                                           Program.GameName,
                                                           Program.Architecture,
                                                           RelativeFilename);

                    byte[] FileContents = File.ReadAllBytes(AbsoluteFilename);
                    if (FileContents.Length == 0)
                    {
                        // Zero-length files added by Ionic cause installation/upgrade to fail on device with error 0xE8000050
                        // We store a single byte in the files as a workaround for now
                        FileContents    = new byte[1];
                        FileContents[0] = 0;
                    }

                    FileSystem.WriteAllBytes(RelativeFilename, FileContents);

                    if ((FileContents.Length >= 1024 * 1024) || (Config.bVerbose))
                    {
                        FilesBeingModifiedToPrintOut.Add(ZipAbsolutePath);
                    }
                }
            }

            // Re-sign the executable if there is a signing context
            if (CodeSigner != null)
            {
                if (Config.OverrideBundleName != null)
                {
                    CodeSigner.Info.SetString("CFBundleDisplayName", Config.OverrideBundleName);
                    string CFBundleIdentifier;
                    if (CodeSigner.Info.GetString("CFBundleIdentifier", out CFBundleIdentifier))
                    {
                        CodeSigner.Info.SetString("CFBundleIdentifier", CFBundleIdentifier + "_" + Config.OverrideBundleName);
                    }
                }
                CodeSigner.PerformSigning();
            }

            // Stick in the iTunesArtwork PNG if available
            string iTunesArtworkPath = Path.Combine(Config.BuildDirectory, "iTunesArtwork");

            if (File.Exists(iTunesArtworkPath))
            {
                Zip.UpdateFile(iTunesArtworkPath, "");
            }

            // Save the Zip

            Program.Log("Compressing files into IPA (-compress={1}).{0}", Config.bVerbose ? "" : "  Only large files will be listed next, but other files are also being packaged.", Config.RecompressionSetting);
            FileSystem.Close();

            TimeSpan ZipLength = DateTime.Now - StartTime;

            FileInfo FinalZipInfo = new FileInfo(Zip.Name);


            Program.Log(String.Format("Finished repackaging into {2:0.00} MB IPA, written to '{0}' (took {1:0.00} s for all steps)",
                                      Zip.Name,
                                      ZipLength.TotalSeconds,
                                      FinalZipInfo.Length / (1024.0f * 1024.0f)));
        }
예제 #3
0
        public static bool ExecuteDeployCommand(string Command, string GamePath, string RPCCommand)
        {
            switch (Command.ToLowerInvariant())
            {
            case "backup":
            {
                string ApplicationIdentifier = RPCCommand;
                if (ApplicationIdentifier == null)
                {
                    ApplicationIdentifier = Utilities.GetStringFromPList("CFBundleIdentifier");
                }

                if (Config.FilesForBackup.Count > 0)
                {
                    if (!DeploymentHelper.Get().BackupFiles(ApplicationIdentifier, Config.FilesForBackup.ToArray()))
                    {
                        Program.Error("Failed to transfer manifest file from device to PC");
                        Program.ReturnCode = (int)ErrorCodes.Error_DeviceBackupFailed;
                    }
                }
                else if (!DeploymentHelper.Get().BackupDocumentsDirectory(ApplicationIdentifier, Config.GetRootBackedUpDocumentsDirectory()))
                {
                    Program.Error("Failed to transfer documents directory from device to PC");
                    Program.ReturnCode = (int)ErrorCodes.Error_DeviceBackupFailed;
                }
            }
            break;

            case "uninstall":
            {
                string ApplicationIdentifier = RPCCommand;
                if (ApplicationIdentifier == null)
                {
                    ApplicationIdentifier = Utilities.GetStringFromPList("CFBundleIdentifier");
                }

                if (!DeploymentHelper.Get().UninstallIPAOnDevice(ApplicationIdentifier))
                {
                    Program.Error("Failed to uninstall IPA on device");
                    Program.ReturnCode = (int)ErrorCodes.Error_AppUninstallFailed;
                }
            }
            break;

            case "deploy":
            case "install":
            {
                string IPAPath = GamePath;
                string AdditionalCommandline = Program.AdditionalCommandline;

                if (!String.IsNullOrEmpty(AdditionalCommandline) && !Config.bIterate)
                {
                    // Read the mobile provision to check for issues
                    FileOperations.ReadOnlyZipFileSystem Zip = new FileOperations.ReadOnlyZipFileSystem(IPAPath);
                    try
                    {
                        // Compare the commandline embedded to prevent us from any unnecessary writing.
                        byte[] CommandlineBytes    = Zip.ReadAllBytes("ue4commandline.txt");
                        string ExistingCommandline = Encoding.UTF8.GetString(CommandlineBytes, 0, CommandlineBytes.Length);
                        if (ExistingCommandline != AdditionalCommandline)
                        {
                            // Ensure we have a temp dir to stage our temporary ipa
                            if (!Directory.Exists(Config.PCStagingRootDir))
                            {
                                Directory.CreateDirectory(Config.PCStagingRootDir);
                            }

                            string TmpFilePath = Path.Combine(Path.GetDirectoryName(Config.PCStagingRootDir), Path.GetFileNameWithoutExtension(IPAPath) + ".tmp.ipa");
                            if (File.Exists(TmpFilePath))
                            {
                                File.Delete(TmpFilePath);
                            }

                            File.Copy(IPAPath, TmpFilePath);

                            // Get the project name:
                            string ProjectFile = ExistingCommandline.Split(' ').FirstOrDefault();

                            // Write out the new commandline.
                            FileOperations.ZipFileSystem WritableZip = new FileOperations.ZipFileSystem(TmpFilePath);
                            byte[] NewCommandline = Encoding.UTF8.GetBytes(ProjectFile + " " + AdditionalCommandline);
                            WritableZip.WriteAllBytes("ue4commandline.txt", NewCommandline);

                            // We need to residn the application after the commandline file has changed.
                            CodeSignatureBuilder CodeSigner = new CodeSignatureBuilder();
                            CodeSigner.FileSystem = WritableZip;

                            CodeSigner.PrepareForSigning();
                            CodeSigner.PerformSigning();

                            WritableZip.Close();

                            // Set the deploying ipa path to our new ipa
                            IPAPath = TmpFilePath;
                        }
                    }
                    catch (System.Exception ex)
                    {
                        Program.Warning(String.Format("Failed to override the commandline.txt file: ({0})", ex.Message));
                    }
                    Zip.Close();
                }

                if (Config.bIterate)
                {
                    string ApplicationIdentifier = RPCCommand;
                    if (String.IsNullOrEmpty(ApplicationIdentifier))
                    {
                        ApplicationIdentifier = Utilities.GetStringFromPList("CFBundleIdentifier");
                    }

                    DeploymentHelper.Get().DeviceId = Config.DeviceId;
                    if (!DeploymentHelper.Get().InstallFilesOnDevice(ApplicationIdentifier, Config.DeltaManifest))
                    {
                        Program.Error("Failed to install Files on device");
                        Program.ReturnCode = (int)ErrorCodes.Error_FilesInstallFailed;
                    }
                }
                else if (File.Exists(IPAPath))
                {
                    DeploymentHelper.Get().DeviceId = Config.DeviceId;
                    if (!DeploymentHelper.Get().InstallIPAOnDevice(IPAPath))
                    {
                        Program.Error("Failed to install IPA on device");
                        Program.ReturnCode = (int)ErrorCodes.Error_AppInstallFailed;
                    }
                }
                else
                {
                    Program.Error(String.Format("Failed to find IPA file: '{0}'", IPAPath));
                    Program.ReturnCode = (int)ErrorCodes.Error_AppNotFound;
                }
            }
            break;

            default:
                return(false);
            }

            return(true);
        }
예제 #4
0
        /**
         * Using the stub IPA previously compiled on the Mac, create a new IPA with assets
         */
        public static void RepackageIPAFromStub()
        {
            if (string.IsNullOrEmpty(Config.RepackageStagingDirectory) || !Directory.Exists(Config.RepackageStagingDirectory))
            {
                Program.Error("Directory specified with -stagedir could not be found!");
                return;
            }

            DateTime StartTime = DateTime.Now;
            CodeSignatureBuilder CodeSigner = null;

            // Clean the staging directory
            Program.ExecuteCommand("Clean", null);

            // Create a copy of the IPA so as to not trash the original
            ZipFile Zip = SetupWorkIPA();
            if (Zip == null)
            {
                return;
            }

            string ZipWorkingDir = String.Format("Payload/{0}{1}.app/", Program.GameName, Program.Architecture);

            FileOperations.ZipFileSystem FileSystem = new FileOperations.ZipFileSystem(Zip, ZipWorkingDir);

            // Check for a staged plist that needs to be merged into the main one
            {
                // Determine if there is a staged one we should try to use instead
                string PossiblePList = Path.Combine(Config.RepackageStagingDirectory, "Info.plist");
                if (File.Exists(PossiblePList))
                {
                    if (Config.bPerformResignWhenRepackaging)
                    {
                        Program.Log("Found Info.plist ({0}) in stage, which will be merged in with stub plist contents", PossiblePList);

                        // Merge the two plists, using the staged one as the authority when they conflict
                        byte[] StagePListBytes = File.ReadAllBytes(PossiblePList);
                        string StageInfoString = Encoding.UTF8.GetString(StagePListBytes);

                        byte[] StubPListBytes = FileSystem.ReadAllBytes("Info.plist");
                        Utilities.PListHelper StubInfo = new Utilities.PListHelper(Encoding.UTF8.GetString(StubPListBytes));

                        StubInfo.MergePlistIn(StageInfoString);

                        // Write it back to the cloned stub, where it will be used for all subsequent actions
                        byte[] MergedPListBytes = Encoding.UTF8.GetBytes(StubInfo.SaveToString());
                        FileSystem.WriteAllBytes("Info.plist", MergedPListBytes);
                    }
                    else
                    {
                        Program.Warning("Found Info.plist ({0}) in stage that will be ignored; IPP cannot combine it with the stub plist since -sign was not specified", PossiblePList);
                    }
                }
            }

            // Get the name of the executable file
            string CFBundleExecutable;
            {
                // Load the .plist from the stub
                byte[] RawInfoPList = FileSystem.ReadAllBytes("Info.plist");

                Utilities.PListHelper Info = new Utilities.PListHelper(Encoding.UTF8.GetString(RawInfoPList));

                // Get the name of the executable file
                if (!Info.GetString("CFBundleExecutable", out CFBundleExecutable))
                {
                    throw new InvalidDataException("Info.plist must contain the key CFBundleExecutable");
                }
            }

            // Tell the file system about the executable file name so that we can set correct attributes on
            // the file when zipping it up
            FileSystem.ExecutableFileName = CFBundleExecutable;

            // Prepare for signing if requested
            if (Config.bPerformResignWhenRepackaging)
            {
                // Start the resign process (load the mobileprovision and info.plist, find the cert, etc...)
                CodeSigner = new CodeSignatureBuilder();
                CodeSigner.FileSystem = FileSystem;

                CodeSigner.PrepareForSigning();

                // Merge in any user overrides that exist
                UpdateVersion(CodeSigner.Info);
            }

            // Empty the current staging directory
            FileOperations.DeleteDirectory(new DirectoryInfo(Config.PCStagingRootDir));

            // we will zip files in the pre-staged payload dir
            string ZipSourceDir = Config.RepackageStagingDirectory;

            // Save the zip
            Program.Log("Saving IPA ...");

            FilesBeingModifiedToPrintOut.Clear();
            Zip.SaveProgress += UpdateSaveProgress;

            Zip.CompressionLevel = (Ionic.Zlib.CompressionLevel)Config.RecompressionSetting;

            // Add all of the payload files, replacing existing files in the stub IPA if necessary (should only occur for icons)
            {
                string SourceDir = Path.GetFullPath(ZipSourceDir);
                string[] PayloadFiles = Directory.GetFiles(SourceDir, "*.*", SearchOption.AllDirectories);
                foreach (string Filename in PayloadFiles)
                {
                    // Get the relative path to the file (this implementation only works because we know the files are all
                    // deeper than the base dir, since they were generated from a search)
                    string AbsoluteFilename = Path.GetFullPath(Filename);
                    string RelativeFilename = AbsoluteFilename.Substring(SourceDir.Length + 1).Replace('\\', '/');

                    string ZipAbsolutePath = String.Format("Payload/{0}{1}.app/{1}",
                        Program.GameName,
                        Program.Architecture,
                        RelativeFilename);

                    byte[] FileContents = File.ReadAllBytes(AbsoluteFilename);
                    if (FileContents.Length == 0)
                    {
                        // Zero-length files added by Ionic cause installation/upgrade to fail on device with error 0xE8000050
                        // We store a single byte in the files as a workaround for now
                        FileContents = new byte[1];
                        FileContents[0] = 0;
                    }

                    FileSystem.WriteAllBytes(RelativeFilename, FileContents);

                    if ((FileContents.Length >= 1024 * 1024) || (Config.bVerbose))
                    {
                        FilesBeingModifiedToPrintOut.Add(ZipAbsolutePath);
                    }
                }
            }

            // Re-sign the executable if there is a signing context
            if (CodeSigner != null)
            {
                if (Config.OverrideBundleName != null)
                {
                    CodeSigner.Info.SetString("CFBundleDisplayName", Config.OverrideBundleName);
                    string CFBundleIdentifier;
                    if (CodeSigner.Info.GetString("CFBundleIdentifier", out CFBundleIdentifier))
                    {
                        CodeSigner.Info.SetString("CFBundleIdentifier", CFBundleIdentifier + "_" + Config.OverrideBundleName);
                    }
                }
                CodeSigner.PerformSigning();
            }

            // Stick in the iTunesArtwork PNG if available
            string iTunesArtworkPath = Path.Combine(Config.BuildDirectory, "iTunesArtwork");
            if (File.Exists(iTunesArtworkPath))
            {
                Zip.UpdateFile(iTunesArtworkPath, "");
            }

            // Save the Zip
            Program.Log("Compressing files into IPA.{0}", Config.bVerbose ? "" : "  Only large files will be listed next, but other files are also being packaged.");
            FileSystem.Close();

            TimeSpan ZipLength = DateTime.Now - StartTime;

            FileInfo FinalZipInfo = new FileInfo(Config.GetIPAPath(".ipa"));

            Program.Log(String.Format("Finished repackaging into {2:0.00} MB IPA, written to '{0}' (took {1:0.00} s)",
                Zip.Name,
                ZipLength.TotalSeconds,
                FinalZipInfo.Length / (1024.0f * 1024.0f)));
        }
예제 #5
0
		public static bool ExecuteDeployCommand(string Command, string GamePath, string RPCCommand)
		{
			switch (Command.ToLowerInvariant())
			{
				case "backup":
					{
						string ApplicationIdentifier = RPCCommand;
						if (ApplicationIdentifier == null)
						{
							ApplicationIdentifier = Utilities.GetStringFromPList("CFBundleIdentifier");
						}

						if (Config.FilesForBackup.Count > 0)
						{
							if (!DeploymentHelper.Get().BackupFiles(ApplicationIdentifier, Config.FilesForBackup.ToArray()))
							{
								Program.Error("Failed to transfer manifest file from device to PC");
								Program.ReturnCode = (int)ErrorCodes.Error_DeviceBackupFailed;
							}
						}
						else if (!DeploymentHelper.Get().BackupDocumentsDirectory(ApplicationIdentifier, Config.GetRootBackedUpDocumentsDirectory()))
						{
							Program.Error("Failed to transfer documents directory from device to PC");
							Program.ReturnCode = (int)ErrorCodes.Error_DeviceBackupFailed;
						}
					}
					break;
				case "uninstall":
					{
						string ApplicationIdentifier = RPCCommand;
						if (ApplicationIdentifier == null)
						{
							ApplicationIdentifier = Utilities.GetStringFromPList("CFBundleIdentifier");
						}

						if (!DeploymentHelper.Get().UninstallIPAOnDevice(ApplicationIdentifier))
						{
							Program.Error("Failed to uninstall IPA on device");
							Program.ReturnCode = (int)ErrorCodes.Error_AppUninstallFailed;
						}
					}
					break;
				case "deploy":
				case "install":
					{
						string IPAPath = GamePath;
						string AdditionalCommandline = Program.AdditionalCommandline;

						if (!String.IsNullOrEmpty(AdditionalCommandline) && !Config.bIterate)
						{
							// Read the mobile provision to check for issues
							FileOperations.ReadOnlyZipFileSystem Zip = new FileOperations.ReadOnlyZipFileSystem(IPAPath);
							try
							{
								// Compare the commandline embedded to prevent us from any unnecessary writing.
								byte[] CommandlineBytes = Zip.ReadAllBytes("ue4commandline.txt");
								string ExistingCommandline = Encoding.UTF8.GetString(CommandlineBytes, 0, CommandlineBytes.Length);
								if (ExistingCommandline != AdditionalCommandline)
								{
									// Ensure we have a temp dir to stage our temporary ipa
									if( !Directory.Exists( Config.PCStagingRootDir ) )
									{
										Directory.CreateDirectory(Config.PCStagingRootDir);
									}

									string TmpFilePath = Path.Combine(Path.GetDirectoryName(Config.PCStagingRootDir), Path.GetFileNameWithoutExtension(IPAPath) + ".tmp.ipa");
									if( File.Exists( TmpFilePath ) )
									{
										File.Delete(TmpFilePath);
									}

									File.Copy(IPAPath, TmpFilePath);
								
									// Get the project name:
									string ProjectFile = ExistingCommandline.Split(' ').FirstOrDefault();

									// Write out the new commandline.
									FileOperations.ZipFileSystem WritableZip = new FileOperations.ZipFileSystem(TmpFilePath);
									byte[] NewCommandline = Encoding.UTF8.GetBytes(ProjectFile + " " + AdditionalCommandline);
									WritableZip.WriteAllBytes("ue4commandline.txt", NewCommandline);

									// We need to residn the application after the commandline file has changed.
									CodeSignatureBuilder CodeSigner = new CodeSignatureBuilder();
									CodeSigner.FileSystem = WritableZip;

									CodeSigner.PrepareForSigning();
									CodeSigner.PerformSigning();

									WritableZip.Close();

									// Set the deploying ipa path to our new ipa
									IPAPath = TmpFilePath;
								}
							}
							catch (System.Exception ex)
							{
								Program.Warning(String.Format("Failed to override the commandline.txt file: ({0})", ex.Message));
							}
							Zip.Close();
						}

						if (Config.bIterate)
						{
							string ApplicationIdentifier = RPCCommand;
							if (String.IsNullOrEmpty(ApplicationIdentifier))
							{
								ApplicationIdentifier = Utilities.GetStringFromPList("CFBundleIdentifier");
							}

							DeploymentHelper.Get().DeviceId = Config.DeviceId;
							if (!DeploymentHelper.Get().InstallFilesOnDevice(ApplicationIdentifier, Config.DeltaManifest))
							{
								Program.Error("Failed to install Files on device");
								Program.ReturnCode = (int)ErrorCodes.Error_FilesInstallFailed;
							}
						}
						else if (File.Exists(IPAPath))
						{
							DeploymentHelper.Get().DeviceId = Config.DeviceId;
							if (!DeploymentHelper.Get().InstallIPAOnDevice(IPAPath))
							{
								Program.Error("Failed to install IPA on device");
								Program.ReturnCode = (int)ErrorCodes.Error_AppInstallFailed;
							}
						}
						else
						{
							Program.Error(String.Format("Failed to find IPA file: '{0}'", IPAPath));
							Program.ReturnCode = (int)ErrorCodes.Error_AppNotFound;
						}
					}
					break;

				default:
					return false;
			}

			return true;
		}
        private void ResignButton_Click(object sender, EventArgs e)
        {
            saveFileDialog1.DefaultExt = "ipa";
            saveFileDialog1.FileName = "";
            saveFileDialog1.Filter = ToolsHub.IpaFilter;
            saveFileDialog1.Title = "Choose a filename for the re-signed IPA";

            string CWD = Directory.GetCurrentDirectory();
            bool bDialogSucceeded = (saveFileDialog1.ShowDialog() == DialogResult.OK);
            Directory.SetCurrentDirectory(CWD);

            if (bDialogSucceeded)
            {
                bool bSavedVerbose = Config.bVerbose;
                Config.bVerbose = true;
                Program.ProgressDialog.OnBeginBackgroundWork = delegate
                {
                    string SrcFilename = IPAFilenameEdit.Text;
                    string DestFilename = saveFileDialog1.FileName;

                    // Delete the target location and copy the source there
                    FileOperations.DeleteFile(DestFilename);
                    FileOperations.CopyRequiredFile(SrcFilename, DestFilename);

                    // Open the file
                    FileOperations.ZipFileSystem FileSystem = new FileOperations.ZipFileSystem(DestFilename);
                    FileSystem.SetCompression(CBCompressModifiedFiles.Checked ? Ionic.Zlib.CompressionLevel.BestCompression : Ionic.Zlib.CompressionLevel.None);

                    // Resign and save the file
                    ResignIPA(FileSystem);
                    FileSystem.Close();
                };
                Config.bVerbose = bSavedVerbose;

                Program.ProgressDialog.ShowDialog();
            }
        }