private async Task CheckJavaExistence() { if (LDirectory.Exists(_globalVariables.PathToPortableJre)) { return; } MessBox.ShowDial( MainResources.JavaInvalidVersion, MainResources.Information_Title, MainResources.OK ); _visualProgress.SetBarValue(0); using (CreateWorking()) { _visualProgress.SetBarUsual(); _visualProgress.ShowBar(); await _utils.DownloadJava(_visualProgress); _visualProgress.HideBar(); } }
private string CreateElement([NotNull] Action <string> elementCreator) { if (elementCreator == null) { throw new ArgumentNullException(nameof(elementCreator)); } if (!LDirectory.Exists(_tempFolder)) { LDirectory.CreateDirectory(_tempFolder); } int entryIndex; lock (_entryLock) { if (_lastEntry == int.MaxValue) { _lastEntry = 1; } else { _lastEntry++; } entryIndex = _lastEntry; } string filePath = Path.Combine(_tempFolder, $"temp_entry_{entryIndex}"); elementCreator(filePath); return(filePath); }
private void CheckForFiles([NotNull] GlobalVariables globalVariables) { var resourcesFolder = Path.Combine(globalVariables.PathToExeFolder, "Resources"); string[] notExistingFiles; if (!LDirectory.Exists(resourcesFolder)) { notExistingFiles = new[] { resourcesFolder }; } else { notExistingFiles = NeededFiles.Select(it => Path.Combine(resourcesFolder, it)) .Where(it => !LFile.Exists(it)).ToArray(); } if (notExistingFiles.Length == 0) { return; } MessBox.ShowDial( string.Format( MainResources.NoNeededFilesError, notExistingFiles.Select(Path.GetFileName).Select(file => $"\"{file}\"").JoinStr(", ") ), MainResources.Error ); Shutdown(); }
private async void StartBtn_Click(object sender, EventArgs e) { string apkFile = ViewModel.CurrentApk.Value; string saveFile = ViewModel.CurrentSave.Value; #region Проверка на существование файлов if (string.IsNullOrEmpty(apkFile) || !LFile.Exists(apkFile) || (ViewModel.SavePlusMess.Value || ViewModel.OnlySave.Value) && (string.IsNullOrEmpty(saveFile) || !LFile.Exists(saveFile) && !LDirectory.Exists(saveFile)) ) { HaveError(MainResources.File_or_save_not_selected, MainResources.File_or_save_not_selected); return; } #endregion _currentLog = CreateLogFileForApp(apkFile); using (CreateWorking()) { try { var currentCulture = Thread.CurrentThread.CurrentUICulture; await Task.Factory.StartNew(() => { Thread.CurrentThread.CurrentCulture = currentCulture; Thread.CurrentThread.CurrentUICulture = currentCulture; ProcessAll(); }); } catch (PathTooLongException ex) { HaveError(Environment.NewLine + ex, MainResources.PathTooLongExceptionMessage); } catch (Exception ex) { #if DEBUG Debug.WriteLine(ex.ToString()); throw; #else _globalVariables.ErrorClient.Notify(ex); HaveError(Environment.NewLine + ex, MainResources.Some_Error_Found); #endif } finally { _currentLog?.Close(); _currentLog = null; } } }
public TempUtils( [NotNull] GlobalVariables globalVariables ) { _tempFolder = globalVariables.TempPath; if (LDirectory.Exists(_tempFolder) && LDirectory.EnumerateFileSystemEntries(_tempFolder).Any()) { LDirectory.Delete(_tempFolder, true); } }
public GlobalVariables() { PathToExe = Assembly.GetExecutingAssembly().Location; PathToExeFolder = Path.GetDirectoryName(PathToExe); PortableSwitchFile = Path.Combine(PathToExeFolder, "portable"); IsPortable = LFile.Exists(PortableSwitchFile); AppDataPath = IsPortable ? Path.Combine(PathToExeFolder, "data") : Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Assembly.GetExecutingAssembly().GetName().Name ); TempPath = Path.Combine(AppDataPath, "temp"); PathToResources = Path.Combine(PathToExeFolder, "Resources"); PathToPortableJre = Path.Combine(AppDataPath, "jre"); PathToPortableJavaExe = Path.Combine(PathToPortableJre, "bin", "java.exe"); ApktoolPath = Path.Combine(PathToResources, "apktool.jar"); BaksmaliPath = Path.Combine(PathToResources, "baksmali.jar"); SmaliPath = Path.Combine(PathToResources, "smali.jar"); SignApkPath = Path.Combine(PathToResources, "signapk.jar"); DefaultKeyPemPath = Path.Combine(PathToResources, "testkey.x509.pem"); DefaultKeyPkPath = Path.Combine(PathToResources, "testkey.pk8"); AdbPath = Path.Combine(PathToResources, "platform-tools", "adb.exe"); if (IsPortable) { try { LDirectory.CreateDirectory(AppDataPath); string tempFile = Path.Combine(AppDataPath, "write_test"); using (LFile.Create(tempFile)) { } LFile.Delete(tempFile); CanWriteToAppData = true; } catch (UnauthorizedAccessException) { CanWriteToAppData = false; } } else { LDirectory.CreateDirectory(AppDataPath); } }
private void UpdateApplication() { try { var webClient = new WebClient(); webClient.DownloadProgressChanged += WebClient_DownloadProgressChanged; webClient.DownloadFileCompleted += WebClient_DownloadFileCompleted; var updateDir = Path.GetDirectoryName(UpdateFilePath); LDirectory.CreateDirectory(updateDir); webClient.DownloadFileAsync(UpdateExeUri, UpdateFilePath); } catch (Exception) { LFile.Delete(UpdateFilePath); } }
public static void ExtractAll(this ZipFile zip, string folder) { LDirectory.Delete(folder, true); LDirectory.CreateDirectory(folder); foreach (ZipEntry entry in zip) { if (entry.IsDirectory) { continue; } LDirectory.CreateDirectory(Path.Combine(folder, Path.GetDirectoryName(entry.Name) ?? String.Empty)); using (var zipStream = zip.GetInputStream(entry)) using (var outputStream = LFile.Create(Path.Combine(folder, entry.Name))) { zipStream.CopyTo(outputStream, 4096); } } }
private void ProcessAll() { Dispatcher.Invoke(LogBox.Clear); Log( string.Format( "{0}{1}Start{1}{0}ExePath = {2}{0}Resources = {3}", Environment.NewLine, Line, _globalVariables.PathToExe, _globalVariables.PathToResources ) ); const int totalSteps = 3; _visualProgress.SetBarUsual(); _visualProgress.ShowBar(); _taskBarManager.SetProgress(0); _taskBarManager.SetUsualState(); void SetStep(int currentStep, string status) { int percentage = (currentStep - 1) * 100 / totalSteps; _visualProgress.SetBarValue(percentage); _visualProgress.SetLabelText(status); _taskBarManager.SetProgress(percentage); } #region Инициализация SetStep(1, MainResources.StepInitializing); _visualProgress.ShowIndeterminateLabel(); string sourceApkPath = ViewModel.CurrentApk.Value; bool alternativeSigning = _settings.AlternativeSigning; string popupText = ViewModel.PopupBoxText.Value; int messagesCount = ViewModel.MessagesCount.Value; bool needSave; bool needMessage; { bool onlySave = ViewModel.OnlySave.Value; bool savePlusMessage = ViewModel.SavePlusMess.Value; bool onlyMessage = ViewModel.OnlyMess.Value; needSave = onlySave || savePlusMessage; needMessage = (savePlusMessage || onlyMessage) && !string.IsNullOrEmpty(popupText) && messagesCount > 0; } BackupType backupType = ViewModel.BackupType.Value; ITempFileProvider tempFileProvider = _tempUtils.CreateTempFileProvider(); ITempFolderProvider tempFolderProvider = _tempUtils.CreateTempFolderProvider(); string resultApkPath = sourceApkPath.Remove(sourceApkPath.Length - Path.GetExtension(sourceApkPath).Length) + "_mod.apk"; string pathToSave = ViewModel.CurrentSave.Value; IApktool apktool = _apktoolProvider.Get(); IProcessDataHandler dataHandler = new ProcessDataCombinedHandler(data => Log(data)); #endregion #region Изменение apk using (var tempApk = ATempUtils.UseTempFile(tempFileProvider)) { LFile.Copy(sourceApkPath, tempApk.TempFile, true); #region Добавление данных SetStep(2, MainResources.StepAddingData); var aes = new AesManaged { KeySize = 128 }; aes.GenerateIV(); aes.GenerateKey(); bool backupFilesAdded = false; // adding local and external backup files if (needSave) { using (var internalDataBackup = ATempUtils.UseTempFile(tempFileProvider)) using (var externalDataBackup = ATempUtils.UseTempFile(tempFileProvider)) { ApkModifer.ParseBackup( pathToBackup: pathToSave, backupType: backupType, resultInternalDataPath: internalDataBackup.TempFile, resultExternalDataPath: externalDataBackup.TempFile, tempFolderProvider: tempFolderProvider ); string internalBackup = internalDataBackup.TempFile; string externalBackup = externalDataBackup.TempFile; var fileToAssetsName = new Dictionary <string, string> { { internalBackup, "data.save" }, { externalBackup, "extdata.save" } }; foreach (var(file, assetsName) in fileToAssetsName.Enumerate()) { if (!LFile.Exists(file) || FileUtils.FileLength(file) == 0) { continue; } using (var tempEncrypted = ATempUtils.UseTempFile(tempFileProvider)) { CommonUtils.EncryptFile( filePath: file, outputPath: tempEncrypted.TempFile, iv: aes.IV, key: aes.Key ); ApkModifer.AddFileToZip( zipPath: tempApk.TempFile, filePath: tempEncrypted.TempFile, pathInZip: "assets/" + assetsName, newEntryCompression: CompressionType.Store ); } backupFilesAdded = true; } } } // adding smali file for restoring if (backupFilesAdded || needMessage) { using (var decompiledFolder = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Baksmali( apkPath: tempApk.TempFile, resultFolder: decompiledFolder.TempFolder, tempFolderProvider: tempFolderProvider, dataHandler: dataHandler ); var manifestPath = Path.Combine(decompiledFolder.TempFolder, "AndroidManifest.xml"); apktool.ExtractSimpleManifest( apkPath: tempApk.TempFile, resultManifestPath: manifestPath, tempFolderProvider: tempFolderProvider ); // have to have smali folders in the same directory as manifest // to find the main smali var manifest = new AndroidManifest(manifestPath); if (manifest.MainSmaliFile == null) { throw new Exception("main smali file not found"); } // using this instead of just pasting "folder/smali" as there can be // no smali folder sometimes (smali_1, etc) string smaliDir = manifest.MainSmaliPath.Substring(decompiledFolder.TempFolder.Length + 1); smaliDir = smaliDir.Substring(0, smaliDir.IndexOf(Path.DirectorySeparatorChar)); string saveGameDir = Path.Combine(decompiledFolder.TempFolder, smaliDir, "com", "savegame"); LDirectory.CreateDirectory(saveGameDir); CommonUtils.GenerateAndSaveSmali( filePath: Path.Combine(saveGameDir, "SavesRestoringPortable.smali"), iv: aes.IV, key: aes.Key, addSave: backupFilesAdded, message: needMessage ? popupText : string.Empty, messagesCount: needMessage ? messagesCount : 0 ); manifest.MainSmaliFile.AddTextToMethod(FileResources.MainSmaliCall); manifest.MainSmaliFile.Save(); using (var folderWithDexes = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Smali( folderWithSmali: decompiledFolder.TempFolder, resultFolder: folderWithDexes.TempFolder, dataHandler: dataHandler ); string[] dexes = LDirectory.GetFiles(folderWithDexes.TempFolder, "*.dex"); ApkModifer.AddFilesToZip( zipPath: tempApk.TempFile, filePaths: dexes, pathsInZip: Array.ConvertAll(dexes, Path.GetFileName), newEntryCompression: CompressionType.Store ); } } } #endregion #region Подпись SetStep(3, MainResources.StepSigning); Log(Line); Log(MainResources.StepSigning); Log(Line); apktool.Sign( sourceApkPath: tempApk.TempFile, signedApkPath: resultApkPath, tempFileProvider: tempFileProvider, dataHandler: dataHandler, deleteMetaInf: !alternativeSigning ); #endregion } #endregion _visualProgress.HideIndeterminateLabel(); SetStep(4, MainResources.AllDone); Log(MainResources.AllDone); Log(string.Empty, false); Log($"{MainResources.Path_to_file} {resultApkPath}"); _globalVariables.LatestModdedApkPath = resultApkPath; if (_settings.Notifications) { _notificationManager.Show( title: MainResources.Information_Title, text: MainResources.ModificationCompletedContent ); } string dialogResult = MessBox.ShowDial( $"{MainResources.Path_to_file} {resultApkPath}", MainResources.Successful, MainResources.OK, MainResources.Open, MainResources.Install ); _visualProgress.HideBar(); _taskBarManager.SetNoneState(); if (dialogResult == MainResources.Open) { Process.Start("explorer.exe", $"/select,{resultApkPath}"); } else if (dialogResult == MainResources.Install) { Dispatcher.Invoke(() => _adbInstallWindowProvider.Get().ShowDialog()); } }
public async Task DownloadJava([NotNull] IVisualProgress visualProgress) { visualProgress.SetLabelText(MainResources.JavaDownloading); visualProgress.ShowIndeterminateLabel(); bool fileDownloaded; const string jreUrl = @"https://pixelcurves.ams3.digitaloceanspaces.com/SaveToGame/jre_1.7.zip"; string fileLocation = Path.Combine(_globalVariables.AppDataPath, "jre.zip"); LDirectory.CreateDirectory(_globalVariables.AppDataPath); using (var client = new WebClient()) { client.DownloadProgressChanged += (sender, args) => visualProgress.SetBarValue(args.ProgressPercentage); while (true) { try { await client.DownloadFileTaskAsync(jreUrl, fileLocation); fileDownloaded = true; break; } catch (Exception ex) { var promt = MessBox.ShowDial( string.Format(MainResources.JavaDownloadFailed, ex.Message), MainResources.Error, MainResources.No, MainResources.Yes ); if (promt == MainResources.Yes) { continue; } fileDownloaded = false; break; } } } if (fileDownloaded) { visualProgress.SetLabelText(MainResources.JavaExtracting); visualProgress.SetBarIndeterminate(); using (var zipFile = new ZipFile(fileLocation)) { await Task.Factory.StartNew(() => zipFile.ExtractAll(_globalVariables.PathToPortableJre)); } LFile.Delete(fileLocation); } visualProgress.HideIndeterminateLabel(); visualProgress.SetLabelText(MainResources.AllDone); }
private void ProcessAll(byte[] xxhdpiBytes, byte[] xhdpiBytes, byte[] hdpiBytes, byte[] mdpiBytes, Dispatcher uiThreadDispatcher) { const string internalDataInApkName = "data.save"; const string externalDataInApkName = "extdata.save"; IVisualProgress visualProgress = VisualProgress.Value; ITaskBarManager taskBarManager = TaskBarManager.Value; string apkFile = Apk.Value; string saveFile = Save.Value; string androidDataFile = Data.Value; string[] androidObbFiles = (string[])Obb.Value?.Clone() ?? new string[0]; string appTitle = AppTitle.Value; bool alternativeSigning = _settings.AlternativeSigning; BackupType backupType = _settings.BackupType; // initializing visualProgress?.SetBarIndeterminate(); visualProgress?.ShowBar(); visualProgress?.ShowIndeterminateLabel(); taskBarManager?.SetProgress(0); taskBarManager?.SetUsualState(); void SetStep(string step, int stepNumber) { WindowTitle.Value = step; Log(step); const int maxStep = 5; int percentage = (stepNumber - 1) * 100 / maxStep; visualProgress?.SetLabelText(step); taskBarManager?.SetProgress(percentage); } SetStep(MainResources.StepInitializing, 1); string resultFilePath = Path.Combine( Path.GetDirectoryName(apkFile) ?? string.Empty, Path.GetFileNameWithoutExtension(apkFile) + "_mod.apk" ); IApktool apktool = _apktoolProvider.Get(); IProcessDataHandler dataHandler = new ProcessDataCombinedHandler(Log); ITempFileProvider tempFileProvider = _tempUtils.CreateTempFileProvider(); ITempFolderProvider tempFolderProvider = _tempUtils.CreateTempFolderProvider(); using (var stgContainerExtracted = AndroidHelper.Logic.Utils.TempUtils.UseTempFolder(tempFolderProvider)) { // extracting SaveToGame container app SetStep(MainResources.CopyingStgApk, 2); string containerZipPath = Path.Combine(_globalVariables.PathToResources, "apk.zip"); using (var zip = new ZipFile(containerZipPath) { Password = _globalVariables.AdditionalFilePassword }) { zip.ExtractAll(stgContainerExtracted.TempFolder); } SetStep(MainResources.AddingData, 3); // creating assets folder for data string stgContainerAssetsPath = Path.Combine(stgContainerExtracted.TempFolder, "assets"); LDirectory.CreateDirectory(stgContainerAssetsPath); // adding backup if (!string.IsNullOrEmpty(saveFile)) { string internalDataPath = Path.Combine(stgContainerAssetsPath, internalDataInApkName); string externalDataPath = Path.Combine(stgContainerAssetsPath, externalDataInApkName); ApkModifer.ParseBackup( pathToBackup: saveFile, backupType: backupType, resultInternalDataPath: internalDataPath, resultExternalDataPath: externalDataPath, tempFolderProvider: tempFolderProvider ); } // adding external data if (!string.IsNullOrEmpty(androidDataFile)) { LFile.Copy( androidDataFile, Path.Combine(stgContainerAssetsPath, externalDataInApkName) ); } // adding obb files if (androidObbFiles.Length != 0) { using (var obbParts = AndroidHelper.Logic.Utils.TempUtils.UseTempFolder(tempFolderProvider)) { ApkModifer.SplitObbFiles( obbFilePaths: androidObbFiles, partsFolderPath: obbParts.TempFolder, // todo: add progress progressNotifier: null ); string assetsDir = Path.Combine(stgContainerExtracted.TempFolder, "assets", "111111222222333333"); LDirectory.CreateDirectory(assetsDir); IEnumerable <string> filesToAdd = LDirectory.EnumerateFiles(obbParts.TempFolder); foreach (var file in filesToAdd) { LFile.Copy(file, Path.Combine(assetsDir, Path.GetFileName(file))); } } } // adding resigned apk to container using (var sourceResigned = AndroidHelper.Logic.Utils.TempUtils.UseTempFile(tempFileProvider)) { apktool.Sign( sourceApkPath: apkFile, signedApkPath: sourceResigned.TempFile, tempFileProvider: tempFileProvider, dataHandler: dataHandler, deleteMetaInf: !alternativeSigning ); LFile.Copy( sourceFileName: sourceResigned.TempFile, destFileName: Path.Combine(stgContainerAssetsPath, "install.bin"), overwrite: false ); } // modifying AndroidManifest { string pathToManifest = Path.Combine(stgContainerExtracted.TempFolder, "AndroidManifest.xml"); string sourcePackageName; using (var sourceManifest = AndroidHelper.Logic.Utils.TempUtils.UseTempFile(tempFileProvider)) { apktool.ExtractSimpleManifest( apkPath: apkFile, resultManifestPath: sourceManifest.TempFile, tempFolderProvider: tempFolderProvider ); sourcePackageName = new AndroidManifest(sourceManifest.TempFile).Package; } LFile.WriteAllText( pathToManifest, LFile.ReadAllText(pathToManifest, Encoding.UTF8) .Replace("change_package", sourcePackageName) .Replace("@string/app_name", appTitle) ); } // adding icons { string iconsFolder = Path.Combine(stgContainerExtracted.TempFolder, "res", "mipmap-"); void DeleteIcon(string folder) => LFile.Delete(Path.Combine($"{iconsFolder}{folder}", "ic_launcher.png")); DeleteIcon("xxhdpi-v4"); DeleteIcon("xhdpi-v4"); DeleteIcon("hdpi-v4"); DeleteIcon("mdpi-v4"); void WriteIcon(string folder, byte[] imageBytes) => LFile.WriteAllBytes(Path.Combine($"{iconsFolder}{folder}", "ic_launcher.png"), imageBytes); WriteIcon("xxhdpi-v4", xxhdpiBytes); WriteIcon("xhdpi-v4", xhdpiBytes); WriteIcon("hdpi-v4", hdpiBytes); WriteIcon("mdpi-v4", mdpiBytes); } // compiling + signing using (var compiledContainer = AndroidHelper.Logic.Utils.TempUtils.UseTempFile(tempFileProvider)) { // compiling SetStep(MainResources.StepCompiling, 4); // todo: check errors List <Error> compilationErrors; apktool.Compile( projectFolderPath: stgContainerExtracted.TempFolder, destinationApkPath: compiledContainer.TempFile, dataHandler: dataHandler, errors: out compilationErrors ); if (compilationErrors.Count > 0) { Log(MainResources.ErrorUp); return; } // signing SetStep(MainResources.StepSigning, 5); apktool.Sign( sourceApkPath: compiledContainer.TempFile, signedApkPath: resultFilePath, tempFileProvider: tempFileProvider, dataHandler: dataHandler, deleteMetaInf: !alternativeSigning ); } } visualProgress?.HideIndeterminateLabel(); visualProgress?.HideBar(); SetStep(MainResources.AllDone, 6); Log(string.Empty); Log($"{MainResources.Path_to_file} {resultFilePath}"); _globalVariables.LatestModdedApkPath = resultFilePath; if (_settings.Notifications) { _notificationManager.Show( title: MainResources.Information_Title, text: MainResources.ModificationCompletedContent ); } string dialogResult = MessBox.ShowDial( $"{MainResources.Path_to_file} {resultFilePath}", MainResources.Successful, MainResources.OK, MainResources.Open, MainResources.Install ); if (dialogResult == MainResources.Open) { Process.Start("explorer.exe", $"/select,{resultFilePath}"); } else if (dialogResult == MainResources.Install) { uiThreadDispatcher.Invoke(() => _adbInstallWindowProvider.Get().ShowDialog()); } taskBarManager?.SetNoneState(); }
public static void ParseBackup( [NotNull] string pathToBackup, BackupType backupType, [NotNull] string resultInternalDataPath, [NotNull] string resultExternalDataPath, //[NotNull] string resultObbPath, [NotNull] ITempFolderProvider tempFolderProvider ) { Guard.NotNullArgument(pathToBackup, nameof(pathToBackup)); Guard.NotNullArgument(resultInternalDataPath, nameof(resultInternalDataPath)); Guard.NotNullArgument(resultExternalDataPath, nameof(resultExternalDataPath)); //Guard.NotNullArgument(resultObbPath, nameof(resultObbPath)); Guard.NotNullArgument(tempFolderProvider, nameof(tempFolderProvider)); switch (backupType) { case BackupType.Titanium: { #region Структура /* * * data * data * .external.appname * . * данные * appname * . * данные */ #endregion using (var extractedBackup = TempUtils.UseTempFolder(tempFolderProvider)) { ExtractTarByEntry(pathToBackup, extractedBackup.TempFolder); string path = Path.Combine(extractedBackup.TempFolder, "data", "data"); foreach (string dir in LDirectory.EnumerateDirectories(path)) { string dirName = Path.GetFileName(dir); if (string.IsNullOrEmpty(dirName)) { continue; } switch (dirName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries)[0]) { case "external obb": //CreateArchive(dir, resultObbPath); break; case "external": CreateArchive(dir, resultExternalDataPath); break; default: CreateArchive(dir, resultInternalDataPath); break; } } } break; } case BackupType.RomToolbox: { #region Структура /* * * data * data * appname * данные * storage\emulated\legacy * Android * data * appname * данные * */ #endregion using (var extractedBackup = TempUtils.UseTempFolder(tempFolderProvider)) { ExtractTarByEntry(pathToBackup, extractedBackup.TempFolder); IEnumerable <string> firstLevelDirs = LDirectory.EnumerateDirectories(extractedBackup.TempFolder); foreach (string firstLevelDir in firstLevelDirs) { if (Path.GetFileName(firstLevelDir) == "data") { string path = Path.Combine(firstLevelDir, "data"); string dir = LDirectory.EnumerateDirectories(path).FirstOrDefault(); if (dir == default) { continue; } CreateArchive(dir, Path.Combine(resultInternalDataPath)); } else { string dir = LDirectory.EnumerateDirectories(firstLevelDir, "Android", SearchOption.AllDirectories).FirstOrDefault(); if (dir == default) { continue; } string path = Path.Combine(dir, "data"); string dir2 = LDirectory.EnumerateDirectories(path).FirstOrDefault(); if (dir2 == default) { continue; } CreateArchive(dir2, resultExternalDataPath); } } } break; } case BackupType.LuckyPatcher: { #region Структура /* * * appname * data.lpbkp * данные * sddata.lpbkp * данные * */ #endregion string dataFile = Path.Combine(pathToBackup, "data.lpbkp"); string sddataFile = Path.Combine(pathToBackup, "sddata.lpbkp"); if (LFile.Exists(dataFile)) { LFile.Move(dataFile, resultInternalDataPath); } if (LFile.Exists(sddataFile)) { LFile.Move(sddataFile, resultExternalDataPath); } break; } default: throw new NotSupportedException($"`{backupType}` is not supported at the moment"); } }
private void ProcessAll() { Dispatcher.Invoke(LogBox.Clear); Log( string.Format( "{0}{1}Start{1}{0}ExePath = {2}{0}Resources = {3}", Environment.NewLine, Line, _globalVariables.PathToExe, _globalVariables.PathToResources ) ); const int totalSteps = 3; _visualProgress.SetBarUsual(); _visualProgress.ShowBar(); _taskBarManager.SetProgress(0); _taskBarManager.SetUsualState(); void SetStep(int currentStep, string status) { int percentage = (currentStep - 1) * 100 / totalSteps; _visualProgress.SetBarValue(percentage); _visualProgress.SetLabelText(status); _taskBarManager.SetProgress(percentage); } #region Инициализация SetStep(1, MainResources.StepInitializing); _visualProgress.ShowIndeterminateLabel(); string sourceApkPath = ViewModel.CurrentApk.Value; bool alternativeSigning = _settings.AlternativeSigning; string popupText = ViewModel.PopupBoxText.Value; int messagesCount = ViewModel.MessagesCount.Value; bool needMessage = true; BackupType backupType = ViewModel.BackupType.Value; ITempFileProvider tempFileProvider = _tempUtils.CreateTempFileProvider(); ITempFolderProvider tempFolderProvider = _tempUtils.CreateTempFolderProvider(); string resultApkPath = sourceApkPath.Remove(sourceApkPath.Length - Path.GetExtension(sourceApkPath).Length) + "_signed.apk"; string pathToSave = ViewModel.CurrentSave.Value; IApktool apktool = _apktoolProvider.Get(); IProcessDataHandler dataHandler = new ProcessDataCombinedHandler(data => Log(data)); #endregion #region Change apk // Temp using (var tempApk = ATempUtils.UseTempFile(tempFileProvider)) { LFile.Copy(sourceApkPath, tempApk.TempFile, true); //Copy apk file to temp #region Adding data SetStep(2, MainResources.StepAddingData); var aes = new AesManaged { KeySize = 128 }; aes.GenerateIV(); aes.GenerateKey(); // adding smali file for restoring using (var decompiledFolder = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Baksmali( apkPath: tempApk.TempFile, resultFolder: decompiledFolder.TempFolder, tempFolderProvider: tempFolderProvider, dataHandler: dataHandler ); var manifestPath = Path.Combine(decompiledFolder.TempFolder, "AndroidManifest.xml"); apktool.ExtractSimpleManifest( apkPath: tempApk.TempFile, resultManifestPath: manifestPath, tempFolderProvider: tempFolderProvider ); // have to have smali folders in the same directory as manifest // to find the main smali var manifest = new AndroidManifest(manifestPath); if (manifest.MainSmaliFile == null) { throw new Exception("main smali file not found"); } // using this instead of just pasting "folder/smali" as there can be // no smali folder sometimes (smali_1, etc) string smaliDir = manifest.MainSmaliPath.Substring(decompiledFolder.TempFolder.Length + 1); smaliDir = smaliDir.Substring(0, smaliDir.IndexOf(Path.DirectorySeparatorChar)); string saveGameDir = Path.Combine(decompiledFolder.TempFolder, smaliDir, "com", "savegame"); LDirectory.CreateDirectory(saveGameDir); //Encrypt smali CommonUtils.GenerateAndSaveSmali( filePath: Path.Combine(saveGameDir, "SavesRestoringPortable.smali"), message: needMessage ? popupText : string.Empty, messagesCount: needMessage ? messagesCount : 0 ); manifest.MainSmaliFile.AddTextToMethod(FileResources.MainSmaliCall); manifest.MainSmaliFile.Save(); using (var folderWithDexes = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Smali( folderWithSmali: decompiledFolder.TempFolder, resultFolder: folderWithDexes.TempFolder, dataHandler: dataHandler ); string[] dexes = LDirectory.GetFiles(folderWithDexes.TempFolder, "*.dex"); ApkModifer.AddFilesToZip( zipPath: tempApk.TempFile, filePaths: dexes, pathsInZip: Array.ConvertAll(dexes, Path.GetFileName), newEntryCompression: CompressionType.Store ); } } #endregion #region Подпись SetStep(3, MainResources.StepSigning); Log(Line); Log(MainResources.StepSigning); Log(Line); LFile.Copy(tempApk.TempFile, Path.GetDirectoryName(sourceApkPath) + "\\" + Path.GetFileNameWithoutExtension(sourceApkPath) + "_unsigned.apk", true); //Copy apk file to temp //Signing //tempApk.TempFile "C:\\Users\\xxxxx\\AppData\\Local\\SaveToGame\\temp\\temp_entry_1" apktool.Sign( sourceApkPath: tempApk.TempFile, signedApkPath: resultApkPath, tempFileProvider: tempFileProvider, dataHandler: dataHandler, deleteMetaInf: !alternativeSigning ); #endregion } #endregion _visualProgress.HideIndeterminateLabel(); SetStep(4, MainResources.AllDone); Log(MainResources.AllDone); Log(string.Empty, false); Log($"{MainResources.Path_to_file} {resultApkPath}"); _globalVariables.LatestModdedApkPath = resultApkPath; if (_settings.Notifications) { _notificationManager.Show( title: MainResources.Information_Title, text: MainResources.ModificationCompletedContent ); } string dialogResult = MessBox.ShowDial( $"{MainResources.Path_to_file} {resultApkPath}", MainResources.Successful, MainResources.OK, MainResources.Open, MainResources.Install ); _visualProgress.HideBar(); _taskBarManager.SetNoneState(); //Dialog result if (dialogResult == MainResources.Open) { Process.Start("explorer.exe", $"/select,{resultApkPath}"); } else if (dialogResult == MainResources.Install) { Dispatcher.Invoke(() => _adbInstallWindowProvider.Get().ShowDialog()); } }