Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Introduce "res-mode" options. #3318

Merged
merged 21 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,30 @@ private static void cmdDecode(CommandLine cli, Config config) throws AndrolibExc
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")) {
Expand Down Expand Up @@ -301,8 +325,6 @@ private static void _version() {
}

private static void _Options() {

// create options
Option versionOption = Option.builder("version")
.longOpt("version")
.desc("Print the version.")
Expand Down Expand Up @@ -409,6 +431,13 @@ private static void _Options() {
.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)
Expand Down Expand Up @@ -469,6 +498,7 @@ private static void _Options() {
decodeOptions.addOption(apiLevelOption);
decodeOptions.addOption(noAssetOption);
decodeOptions.addOption(forceManOption);
decodeOptions.addOption(resolveResModeOption);

buildOptions.addOption(apiLevelOption);
buildOptions.addOption(debugBuiOption);
Expand Down Expand Up @@ -525,6 +555,7 @@ private static void _Options() {
allOptions.addOption(debugDecOption);
allOptions.addOption(noDbgOption);
allOptions.addOption(forceManOption);
allOptions.addOption(resolveResModeOption);
allOptions.addOption(noAssetOption);
allOptions.addOption(keepResOption);
allOptions.addOption(debugBuiOption);
Expand Down
28 changes: 28 additions & 0 deletions brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -72,8 +78,23 @@ public boolean isAapt2() {
return this.useAapt2 || this.aaptVersion == 2;
}

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() {
Expand Down Expand Up @@ -105,6 +126,13 @@ public void setDecodeSources(short mode) throws AndrolibException {
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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ public ResTypeSpec getType() {
return mType;
}

public boolean isDummyResSpec() {
return getName().startsWith("APKTOOL_DUMMY_");
}

public void addResource(ResResource res) throws AndrolibException {
addResource(res, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public boolean getAnalysisMode() {
return mConfig.analysisMode;
}

public Config getConfig() {
return mConfig;
}

public boolean isMainPkgLoaded() {
return mMainPkgLoaded;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
*
* 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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,
Expand All @@ -46,15 +47,21 @@ public String convertToResXmlFormat(ResScalarValue value)
}

@Override
protected void serializeBody(XmlSerializer serializer, ResResource res)
throws AndrolibException, IOException {
protected void serializeBody(XmlSerializer serializer, ResResource res) throws AndrolibException, IOException {
for (Duo<ResReferenceValue, ResIntValue> 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");
Expand All @@ -81,4 +88,6 @@ private String decodeValue(int value) throws AndrolibException {

private final Duo<ResReferenceValue, ResIntValue>[] mItems;
private final Map<Integer, String> mItemsCache = new HashMap<>();

private static final Logger LOGGER = Logger.getLogger(ResEnumAttr.class.getName());
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)) {
Expand Down Expand Up @@ -70,13 +73,19 @@ public String convertToResXmlFormat(ResScalarValue value)
}

@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");
}
}
Expand Down Expand Up @@ -130,24 +139,5 @@ private void loadFlags() {
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());
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ public void serializeToResValuesXml(XmlSerializer serializer,
}
}

// Dummy attributes should be <item> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void serializeToResValuesXml(XmlSerializer serializer,
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Loading