mirror of
https://github.com/revanced/Apktool.git
synced 2025-01-05 17:45:52 +01:00
Decoding XML files using pure-Java AXmlResourceParser instead of ResXmlStreamDecoder.
This commit is contained in:
parent
17380788c6
commit
a1d9766a90
@ -17,7 +17,7 @@
|
||||
|
||||
package brut.androlib.res;
|
||||
|
||||
import brut.androlib.*;
|
||||
import brut.androlib.AndrolibException;
|
||||
import brut.androlib.res.data.*;
|
||||
import brut.androlib.res.data.value.ResFileValue;
|
||||
import brut.androlib.res.data.value.ResXmlSerializable;
|
||||
@ -25,16 +25,11 @@ import brut.androlib.res.decoder.*;
|
||||
import brut.androlib.res.jni.JniPackage;
|
||||
import brut.androlib.res.jni.JniPackageGroup;
|
||||
import brut.common.BrutException;
|
||||
import brut.directory.Directory;
|
||||
import brut.directory.DirectoryException;
|
||||
import brut.directory.FileDirectory;
|
||||
import brut.directory.ZipRODirectory;
|
||||
import brut.util.Jar;
|
||||
import brut.util.OS;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import brut.directory.*;
|
||||
import brut.util.*;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
/**
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
@ -53,9 +48,11 @@ final public class AndrolibResources {
|
||||
|
||||
public void decode(ResTable resTable, File apkFile, File outDir)
|
||||
throws AndrolibException {
|
||||
ResXmlSerializer serial = getResXmlSerializer(resTable);
|
||||
ResFileDecoder fileDecoder = getResFileDecoder(serial);
|
||||
serial.setCurrentPackage(
|
||||
Duo<ResFileDecoder, ResAttrDecoder> duo = getResFileDecoder();
|
||||
ResFileDecoder fileDecoder = duo.m1;
|
||||
ResAttrDecoder attrDecoder = duo.m2;
|
||||
|
||||
attrDecoder.setCurrentPackage(
|
||||
resTable.listMainPackages().iterator().next());
|
||||
|
||||
Directory in, out;
|
||||
@ -72,15 +69,16 @@ final public class AndrolibResources {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
|
||||
ResXmlSerializer xmlSerializer = getResXmlSerializer();
|
||||
for (ResPackage pkg : resTable.listMainPackages()) {
|
||||
serial.setCurrentPackage(pkg);
|
||||
attrDecoder.setCurrentPackage(pkg);
|
||||
for (ResResource res : pkg.listFiles()) {
|
||||
ResFileValue fileValue = (ResFileValue) res.getValue();
|
||||
fileDecoder.decode(in, fileValue.getStrippedPath(),
|
||||
out, res.getFilePath());
|
||||
}
|
||||
for (ResValuesFile valuesFile : pkg.listValuesFiles()) {
|
||||
generateValuesFile(valuesFile, out, serial);
|
||||
generateValuesFile(valuesFile, out, xmlSerializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,27 +129,32 @@ final public class AndrolibResources {
|
||||
new ResSmaliUpdater().updateResIDs(resTable, smaliDir);
|
||||
}
|
||||
|
||||
public ResFileDecoder getResFileDecoder(ResXmlSerializer serializer) {
|
||||
public Duo<ResFileDecoder, ResAttrDecoder> getResFileDecoder() {
|
||||
ResStreamDecoderContainer decoders =
|
||||
new ResStreamDecoderContainer();
|
||||
decoders.setDecoder("raw", new ResRawStreamDecoder());
|
||||
|
||||
ResAttrDecoder attrDecoder = new ResAttrDecoder();
|
||||
AXmlResourceParser axmlParser = new AXmlResourceParser();
|
||||
axmlParser.setAttrDecoder(attrDecoder);
|
||||
decoders.setDecoder("xml",
|
||||
new ResXmlStreamDecoder(serializer));
|
||||
return new ResFileDecoder(decoders);
|
||||
new XmlPullStreamDecoder(axmlParser, getResXmlSerializer()));
|
||||
|
||||
return new Duo<ResFileDecoder, ResAttrDecoder>(
|
||||
new ResFileDecoder(decoders), attrDecoder);
|
||||
}
|
||||
|
||||
public ResXmlSerializer getResXmlSerializer(ResTable resTable) {
|
||||
public ResXmlSerializer getResXmlSerializer() {
|
||||
ResXmlSerializer serial = new ResXmlSerializer();
|
||||
serial.setProperty(serial.PROPERTY_SERIALIZER_INDENTATION, " ");
|
||||
return serial;
|
||||
}
|
||||
|
||||
private void generateValuesFile(ResValuesFile valuesFile, Directory out,
|
||||
ResXmlSerializer serial) throws AndrolibException {
|
||||
XmlSerializer serial) throws AndrolibException {
|
||||
try {
|
||||
OutputStream outStream = out.getFileOutput(valuesFile.getPath());
|
||||
serial.setOutput((outStream), null);
|
||||
serial.setDecodingEnabled(false);
|
||||
serial.startDocument(null, null);
|
||||
serial.startTag(null, "resources");
|
||||
|
||||
|
@ -17,102 +17,17 @@
|
||||
|
||||
package brut.androlib.res.decoder;
|
||||
|
||||
import brut.androlib.*;
|
||||
import brut.androlib.err.UndefinedResObject;
|
||||
import brut.androlib.res.AndrolibResources;
|
||||
import brut.androlib.res.data.ResPackage;
|
||||
import brut.androlib.res.data.value.ResAttr;
|
||||
import brut.androlib.res.data.value.ResScalarValue;
|
||||
import java.io.IOException;
|
||||
import org.xmlpull.mxp1_serializer.MXSerializer;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
/**
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
*/
|
||||
public class ResXmlSerializer extends MXSerializer {
|
||||
private final static String RES_NAMESPACE =
|
||||
"http://schemas.android.com/apk/res/android";
|
||||
|
||||
private ResPackage mCurrentPackage;
|
||||
private boolean mDecodingEnabled = true;
|
||||
|
||||
@Override
|
||||
public XmlSerializer attribute(String namespace, String name, String value)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException
|
||||
{
|
||||
if (! mDecodingEnabled) {
|
||||
return super.attribute(namespace, name, value);
|
||||
}
|
||||
String origVal = value;
|
||||
|
||||
try {
|
||||
ResScalarValue resValue =
|
||||
mCurrentPackage.getValueFactory().factory(value);
|
||||
value = null;
|
||||
|
||||
if (namespace != null && ! namespace.isEmpty()) {
|
||||
String pkgName = RES_NAMESPACE.equals(namespace) ?
|
||||
"android" : mCurrentPackage.getName();
|
||||
try {
|
||||
ResAttr attr = (ResAttr) mCurrentPackage.getResTable()
|
||||
.getValue(pkgName, "attr", name);
|
||||
value = attr.convertToResXmlFormat(resValue);
|
||||
} catch (UndefinedResObject ex) {
|
||||
System.err.println(String.format(
|
||||
"warning: udefined attr when decoding: " +
|
||||
"ns=%s, name=%s, value=%s",
|
||||
namespace, name, origVal));
|
||||
}
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
value = resValue.toResXmlFormat();
|
||||
}
|
||||
} catch (AndrolibException ex) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"could not decode attribute: ns=%s, name=%s, value=%s",
|
||||
namespace, name, origVal), ex);
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return super.attribute(namespace, name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlSerializer text(String text) throws IOException {
|
||||
if (mDecodingEnabled) {
|
||||
text = AndrolibResources.escapeForResXml(text);
|
||||
}
|
||||
return super.text(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlSerializer text(char[] buf, int start, int len) throws IOException {
|
||||
if (mDecodingEnabled) {
|
||||
return this.text(new String(buf, start, len));
|
||||
}
|
||||
return super.text(buf, start, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument(String encoding, Boolean standalone) throws
|
||||
IOException, IllegalArgumentException, IllegalStateException {
|
||||
super.startDocument(encoding != null ? encoding : "UTF-8", standalone);
|
||||
super.out.write("\n");
|
||||
super.setPrefix("android", RES_NAMESPACE);
|
||||
}
|
||||
|
||||
public void setCurrentPackage(ResPackage package_) {
|
||||
mCurrentPackage = package_;
|
||||
}
|
||||
|
||||
public boolean setDecodingEnabled(boolean escapeRefs) {
|
||||
boolean oldVal = mDecodingEnabled;
|
||||
this.mDecodingEnabled = escapeRefs;
|
||||
return oldVal;
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class ResXmlStreamDecoder implements ResStreamDecoder {
|
||||
XmlSerializerWrapper ser =
|
||||
getXmlWrapperFactory().newSerializerWrapper(mSerializer);
|
||||
ser.setOutput(out, null);
|
||||
mSerializer.setDecodingEnabled(true);
|
||||
// mSerializer.setDecodingEnabled(true);
|
||||
|
||||
while (par.nextToken() != XmlPullParser.END_DOCUMENT) {
|
||||
ser.event(par);
|
||||
|
Loading…
Reference in New Issue
Block a user