Merge ResAttrDecoder into the AXmlResourceParser (#3243)

This commit is contained in:
sv99 2023-08-02 01:43:15 +03:00 committed by GitHub
parent 9d7d58016e
commit 0a354a9d97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 126 deletions

View File

@ -19,10 +19,15 @@ package brut.androlib.res.decoder;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.util.TypedValue; import android.util.TypedValue;
import brut.androlib.exceptions.AndrolibException; 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.ResID;
import brut.androlib.res.data.ResResSpec;
import brut.androlib.res.data.ResTable; import brut.androlib.res.data.ResTable;
import brut.androlib.res.data.arsc.ARSCHeader; import brut.androlib.res.data.arsc.ARSCHeader;
import brut.androlib.res.data.axml.NamespaceStack; 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.androlib.res.xml.ResXmlEncoders;
import brut.util.ExtCountingDataInput; import brut.util.ExtCountingDataInput;
import com.google.common.io.LittleEndianDataInputStream; import com.google.common.io.LittleEndianDataInputStream;
@ -44,20 +49,16 @@ import java.util.logging.Logger;
public class AXmlResourceParser implements XmlResourceParser { public class AXmlResourceParser implements XmlResourceParser {
public AXmlResourceParser(ResTable resTable) { public AXmlResourceParser(ResTable resTable) {
mResTable = resTable;
resetEventInfo(); resetEventInfo();
setAttrDecoder(new ResAttrDecoder(resTable));
} }
public AndrolibException getFirstError() { public AndrolibException getFirstError() {
return mFirstError; return mFirstError;
} }
public ResAttrDecoder getAttrDecoder() { public ResTable getResTable() {
return mAttrDecoder; return mResTable;
}
public void setAttrDecoder(ResAttrDecoder attrDecoder) {
mAttrDecoder = attrDecoder;
} }
public void open(InputStream stream) { public void open(InputStream stream) {
@ -298,6 +299,19 @@ public class AXmlResourceParser implements XmlResourceParser {
return value; 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) { private String getNonDefaultNamespaceUri(int offset) {
String prefix = mStringBlock.getString(mNamespaces.getPrefix(offset)); String prefix = mStringBlock.getString(mNamespaces.getPrefix(offset));
if (prefix != null) { if (prefix != null) {
@ -337,7 +351,7 @@ public class AXmlResourceParser implements XmlResourceParser {
int resourceId = getAttributeNameResource(index); int resourceId = getAttributeNameResource(index);
try { try {
resourceMapValue = mAttrDecoder.decodeFromResourceId(resourceId); resourceMapValue = decodeFromResourceId(resourceId);
} catch (AndrolibException ignored) { } catch (AndrolibException ignored) {
resourceMapValue = null; resourceMapValue = null;
} }
@ -389,7 +403,6 @@ public class AXmlResourceParser implements XmlResourceParser {
int valueData = mAttributes[offset + ATTRIBUTE_IX_VALUE_DATA]; int valueData = mAttributes[offset + ATTRIBUTE_IX_VALUE_DATA];
int valueRaw = mAttributes[offset + ATTRIBUTE_IX_VALUE_STRING]; int valueRaw = mAttributes[offset + ATTRIBUTE_IX_VALUE_STRING];
if (mAttrDecoder != null) {
try { try {
String stringBlockValue = valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(mStringBlock.getString(valueRaw)); String stringBlockValue = valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(mStringBlock.getString(valueRaw));
String resourceMapValue = null; String resourceMapValue = null;
@ -398,7 +411,7 @@ public class AXmlResourceParser implements XmlResourceParser {
// spam lookups against resource table for invalid ids. // spam lookups against resource table for invalid ids.
if (valueType == TypedValue.TYPE_REFERENCE || valueType == TypedValue.TYPE_DYNAMIC_REFERENCE || if (valueType == TypedValue.TYPE_REFERENCE || valueType == TypedValue.TYPE_DYNAMIC_REFERENCE ||
valueType == TypedValue.TYPE_ATTRIBUTE || valueType == TypedValue.TYPE_DYNAMIC_ATTRIBUTE) { valueType == TypedValue.TYPE_ATTRIBUTE || valueType == TypedValue.TYPE_DYNAMIC_ATTRIBUTE) {
resourceMapValue = mAttrDecoder.decodeFromResourceId(valueData); resourceMapValue = decodeFromResourceId(valueData);
} }
String value = stringBlockValue; String value = stringBlockValue;
@ -417,12 +430,22 @@ public class AXmlResourceParser implements XmlResourceParser {
} }
} }
return mAttrDecoder.decode( // try to decode from resource table
valueType, int attrResId = getAttributeNameResource(index);
valueData, ResScalarValue resValue = mResTable.getCurrentResPackage()
value, .getValueFactory().factory(valueType, valueData, value);
getAttributeNameResource(index)
); 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) { } catch (AndrolibException ex) {
setFirstError(ex); setFirstError(ex);
LOGGER.log(Level.WARNING, String.format("Could not decode attr value, using undecoded value " LOGGER.log(Level.WARNING, String.format("Could not decode attr value, using undecoded value "
@ -431,7 +454,6 @@ public class AXmlResourceParser implements XmlResourceParser {
getAttributeName(index), getAttributeName(index),
valueData), ex); valueData), ex);
} }
}
return TypedValue.coerceToString(valueType, valueData); return TypedValue.coerceToString(valueType, valueData);
} }
@ -801,7 +823,7 @@ public class AXmlResourceParser implements XmlResourceParser {
} }
private ExtCountingDataInput mIn; private ExtCountingDataInput mIn;
private ResAttrDecoder mAttrDecoder; private final ResTable mResTable;
private AndrolibException mFirstError; private AndrolibException mFirstError;
private boolean isOperational = false; private boolean isOperational = false;

View File

@ -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;
}

View File

@ -31,7 +31,7 @@ import org.xmlpull.v1.wrapper.classic.StaticXmlSerializerWrapper;
import java.io.*; import java.io.*;
public class XmlPullStreamDecoder implements ResStreamDecoder { public class XmlPullStreamDecoder implements ResStreamDecoder {
public XmlPullStreamDecoder(XmlPullParser parser, public XmlPullStreamDecoder(AXmlResourceParser parser,
ExtXmlSerializer serializer) { ExtXmlSerializer serializer) {
this.mParser = parser; this.mParser = parser;
this.mSerial = serializer; this.mSerial = serializer;
@ -43,7 +43,7 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
try { try {
XmlPullWrapperFactory factory = XmlPullWrapperFactory.newInstance(); XmlPullWrapperFactory factory = XmlPullWrapperFactory.newInstance();
XmlPullParserWrapper par = factory.newPullParserWrapper(mParser); XmlPullParserWrapper par = factory.newPullParserWrapper(mParser);
final ResTable resTable = ((AXmlResourceParser) mParser).getAttrDecoder().getResTable(); final ResTable resTable = mParser.getResTable();
XmlSerializerWrapper ser = new StaticXmlSerializerWrapper(mSerial, factory) { XmlSerializerWrapper ser = new StaticXmlSerializerWrapper(mSerial, factory) {
boolean hideSdkInfo = false; boolean hideSdkInfo = false;
@ -149,6 +149,6 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
decode(in, out); decode(in, out);
} }
private final XmlPullParser mParser; private final AXmlResourceParser mParser;
private final ExtXmlSerializer mSerial; private final ExtXmlSerializer mSerial;
} }