mirror of
https://github.com/revanced/Apktool.git
synced 2025-04-30 14:14:25 +02:00
Reworks Attr/Array Handler (#3326)
* test: add example pkcs key * fix: rework towards ResScalarValue instead of ResIntValue * fix: prefer res name instead of "guessing" based on ids
This commit is contained in:
parent
c07e4a92e6
commit
515af4faf8
@ -23,9 +23,11 @@ import java.util.*;
|
||||
public final class ResTypeSpec {
|
||||
|
||||
public static final String RES_TYPE_NAME_ARRAY = "array";
|
||||
public static final String RES_TYPE_NAME_PLURALS = "plurals";
|
||||
public static final String RES_TYPE_NAME_STYLES = "style";
|
||||
public static final String RES_TYPE_NAME_ATTR = "attr";
|
||||
public static final String RES_TYPE_NAME_ATTR_PRIVATE = "^attr-private";
|
||||
public static final String RES_TYPE_NAME_PLURALS = "plurals";
|
||||
public static final String RES_TYPE_NAME_STRING = "string";
|
||||
public static final String RES_TYPE_NAME_STYLES = "style";
|
||||
|
||||
private final String mName;
|
||||
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<>();
|
||||
@ -46,7 +48,7 @@ public final class ResTypeSpec {
|
||||
}
|
||||
|
||||
public boolean isString() {
|
||||
return mName.equalsIgnoreCase("string");
|
||||
return mName.equalsIgnoreCase(RES_TYPE_NAME_STRING);
|
||||
}
|
||||
|
||||
public ResResSpec getResSpec(String name) throws AndrolibException {
|
||||
|
@ -91,6 +91,4 @@ public class ResArrayValue extends ResBagValue implements ResValuesXmlSerializab
|
||||
|
||||
private final ResScalarValue[] mItems;
|
||||
private final String[] AllowedArrayTypes = {"string", "integer"};
|
||||
|
||||
public static final int BAG_KEY_ARRAY_START = 0x02000000;
|
||||
}
|
||||
|
@ -64,38 +64,39 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
|
||||
public static ResAttr factory(ResReferenceValue parent,
|
||||
Duo<Integer, ResScalarValue>[] items, ResValueFactory factory,
|
||||
ResPackage pkg) throws AndrolibException {
|
||||
|
||||
int type = ((ResIntValue) items[0].m2).getValue();
|
||||
int scalarType = type & 0xffff;
|
||||
Integer min = null, max = null;
|
||||
Boolean l10n = null;
|
||||
int i;
|
||||
for (i = 1; i < items.length; i++) {
|
||||
switch (items[i].m1) {
|
||||
case BAG_KEY_ATTR_MIN:
|
||||
min = ((ResIntValue) items[i].m2).getValue();
|
||||
min = (items[i].m2).getRawIntValue();
|
||||
continue;
|
||||
case BAG_KEY_ATTR_MAX:
|
||||
max = ((ResIntValue) items[i].m2).getValue();
|
||||
max = (items[i].m2).getRawIntValue();
|
||||
continue;
|
||||
case BAG_KEY_ATTR_L10N:
|
||||
l10n = ((ResIntValue) items[i].m2).getValue() != 0;
|
||||
l10n = (items[i].m2).getRawIntValue() != 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// #2806 - Make sure we handle int-based values and not just ResIntValue
|
||||
int rawValue = items[0].m2.getRawIntValue();
|
||||
int scalarType = rawValue & 0xffff;
|
||||
|
||||
if (i == items.length) {
|
||||
return new ResAttr(parent, scalarType, min, max, l10n);
|
||||
}
|
||||
Duo<ResReferenceValue, ResIntValue>[] attrItems = new Duo[items.length - i];
|
||||
Duo<ResReferenceValue, ResScalarValue>[] attrItems = new Duo[items.length - i];
|
||||
int j = 0;
|
||||
for (; i < items.length; i++) {
|
||||
int resId = items[i].m1;
|
||||
pkg.addSynthesizedRes(resId);
|
||||
attrItems[j++] = new Duo<>(factory.newReference(resId, null), (ResIntValue) items[i].m2);
|
||||
attrItems[j++] = new Duo<>(factory.newReference(resId, null), items[i].m2);
|
||||
}
|
||||
switch (type & 0xff0000) {
|
||||
switch (rawValue & 0xff0000) {
|
||||
case TYPE_ENUM:
|
||||
return new ResEnumAttr(parent, scalarType, min, max, l10n, attrItems);
|
||||
case TYPE_FLAGS:
|
||||
@ -145,7 +146,6 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
|
||||
private final Integer mMax;
|
||||
private final Boolean mL10n;
|
||||
|
||||
public static final int BAG_KEY_ATTR_TYPE = 0x01000000;
|
||||
private static final int BAG_KEY_ATTR_MIN = 0x01000001;
|
||||
private static final int BAG_KEY_ATTR_MAX = 0x01000002;
|
||||
private static final int BAG_KEY_ATTR_L10N = 0x01000003;
|
||||
|
@ -29,7 +29,7 @@ import java.util.logging.Logger;
|
||||
|
||||
public class ResEnumAttr extends ResAttr {
|
||||
ResEnumAttr(ResReferenceValue parent, int type, Integer min, Integer max,
|
||||
Boolean l10n, Duo<ResReferenceValue, ResIntValue>[] items) {
|
||||
Boolean l10n, Duo<ResReferenceValue, ResScalarValue>[] items) {
|
||||
super(parent, type, min, max, l10n);
|
||||
mItems = items;
|
||||
}
|
||||
@ -48,8 +48,8 @@ public class ResEnumAttr extends ResAttr {
|
||||
|
||||
@Override
|
||||
protected void serializeBody(XmlSerializer serializer, ResResource res) throws AndrolibException, IOException {
|
||||
for (Duo<ResReferenceValue, ResIntValue> duo : mItems) {
|
||||
int intVal = duo.m2.getValue();
|
||||
for (Duo<ResReferenceValue, ResScalarValue> duo : mItems) {
|
||||
int intVal = duo.m2.getRawIntValue();
|
||||
|
||||
// #2836 - Support skipping items if the resource cannot be identified.
|
||||
ResResSpec m1Referent = duo.m1.getReferent();
|
||||
@ -72,8 +72,8 @@ public class ResEnumAttr extends ResAttr {
|
||||
String value2 = mItemsCache.get(value);
|
||||
if (value2 == null) {
|
||||
ResReferenceValue ref = null;
|
||||
for (Duo<ResReferenceValue, ResIntValue> duo : mItems) {
|
||||
if (duo.m2.getValue() == value) {
|
||||
for (Duo<ResReferenceValue, ResScalarValue> duo : mItems) {
|
||||
if (duo.m2.getRawIntValue() == value) {
|
||||
ref = duo.m1;
|
||||
break;
|
||||
}
|
||||
@ -86,7 +86,7 @@ public class ResEnumAttr extends ResAttr {
|
||||
return value2;
|
||||
}
|
||||
|
||||
private final Duo<ResReferenceValue, ResIntValue>[] mItems;
|
||||
private final Duo<ResReferenceValue, ResScalarValue>[] mItems;
|
||||
private final Map<Integer, String> mItemsCache = new HashMap<>();
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ResEnumAttr.class.getName());
|
||||
|
@ -29,12 +29,12 @@ import java.util.logging.Logger;
|
||||
|
||||
public class ResFlagsAttr extends ResAttr {
|
||||
ResFlagsAttr(ResReferenceValue parent, int type, Integer min, Integer max,
|
||||
Boolean l10n, Duo<ResReferenceValue, ResIntValue>[] items) {
|
||||
Boolean l10n, Duo<ResReferenceValue, ResScalarValue>[] items) {
|
||||
super(parent, type, min, max, l10n);
|
||||
|
||||
mItems = new FlagItem[items.length];
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
mItems[i] = new FlagItem(items[i].m1, items[i].m2.getValue());
|
||||
mItems[i] = new FlagItem(items[i].m1, items[i].m2.getRawIntValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,5 @@ public class ResPluralsValue extends ResBagValue implements
|
||||
private final ResScalarValue[] mItems;
|
||||
|
||||
public static final int BAG_KEY_PLURALS_START = 0x01000004;
|
||||
public static final int BAG_KEY_PLURALS_END = 0x01000009;
|
||||
private static final String[] QUANTITY_MAP = new String[] { "other", "zero", "one", "two", "few", "many" };
|
||||
}
|
||||
|
@ -80,40 +80,30 @@ public class ResValueFactory {
|
||||
return new ResStringValue(value, rawValue);
|
||||
}
|
||||
|
||||
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec) throws AndrolibException {
|
||||
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec)
|
||||
throws AndrolibException {
|
||||
ResReferenceValue parentVal = newReference(parent, null);
|
||||
|
||||
if (items.length == 0) {
|
||||
return new ResBagValue(parentVal);
|
||||
}
|
||||
int key = items[0].m1;
|
||||
if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
|
||||
return ResAttr.factory(parentVal, items, this, mPackage);
|
||||
}
|
||||
|
||||
String resTypeName = resTypeSpec.getName();
|
||||
|
||||
// Android O Preview added an unknown enum for c. This is hardcoded as 0 for now.
|
||||
if (ResTypeSpec.RES_TYPE_NAME_ARRAY.equals(resTypeName)
|
||||
|| key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
|
||||
switch (resTypeName) {
|
||||
case ResTypeSpec.RES_TYPE_NAME_ATTR:
|
||||
case ResTypeSpec.RES_TYPE_NAME_ATTR_PRIVATE:
|
||||
return ResAttr.factory(parentVal, items, this, mPackage);
|
||||
case ResTypeSpec.RES_TYPE_NAME_ARRAY:
|
||||
return new ResArrayValue(parentVal, items);
|
||||
}
|
||||
|
||||
if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) ||
|
||||
(key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) {
|
||||
case ResTypeSpec.RES_TYPE_NAME_PLURALS:
|
||||
return new ResPluralsValue(parentVal, items);
|
||||
}
|
||||
|
||||
if (ResTypeSpec.RES_TYPE_NAME_ATTR.equals(resTypeName)) {
|
||||
return new ResAttr(parentVal, 0, null, null, null);
|
||||
}
|
||||
|
||||
default:
|
||||
if (resTypeName.startsWith(ResTypeSpec.RES_TYPE_NAME_STYLES)) {
|
||||
return new ResStyleValue(parentVal, items, this);
|
||||
}
|
||||
|
||||
throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName);
|
||||
}
|
||||
}
|
||||
|
||||
public ResReferenceValue newReference(int resID, String rawValue) {
|
||||
return newReference(resID, rawValue, false);
|
||||
|
@ -35,4 +35,7 @@
|
||||
<item>res/</item>
|
||||
<item>view/</item>
|
||||
</string-array>
|
||||
<string-array name="issue_2806">
|
||||
<item>MIICXAIBAAKBgQCjcGqTkOq0CR3rTx0ZSQSIdTrDrFAYl29611xN8aVgMQIWtDB/lD0W5TpKPuU9iaiG/sSn/VYt6EzN7Sr332jj7cyl2WrrHI6ujRswNy4HojMuqtfab5FFDpRmCuvl35fge18OvoQTJELhhJ1EvJ5KUeZiuJ3u3YyMnxxXzLuKbQIDAQABAoGAPrNDz7TKtaLBvaIuMaMXgBopHyQd3jFKbT/tg2Fu5kYm3PrnmCoQfZYXFKCoZUFIS/G1FBVWWGpD/MQ9tbYZkKpwuH+t2rGndMnLXiTC296/s9uix7gsjnT4Naci5N6EN9pVUBwQmGrYUTHFc58ThtelSiPARX7LSU2ibtJSv8ECQQDWBRrrAYmbCUN7ra0DFT6SppaDtvvuKtb+mUeKbg0B8U4y4wCIK5GH8EyQSwUWcXnNBO05rlUPbifsDLv/u82lAkEAw39sTJ0KmJJyaChqvqAJ8guulKlgucQJ0Et9ppZyet9iVwNKX/aW9UlwGBMQdafQ36nd1QMEA8AbAw4D+hw/KQJBANJbHDUGQtk2hrSmZNoV5HXB9Uiq7v4N71k5ER8XwgM5yVGs2tX8dMM3RhnBEtQXXs9LW1uJZSOQcv7JGXNnhN0CQBZenzrJAWxh3XtznHtBfsHWelyCYRIAj4rpCHCmaGUM6IjCVKFUawOYKp5mmAyObkUZf8ue87emJLEdynC1CLkCQHduNjP1hemAGWrd6v8BHhE3kKtcK6KHsPvJR5dOfzbdHAqVePERhISfN6cwZt5p8B3/JUwSR8el66DF7Jm57BM=</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user