From 430fc723885767b4391c9c064fd06470ff866887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Wi=C5=9Bniewski?= Date: Mon, 30 Aug 2010 18:38:02 +0200 Subject: [PATCH] Added possibility to keep invalid resources, so they could be fixed manually. --- src/brut/androlib/ApkDecoder.java | 7 +++++ src/brut/androlib/res/AndrolibResources.java | 19 +++++++++---- .../androlib/res/decoder/ARSCDecoder.java | 28 +++++++++++++------ 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/brut/androlib/ApkDecoder.java b/src/brut/androlib/ApkDecoder.java index 3438e4f0..d3d41626 100644 --- a/src/brut/androlib/ApkDecoder.java +++ b/src/brut/androlib/ApkDecoder.java @@ -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; } diff --git a/src/brut/androlib/res/AndrolibResources.java b/src/brut/androlib/res/AndrolibResources.java index 903c486c..91e1aec6 100644 --- a/src/brut/androlib/res/AndrolibResources.java +++ b/src/brut/androlib/res/AndrolibResources.java @@ -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()); } diff --git a/src/brut/androlib/res/decoder/ARSCDecoder.java b/src/brut/androlib/res/decoder/ARSCDecoder.java index 6209aac9..4f6bd3d0 100644 --- a/src/brut/androlib/res/decoder/ARSCDecoder.java +++ b/src/brut/androlib/res/decoder/ARSCDecoder.java @@ -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(); @@ -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 mFlagsOffsets; + private final boolean mKeepBroken; private Header mHeader; private StringBlock mTableStrings;