mirror of
https://github.com/revanced/Apktool.git
synced 2024-12-05 02:22:55 +01:00
Removed some bits related to C++-based XML decoding.
This commit is contained in:
parent
a1d9766a90
commit
ac810d0619
@ -1,364 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 android.content.res;
|
||||
|
||||
import android.util.TypedValue;
|
||||
|
||||
import brut.util.Jar;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Wrapper around a compiled XML file.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
final public class XmlBlock {
|
||||
static {
|
||||
Jar.load("/brut/androlib/libAndroid.so");
|
||||
}
|
||||
|
||||
private static final boolean DEBUG=false;
|
||||
|
||||
public XmlBlock(byte[] data) {
|
||||
mNative = nativeCreate(data, 0, data.length);
|
||||
mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
|
||||
}
|
||||
|
||||
public XmlBlock(byte[] data, int offset, int size) {
|
||||
mNative = nativeCreate(data, offset, size);
|
||||
mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
synchronized (this) {
|
||||
if (mOpen) {
|
||||
mOpen = false;
|
||||
decOpenCountLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void decOpenCountLocked() {
|
||||
mOpenCount--;
|
||||
if (mOpenCount == 0) {
|
||||
nativeDestroy(mNative);
|
||||
}
|
||||
}
|
||||
|
||||
public XmlPullParser newParser() {
|
||||
synchronized (this) {
|
||||
if (mNative != 0) {
|
||||
return new Parser(nativeCreateParseState(mNative), this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ final class Parser implements XmlPullParser {
|
||||
Parser(int parseState, XmlBlock block) {
|
||||
mParseState = parseState;
|
||||
mBlock = block;
|
||||
block.mOpenCount++;
|
||||
}
|
||||
|
||||
public void setFeature(String name, boolean state) throws XmlPullParserException {
|
||||
if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
|
||||
return;
|
||||
}
|
||||
if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
|
||||
return;
|
||||
}
|
||||
throw new XmlPullParserException("Unsupported feature: " + name);
|
||||
}
|
||||
public boolean getFeature(String name) {
|
||||
if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public void setProperty(String name, Object value) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("setProperty() not supported");
|
||||
}
|
||||
public Object getProperty(String name) {
|
||||
return null;
|
||||
}
|
||||
public void setInput(Reader in) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("setInput() not supported");
|
||||
}
|
||||
public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("setInput() not supported");
|
||||
}
|
||||
public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("defineEntityReplacementText() not supported");
|
||||
}
|
||||
public String getNamespacePrefix(int pos) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("getNamespacePrefix() not supported");
|
||||
}
|
||||
public String getInputEncoding() {
|
||||
return null;
|
||||
}
|
||||
public String getNamespace(String prefix) {
|
||||
throw new RuntimeException("getNamespace() not supported");
|
||||
}
|
||||
public int getNamespaceCount(int depth) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("getNamespaceCount() not supported");
|
||||
}
|
||||
public String getPositionDescription() {
|
||||
return "Binary XML file line #" + getLineNumber();
|
||||
}
|
||||
public String getNamespaceUri(int pos) throws XmlPullParserException {
|
||||
throw new XmlPullParserException("getNamespaceUri() not supported");
|
||||
}
|
||||
public int getColumnNumber() {
|
||||
return -1;
|
||||
}
|
||||
public int getDepth() {
|
||||
return mDepth;
|
||||
}
|
||||
public String getText() {
|
||||
int id = nativeGetText(mParseState);
|
||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
||||
}
|
||||
public int getLineNumber() {
|
||||
return nativeGetLineNumber(mParseState);
|
||||
}
|
||||
public int getEventType() throws XmlPullParserException {
|
||||
return mEventType;
|
||||
}
|
||||
public boolean isWhitespace() throws XmlPullParserException {
|
||||
// whitespace was stripped by aapt.
|
||||
return false;
|
||||
}
|
||||
public String getPrefix() {
|
||||
throw new RuntimeException("getPrefix not supported");
|
||||
}
|
||||
public char[] getTextCharacters(int[] holderForStartAndLength) {
|
||||
String txt = getText();
|
||||
char[] chars = null;
|
||||
if (txt != null) {
|
||||
holderForStartAndLength[0] = 0;
|
||||
holderForStartAndLength[1] = txt.length();
|
||||
chars = new char[txt.length()];
|
||||
txt.getChars(0, txt.length(), chars, 0);
|
||||
}
|
||||
return chars;
|
||||
}
|
||||
public String getNamespace() {
|
||||
int id = nativeGetNamespace(mParseState);
|
||||
return id >= 0 ? mStrings.get(id).toString() : "";
|
||||
}
|
||||
public String getName() {
|
||||
int id = nativeGetName(mParseState);
|
||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
||||
}
|
||||
public String getAttributeNamespace(int index) {
|
||||
int id = nativeGetAttributeNamespace(mParseState, index);
|
||||
if (DEBUG) System.out.println("getAttributeNamespace of " + index + " = " + id);
|
||||
if (id >= 0) return mStrings.get(id).toString();
|
||||
else if (id == -1) return "";
|
||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||
}
|
||||
public String getAttributeName(int index) {
|
||||
int id = nativeGetAttributeName(mParseState, index);
|
||||
if (DEBUG) System.out.println("getAttributeName of " + index + " = " + id);
|
||||
if (id >= 0) return mStrings.get(id).toString();
|
||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||
}
|
||||
public String getAttributePrefix(int index) {
|
||||
throw new RuntimeException("getAttributePrefix not supported");
|
||||
}
|
||||
public boolean isEmptyElementTag() throws XmlPullParserException {
|
||||
// XXX Need to detect this.
|
||||
return false;
|
||||
}
|
||||
public int getAttributeCount() {
|
||||
return mEventType == START_TAG ? nativeGetAttributeCount(mParseState) : -1;
|
||||
}
|
||||
public String getAttributeValue(int index) {
|
||||
int id = nativeGetAttributeStringValue(mParseState, index);
|
||||
if (DEBUG) System.out.println("getAttributeValue of " + index + " = " + id);
|
||||
if (id >= 0) return mStrings.get(id).toString();
|
||||
|
||||
// May be some other type... check and try to convert if so.
|
||||
int t = nativeGetAttributeDataType(mParseState, index);
|
||||
if (t == TypedValue.TYPE_NULL) {
|
||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||
}
|
||||
|
||||
int v = nativeGetAttributeData(mParseState, index);
|
||||
return TypedValue.coerceToString(t, v);
|
||||
}
|
||||
public String getAttributeType(int index) {
|
||||
return "CDATA";
|
||||
}
|
||||
public boolean isAttributeDefault(int index) {
|
||||
return false;
|
||||
}
|
||||
public int nextToken() throws XmlPullParserException,IOException {
|
||||
return next();
|
||||
}
|
||||
public String getAttributeValue(String namespace, String name) {
|
||||
int idx = nativeGetAttributeIndex(mParseState, namespace, name);
|
||||
if (idx >= 0) {
|
||||
if (DEBUG) System.out.println("getAttributeName of "
|
||||
+ namespace + ":" + name + " index = " + idx);
|
||||
if (DEBUG) System.out.println(
|
||||
"Namespace=" + getAttributeNamespace(idx)
|
||||
+ "Name=" + getAttributeName(idx)
|
||||
+ ", Value=" + getAttributeValue(idx));
|
||||
return getAttributeValue(idx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public int next() throws XmlPullParserException,IOException {
|
||||
if (!mStarted) {
|
||||
mStarted = true;
|
||||
return START_DOCUMENT;
|
||||
}
|
||||
if (mParseState == 0) {
|
||||
return END_DOCUMENT;
|
||||
}
|
||||
int ev = nativeNext(mParseState);
|
||||
if (mDecNextDepth) {
|
||||
mDepth--;
|
||||
mDecNextDepth = false;
|
||||
}
|
||||
switch (ev) {
|
||||
case START_TAG:
|
||||
mDepth++;
|
||||
break;
|
||||
case END_TAG:
|
||||
mDecNextDepth = true;
|
||||
break;
|
||||
}
|
||||
mEventType = ev;
|
||||
if (ev == END_DOCUMENT) {
|
||||
// Automatically close the parse when we reach the end of
|
||||
// a document, since the standard XmlPullParser interface
|
||||
// doesn't have such an API so most clients will leave us
|
||||
// dangling.
|
||||
close();
|
||||
}
|
||||
return ev;
|
||||
}
|
||||
public void require(int type, String namespace, String name) throws XmlPullParserException,IOException {
|
||||
if (type != getEventType()
|
||||
|| (namespace != null && !namespace.equals( getNamespace () ) )
|
||||
|| (name != null && !name.equals( getName() ) ) )
|
||||
throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription());
|
||||
}
|
||||
public String nextText() throws XmlPullParserException,IOException {
|
||||
if(getEventType() != START_TAG) {
|
||||
throw new XmlPullParserException(
|
||||
getPositionDescription()
|
||||
+ ": parser must be on START_TAG to read next text", this, null);
|
||||
}
|
||||
int eventType = next();
|
||||
if(eventType == TEXT) {
|
||||
String result = getText();
|
||||
eventType = next();
|
||||
if(eventType != END_TAG) {
|
||||
throw new XmlPullParserException(
|
||||
getPositionDescription()
|
||||
+ ": event TEXT it must be immediately followed by END_TAG", this, null);
|
||||
}
|
||||
return result;
|
||||
} else if(eventType == END_TAG) {
|
||||
return "";
|
||||
} else {
|
||||
throw new XmlPullParserException(
|
||||
getPositionDescription()
|
||||
+ ": parser must be on START_TAG or TEXT to read text", this, null);
|
||||
}
|
||||
}
|
||||
public int nextTag() throws XmlPullParserException,IOException {
|
||||
int eventType = next();
|
||||
if(eventType == TEXT && isWhitespace()) { // skip whitespace
|
||||
eventType = next();
|
||||
}
|
||||
if (eventType != START_TAG && eventType != END_TAG) {
|
||||
throw new XmlPullParserException(
|
||||
getPositionDescription()
|
||||
+ ": expected start or end tag", this, null);
|
||||
}
|
||||
return eventType;
|
||||
}
|
||||
public void close() {
|
||||
synchronized (mBlock) {
|
||||
if (mParseState != 0) {
|
||||
nativeDestroyParseState(mParseState);
|
||||
mParseState = 0;
|
||||
mBlock.decOpenCountLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
}
|
||||
|
||||
/*package*/ final CharSequence getPooledString(int id) {
|
||||
return mStrings.get(id);
|
||||
}
|
||||
|
||||
/*package*/ int mParseState;
|
||||
private final XmlBlock mBlock;
|
||||
private boolean mStarted = false;
|
||||
private boolean mDecNextDepth = false;
|
||||
private int mDepth = 0;
|
||||
private int mEventType = START_DOCUMENT;
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
}
|
||||
|
||||
private final int mNative;
|
||||
private final StringBlock mStrings;
|
||||
private boolean mOpen = true;
|
||||
private int mOpenCount = 1;
|
||||
|
||||
private static final native int nativeCreate(byte[] data,
|
||||
int offset,
|
||||
int size);
|
||||
private static final native int nativeGetStringBlock(int obj);
|
||||
|
||||
private static final native int nativeCreateParseState(int obj);
|
||||
private static final native int nativeNext(int state);
|
||||
private static final native int nativeGetNamespace(int state);
|
||||
private static final native int nativeGetName(int state);
|
||||
private static final native int nativeGetText(int state);
|
||||
private static final native int nativeGetLineNumber(int state);
|
||||
private static final native int nativeGetAttributeCount(int state);
|
||||
private static final native int nativeGetAttributeNamespace(int state, int idx);
|
||||
private static final native int nativeGetAttributeName(int state, int idx);
|
||||
private static final native int nativeGetAttributeDataType(int state, int idx);
|
||||
private static final native int nativeGetAttributeData(int state, int idx);
|
||||
private static final native int nativeGetAttributeStringValue(int state, int idx);
|
||||
private static final native int nativeGetAttributeIndex(int state, String namespace, String name);
|
||||
private static final native void nativeDestroyParseState(int state);
|
||||
|
||||
private static final native void nativeDestroy(int obj);
|
||||
}
|
@ -24,7 +24,6 @@ import brut.androlib.res.jni.JniBagItem;
|
||||
import brut.androlib.res.jni.JniEntry;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@ -66,45 +65,6 @@ public class ResValueFactory {
|
||||
throw new AndrolibException("Invalid value type: "+ type);
|
||||
}
|
||||
|
||||
public ResScalarValue factory(String string) throws AndrolibException {
|
||||
if (string.isEmpty()) {
|
||||
return new ResStringValue(string);
|
||||
}
|
||||
Integer i;
|
||||
|
||||
char c = string.charAt(0);
|
||||
boolean theme = false;
|
||||
if (c == '?') {
|
||||
c = '@';
|
||||
theme = true;
|
||||
}
|
||||
if (c == '@' || c == '#') {
|
||||
i = parseInt(string.substring(1), true);
|
||||
if (i != null) {
|
||||
switch (c) {
|
||||
case '@':
|
||||
return newReference(i, theme);
|
||||
case '#':
|
||||
return new ResColorValue(i);
|
||||
}
|
||||
}
|
||||
Matcher m = resIdPattern.matcher(string.substring(1));
|
||||
if (m.matches()) {
|
||||
ResPackage pkg = m.group(1) == null ? mPackage
|
||||
: mPackage.getResTable().getPackage(m.group(1));
|
||||
return newReference(pkg.getType(m.group(2))
|
||||
.getResSpec(m.group(3)).getId().id, theme);
|
||||
}
|
||||
}
|
||||
|
||||
i = parseInt(string);
|
||||
if (i != null) {
|
||||
return new ResIntValue(i);
|
||||
}
|
||||
|
||||
return new ResStringValue(string);
|
||||
}
|
||||
|
||||
public ResValue factory(JniEntry entry)
|
||||
throws AndrolibException {
|
||||
switch (entry.valueType) {
|
||||
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 Ryszard Wiśniewski <brut.alll@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
|
||||
*
|
||||
* http://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.
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package brut.androlib.res.decoder;
|
||||
|
||||
import android.content.res.XmlBlock;
|
||||
import brut.androlib.AndrolibException;
|
||||
import java.io.*;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.xmlpull.v1.*;
|
||||
import org.xmlpull.v1.wrapper.*;
|
||||
|
||||
/**
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
*/
|
||||
public class ResXmlStreamDecoder implements ResStreamDecoder {
|
||||
private final ResXmlSerializer mSerializer;
|
||||
|
||||
public ResXmlStreamDecoder(ResXmlSerializer serializer) {
|
||||
this.mSerializer = serializer;
|
||||
}
|
||||
|
||||
public void decode(InputStream in, OutputStream out)
|
||||
throws AndrolibException {
|
||||
try {
|
||||
XmlPullParserWrapper par =
|
||||
getResXmlParserWrapper(in);
|
||||
XmlSerializerWrapper ser =
|
||||
getXmlWrapperFactory().newSerializerWrapper(mSerializer);
|
||||
ser.setOutput(out, null);
|
||||
// mSerializer.setDecodingEnabled(true);
|
||||
|
||||
while (par.nextToken() != XmlPullParser.END_DOCUMENT) {
|
||||
ser.event(par);
|
||||
}
|
||||
ser.flush();
|
||||
} catch (IOException ex) {
|
||||
throw new AndrolibException("could not decode XML stream", ex);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new AndrolibException("could not decode XML stream", ex);
|
||||
} catch (IllegalStateException ex) {
|
||||
throw new AndrolibException("could not decode XML stream", ex);
|
||||
} catch (XmlPullParserException ex) {
|
||||
throw new AndrolibException("could not decode XML stream", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private XmlPullParserWrapper getResXmlParserWrapper(InputStream in)
|
||||
throws IOException, XmlPullParserException {
|
||||
XmlBlock xml = new XmlBlock(copyStreamToByteArray(in));
|
||||
XmlPullParser parser = xml.newParser();
|
||||
return getXmlWrapperFactory().newPullParserWrapper(parser);
|
||||
}
|
||||
|
||||
private XmlPullWrapperFactory getXmlWrapperFactory()
|
||||
throws XmlPullParserException {
|
||||
return XmlPullWrapperFactory.newInstance();
|
||||
}
|
||||
|
||||
private byte[] copyStreamToByteArray(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
IOUtils.copy(in, out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user