Added possibility to keep invalid resources, so they could be fixed manually.

This commit is contained in:
Ryszard Wiśniewski 2010-08-30 18:38:02 +02:00
parent 0c1a55cb31
commit 430fc72388
3 changed files with 40 additions and 14 deletions

View File

@ -17,6 +17,7 @@
package brut.androlib;
import brut.androlib.err.OutDirExistsException;
import brut.androlib.res.AndrolibResources;
import brut.androlib.res.data.ResPackage;
import brut.androlib.res.data.ResTable;
import brut.androlib.res.util.ExtFile;
@ -128,12 +129,17 @@ public class ApkDecoder {
}
}
public void setKeepBrokenResources(boolean keepBrokenResources) {
mKeepBrokenResources = keepBrokenResources;
}
public ResTable getResTable() throws AndrolibException {
if (mResTable == null) {
if (! hasResources()) {
throw new AndrolibException(
"Apk doesn't containt resources.arsc file");
}
AndrolibResources.sKeepBroken = mKeepBrokenResources;
mResTable = mAndrolib.getResTable(mApkFile);
mResTable.setFrameTag(mFrameTag);
}
@ -218,4 +224,5 @@ public class ApkDecoder {
private boolean mDebug = false;
private boolean mForceDelete = false;
private String mFrameTag;
private boolean mKeepBrokenResources = false;
}

View File

@ -49,7 +49,8 @@ final public class AndrolibResources {
public ResPackage loadMainPkg(ResTable resTable, ExtFile apkFile)
throws AndrolibException {
LOGGER.info("Loading resource table...");
ResPackage[] pkgs = getResPackagesFromApk(apkFile, resTable);
ResPackage[] pkgs = getResPackagesFromApk(
apkFile, resTable, sKeepBroken);
ResPackage pkg = null;
switch (pkgs.length) {
@ -78,7 +79,8 @@ final public class AndrolibResources {
File apk = getFrameworkApk(id, frameTag);
LOGGER.info("Loading resource table from file: " + apk);
ResPackage[] pkgs = getResPackagesFromApk(new ExtFile(apk), resTable);
ResPackage[] pkgs = getResPackagesFromApk(
new ExtFile(apk), resTable, true);
if (pkgs.length != 1) {
throw new AndrolibException(
@ -300,11 +302,11 @@ final public class AndrolibResources {
}
private ResPackage[] getResPackagesFromApk(ExtFile apkFile,
ResTable resTable) throws AndrolibException {
ResTable resTable, boolean keepBroken) throws AndrolibException {
try {
return ARSCDecoder.decode(
apkFile.getDirectory().getFileInput("resources.arsc"), false,
resTable).getPackages();
keepBroken, resTable).getPackages();
} catch (DirectoryException ex) {
throw new AndrolibException(
"Could not load resources.arsc from file: " + apkFile, ex);
@ -372,7 +374,7 @@ final public class AndrolibResources {
byte[] data = IOUtils.toByteArray(in);
ARSCData arsc = ARSCDecoder.decode(
new ByteArrayInputStream(data), true);
new ByteArrayInputStream(data), true, true);
publicizeResources(data, arsc.getFlagsOffsets());
File outFile = new File(getFrameworkDir(),
@ -439,7 +441,7 @@ final public class AndrolibResources {
public void publicizeResources(byte[] arsc) throws AndrolibException {
publicizeResources(arsc,
ARSCDecoder.decode(new ByteArrayInputStream(arsc), true)
ARSCDecoder.decode(new ByteArrayInputStream(arsc), true, true)
.getFlagsOffsets());
}
@ -551,6 +553,11 @@ final public class AndrolibResources {
return out.toString();
}
// TODO: dirty static hack. I have to refactor decoding mechanisms.
public static boolean sKeepBroken = false;
private final static Logger LOGGER =
Logger.getLogger(AndrolibResources.class.getName());
}

View File

@ -34,16 +34,17 @@ import org.apache.commons.io.input.CountingInputStream;
*/
public class ARSCDecoder {
public static ARSCData decode(InputStream arscStream,
boolean findFlagsOffsets) throws AndrolibException {
return decode(arscStream, findFlagsOffsets, new ResTable());
boolean findFlagsOffsets, boolean keepBroken)
throws AndrolibException {
return decode(arscStream, findFlagsOffsets, keepBroken, new ResTable());
}
public static ARSCData decode(InputStream arscStream,
boolean findFlagsOffsets, ResTable resTable)
boolean findFlagsOffsets, boolean keepBroken, ResTable resTable)
throws AndrolibException {
try {
ARSCDecoder decoder = new ARSCDecoder(arscStream, resTable,
findFlagsOffsets);
findFlagsOffsets, keepBroken);
ResPackage[] pkgs = decoder.readTable();
return new ARSCData(
pkgs,
@ -56,7 +57,7 @@ public class ARSCDecoder {
}
private ARSCDecoder(InputStream arscStream, ResTable resTable,
boolean storeFlagsOffsets) {
boolean storeFlagsOffsets, boolean keepBroken) {
if (storeFlagsOffsets) {
arscStream = mCountIn = new CountingInputStream(arscStream);
mFlagsOffsets = new ArrayList<FlagsOffset>();
@ -66,6 +67,7 @@ public class ARSCDecoder {
}
mIn = new ExtDataInput(new LEDataInputStream(arscStream));
mResTable = resTable;
mKeepBroken = keepBroken;
}
private ResPackage[] readTable() throws IOException, AndrolibException {
@ -142,11 +144,20 @@ public class ARSCDecoder {
ResConfigFlags flags = readConfigFlags();
int[] entryOffsets = mIn.readIntArray(entryCount);
ResConfig config;
if (flags.isInvalid) {
String resName = mType.getName() + flags.getQualifiers();
if (mKeepBroken) {
LOGGER.warning(
"Invalid config flags detected: " + resName);
} else {
LOGGER.warning(
"Invalid config flags detected. Dropping resources: " + resName);
}
}
ResConfig config;
if (flags.isInvalid && ! mKeepBroken) {
config = null;
LOGGER.warning(
"Invalid config flags detected. Dropping resources: " + mType.getName() + flags.getQualifiers());
} else if (mPkg.hasConfig(flags)) {
config = mPkg.getConfig(flags);
} else {
@ -328,6 +339,7 @@ public class ARSCDecoder {
private final ResTable mResTable;
private final CountingInputStream mCountIn;
private final List<FlagsOffset> mFlagsOffsets;
private final boolean mKeepBroken;
private Header mHeader;
private StringBlock mTableStrings;