From b0981fa7e7192944cf1df4493d0938cdbbf1ed3d Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Fri, 20 Sep 2024 23:55:34 +0300 Subject: [PATCH 1/8] refactor: ApkDecoder & ApkBuilder overhaul A major rewrite of ApkDecoder and ApkBuilder classes to make them managable. Removed many instances of redundancy and improved syntaxed and indentation. Modifying the stock Apktool source to our needs have become too difficult, so I'm pushing the general (not specific to our needs) changes upstream. I'd change a lot more, but I wanted to make sure all tests pass as expected, despite some of them being wierd, outdated or unnecessary. This also fixes certain files in META-INF being lost during recompile when the -c/--copy-original option isn't used. This has been tweaked and tested for several days and I vouch for its stablity. --- .../src/main/java/brut/apktool/Main.java | 83 ++- .../main/java/brut/androlib/AaptInvoker.java | 130 ++-- .../main/java/brut/androlib/ApkBuilder.java | 670 +++++++++--------- .../main/java/brut/androlib/ApkDecoder.java | 471 ++++++------ .../java/brut/androlib/ApktoolProperties.java | 4 +- .../java/brut/androlib/BackgroundWorker.java | 4 +- .../src/main/java/brut/androlib/Config.java | 8 +- .../main/java/brut/androlib/apk/ApkInfo.java | 112 +-- .../main/java/brut/androlib/mod/SmaliMod.java | 75 +- .../java/brut/androlib/res/Framework.java | 6 +- .../brut/androlib/res/ResourcesDecoder.java | 14 +- .../java/brut/androlib/res/data/ResTable.java | 33 +- .../brut/androlib/res/data/ResTypeSpec.java | 2 +- .../res/data/value/ResArrayValue.java | 4 +- .../res/data/value/ResScalarValue.java | 4 +- .../res/data/value/ResValueFactory.java | 2 +- .../androlib/res/decoder/ARSCDecoder.java | 2 +- .../res/decoder/AXmlResourceParser.java | 16 +- ... => AndroidManifestPullStreamDecoder.java} | 33 +- .../AndroidManifestResourceParser.java | 8 +- .../res/decoder/ResStreamDecoder.java | 3 +- .../res/decoder/ResXmlPullStreamDecoder.java | 63 ++ .../androlib/res/decoder/StringBlock.java | 5 +- .../brut/androlib/res/xml/ResXmlPatcher.java | 262 +++---- .../java/brut/androlib/src/SmaliBuilder.java | 47 +- .../java/brut/androlib/src/SmaliDecoder.java | 8 +- .../src/test/java/brut/androlib/BaseTest.java | 6 +- .../aapt1/AndroidOreoNotSparseTest.java | 4 +- .../androlib/aapt1/AndroidOreoSparseTest.java | 4 +- .../androlib/aapt1/BuildAndDecodeJarTest.java | 4 +- .../androlib/aapt1/BuildAndDecodeTest.java | 4 +- .../androlib/aapt1/DebugTagRetainedTest.java | 4 +- .../aapt1/DefaultBaksmaliVariableTest.java | 4 +- .../aapt1/EmptyResourcesArscTest.java | 4 +- .../androlib/aapt1/ExternalEntityTest.java | 4 +- .../aapt1/LargeIntsInManifestTest.java | 6 +- .../androlib/aapt1/ProviderAttributeTest.java | 6 +- .../androlib/aapt1/SharedLibraryTest.java | 2 +- .../aapt1/UnknownCompressionTest.java | 2 +- .../androlib/aapt2/BuildAndDecodeTest.java | 5 +- .../DebuggableFalseChangeToTrueTest.java | 3 +- .../aapt2/DebuggableTrueAddedTest.java | 3 +- .../aapt2/DebuggableTrueRetainedTest.java | 3 +- .../androlib/aapt2/NetworkConfigTest.java | 3 +- .../androlib/aapt2/NoNetworkConfigTest.java | 3 +- .../androlib/aapt2/NonStandardPkgIdTest.java | 1 - .../brut/androlib/decode/AndResGuardTest.java | 4 +- .../androlib/decode/CompactResourceTest.java | 2 +- .../decode/DecodeKotlinCoroutinesTest.java | 8 +- .../androlib/decode/DecodeKotlinTest.java | 2 +- .../DoubleExtensionUnknownFileTest.java | 4 +- .../androlib/decode/DuplicateDexTest.java | 4 +- .../brut/androlib/decode/Empty9PatchTest.java | 2 +- .../brut/androlib/decode/EmptyArscTest.java | 2 +- .../ForceManifestDecodeNoResourcesTest.java | 2 +- .../decode/MissingVersionManifestTest.java | 2 +- .../decode/OutsideOfDirectoryEntryTest.java | 2 +- .../decode/ParentDirectoryTraversalTest.java | 2 +- .../androlib/decode/ProtectedApkTest.java | 2 +- .../ResourceDirectoryTraversalTest.java | 2 +- .../androlib/decode/ResourceModeTest.java | 6 +- .../brut/androlib/decode/SparseFlagTest.java | 4 +- .../androlib/decode/VectorDrawableTest.java | 2 +- .../util/UnknownDirectoryTraversalTest.java | 30 +- .../brut/directory/AbstractDirectory.java | 11 +- .../src/main/java/brut/directory/DirUtil.java | 32 +- .../src/main/java/brut/directory/ExtFile.java | 9 + .../java/brut/directory/FileDirectory.java | 9 +- .../java/brut/directory/ZipRODirectory.java | 8 +- .../main/java/brut/directory/ZipUtils.java | 100 ++- .../src/main/java/brut/util/AaptManager.java | 116 +-- .../src/main/java/brut/util/BrutIO.java | 40 +- brut.j.util/src/main/java/brut/util/OS.java | 6 +- .../src/main/java/brut/util/OSDetection.java | 2 +- 74 files changed, 1316 insertions(+), 1243 deletions(-) rename brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/{XmlPullStreamDecoder.java => AndroidManifestPullStreamDecoder.java} (82%) create mode 100644 brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResXmlPullStreamDecoder.java diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index 94967f2b92..dfeabd4ebc 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -215,7 +215,6 @@ private static void cmdDecode(CommandLine cli, Config config) throws AndrolibExc ExtFile apkFile = new ExtFile(apkName); ApkDecoder decoder = new ApkDecoder(config, apkFile); - try { decoder.decode(outDir); } catch (OutDirExistsException ex) { @@ -235,18 +234,12 @@ private static void cmdDecode(CommandLine cli, Config config) throws AndrolibExc + ". You must install proper " + "framework files, see project website for more info."); System.exit(1); - } catch (IOException ex) { - System.err.println("Could not modify file. Please ensure you have permission."); - System.exit(1); - } catch (DirectoryException ex) { - System.err.println("Could not modify internal dex files. Please ensure you have permission."); - System.exit(1); } } - private static void cmdBuild(CommandLine cli, Config config) { + private static void cmdBuild(CommandLine cli, Config config) throws AndrolibException { String[] args = cli.getArgs(); - String appDirName = args.length < 2 ? "." : args[1]; + String apkDirName = args.length < 2 ? "." : args[1]; // check for build options if (cli.hasOption("f") || cli.hasOption("force-all")) { @@ -262,7 +255,32 @@ private static void cmdBuild(CommandLine cli, Config config) { config.verbose = true; } if (cli.hasOption("a") || cli.hasOption("aapt")) { - config.aaptPath = cli.getOptionValue("a"); + if (cli.hasOption("use-aapt1") || cli.hasOption("use-aapt2")) { + System.err.println("You can only use one of -a/--aapt or --use-aapt1 or --use-aapt2."); + System.exit(1); + } + + try { + String aaptPath = cli.getOptionValue("a"); + int aaptVersion = AaptManager.getAaptVersion(aaptPath); + if (aaptVersion < AaptManager.AAPT_VERSION_MIN && aaptVersion > AaptManager.AAPT_VERSION_MAX) { + System.err.println("AAPT version " + aaptVersion + " is not supported"); + System.exit(1); + } + + config.aaptPath = aaptPath; + config.aaptVersion = aaptVersion; + } catch (BrutException ex) { + System.err.println(ex.getMessage()); + System.exit(1); + } + } else if (cli.hasOption("use-aapt1")) { + if (cli.hasOption("use-aapt2")) { + System.err.println("You can only use one of --use-aapt1 or --use-aapt2."); + System.exit(1); + } + + config.aaptVersion = 1; } if (cli.hasOption("c") || cli.hasOption("copy-original")) { config.copyOriginalFiles = true; @@ -270,13 +288,8 @@ private static void cmdBuild(CommandLine cli, Config config) { if (cli.hasOption("nc") || cli.hasOption("no-crunch")) { config.noCrunch = true; } - if (cli.hasOption("use-aapt1")) { - config.useAapt2 = false; - } - - if (cli.hasOption("use-aapt1") && cli.hasOption("use-aapt2")) { - System.err.println("You can only use one of --use-aapt1 or --use-aapt2."); - System.exit(1); + if (cli.hasOption("na") || cli.hasOption("no-apk")) { + config.noApk = true; } File outFile; @@ -286,21 +299,14 @@ private static void cmdBuild(CommandLine cli, Config config) { outFile = null; } - if (config.netSecConf && !config.useAapt2) { - System.err.println("-n / --net-sec-conf is only supported with --use-aapt2."); + if (config.netSecConf && config.aaptVersion == 1) { + System.err.println("-n / --net-sec-conf is not supported with legacy AAPT."); System.exit(1); } - // try and build apk - try { - if (cli.hasOption("a") || cli.hasOption("aapt")) { - config.aaptVersion = AaptManager.getAaptVersion(cli.getOptionValue("a")); - } - new ApkBuilder(config, new ExtFile(appDirName)).build(outFile); - } catch (BrutException ex) { - System.err.println(ex.getMessage()); - System.exit(1); - } + ExtFile apkDir = new ExtFile(apkDirName); + ApkBuilder builder = new ApkBuilder(config, apkDir); + builder.build(outFile); } private static void cmdInstallFramework(CommandLine cli, Config config) throws AndrolibException { @@ -462,13 +468,13 @@ private static void _options() { .build(); Option aapt1Option = Option.builder() - .longOpt("use-aapt1") - .desc("Use aapt binary instead of aapt2 during the build step.") - .build(); + .longOpt("use-aapt1") + .desc("Use aapt binary instead of aapt2 during the build step.") + .build(); Option aapt2Option = Option.builder() .longOpt("use-aapt2") - .desc("Use aapt2 binary instead of aapt during the build step.") + .desc("Use aapt2 binary instead of aapt during the build step. (default)") .build(); Option originalOption = Option.builder("c") @@ -481,6 +487,11 @@ private static void _options() { .desc("Disable crunching of resource files during the build step.") .build(); + Option noApkOption = Option.builder("na") + .longOpt("no-apk") + .desc("Disable repacking of the built files into a new apk.") + .build(); + Option tagOption = Option.builder("t") .longOpt("tag") .desc("Tag frameworks using .") @@ -530,6 +541,7 @@ private static void _options() { buildOptions.addOption(originalOption); buildOptions.addOption(aapt1Option); buildOptions.addOption(noCrunchOption); + buildOptions.addOption(noApkOption); } // add global options @@ -591,6 +603,7 @@ private static void _options() { allOptions.addOption(aapt1Option); allOptions.addOption(aapt2Option); allOptions.addOption(noCrunchOption); + allOptions.addOption(noApkOption); allOptions.addOption(onlyMainClassesOption); } @@ -675,8 +688,8 @@ public String format(LogRecord record) { } } } - } catch (Exception exception) { - reportError(null, exception, ErrorManager.FORMAT_FAILURE); + } catch (Exception ex) { + reportError(null, ex, ErrorManager.FORMAT_FAILURE); } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java index db9afc783e..47868e2477 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java @@ -39,39 +39,39 @@ public AaptInvoker(Config config, ApkInfo apkInfo) { private File getAaptBinaryFile() throws AndrolibException { try { - if (getAaptVersion() == 2) { - return AaptManager.getAapt2(); + switch (mConfig.aaptVersion) { + case 2: + return AaptManager.getAapt2(); + default: + return AaptManager.getAapt1(); } - return AaptManager.getAapt1(); } catch (BrutException ex) { throw new AndrolibException(ex); } } - private int getAaptVersion() { - return mConfig.isAapt2() ? 2 : 1; - } + public void invokeAapt(File apkFile, File manifest, File resDir, File rawDir, File assetDir, File[] include) + throws AndrolibException { - private File createDoNotCompressExtensionsFile(ApkInfo apkInfo) throws AndrolibException { - if (apkInfo.doNotCompress == null || apkInfo.doNotCompress.isEmpty()) { - return null; - } + String aaptPath = mConfig.aaptPath; + boolean customAapt = !aaptPath.isEmpty(); + List cmd = new ArrayList<>(); - File doNotCompressFile; try { - doNotCompressFile = File.createTempFile("APKTOOL", null); - doNotCompressFile.deleteOnExit(); - - BufferedWriter fileWriter = new BufferedWriter(new FileWriter(doNotCompressFile)); - for (String extension : apkInfo.doNotCompress) { - fileWriter.write(extension); - fileWriter.newLine(); - } - fileWriter.close(); + String aaptCommand = AaptManager.getAaptExecutionCommand(aaptPath, getAaptBinaryFile()); + cmd.add(aaptCommand); + } catch (BrutException ex) { + LOGGER.warning("aapt: " + ex.getMessage() + " (defaulting to $PATH binary)"); + cmd.add(AaptManager.getAaptBinaryName(mConfig.aaptVersion)); + } - return doNotCompressFile; - } catch (IOException ex) { - throw new AndrolibException(ex); + switch (mConfig.aaptVersion) { + case 2: + invokeAapt2(apkFile, manifest, resDir, rawDir, assetDir, include, cmd, customAapt); + break; + default: + invokeAapt1(apkFile, manifest, resDir, rawDir, assetDir, include, cmd, customAapt); + break; } } @@ -131,7 +131,9 @@ private void invokeAapt2(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-o"); cmd.add(apkFile.getAbsolutePath()); - if (mApkInfo.packageInfo.forcedPackageId != null && ! mApkInfo.sharedLibrary) { + if (mApkInfo.packageInfo.forcedPackageId != null && !mApkInfo.packageInfo.forcedPackageId.equals("1") + && !mApkInfo.sharedLibrary) { + cmd.add("--allow-reserved-package-id"); cmd.add("--package-id"); cmd.add(mApkInfo.packageInfo.forcedPackageId); } @@ -174,8 +176,6 @@ private void invokeAapt2(File apkFile, File manifest, File resDir, File rawDir, cmd.add("--no-version-transitions"); cmd.add("--no-resource-deduping"); - cmd.add("--allow-reserved-package-id"); - cmd.add("--no-compile-sdk-metadata"); // #3427 - Ignore stricter parsing during aapt2 @@ -189,17 +189,18 @@ private void invokeAapt2(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-x"); } - if (mApkInfo.doNotCompress != null && !customAapt) { - // Use custom -e option to avoid limits on commandline length. - // Can only be used when custom aapt binary is not used. - String extensionsFilePath = - Objects.requireNonNull(createDoNotCompressExtensionsFile(mApkInfo)).getAbsolutePath(); - cmd.add("-e"); - cmd.add(extensionsFilePath); - } else if (mApkInfo.doNotCompress != null) { - for (String file : mApkInfo.doNotCompress) { - cmd.add("-0"); - cmd.add(file); + if (!mApkInfo.doNotCompress.isEmpty()) { + if (customAapt) { + for (String file : mApkInfo.doNotCompress) { + cmd.add("-0"); + cmd.add(file); + } + } else { + // Use custom -e option to avoid limits on commandline length. + // Can only be used when custom aapt binary is not used. + String extensionsFilePath = createDoNotCompressExtensionsFile(mApkInfo.doNotCompress); + cmd.add("-e"); + cmd.add(extensionsFilePath); } } @@ -264,7 +265,7 @@ private void invokeAapt1(File apkFile, File manifest, File resDir, File rawDir, } // force package id so that some frameworks build with correct id // disable if user adds own aapt (can't know if they have this feature) - if (mApkInfo.packageInfo.forcedPackageId != null && ! customAapt && ! mApkInfo.sharedLibrary) { + if (mApkInfo.packageInfo.forcedPackageId != null && !mApkInfo.sharedLibrary && !customAapt) { cmd.add("--forced-package-id"); cmd.add(mApkInfo.packageInfo.forcedPackageId); } @@ -311,17 +312,18 @@ private void invokeAapt1(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-x"); } - if (mApkInfo.doNotCompress != null && !customAapt) { - // Use custom -e option to avoid limits on commandline length. - // Can only be used when custom aapt binary is not used. - String extensionsFilePath = - Objects.requireNonNull(createDoNotCompressExtensionsFile(mApkInfo)).getAbsolutePath(); - cmd.add("-e"); - cmd.add(extensionsFilePath); - } else if (mApkInfo.doNotCompress != null) { - for (String file : mApkInfo.doNotCompress) { - cmd.add("-0"); - cmd.add(file); + if (!mApkInfo.doNotCompress.isEmpty()) { + if (customAapt) { + for (String file : mApkInfo.doNotCompress) { + cmd.add("-0"); + cmd.add(file); + } + } else { + // Use custom -e option to avoid limits on commandline length. + // Can only be used when custom aapt binary is not used. + String extensionsFilePath = createDoNotCompressExtensionsFile(mApkInfo.doNotCompress); + cmd.add("-e"); + cmd.add(extensionsFilePath); } } @@ -360,25 +362,21 @@ private void invokeAapt1(File apkFile, File manifest, File resDir, File rawDir, } } - public void invokeAapt(File apkFile, File manifest, File resDir, File rawDir, File assetDir, File[] include) - throws AndrolibException { - - String aaptPath = mConfig.aaptPath; - boolean customAapt = !aaptPath.isEmpty(); - List cmd = new ArrayList<>(); - + private String createDoNotCompressExtensionsFile(Collection doNotCompress) throws AndrolibException { try { - String aaptCommand = AaptManager.getAaptExecutionCommand(aaptPath, getAaptBinaryFile()); - cmd.add(aaptCommand); - } catch (BrutException ex) { - LOGGER.warning("aapt: " + ex.getMessage() + " (defaulting to $PATH binary)"); - cmd.add(AaptManager.getAaptBinaryName(getAaptVersion())); - } + File doNotCompressFile = File.createTempFile("APKTOOL", null); + doNotCompressFile.deleteOnExit(); - if (mConfig.isAapt2()) { - invokeAapt2(apkFile, manifest, resDir, rawDir, assetDir, include, cmd, customAapt); - return; + BufferedWriter fileWriter = new BufferedWriter(new FileWriter(doNotCompressFile)); + for (String extension : doNotCompress) { + fileWriter.write(extension); + fileWriter.newLine(); + } + fileWriter.close(); + + return doNotCompressFile.getAbsolutePath(); + } catch (IOException ex) { + throw new AndrolibException(ex); } - invokeAapt1(apkFile, manifest, resDir, rawDir, assetDir, include, cmd, customAapt); } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index 5c9e3de4a2..91dc20ec07 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -31,6 +31,7 @@ import brut.directory.DirectoryException; import brut.directory.ExtFile; import brut.directory.ZipUtils; +import brut.util.AaptManager; import brut.util.BrutIO; import brut.util.OS; import org.apache.commons.io.FileUtils; @@ -44,8 +45,6 @@ import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Logger; -import java.util.zip.CRC32; -import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ApkBuilder { @@ -58,17 +57,6 @@ public class ApkBuilder { private ApkInfo mApkInfo; private int mMinSdkVersion = 0; - private final static String APK_DIRNAME = "build/apk"; - private final static String UNK_DIRNAME = "unknown"; - private final static String[] APK_RESOURCES_FILENAMES = new String[] { - "resources.arsc", "AndroidManifest.xml", "res", "r", "R" }; - private final static String[] APK_RESOURCES_WITHOUT_RES_FILENAMES = new String[] { - "resources.arsc", "AndroidManifest.xml" }; - private final static String[] APP_RESOURCES_FILENAMES = new String[] { - "AndroidManifest.xml", "res" }; - private final static String[] APK_MANIFEST_FILENAMES = new String[] { - "AndroidManifest.xml" }; - public ApkBuilder(ExtFile apkDir) { this(Config.getDefaultConfig(), apkDir); } @@ -78,97 +66,121 @@ public ApkBuilder(Config config, ExtFile apkDir) { mApkDir = apkDir; } - public void build(File outFile) throws BrutException { - LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " with " + mConfig.jobs + " thread(s)."); + public void build(File outApk) throws AndrolibException { try { - mWorker = new BackgroundWorker(mConfig.jobs); + boolean isAsync = mConfig.jobs > 1; + mWorker = new BackgroundWorker(isAsync ? mConfig.jobs - 1 : 1); mApkInfo = ApkInfo.load(mApkDir); - if (mApkInfo.getSdkInfo() != null && mApkInfo.getSdkInfo().get("minSdkVersion") != null) { - String minSdkVersion = mApkInfo.getSdkInfo().get("minSdkVersion"); + String minSdkVersion = mApkInfo.getMinSdkVersion(); + if (minSdkVersion != null) { mMinSdkVersion = mApkInfo.getMinSdkVersionFromAndroidCodename(minSdkVersion); } - if (outFile == null) { + if (outApk == null) { String outFileName = mApkInfo.apkFileName; - outFile = new File(mApkDir, "dist" + File.separator + (outFileName == null ? "out.apk" : outFileName)); + if (outFileName == null) { + outFileName = "out.apk"; + } + outApk = new File(mApkDir, "dist" + File.separator + outFileName); } + File outDir = new File(mApkDir, "build" + File.separator + "apk"); //noinspection ResultOfMethodCallIgnored - new File(mApkDir, APK_DIRNAME).mkdirs(); + outDir.mkdirs(); + + LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + outApk.getName() + + (isAsync ? " with " + mConfig.jobs + " threads" : "")); + + buildSources(outDir, isAsync); + File manifest = new File(mApkDir, "AndroidManifest.xml"); - File manifestOriginal = new File(mApkDir, "AndroidManifest.xml.orig"); - - scheduleBuildDexFiles(); - backupManifestFile(manifest, manifestOriginal); - buildResources(); - copyLibs(); - copyOriginalFilesIfEnabled(); - mWorker.waitForFinish(); - if (mBuildError.get() != null) { - throw mBuildError.get(); + File manifestOrig = new File(mApkDir, "AndroidManifest.xml.orig"); + backupManifestFile(manifest, manifestOrig); + buildResources(outDir, manifest); + + if (isAsync) { + mWorker.waitForFinish(); + if (mBuildError.get() != null) { + throw mBuildError.get(); + } } - buildApk(outFile); + if (!mConfig.noApk) { + if (outApk.exists()) { + //noinspection ResultOfMethodCallIgnored + outApk.delete(); + } else { + File parentDir = outApk.getParentFile(); + if (parentDir != null && !parentDir.exists()) { + //noinspection ResultOfMethodCallIgnored + parentDir.mkdirs(); + } + } + + copyOriginalFiles(outDir); + + LOGGER.info("Building apk file..."); + + try (ZipOutputStream outStream = new ZipOutputStream(Files.newOutputStream(outApk.toPath()))) { + // zip aapt output files + try { + ZipUtils.zipDir(outDir, outStream, mApkInfo.doNotCompress); + } catch (IOException ex) { + throw new AndrolibException(ex); + } + + // zip remaining standard files + importRawFiles(outStream); + + // zip unknown files + importUnknownFiles(outStream); + } catch (IOException ex) { + throw new AndrolibException(ex); + } + + LOGGER.info("Built apk into: " + outApk.getPath()); + } // we copied the AndroidManifest.xml to AndroidManifest.xml.orig so we can edit it // lets restore the unedited one, to not change the original - if (manifest.isFile() && manifest.exists() && manifestOriginal.isFile()) { + if (manifest.isFile() && manifestOrig.isFile()) { try { - if (new File(mApkDir, "AndroidManifest.xml").delete()) { - FileUtils.moveFile(manifestOriginal, manifest); + if (manifest.delete()) { + FileUtils.moveFile(manifestOrig, manifest); } } catch (IOException ex) { - throw new AndrolibException(ex.getMessage()); + throw new AndrolibException(ex); } } - LOGGER.info("Built apk into: " + outFile.getPath()); } finally { mWorker.shutdownNow(); } } - private void backupManifestFile(File manifest, File manifestOriginal) throws AndrolibException { - // If we decoded in "raw", we cannot patch AndroidManifest - if (new File(mApkDir, "resources.arsc").exists()) { - return; + private void buildSources(File outDir, boolean isAsync) throws AndrolibException { + if (!copySourcesRaw(outDir, "classes.dex")) { + buildSourcesSmali(outDir, "smali", "classes.dex", isAsync); } - if (manifest.isFile() && manifest.exists()) { - try { - if (manifestOriginal.exists()) { - //noinspection ResultOfMethodCallIgnored - manifestOriginal.delete(); - } - FileUtils.copyFile(manifest, manifestOriginal); - ResXmlPatcher.fixingPublicAttrsInProviderAttributes(manifest); - } catch (IOException ex) { - throw new AndrolibException(ex.getMessage()); - } - } - } - private void scheduleBuildDexFiles() throws AndrolibException { try { - mWorker.submit(() -> scheduleDexBuild("classes.dex", "smali")); + Directory in = mApkDir.getDirectory(); // loop through any smali_ directories for multi-dex apks - Map dirs = mApkDir.getDirectory().getDirs(); - for (Map.Entry directory : dirs.entrySet()) { - String name = directory.getKey(); - if (name.startsWith("smali_")) { - String filename = name.substring(name.indexOf("_") + 1) + ".dex"; - mWorker.submit(() -> scheduleDexBuild(filename, name)); + for (String dirName : in.getDirs().keySet()) { + if (dirName.startsWith("smali_")) { + String fileName = dirName.substring(dirName.indexOf("_") + 1) + ".dex"; + if (!copySourcesRaw(outDir, fileName)) { + buildSourcesSmali(outDir, dirName, fileName, isAsync); + } } } // loop through any classes#.dex files for multi-dex apks - File[] dexFiles = mApkDir.listFiles(); - if (dexFiles != null) { - for (File dex : dexFiles) { - // skip classes.dex because we have handled it in buildSources() - if (dex.getName().endsWith(".dex") && !dex.getName().equalsIgnoreCase("classes.dex")) { - buildSourcesRaw(dex.getName()); - } + for (String fileName : in.getFiles()) { + // skip classes.dex because we have handled it + if (fileName.endsWith(".dex") && !fileName.equals("classes.dex")) { + copySourcesRaw(outDir, fileName); } } } catch (DirectoryException ex) { @@ -176,338 +188,320 @@ private void scheduleBuildDexFiles() throws AndrolibException { } } - private void scheduleDexBuild(String filename, String smali) { + private boolean copySourcesRaw(File outDir, String fileName) throws AndrolibException { + File working = new File(mApkDir, fileName); + if (!working.isFile()) { + return false; + } + + File stored = new File(outDir, fileName); + if (!mConfig.forceBuildAll && !isModified(working, stored)) { + return true; + } + + LOGGER.info("Copying raw " + fileName + " file..."); try { - if (mBuildError.get() != null) { - return; - } - if (!buildSourcesRaw(filename) && !buildSourcesSmali(smali, filename)) { - LOGGER.warning("Could not find sources"); - } - } catch (AndrolibException e) { - mBuildError.compareAndSet(null, e); + BrutIO.copyAndClose(Files.newInputStream(working.toPath()), Files.newOutputStream(stored.toPath())); + } catch (IOException ex) { + throw new AndrolibException(ex); } + return true; } - private boolean buildSourcesRaw(String filename) throws AndrolibException { - File working = new File(mApkDir, filename); - if (!working.exists()) { - return false; + private void buildSourcesSmali(File outDir, String dirName, String fileName, boolean isAsync) + throws AndrolibException { + if (isAsync) { + mWorker.submit(() -> { + if (mBuildError.get() == null) { + try { + buildSourcesSmali(outDir, dirName, fileName); + } catch (AndrolibException ex) { + mBuildError.compareAndSet(null, ex); + } + } + }); + } else { + buildSourcesSmali(outDir, dirName, fileName); } - File stored = new File(mApkDir, APK_DIRNAME + "/" + filename); - if (mConfig.forceBuildAll || isModified(working, stored)) { - LOGGER.info("Copying " + mApkDir.toString() + " " + filename + " file..."); - try { - BrutIO.copyAndClose(Files.newInputStream(working.toPath()), Files.newOutputStream(stored.toPath())); - return true; - } catch (IOException ex) { - throw new AndrolibException(ex); + } + + private void buildSourcesSmali(File outDir, String dirName, String fileName) throws AndrolibException { + File smaliDir = new File(mApkDir, dirName); + if (!smaliDir.isDirectory()) { + return; + } + + File dex = new File(outDir, fileName); + if (!mConfig.forceBuildAll) { + LOGGER.info("Checking whether sources have changed..."); + if (!isModified(smaliDir, dex)) { + return; } } - return true; + //noinspection ResultOfMethodCallIgnored + dex.delete(); + + int apiLevel = mConfig.apiLevel > 0 ? mConfig.apiLevel : mMinSdkVersion; + + LOGGER.info("Smaling " + dirName + " folder into " + fileName + "..."); + SmaliBuilder.build(smaliDir, dex, apiLevel); } - private boolean buildSourcesSmali(String folder, String filename) throws AndrolibException { - ExtFile smaliDir = new ExtFile(mApkDir, folder); - if (!smaliDir.exists()) { - return false; + private void backupManifestFile(File manifest, File manifestOrig) throws AndrolibException { + // if we decoded in "raw", we cannot patch AndroidManifest + if (new File(mApkDir, "resources.arsc").isFile()) { + return; } - File dex = new File(mApkDir, APK_DIRNAME + "/" + filename); - if (!mConfig.forceBuildAll) { - LOGGER.info("Checking whether sources has changed..."); + + if (!manifest.isFile()) { + return; } - if (mConfig.forceBuildAll || isModified(smaliDir, dex)) { - LOGGER.info("Smaling " + folder + " folder into " + filename + "..."); + + if (manifestOrig.exists()) { //noinspection ResultOfMethodCallIgnored - dex.delete(); - SmaliBuilder.build(smaliDir, dex, mConfig.apiLevel > 0 ? mConfig.apiLevel : mMinSdkVersion); + manifestOrig.delete(); + } + + try { + FileUtils.copyFile(manifest, manifestOrig); + ResXmlPatcher.fixingPublicAttrsInProviderAttributes(manifest); + } catch (IOException ex) { + throw new AndrolibException(ex); } - return true; } - private void buildResources() throws BrutException { - // create res folder, manifest file and resources.arsc - if (!buildResourcesRaw() && !buildResourcesFull() && !buildManifest()) { - LOGGER.warning("Could not find resources"); + private void buildResources(File outDir, File manifest) throws AndrolibException { + if (!manifest.isFile()) { + LOGGER.fine("Could not find AndroidManifest.xml"); + return; + } + + if (new File(mApkDir, "resources.arsc").isFile()) { + copyResourcesRaw(outDir, manifest); + } else if (new File(mApkDir, "res").isDirectory()) { + buildResourcesFull(outDir, manifest); + } else { + LOGGER.fine("Could not find resources"); + buildManifest(outDir, manifest); } } - private boolean buildResourcesRaw() throws AndrolibException { - try { - if (!new File(mApkDir, "resources.arsc").exists()) { - return false; - } - File apkDir = new File(mApkDir, APK_DIRNAME); - if (!mConfig.forceBuildAll) { - LOGGER.info("Checking whether resources has changed..."); - } - if (mConfig.forceBuildAll || isModified(newFiles(APK_RESOURCES_FILENAMES, mApkDir), - newFiles(APK_RESOURCES_FILENAMES, apkDir))) { - LOGGER.info("Copying raw resources..."); - mApkDir.getDirectory().copyToDir(apkDir, APK_RESOURCES_FILENAMES); + private void copyResourcesRaw(File outDir, File manifest) throws AndrolibException { + if (!mConfig.forceBuildAll) { + LOGGER.info("Checking whether resources have changed..."); + if (!isModified(manifest, new File(outDir, "AndroidManifest.xml")) + && !isModified(new File(mApkDir, "resources.arsc"), new File(outDir, "resources.arsc")) + && !isModified(newFiles(mApkDir, ApkInfo.RESOURCES_DIRNAMES), + newFiles(outDir, ApkInfo.RESOURCES_DIRNAMES))) { + return; } - return true; + } + + LOGGER.info("Copying raw resources..."); + try { + Directory in = mApkDir.getDirectory(); + + in.copyToDir(outDir, "AndroidManifest.xml"); + in.copyToDir(outDir, "resources.arsc"); + in.copyToDir(outDir, ApkInfo.RESOURCES_DIRNAMES); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - private boolean buildResourcesFull() throws AndrolibException { - try { - if (!new File(mApkDir, "res").exists()) { - return false; - } - if (!mConfig.forceBuildAll) { - LOGGER.info("Checking whether resources has changed..."); + private void buildResourcesFull(File outDir, File manifest) throws AndrolibException { + File resourcesFile = new File(outDir.getParentFile(), "resources.zip"); + if (!mConfig.forceBuildAll) { + LOGGER.info("Checking whether resources have changed..."); + if (!isModified(manifest, new File(outDir, "AndroidManifest.xml")) + && !isModified(newFiles(mApkDir, ApkInfo.RESOURCES_DIRNAMES), + newFiles(outDir, ApkInfo.RESOURCES_DIRNAMES)) + && (mConfig.aaptVersion == 1 || resourcesFile.isFile())) { + return; } - File apkDir = new File(mApkDir, APK_DIRNAME); - File resourceFile = new File(apkDir.getParent(), "resources.zip"); - - if (mConfig.forceBuildAll || isModified(newFiles(APP_RESOURCES_FILENAMES, mApkDir), - newFiles(APK_RESOURCES_FILENAMES, apkDir)) || (mConfig.isAapt2() && !isFile(resourceFile))) { - LOGGER.info("Building resources..."); - - if (mConfig.debugMode) { - if (mConfig.isAapt2()) { - LOGGER.info("Using aapt2 - setting 'debuggable' attribute to 'true' in AndroidManifest.xml"); - ResXmlPatcher.setApplicationDebugTagTrue(new File(mApkDir, "AndroidManifest.xml")); - } else { - ResXmlPatcher.removeApplicationDebugTag(new File(mApkDir, "AndroidManifest.xml")); - } - } + } + //noinspection ResultOfMethodCallIgnored + resourcesFile.delete(); - if (mConfig.netSecConf) { - ApkInfo meta = ApkInfo.load(new ExtFile(mApkDir)); - if (meta.getSdkInfo() != null && meta.getSdkInfo().get("targetSdkVersion") != null) { - if (Integer.parseInt(meta.getSdkInfo().get("targetSdkVersion")) < ResConfigFlags.SDK_NOUGAT) { - LOGGER.warning("Target SDK version is lower than 24! Network Security Configuration might be ignored!"); - } - } - File netSecConfOrig = new File(mApkDir, "res/xml/network_security_config.xml"); - if (netSecConfOrig.exists()) { - LOGGER.info("Replacing existing network_security_config.xml!"); - //noinspection ResultOfMethodCallIgnored - netSecConfOrig.delete(); - } - ResXmlPatcher.modNetworkSecurityConfig(netSecConfOrig); - ResXmlPatcher.setNetworkSecurityConfig(new File(mApkDir, "AndroidManifest.xml")); - LOGGER.info("Added permissive network security config in manifest"); + try { + if (mConfig.debugMode) { + if (mConfig.aaptVersion == 2) { + LOGGER.info("Using aapt2 - setting 'debuggable' attribute to 'true' in AndroidManifest.xml"); + ResXmlPatcher.setApplicationDebugTagTrue(manifest); + } else { + ResXmlPatcher.removeApplicationDebugTag(manifest); } + } - File apkFile = File.createTempFile("APKTOOL", null); - //noinspection ResultOfMethodCallIgnored - apkFile.delete(); - //noinspection ResultOfMethodCallIgnored - resourceFile.delete(); - - File ninePatch = new File(mApkDir, "9patch"); - if (!ninePatch.exists()) { - ninePatch = null; + if (mConfig.netSecConf) { + String targetSdkVersion = mApkInfo.getTargetSdkVersion(); + if (targetSdkVersion != null) { + if (Integer.parseInt(targetSdkVersion) < ResConfigFlags.SDK_NOUGAT) { + LOGGER.warning("Target SDK version is lower than 24! Network Security Configuration might be ignored!"); + } } - AaptInvoker invoker = new AaptInvoker(mConfig, mApkInfo); - invoker.invokeAapt(apkFile, new File(mApkDir, "AndroidManifest.xml"), - new File(mApkDir, "res"), ninePatch, null, getIncludeFiles()); - - ExtFile tmpExtFile = new ExtFile(apkFile); - Directory tmpDir = tmpExtFile.getDirectory(); - // Sometimes an application is built with a resources.arsc file with no resources, - // Apktool assumes it will have a rebuilt arsc file, when it doesn't. So if we - // encounter a copy error, move to a warning and continue on. (#1730) - try { - tmpDir.copyToDir(apkDir, - tmpDir.containsDir("res") ? APK_RESOURCES_FILENAMES - : APK_RESOURCES_WITHOUT_RES_FILENAMES); - } catch (DirectoryException ex) { - LOGGER.warning(ex.getMessage()); - } finally { - tmpExtFile.close(); + File netSecConfOrig = new File(mApkDir, "res/xml/network_security_config.xml"); + if (netSecConfOrig.exists()) { + LOGGER.info("Replacing existing network_security_config.xml!"); + //noinspection ResultOfMethodCallIgnored + netSecConfOrig.delete(); } - // delete tmpDir - //noinspection ResultOfMethodCallIgnored - apkFile.delete(); + ResXmlPatcher.modNetworkSecurityConfig(netSecConfOrig); + ResXmlPatcher.setNetworkSecurityConfig(manifest); + LOGGER.info("Added permissive network security config in manifest"); } - return true; - } catch (IOException | BrutException | ParserConfigurationException | TransformerException | SAXException ex) { + } catch (IOException | ParserConfigurationException | TransformerException | SAXException ex) { throw new AndrolibException(ex); } - } - private boolean buildManifestRaw() throws AndrolibException { + ExtFile tmpFile; try { - File apkDir = new File(mApkDir, APK_DIRNAME); - LOGGER.info("Copying raw AndroidManifest.xml..."); - mApkDir.getDirectory().copyToDir(apkDir, APK_MANIFEST_FILENAMES); - return true; - } catch (DirectoryException ex) { + tmpFile = new ExtFile(File.createTempFile("APKTOOL", null)); + } catch (IOException ex) { throw new AndrolibException(ex); } - } + //noinspection ResultOfMethodCallIgnored + tmpFile.delete(); + + File resDir = new File(mApkDir, "res"); + File ninePatch = new File(mApkDir, "9patch"); + if (!ninePatch.isDirectory()) { + ninePatch = null; + } + + LOGGER.info("Building resources with " + AaptManager.getAaptBinaryName(mConfig.aaptVersion) + "..."); - private boolean buildManifest() throws BrutException { try { - if (!new File(mApkDir, "AndroidManifest.xml").exists()) { - return false; - } - if (!mConfig.forceBuildAll) { - LOGGER.info("Checking whether resources has changed..."); - } + AaptInvoker invoker = new AaptInvoker(mConfig, mApkInfo); + invoker.invokeAapt(tmpFile, manifest, resDir, ninePatch, null, getIncludeFiles()); - File apkDir = new File(mApkDir, APK_DIRNAME); + Directory tmpDir = tmpFile.getDirectory(); + tmpDir.copyToDir(outDir, "AndroidManifest.xml"); + tmpDir.copyToDir(outDir, "resources.arsc"); + tmpDir.copyToDir(outDir, ApkInfo.RESOURCES_DIRNAMES); + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } finally { + //noinspection ResultOfMethodCallIgnored + tmpFile.delete(); + } + } - if (mConfig.forceBuildAll || isModified(newFiles(APK_MANIFEST_FILENAMES, mApkDir), - newFiles(APK_MANIFEST_FILENAMES, apkDir))) { - LOGGER.info("Building AndroidManifest.xml..."); + private void buildManifest(File outDir, File manifest) throws AndrolibException { + if (!mConfig.forceBuildAll) { + LOGGER.info("Checking whether AndroidManifest.xml has changed..."); + if (!isModified(manifest, new File(outDir, "AndroidManifest.xml"))) { + return; + } + } - File apkFile = File.createTempFile("APKTOOL", null); - //noinspection ResultOfMethodCallIgnored - apkFile.delete(); + ExtFile tmpFile; + try { + tmpFile = new ExtFile(File.createTempFile("APKTOOL", null)); + } catch (IOException ex) { + throw new AndrolibException(ex); + } + //noinspection ResultOfMethodCallIgnored + tmpFile.delete(); - File ninePatch = new File(mApkDir, "9patch"); - if (!ninePatch.exists()) { - ninePatch = null; - } + File ninePatch = new File(mApkDir, "9patch"); + if (!ninePatch.isDirectory()) { + ninePatch = null; + } - AaptInvoker invoker = new AaptInvoker(mConfig, mApkInfo); - invoker.invokeAapt(apkFile, new File(mApkDir, "AndroidManifest.xml"), - null, ninePatch, null, getIncludeFiles()); + LOGGER.info("Building AndroidManifest.xml with " + AaptManager.getAaptBinaryName(mConfig.aaptVersion) + "..."); - Directory tmpDir = new ExtFile(apkFile).getDirectory(); - tmpDir.copyToDir(apkDir, APK_MANIFEST_FILENAMES); + try { + AaptInvoker invoker = new AaptInvoker(mConfig, mApkInfo); + invoker.invokeAapt(tmpFile, manifest, null, ninePatch, null, getIncludeFiles()); - //noinspection ResultOfMethodCallIgnored - apkFile.delete(); - } - return true; - } catch (IOException | DirectoryException ex) { + Directory tmpDir = tmpFile.getDirectory(); + tmpDir.copyToDir(outDir, "AndroidManifest.xml"); + } catch (DirectoryException ex) { throw new AndrolibException(ex); } catch (AndrolibException ex) { LOGGER.warning("Parse AndroidManifest.xml failed, treat it as raw file."); - return buildManifestRaw(); + copyManifestRaw(outDir); + } finally { + //noinspection ResultOfMethodCallIgnored + tmpFile.delete(); } } - private void copyLibs() throws AndrolibException { - buildLibrary("lib"); - buildLibrary("libs"); - buildLibrary("kotlin"); - buildLibrary("META-INF/services"); - } + private void copyManifestRaw(File outDir) throws AndrolibException { + LOGGER.info("Copying raw manifest..."); + try { + Directory in = mApkDir.getDirectory(); - private void buildLibrary(String folder) throws AndrolibException { - File working = new File(mApkDir, folder); + in.copyToDir(outDir, "AndroidManifest.xml"); + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } - if (!working.exists()) { + private void copyOriginalFiles(File outDir) throws AndrolibException { + if (!mConfig.copyOriginalFiles) { return; } - File stored = new File(mApkDir, APK_DIRNAME + "/" + folder); - if (mConfig.forceBuildAll || isModified(working, stored)) { - LOGGER.info("Copying libs... (/" + folder + ")"); - try { - OS.rmdir(stored); - OS.cpdir(working, stored); - } catch (BrutException ex) { - throw new AndrolibException(ex); - } + ExtFile originalDir = new ExtFile(mApkDir, "original"); + if (!originalDir.isDirectory()) { + return; } - } - private void copyOriginalFilesIfEnabled() throws AndrolibException { - if (mConfig.copyOriginalFiles) { - File originalDir = new File(mApkDir, "original"); - if (originalDir.exists()) { - try { - LOGGER.info("Copy original files..."); - Directory in = (new ExtFile(originalDir)).getDirectory(); - if (in.containsFile("AndroidManifest.xml")) { - LOGGER.info("Copy AndroidManifest.xml..."); - in.copyToDir(new File(mApkDir, APK_DIRNAME), "AndroidManifest.xml"); - } - if (in.containsFile("stamp-cert-sha256")) { - LOGGER.info("Copy stamp-cert-sha256..."); - in.copyToDir(new File(mApkDir, APK_DIRNAME), "stamp-cert-sha256"); - } - if (in.containsDir("META-INF")) { - LOGGER.info("Copy META-INF..."); - in.copyToDir(new File(mApkDir, APK_DIRNAME), "META-INF"); - } - } catch (DirectoryException ex) { - throw new AndrolibException(ex); + LOGGER.info("Copying original files..."); + try { + Directory in = originalDir.getDirectory(); + + for (String fileName : in.getFiles(true)) { + if (ApkInfo.ORIGINAL_FILENAMES_PATTERN.matcher(fileName).matches()) { + in.copyToDir(outDir, fileName); } } + } catch (DirectoryException ex) { + throw new AndrolibException(ex); } } - private void buildApk(File outApk) throws AndrolibException { - LOGGER.info("Building apk file..."); - if (outApk.exists()) { - //noinspection ResultOfMethodCallIgnored - outApk.delete(); - } else { - File outDir = outApk.getParentFile(); - if (outDir != null && !outDir.exists()) { - //noinspection ResultOfMethodCallIgnored - outDir.mkdirs(); + private void importRawFiles(ZipOutputStream outStream) throws AndrolibException { + for (String dirName : ApkInfo.RAW_DIRNAMES) { + File rawDir = new File(mApkDir, dirName); + if (!rawDir.isDirectory()) { + continue; } - } - File assetDir = new File(mApkDir, "assets"); - if (!assetDir.exists()) { - assetDir = null; - } - try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(outApk.toPath()))) { - // zip all AAPT-generated files - ZipUtils.zipFoldersPreserveStream(new File(mApkDir, APK_DIRNAME), zipOutputStream, assetDir, mApkInfo.doNotCompress); - // we must copy some files manually - // this is because Aapt won't add files it doesn't know (ex unknown files) - if (mApkInfo.unknownFiles != null) { - LOGGER.info("Copying unknown files/dir..."); - copyUnknownFiles(zipOutputStream, mApkInfo.unknownFiles); + LOGGER.info("Importing " + dirName + "..."); + try { + ZipUtils.zipDir(mApkDir, dirName, outStream, mApkInfo.doNotCompress); + } catch (IOException ex) { + throw new AndrolibException(ex); } - } catch (IOException | BrutException e) { - throw new AndrolibException(e); } } - private void copyUnknownFiles(ZipOutputStream outputFile, Map files) - throws BrutException, IOException { - File unknownFileDir = new File(mApkDir, UNK_DIRNAME); - - // loop through unknown files - for (Map.Entry unknownFileInfo : files.entrySet()) { - File inputFile; + private void importUnknownFiles(ZipOutputStream outStream) throws AndrolibException { + Map unknownFiles = mApkInfo.unknownFiles; + if (unknownFiles == null || unknownFiles.isEmpty()) { + return; + } - try { - inputFile = new File(unknownFileDir, BrutIO.sanitizeFilepath(unknownFileDir, unknownFileInfo.getKey())); - } catch (RootUnknownFileException | InvalidUnknownFileException | TraversalUnknownFileException exception) { - LOGGER.warning(String.format("Skipping file %s (%s)", unknownFileInfo.getKey(), exception.getMessage())); - continue; - } + File unknownDir = new File(mApkDir, "unknown"); + if (!unknownDir.isDirectory()) { + return; + } - if (inputFile.isDirectory()) { - continue; - } + LOGGER.info("Importing unknown files..."); + for (String fileName : unknownFiles.keySet()) { + boolean doNotCompress = Integer.parseInt(unknownFiles.get(fileName)) == 0; - ZipEntry newEntry = new ZipEntry(unknownFileInfo.getKey()); - int method = Integer.parseInt(unknownFileInfo.getValue()); - LOGGER.fine(String.format("Copying unknown file %s with method %d", unknownFileInfo.getKey(), method)); - if (method == ZipEntry.STORED) { - newEntry.setMethod(ZipEntry.STORED); - newEntry.setSize(inputFile.length()); - newEntry.setCompressedSize(-1); - BufferedInputStream unknownFile = new BufferedInputStream(Files.newInputStream(inputFile.toPath())); - CRC32 crc = BrutIO.calculateCrc(unknownFile); - newEntry.setCrc(crc.getValue()); - unknownFile.close(); - } else { - newEntry.setMethod(ZipEntry.DEFLATED); + LOGGER.fine("Importing unknown file " + fileName + " (" + (doNotCompress ? "stored" : "deflated") + ")"); + try { + ZipUtils.zipFile(unknownDir, fileName, outStream, doNotCompress); + } catch (IOException ex) { + LOGGER.warning("Skipping file " + fileName + " (" + ex.getMessage() + ")"); } - outputFile.putNextEntry(newEntry); - - BrutIO.copy(inputFile, outputFile); - outputFile.closeEntry(); } } @@ -533,11 +527,7 @@ private File[] getIncludeFiles() throws AndrolibException { } private boolean isModified(File working, File stored) { - return !stored.exists() || BrutIO.recursiveModifiedTime(working) > BrutIO .recursiveModifiedTime(stored); - } - - private boolean isFile(File working) { - return working.exists(); + return !stored.exists() || BrutIO.recursiveModifiedTime(working) > BrutIO.recursiveModifiedTime(stored); } private boolean isModified(File[] working, File[] stored) { @@ -549,29 +539,11 @@ private boolean isModified(File[] working, File[] stored) { return BrutIO.recursiveModifiedTime(working) > BrutIO.recursiveModifiedTime(stored); } - private File[] newFiles(String[] names, File dir) { + private File[] newFiles(File dir, String[] names) { File[] files = new File[names.length]; for (int i = 0; i < names.length; i++) { files[i] = new File(dir, names[i]); } return files; } - - public boolean detectWhetherAppIsFramework() throws AndrolibException { - File publicXml = new File(mApkDir, "res/values/public.xml"); - if (!publicXml.exists()) { - return false; - } - - Iterator it; - try { - it = IOUtils.lineIterator(new FileReader(new File(mApkDir, "res/values/public.xml"))); - } catch (FileNotFoundException ex) { - throw new AndrolibException( - "Could not detect whether app is framework one", ex); - } - it.next(); - it.next(); - return it.next().contains("0x01"); - } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 1f328fbefc..2bbd4cbb1b 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -39,53 +39,38 @@ public class ApkDecoder { private final static Logger LOGGER = Logger.getLogger(ApkDecoder.class.getName()); - private final AtomicReference mBuildError = new AtomicReference<>(null); + // extensions of files that are often packed uncompressed + public final static Pattern NO_COMPRESS_EXT_PATTERN = Pattern.compile( + "dex|so|jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|" + + "imy|xmf|mp4|m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv"); + + private final AtomicReference mBuildError = new AtomicReference<>(null); private final Config mConfig; - private final ApkInfo mApkInfo; - private volatile int mMinSdkVersion = 0; + private final ExtFile mApkFile; private BackgroundWorker mWorker; - - private final static String SMALI_DIRNAME = "smali"; - private final static String UNK_DIRNAME = "unknown"; - private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] { - "classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "r", "R", - "lib", "libs", "assets", "META-INF", "kotlin", "stamp-cert-sha256" }; - private final static String[] APK_RESOURCES_FILENAMES = new String[] { - "resources.arsc", "res", "r", "R" }; - private final static String[] APK_MANIFEST_FILENAMES = new String[] { - "AndroidManifest.xml" }; - private final static Pattern NO_COMPRESS_PATTERN = Pattern.compile("(" + - "jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|imy|xmf|mp4|" + - "m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv)$"); - - public ApkDecoder(File apkFile) { - this(Config.getDefaultConfig(), new ExtFile(apkFile)); - } + private ApkInfo mApkInfo; + private volatile int mMinSdkVersion = 0; public ApkDecoder(ExtFile apkFile) { this(Config.getDefaultConfig(), apkFile); } - public ApkDecoder(Config config, File apkFile) { - this(config, new ExtFile(apkFile)); - } - public ApkDecoder(Config config, ExtFile apkFile) { mConfig = config; - mApkInfo = new ApkInfo(apkFile); + mApkFile = apkFile; } - public ApkInfo decode(File outDir) throws AndrolibException, IOException, DirectoryException { - ExtFile apkFile = mApkInfo.getApkFile(); + public ApkInfo decode(File outDir) throws AndrolibException { + if (!mConfig.forceDelete && outDir.exists()) { + throw new OutDirExistsException(); + } + if (!mApkFile.isFile() || !mApkFile.canRead()) { + throw new InFileNotFoundException(); + } try { - mWorker = new BackgroundWorker(mConfig.jobs); - if (!mConfig.forceDelete && outDir.exists()) { - throw new OutDirExistsException(); - } - - if (!apkFile.isFile() || !apkFile.canRead()) { - throw new InFileNotFoundException(); - } + boolean isAsync = mConfig.jobs > 1; + mWorker = new BackgroundWorker(isAsync ? mConfig.jobs - 1 : 1); + mApkInfo = new ApkInfo(mApkFile); try { OS.rmdir(outDir); @@ -95,245 +80,240 @@ public ApkInfo decode(File outDir) throws AndrolibException, IOException, Direct //noinspection ResultOfMethodCallIgnored outDir.mkdirs(); - LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkInfo.apkFileName + - " with " + mConfig.jobs + " thread(s)."); - - if (mApkInfo.hasSources()) { - switch (mConfig.decodeSources) { - case Config.DECODE_SOURCES_NONE: - copySourcesRaw(outDir, "classes.dex"); - break; - case Config.DECODE_SOURCES_SMALI: - case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: - scheduleDecodeSourcesSmali(outDir, "classes.dex"); - break; - } - } - - if (mApkInfo.hasMultipleSources()) { - // foreach unknown dex file in root, lets disassemble it - Set files = apkFile.getDirectory().getFiles(true); - for (String file : files) { - if (file.endsWith(".dex")) { - if (!file.equalsIgnoreCase("classes.dex")) { - switch(mConfig.decodeSources) { - case Config.DECODE_SOURCES_NONE: - copySourcesRaw(outDir, file); - break; - case Config.DECODE_SOURCES_SMALI: - scheduleDecodeSourcesSmali(outDir, file); - break; - case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: - if (file.startsWith("classes") && file.endsWith(".dex")) { - scheduleDecodeSourcesSmali(outDir, file); - } else { - copySourcesRaw(outDir, file); - } - break; - } - } - } - } - } + LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName() + + (isAsync ? " with " + mConfig.jobs + " threads" : "")); - ResourcesDecoder resourcesDecoder = new ResourcesDecoder(mConfig, mApkInfo); + decodeSources(outDir, isAsync); - if (mApkInfo.hasResources()) { - switch (mConfig.decodeResources) { - case Config.DECODE_RESOURCES_NONE: - copyResourcesRaw(outDir); - break; - case Config.DECODE_RESOURCES_FULL: - resourcesDecoder.decodeResources(outDir); - break; - } - } + ResourcesDecoder resDecoder = new ResourcesDecoder(mConfig, mApkInfo); + decodeResources(outDir, resDecoder); + decodeManifest(outDir, resDecoder); + updateApkInfo(outDir, resDecoder); - if (mApkInfo.hasManifest()) { - if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL || - mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) { - resourcesDecoder.decodeManifest(outDir); - } - else { - copyManifestRaw(outDir); + if (isAsync) { + mWorker.waitForFinish(); + if (mBuildError.get() != null) { + throw mBuildError.get(); } } - resourcesDecoder.updateApkInfo(outDir); + copyOriginalFiles(outDir); copyRawFiles(outDir); copyUnknownFiles(outDir); - recordUncompressedFiles(resourcesDecoder.getResFileMapping()); - copyOriginalFiles(outDir); - mWorker.waitForFinish(); - if (mBuildError.get() != null) { - throw mBuildError.get(); - } - - // In case we have no resources. We should store the minSdk we pulled from the source opcode api level - if (!mApkInfo.hasResources() && mMinSdkVersion > 0) { - mApkInfo.setSdkInfoField("minSdkVersion", Integer.toString(mMinSdkVersion)); - } - writeApkInfo(outDir); return mApkInfo; } finally { mWorker.shutdownNow(); try { - apkFile.close(); + mApkFile.close(); } catch (IOException ignored) {} } } - private void writeApkInfo(File outDir) throws AndrolibException { - mApkInfo.save(new File(outDir, "apktool.yml")); - } + private void decodeSources(File outDir, boolean isAsync) throws AndrolibException { + if (!mApkInfo.hasSources()) { + return; + } - private void copyManifestRaw(File outDir) throws AndrolibException { - try { - LOGGER.info("Copying raw manifest..."); - mApkInfo.getApkFile().getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); + switch (mConfig.decodeSources) { + case Config.DECODE_SOURCES_NONE: + copySourcesRaw(outDir, "classes.dex"); + break; + case Config.DECODE_SOURCES_SMALI: + case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: + decodeSourcesSmali(outDir, "classes.dex", isAsync); + break; } - } - private void copyResourcesRaw(File outDir) throws AndrolibException { try { - LOGGER.info("Copying raw resources..."); - mApkInfo.getApkFile().getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES); + Directory in = mApkFile.getDirectory(); + + // foreach unknown dex file in root, lets disassemble it + for (String fileName : in.getFiles(true)) { + if (fileName.endsWith(".dex") && !fileName.equals("classes.dex")) { + switch (mConfig.decodeSources) { + case Config.DECODE_SOURCES_NONE: + copySourcesRaw(outDir, fileName); + break; + case Config.DECODE_SOURCES_SMALI: + decodeSourcesSmali(outDir, fileName, isAsync); + break; + case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: + if (fileName.startsWith("classes")) { + decodeSourcesSmali(outDir, fileName, isAsync); + } else { + copySourcesRaw(outDir, fileName); + } + break; + } + } + } } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - private void copySourcesRaw(File outDir, String filename) throws AndrolibException { + private void copySourcesRaw(File outDir, String fileName) throws AndrolibException { + LOGGER.info("Copying raw " + fileName + " file..."); try { - LOGGER.info("Copying raw " + filename + " file..."); - mApkInfo.getApkFile().getDirectory().copyToDir(outDir, filename); + Directory in = mApkFile.getDirectory(); + + in.copyToDir(outDir, fileName); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - private void scheduleDecodeSourcesSmali(File outDir, String filename) { - mWorker.submit(() -> { - try { - decodeSourcesSmali(outDir, filename); - } catch (AndrolibException e) { - mBuildError.compareAndSet(null, new RuntimeException(e)); - } - }); + private void decodeSourcesSmali(File outDir, String fileName, boolean isAsync) throws AndrolibException { + if (isAsync) { + mWorker.submit(() -> { + if (mBuildError.get() == null) { + try { + decodeSourcesSmali(outDir, fileName); + } catch (AndrolibException ex) { + mBuildError.compareAndSet(null, ex); + } + } + }); + } else { + decodeSourcesSmali(outDir, fileName); + } } - private void decodeSourcesSmali(File outDir, String filename) throws AndrolibException { + private void decodeSourcesSmali(File outDir, String fileName) throws AndrolibException { + File smaliDir; + if (fileName.equals("classes.dex")) { + smaliDir = new File(outDir, "smali"); + } else { + smaliDir = new File(outDir, "smali_" + fileName.substring(0, fileName.indexOf("."))); + } try { - File smaliDir; - if (filename.equalsIgnoreCase("classes.dex")) { - smaliDir = new File(outDir, SMALI_DIRNAME); - } else { - smaliDir = new File(outDir, SMALI_DIRNAME + "_" + filename.substring(0, filename.indexOf("."))); - } OS.rmdir(smaliDir); - //noinspection ResultOfMethodCallIgnored - smaliDir.mkdirs(); - LOGGER.info("Baksmaling " + filename + "..."); - DexFile dexFile = SmaliDecoder.decode(mApkInfo.getApkFile(), smaliDir, filename, - mConfig.baksmaliDebugMode, mConfig.apiLevel); - int minSdkVersion = dexFile.getOpcodes().api; - if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) { - mMinSdkVersion = minSdkVersion; - } } catch (BrutException ex) { throw new AndrolibException(ex); } + //noinspection ResultOfMethodCallIgnored + smaliDir.mkdirs(); + + LOGGER.info("Baksmaling " + fileName + "..."); + DexFile dexFile = SmaliDecoder.decode(mApkFile, smaliDir, fileName, + mConfig.baksmaliDebugMode, mConfig.apiLevel); + + // record minSdkVersion for jars + int minSdkVersion = dexFile.getOpcodes().api; + if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) { + mMinSdkVersion = minSdkVersion; + } } - private void copyRawFiles(File outDir) throws AndrolibException { - LOGGER.info("Copying assets and libs..."); + private void decodeResources(File outDir, ResourcesDecoder resDecoder) throws AndrolibException { + if (!mApkInfo.hasResources()) { + return; + } + + switch (mConfig.decodeResources) { + case Config.DECODE_RESOURCES_NONE: + copyResourcesRaw(outDir); + break; + case Config.DECODE_RESOURCES_FULL: + resDecoder.decodeResources(outDir); + break; + } + } + + private void copyResourcesRaw(File outDir) throws AndrolibException { + LOGGER.info("Copying raw resources..."); try { - Directory in = mApkInfo.getApkFile().getDirectory(); + Directory in = mApkFile.getDirectory(); - if (mConfig.decodeAssets == Config.DECODE_ASSETS_FULL) { - if (in.containsDir("assets")) { - in.copyToDir(outDir, "assets"); - } - } - if (in.containsDir("lib")) { - in.copyToDir(outDir, "lib"); - } - if (in.containsDir("libs")) { - in.copyToDir(outDir, "libs"); - } - if (in.containsDir("kotlin")) { - in.copyToDir(outDir, "kotlin"); - } + in.copyToDir(outDir, "resources.arsc"); + in.copyToDir(outDir, ApkInfo.RESOURCES_DIRNAMES); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - private boolean isAPKFileNames(String file) { - for (String apkFile : APK_STANDARD_ALL_FILENAMES) { - if (file.startsWith("classes") && file.endsWith(".dex")) { - return true; - } + private void decodeManifest(File outDir, ResourcesDecoder resDecoder) throws AndrolibException { + if (!mApkInfo.hasManifest()) { + return; + } - if (apkFile.equals(file) || file.startsWith(apkFile + "/")) { - return true; - } + if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL + || mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) { + resDecoder.decodeManifest(outDir); + } else { + copyManifestRaw(outDir); } - return false; } - private void copyUnknownFiles(File outDir) throws AndrolibException { - LOGGER.info("Copying unknown files..."); - File unknownOut = new File(outDir, UNK_DIRNAME); + private void copyManifestRaw(File outDir) throws AndrolibException { + LOGGER.info("Copying raw manifest..."); try { - Directory unk = mApkInfo.getApkFile().getDirectory(); - - // loop all items in container recursively, ignoring any that are pre-defined by aapt - Set files = unk.getFiles(true); - for (String file : files) { - if (!isAPKFileNames(file) && !file.endsWith(".dex")) { + Directory in = mApkFile.getDirectory(); - // copy file out of archive into special "unknown" folder - unk.copyToDir(unknownOut, file); - // let's record the name of the file, and its compression type - // so that we may re-include it the same way - mApkInfo.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(file))); - } - } + in.copyToDir(outDir, "AndroidManifest.xml"); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - private void copyOriginalFiles(File outDir) throws AndrolibException { - LOGGER.info("Copying original files..."); - File originalDir = new File(outDir, "original"); - if (!originalDir.exists()) { - //noinspection ResultOfMethodCallIgnored - originalDir.mkdirs(); + private void updateApkInfo(File outDir, ResourcesDecoder resDecoder) throws AndrolibException { + resDecoder.updateApkInfo(outDir); + + // in case we have no resources, we should store the minSdk we pulled from the source opcode api level + if (!mApkInfo.hasResources() && mMinSdkVersion > 0) { + mApkInfo.setMinSdkVersion(Integer.toString(mMinSdkVersion)); } + // record uncompressed files try { - Directory in = mApkInfo.getApkFile().getDirectory(); - if (in.containsFile("AndroidManifest.xml")) { - in.copyToDir(originalDir, "AndroidManifest.xml"); + Map resFileMapping = resDecoder.getResFileMapping(); + Set uncompressedExts = new HashSet<>(); + Set uncompressedFiles = new HashSet<>(); + Directory in = mApkFile.getDirectory(); + + for (String fileName : in.getFiles(true)) { + if (in.getCompressionLevel(fileName) == 0) { + String ext; + if (in.getSize(fileName) > 0 + && !(ext = FilenameUtils.getExtension(fileName)).isEmpty() + && NO_COMPRESS_EXT_PATTERN.matcher(ext).matches()) { + uncompressedExts.add(ext); + } else { + uncompressedFiles.add(resFileMapping.getOrDefault(fileName, fileName)); + } + } } - if (in.containsFile("stamp-cert-sha256")) { - in.copyToDir(originalDir, "stamp-cert-sha256"); + + // exclude files with an already recorded extenstion + if (!uncompressedExts.isEmpty() && !uncompressedFiles.isEmpty()) { + Iterator it = uncompressedFiles.iterator(); + while (it.hasNext()) { + String fileName = it.next(); + String ext = FilenameUtils.getExtension(fileName); + if (uncompressedExts.contains(ext)) { + it.remove(); + } + } } - if (in.containsDir("META-INF")) { - in.copyToDir(originalDir, "META-INF"); - - if (in.containsDir("META-INF/services")) { - // If the original APK contains the folder META-INF/services folder - // that is used for service locators (like coroutines on android), - // copy it to the destination folder, so it does not get dropped. - LOGGER.info("Copying META-INF/services directory"); - in.copyToDir(outDir, "META-INF/services"); + + // update apk info + int doNotCompressSize = uncompressedExts.size() + uncompressedFiles.size(); + if (doNotCompressSize > 0) { + List doNotCompress = new ArrayList<>(doNotCompressSize); + if (!uncompressedExts.isEmpty()) { + List uncompressedExtsList = new ArrayList<>(uncompressedExts); + uncompressedExtsList.sort(null); + doNotCompress.addAll(uncompressedExtsList); + } + if (!uncompressedFiles.isEmpty()) { + List uncompressedFilesList = new ArrayList<>(uncompressedFiles); + uncompressedFilesList.sort(null); + doNotCompress.addAll(uncompressedFilesList); + } + if (!doNotCompress.isEmpty()) { + mApkInfo.doNotCompress = doNotCompress; } } } catch (DirectoryException ex) { @@ -341,36 +321,65 @@ private void copyOriginalFiles(File outDir) throws AndrolibException { } } - private void recordUncompressedFiles(Map resFileMapping) throws AndrolibException { + private void copyRawFiles(File outDir) throws AndrolibException { try { - List uncompressedFilesOrExts = new ArrayList<>(); - Directory unk = mApkInfo.getApkFile().getDirectory(); - Set files = unk.getFiles(true); - - for (String file : files) { - if (isAPKFileNames(file) && unk.getCompressionLevel(file) == 0) { - String extOrFile = ""; - if (unk.getSize(file) != 0) { - extOrFile = FilenameUtils.getExtension(file); - } - - if (extOrFile.isEmpty() || !NO_COMPRESS_PATTERN.matcher(extOrFile).find()) { - extOrFile = file; - if (resFileMapping.containsKey(extOrFile)) { - extOrFile = resFileMapping.get(extOrFile); + Directory in = mApkFile.getDirectory(); + + for (String dirName : ApkInfo.RAW_DIRNAMES) { + if ((mConfig.decodeAssets == Config.DECODE_ASSETS_FULL || !dirName.equals("assets")) + && in.containsDir(dirName)) { + LOGGER.info("Copying " + dirName + "..."); + for (String fileName : in.getDir(dirName).getFiles(true)) { + fileName = dirName + "/" + fileName; + if (!ApkInfo.ORIGINAL_FILENAMES_PATTERN.matcher(fileName).matches()) { + in.copyToDir(outDir, fileName); } } - if (!uncompressedFilesOrExts.contains(extOrFile)) { - uncompressedFilesOrExts.add(extOrFile); - } } } - // update apk info - if (!uncompressedFilesOrExts.isEmpty()) { - mApkInfo.doNotCompress = uncompressedFilesOrExts; + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } + + private void copyOriginalFiles(File outDir) throws AndrolibException { + LOGGER.info("Copying original files..."); + try { + Directory in = mApkFile.getDirectory(); + File originalDir = new File(outDir, "original"); + + for (String fileName : in.getFiles(true)) { + if (ApkInfo.ORIGINAL_FILENAMES_PATTERN.matcher(fileName).matches()) { + in.copyToDir(originalDir, fileName); + } } } catch (DirectoryException ex) { throw new AndrolibException(ex); } } + + private void copyUnknownFiles(File outDir) throws AndrolibException { + LOGGER.info("Copying unknown files..."); + try { + Directory in = mApkFile.getDirectory(); + File unknownDir = new File(outDir, "unknown"); + + for (String fileName : in.getFiles(true)) { + if (!ApkInfo.STANDARD_FILENAMES_PATTERN.matcher(fileName).matches()) { + // copy file out of archive into special "unknown" folder + in.copyToDir(unknownDir, fileName); + // let's record the name of the file, and its compression type + // so that we may re-include it the same way + int compressionLevel = in.getCompressionLevel(fileName); + mApkInfo.addUnknownFileInfo(fileName, String.valueOf(compressionLevel)); + } + } + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } + + private void writeApkInfo(File outDir) throws AndrolibException { + mApkInfo.save(new File(outDir, "apktool.yml")); + } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApktoolProperties.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApktoolProperties.java index 10fcf31a34..b9caea6fde 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApktoolProperties.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApktoolProperties.java @@ -65,7 +65,7 @@ private static void loadProps() { properties.load(templateStream); version = properties.getProperty("application.version"); templateStream.close(); - } catch (IOException ignored) { } + } catch (IOException ignored) {} } sProps.put("baksmaliVersion", version); @@ -83,7 +83,7 @@ private static void loadProps() { properties.load(templateStream); version = properties.getProperty("application.version"); templateStream.close(); - } catch (IOException ignored) { } + } catch (IOException ignored) {} } sProps.put("smaliVersion", version); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/BackgroundWorker.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/BackgroundWorker.java index b30d715af2..1b702a2745 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/BackgroundWorker.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/BackgroundWorker.java @@ -34,8 +34,8 @@ public void waitForFinish() { for (Future future : mWorkerFutures) { try { future.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); + } catch (InterruptedException | ExecutionException ex) { + throw new RuntimeException(ex); } } mWorkerFutures.clear(); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java index 63d3cc9114..85e71a1c69 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java @@ -51,8 +51,8 @@ public class Config { public boolean verbose = false; public boolean copyOriginalFiles = false; public boolean updateFiles = false; - public boolean useAapt2 = true; public boolean noCrunch = false; + public boolean noApk = false; // Decode options public short decodeSources = DECODE_SOURCES_SMALI; @@ -71,13 +71,9 @@ public class Config { public String frameworkDirectory = null; public String frameworkTag = null; public String aaptPath = ""; - public int aaptVersion = 1; // default to v1 + public int aaptVersion = 2; // default to v2 // Utility functions - public boolean isAapt2() { - return this.useAapt2 || this.aaptVersion == 2; - } - public boolean isDecodeResolveModeUsingDummies() { return decodeResolveMode == DECODE_RES_RESOLVE_DUMMY; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java index 9f8ff7dbd5..73d0d61313 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java @@ -25,8 +25,20 @@ import java.io.*; import java.util.*; +import java.util.regex.Pattern; public class ApkInfo implements YamlSerializable { + public final static String[] RESOURCES_DIRNAMES = new String[] { "res", "r", "R" }; + public final static String[] RAW_DIRNAMES = new String[] { "assets", "lib", "libs", "kotlin", "META-INF/services" }; + + public final static Pattern ORIGINAL_FILENAMES_PATTERN = Pattern.compile( + "AndroidManifest\\.xml|META-INF/[^/]+\\.(RSA|SF|MF)|stamp-cert-sha256"); + + public final static Pattern STANDARD_FILENAMES_PATTERN = Pattern.compile( + "[^/]+\\.dex|resources\\.arsc|(" + String.join("|", RESOURCES_DIRNAMES) + "|" + + String.join("|", RAW_DIRNAMES) + ")/.*|" + ORIGINAL_FILENAMES_PATTERN.pattern()); + + // only set when loaded from a file (not a stream) private transient ExtFile mApkFile; public String version; @@ -40,7 +52,7 @@ public class ApkInfo implements YamlSerializable { public boolean sharedLibrary; public boolean sparseResources; public Map unknownFiles = new LinkedHashMap<>(); - public List doNotCompress; + public List doNotCompress = new ArrayList<>(); /** @deprecated use {@link #resourcesAreCompressed} */ public boolean compressionType; @@ -50,7 +62,7 @@ public ApkInfo() { } public ApkInfo(ExtFile apkFile) { - this.version = ApktoolProperties.getVersion(); + version = ApktoolProperties.getVersion(); if (apkFile != null) { setApkFile(apkFile); } @@ -62,59 +74,39 @@ public ExtFile getApkFile() { public void setApkFile(ExtFile apkFile) { mApkFile = apkFile; - if (this.apkFileName == null) { - this.apkFileName = apkFile.getName(); + if (apkFileName == null) { + apkFileName = apkFile.getName(); } } - public boolean hasManifest() throws AndrolibException { - if (mApkFile == null) { - return false; - } - try { - return mApkFile.getDirectory().containsFile("AndroidManifest.xml"); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } - } - - public boolean hasResources() throws AndrolibException { + public boolean hasSources() throws AndrolibException { if (mApkFile == null) { return false; } try { - return mApkFile.getDirectory().containsFile("resources.arsc"); + return mApkFile.getDirectory().containsFile("classes.dex"); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - public boolean hasSources() throws AndrolibException { + public boolean hasManifest() throws AndrolibException { if (mApkFile == null) { return false; } try { - return mApkFile.getDirectory().containsFile("classes.dex"); + return mApkFile.getDirectory().containsFile("AndroidManifest.xml"); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - public boolean hasMultipleSources() throws AndrolibException { + public boolean hasResources() throws AndrolibException { if (mApkFile == null) { return false; } try { - Set files = mApkFile.getDirectory().getFiles(false); - for (String file : files) { - if (file.endsWith(".dex")) { - if (!file.equalsIgnoreCase("classes.dex")) { - return true; - } - } - } - - return false; + return mApkFile.getDirectory().containsFile("resources.arsc"); } catch (DirectoryException ex) { throw new AndrolibException(ex); } @@ -140,30 +132,39 @@ public Map getSdkInfo() { } public void setSdkInfo(Map sdkInfo) { - this.sdkInfo = sdkInfo; - } - - public void setSdkInfoField(String key, String value) { - sdkInfo.put(key, value); + this.sdkInfo.clear(); + this.sdkInfo.putAll(sdkInfo); } public String getMinSdkVersion() { return sdkInfo.get("minSdkVersion"); } + public void setMinSdkVersion(String minSdkVersion) { + sdkInfo.put("minSdkVersion", minSdkVersion); + } + public String getMaxSdkVersion() { return sdkInfo.get("maxSdkVersion"); } + public void setMaxSdkVersion(String maxSdkVersion) { + sdkInfo.put("maxSdkVersion", maxSdkVersion); + } + public String getTargetSdkVersion() { return sdkInfo.get("targetSdkVersion"); } + public void setTargetSdkVersion(String targetSdkVersion) { + sdkInfo.put("targetSdkVersion", targetSdkVersion); + } + public int getMinSdkVersionFromAndroidCodename(String sdkVersion) { int sdkNumber = mapSdkShorthandToVersion(sdkVersion); if (sdkNumber == ResConfigFlags.SDK_BASE) { - return Integer.parseInt(sdkInfo.get("minSdkVersion")); + return Integer.parseInt(getMinSdkVersion()); } return sdkNumber; } @@ -205,15 +206,15 @@ private int mapSdkShorthandToVersion(String sdkVersion) { public void save(File file) throws AndrolibException { try (YamlWriter writer = new YamlWriter(new FileOutputStream(file))) { write(writer); - } catch (FileNotFoundException e) { + } catch (FileNotFoundException ex) { throw new AndrolibException("File not found"); - } catch (Exception e) { - throw new AndrolibException(e); + } catch (Exception ex) { + throw new AndrolibException(ex); } } - public static ApkInfo load(InputStream is) throws AndrolibException { - YamlReader reader = new YamlReader(is); + public static ApkInfo load(InputStream in) throws AndrolibException { + YamlReader reader = new YamlReader(in); ApkInfo apkInfo = new ApkInfo(); reader.readRoot(apkInfo); return apkInfo; @@ -234,56 +235,57 @@ public void readItem(YamlReader reader) throws AndrolibException { YamlLine line = reader.getLine(); switch (line.getKey()) { case "version": { - this.version = line.getValue(); + version = line.getValue(); break; } case "apkFileName": { - this.apkFileName = line.getValue(); + apkFileName = line.getValue(); break; } case "isFrameworkApk": { - this.isFrameworkApk = line.getValueBool(); + isFrameworkApk = line.getValueBool(); break; } case "usesFramework": { - this.usesFramework = new UsesFramework(); + usesFramework = new UsesFramework(); reader.readObject(usesFramework); break; } case "sdkInfo": { + sdkInfo.clear(); reader.readMap(sdkInfo); break; } case "packageInfo": { - this.packageInfo = new PackageInfo(); + packageInfo = new PackageInfo(); reader.readObject(packageInfo); break; } case "versionInfo": { - this.versionInfo = new VersionInfo(); + versionInfo = new VersionInfo(); reader.readObject(versionInfo); break; } case "compressionType": case "resourcesAreCompressed": { - this.resourcesAreCompressed = line.getValueBool(); + resourcesAreCompressed = line.getValueBool(); break; } case "sharedLibrary": { - this.sharedLibrary = line.getValueBool(); + sharedLibrary = line.getValueBool(); break; } case "sparseResources": { - this.sparseResources = line.getValueBool(); + sparseResources = line.getValueBool(); break; } case "unknownFiles": { - this.unknownFiles = new LinkedHashMap<>(); + unknownFiles.clear(); reader.readMap(unknownFiles); break; } case "doNotCompress": { - this.doNotCompress = new ArrayList<>(); + doNotCompress.clear(); reader.readStringList(doNotCompress); break; } @@ -302,9 +304,11 @@ public void write(YamlWriter writer) { writer.writeBool("resourcesAreCompressed", resourcesAreCompressed); writer.writeBool("sharedLibrary", sharedLibrary); writer.writeBool("sparseResources", sparseResources); - if (unknownFiles.size() > 0) { + if (!unknownFiles.isEmpty()) { writer.writeStringMap("unknownFiles", unknownFiles); } - writer.writeList("doNotCompress", doNotCompress); + if (!doNotCompress.isEmpty()) { + writer.writeList("doNotCompress", doNotCompress); + } } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java index 26652e5857..2e1e65f9a1 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java @@ -33,56 +33,47 @@ public class SmaliMod { public static boolean assembleSmaliFile(File smaliFile, DexBuilder dexBuilder, int apiLevel, boolean verboseErrors, boolean printTokens) throws IOException, RecognitionException { - - CommonTokenStream tokens; - smaliFlexLexer lexer; - - InputStream is = Files.newInputStream(smaliFile.toPath()); - InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8); - - lexer = new smaliFlexLexer(reader, apiLevel); - (lexer).setSourceFile(smaliFile); - tokens = new CommonTokenStream(lexer); - - if (printTokens) { - tokens.getTokens(); - - for (int i=0; i 0 || lexer.getNumberOfSyntaxErrors() > 0) { - is.close(); - reader.close(); - return false; - } + smaliParser.smali_file_return result = parser.smali_file(); - CommonTree t = result.getTree(); + if (parser.getNumberOfSyntaxErrors() > 0 || lexer.getNumberOfSyntaxErrors() > 0) { + return false; + } - CommonTreeNodeStream treeStream = new CommonTreeNodeStream(t); - treeStream.setTokenStream(tokens); + CommonTree t = result.getTree(); - smaliTreeWalker dexGen = new smaliTreeWalker(treeStream); - dexGen.setApiLevel(apiLevel); - dexGen.setVerboseErrors(verboseErrors); - dexGen.setDexBuilder(dexBuilder); - dexGen.smali_file(); + CommonTreeNodeStream treeStream = new CommonTreeNodeStream(t); + treeStream.setTokenStream(tokens); - is.close(); - reader.close(); + smaliTreeWalker dexGen = new smaliTreeWalker(treeStream); + dexGen.setApiLevel(apiLevel); + dexGen.setVerboseErrors(verboseErrors); + dexGen.setDexBuilder(dexBuilder); + dexGen.smali_file(); - return dexGen.getNumberOfSyntaxErrors() == 0; + return dexGen.getNumberOfSyntaxErrors() == 0; + } } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java index 80ab4b28f3..55b8076fc6 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java @@ -52,7 +52,7 @@ public void installFramework(File frameFile) throws AndrolibException { public void installFramework(File frameFile, String tag) throws AndrolibException { InputStream in = null; ZipOutputStream out = null; - try(ZipFile zip = new ZipFile(frameFile)) { + try (ZipFile zip = new ZipFile(frameFile)) { ZipEntry entry = zip.getEntry("resources.arsc"); if (entry == null) { @@ -247,8 +247,8 @@ public void emptyFrameworkDirectory() throws AndrolibException { } } } - } catch (NullPointerException e) { - throw new AndrolibException(e); + } catch (NullPointerException ex) { + throw new AndrolibException(ex); } } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java index f74f6a9312..a1749e3370 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java @@ -75,7 +75,7 @@ public void decodeManifest(File outDir) throws AndrolibException { } AXmlResourceParser axmlParser = new AndroidManifestResourceParser(mResTable); - XmlPullStreamDecoder fileDecoder = new XmlPullStreamDecoder(axmlParser, getResXmlSerializer()); + ResStreamDecoder fileDecoder = new AndroidManifestPullStreamDecoder(axmlParser, getResXmlSerializer()); Directory inApk, out; InputStream inputStream = null; @@ -91,7 +91,7 @@ public void decodeManifest(File outDir) throws AndrolibException { } inputStream = inApk.getFileInput("AndroidManifest.xml"); outputStream = out.getFileOutput("AndroidManifest.xml"); - fileDecoder.decodeManifest(inputStream, outputStream); + fileDecoder.decode(inputStream, outputStream); } catch (DirectoryException ex) { throw new AndrolibException(ex); @@ -136,8 +136,8 @@ private void adjustPackageManifest(String filePath) throws AndrolibException { // 2) Check if pkgRenamed is null // 3) Check if pkgOriginal === mPackageRenamed // 4) Check if pkgOriginal is ignored via IGNORED_PACKAGES - if (pkgOriginal == null || pkgRenamed == null || pkgOriginal.equalsIgnoreCase(pkgRenamed) - || (Arrays.asList(IGNORED_PACKAGES).contains(pkgOriginal))) { + if (pkgOriginal == null || pkgRenamed == null || pkgOriginal.equals(pkgRenamed) + || (Arrays.asList(IGNORED_PACKAGES).contains(pkgOriginal))) { LOGGER.info("Regular manifest package..."); } else { LOGGER.info("Renamed manifest package found! Replacing " + pkgRenamed + " with " + pkgOriginal); @@ -157,7 +157,7 @@ public void decodeResources(File outDir) throws AndrolibException { decoders.setDecoder("9patch", new Res9patchStreamDecoder()); AXmlResourceParser axmlParser = new AXmlResourceParser(mResTable); - decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser, getResXmlSerializer())); + decoders.setDecoder("xml", new ResXmlPullStreamDecoder(axmlParser, getResXmlSerializer())); ResFileDecoder fileDecoder = new ResFileDecoder(decoders); Directory in, out, outRes; @@ -220,7 +220,7 @@ private void generateValuesFile(ResValuesFile valuesFile, Directory out, serial.endDocument(); serial.flush(); outStream.close(); - } catch (IOException | DirectoryException ex) { + } catch (DirectoryException | IOException ex) { throw new AndrolibException("Could not generate: " + valuesFile.getPath(), ex); } } @@ -245,7 +245,7 @@ private void generatePublicXml(ResPackage pkg, Directory out, serial.endDocument(); serial.flush(); outStream.close(); - } catch (IOException | DirectoryException ex) { + } catch (DirectoryException | IOException ex) { throw new AndrolibException("Could not generate public.xml file", ex); } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java index 1c29ef4fb2..5846530bf9 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java @@ -118,7 +118,7 @@ private ResPackage selectPkgWithMostResSpecs(ResPackage[] pkgs) { for (int i = 0; i < pkgs.length; i++) { ResPackage resPackage = pkgs[i]; - if (resPackage.getResSpecCount() > value && ! resPackage.getName().equalsIgnoreCase("android")) { + if (resPackage.getResSpecCount() > value && ! resPackage.getName().equals("android")) { value = resPackage.getResSpecCount(); id = resPackage.getId(); index = i; @@ -178,8 +178,8 @@ private ResPackage loadFrameworkPkg(int id) throws AndrolibException { private ResPackage[] loadResPackagesFromApk(ExtFile apkFile, boolean keepBrokenResources) throws AndrolibException { try { Directory dir = apkFile.getDirectory(); - try (BufferedInputStream bfi = new BufferedInputStream(dir.getFileInput("resources.arsc"))) { - return ARSCDecoder.decode(bfi, false, keepBrokenResources, this).getPackages(); + try (BufferedInputStream bis = new BufferedInputStream(dir.getFileInput("resources.arsc"))) { + return ARSCDecoder.decode(bis, false, keepBrokenResources, this).getPackages(); } } catch (DirectoryException | IOException ex) { throw new AndrolibException("Could not load resources.arsc from file: " + apkFile, ex); @@ -190,7 +190,7 @@ public ResPackage getHighestSpecPackage() throws AndrolibException { int id = 0; int value = 0; for (ResPackage resPackage : mPackagesById.values()) { - if (resPackage.getResSpecCount() > value && !resPackage.getName().equalsIgnoreCase("android")) { + if (resPackage.getResSpecCount() > value && !resPackage.getName().equals("android")) { value = resPackage.getResSpecCount(); id = resPackage.getId(); } @@ -331,24 +331,25 @@ private UsesFramework getUsesFramework() { } private void updateSdkInfoFromResources(File outDir) { - String refValue; - Map sdkInfo = mApkInfo.getSdkInfo(); - if (sdkInfo.get("minSdkVersion") != null) { - refValue = ResXmlPatcher.pullValueFromIntegers(outDir, sdkInfo.get("minSdkVersion")); + String minSdkVersion = mApkInfo.getMinSdkVersion(); + if (minSdkVersion != null) { + String refValue = ResXmlPatcher.pullValueFromIntegers(outDir, minSdkVersion); if (refValue != null) { - sdkInfo.put("minSdkVersion", refValue); + mApkInfo.setMinSdkVersion(refValue); } } - if (sdkInfo.get("targetSdkVersion") != null) { - refValue = ResXmlPatcher.pullValueFromIntegers(outDir, sdkInfo.get("targetSdkVersion")); + String targetSdkVersion = mApkInfo.getTargetSdkVersion(); + if (targetSdkVersion != null) { + String refValue = ResXmlPatcher.pullValueFromIntegers(outDir, targetSdkVersion); if (refValue != null) { - sdkInfo.put("targetSdkVersion", refValue); + mApkInfo.setTargetSdkVersion(refValue); } } - if (sdkInfo.get("maxSdkVersion") != null) { - refValue = ResXmlPatcher.pullValueFromIntegers(outDir, sdkInfo.get("maxSdkVersion")); + String maxSdkVersion = mApkInfo.getMaxSdkVersion(); + if (maxSdkVersion != null) { + String refValue = ResXmlPatcher.pullValueFromIntegers(outDir, maxSdkVersion); if (refValue != null) { - sdkInfo.put("maxSdkVersion", refValue); + mApkInfo.setMaxSdkVersion(refValue); } } } @@ -367,7 +368,7 @@ private void initPackageInfo() throws AndrolibException { } // only put rename-manifest-package into apktool.yml, if the change will be required - if (renamed != null && !renamed.equalsIgnoreCase(original)) { + if (renamed != null && !renamed.equals(original)) { mApkInfo.packageInfo.renameManifestPackage = renamed; } mApkInfo.packageInfo.forcedPackageId = String.valueOf(id); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java index f1b0cd243d..57e99e00ee 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java @@ -48,7 +48,7 @@ public int getId() { } public boolean isString() { - return mName.equalsIgnoreCase(RES_TYPE_NAME_STRING); + return mName.equals(RES_TYPE_NAME_STRING); } public ResResSpec getResSpec(String name) throws AndrolibException { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResArrayValue.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResArrayValue.java index 2b1e2046b3..d4d34beb36 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResArrayValue.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResArrayValue.java @@ -41,8 +41,8 @@ public ResArrayValue(ResReferenceValue parent, ResScalarValue[] items) { } @Override - public void serializeToResValuesXml(XmlSerializer serializer, - ResResource res) throws IOException, AndrolibException { + public void serializeToResValuesXml(XmlSerializer serializer, ResResource res) + throws IOException, AndrolibException { String type = getType(); type = (type == null ? "" : type + "-") + "array"; serializer.startTag(null, type); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java index 30ee763b59..a2f72632b3 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java @@ -73,7 +73,7 @@ public void serializeToResValuesXml(XmlSerializer serializer, String body = encodeAsResXmlValue(); // check for resource reference - if (!type.equalsIgnoreCase("color")) { + if (!type.equals("color")) { if (body.contains("@")) { if (!res.getFilePath().contains("string")) { item = true; @@ -89,7 +89,7 @@ public void serializeToResValuesXml(XmlSerializer serializer, // Android does not allow values (false) for ids.xml anymore // https://issuetracker.google.com/issues/80475496 // But it decodes as a ResBoolean, which makes no sense. So force it to empty - if (type.equalsIgnoreCase("id") && !body.isEmpty()) { + if (type.equals("id") && !body.isEmpty()) { body = ""; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java index 1d20c79fc2..a6af2a48ce 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java @@ -79,7 +79,7 @@ public ResIntBasedValue factory(String value, int rawValue) { } public ResBagValue bagFactory(int parent, Duo[] items, ResTypeSpec resTypeSpec) - throws AndrolibException { + throws AndrolibException { ResReferenceValue parentVal = newReference(parent, null); if (items.length == 0) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 24bfe96437..17253f684b 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -317,7 +317,7 @@ private ResType readTableType() throws IOException, AndrolibException { int entriesStartAligned = mHeader.startPosition + entriesStart; if (mIn.position() < entriesStartAligned) { long bytesSkipped = mIn.skip(entriesStartAligned - mIn.position()); - LOGGER.fine("Skipping: " + bytesSkipped + " byte(s) to align with ResTable_entry start."); + LOGGER.fine(String.format("Skipping: %d byte(s) to align with ResTable_entry start.", bytesSkipped)); } for (int i : entryOffsetMap.keySet()) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java index a2e01d4057..23891e156d 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java @@ -89,9 +89,9 @@ public int next() throws XmlPullParserException, IOException { try { doNext(); return mEvent; - } catch (IOException e) { + } catch (IOException ex) { close(); - throw e; + throw ex; } } @@ -348,10 +348,10 @@ public String getAttributeName(int index) { String resourceMapValue; String stringBlockValue = mStringBlock.getString(name); - int resourceId = getAttributeNameResource(index); + int attrResId = getAttributeNameResource(index); try { - resourceMapValue = decodeFromResourceId(resourceId); + resourceMapValue = decodeFromResourceId(attrResId); } catch (AndrolibException ignored) { resourceMapValue = null; } @@ -371,7 +371,7 @@ public String getAttributeName(int index) { } // In this case we have a bogus resource. If it was not found in either. - return "APKTOOL_MISSING_" + Integer.toHexString(resourceId); + return "APKTOOL_MISSING_" + Integer.toHexString(attrResId); } @Override @@ -409,8 +409,10 @@ public String getAttributeValue(int index) { // Ensure we only track down obfuscated values for reference/attribute type values. Otherwise, we might // spam lookups against resource table for invalid ids. - if (valueType == TypedValue.TYPE_REFERENCE || valueType == TypedValue.TYPE_DYNAMIC_REFERENCE || - valueType == TypedValue.TYPE_ATTRIBUTE || valueType == TypedValue.TYPE_DYNAMIC_ATTRIBUTE) { + if (valueType == TypedValue.TYPE_REFERENCE + || valueType == TypedValue.TYPE_DYNAMIC_REFERENCE + || valueType == TypedValue.TYPE_ATTRIBUTE + || valueType == TypedValue.TYPE_DYNAMIC_ATTRIBUTE) { resourceMapValue = decodeFromResourceId(valueData); } String value = getPreferredString(stringBlockValue, resourceMapValue); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestPullStreamDecoder.java similarity index 82% rename from brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java rename to brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestPullStreamDecoder.java index de7aff98da..1e088093ad 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestPullStreamDecoder.java @@ -30,8 +30,8 @@ import java.io.*; -public class XmlPullStreamDecoder implements ResStreamDecoder { - public XmlPullStreamDecoder(AXmlResourceParser parser, +public class AndroidManifestPullStreamDecoder implements ResStreamDecoder { + public AndroidManifestPullStreamDecoder(AXmlResourceParser parser, ExtXmlSerializer serializer) { this.mParser = parser; this.mSerial = serializer; @@ -55,11 +55,11 @@ public void event(XmlPullParser pp) int type = pp.getEventType(); if (type == XmlPullParser.START_TAG) { - if ("manifest".equalsIgnoreCase(pp.getName())) { + if ("manifest".equals(pp.getName())) { try { hidePackageInfo = parseManifest(pp); } catch (AndrolibException ignored) {} - } else if ("uses-sdk".equalsIgnoreCase(pp.getName())) { + } else if ("uses-sdk".equals(pp.getName())) { try { hideSdkInfo = parseAttr(pp); if (hideSdkInfo) { @@ -68,10 +68,10 @@ public void event(XmlPullParser pp) } catch (AndrolibException ignored) {} } } else if (hideSdkInfo && type == XmlPullParser.END_TAG - && "uses-sdk".equalsIgnoreCase(pp.getName())) { + && "uses-sdk".equals(pp.getName())) { return; } else if (hidePackageInfo && type == XmlPullParser.END_TAG - && "manifest".equalsIgnoreCase(pp.getName())) { + && "manifest".equals(pp.getName())) { super.event(pp); return; } @@ -86,11 +86,11 @@ private boolean parseManifest(XmlPullParser pp) for (int i = 0; i < pp.getAttributeCount(); i++) { attr_name = pp.getAttributeName(i); - if (attr_name.equalsIgnoreCase(("package"))) { + if (attr_name.equals(("package"))) { resTable.setPackageRenamed(pp.getAttributeValue(i)); - } else if (attr_name.equalsIgnoreCase("versionCode")) { + } else if (attr_name.equals("versionCode")) { resTable.setVersionCode(pp.getAttributeValue(i)); - } else if (attr_name.equalsIgnoreCase("versionName")) { + } else if (attr_name.equals("versionName")) { resTable.setVersionName(pp.getAttributeValue(i)); } } @@ -103,14 +103,14 @@ private boolean parseAttr(XmlPullParser pp) final String a_ns = "http://schemas.android.com/apk/res/android"; String ns = pp.getAttributeNamespace(i); - if (a_ns.equalsIgnoreCase(ns)) { + if (a_ns.equals(ns)) { String name = pp.getAttributeName(i); String value = pp.getAttributeValue(i); if (name != null && value != null) { - if (name.equalsIgnoreCase("minSdkVersion") - || name.equalsIgnoreCase("targetSdkVersion") - || name.equalsIgnoreCase("maxSdkVersion") - || name.equalsIgnoreCase("compileSdkVersion")) { + if (name.equals("minSdkVersion") + || name.equals("targetSdkVersion") + || name.equals("maxSdkVersion") + || name.equals("compileSdkVersion")) { resTable.addSdkInfo(name, value); } else { resTable.clearSdkInfo(); @@ -144,11 +144,6 @@ private boolean parseAttr(XmlPullParser pp) } } - public void decodeManifest(InputStream in, OutputStream out) - throws AndrolibException { - decode(in, out); - } - private final AXmlResourceParser mParser; private final ExtXmlSerializer mSerial; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestResourceParser.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestResourceParser.java index 64562b4c03..8fd38da587 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestResourceParser.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AndroidManifestResourceParser.java @@ -58,9 +58,9 @@ public String getAttributeValue(int index) { } private boolean isNumericStringMetadataAttributeValue(int index, String value) { - return "meta-data".equalsIgnoreCase(super.getName()) - && "value".equalsIgnoreCase(super.getAttributeName(index)) - && super.getAttributeValueType(index) == TypedValue.TYPE_STRING - && PATTERN_NUMERIC_STRING.matcher(value).matches(); + return "meta-data".equals(super.getName()) + && "value".equals(super.getAttributeName(index)) + && super.getAttributeValueType(index) == TypedValue.TYPE_STRING + && PATTERN_NUMERIC_STRING.matcher(value).matches(); } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResStreamDecoder.java index d2f63ae069..d0825d1c9c 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResStreamDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResStreamDecoder.java @@ -20,6 +20,5 @@ import java.io.*; public interface ResStreamDecoder { - void decode(InputStream in, OutputStream out) - throws AndrolibException; + void decode(InputStream in, OutputStream out) throws AndrolibException; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResXmlPullStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResXmlPullStreamDecoder.java new file mode 100644 index 0000000000..1719b20c3d --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResXmlPullStreamDecoder.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 Ryszard Wiśniewski + * Copyright (C) 2010 Connor Tumbleson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package brut.androlib.res.decoder; + +import brut.androlib.exceptions.AndrolibException; +import brut.androlib.exceptions.AXmlDecodingException; +import brut.androlib.exceptions.RawXmlEncounteredException; +import brut.androlib.res.util.ExtXmlSerializer; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.wrapper.XmlPullParserWrapper; +import org.xmlpull.v1.wrapper.XmlPullWrapperFactory; +import org.xmlpull.v1.wrapper.XmlSerializerWrapper; +import org.xmlpull.v1.wrapper.classic.StaticXmlSerializerWrapper; + +import java.io.*; + +public class ResXmlPullStreamDecoder implements ResStreamDecoder { + public ResXmlPullStreamDecoder(AXmlResourceParser parser, + ExtXmlSerializer serializer) { + this.mParser = parser; + this.mSerial = serializer; + } + + @Override + public void decode(InputStream in, OutputStream out) + throws AndrolibException { + try { + XmlPullWrapperFactory factory = XmlPullWrapperFactory.newInstance(); + XmlPullParserWrapper par = factory.newPullParserWrapper(mParser); + XmlSerializerWrapper ser = new StaticXmlSerializerWrapper(mSerial, factory); + + par.setInput(in, null); + ser.setOutput(out, null); + + while (par.nextToken() != XmlPullParser.END_DOCUMENT) { + ser.event(par); + } + ser.flush(); + } catch (XmlPullParserException ex) { + throw new AXmlDecodingException("Could not decode XML", ex); + } catch (IOException ex) { + throw new RawXmlEncounteredException("Could not decode XML", ex); + } + } + + private final AXmlResourceParser mParser; + private final ExtXmlSerializer mSerial; +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java index 34a95598d4..91237325b2 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java @@ -25,7 +25,6 @@ import java.nio.ByteBuffer; import java.nio.charset.*; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.logging.Logger; @@ -139,7 +138,7 @@ public String getHTML(int index) { for (int i = 0; i < style.length; i += 3) { spans.add(new StyledString.Span(getString(style[i]), style[i + 1], style[i + 2])); } - Collections.sort(spans); + spans.sort(null); StyledString styledString = new StyledString(text, spans); return styledString.toString(); @@ -240,7 +239,7 @@ String decodeString(int offset, int length) { // in some places, Android uses 3-byte UTF-8 sequences instead of 4-bytes. // If decoding failed, we try to use CESU-8 decoder, which is closer to what Android actually uses. return CESU8_DECODER.decode(wrappedBufferRetry).toString(); - } catch (CharacterCodingException e) { + } catch (CharacterCodingException ex) { LOGGER.warning("Failed to decode a string with CESU-8 decoder."); return null; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java index 0acd9328f4..44dbfacf03 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java @@ -41,24 +41,25 @@ public final class ResXmlPatcher { * @throws AndrolibException Error reading Manifest file */ public static void removeApplicationDebugTag(File file) throws AndrolibException { - if (file.exists()) { - try { - Document doc = loadDocument(file); - Node application = doc.getElementsByTagName("application").item(0); - - // load attr - NamedNodeMap attr = application.getAttributes(); - Node debugAttr = attr.getNamedItem("android:debuggable"); - - // remove application:debuggable - if (debugAttr != null) { - attr.removeNamedItem("android:debuggable"); - } + if (!file.exists()) { + return; + } + try { + Document doc = loadDocument(file); + Node application = doc.getElementsByTagName("application").item(0); - saveDocument(file, doc); + // load attr + NamedNodeMap attr = application.getAttributes(); + Node debugAttr = attr.getNamedItem("android:debuggable"); - } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { + // remove application:debuggable + if (debugAttr != null) { + attr.removeNamedItem("android:debuggable"); } + + saveDocument(file, doc); + + } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } } @@ -68,27 +69,28 @@ public static void removeApplicationDebugTag(File file) throws AndrolibException * @param file AndroidManifest file */ public static void setApplicationDebugTagTrue(File file) { - if (file.exists()) { - try { - Document doc = loadDocument(file); - Node application = doc.getElementsByTagName("application").item(0); - - // load attr - NamedNodeMap attr = application.getAttributes(); - Node debugAttr = attr.getNamedItem("android:debuggable"); - - if (debugAttr == null) { - debugAttr = doc.createAttribute("android:debuggable"); - attr.setNamedItem(debugAttr); - } + if (!file.exists()) { + return; + } + try { + Document doc = loadDocument(file); + Node application = doc.getElementsByTagName("application").item(0); - // set application:debuggable to 'true - debugAttr.setNodeValue("true"); + // load attr + NamedNodeMap attr = application.getAttributes(); + Node debugAttr = attr.getNamedItem("android:debuggable"); - saveDocument(file, doc); - - } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { + if (debugAttr == null) { + debugAttr = doc.createAttribute("android:debuggable"); + attr.setNamedItem(debugAttr); } + + // set application:debuggable to 'true + debugAttr.setNodeValue("true"); + + saveDocument(file, doc); + + } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } } @@ -98,28 +100,29 @@ public static void setApplicationDebugTagTrue(File file) { * @param file AndroidManifest file */ public static void setNetworkSecurityConfig(File file) { - if (file.exists()) { - try { - Document doc = loadDocument(file); - Node application = doc.getElementsByTagName("application").item(0); - - // load attr - NamedNodeMap attr = application.getAttributes(); - Node netSecConfAttr = attr.getNamedItem("android:networkSecurityConfig"); - - if (netSecConfAttr == null) { - // there is not an already existing network security configuration - netSecConfAttr = doc.createAttribute("android:networkSecurityConfig"); - attr.setNamedItem(netSecConfAttr); - } - - // whether it already existed or it was created now set it to the proper value - netSecConfAttr.setNodeValue("@xml/network_security_config"); + if (!file.exists()) { + return; + } + try { + Document doc = loadDocument(file); + Node application = doc.getElementsByTagName("application").item(0); - saveDocument(file, doc); + // load attr + NamedNodeMap attr = application.getAttributes(); + Node netSecConfAttr = attr.getNamedItem("android:networkSecurityConfig"); - } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { + if (netSecConfAttr == null) { + // there is not an already existing network security configuration + netSecConfAttr = doc.createAttribute("android:networkSecurityConfig"); + attr.setNamedItem(netSecConfAttr); } + + // whether it already existed or it was created now set it to the proper value + netSecConfAttr.setNodeValue("@xml/network_security_config"); + + saveDocument(file, doc); + + } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } } @@ -173,50 +176,52 @@ public static void modNetworkSecurityConfig(File file) * @param file File for AndroidManifest.xml */ public static void fixingPublicAttrsInProviderAttributes(File file) { - boolean saved = false; - if (file.exists()) { - try { - Document doc = loadDocument(file); - XPath xPath = XPathFactory.newInstance().newXPath(); - XPathExpression expression = xPath.compile("/manifest/application/provider"); - - Object result = expression.evaluate(doc, XPathConstants.NODESET); - NodeList nodes = (NodeList) result; - - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - NamedNodeMap attrs = node.getAttributes(); - Node provider = attrs.getNamedItem("android:authorities"); - - if (provider != null) { - saved = isSaved(file, saved, provider); - } - } + if (!file.exists()) { + return; + } + try { + Document doc = loadDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression expression = xPath.compile("/manifest/application/provider"); - // android:scheme - xPath = XPathFactory.newInstance().newXPath(); - expression = xPath.compile("/manifest/application/activity/intent-filter/data"); + Object result = expression.evaluate(doc, XPathConstants.NODESET); + NodeList nodes = (NodeList) result; - result = expression.evaluate(doc, XPathConstants.NODESET); - nodes = (NodeList) result; + boolean saved = false; - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - NamedNodeMap attrs = node.getAttributes(); - Node provider = attrs.getNamedItem("android:scheme"); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + NamedNodeMap attrs = node.getAttributes(); + Node provider = attrs.getNamedItem("android:authorities"); - if (provider != null) { - saved = isSaved(file, saved, provider); - } + if (provider != null) { + saved = isSaved(file, saved, provider); } + } - if (saved) { - saveDocument(file, doc); + // android:scheme + xPath = XPathFactory.newInstance().newXPath(); + expression = xPath.compile("/manifest/application/activity/intent-filter/data"); + + result = expression.evaluate(doc, XPathConstants.NODESET); + nodes = (NodeList) result; + + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + NamedNodeMap attrs = node.getAttributes(); + Node provider = attrs.getNamedItem("android:scheme"); + + if (provider != null) { + saved = isSaved(file, saved, provider); } + } - } catch (SAXException | ParserConfigurationException | IOException | - XPathExpressionException | TransformerException ignored) { + if (saved) { + saveDocument(file, doc); } + + } catch (SAXException | ParserConfigurationException | IOException + | XPathExpressionException | TransformerException ignored) { } } @@ -254,23 +259,20 @@ public static String pullValueFromStrings(File directory, String key) { File file = new File(directory, "/res/values/strings.xml"); key = key.replace("@string/", ""); - if (file.exists()) { - try { - Document doc = loadDocument(file); - XPath xPath = XPathFactory.newInstance().newXPath(); - XPathExpression expression = xPath.compile("/resources/string[@name=" + '"' + key + "\"]/text()"); - - Object result = expression.evaluate(doc, XPathConstants.STRING); + if (!file.exists()) { + return null; + } + try { + Document doc = loadDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression expression = xPath.compile("/resources/string[@name=" + '"' + key + "\"]/text()"); - if (result != null) { - return (String) result; - } + Object result = expression.evaluate(doc, XPathConstants.STRING); + return result != null ? (String) result : null; - } catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException ignored) { - } + } catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException ignored) { + return null; } - - return null; } /** @@ -288,23 +290,20 @@ public static String pullValueFromIntegers(File directory, String key) { File file = new File(directory, "/res/values/integers.xml"); key = key.replace("@integer/", ""); - if (file.exists()) { - try { - Document doc = loadDocument(file); - XPath xPath = XPathFactory.newInstance().newXPath(); - XPathExpression expression = xPath.compile("/resources/integer[@name=" + '"' + key + "\"]/text()"); - - Object result = expression.evaluate(doc, XPathConstants.STRING); + if (!file.exists()) { + return null; + } + try { + Document doc = loadDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression expression = xPath.compile("/resources/integer[@name=" + '"' + key + "\"]/text()"); - if (result != null) { - return (String) result; - } + Object result = expression.evaluate(doc, XPathConstants.STRING); + return result != null ? (String) result : null; - } catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException ignored) { - } + } catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException ignored) { + return null; } - - return null; } /** @@ -313,24 +312,25 @@ public static String pullValueFromIntegers(File directory, String key) { * @param file File representing AndroidManifest.xml */ public static void removeManifestVersions(File file) { - if (file.exists()) { - try { - Document doc = loadDocument(file); - Node manifest = doc.getFirstChild(); - NamedNodeMap attr = manifest.getAttributes(); - Node vCode = attr.getNamedItem("android:versionCode"); - Node vName = attr.getNamedItem("android:versionName"); - - if (vCode != null) { - attr.removeNamedItem("android:versionCode"); - } - if (vName != null) { - attr.removeNamedItem("android:versionName"); - } - saveDocument(file, doc); + if (!file.exists()) { + return; + } + try { + Document doc = loadDocument(file); + Node manifest = doc.getFirstChild(); + NamedNodeMap attr = manifest.getAttributes(); + Node vCode = attr.getNamedItem("android:versionCode"); + Node vName = attr.getNamedItem("android:versionName"); - } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { + if (vCode != null) { + attr.removeNamedItem("android:versionCode"); } + if (vName != null) { + attr.removeNamedItem("android:versionName"); + } + saveDocument(file, doc); + + } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java index 6880c1557a..d7d7bb83ff 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java @@ -20,7 +20,6 @@ import brut.androlib.mod.SmaliMod; import brut.directory.DirectoryException; import brut.directory.ExtFile; -import org.antlr.runtime.RecognitionException; import com.android.tools.smali.dexlib2.Opcodes; import com.android.tools.smali.dexlib2.writer.builder.DexBuilder; import com.android.tools.smali.dexlib2.writer.io.FileDataStore; @@ -31,12 +30,12 @@ public class SmaliBuilder { - public static void build(ExtFile smaliDir, File dexFile, int apiLevel) throws AndrolibException { + public static void build(File smaliDir, File dexFile, int apiLevel) throws AndrolibException { new SmaliBuilder(smaliDir, dexFile, apiLevel).build(); } - private SmaliBuilder(ExtFile smaliDir, File dexFile, int apiLevel) { - mSmaliDir = smaliDir; + private SmaliBuilder(File smaliDir, File dexFile, int apiLevel) { + mSmaliDir = new ExtFile(smaliDir); mDexFile = dexFile; mApiLevel = apiLevel; } @@ -53,29 +52,35 @@ private void build() throws AndrolibException { for (String fileName : mSmaliDir.getDirectory().getFiles(true)) { buildFile(fileName, dexBuilder); } - dexBuilder.writeTo(new FileDataStore( new File(mDexFile.getAbsolutePath()))); - } catch (IOException | DirectoryException ex) { - throw new AndrolibException(ex); + dexBuilder.writeTo(new FileDataStore(new File(mDexFile.getAbsolutePath()))); + } catch (DirectoryException | IOException | RuntimeException ex) { + throw new AndrolibException("Could not smali folder: " + mSmaliDir.getName(), ex); } } - private void buildFile(String fileName, DexBuilder dexBuilder) - throws AndrolibException, IOException { - File inFile = new File(mSmaliDir, fileName); - InputStream inStream = Files.newInputStream(inFile.toPath()); + private void buildFile(String fileName, DexBuilder dexBuilder) throws AndrolibException { + if (!fileName.endsWith(".smali")) { + LOGGER.warning("Unknown file type, ignoring: " + fileName); + return; + } - if (fileName.endsWith(".smali")) { - try { - if (!SmaliMod.assembleSmaliFile(inFile, dexBuilder, mApiLevel, false, false)) { - throw new AndrolibException("Could not smali file: " + fileName); - } - } catch (IOException | RecognitionException ex) { - throw new AndrolibException(ex); + boolean success; + Exception cause; + try { + File inFile = new File(mSmaliDir, fileName); + success = SmaliMod.assembleSmaliFile(inFile, dexBuilder, mApiLevel, false, false); + cause = null; + } catch (Exception ex) { + success = false; + cause = ex; + } + if (!success) { + AndrolibException ex = new AndrolibException("Could not smali file: " + fileName); + if (cause != null) { + ex.initCause(cause); } - } else { - LOGGER.warning("Unknown file type, ignoring: " + inFile); + throw ex; } - inStream.close(); } private final ExtFile mSmaliDir; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java index 688025b693..b3a52a5d43 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java @@ -39,7 +39,7 @@ public static DexFile decode(File apkFile, File outDir, String dexName, boolean private SmaliDecoder(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel) { mApkFile = apkFile; mOutDir = outDir; - mDexFile = dexName; + mDexName = dexName; mBakDeb = bakDeb; mApiLevel = apiLevel; } @@ -76,7 +76,7 @@ private DexFile decode() throws AndrolibException { if (container.getDexEntryNames().size() == 1) { dexEntry = container.getEntry(container.getDexEntryNames().get(0)); } else { - dexEntry = container.getEntry(mDexFile); + dexEntry = container.getEntry(mDexName); } // Double-check the passed param exists @@ -100,13 +100,13 @@ private DexFile decode() throws AndrolibException { return dexFile; } catch (IOException ex) { - throw new AndrolibException(ex); + throw new AndrolibException("Could not baksmali file: " + mDexName, ex); } } private final File mApkFile; private final File mOutDir; - private final String mDexFile; + private final String mDexName; private final boolean mBakDeb; private final int mApiLevel; } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java index 12d3a351f9..be57380681 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java @@ -67,10 +67,10 @@ protected void compareBinaryFolder(String path, boolean res) throws BrutExceptio FileDirectory fileDirectory = new FileDirectory(sTestOrigDir, location); Set files = fileDirectory.getFiles(true); - for (String filename : files) { + for (String fileName : files) { - File control = new File((sTestOrigDir + location), filename); - File test = new File((sTestNewDir + location), filename); + File control = new File((sTestOrigDir + location), fileName); + File test = new File((sTestNewDir + location), fileName); if (! test.isFile() || ! control.isFile()) { exists = false; diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java index e13deccdd4..dddebae5ca 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java @@ -39,7 +39,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Unpacking not_sparse.apk..."); TestUtils.copyResourceDir(AndroidOreoNotSparseTest.class, "aapt1/issue1594", sTestOrigDir); - File testApk = new File(sTestOrigDir, "not_sparse.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "not_sparse.apk"); LOGGER.info("Decoding not_sparse.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); @@ -47,7 +47,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building not_sparse.apk..."); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestNewDir).build(testApk); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java index 9461916780..8e8b1f97fa 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java @@ -39,7 +39,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Unpacking sparse.apk..."); TestUtils.copyResourceDir(AndroidOreoSparseTest.class, "aapt1/issue1594", sTestOrigDir); - File testApk = new File(sTestOrigDir, "sparse.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "sparse.apk"); LOGGER.info("Decoding sparse.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); @@ -47,7 +47,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building sparse.apk..."); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestNewDir).build(testApk); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java index 2de35510e6..9b85e70f28 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java @@ -40,9 +40,9 @@ public static void beforeClass() throws Exception { TestUtils.copyResourceDir(BuildAndDecodeJarTest.class, "aapt1/testjar/", sTestOrigDir); LOGGER.info("Building testjar.jar..."); - File testJar = new File(sTmpDir, "testjar.jar"); + ExtFile testJar = new ExtFile(sTmpDir, "testjar.jar"); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestOrigDir).build(testJar); LOGGER.info("Decoding testjar.jar..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java index f5385d651e..459ac4afc1 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java @@ -48,9 +48,9 @@ public static void beforeClass() throws Exception { TestUtils.copyResourceDir(BuildAndDecodeTest.class, "aapt1/testapp/", sTestOrigDir); LOGGER.info("Building testapp.apk..."); - File testApk = new File(sTmpDir, "testapp.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding testapp.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java index 9c63aa2904..b206789f25 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java @@ -48,10 +48,10 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue1235.apk..."); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; config.debugMode = true; - File testApk = new File(sTmpDir, "issue1235.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "issue1235.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding issue1235.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java index ccdd9b1c32..182141657a 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java @@ -42,9 +42,9 @@ public static void beforeClass() throws Exception { TestUtils.copyResourceDir(DefaultBaksmaliVariableTest.class, "aapt1/issue1481/", sTestOrigDir); LOGGER.info("Building issue1481.jar..."); - File testJar = new File(sTmpDir, "issue1481.jar"); + ExtFile testJar = new ExtFile(sTmpDir, "issue1481.jar"); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestOrigDir).build(testJar); LOGGER.info("Decoding issue1481.jar..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java index 240d304076..e3e2c31526 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java @@ -42,7 +42,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Unpacking issue1730.apk..."); TestUtils.copyResourceDir(EmptyResourcesArscTest.class, "aapt1/issue1730", sTestOrigDir); - File testApk = new File(sTestOrigDir, "issue1730.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "issue1730.apk"); LOGGER.info("Decoding issue1730.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); @@ -50,7 +50,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue1730.apk..."); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestNewDir).build(testApk); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java index 4c673958f8..7ddaa4a5bb 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java @@ -39,9 +39,9 @@ public static void beforeClass() throws Exception { TestUtils.copyResourceDir(ExternalEntityTest.class, "decode/doctype/", sTestOrigDir); LOGGER.info("Building doctype.apk..."); - File testApk = new File(sTestOrigDir, "doctype.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "doctype.apk"); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding doctype.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java index c8e4574c53..ea4061fbe7 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java @@ -44,7 +44,7 @@ public void checkIfLargeIntsAreHandledTest() throws BrutException, IOException { String apk = "issue767.apk"; // decode issue767.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); @@ -52,13 +52,13 @@ public void checkIfLargeIntsAreHandledTest() throws BrutException, IOException { // build issue767 Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; ExtFile testApk = new ExtFile(sTmpDir, apk + ".out"); new ApkBuilder(config, testApk).build(null); String newApk = apk + ".out" + File.separator + "dist" + File.separator + apk; // decode issue767 again - apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + newApk)); + apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + newApk)); sTestNewDir = new ExtFile(sTmpDir + File.separator + apk + ".out.two"); outDir = new File(sTmpDir + File.separator + apk + ".out.two"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java index 35a9ba9a6d..bf54c126ef 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java @@ -53,20 +53,20 @@ public void isProviderStringReplacementWorking() throws BrutException, IOExcepti String apk = "issue636.apk"; // decode issue636.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); // build issue636 ExtFile testApk = new ExtFile(sTmpDir, apk + ".out"); Config config = Config.getDefaultConfig(); - config.useAapt2 = false; + config.aaptVersion = 1; new ApkBuilder(config, testApk).build(null); String newApk = apk + ".out" + File.separator + "dist" + File.separator + apk; assertTrue(fileExists(newApk)); // decode issues636 again - apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + newApk)); + apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + newApk)); outDir = new File(sTmpDir + File.separator + apk + ".out.two"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java index bc7b44f231..3021db8800 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java @@ -81,7 +81,7 @@ public void isSharedResourceDecodingAndRebuildingWorking() throws IOException, B Config config = Config.getDefaultConfig(); config.frameworkDirectory = sTmpDir.getAbsolutePath(); config.frameworkTag = "shared"; - config.useAapt2 = false; + config.aaptVersion = 1; // install library/framework new Framework(config).installFramework(new File(sTmpDir + File.separator + library)); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java index 5e087db2fa..e7f5999833 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java @@ -42,7 +42,7 @@ public static void beforeClass() throws Exception { String apk = "deflated_unknowns.apk"; Config config = Config.getDefaultConfig(); config.frameworkDirectory = sTmpDir.getAbsolutePath(); - config.useAapt2 = false; + config.aaptVersion = 1; sTestOrigDir = new ExtFile(sTmpDir, apk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java index 14014adcf6..056a7937c2 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java @@ -49,11 +49,10 @@ public static void beforeClass() throws Exception { TestUtils.copyResourceDir(BuildAndDecodeTest.class, "aapt2/testapp/", sTestOrigDir); Config config = Config.getDefaultConfig(); - config.useAapt2 = true; config.verbose = true; LOGGER.info("Building testapp.apk..."); - File testApk = new File(sTmpDir, "testapp.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding testapp.apk..."); @@ -135,7 +134,7 @@ public void leadingDollarSignResourceNameTest() throws BrutException { } @Test - public void samsungQmgFilesHandledTest() throws IOException, BrutException { + public void samsungQmgFilesHandledTest() throws BrutException, IOException { compareBinaryFolder("drawable-xhdpi", true); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java index 8ca7f8d6f3..79853d69b4 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java @@ -49,10 +49,9 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue2328-debuggable-flase.apk..."); Config config = Config.getDefaultConfig(); config.debugMode = true; - config.useAapt2 = true; config.verbose = true; - File testApk = new File(sTmpDir, "issue2328-debuggable-flase.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "issue2328-debuggable-flase.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding issue2328-debuggable-flase.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java index 9cab0376ba..f8c4ba661b 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java @@ -49,10 +49,9 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue2328-debuggable-missing.apk..."); Config config = Config.getDefaultConfig(); config.debugMode = true; - config.useAapt2 = true; config.verbose = true; - File testApk = new File(sTmpDir, "issue2328-debuggable-missing.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "issue2328-debuggable-missing.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding issue2328-debuggable-missing.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java index d85822f483..49fe6564ab 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java @@ -49,10 +49,9 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue2328-debuggable-true.apk..."); Config config = Config.getDefaultConfig(); config.debugMode = true; - config.useAapt2 = true; config.verbose = true; - File testApk = new File(sTmpDir, "issue2328-debuggable-true.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "issue2328-debuggable-true.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding issue2328-debuggable-true.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java index 51be370612..a26f8beef6 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java @@ -53,8 +53,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building testapp.apk..."); Config config = Config.getDefaultConfig(); config.netSecConf = true; - config.useAapt2 = true; - File testApk = new File(sTmpDir, "testapp.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding testapp.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java index d19d3f1d14..93142a7ca6 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java @@ -55,8 +55,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building testapp.apk..."); Config config = Config.getDefaultConfig(); config.netSecConf = true; - config.useAapt2 = true; - File testApk = new File(sTmpDir, "testapp.apk"); + ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); new ApkBuilder(config, sTestOrigDir).build(testApk); LOGGER.info("Decoding testapp.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java index 34ea0c6b2e..72a2bf3d86 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java @@ -45,7 +45,6 @@ public static void beforeClass() throws Exception { TestUtils.copyResourceDir(BuildAndDecodeTest.class, "aapt2/pkgid8/", sTestOrigDir); Config config = Config.getDefaultConfig(); - config.useAapt2 = true; config.verbose = true; LOGGER.info("Building pkgid8.apk..."); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java index fe6d3dc3fd..78b267958d 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java @@ -48,7 +48,7 @@ public void checkifAndResDecodeRemapsRFolder() throws BrutException, IOException String apk = "issue1170.apk"; // decode issue1170.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); @@ -65,7 +65,7 @@ public void checkIfAndResDecodeRemapsRFolderInRawMode() throws BrutException, IO config.forceDelete = true; config.decodeResources = Config.DECODE_RESOURCES_NONE; String apk = "issue1170.apk"; - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".raw.out"); File outDir = new File(sTmpDir + File.separator + apk + ".raw.out"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java index 5b4ad679d5..83cb595a81 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java @@ -48,7 +48,7 @@ public static void afterClass() throws BrutException { @Test public void checkIfDecodeSucceeds() throws BrutException, IOException, ParserConfigurationException, SAXException { String apk = "issue3366.apk"; - File testApk = new File(sTmpDir, apk); + ExtFile testApk = new ExtFile(sTmpDir, apk); // decode issue3366.apk ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java index d52b35556f..9c8ec38d18 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java @@ -55,7 +55,7 @@ public void kotlinCoroutinesDecodeTest() throws IOException, AndrolibException, Config config = Config.getDefaultConfig(); config.forceDelete = true; // decode kotlin coroutines - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); File coroutinesExceptionHandler = new File(sTmpDir + File.separator + apk + ".out" + File.separator + "META-INF" + File.separator + "services", "kotlinx.coroutines.CoroutineExceptionHandler"); @@ -66,12 +66,12 @@ public void kotlinCoroutinesDecodeTest() throws IOException, AndrolibException, } @Test - public void kotlinCoroutinesEncodeAfterDecodeTest() throws IOException, BrutException { + public void kotlinCoroutinesEncodeAfterDecodeTest() throws BrutException, IOException { Config config = Config.getDefaultConfig(); config.forceDelete = true; // decode kotlin coroutines - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); @@ -82,7 +82,7 @@ public void kotlinCoroutinesEncodeAfterDecodeTest() throws IOException, BrutExce assertTrue(fileExists(newApk)); // decode kotlin coroutines again - apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + newApk)); + apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + newApk)); outDir = new File(sTmpDir + File.separator + apk + ".out.two"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinTest.java index 415138e7c9..2dc515ad11 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinTest.java @@ -43,7 +43,7 @@ public static void beforeClass() throws Exception { String apk = "testkotlin.apk"; // decode testkotlin.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestNewDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DoubleExtensionUnknownFileTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DoubleExtensionUnknownFileTest.java index 29c68a1b9b..b56dc48a22 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DoubleExtensionUnknownFileTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DoubleExtensionUnknownFileTest.java @@ -52,7 +52,7 @@ public void multipleExtensionUnknownFileTest() throws BrutException, IOException String apk = "issue1244.apk"; // decode issue1244.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); ExtFile decodedApk = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); @@ -60,7 +60,7 @@ public void multipleExtensionUnknownFileTest() throws BrutException, IOException ApkInfo apkInfo = ApkInfo.load(decodedApk); for (String string : apkInfo.doNotCompress) { if (StringUtils.countMatches(string, ".") > 1) { - assertTrue(string.equalsIgnoreCase("assets/bin/Data/sharedassets1.assets.split0")); + assertTrue(string.equals("assets/bin/Data/sharedassets1.assets.split0")); } } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java index 9af4216f54..85b4eee864 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java @@ -45,7 +45,7 @@ public void afterClass() throws BrutException { @Test(expected = AndrolibException.class) public void decodeAllSourcesShouldThrowException() throws BrutException, IOException { - File testApk = new File(sTestOrigDir, "duplicatedex.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "duplicatedex.apk"); LOGGER.info("Decoding duplicatedex.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); @@ -58,7 +58,7 @@ public void decodeAllSourcesShouldThrowException() throws BrutException, IOExcep @Test public void decodeUsingOnlyMainClassesMode() throws BrutException, IOException { - File testApk = new File(sTestOrigDir, "duplicatedex.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "duplicatedex.apk"); LOGGER.info("Decoding duplicatedex.apk..."); Config config = Config.getDefaultConfig(); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/Empty9PatchTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/Empty9PatchTest.java index d9789e2953..da4d9f0968 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/Empty9PatchTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/Empty9PatchTest.java @@ -51,7 +51,7 @@ public void decodeWithEmpty9PatchFile() throws BrutException, IOException { String apk = "empty9patch.apk"; // decode empty9patch.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/EmptyArscTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/EmptyArscTest.java index 4a7916d67d..75de4d6beb 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/EmptyArscTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/EmptyArscTest.java @@ -50,7 +50,7 @@ public void decodeWithEmptyArscFile() throws BrutException, IOException { String apk = "test.apk"; // decode test.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java index 3ce0491bfc..d6f919dcc3 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java @@ -139,7 +139,7 @@ private void decodeFile(String apk, short decodeResources, short decodeManifest, config.forceDelete = true; config.decodeResources = decodeResources; config.forceDecodeManifest = decodeManifest; - ApkDecoder apkDecoder = new ApkDecoder(config, new File(apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(apk)); apkDecoder.decode(new File(output)); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingVersionManifestTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingVersionManifestTest.java index 55eaf149a4..a6002f68e7 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingVersionManifestTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingVersionManifestTest.java @@ -51,7 +51,7 @@ public void missingVersionParsesCorrectlyTest() throws BrutException, IOExceptio String apk = "issue1264.apk"; // decode issue1264.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); ExtFile decodedApk = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/OutsideOfDirectoryEntryTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/OutsideOfDirectoryEntryTest.java index 80b4c4f5bc..2978b3aab5 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/OutsideOfDirectoryEntryTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/OutsideOfDirectoryEntryTest.java @@ -42,7 +42,7 @@ public static void beforeClass() throws Exception { String apk = "issue1589.apk"; // decode issue1589.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestNewDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java index 1805a27eac..31217342e7 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java @@ -52,7 +52,7 @@ public void checkIfDrawableFileDecodesProperly() throws BrutException, IOExcepti config.forceDelete = true; config.decodeResources = Config.DECODE_RESOURCES_NONE; // decode issue1498.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); File outDir = new File(sTmpDir + File.separator + apk + ".out"); // this should not raise an exception: apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ProtectedApkTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ProtectedApkTest.java index 2c979766b4..c1f419bbc6 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ProtectedApkTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ProtectedApkTest.java @@ -47,7 +47,7 @@ public void checkIfDecodeWorksWithoutCrash() throws BrutException, IOException { String apk = "protected-v1.apk"; // decode protected-v1.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java index 44ec664cb9..909db16516 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java @@ -52,7 +52,7 @@ public void checkIfMaliciousRawFileIsDisassembledProperly() throws BrutException Config config = Config.getDefaultConfig(); config.forceDelete = true; - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java index 1fbe855dd9..fcd6e9efac 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java @@ -53,7 +53,7 @@ public void checkDecodingModeAsRemove() throws BrutException, IOException { config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_REMOVE); // decode issue2836.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "remove.out"); File outDir = new File(sTmpDir + File.separator + apk + "remove.out"); @@ -84,7 +84,7 @@ public void checkDecodingModeAsDummies() throws BrutException, IOException { config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_DUMMY); // decode issue2836.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "dummies.out"); File outDir = new File(sTmpDir + File.separator + apk + "dummies.out"); @@ -115,7 +115,7 @@ public void checkDecodingModeAsLeave() throws BrutException, IOException { config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_RETAIN); // decode issue2836.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "leave.out"); File outDir = new File(sTmpDir + File.separator + apk + "leave.out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java index c3959250f4..409cc01ff7 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java @@ -50,7 +50,7 @@ public void afterClass() throws BrutException { @Test public void decodeWithExpectationOfSparseResources() throws BrutException, IOException { - File testApk = new File(sTestOrigDir, "sparse.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "sparse.apk"); LOGGER.info("Decoding sparse.apk..."); Config config = Config.getDefaultConfig(); @@ -67,7 +67,7 @@ public void decodeWithExpectationOfSparseResources() throws BrutException, IOExc @Test public void decodeWithExpectationOfNoSparseResources() throws BrutException, IOException { - File testApk = new File(sTestOrigDir, "not-sparse.apk"); + ExtFile testApk = new ExtFile(sTestOrigDir, "not-sparse.apk"); LOGGER.info("Decoding not-sparse.apk..."); Config config = Config.getDefaultConfig(); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/VectorDrawableTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/VectorDrawableTest.java index 255775a8d3..5f6c07061b 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/VectorDrawableTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/VectorDrawableTest.java @@ -50,7 +50,7 @@ public void checkIfDrawableFileDecodesProperly() throws BrutException, IOExcepti String apk = "issue1456.apk"; // decode issue1456.apk - ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk)); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); File outDir = new File(sTmpDir + File.separator + apk + ".out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/util/UnknownDirectoryTraversalTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/util/UnknownDirectoryTraversalTest.java index 269b3fc07e..27ddc960af 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/util/UnknownDirectoryTraversalTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/util/UnknownDirectoryTraversalTest.java @@ -50,32 +50,32 @@ public static void afterClass() throws BrutException { } @Test - public void validFileTest() throws IOException, BrutException { - String validFilename = BrutIO.sanitizeFilepath(sTmpDir, "file"); - assertEquals(validFilename, "file"); + public void validFileTest() throws BrutException, IOException { + String validFileName = BrutIO.sanitizePath(sTmpDir, "file"); + assertEquals(validFileName, "file"); - File validFile = new File(sTmpDir, validFilename); + File validFile = new File(sTmpDir, validFileName); assertTrue(validFile.isFile()); } @Test(expected = TraversalUnknownFileException.class) - public void invalidBackwardFileTest() throws IOException, BrutException { - BrutIO.sanitizeFilepath(sTmpDir, "../file"); + public void invalidBackwardFileTest() throws BrutException, IOException { + BrutIO.sanitizePath(sTmpDir, "../file"); } @Test(expected = RootUnknownFileException.class) - public void invalidRootFileTest() throws IOException, BrutException { + public void invalidRootFileTest() throws BrutException, IOException { String rootLocation = OSDetection.isWindows() ? "C:/" : File.separator; - BrutIO.sanitizeFilepath(sTmpDir, rootLocation + "file"); + BrutIO.sanitizePath(sTmpDir, rootLocation + "file"); } @Test(expected = InvalidUnknownFileException.class) - public void noFilePassedTest() throws IOException, BrutException { - BrutIO.sanitizeFilepath(sTmpDir, ""); + public void noFilePassedTest() throws BrutException, IOException { + BrutIO.sanitizePath(sTmpDir, ""); } @Test(expected = TraversalUnknownFileException.class) - public void invalidBackwardPathOnWindows() throws IOException, BrutException { + public void invalidBackwardPathOnWindows() throws BrutException, IOException { String invalidPath; if (! OSDetection.isWindows()) { invalidPath = "../../app"; @@ -83,12 +83,12 @@ public void invalidBackwardPathOnWindows() throws IOException, BrutException { invalidPath = "..\\..\\app.exe"; } - BrutIO.sanitizeFilepath(sTmpDir, invalidPath); + BrutIO.sanitizePath(sTmpDir, invalidPath); } @Test - public void validDirectoryFileTest() throws IOException, BrutException { - String validFilename = BrutIO.sanitizeFilepath(sTmpDir, "dir" + File.separator + "file"); - assertEquals("dir" + File.separator + "file", validFilename); + public void validDirectoryFileTest() throws BrutException, IOException { + String validFileName = BrutIO.sanitizePath(sTmpDir, "dir" + File.separator + "file"); + assertEquals("dir" + File.separator + "file", validFileName); } } diff --git a/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java b/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java index ecd5da77b9..a39aa69b6d 100644 --- a/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java +++ b/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java @@ -59,7 +59,7 @@ public boolean containsFile(String path) { SubPath subpath; try { subpath = getSubPath(path); - } catch (PathNotExist e) { + } catch (PathNotExist ex) { return false; } @@ -74,7 +74,7 @@ public boolean containsDir(String path) { SubPath subpath; try { subpath = getSubPath(path); - } catch (PathNotExist e) { + } catch (PathNotExist ex) { return false; } @@ -117,10 +117,9 @@ public OutputStream getFileOutput(String path) throws DirectoryException { } Directory dir; - // IMPOSSIBLE_EXCEPTION try { dir = createDir(parsed.dir); - } catch (PathAlreadyExists e) { + } catch (PathAlreadyExists ex) { dir = getAbstractDirs().get(parsed.dir); } return dir.getFileOutput(parsed.subpath); @@ -165,7 +164,7 @@ public boolean removeFile(String path) { SubPath subpath; try { subpath = getSubPath(path); - } catch (PathNotExist e) { + } catch (PathNotExist ex) { return false; } @@ -226,7 +225,7 @@ protected Map getAbstractDirs(boolean recursive) { } Map dirs = new LinkedHashMap<>(mDirs); - for (Map.Entry dir : getAbstractDirs().entrySet()) { + for (Map.Entry dir : mDirs.entrySet()) { for (Map.Entry subdir : dir.getValue().getAbstractDirs( true).entrySet()) { dirs.put(dir.getKey() + separator + subdir.getKey(), diff --git a/brut.j.dir/src/main/java/brut/directory/DirUtil.java b/brut.j.dir/src/main/java/brut/directory/DirUtil.java index 906fdac256..c6e96794f1 100644 --- a/brut.j.dir/src/main/java/brut/directory/DirUtil.java +++ b/brut.j.dir/src/main/java/brut/directory/DirUtil.java @@ -22,6 +22,7 @@ import brut.common.TraversalUnknownFileException; import brut.util.BrutIO; import brut.util.OS; + import java.io.*; import java.nio.file.FileSystemException; import java.nio.file.Files; @@ -34,15 +35,13 @@ private DirUtil() { // Private constructor for utility class } - public static void copyToDir(Directory in, Directory out) - throws DirectoryException { + public static void copyToDir(Directory in, Directory out) throws DirectoryException { for (String fileName : in.getFiles(true)) { copyToDir(in, out, fileName); } } - public static void copyToDir(Directory in, Directory out, - String[] fileNames) throws DirectoryException { + public static void copyToDir(Directory in, Directory out, String[] fileNames) throws DirectoryException { for (String fileName : fileNames) { copyToDir(in, out, fileName); } @@ -84,23 +83,24 @@ public static void copyToDir(Directory in, File out, String fileName) throws DirectoryException { try { if (in.containsDir(fileName)) { - OS.rmdir(new File(out, fileName)); - in.getDir(fileName).copyToDir(new File(out, fileName)); - } else if (!in.containsDir(fileName) && !in.containsFile(fileName)) { - // Skip copies of directories/files not found. - } else { - String cleanedFilename = BrutIO.sanitizeFilepath(out, fileName); - if (! cleanedFilename.isEmpty()) { - File outFile = new File(out, cleanedFilename); + File outDir = new File(out, fileName); + OS.rmdir(outDir); + in.getDir(fileName).copyToDir(outDir); + } else if (in.containsFile(fileName)) { + String validFileName = BrutIO.sanitizePath(out, fileName); + if (!validFileName.isEmpty()) { + File outFile = new File(out, validFileName); //noinspection ResultOfMethodCallIgnored outFile.getParentFile().mkdirs(); BrutIO.copyAndClose(in.getFileInput(fileName), Files.newOutputStream(outFile.toPath())); } + } else { + // Skip if directory/file not found } - } catch (FileSystemException exception) { - LOGGER.warning(String.format("Skipping file %s (%s)", fileName, exception.getReason())); - } catch (RootUnknownFileException | InvalidUnknownFileException | TraversalUnknownFileException | IOException exception) { - LOGGER.warning(String.format("Skipping file %s (%s)", fileName, exception.getMessage())); + } catch (FileSystemException ex) { + LOGGER.warning(String.format("Skipping file %s (%s)", fileName, ex.getReason())); + } catch (RootUnknownFileException | InvalidUnknownFileException | TraversalUnknownFileException | IOException ex) { + LOGGER.warning(String.format("Skipping file %s (%s)", fileName, ex.getMessage())); } catch (BrutException ex) { throw new DirectoryException("Error copying file: " + fileName, ex); } diff --git a/brut.j.dir/src/main/java/brut/directory/ExtFile.java b/brut.j.dir/src/main/java/brut/directory/ExtFile.java index 575ea9b338..5572848795 100644 --- a/brut.j.dir/src/main/java/brut/directory/ExtFile.java +++ b/brut.j.dir/src/main/java/brut/directory/ExtFile.java @@ -58,5 +58,14 @@ public void close() throws IOException { } } + @Override + public boolean delete() { + try { + close(); + } catch (IOException ignored) {} + + return super.delete(); + } + private Directory mDirectory; } diff --git a/brut.j.dir/src/main/java/brut/directory/FileDirectory.java b/brut.j.dir/src/main/java/brut/directory/FileDirectory.java index fd6e88a5e0..33b7fd59c7 100644 --- a/brut.j.dir/src/main/java/brut/directory/FileDirectory.java +++ b/brut.j.dir/src/main/java/brut/directory/FileDirectory.java @@ -70,8 +70,8 @@ protected AbstractDirectory createDirLocal(String name) throws DirectoryExceptio protected InputStream getFileInputLocal(String name) throws DirectoryException { try { return new FileInputStream(generatePath(name)); - } catch (FileNotFoundException e) { - throw new DirectoryException(e); + } catch (FileNotFoundException ex) { + throw new DirectoryException(ex); } } @@ -79,8 +79,8 @@ protected InputStream getFileInputLocal(String name) throws DirectoryException { protected OutputStream getFileOutputLocal(String name) throws DirectoryException { try { return new FileOutputStream(generatePath(name)); - } catch (FileNotFoundException e) { - throw new DirectoryException(e); + } catch (FileNotFoundException ex) { + throw new DirectoryException(ex); } } @@ -115,7 +115,6 @@ private void loadAll() { if (file.isFile()) { mFiles.add(file.getName()); } else { - // IMPOSSIBLE_EXCEPTION try { mDirs.put(file.getName(), new FileDirectory(file)); } catch (DirectoryException ignored) {} diff --git a/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java b/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java index b6072abe40..4eb8bc7600 100644 --- a/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java +++ b/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java @@ -51,8 +51,8 @@ public ZipRODirectory(File zipFile, String path) throws DirectoryException { super(); try { mZipFile = new ZipFile(zipFile); - } catch (IOException e) { - throw new DirectoryException(e); + } catch (IOException ex) { + throw new DirectoryException(ex); } mPath = path; } @@ -73,8 +73,8 @@ protected InputStream getFileInputLocal(String name) throws DirectoryException { try { return getZipFile().getInputStream(new ZipEntry(getPath() + name)); - } catch (IOException e) { - throw new PathNotExist(name, e); + } catch (IOException ex) { + throw new PathNotExist(name, ex); } } diff --git a/brut.j.dir/src/main/java/brut/directory/ZipUtils.java b/brut.j.dir/src/main/java/brut/directory/ZipUtils.java index db9dcdf36b..d632e3fb54 100644 --- a/brut.j.dir/src/main/java/brut/directory/ZipUtils.java +++ b/brut.j.dir/src/main/java/brut/directory/ZipUtils.java @@ -17,6 +17,9 @@ package brut.directory; import brut.common.BrutException; +import brut.common.InvalidUnknownFileException; +import brut.common.RootUnknownFileException; +import brut.common.TraversalUnknownFileException; import brut.util.BrutIO; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; @@ -24,64 +27,89 @@ import java.io.*; import java.nio.file.Files; import java.util.Collection; +import java.util.function.Predicate; +import java.util.logging.Logger; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipUtils { - - private static Collection mDoNotCompress; + private static final Logger LOGGER = Logger.getLogger(""); private ZipUtils() { // Private constructor for utility class } - public static void zipFoldersPreserveStream(final File folder, final ZipOutputStream zipOutputStream, final File assets, final Collection doNotCompress) - throws BrutException, IOException { + public static void zipDir(File dir, ZipOutputStream out, Collection doNotCompress) + throws IOException { + zipDir(dir, null, out, doNotCompress); + } + + public static void zipDir(File baseDir, String dirName, ZipOutputStream out, Collection doNotCompress) + throws IOException { + File dir; + if (dirName == null || dirName.isEmpty()) { + dir = baseDir; + } else { + dir = new File(baseDir, dirName); + } + if (!dir.isDirectory()) { + return; + } - mDoNotCompress = doNotCompress; - zipFolders(folder, zipOutputStream); + for (File file : dir.listFiles()) { + String fileName = baseDir.toURI().relativize(file.toURI()).getPath(); - // We manually set the assets because we need to retain the folder structure - if (assets != null) { - processFolder(assets, zipOutputStream, assets.getPath().length() - 6); + if (file.isDirectory()) { + zipDir(baseDir, fileName, out, doNotCompress); + } else if (file.isFile()) { + zipFile(baseDir, fileName, out, doNotCompress != null && !doNotCompress.isEmpty() + ? entryName -> doNotCompress.contains(entryName) + || doNotCompress.contains(FilenameUtils.getExtension(entryName)) + : entryName -> false); + } } } - private static void zipFolders(final File folder, final ZipOutputStream outputStream) - throws BrutException, IOException { - processFolder(folder, outputStream, folder.getPath().length() + 1); + public static void zipFile(File baseDir, String fileName, ZipOutputStream out, boolean doNotCompress) + throws IOException { + zipFile(baseDir, fileName, out, entryName -> doNotCompress); } - private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength) - throws BrutException, IOException { - for (final File file : folder.listFiles()) { - if (file.isFile()) { - final String cleanedPath = BrutIO.sanitizeFilepath(folder, file.getPath().substring(prefixLength)); - final ZipEntry zipEntry = new ZipEntry(BrutIO.adaptSeparatorToUnix(cleanedPath)); + private static void zipFile(File baseDir, String fileName, ZipOutputStream out, Predicate doNotCompress) + throws IOException { + try { + String validFileName = BrutIO.sanitizePath(baseDir, fileName); + if (validFileName.isEmpty()) { + return; + } + + File file = new File(baseDir, validFileName); + if (!file.isFile()) { + return; + } - // aapt binary by default takes in parameters via -0 arsc to list extensions that shouldn't be - // compressed. We will replicate that behavior - final String extension = FilenameUtils.getExtension(file.getAbsolutePath()); - if (mDoNotCompress != null && (mDoNotCompress.contains(extension) || mDoNotCompress.contains(zipEntry.getName()))) { - zipEntry.setMethod(ZipEntry.STORED); - zipEntry.setSize(file.length()); - BufferedInputStream unknownFile = new BufferedInputStream(Files.newInputStream(file.toPath())); - CRC32 crc = BrutIO.calculateCrc(unknownFile); + String entryName = BrutIO.adaptSeparatorToUnix(validFileName); + ZipEntry zipEntry = new ZipEntry(entryName); + + if (doNotCompress.test(entryName)) { + zipEntry.setMethod(ZipEntry.STORED); + zipEntry.setSize(file.length()); + try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(file.toPath()))) { + CRC32 crc = BrutIO.calculateCrc(bis); zipEntry.setCrc(crc.getValue()); - unknownFile.close(); - } else { - zipEntry.setMethod(ZipEntry.DEFLATED); } + } else { + zipEntry.setMethod(ZipEntry.DEFLATED); + } - zipOutputStream.putNextEntry(zipEntry); - try (FileInputStream inputStream = new FileInputStream(file)) { - IOUtils.copy(inputStream, zipOutputStream); - } - zipOutputStream.closeEntry(); - } else if (file.isDirectory()) { - processFolder(file, zipOutputStream, prefixLength); + out.putNextEntry(zipEntry); + try (InputStream in = Files.newInputStream(file.toPath())) { + IOUtils.copy(in, out); } + out.closeEntry(); + } catch (RootUnknownFileException | InvalidUnknownFileException | TraversalUnknownFileException ex) { + LOGGER.warning(String.format("Skipping file %s (%s)", fileName, ex.getMessage())); } } } diff --git a/brut.j.util/src/main/java/brut/util/AaptManager.java b/brut.j.util/src/main/java/brut/util/AaptManager.java index b1375b15d9..e62d33ead3 100644 --- a/brut.j.util/src/main/java/brut/util/AaptManager.java +++ b/brut.j.util/src/main/java/brut/util/AaptManager.java @@ -22,6 +22,8 @@ import java.util.List; public class AaptManager { + public static final int AAPT_VERSION_MIN = 1; + public static final int AAPT_VERSION_MAX = 2; public static File getAapt2() throws BrutException { return getAapt(2); @@ -31,59 +33,71 @@ public static File getAapt1() throws BrutException { return getAapt(1); } - private static File getAapt(Integer version) throws BrutException { - File aaptBinary; - String aaptVersion = getAaptBinaryName(version); + private static File getAapt(int version) throws BrutException { + String aaptName = getAaptBinaryName(version); - if (! OSDetection.is64Bit() && OSDetection.isMacOSX()) { - throw new BrutException("32 bit OS detected. No 32 bit binaries available."); + if (!OSDetection.is64Bit() && OSDetection.isMacOSX()) { + throw new BrutException(aaptName + " binaries are not available for 32-bit platform: " + OSDetection.returnOS()); } - // Set the 64 bit flag - aaptVersion += OSDetection.is64Bit() ? "_64" : ""; - - try { - if (OSDetection.isMacOSX()) { - aaptBinary = Jar.getResourceAsFile("/prebuilt/macosx/" + aaptVersion, AaptManager.class); - } else if (OSDetection.isUnix()) { - aaptBinary = Jar.getResourceAsFile("/prebuilt/linux/" + aaptVersion, AaptManager.class); - } else if (OSDetection.isWindows()) { - aaptBinary = Jar.getResourceAsFile("/prebuilt/windows/" + aaptVersion + ".exe", AaptManager.class); - } else { - throw new BrutException("Could not identify platform: " + OSDetection.returnOS()); - } - } catch (BrutException ex) { - throw new BrutException(ex); + StringBuilder aaptPath = new StringBuilder("/prebuilt/"); + if (OSDetection.isUnix()) { + aaptPath.append("linux"); + } else if (OSDetection.isMacOSX()) { + aaptPath.append("macosx"); + } else if (OSDetection.isWindows()) { + aaptPath.append("windows"); + } else { + throw new BrutException("Could not identify platform: " + OSDetection.returnOS()); + } + aaptPath.append("/"); + aaptPath.append(aaptName); + if (OSDetection.is64Bit()) { + aaptPath.append("_64"); + } + if (OSDetection.isWindows()) { + aaptPath.append(".exe"); } - if (aaptBinary.setExecutable(true)) { - return aaptBinary; + File aaptBinary = Jar.getResourceAsFile(aaptPath.toString(), AaptManager.class); + if (!aaptBinary.setExecutable(true)) { + throw new BrutException("Can't set aapt binary as executable"); } - throw new BrutException("Can't set aapt binary as executable"); + return aaptBinary; } - public static String getAaptExecutionCommand(String aaptPath, File aapt) throws BrutException { - if (! aaptPath.isEmpty()) { - File aaptFile = new File(aaptPath); - if (aaptFile.canRead() && aaptFile.exists()) { - //noinspection ResultOfMethodCallIgnored - aaptFile.setExecutable(true); - return aaptFile.getPath(); - } else { - throw new BrutException("binary could not be read: " + aaptFile.getAbsolutePath()); - } - } else { - return aapt.getAbsolutePath(); + public static String getAaptBinaryName(int version) { + switch (version) { + case 2: + return "aapt2"; + default: + return "aapt"; } } - public static int getAaptVersion(String aaptLocation) throws BrutException { - return getAaptVersion(new File(aaptLocation)); + public static int getAaptVersion(String aaptPath) throws BrutException { + return getAaptVersion(new File(aaptPath)); } - public static String getAaptBinaryName(Integer version) { - return "aapt" + (version == 2 ? "2" : ""); + public static int getAaptVersion(File aaptBinary) throws BrutException { + if (!aaptBinary.isFile() || !aaptBinary.canRead()) { + throw new BrutException("Can't read aapt binary: " + aaptBinary.getAbsolutePath()); + } + if (!aaptBinary.setExecutable(true)) { + throw new BrutException("Can't set aapt binary as executable: " + aaptBinary.getAbsolutePath()); + } + + List cmd = new ArrayList<>(); + cmd.add(aaptBinary.getAbsolutePath()); + cmd.add("version"); + + String version = OS.execAndReturn(cmd.toArray(new String[0])); + if (version == null) { + throw new BrutException("Could not execute aapt binary at location: " + aaptBinary.getAbsolutePath()); + } + + return getAppVersionFromString(version); } public static int getAppVersionFromString(String version) throws BrutException { @@ -98,23 +112,19 @@ public static int getAppVersionFromString(String version) throws BrutException { throw new BrutException("aapt version could not be identified: " + version); } - public static int getAaptVersion(File aapt) throws BrutException { - if (!aapt.isFile()) { - throw new BrutException("Could not identify aapt binary as executable."); + public static String getAaptExecutionCommand(String aaptPath, File aaptBinary) throws BrutException { + if (aaptPath.isEmpty()) { + return aaptBinary.getAbsolutePath(); } - //noinspection ResultOfMethodCallIgnored - aapt.setExecutable(true); - - List cmd = new ArrayList<>(); - cmd.add(aapt.getAbsolutePath()); - cmd.add("version"); - String version = OS.execAndReturn(cmd.toArray(new String[0])); - - if (version == null) { - throw new BrutException("Could not execute aapt binary at location: " + aapt.getAbsolutePath()); + aaptBinary = new File(aaptPath); + if (!aaptBinary.isFile() || !aaptBinary.canRead()) { + throw new BrutException("Can't read aapt binary: " + aaptBinary.getAbsolutePath()); + } + if (!aaptBinary.setExecutable(true)) { + throw new BrutException("Can't set aapt binary as executable: " + aaptBinary.getAbsolutePath()); } - return getAppVersionFromString(version); + return aaptBinary.getPath(); } } diff --git a/brut.j.util/src/main/java/brut/util/BrutIO.java b/brut.j.util/src/main/java/brut/util/BrutIO.java index e56867dc3d..8f319a4d94 100644 --- a/brut.j.util/src/main/java/brut/util/BrutIO.java +++ b/brut.j.util/src/main/java/brut/util/BrutIO.java @@ -24,13 +24,9 @@ import java.io.*; import java.util.zip.CRC32; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; public class BrutIO { - public static void copyAndClose(InputStream in, OutputStream out) - throws IOException { + public static void copyAndClose(InputStream in, OutputStream out) throws IOException { try { IOUtils.copy(in, out); } finally { @@ -68,23 +64,25 @@ public static CRC32 calculateCrc(InputStream input) throws IOException { CRC32 crc = new CRC32(); int bytesRead; byte[] buffer = new byte[8192]; - while((bytesRead = input.read(buffer)) != -1) { + while ((bytesRead = input.read(buffer)) != -1) { crc.update(buffer, 0, bytesRead); } return crc; } - public static String sanitizeFilepath(final File directory, final String entry) throws IOException, BrutException { - if (entry.isEmpty()) { + public static String sanitizePath(File baseDir, String path) + throws InvalidUnknownFileException, RootUnknownFileException, + TraversalUnknownFileException, IOException { + if (path.isEmpty()) { throw new InvalidUnknownFileException("Invalid Unknown File"); } - if (new File(entry).isAbsolute()) { + if (new File(path).isAbsolute()) { throw new RootUnknownFileException("Absolute Unknown Files is not allowed"); } - final String canonicalDirPath = directory.getCanonicalPath() + File.separator; - final String canonicalEntryPath = new File(directory, entry).getCanonicalPath(); + String canonicalDirPath = baseDir.getCanonicalPath() + File.separator; + String canonicalEntryPath = new File(baseDir, path).getCanonicalPath(); if (!canonicalEntryPath.startsWith(canonicalDirPath)) { throw new TraversalUnknownFileException("Directory Traversal is not allowed"); @@ -94,8 +92,11 @@ public static String sanitizeFilepath(final File directory, final String entry) return canonicalEntryPath.substring(canonicalDirPath.length()); } - public static boolean detectPossibleDirectoryTraversal(String entry) { - return entry.contains("../") || entry.contains("/..") || entry.contains("..\\") || entry.contains("\\.."); + public static boolean detectPossibleDirectoryTraversal(String path) { + return path.contains("../") + || path.contains("/..") + || path.contains("..\\") + || path.contains("\\.."); } public static String adaptSeparatorToUnix(String path) { @@ -107,17 +108,4 @@ public static String adaptSeparatorToUnix(String path) { return path; } - - public static void copy(File inputFile, ZipOutputStream outputFile) throws IOException { - try (FileInputStream fis = new FileInputStream(inputFile)) { - IOUtils.copy(fis, outputFile); - } - } - - public static void copy(ZipFile inputFile, ZipOutputStream outputFile, ZipEntry entry) throws IOException { - try (InputStream is = inputFile.getInputStream(entry)) { - IOUtils.copy(is, outputFile); - } - } - } diff --git a/brut.j.util/src/main/java/brut/util/OS.java b/brut.j.util/src/main/java/brut/util/OS.java index 58f3c53137..354db5207e 100644 --- a/brut.j.util/src/main/java/brut/util/OS.java +++ b/brut.j.util/src/main/java/brut/util/OS.java @@ -126,7 +126,7 @@ public static String execAndReturn(String[] cmd) { System.err.println("Stream collector did not terminate."); } return collector.get(); - } catch (IOException | InterruptedException e) { + } catch (IOException | InterruptedException ex) { return null; } } @@ -149,8 +149,8 @@ public static File createTempDirectory() throws BrutException { static class StreamForwarder extends Thread { - StreamForwarder(InputStream is, String type) { - mIn = is; + StreamForwarder(InputStream in, String type) { + mIn = in; mType = type; } diff --git a/brut.j.util/src/main/java/brut/util/OSDetection.java b/brut.j.util/src/main/java/brut/util/OSDetection.java index 2f7eae5c5c..63a5d5ea14 100644 --- a/brut.j.util/src/main/java/brut/util/OSDetection.java +++ b/brut.j.util/src/main/java/brut/util/OSDetection.java @@ -39,7 +39,7 @@ public static boolean is64Bit() { return arch != null && arch.endsWith("64") || wow64Arch != null && wow64Arch.endsWith("64"); } - return BIT.equalsIgnoreCase("64"); + return BIT.equals("64"); } public static String returnOS() { From 556628acc1fd4fafa6fd1f8785904ba6ce6ca7bd Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Sat, 21 Sep 2024 00:29:57 +0300 Subject: [PATCH 2/8] style: fix more redundancy --- .../main/java/brut/androlib/ApkBuilder.java | 25 +++++++++-------- .../main/java/brut/androlib/ApkDecoder.java | 27 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index 91dc20ec07..2b1a08cbb3 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -67,9 +67,10 @@ public ApkBuilder(Config config, ExtFile apkDir) { } public void build(File outApk) throws AndrolibException { + if (mConfig.jobs > 1) { + mWorker = new BackgroundWorker(mConfig.jobs - 1); + } try { - boolean isAsync = mConfig.jobs > 1; - mWorker = new BackgroundWorker(isAsync ? mConfig.jobs - 1 : 1); mApkInfo = ApkInfo.load(mApkDir); String minSdkVersion = mApkInfo.getMinSdkVersion(); @@ -90,16 +91,16 @@ public void build(File outApk) throws AndrolibException { outDir.mkdirs(); LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + outApk.getName() - + (isAsync ? " with " + mConfig.jobs + " threads" : "")); + + (mWorker != null ? " with " + mConfig.jobs + " threads" : "")); - buildSources(outDir, isAsync); + buildSources(outDir); File manifest = new File(mApkDir, "AndroidManifest.xml"); File manifestOrig = new File(mApkDir, "AndroidManifest.xml.orig"); backupManifestFile(manifest, manifestOrig); buildResources(outDir, manifest); - if (isAsync) { + if (mWorker != null) { mWorker.waitForFinish(); if (mBuildError.get() != null) { throw mBuildError.get(); @@ -154,13 +155,15 @@ public void build(File outApk) throws AndrolibException { } } } finally { - mWorker.shutdownNow(); + if (mWorker != null) { + mWorker.shutdownNow(); + } } } - private void buildSources(File outDir, boolean isAsync) throws AndrolibException { + private void buildSources(File outDir) throws AndrolibException { if (!copySourcesRaw(outDir, "classes.dex")) { - buildSourcesSmali(outDir, "smali", "classes.dex", isAsync); + buildSourcesSmali(outDir, "smali", "classes.dex"); } try { @@ -171,7 +174,7 @@ private void buildSources(File outDir, boolean isAsync) throws AndrolibException if (dirName.startsWith("smali_")) { String fileName = dirName.substring(dirName.indexOf("_") + 1) + ".dex"; if (!copySourcesRaw(outDir, fileName)) { - buildSourcesSmali(outDir, dirName, fileName, isAsync); + buildSourcesSmali(outDir, dirName, fileName); } } } @@ -208,9 +211,9 @@ private boolean copySourcesRaw(File outDir, String fileName) throws AndrolibExce return true; } - private void buildSourcesSmali(File outDir, String dirName, String fileName, boolean isAsync) + private void buildSourcesSmali(File outDir, String dirName, String fileName) throws AndrolibException { - if (isAsync) { + if (mWorker != null) { mWorker.submit(() -> { if (mBuildError.get() == null) { try { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 2bbd4cbb1b..cec8fb2b7b 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -67,9 +67,10 @@ public ApkInfo decode(File outDir) throws AndrolibException { if (!mApkFile.isFile() || !mApkFile.canRead()) { throw new InFileNotFoundException(); } + if (mConfig.jobs > 1) { + mWorker = new BackgroundWorker(mConfig.jobs - 1); + } try { - boolean isAsync = mConfig.jobs > 1; - mWorker = new BackgroundWorker(isAsync ? mConfig.jobs - 1 : 1); mApkInfo = new ApkInfo(mApkFile); try { @@ -81,16 +82,16 @@ public ApkInfo decode(File outDir) throws AndrolibException { outDir.mkdirs(); LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName() - + (isAsync ? " with " + mConfig.jobs + " threads" : "")); + + (mWorker != null ? " with " + mConfig.jobs + " threads" : "")); - decodeSources(outDir, isAsync); + decodeSources(outDir); ResourcesDecoder resDecoder = new ResourcesDecoder(mConfig, mApkInfo); decodeResources(outDir, resDecoder); decodeManifest(outDir, resDecoder); updateApkInfo(outDir, resDecoder); - if (isAsync) { + if (mWorker != null) { mWorker.waitForFinish(); if (mBuildError.get() != null) { throw mBuildError.get(); @@ -104,14 +105,16 @@ public ApkInfo decode(File outDir) throws AndrolibException { return mApkInfo; } finally { - mWorker.shutdownNow(); + if (mWorker != null) { + mWorker.shutdownNow(); + } try { mApkFile.close(); } catch (IOException ignored) {} } } - private void decodeSources(File outDir, boolean isAsync) throws AndrolibException { + private void decodeSources(File outDir) throws AndrolibException { if (!mApkInfo.hasSources()) { return; } @@ -122,7 +125,7 @@ private void decodeSources(File outDir, boolean isAsync) throws AndrolibExceptio break; case Config.DECODE_SOURCES_SMALI: case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: - decodeSourcesSmali(outDir, "classes.dex", isAsync); + decodeSourcesSmali(outDir, "classes.dex"); break; } @@ -137,11 +140,11 @@ private void decodeSources(File outDir, boolean isAsync) throws AndrolibExceptio copySourcesRaw(outDir, fileName); break; case Config.DECODE_SOURCES_SMALI: - decodeSourcesSmali(outDir, fileName, isAsync); + decodeSourcesSmali(outDir, fileName); break; case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: if (fileName.startsWith("classes")) { - decodeSourcesSmali(outDir, fileName, isAsync); + decodeSourcesSmali(outDir, fileName); } else { copySourcesRaw(outDir, fileName); } @@ -165,8 +168,8 @@ private void copySourcesRaw(File outDir, String fileName) throws AndrolibExcepti } } - private void decodeSourcesSmali(File outDir, String fileName, boolean isAsync) throws AndrolibException { - if (isAsync) { + private void decodeSourcesSmali(File outDir, String fileName) throws AndrolibException { + if (mWorker != null) { mWorker.submit(() -> { if (mBuildError.get() == null) { try { From 6457442cd5a97ea1aa3dde9a6abe8df6b7c024eb Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Sat, 21 Sep 2024 00:39:48 +0300 Subject: [PATCH 3/8] style: fix more redundancy --- .../src/main/java/brut/androlib/ApkBuilder.java | 9 ++++----- .../src/main/java/brut/androlib/ApkDecoder.java | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index 2b1a08cbb3..de15688615 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -211,24 +211,23 @@ private boolean copySourcesRaw(File outDir, String fileName) throws AndrolibExce return true; } - private void buildSourcesSmali(File outDir, String dirName, String fileName) - throws AndrolibException { + private void buildSourcesSmali(File outDir, String dirName, String fileName) throws AndrolibException { if (mWorker != null) { mWorker.submit(() -> { if (mBuildError.get() == null) { try { - buildSourcesSmali(outDir, dirName, fileName); + buildSourcesSmaliJob(outDir, dirName, fileName); } catch (AndrolibException ex) { mBuildError.compareAndSet(null, ex); } } }); } else { - buildSourcesSmali(outDir, dirName, fileName); + buildSourcesSmaliJob(outDir, dirName, fileName); } } - private void buildSourcesSmali(File outDir, String dirName, String fileName) throws AndrolibException { + private void buildSourcesSmaliJob(File outDir, String dirName, String fileName) throws AndrolibException { File smaliDir = new File(mApkDir, dirName); if (!smaliDir.isDirectory()) { return; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index cec8fb2b7b..094ac03a9a 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -173,18 +173,18 @@ private void decodeSourcesSmali(File outDir, String fileName) throws AndrolibExc mWorker.submit(() -> { if (mBuildError.get() == null) { try { - decodeSourcesSmali(outDir, fileName); + decodeSourcesSmaliJob(outDir, fileName); } catch (AndrolibException ex) { mBuildError.compareAndSet(null, ex); } } }); } else { - decodeSourcesSmali(outDir, fileName); + decodeSourcesSmaliJob(outDir, fileName); } } - private void decodeSourcesSmali(File outDir, String fileName) throws AndrolibException { + private void decodeSourcesSmaliJob(File outDir, String fileName) throws AndrolibException { File smaliDir; if (fileName.equals("classes.dex")) { smaliDir = new File(outDir, "smali"); From 3bd61b4ab05fb0a9e88a56be01fda711dc820143 Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Sat, 21 Sep 2024 03:56:29 +0300 Subject: [PATCH 4/8] tweak: consistent case-sensitivity for cmd and options --- .../src/main/java/brut/apktool/Main.java | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index dfeabd4ebc..9bc1ba25d3 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -88,24 +88,34 @@ public static void main(String[] args) throws BrutException { boolean cmdFound = false; for (String opt : commandLine.getArgs()) { - if (opt.equalsIgnoreCase("d") || opt.equalsIgnoreCase("decode")) { - cmdDecode(commandLine, config); - cmdFound = true; - } else if (opt.equalsIgnoreCase("b") || opt.equalsIgnoreCase("build")) { - cmdBuild(commandLine, config); - cmdFound = true; - } else if (opt.equalsIgnoreCase("if") || opt.equalsIgnoreCase("install-framework")) { - cmdInstallFramework(commandLine, config); - cmdFound = true; - } else if (opt.equalsIgnoreCase("empty-framework-dir")) { - cmdEmptyFrameworkDirectory(commandLine, config); - cmdFound = true; - } else if (opt.equalsIgnoreCase("list-frameworks")) { - cmdListFrameworks(commandLine, config); - cmdFound = true; - } else if (opt.equalsIgnoreCase("publicize-resources")) { - cmdPublicizeResources(commandLine, config); - cmdFound = true; + switch (opt) { + case "d": + case "decode": + cmdDecode(commandLine, config); + cmdFound = true; + break; + case "b": + case "build": + cmdBuild(commandLine, config); + cmdFound = true; + break; + case "if": + case "install-framework": + cmdInstallFramework(commandLine, config); + cmdFound = true; + break; + case "empty-framework-dir": + cmdEmptyFrameworkDirectory(commandLine, config); + cmdFound = true; + break; + case "list-frameworks": + cmdListFrameworks(commandLine, config); + cmdFound = true; + break; + case "publicize-resources": + cmdPublicizeResources(commandLine, config); + cmdFound = true; + break; } } From 3e72c1d2eb37032b3404a502dd90346b5e8d28be Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Sat, 21 Sep 2024 20:57:07 +0300 Subject: [PATCH 5/8] refactor: tracking unknownFiles via apkInfo is redundant 1) We take advantage of the fact that doNotCompress already tracks uncompressed files, including those separated into "unknown". With this change the "unknownFiles" is simply ignored, so it's backward-compatible with existing decoded APK dirs. Tweaked a few tests to match the removal of "unknownFiles". 2) Passing doNotCompress to AAPT is redundant, Apktool extracts the temp APK packed by AAPT to build/apk and then repackages it anyway, so it serves no purpose. --- .../main/java/brut/androlib/AaptInvoker.java | 48 ------------------- .../main/java/brut/androlib/ApkBuilder.java | 18 ++----- .../main/java/brut/androlib/ApkDecoder.java | 7 +-- .../main/java/brut/androlib/apk/ApkInfo.java | 13 ----- .../src/test/java/brut/androlib/BaseTest.java | 20 ++------ .../androlib/aapt1/BuildAndDecodeTest.java | 2 +- .../aapt1/UnknownCompressionTest.java | 8 ++-- .../androlib/aapt2/BuildAndDecodeTest.java | 2 +- .../brut/androlib/apk/ApkInfoReaderTest.java | 15 +----- .../apk/ApkInfoSerializationTest.java | 14 ++---- .../androlib/apk/ConsistentPropertyTest.java | 1 - .../test/resources/aapt1/testapp/apktool.yml | 9 +--- .../test/resources/aapt2/testapp/apktool.yml | 3 -- .../src/test/resources/apk/basic.yml | 2 - .../test/resources/apk/list_with_indent.yml | 2 - .../src/test/resources/apk/unknown_files.yml | 9 +--- 16 files changed, 22 insertions(+), 151 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java index 47868e2477..c9c17c8545 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java @@ -189,21 +189,6 @@ private void invokeAapt2(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-x"); } - if (!mApkInfo.doNotCompress.isEmpty()) { - if (customAapt) { - for (String file : mApkInfo.doNotCompress) { - cmd.add("-0"); - cmd.add(file); - } - } else { - // Use custom -e option to avoid limits on commandline length. - // Can only be used when custom aapt binary is not used. - String extensionsFilePath = createDoNotCompressExtensionsFile(mApkInfo.doNotCompress); - cmd.add("-e"); - cmd.add(extensionsFilePath); - } - } - if (!mApkInfo.resourcesAreCompressed) { cmd.add("-0"); cmd.add("arsc"); @@ -312,21 +297,6 @@ private void invokeAapt1(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-x"); } - if (!mApkInfo.doNotCompress.isEmpty()) { - if (customAapt) { - for (String file : mApkInfo.doNotCompress) { - cmd.add("-0"); - cmd.add(file); - } - } else { - // Use custom -e option to avoid limits on commandline length. - // Can only be used when custom aapt binary is not used. - String extensionsFilePath = createDoNotCompressExtensionsFile(mApkInfo.doNotCompress); - cmd.add("-e"); - cmd.add(extensionsFilePath); - } - } - if (!mApkInfo.resourcesAreCompressed) { cmd.add("-0"); cmd.add("arsc"); @@ -361,22 +331,4 @@ private void invokeAapt1(File apkFile, File manifest, File resDir, File rawDir, throw new AndrolibException(ex); } } - - private String createDoNotCompressExtensionsFile(Collection doNotCompress) throws AndrolibException { - try { - File doNotCompressFile = File.createTempFile("APKTOOL", null); - doNotCompressFile.deleteOnExit(); - - BufferedWriter fileWriter = new BufferedWriter(new FileWriter(doNotCompressFile)); - for (String extension : doNotCompress) { - fileWriter.write(extension); - fileWriter.newLine(); - } - fileWriter.close(); - - return doNotCompressFile.getAbsolutePath(); - } catch (IOException ex) { - throw new AndrolibException(ex); - } - } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index de15688615..5a710bed46 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -484,26 +484,16 @@ private void importRawFiles(ZipOutputStream outStream) throws AndrolibException } private void importUnknownFiles(ZipOutputStream outStream) throws AndrolibException { - Map unknownFiles = mApkInfo.unknownFiles; - if (unknownFiles == null || unknownFiles.isEmpty()) { - return; - } - File unknownDir = new File(mApkDir, "unknown"); if (!unknownDir.isDirectory()) { return; } LOGGER.info("Importing unknown files..."); - for (String fileName : unknownFiles.keySet()) { - boolean doNotCompress = Integer.parseInt(unknownFiles.get(fileName)) == 0; - - LOGGER.fine("Importing unknown file " + fileName + " (" + (doNotCompress ? "stored" : "deflated") + ")"); - try { - ZipUtils.zipFile(unknownDir, fileName, outStream, doNotCompress); - } catch (IOException ex) { - LOGGER.warning("Skipping file " + fileName + " (" + ex.getMessage() + ")"); - } + try { + ZipUtils.zipDir(unknownDir, outStream, mApkInfo.doNotCompress); + } catch (IOException ex) { + throw new AndrolibException(ex); } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 094ac03a9a..ad4cbf3c8f 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -40,7 +40,7 @@ public class ApkDecoder { private final static Logger LOGGER = Logger.getLogger(ApkDecoder.class.getName()); // extensions of files that are often packed uncompressed - public final static Pattern NO_COMPRESS_EXT_PATTERN = Pattern.compile( + private final static Pattern NO_COMPRESS_EXT_PATTERN = Pattern.compile( "dex|so|jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|" + "imy|xmf|mp4|m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv"); @@ -369,12 +369,7 @@ private void copyUnknownFiles(File outDir) throws AndrolibException { for (String fileName : in.getFiles(true)) { if (!ApkInfo.STANDARD_FILENAMES_PATTERN.matcher(fileName).matches()) { - // copy file out of archive into special "unknown" folder in.copyToDir(unknownDir, fileName); - // let's record the name of the file, and its compression type - // so that we may re-include it the same way - int compressionLevel = in.getCompressionLevel(fileName); - mApkInfo.addUnknownFileInfo(fileName, String.valueOf(compressionLevel)); } } } catch (DirectoryException ex) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java index 73d0d61313..63a9304ab3 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java @@ -51,7 +51,6 @@ public class ApkInfo implements YamlSerializable { public boolean resourcesAreCompressed; public boolean sharedLibrary; public boolean sparseResources; - public Map unknownFiles = new LinkedHashMap<>(); public List doNotCompress = new ArrayList<>(); /** @deprecated use {@link #resourcesAreCompressed} */ @@ -112,10 +111,6 @@ public boolean hasResources() throws AndrolibException { } } - public void addUnknownFileInfo(String file, String value) { - unknownFiles.put(file, value); - } - public String checkTargetSdkVersionBounds() { int target = mapSdkShorthandToVersion(getTargetSdkVersion()); @@ -279,11 +274,6 @@ public void readItem(YamlReader reader) throws AndrolibException { sparseResources = line.getValueBool(); break; } - case "unknownFiles": { - unknownFiles.clear(); - reader.readMap(unknownFiles); - break; - } case "doNotCompress": { doNotCompress.clear(); reader.readStringList(doNotCompress); @@ -304,9 +294,6 @@ public void write(YamlWriter writer) { writer.writeBool("resourcesAreCompressed", resourcesAreCompressed); writer.writeBool("sharedLibrary", sharedLibrary); writer.writeBool("sparseResources", sparseResources); - if (!unknownFiles.isEmpty()) { - writer.writeStringMap("unknownFiles", unknownFiles); - } if (!doNotCompress.isEmpty()) { writer.writeList("doNotCompress", doNotCompress); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java index be57380681..555e0c7c99 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BaseTest.java @@ -38,22 +38,6 @@ public class BaseTest { - protected void compareUnknownFiles() throws BrutException { - ApkInfo control = ApkInfo.load(sTestOrigDir); - ApkInfo test = ApkInfo.load(sTestNewDir); - assertNotNull(control.unknownFiles); - assertNotNull(test.unknownFiles); - - Map controlFiles = control.unknownFiles; - Map testFiles = test.unknownFiles; - assertEquals(controlFiles.size(), testFiles.size()); - - // Make sure that the compression methods are still the same - for (Map.Entry controlEntry : controlFiles.entrySet()) { - assertEquals(controlEntry.getValue(), testFiles.get(controlEntry.getKey())); - } - } - protected void compareBinaryFolder(String path, boolean res) throws BrutException, IOException { boolean exists = true; @@ -92,6 +76,10 @@ protected void compareAssetsFolder(String path) throws BrutException, IOExceptio compareBinaryFolder(File.separatorChar + "assets" + File.separatorChar + path, false); } + protected void compareUnknownFiles() throws BrutException, IOException { + compareBinaryFolder(File.separatorChar + "unknown", false); + } + protected void compareValuesFiles(String path) throws BrutException { compareXmlFiles("res/" + path, new ElementNameAndAttributeQualifier("name")); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java index 459ac4afc1..28ee8df898 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java @@ -540,7 +540,7 @@ public void libsTest() throws BrutException, IOException { } @Test - public void unknownFolderTest() throws BrutException { + public void unknownFolderTest() throws BrutException, IOException { compareUnknownFiles(); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java index e7f5999833..4783759330 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java @@ -71,7 +71,7 @@ public void pkmExtensionDeflatedTest() throws BrutException, IOException { // Check that control = rebuilt (both deflated) // Add extra check for checking not equal to 0, just in case control gets broken assertEquals(control, rebuilt); - assertNotSame(0, rebuilt); + assertNotSame(Integer.valueOf(0), rebuilt); } @Test @@ -95,11 +95,11 @@ public void confirmJsonFileIsDeflatedTest() throws BrutException, IOException { } @Test - public void confirmPngFileIsCorrectlyDeflatedTest() throws BrutException, IOException { + public void confirmPngFileIsStoredTest() throws BrutException, IOException { Integer control = sTestOrigDir.getDirectory().getCompressionLevel("950x150.png"); Integer rebuilt = sTestNewDir.getDirectory().getCompressionLevel("950x150.png"); - assertEquals(control, rebuilt); - assertEquals(Integer.valueOf(8), rebuilt); + assertNotSame(control, rebuilt); + assertEquals(Integer.valueOf(0), rebuilt); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java index 056a7937c2..2215266493 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java @@ -174,7 +174,7 @@ public void singleDexTest() throws BrutException, IOException { } @Test - public void unknownFolderTest() throws BrutException { + public void unknownFolderTest() throws BrutException, IOException { compareUnknownFiles(); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java index 4e3b1c2ebd..b2ac3aca8c 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java @@ -97,20 +97,12 @@ public void testUnknownFiles() throws AndrolibException { assertEquals("1.0", apkInfo.versionInfo.versionName); assertFalse(apkInfo.resourcesAreCompressed); assertNotNull(apkInfo.doNotCompress); - assertEquals(4, apkInfo.doNotCompress.size()); + assertEquals(5, apkInfo.doNotCompress.size()); assertEquals("assets/0byte_file.jpg", apkInfo.doNotCompress.get(0)); assertEquals("arsc", apkInfo.doNotCompress.get(1)); assertEquals("png", apkInfo.doNotCompress.get(2)); assertEquals("mp3", apkInfo.doNotCompress.get(3)); - assertNotNull(apkInfo.unknownFiles); - assertEquals(7, apkInfo.unknownFiles.size()); - assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/assets/a.txt")); - assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/b.txt")); - assertEquals("8", apkInfo.unknownFiles.get("hidden.file")); - assertEquals("8", apkInfo.unknownFiles.get("non\u007Fprintable.file")); - assertEquals("0", apkInfo.unknownFiles.get("stored.file")); - assertEquals("8", apkInfo.unknownFiles.get("unk_folder/unknown_file")); - assertEquals("8", apkInfo.unknownFiles.get("lib_bug603/bug603")); + assertEquals("stored.file", apkInfo.doNotCompress.get(4)); } @Test @@ -134,9 +126,6 @@ public void testUlist_with_indent() throws AndrolibException { assertEquals("22", apkInfo.getSdkInfo().get("targetSdkVersion")); assertFalse(apkInfo.sharedLibrary); assertTrue(apkInfo.sparseResources); - assertNotNull(apkInfo.unknownFiles); - assertEquals(1, apkInfo.unknownFiles.size()); - assertEquals("1", apkInfo.unknownFiles.get("hidden.file")); assertNotNull(apkInfo.versionInfo); assertEquals("71", apkInfo.versionInfo.versionCode); assertEquals("1.0.70", apkInfo.versionInfo.versionName); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java index 295493a06a..82200b82f0 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java @@ -37,7 +37,7 @@ public void checkApkInfoSerialization() throws IOException, AndrolibException { this.getClass().getResourceAsStream("/apk/unknown_files.yml")); check(control); - File savedApkInfo = folder.newFile( "saved.yml" ); + File savedApkInfo = folder.newFile("saved.yml"); control.save(savedApkInfo); try (FileInputStream fis = new FileInputStream(savedApkInfo)) { ApkInfo saved = ApkInfo.load(fis); @@ -59,19 +59,11 @@ private void check(ApkInfo apkInfo) { assertEquals("1.0", apkInfo.versionInfo.versionName); assertFalse(apkInfo.resourcesAreCompressed); assertNotNull(apkInfo.doNotCompress); - assertEquals(4, apkInfo.doNotCompress.size()); + assertEquals(5, apkInfo.doNotCompress.size()); assertEquals("assets/0byte_file.jpg", apkInfo.doNotCompress.get(0)); assertEquals("arsc", apkInfo.doNotCompress.get(1)); assertEquals("png", apkInfo.doNotCompress.get(2)); assertEquals("mp3", apkInfo.doNotCompress.get(3)); - assertNotNull(apkInfo.unknownFiles); - assertEquals(7, apkInfo.unknownFiles.size()); - assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/assets/a.txt")); - assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/b.txt")); - assertEquals("8", apkInfo.unknownFiles.get("hidden.file")); - assertEquals("8", apkInfo.unknownFiles.get("non\u007Fprintable.file")); - assertEquals("0", apkInfo.unknownFiles.get("stored.file")); - assertEquals("8", apkInfo.unknownFiles.get("unk_folder/unknown_file")); - assertEquals("8", apkInfo.unknownFiles.get("lib_bug603/bug603")); + assertEquals("stored.file", apkInfo.doNotCompress.get(4)); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java index bada5313e7..eb2f1594e0 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java @@ -43,7 +43,6 @@ public void testAssertingAllKnownApkInfoProperties() throws AndrolibException { assertFalse(apkInfo.resourcesAreCompressed); assertFalse(apkInfo.sharedLibrary); assertTrue(apkInfo.sparseResources); - assertEquals(1, apkInfo.unknownFiles.size()); assertEquals(2, apkInfo.doNotCompress.size()); assertFalse(apkInfo.compressionType); } diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml index 8362ef054a..aa0c138e3d 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml @@ -15,11 +15,4 @@ doNotCompress: - arsc - png - mp3 -unknownFiles: - AssetBundle/assets/a.txt: '8' - AssetBundle/b.txt: '8' - hidden.file: '8' - non\u007Fprintable.file: '8' - stored.file: '0' - unk_folder/unknown_file: '8' - lib_bug603/bug603: '8' +- stored.file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml index e83d2e54c2..12c746f57c 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml @@ -13,6 +13,3 @@ compressionType: false doNotCompress: - assets/0byte_file.jpg sparseResources: false -unknownFiles: - AssetBundle/assets/a.txt: '8' - AssetBundle/b.txt: '8' diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml b/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml index b51612c6bd..e98da55c2b 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml @@ -14,8 +14,6 @@ sdkInfo: targetSdkVersion: '22' sharedLibrary: false sparseResources: true -unknownFiles: - hidden.file: 1 usesFramework: ids: - 1 diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml b/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml index b51612c6bd..e98da55c2b 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml @@ -14,8 +14,6 @@ sdkInfo: targetSdkVersion: '22' sharedLibrary: false sparseResources: true -unknownFiles: - hidden.file: 1 usesFramework: ids: - 1 diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml b/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml index 8362ef054a..aa0c138e3d 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml @@ -15,11 +15,4 @@ doNotCompress: - arsc - png - mp3 -unknownFiles: - AssetBundle/assets/a.txt: '8' - AssetBundle/b.txt: '8' - hidden.file: '8' - non\u007Fprintable.file: '8' - stored.file: '0' - unk_folder/unknown_file: '8' - lib_bug603/bug603: '8' +- stored.file From 4d730d9fce8de1d14efdce454f0ce8ed797614f5 Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Tue, 24 Sep 2024 03:02:01 +0300 Subject: [PATCH 6/8] refactor: fix minSdkVersion from baksmali + clean up more redundancy * Regression: minSdkVersion inferred from baksmali was not stored properly. * The arsc extension can be generalized for simplicity as seen in AOSP source. https://cs.android.com/android/platform/superproject/main/+/main:external/deqp/scripts/android/build_apk.py;l=644?q=apk%20pack&ss=android%2Fplatform%2Fsuperproject%2Fmain:external%2F Note: NO_COMPRESS_EXT_PATTERN only collapses paths to a common extension. It does NOT force these extensions to be always uncompressed. doNotCompress is the one determining files/extensions that should be uncompressed. (no funcionality was changed) * resourcesAreCompressed in apkInfo is redundant. It was only used in invokeAapt, but not ApkBuilder. Its value is also never set by Apktool, only read. Like with doNotCompress, passing any kind of compression rules to AAPT is pointless, since we don't use the temp APK packed by AAPT directly - it's extracted and repacked by ApkBuilder, where doNotCompress already determines whether resources.arsc should or should not be compressed in the final APK. (no funcionality was changed) --- .../src/main/java/brut/androlib/AaptInvoker.java | 10 ---------- .../src/main/java/brut/androlib/ApkDecoder.java | 15 ++++++++------- .../src/main/java/brut/androlib/apk/ApkInfo.java | 10 ---------- .../java/brut/androlib/apk/ApkInfoReaderTest.java | 6 ++---- .../androlib/apk/ApkInfoSerializationTest.java | 1 - .../brut/androlib/apk/ConsistentPropertyTest.java | 2 -- .../test/resources/aapt1/issue1235/apktool.yml | 3 +-- .../src/test/resources/aapt1/testapp/apktool.yml | 1 - .../aapt2/issue2328/debuggable-false/apktool.yml | 3 +-- .../issue2328/debuggable-missing/apktool.yml | 3 +-- .../aapt2/issue2328/debuggable-true/apktool.yml | 3 +-- .../src/test/resources/aapt2/pkgid8/apktool.yml | 3 +-- .../src/test/resources/aapt2/testapp/apktool.yml | 1 - .../apktool-lib/src/test/resources/apk/basic.yml | 3 +-- .../src/test/resources/apk/cve20220476.yml | 3 +-- .../test/resources/apk/first_incorrect_indent.yml | 3 +-- .../src/test/resources/apk/list_with_indent.yml | 3 +-- .../test/resources/apk/skip_incorrect_indent.yml | 3 +-- .../src/test/resources/apk/standard.yml | 3 +-- .../src/test/resources/apk/unknown_fields.yml | 3 +-- .../src/test/resources/apk/unknown_files.yml | 1 - .../src/test/resources/decode/doctype/apktool.yml | 3 +-- .../test/resources/decode/issue2543/apktool.yml | 3 +-- 23 files changed, 24 insertions(+), 65 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java index c9c17c8545..a74a024dd3 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java @@ -189,11 +189,6 @@ private void invokeAapt2(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-x"); } - if (!mApkInfo.resourcesAreCompressed) { - cmd.add("-0"); - cmd.add("arsc"); - } - if (include != null) { for (File file : include) { cmd.add("-I"); @@ -297,11 +292,6 @@ private void invokeAapt1(File apkFile, File manifest, File resDir, File rawDir, cmd.add("-x"); } - if (!mApkInfo.resourcesAreCompressed) { - cmd.add("-0"); - cmd.add("arsc"); - } - if (include != null) { for (File file : include) { cmd.add("-I"); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index ad4cbf3c8f..2499538f7f 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -41,8 +41,8 @@ public class ApkDecoder { // extensions of files that are often packed uncompressed private final static Pattern NO_COMPRESS_EXT_PATTERN = Pattern.compile( - "dex|so|jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|" + - "imy|xmf|mp4|m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv"); + "dex|arsc|so|jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|" + + "rtttl|imy|xmf|mp4|m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv"); private final AtomicReference mBuildError = new AtomicReference<>(null); private final Config mConfig; @@ -101,6 +101,12 @@ public ApkInfo decode(File outDir) throws AndrolibException { copyOriginalFiles(outDir); copyRawFiles(outDir); copyUnknownFiles(outDir); + + // in case we have no resources, we should store the minSdk we pulled from the source opcode api level + if (!mApkInfo.hasResources() && mMinSdkVersion > 0) { + mApkInfo.setMinSdkVersion(Integer.toString(mMinSdkVersion)); + } + writeApkInfo(outDir); return mApkInfo; @@ -264,11 +270,6 @@ private void copyManifestRaw(File outDir) throws AndrolibException { private void updateApkInfo(File outDir, ResourcesDecoder resDecoder) throws AndrolibException { resDecoder.updateApkInfo(outDir); - // in case we have no resources, we should store the minSdk we pulled from the source opcode api level - if (!mApkInfo.hasResources() && mMinSdkVersion > 0) { - mApkInfo.setMinSdkVersion(Integer.toString(mMinSdkVersion)); - } - // record uncompressed files try { Map resFileMapping = resDecoder.getResFileMapping(); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java index 63a9304ab3..f204be9589 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java @@ -48,14 +48,10 @@ public class ApkInfo implements YamlSerializable { private Map sdkInfo = new LinkedHashMap<>(); public PackageInfo packageInfo = new PackageInfo(); public VersionInfo versionInfo = new VersionInfo(); - public boolean resourcesAreCompressed; public boolean sharedLibrary; public boolean sparseResources; public List doNotCompress = new ArrayList<>(); - /** @deprecated use {@link #resourcesAreCompressed} */ - public boolean compressionType; - public ApkInfo() { this(null); } @@ -261,11 +257,6 @@ public void readItem(YamlReader reader) throws AndrolibException { reader.readObject(versionInfo); break; } - case "compressionType": - case "resourcesAreCompressed": { - resourcesAreCompressed = line.getValueBool(); - break; - } case "sharedLibrary": { sharedLibrary = line.getValueBool(); break; @@ -291,7 +282,6 @@ public void write(YamlWriter writer) { writer.writeStringMap("sdkInfo", sdkInfo); writer.writeObject("packageInfo", packageInfo); writer.writeObject("versionInfo", versionInfo); - writer.writeBool("resourcesAreCompressed", resourcesAreCompressed); writer.writeBool("sharedLibrary", sharedLibrary); writer.writeBool("sparseResources", sparseResources); if (!doNotCompress.isEmpty()) { diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java index b2ac3aca8c..839b09fd02 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoReaderTest.java @@ -25,9 +25,8 @@ public class ApkInfoReaderTest { private void checkStandard(ApkInfo apkInfo) { assertEquals("standard.apk", apkInfo.apkFileName); - assertFalse(apkInfo.resourcesAreCompressed); assertEquals(1, apkInfo.doNotCompress.size()); - assertEquals("resources.arsc", apkInfo.doNotCompress.iterator().next()); + assertEquals("arsc", apkInfo.doNotCompress.iterator().next()); assertFalse(apkInfo.isFrameworkApk); assertNotNull(apkInfo.packageInfo); assertEquals("127", apkInfo.packageInfo.forcedPackageId); @@ -95,7 +94,6 @@ public void testUnknownFiles() throws AndrolibException { assertNotNull(apkInfo.versionInfo); assertEquals("1", apkInfo.versionInfo.versionCode); assertEquals("1.0", apkInfo.versionInfo.versionName); - assertFalse(apkInfo.resourcesAreCompressed); assertNotNull(apkInfo.doNotCompress); assertEquals(5, apkInfo.doNotCompress.size()); assertEquals("assets/0byte_file.jpg", apkInfo.doNotCompress.get(0)); @@ -131,7 +129,7 @@ public void testUlist_with_indent() throws AndrolibException { assertEquals("1.0.70", apkInfo.versionInfo.versionName); assertNotNull(apkInfo.doNotCompress); assertEquals(2, apkInfo.doNotCompress.size()); - assertEquals("resources.arsc", apkInfo.doNotCompress.get(0)); + assertEquals("arsc", apkInfo.doNotCompress.get(0)); assertEquals("png", apkInfo.doNotCompress.get(1)); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java index 82200b82f0..fc15a9081a 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ApkInfoSerializationTest.java @@ -57,7 +57,6 @@ private void check(ApkInfo apkInfo) { assertNotNull(apkInfo.versionInfo); assertEquals("1", apkInfo.versionInfo.versionCode); assertEquals("1.0", apkInfo.versionInfo.versionName); - assertFalse(apkInfo.resourcesAreCompressed); assertNotNull(apkInfo.doNotCompress); assertEquals(5, apkInfo.doNotCompress.size()); assertEquals("assets/0byte_file.jpg", apkInfo.doNotCompress.get(0)); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java index eb2f1594e0..8bd82fab89 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/apk/ConsistentPropertyTest.java @@ -40,10 +40,8 @@ public void testAssertingAllKnownApkInfoProperties() throws AndrolibException { assertEquals("com.test.basic", apkInfo.packageInfo.renameManifestPackage); assertEquals("71", apkInfo.versionInfo.versionCode); assertEquals("1.0.70", apkInfo.versionInfo.versionName); - assertFalse(apkInfo.resourcesAreCompressed); assertFalse(apkInfo.sharedLibrary); assertTrue(apkInfo.sparseResources); assertEquals(2, apkInfo.doNotCompress.size()); - assertFalse(apkInfo.compressionType); } } diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/issue1235/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt1/issue1235/apktool.yml index 9daf7e741f..96426c320e 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt1/issue1235/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt1/issue1235/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '127' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml index aa0c138e3d..87d8da1839 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/apktool.yml @@ -9,7 +9,6 @@ packageInfo: versionInfo: versionCode: '1' versionName: '1.0' -compressionType: false doNotCompress: - assets/0byte_file.jpg - arsc diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-false/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-false/apktool.yml index 73522b6244..ecc612a206 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-false/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-false/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '127' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-missing/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-missing/apktool.yml index 73522b6244..ecc612a206 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-missing/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-missing/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '127' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-true/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-true/apktool.yml index 73522b6244..ecc612a206 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-true/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/issue2328/debuggable-true/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '127' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/pkgid8/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt2/pkgid8/apktool.yml index 7487500608..dc7aef41a4 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt2/pkgid8/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/pkgid8/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '128' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml index 12c746f57c..f11e206fa0 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/apktool.yml @@ -9,7 +9,6 @@ packageInfo: versionInfo: versionCode: '1' versionName: '1.0' -compressionType: false doNotCompress: - assets/0byte_file.jpg sparseResources: false diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml b/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml index e98da55c2b..c1ecc383bf 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/basic.yml @@ -1,8 +1,7 @@ !!brut.androlib.meta.MetaInfo apkFileName: basic.apk -compressionType: false doNotCompress: - - resources.arsc + - arsc - png isFrameworkApk: false packageInfo: diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/cve20220476.yml b/brut.apktool/apktool-lib/src/test/resources/apk/cve20220476.yml index 2006ae81db..a705c8c7c5 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/cve20220476.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/cve20220476.yml @@ -1,9 +1,8 @@ !!brut.androlib.meta.MetaInfo apkFileName: cve20220476.apk -compressionType: false some_var: !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["https://127.0.0.1:8000"]]]] doNotCompress: -- resources.arsc +- arsc isFrameworkApk: false packageInfo: forcedPackageId: '127' diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/first_incorrect_indent.yml b/brut.apktool/apktool-lib/src/test/resources/apk/first_incorrect_indent.yml index 49e9b66901..08f35ab74e 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/first_incorrect_indent.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/first_incorrect_indent.yml @@ -1,9 +1,8 @@ !!brut.androlib.meta.MetaInfo version: 2.0.0 apkFileName: standard.apk -compressionType: false doNotCompress: -- resources.arsc +- arsc isFrameworkApk: false packageInfo: forcedPackageId: '127' diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml b/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml index e98da55c2b..c1ecc383bf 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/list_with_indent.yml @@ -1,8 +1,7 @@ !!brut.androlib.meta.MetaInfo apkFileName: basic.apk -compressionType: false doNotCompress: - - resources.arsc + - arsc - png isFrameworkApk: false packageInfo: diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/skip_incorrect_indent.yml b/brut.apktool/apktool-lib/src/test/resources/apk/skip_incorrect_indent.yml index cfdc2d7838..f135689727 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/skip_incorrect_indent.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/skip_incorrect_indent.yml @@ -1,9 +1,8 @@ !!brut.androlib.meta.MetaInfo apkFileName: standard.apk version: 2.0.0 -compressionType: false doNotCompress: -- resources.arsc +- arsc isFrameworkApk: false packageInfo: forcedPackageId: '127' diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/standard.yml b/brut.apktool/apktool-lib/src/test/resources/apk/standard.yml index 6aa78ecb55..deb61b225b 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/standard.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/standard.yml @@ -1,8 +1,7 @@ !!brut.androlib.meta.MetaInfo apkFileName: standard.apk -compressionType: false doNotCompress: -- resources.arsc +- arsc isFrameworkApk: false packageInfo: forcedPackageId: '127' diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/unknown_fields.yml b/brut.apktool/apktool-lib/src/test/resources/apk/unknown_fields.yml index 876e9fcaef..dd90de4075 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/unknown_fields.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/unknown_fields.yml @@ -1,9 +1,8 @@ !!brut.androlib.meta.MetaInfo apkFileName: standard.apk -compressionType: false test: test doNotCompress: -- resources.arsc +- arsc isFrameworkApk: false packageInfo: forcedPackageId: '127' diff --git a/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml b/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml index aa0c138e3d..87d8da1839 100644 --- a/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml +++ b/brut.apktool/apktool-lib/src/test/resources/apk/unknown_files.yml @@ -9,7 +9,6 @@ packageInfo: versionInfo: versionCode: '1' versionName: '1.0' -compressionType: false doNotCompress: - assets/0byte_file.jpg - arsc diff --git a/brut.apktool/apktool-lib/src/test/resources/decode/doctype/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/decode/doctype/apktool.yml index 1e3c552c84..fd49b569cc 100644 --- a/brut.apktool/apktool-lib/src/test/resources/decode/doctype/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/decode/doctype/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '127' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/decode/issue2543/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/decode/issue2543/apktool.yml index 7e576b377a..2fa938a15d 100644 --- a/brut.apktool/apktool-lib/src/test/resources/decode/issue2543/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/decode/issue2543/apktool.yml @@ -8,5 +8,4 @@ packageInfo: forcedPackageId: '127' versionInfo: versionCode: '1' - versionName: '1.0' -compressionType: false \ No newline at end of file + versionName: '1.0' \ No newline at end of file From d613502caa82ff5b1d89d08787155884db3ffa0a Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Wed, 25 Sep 2024 01:35:05 +0300 Subject: [PATCH 7/8] style: optional args come after required args --- .../apktool-cli/src/main/java/brut/apktool/Main.java | 4 ++-- .../src/main/java/brut/androlib/ApkBuilder.java | 10 +++++----- .../src/main/java/brut/androlib/ApkDecoder.java | 12 ++++++------ .../androlib/aapt1/AndroidOreoNotSparseTest.java | 2 +- .../brut/androlib/aapt1/AndroidOreoSparseTest.java | 2 +- .../brut/androlib/aapt1/BuildAndDecodeJarTest.java | 2 +- .../java/brut/androlib/aapt1/BuildAndDecodeTest.java | 2 +- .../brut/androlib/aapt1/DebugTagRetainedTest.java | 2 +- .../androlib/aapt1/DefaultBaksmaliVariableTest.java | 2 +- .../brut/androlib/aapt1/EmptyResourcesArscTest.java | 2 +- .../java/brut/androlib/aapt1/ExternalEntityTest.java | 2 +- .../brut/androlib/aapt1/LargeIntsInManifestTest.java | 2 +- .../brut/androlib/aapt1/ProviderAttributeTest.java | 2 +- .../java/brut/androlib/aapt1/SharedLibraryTest.java | 8 ++++---- .../test/java/brut/androlib/aapt1/SkipAssetTest.java | 4 ++-- .../brut/androlib/aapt1/UnknownCompressionTest.java | 2 +- .../java/brut/androlib/aapt2/BuildAndDecodeTest.java | 2 +- .../aapt2/DebuggableFalseChangeToTrueTest.java | 2 +- .../brut/androlib/aapt2/DebuggableTrueAddedTest.java | 2 +- .../androlib/aapt2/DebuggableTrueRetainedTest.java | 2 +- .../java/brut/androlib/aapt2/NetworkConfigTest.java | 2 +- .../brut/androlib/aapt2/NoNetworkConfigTest.java | 2 +- .../brut/androlib/aapt2/NonStandardPkgIdTest.java | 2 +- .../java/brut/androlib/decode/AndResGuardTest.java | 2 +- .../brut/androlib/decode/CompactResourceTest.java | 2 +- .../androlib/decode/DecodeKotlinCoroutinesTest.java | 8 ++++---- .../java/brut/androlib/decode/DuplicateDexTest.java | 6 +++--- .../decode/ForceManifestDecodeNoResourcesTest.java | 2 +- .../java/brut/androlib/decode/MinifiedArscTest.java | 2 +- .../decode/ParentDirectoryTraversalTest.java | 2 +- .../decode/ResourceDirectoryTraversalTest.java | 2 +- .../java/brut/androlib/decode/ResourceModeTest.java | 6 +++--- .../java/brut/androlib/decode/SparseFlagTest.java | 8 ++++---- .../androlib/res/src/DexStaticFieldValueTest.java | 4 ++-- 34 files changed, 59 insertions(+), 59 deletions(-) diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index 9bc1ba25d3..da8d52dd44 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -224,7 +224,7 @@ private static void cmdDecode(CommandLine cli, Config config) throws AndrolibExc } ExtFile apkFile = new ExtFile(apkName); - ApkDecoder decoder = new ApkDecoder(config, apkFile); + ApkDecoder decoder = new ApkDecoder(apkFile, config); try { decoder.decode(outDir); } catch (OutDirExistsException ex) { @@ -315,7 +315,7 @@ private static void cmdBuild(CommandLine cli, Config config) throws AndrolibExce } ExtFile apkDir = new ExtFile(apkDirName); - ApkBuilder builder = new ApkBuilder(config, apkDir); + ApkBuilder builder = new ApkBuilder(apkDir, config); builder.build(outFile); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index 5a710bed46..a1e72fb0d8 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -50,18 +50,18 @@ public class ApkBuilder { private final static Logger LOGGER = Logger.getLogger(ApkBuilder.class.getName()); - private final AtomicReference mBuildError = new AtomicReference<>(null); - private final Config mConfig; private final ExtFile mApkDir; - private BackgroundWorker mWorker; + private final Config mConfig; private ApkInfo mApkInfo; private int mMinSdkVersion = 0; + private BackgroundWorker mWorker; + private final AtomicReference mBuildError = new AtomicReference<>(null); public ApkBuilder(ExtFile apkDir) { - this(Config.getDefaultConfig(), apkDir); + this(apkDir, Config.getDefaultConfig()); } - public ApkBuilder(Config config, ExtFile apkDir) { + public ApkBuilder(ExtFile apkDir, Config config) { mConfig = config; mApkDir = apkDir; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 2499538f7f..36e71dab6d 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -44,20 +44,20 @@ public class ApkDecoder { "dex|arsc|so|jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|" + "rtttl|imy|xmf|mp4|m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv"); - private final AtomicReference mBuildError = new AtomicReference<>(null); - private final Config mConfig; private final ExtFile mApkFile; - private BackgroundWorker mWorker; + private final Config mConfig; private ApkInfo mApkInfo; private volatile int mMinSdkVersion = 0; + private BackgroundWorker mWorker; + private final AtomicReference mBuildError = new AtomicReference<>(null); public ApkDecoder(ExtFile apkFile) { - this(Config.getDefaultConfig(), apkFile); + this(apkFile, Config.getDefaultConfig()); } - public ApkDecoder(Config config, ExtFile apkFile) { - mConfig = config; + public ApkDecoder(ExtFile apkFile, Config config) { mApkFile = apkFile; + mConfig = config; } public ApkInfo decode(File outDir) throws AndrolibException { diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java index dddebae5ca..275d338ed2 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoNotSparseTest.java @@ -48,7 +48,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building not_sparse.apk..."); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } @AfterClass diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java index 8e8b1f97fa..a8d4cad53a 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/AndroidOreoSparseTest.java @@ -48,7 +48,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building sparse.apk..."); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } @AfterClass diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java index 9b85e70f28..812e74d846 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeJarTest.java @@ -43,7 +43,7 @@ public static void beforeClass() throws Exception { ExtFile testJar = new ExtFile(sTmpDir, "testjar.jar"); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestOrigDir).build(testJar); + new ApkBuilder(sTestOrigDir, config).build(testJar); LOGGER.info("Decoding testjar.jar..."); ApkDecoder apkDecoder = new ApkDecoder(testJar); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java index 28ee8df898..49ab1b9616 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java @@ -51,7 +51,7 @@ public static void beforeClass() throws Exception { ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding testapp.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java index b206789f25..2aafb45e51 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java @@ -52,7 +52,7 @@ public static void beforeClass() throws Exception { config.debugMode = true; ExtFile testApk = new ExtFile(sTmpDir, "issue1235.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding issue1235.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java index 182141657a..c3a63ed6d7 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DefaultBaksmaliVariableTest.java @@ -45,7 +45,7 @@ public static void beforeClass() throws Exception { ExtFile testJar = new ExtFile(sTmpDir, "issue1481.jar"); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestOrigDir).build(testJar); + new ApkBuilder(sTestOrigDir, config).build(testJar); LOGGER.info("Decoding issue1481.jar..."); ApkDecoder apkDecoder = new ApkDecoder(testJar); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java index e3e2c31526..4a46b79f28 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/EmptyResourcesArscTest.java @@ -51,7 +51,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue1730.apk..."); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } @AfterClass diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java index 7ddaa4a5bb..f24400971d 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ExternalEntityTest.java @@ -42,7 +42,7 @@ public static void beforeClass() throws Exception { ExtFile testApk = new ExtFile(sTestOrigDir, "doctype.apk"); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding doctype.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java index ea4061fbe7..e670b795f5 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/LargeIntsInManifestTest.java @@ -54,7 +54,7 @@ public void checkIfLargeIntsAreHandledTest() throws BrutException, IOException { Config config = Config.getDefaultConfig(); config.aaptVersion = 1; ExtFile testApk = new ExtFile(sTmpDir, apk + ".out"); - new ApkBuilder(config, testApk).build(null); + new ApkBuilder(testApk, config).build(null); String newApk = apk + ".out" + File.separator + "dist" + File.separator + apk; // decode issue767 again diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java index bf54c126ef..f618cdd206 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java @@ -61,7 +61,7 @@ public void isProviderStringReplacementWorking() throws BrutException, IOExcepti ExtFile testApk = new ExtFile(sTmpDir, apk + ".out"); Config config = Config.getDefaultConfig(); config.aaptVersion = 1; - new ApkBuilder(config, testApk).build(null); + new ApkBuilder(testApk, config).build(null); String newApk = apk + ".out" + File.separator + "dist" + File.separator + apk; assertTrue(fileExists(newApk)); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java index 3021db8800..fa5f08ab5f 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SharedLibraryTest.java @@ -88,23 +88,23 @@ public void isSharedResourceDecodingAndRebuildingWorking() throws IOException, B assertTrue(fileExists("2-shared.apk")); // decode client.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + client)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + client), config); File outDir = new File(sTmpDir + File.separator + client + ".out"); apkDecoder.decode(outDir); // decode library.apk - ApkDecoder libraryDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + library)); + ApkDecoder libraryDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + library), config); outDir = new File(sTmpDir + File.separator + library + ".out"); libraryDecoder.decode(outDir); // build client.apk ExtFile clientApk = new ExtFile(sTmpDir, client + ".out"); - new ApkBuilder(config, clientApk).build(null); + new ApkBuilder(clientApk, config).build(null); assertTrue(fileExists(client + ".out" + File.separator + "dist" + File.separator + client)); // build library.apk (shared library) ExtFile libraryApk = new ExtFile(sTmpDir, library + ".out"); - new ApkBuilder(config, libraryApk).build(null); + new ApkBuilder(libraryApk, config).build(null); assertTrue(fileExists(library + ".out" + File.separator + "dist" + File.separator + library)); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SkipAssetTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SkipAssetTest.java index f6d02f3b41..1e375304b5 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SkipAssetTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/SkipAssetTest.java @@ -52,7 +52,7 @@ public void checkIfEnablingSkipAssetWorks() throws BrutException, IOException { config.forceDelete = true; // decode issue1605.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(sTestOrigDir); @@ -69,7 +69,7 @@ public void checkControl() throws BrutException, IOException { config.forceDelete = true; // decode issue1605.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(sTestOrigDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java index 4783759330..930b41c438 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/UnknownCompressionTest.java @@ -54,7 +54,7 @@ public static void beforeClass() throws Exception { // build deflated_unknowns ExtFile clientApkFolder = new ExtFile(sTestOrigDir.getAbsolutePath() + ".out"); - new ApkBuilder(config, clientApkFolder).build(null); + new ApkBuilder(clientApkFolder, config).build(null); sTestNewDir = new ExtFile(clientApkFolder, "dist" + File.separator + apk); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java index 2215266493..ab008d4238 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java @@ -53,7 +53,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building testapp.apk..."); ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding testapp.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java index 79853d69b4..4c30f86431 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableFalseChangeToTrueTest.java @@ -52,7 +52,7 @@ public static void beforeClass() throws Exception { config.verbose = true; ExtFile testApk = new ExtFile(sTmpDir, "issue2328-debuggable-flase.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding issue2328-debuggable-flase.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java index f8c4ba661b..8cce9d8239 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueAddedTest.java @@ -52,7 +52,7 @@ public static void beforeClass() throws Exception { config.verbose = true; ExtFile testApk = new ExtFile(sTmpDir, "issue2328-debuggable-missing.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding issue2328-debuggable-missing.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java index 49fe6564ab..321129a070 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/DebuggableTrueRetainedTest.java @@ -52,7 +52,7 @@ public static void beforeClass() throws Exception { config.verbose = true; ExtFile testApk = new ExtFile(sTmpDir, "issue2328-debuggable-true.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding issue2328-debuggable-true.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java index a26f8beef6..f9789bc1c3 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NetworkConfigTest.java @@ -54,7 +54,7 @@ public static void beforeClass() throws Exception { Config config = Config.getDefaultConfig(); config.netSecConf = true; ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding testapp.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java index 93142a7ca6..d483daba7b 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NoNetworkConfigTest.java @@ -56,7 +56,7 @@ public static void beforeClass() throws Exception { Config config = Config.getDefaultConfig(); config.netSecConf = true; ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding testapp.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java index 72a2bf3d86..4158f51b5f 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/NonStandardPkgIdTest.java @@ -49,7 +49,7 @@ public static void beforeClass() throws Exception { LOGGER.info("Building pkgid8.apk..."); ExtFile testApk = new ExtFile(sTmpDir, "pkgid8.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding pkgid8.apk..."); ApkInfo testInfo = new ApkInfo(testApk); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java index 78b267958d..39518bd4c0 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/AndResGuardTest.java @@ -65,7 +65,7 @@ public void checkIfAndResDecodeRemapsRFolderInRawMode() throws BrutException, IO config.forceDelete = true; config.decodeResources = Config.DECODE_RESOURCES_NONE; String apk = "issue1170.apk"; - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + ".raw.out"); File outDir = new File(sTmpDir + File.separator + apk + ".raw.out"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java index 83cb595a81..c7f6a5835b 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/CompactResourceTest.java @@ -62,6 +62,6 @@ public void checkIfDecodeSucceeds() throws BrutException, IOException, ParserCon Config config = Config.getDefaultConfig(); LOGGER.info("Building duplicatedex.apk..."); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java index 9c8ec38d18..96561eac2c 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeKotlinCoroutinesTest.java @@ -55,7 +55,7 @@ public void kotlinCoroutinesDecodeTest() throws IOException, AndrolibException, Config config = Config.getDefaultConfig(); config.forceDelete = true; // decode kotlin coroutines - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); File coroutinesExceptionHandler = new File(sTmpDir + File.separator + apk + ".out" + File.separator + "META-INF" + File.separator + "services", "kotlinx.coroutines.CoroutineExceptionHandler"); @@ -71,18 +71,18 @@ public void kotlinCoroutinesEncodeAfterDecodeTest() throws BrutException, IOExce Config config = Config.getDefaultConfig(); config.forceDelete = true; // decode kotlin coroutines - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); // build kotlin coroutines ExtFile testApk = new ExtFile(sTmpDir, apk + ".out"); - new ApkBuilder(config, testApk).build(null); + new ApkBuilder(testApk, config).build(null); String newApk = apk + ".out" + File.separator + "dist" + File.separator + apk; assertTrue(fileExists(newApk)); // decode kotlin coroutines again - apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + newApk)); + apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + newApk), config); outDir = new File(sTmpDir + File.separator + apk + ".out.two"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java index 85b4eee864..a4ab7491e8 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DuplicateDexTest.java @@ -53,7 +53,7 @@ public void decodeAllSourcesShouldThrowException() throws BrutException, IOExcep LOGGER.info("Building duplicatedex.apk..."); Config config = Config.getDefaultConfig(); - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } @Test @@ -64,11 +64,11 @@ public void decodeUsingOnlyMainClassesMode() throws BrutException, IOException { Config config = Config.getDefaultConfig(); config.decodeSources = Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES; - ApkDecoder apkDecoder = new ApkDecoder(config, testApk); + ApkDecoder apkDecoder = new ApkDecoder(testApk, config); apkDecoder.decode(sTestNewDir); LOGGER.info("Building duplicatedex.apk..."); - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java index d6f919dcc3..da1acfed73 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ForceManifestDecodeNoResourcesTest.java @@ -139,7 +139,7 @@ private void decodeFile(String apk, short decodeResources, short decodeManifest, config.forceDelete = true; config.decodeResources = decodeResources; config.forceDecodeManifest = decodeManifest; - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(apk), config); apkDecoder.decode(new File(output)); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MinifiedArscTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MinifiedArscTest.java index f4e1207742..168bc9b98d 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MinifiedArscTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MinifiedArscTest.java @@ -48,7 +48,7 @@ public static void beforeClass() throws Exception { Config config = Config.getDefaultConfig(); config.forceDelete = true; // decode issue1157.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir, apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir, apk), config); // this should not raise an exception: apkDecoder.decode(sTestNewDir); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java index 31217342e7..f1bb0917d4 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ParentDirectoryTraversalTest.java @@ -52,7 +52,7 @@ public void checkIfDrawableFileDecodesProperly() throws BrutException, IOExcepti config.forceDelete = true; config.decodeResources = Config.DECODE_RESOURCES_NONE; // decode issue1498.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); File outDir = new File(sTmpDir + File.separator + apk + ".out"); // this should not raise an exception: apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java index 909db16516..a9245b66bf 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceDirectoryTraversalTest.java @@ -52,7 +52,7 @@ public void checkIfMaliciousRawFileIsDisassembledProperly() throws BrutException Config config = Config.getDefaultConfig(); config.forceDelete = true; - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); File outDir = new File(sTmpDir + File.separator + apk + ".out"); apkDecoder.decode(outDir); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java index fcd6e9efac..e0af62f454 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java @@ -53,7 +53,7 @@ public void checkDecodingModeAsRemove() throws BrutException, IOException { config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_REMOVE); // decode issue2836.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "remove.out"); File outDir = new File(sTmpDir + File.separator + apk + "remove.out"); @@ -84,7 +84,7 @@ public void checkDecodingModeAsDummies() throws BrutException, IOException { config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_DUMMY); // decode issue2836.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "dummies.out"); File outDir = new File(sTmpDir + File.separator + apk + "dummies.out"); @@ -115,7 +115,7 @@ public void checkDecodingModeAsLeave() throws BrutException, IOException { config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_RETAIN); // decode issue2836.apk - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(sTmpDir + File.separator + apk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(sTmpDir + File.separator + apk), config); sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "leave.out"); File outDir = new File(sTmpDir + File.separator + apk + "leave.out"); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java index 409cc01ff7..1667b28006 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/SparseFlagTest.java @@ -56,13 +56,13 @@ public void decodeWithExpectationOfSparseResources() throws BrutException, IOExc Config config = Config.getDefaultConfig(); config.frameworkTag = "issue-3298"; - ApkDecoder apkDecoder = new ApkDecoder(config, testApk); + ApkDecoder apkDecoder = new ApkDecoder(testApk, config); ApkInfo apkInfo = apkDecoder.decode(sTestNewDir); assertTrue("Expecting sparse resources", apkInfo.sparseResources); LOGGER.info("Building sparse.apk..."); - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } @Test @@ -73,12 +73,12 @@ public void decodeWithExpectationOfNoSparseResources() throws BrutException, IOE Config config = Config.getDefaultConfig(); config.frameworkTag = "issue-3298"; - ApkDecoder apkDecoder = new ApkDecoder(config, testApk); + ApkDecoder apkDecoder = new ApkDecoder(testApk, config); ApkInfo apkInfo = apkDecoder.decode(sTestNewDir); assertFalse("Expecting not-sparse resources", apkInfo.sparseResources); LOGGER.info("Building not-sparse.apk..."); - new ApkBuilder(config, sTestNewDir).build(testApk); + new ApkBuilder(sTestNewDir, config).build(testApk); } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/res/src/DexStaticFieldValueTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/res/src/DexStaticFieldValueTest.java index e8f8dd50f6..4007f5802d 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/res/src/DexStaticFieldValueTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/res/src/DexStaticFieldValueTest.java @@ -49,11 +49,11 @@ public static void beforeClass() throws Exception { LOGGER.info("Building issue2543.apk..."); File testApk = new File(sTmpDir, "issue2543.apk"); - new ApkBuilder(config, sTestOrigDir).build(testApk); + new ApkBuilder(sTestOrigDir, config).build(testApk); LOGGER.info("Decoding issue2543.apk..."); config.baksmaliDebugMode = false; - ApkDecoder apkDecoder = new ApkDecoder(config, new ExtFile(testApk)); + ApkDecoder apkDecoder = new ApkDecoder(new ExtFile(testApk), config); apkDecoder.decode(sTestNewDir); } From ac582cccf3bccbe6cd29da3ccd2000f852c96db5 Mon Sep 17 00:00:00 2001 From: IcyClawz Date: Wed, 25 Sep 2024 01:40:00 +0300 Subject: [PATCH 8/8] style: optional args come after required args --- .../apktool-lib/src/main/java/brut/androlib/ApkBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index a1e72fb0d8..a4cb2bee77 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -62,8 +62,8 @@ public ApkBuilder(ExtFile apkDir) { } public ApkBuilder(ExtFile apkDir, Config config) { - mConfig = config; mApkDir = apkDir; + mConfig = config; } public void build(File outApk) throws AndrolibException {