예제 #1
0
        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();
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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();
        }
예제 #4
0
        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;
                }
            }
        }
예제 #5
0
        public TempUtils(
            [NotNull] GlobalVariables globalVariables
            )
        {
            _tempFolder = globalVariables.TempPath;

            if (LDirectory.Exists(_tempFolder) && LDirectory.EnumerateFileSystemEntries(_tempFolder).Any())
            {
                LDirectory.Delete(_tempFolder, true);
            }
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
                    }
            }
        }
예제 #9
0
        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());
            }
        }
예제 #10
0
        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);
        }
예제 #11
0
        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();
        }
예제 #12
0
        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");
            }
        }
예제 #13
0
        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());
            }
        }