mirror of
https://github.com/revanced/Apktool.git
synced 2024-08-28 18:16:41 +02:00
Merge ResAttrDecoder into the AXmlResourceParser (#3243)
This commit is contained in:
parent
9d7d58016e
commit
0a354a9d97
@ -19,10 +19,15 @@ package brut.androlib.res.decoder;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.util.TypedValue;
|
||||
import brut.androlib.exceptions.AndrolibException;
|
||||
import brut.androlib.exceptions.CantFindFrameworkResException;
|
||||
import brut.androlib.exceptions.UndefinedResObjectException;
|
||||
import brut.androlib.res.data.ResID;
|
||||
import brut.androlib.res.data.ResResSpec;
|
||||
import brut.androlib.res.data.ResTable;
|
||||
import brut.androlib.res.data.arsc.ARSCHeader;
|
||||
import brut.androlib.res.data.axml.NamespaceStack;
|
||||
import brut.androlib.res.data.value.ResAttr;
|
||||
import brut.androlib.res.data.value.ResScalarValue;
|
||||
import brut.androlib.res.xml.ResXmlEncoders;
|
||||
import brut.util.ExtCountingDataInput;
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
@ -44,20 +49,16 @@ import java.util.logging.Logger;
|
||||
public class AXmlResourceParser implements XmlResourceParser {
|
||||
|
||||
public AXmlResourceParser(ResTable resTable) {
|
||||
mResTable = resTable;
|
||||
resetEventInfo();
|
||||
setAttrDecoder(new ResAttrDecoder(resTable));
|
||||
}
|
||||
|
||||
public AndrolibException getFirstError() {
|
||||
return mFirstError;
|
||||
}
|
||||
|
||||
public ResAttrDecoder getAttrDecoder() {
|
||||
return mAttrDecoder;
|
||||
}
|
||||
|
||||
public void setAttrDecoder(ResAttrDecoder attrDecoder) {
|
||||
mAttrDecoder = attrDecoder;
|
||||
public ResTable getResTable() {
|
||||
return mResTable;
|
||||
}
|
||||
|
||||
public void open(InputStream stream) {
|
||||
@ -298,6 +299,19 @@ public class AXmlResourceParser implements XmlResourceParser {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String decodeFromResourceId(int attrResId) throws AndrolibException {
|
||||
if (attrResId != 0) {
|
||||
try {
|
||||
ResResSpec resResSpec = mResTable.getResSpec(attrResId);
|
||||
if (resResSpec != null) {
|
||||
return resResSpec.getName();
|
||||
}
|
||||
} catch (UndefinedResObjectException | CantFindFrameworkResException ignored) {}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getNonDefaultNamespaceUri(int offset) {
|
||||
String prefix = mStringBlock.getString(mNamespaces.getPrefix(offset));
|
||||
if (prefix != null) {
|
||||
@ -337,7 +351,7 @@ public class AXmlResourceParser implements XmlResourceParser {
|
||||
int resourceId = getAttributeNameResource(index);
|
||||
|
||||
try {
|
||||
resourceMapValue = mAttrDecoder.decodeFromResourceId(resourceId);
|
||||
resourceMapValue = decodeFromResourceId(resourceId);
|
||||
} catch (AndrolibException ignored) {
|
||||
resourceMapValue = null;
|
||||
}
|
||||
@ -389,48 +403,56 @@ public class AXmlResourceParser implements XmlResourceParser {
|
||||
int valueData = mAttributes[offset + ATTRIBUTE_IX_VALUE_DATA];
|
||||
int valueRaw = mAttributes[offset + ATTRIBUTE_IX_VALUE_STRING];
|
||||
|
||||
if (mAttrDecoder != null) {
|
||||
try {
|
||||
String stringBlockValue = valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(mStringBlock.getString(valueRaw));
|
||||
String resourceMapValue = null;
|
||||
try {
|
||||
String stringBlockValue = valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(mStringBlock.getString(valueRaw));
|
||||
String resourceMapValue = null;
|
||||
|
||||
// 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) {
|
||||
resourceMapValue = mAttrDecoder.decodeFromResourceId(valueData);
|
||||
}
|
||||
String value = stringBlockValue;
|
||||
|
||||
if (stringBlockValue != null && resourceMapValue != null) {
|
||||
int slashPos = stringBlockValue.lastIndexOf("/");
|
||||
int colonPos = stringBlockValue.lastIndexOf(":");
|
||||
|
||||
// Handle a value with a format of "@yyy/xxx", but avoid "@yyy/zzz:xxx"
|
||||
if (slashPos != -1) {
|
||||
if (colonPos == -1) {
|
||||
String type = stringBlockValue.substring(0, slashPos);
|
||||
value = type + "/" + resourceMapValue;
|
||||
}
|
||||
} else if (! stringBlockValue.equals(resourceMapValue)) {
|
||||
value = resourceMapValue;
|
||||
}
|
||||
}
|
||||
|
||||
return mAttrDecoder.decode(
|
||||
valueType,
|
||||
valueData,
|
||||
value,
|
||||
getAttributeNameResource(index)
|
||||
);
|
||||
} catch (AndrolibException ex) {
|
||||
setFirstError(ex);
|
||||
LOGGER.log(Level.WARNING, String.format("Could not decode attr value, using undecoded value "
|
||||
+ "instead: ns=%s, name=%s, value=0x%08x",
|
||||
getAttributePrefix(index),
|
||||
getAttributeName(index),
|
||||
valueData), ex);
|
||||
// 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) {
|
||||
resourceMapValue = decodeFromResourceId(valueData);
|
||||
}
|
||||
String value = stringBlockValue;
|
||||
|
||||
if (stringBlockValue != null && resourceMapValue != null) {
|
||||
int slashPos = stringBlockValue.lastIndexOf("/");
|
||||
int colonPos = stringBlockValue.lastIndexOf(":");
|
||||
|
||||
// Handle a value with a format of "@yyy/xxx", but avoid "@yyy/zzz:xxx"
|
||||
if (slashPos != -1) {
|
||||
if (colonPos == -1) {
|
||||
String type = stringBlockValue.substring(0, slashPos);
|
||||
value = type + "/" + resourceMapValue;
|
||||
}
|
||||
} else if (! stringBlockValue.equals(resourceMapValue)) {
|
||||
value = resourceMapValue;
|
||||
}
|
||||
}
|
||||
|
||||
// try to decode from resource table
|
||||
int attrResId = getAttributeNameResource(index);
|
||||
ResScalarValue resValue = mResTable.getCurrentResPackage()
|
||||
.getValueFactory().factory(valueType, valueData, value);
|
||||
|
||||
String decoded = null;
|
||||
if (attrResId > 0) {
|
||||
try {
|
||||
ResAttr attr = (ResAttr) mResTable.getResSpec(attrResId).getDefaultResource().getValue();
|
||||
|
||||
decoded = attr.convertToResXmlFormat(resValue);
|
||||
} catch (UndefinedResObjectException | ClassCastException ignored) {}
|
||||
}
|
||||
|
||||
return decoded != null ? decoded : resValue.encodeAsResXmlAttr();
|
||||
|
||||
} catch (AndrolibException ex) {
|
||||
setFirstError(ex);
|
||||
LOGGER.log(Level.WARNING, String.format("Could not decode attr value, using undecoded value "
|
||||
+ "instead: ns=%s, name=%s, value=0x%08x",
|
||||
getAttributePrefix(index),
|
||||
getAttributeName(index),
|
||||
valueData), ex);
|
||||
}
|
||||
return TypedValue.coerceToString(valueType, valueData);
|
||||
}
|
||||
@ -801,7 +823,7 @@ public class AXmlResourceParser implements XmlResourceParser {
|
||||
}
|
||||
|
||||
private ExtCountingDataInput mIn;
|
||||
private ResAttrDecoder mAttrDecoder;
|
||||
private final ResTable mResTable;
|
||||
private AndrolibException mFirstError;
|
||||
|
||||
private boolean isOperational = false;
|
||||
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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.decoder;
|
||||
|
||||
import brut.androlib.exceptions.AndrolibException;
|
||||
import brut.androlib.exceptions.CantFindFrameworkResException;
|
||||
import brut.androlib.exceptions.UndefinedResObjectException;
|
||||
import brut.androlib.res.data.ResID;
|
||||
import brut.androlib.res.data.ResResSpec;
|
||||
import brut.androlib.res.data.ResTable;
|
||||
import brut.androlib.res.data.value.ResAttr;
|
||||
import brut.androlib.res.data.value.ResScalarValue;
|
||||
|
||||
public class ResAttrDecoder {
|
||||
|
||||
public ResAttrDecoder(ResTable resTable) {
|
||||
mResTable = resTable;
|
||||
}
|
||||
|
||||
public String decode(int type, int value, String rawValue, int attrResId) throws AndrolibException {
|
||||
ResScalarValue resValue = mResTable.getCurrentResPackage().getValueFactory().factory(type, value, rawValue);
|
||||
|
||||
String decoded = null;
|
||||
if (attrResId > 0) {
|
||||
try {
|
||||
ResAttr attr = (ResAttr) mResTable.getResSpec(attrResId).getDefaultResource().getValue();
|
||||
|
||||
decoded = attr.convertToResXmlFormat(resValue);
|
||||
} catch (UndefinedResObjectException | ClassCastException ignored) {}
|
||||
}
|
||||
|
||||
return decoded != null ? decoded : resValue.encodeAsResXmlAttr();
|
||||
}
|
||||
|
||||
public String decodeFromResourceId(int attrResId) throws AndrolibException {
|
||||
if (attrResId != 0) {
|
||||
try {
|
||||
ResResSpec resResSpec = mResTable.getResSpec(attrResId);
|
||||
if (resResSpec != null) {
|
||||
return resResSpec.getName();
|
||||
}
|
||||
} catch (UndefinedResObjectException | CantFindFrameworkResException ignored) {}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ResTable getResTable() throws AndrolibException {
|
||||
if (mResTable == null) {
|
||||
throw new AndrolibException("Res Table not set");
|
||||
}
|
||||
return mResTable;
|
||||
}
|
||||
|
||||
public void setResTable(ResTable resTable) {
|
||||
mResTable = resTable;
|
||||
}
|
||||
|
||||
private ResTable mResTable;
|
||||
}
|
@ -31,7 +31,7 @@ import org.xmlpull.v1.wrapper.classic.StaticXmlSerializerWrapper;
|
||||
import java.io.*;
|
||||
|
||||
public class XmlPullStreamDecoder implements ResStreamDecoder {
|
||||
public XmlPullStreamDecoder(XmlPullParser parser,
|
||||
public XmlPullStreamDecoder(AXmlResourceParser parser,
|
||||
ExtXmlSerializer serializer) {
|
||||
this.mParser = parser;
|
||||
this.mSerial = serializer;
|
||||
@ -43,7 +43,7 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
|
||||
try {
|
||||
XmlPullWrapperFactory factory = XmlPullWrapperFactory.newInstance();
|
||||
XmlPullParserWrapper par = factory.newPullParserWrapper(mParser);
|
||||
final ResTable resTable = ((AXmlResourceParser) mParser).getAttrDecoder().getResTable();
|
||||
final ResTable resTable = mParser.getResTable();
|
||||
|
||||
XmlSerializerWrapper ser = new StaticXmlSerializerWrapper(mSerial, factory) {
|
||||
boolean hideSdkInfo = false;
|
||||
@ -149,6 +149,6 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
|
||||
decode(in, out);
|
||||
}
|
||||
|
||||
private final XmlPullParser mParser;
|
||||
private final AXmlResourceParser mParser;
|
||||
private final ExtXmlSerializer mSerial;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user