From a117132e39e982aee5609f19498769f62f86650b Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Sat, 9 Sep 2023 07:29:39 -0400 Subject: [PATCH] Feat: Introduce "res-mode" options. (#3318) * Revert "Remove Apktool Dummys. (#3258)" This reverts commit 0e226928ce428077aa3177b11c7da62b3c1aef27. * feat: properly add dummys * refactor: shorten ResTypeSpec * style: remove extra space * refactor: extract FlagItem into own class * refactor: notate which type is null * fix: only add dummys if enabled * feat: skip unknown (if enabled) * feat: introduce "res-mode" * feat: expose config on res table * feat: add method to base attr for res skips * fix: ensure autobuild doesn't choke * refactor: remove java17 enhanced switch * refactor: rename methods * refactor: cleanup res-mode param * test: introduction of test/sample apk * refactor: make ResXmlPatcher public for loading XML * test: assertions for dummy|leave|retain * fix: prevent using `@null` as a name * refactor: shorten long param for 'resm' * refactor: leave for preserve --- .../src/main/java/brut/apktool/Main.java | 35 ++++- .../src/main/java/brut/androlib/Config.java | 30 +++- .../brut/androlib/res/data/ResResSpec.java | 4 + .../java/brut/androlib/res/data/ResTable.java | 4 + .../brut/androlib/res/data/arsc/FlagItem.java | 41 +++++ .../androlib/res/data/value/ResEnumAttr.java | 15 +- .../androlib/res/data/value/ResFlagsAttr.java | 40 ++--- .../res/data/value/ResScalarValue.java | 5 + .../res/data/value/ResStyleValue.java | 2 +- .../androlib/res/data/value/ResValue.java | 6 +- .../androlib/res/decoder/ARSCDecoder.java | 34 ++++- .../brut/androlib/res/xml/ResXmlPatcher.java | 2 +- .../test/java/brut/androlib/TestUtils.java | 12 ++ .../androlib/decode/ResourceModeTest.java | 140 ++++++++++++++++++ .../resources/decode/issue2836/issue2836.apk | Bin 0 -> 54987 bytes 15 files changed, 335 insertions(+), 35 deletions(-) create mode 100644 brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/arsc/FlagItem.java create mode 100644 brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java create mode 100644 brut.apktool/apktool-lib/src/test/resources/decode/issue2836/issue2836.apk 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 d747b585..e329cc2e 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 @@ -167,6 +167,30 @@ public class Main { if (cli.hasOption("m") || cli.hasOption("match-original")) { config.analysisMode = true; } + if (cli.hasOption("res-mode") || cli.hasOption("resolve-resources-mode")) { + String mode = cli.getOptionValue("res-mode"); + if (mode == null) { + mode = cli.getOptionValue("resolve-resources-mode"); + } + switch (mode) { + case "remove": + case "delete": + config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_REMOVE); + break; + case "dummy": + case "dummies": + config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_DUMMY); + break; + case "keep": + case "preserve": + config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_RETAIN); + break; + default: + System.err.println("Unknown resolve resources mode: " + mode); + System.err.println("Expect: 'remove', 'dummy' or 'keep'."); + System.exit(1); + } + } File outDir; if (cli.hasOption("o") || cli.hasOption("output")) { @@ -301,8 +325,6 @@ public class Main { } private static void _Options() { - - // create options Option versionOption = Option.builder("version") .longOpt("version") .desc("Print the version.") @@ -409,6 +431,13 @@ public class Main { .desc("Skip changes detection and build all files.") .build(); + Option resolveResModeOption = Option.builder("resm") + .longOpt("resource-mode") + .desc("Sets the resolve resources mode. Possible values are: 'remove' (default), 'dummy' or 'keep'.") + .hasArg(true) + .argName("mode") + .build(); + Option aaptOption = Option.builder("a") .longOpt("aapt") .hasArg(true) @@ -469,6 +498,7 @@ public class Main { decodeOptions.addOption(apiLevelOption); decodeOptions.addOption(noAssetOption); decodeOptions.addOption(forceManOption); + decodeOptions.addOption(resolveResModeOption); buildOptions.addOption(apiLevelOption); buildOptions.addOption(debugBuiOption); @@ -525,6 +555,7 @@ public class Main { allOptions.addOption(debugDecOption); allOptions.addOption(noDbgOption); allOptions.addOption(forceManOption); + allOptions.addOption(resolveResModeOption); allOptions.addOption(noAssetOption); allOptions.addOption(keepResOption); allOptions.addOption(debugBuiOption); 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 9aad41e1..7fa561b0 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 @@ -23,6 +23,7 @@ import java.io.File; import java.util.logging.Logger; public class Config { + private static Config instance = null; private final static Logger LOGGER = Logger.getLogger(Config.class.getName()); public final static short DECODE_SOURCES_NONE = 0x0000; @@ -38,6 +39,10 @@ public class Config { public final static short DECODE_ASSETS_NONE = 0x0000; public final static short DECODE_ASSETS_FULL = 0x0001; + public final static short DECODE_RES_RESOLVE_REMOVE = 0x0000; + public final static short DECODE_RES_RESOLVE_DUMMY = 0x0001; + public final static short DECODE_RES_RESOLVE_RETAIN = 0x0002; + // Build options public boolean forceBuildAll = false; public boolean forceDeleteFramework = false; @@ -55,6 +60,7 @@ public class Config { public short decodeResources = DECODE_RESOURCES_FULL; public short forceDecodeManifest = FORCE_DECODE_MANIFEST_NONE; public short decodeAssets = DECODE_ASSETS_FULL; + public short decodeResolveMode = DECODE_RES_RESOLVE_REMOVE; public int apiLevel = 0; public boolean analysisMode = false; public boolean forceDelete = false; @@ -72,8 +78,23 @@ public class Config { return this.useAapt2 || this.aaptVersion == 2; } - private Config() { + public boolean isDecodeResolveModeUsingDummies() { + return decodeResolveMode == DECODE_RES_RESOLVE_DUMMY; + } + public boolean isDecodeResolveModeRemoving() { + return decodeResolveMode == DECODE_RES_RESOLVE_REMOVE; + } + + private Config() { + instance = this; + } + + public static Config getInstance() { + if (instance == null) { + instance = new Config(); + } + return instance; } private void setDefaultFrameworkDirectory() { @@ -105,6 +126,13 @@ public class Config { decodeSources = mode; } + public void setDecodeResolveMode(short mode) throws AndrolibException { + if (mode != DECODE_RES_RESOLVE_REMOVE && mode != DECODE_RES_RESOLVE_DUMMY && mode != DECODE_RES_RESOLVE_RETAIN) { + throw new AndrolibException("Invalid decode resources mode"); + } + decodeResolveMode = mode; + } + public void setDecodeResources(short mode) throws AndrolibException { if (mode != DECODE_RESOURCES_NONE && mode != DECODE_RESOURCES_FULL) { throw new AndrolibException("Invalid decode resources mode"); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java index 338a4e9c..c12b8240 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java @@ -105,6 +105,10 @@ public class ResResSpec { return mType; } + public boolean isDummyResSpec() { + return getName().startsWith("APKTOOL_DUMMY_"); + } + public void addResource(ResResource res) throws AndrolibException { addResource(res, false); } 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 f4341d18..1c29ef4f 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 @@ -70,6 +70,10 @@ public class ResTable { return mConfig.analysisMode; } + public Config getConfig() { + return mConfig; + } + public boolean isMainPkgLoaded() { return mMainPkgLoaded; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/arsc/FlagItem.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/arsc/FlagItem.java new file mode 100644 index 00000000..4c2dfb4a --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/arsc/FlagItem.java @@ -0,0 +1,41 @@ +/* + * 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.data.arsc; + +import brut.androlib.exceptions.AndrolibException; +import brut.androlib.res.data.value.ResReferenceValue; + +public class FlagItem { + public final ResReferenceValue ref; + public final int flag; + public String value; + + public FlagItem(ResReferenceValue ref, int flag) { + this.ref = ref; + this.flag = flag; + } + + public String getValue() throws AndrolibException { + if (value == null) { + if (ref.referentIsNull()) { + return String.format("APKTOOL_MISSING_0x%08x", ref.getRawIntValue()); + } + value = ref.getReferent().getName(); + } + return value; + } +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResEnumAttr.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResEnumAttr.java index 1cffc3b6..ed755e2e 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResEnumAttr.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResEnumAttr.java @@ -25,6 +25,7 @@ import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.logging.Logger; public class ResEnumAttr extends ResAttr { ResEnumAttr(ResReferenceValue parent, int type, Integer min, Integer max, @@ -46,15 +47,21 @@ public class ResEnumAttr extends ResAttr { } @Override - protected void serializeBody(XmlSerializer serializer, ResResource res) - throws AndrolibException, IOException { + protected void serializeBody(XmlSerializer serializer, ResResource res) throws AndrolibException, IOException { for (Duo duo : mItems) { int intVal = duo.m2.getValue(); + + // #2836 - Support skipping items if the resource cannot be identified. ResResSpec m1Referent = duo.m1.getReferent(); + if (m1Referent == null && shouldRemoveUnknownRes()) { + LOGGER.fine(String.format("null enum reference: m1=0x%08x(%s), m2=0x%08x(%s)", + duo.m1.getRawIntValue(), duo.m1.getType(), duo.m2.getRawIntValue(), duo.m2.getType())); + continue; + } serializer.startTag(null, "enum"); serializer.attribute(null, "name", - m1Referent != null ? m1Referent.getName() : "@null" + m1Referent != null ? m1Referent.getName() : String.format("APKTOOL_MISSING_0x%08x", duo.m1.getRawIntValue()) ); serializer.attribute(null, "value", String.valueOf(intVal)); serializer.endTag(null, "enum"); @@ -81,4 +88,6 @@ public class ResEnumAttr extends ResAttr { private final Duo[] mItems; private final Map mItemsCache = new HashMap<>(); + + private static final Logger LOGGER = Logger.getLogger(ResEnumAttr.class.getName()); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFlagsAttr.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFlagsAttr.java index d69ea509..cb8f89c0 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFlagsAttr.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFlagsAttr.java @@ -17,12 +17,15 @@ package brut.androlib.res.data.value; import brut.androlib.exceptions.AndrolibException; +import brut.androlib.res.data.ResResSpec; import brut.androlib.res.data.ResResource; +import brut.androlib.res.data.arsc.FlagItem; import brut.util.Duo; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.Arrays; +import java.util.logging.Logger; public class ResFlagsAttr extends ResAttr { ResFlagsAttr(ResReferenceValue parent, int type, Integer min, Integer max, @@ -38,7 +41,7 @@ public class ResFlagsAttr extends ResAttr { @Override public String convertToResXmlFormat(ResScalarValue value) throws AndrolibException { - if(value instanceof ResReferenceValue) { + if (value instanceof ResReferenceValue) { return value.encodeAsResXml(); } if (!(value instanceof ResIntValue)) { @@ -70,13 +73,19 @@ public class ResFlagsAttr extends ResAttr { } @Override - protected void serializeBody(XmlSerializer serializer, ResResource res) - throws AndrolibException, IOException { + protected void serializeBody(XmlSerializer serializer, ResResource res) throws AndrolibException, IOException { for (FlagItem item : mItems) { + ResResSpec referent = item.ref.getReferent(); + + // #2836 - Support skipping items if the resource cannot be identified. + if (referent == null && shouldRemoveUnknownRes()) { + LOGGER.fine(String.format("null flag reference: 0x%08x(%s)", item.ref.getValue(), item.ref.getType())); + continue; + } + serializer.startTag(null, "flag"); serializer.attribute(null, "name", item.getValue()); - serializer.attribute(null, "value", - String.format("0x%08x", item.flag)); + serializer.attribute(null, "value", String.format("0x%08x", item.flag)); serializer.endTag(null, "flag"); } } @@ -130,24 +139,5 @@ public class ResFlagsAttr extends ResAttr { private FlagItem[] mZeroFlags; private FlagItem[] mFlags; - private static class FlagItem { - public final ResReferenceValue ref; - public final int flag; - public String value; - - public FlagItem(ResReferenceValue ref, int flag) { - this.ref = ref; - this.flag = flag; - } - - public String getValue() throws AndrolibException { - if (value == null) { - if (ref.referentIsNull()) { - return "@null"; - } - value = ref.getReferent().getName(); - } - return value; - } - } + private static final Logger LOGGER = Logger.getLogger(ResFlagsAttr.class.getName()); } 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 21978f77..30ee763b 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 @@ -81,6 +81,11 @@ public abstract class ResScalarValue extends ResIntBasedValue implements } } + // Dummy attributes should be with type attribute + if (res.getResSpec().isDummyResSpec()) { + item = true; + } + // 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 diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResStyleValue.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResStyleValue.java index ab8dc271..2a81b4db 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResStyleValue.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResStyleValue.java @@ -53,7 +53,7 @@ public class ResStyleValue extends ResBagValue implements ResResSpec spec = mItem.m1.getReferent(); if (spec == null) { - LOGGER.fine(String.format("null reference: m1=0x%08x(%s), m2=0x%08x(%s)", + LOGGER.fine(String.format("null style reference: m1=0x%08x(%s), m2=0x%08x(%s)", mItem.m1.getRawIntValue(), mItem.m1.getType(), mItem.m2.getRawIntValue(), mItem.m2.getType())); continue; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValue.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValue.java index 1d12f497..dec2394e 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValue.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValue.java @@ -16,6 +16,10 @@ */ package brut.androlib.res.data.value; -public class ResValue { +import brut.androlib.Config; +public class ResValue { + public boolean shouldRemoveUnknownRes() { + return Config.getInstance().isDecodeResolveModeRemoving(); + } } 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 cb702f44..17e15b51 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 @@ -59,11 +59,11 @@ public class ARSCDecoder { mIn = new ExtCountingDataInput(new LittleEndianDataInputStream(arscStream)); mResTable = resTable; mKeepBroken = keepBroken; + mMissingResSpecMap = new LinkedHashMap<>(); } private ResPackage[] readResourceTable() throws IOException, AndrolibException { Set pkgs = new LinkedHashSet<>(); - ResTypeSpec typeSpec; int chunkNumber = 1; @@ -118,6 +118,10 @@ public class ARSCDecoder { } } + if (mResTable.getConfig().isDecodeResolveModeUsingDummies() && mPkg != null && mPkg.getResSpecCount() > 0) { + addMissingResSpecs(); + } + return pkgs.toArray(new ResPackage[0]); } @@ -300,6 +304,7 @@ public class ARSCDecoder { mResId = (mResId & 0xffff0000) | i; int offset = entryOffsetMap.get(i); if (offset == NO_ENTRY) { + mMissingResSpecMap.put(mResId, typeId); continue; } @@ -315,6 +320,8 @@ public class ARSCDecoder { EntryData entryData = readEntryData(); if (entryData != null) { readEntry(entryData); + } else { + mMissingResSpecMap.put(mResId, typeId); } } @@ -589,6 +596,30 @@ public class ARSCDecoder { mResTypeSpecs.put(resTypeSpec.getId(), resTypeSpec); } + private void addMissingResSpecs() throws AndrolibException { + for (int resId : mMissingResSpecMap.keySet()) { + int typeId = mMissingResSpecMap.get(resId); + String resName = "APKTOOL_DUMMY_" + Integer.toHexString(resId); + ResID id = new ResID(resId); + ResResSpec spec = new ResResSpec(id, resName, mPkg, mResTypeSpecs.get(typeId)); + + // If we already have this resID don't add it again. + if (! mPkg.hasResSpec(id)) { + mPkg.addResSpec(spec); + spec.getType().addResSpec(spec); + ResType resType = mPkg.getOrCreateConfig(new ResConfigFlags()); + + // We are going to make dummy attributes a null reference (@null) now instead of a boolean false. + // This is because aapt2 is stricter when it comes to what we can put in an application. + ResValue value = new ResReferenceValue(mPkg, 0, ""); + + ResResource res = new ResResource(resType, spec, value); + resType.addResource(res); + spec.addResource(res); + } + } + } + private ARSCHeader nextChunk() throws IOException { return mHeader = ARSCHeader.read(mIn); } @@ -614,6 +645,7 @@ public class ARSCDecoder { private ResType mType; private int mResId; private int mTypeIdOffset = 0; + private final HashMap mMissingResSpecMap; private final HashMap mResTypeSpecs = new HashMap<>(); private final static short ENTRY_FLAG_COMPLEX = 0x0001; 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 53cdf52c..0acd9328 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 @@ -365,7 +365,7 @@ public final class ResXmlPatcher { * @throws SAXException * @throws ParserConfigurationException */ - private static Document loadDocument(File file) + public static Document loadDocument(File file) throws IOException, SAXException, ParserConfigurationException { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java index b2b9d2a5..855326ff 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java @@ -18,15 +18,19 @@ package brut.androlib; import brut.androlib.exceptions.AndrolibException; import brut.androlib.res.Framework; +import brut.androlib.res.xml.ResXmlPatcher; import brut.common.BrutException; import brut.directory.DirUtil; import brut.directory.Directory; import brut.directory.FileDirectory; import brut.util.OS; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; +import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.net.URL; import java.net.URLDecoder; @@ -77,6 +81,14 @@ public abstract class TestUtils { } } + public static Document getDocumentFromFile(File file) throws BrutException { + try { + return ResXmlPatcher.loadDocument(file); + } catch (ParserConfigurationException | SAXException | IOException ex) { + throw new BrutException(ex); + } + } + public static void copyResourceDir(Class class_, String dirPath, File out) throws BrutException { if (!out.exists()) { out.mkdirs(); 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 new file mode 100644 index 00000000..1fbe855d --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ResourceModeTest.java @@ -0,0 +1,140 @@ +/* + * 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.decode; + +import brut.androlib.ApkDecoder; +import brut.androlib.BaseTest; +import brut.androlib.Config; +import brut.androlib.TestUtils; +import brut.directory.ExtFile; +import brut.common.BrutException; +import brut.util.OS; +import java.io.File; +import java.io.IOException; + +import org.junit.*; +import org.w3c.dom.Document; + +import static org.junit.Assert.*; + +public class ResourceModeTest extends BaseTest { + + @BeforeClass + public static void beforeClass() throws Exception { + TestUtils.cleanFrameworkFile(); + sTmpDir = new ExtFile(OS.createTempDirectory()); + TestUtils.copyResourceDir(ResourceModeTest.class, "decode/issue2836/", sTmpDir); + } + + @AfterClass + public static void afterClass() throws BrutException { + OS.rmdir(sTmpDir); + } + + @Test + public void checkDecodingModeAsRemove() throws BrutException, IOException { + String apk = "issue2836.apk"; + + Config config = Config.getDefaultConfig(); + config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_REMOVE); + + // decode issue2836.apk + ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "remove.out"); + + File outDir = new File(sTmpDir + File.separator + apk + "remove.out"); + apkDecoder.decode(outDir); + + File stringsXml = new File(sTestOrigDir,"res/values/strings.xml"); + assertTrue(stringsXml.isFile()); + + File attrXml = new File(sTestOrigDir,"res/values/attrs.xml"); + Document attrDocument = TestUtils.getDocumentFromFile(attrXml); + assertEquals(3, attrDocument.getElementsByTagName("enum").getLength()); + + File colorXml = new File(sTestOrigDir,"res/values/colors.xml"); + Document colorDocument = TestUtils.getDocumentFromFile(colorXml); + assertEquals(8, colorDocument.getElementsByTagName("color").getLength()); + assertEquals(0, colorDocument.getElementsByTagName("item").getLength()); + + File publicXml = new File(sTestOrigDir,"res/values/public.xml"); + Document publicDocument = TestUtils.getDocumentFromFile(publicXml); + assertEquals(21, publicDocument.getElementsByTagName("public").getLength()); + } + + @Test + public void checkDecodingModeAsDummies() throws BrutException, IOException { + String apk = "issue2836.apk"; + + Config config = Config.getDefaultConfig(); + config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_DUMMY); + + // decode issue2836.apk + ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "dummies.out"); + + File outDir = new File(sTmpDir + File.separator + apk + "dummies.out"); + apkDecoder.decode(outDir); + + File stringsXml = new File(sTestOrigDir,"res/values/strings.xml"); + assertTrue(stringsXml.isFile()); + + File attrXml = new File(sTestOrigDir,"res/values/attrs.xml"); + Document attrDocument = TestUtils.getDocumentFromFile(attrXml); + assertEquals(4, attrDocument.getElementsByTagName("enum").getLength()); + + File colorXml = new File(sTestOrigDir,"res/values/colors.xml"); + Document colorDocument = TestUtils.getDocumentFromFile(colorXml); + assertEquals(8, colorDocument.getElementsByTagName("color").getLength()); + assertEquals(1, colorDocument.getElementsByTagName("item").getLength()); + + File publicXml = new File(sTestOrigDir,"res/values/public.xml"); + Document publicDocument = TestUtils.getDocumentFromFile(publicXml); + assertEquals(22, publicDocument.getElementsByTagName("public").getLength()); + } + + @Test + public void checkDecodingModeAsLeave() throws BrutException, IOException { + String apk = "issue2836.apk"; + + Config config = Config.getDefaultConfig(); + config.setDecodeResolveMode(Config.DECODE_RES_RESOLVE_RETAIN); + + // decode issue2836.apk + ApkDecoder apkDecoder = new ApkDecoder(config, new File(sTmpDir + File.separator + apk)); + sTestOrigDir = new ExtFile(sTmpDir + File.separator + apk + "leave.out"); + + File outDir = new File(sTmpDir + File.separator + apk + "leave.out"); + apkDecoder.decode(outDir); + + File stringsXml = new File(sTestOrigDir,"res/values/strings.xml"); + assertTrue(stringsXml.isFile()); + + File attrXml = new File(sTestOrigDir,"res/values/attrs.xml"); + Document attrDocument = TestUtils.getDocumentFromFile(attrXml); + assertEquals(4, attrDocument.getElementsByTagName("enum").getLength()); + + File colorXml = new File(sTestOrigDir,"res/values/colors.xml"); + Document colorDocument = TestUtils.getDocumentFromFile(colorXml); + assertEquals(8, colorDocument.getElementsByTagName("color").getLength()); + assertEquals(0, colorDocument.getElementsByTagName("item").getLength()); + + File publicXml = new File(sTestOrigDir,"res/values/public.xml"); + Document publicDocument = TestUtils.getDocumentFromFile(publicXml); + assertEquals(21, publicDocument.getElementsByTagName("public").getLength()); + } +} diff --git a/brut.apktool/apktool-lib/src/test/resources/decode/issue2836/issue2836.apk b/brut.apktool/apktool-lib/src/test/resources/decode/issue2836/issue2836.apk new file mode 100644 index 0000000000000000000000000000000000000000..367304fd052bf1df41891941d8bc5d66e94eca98 GIT binary patch literal 54987 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 I$C9G|0mh7$HUIzs literal 0 HcmV?d00001