From d40710005f1db36f322302aded4540672b84c17d Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Thu, 19 Feb 2015 09:05:00 -0600 Subject: [PATCH] Handle BCP additional fields (script & variant) layoutDirection was being read in error. layoutDirection is read via bit shifting over screenLayout (byte 32, 33) The then removed layoutDirection freed up 2 bytes. This gave us 12 bytes of unknown space from byte 36 to 48. This corresponded to localeScript[4] and localeVariant[8] Adding proper support for those bytes fixed BCP support --- .../androlib/res/decoder/ARSCDecoder.java | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 5f1372e4..57caf4ad 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -291,9 +291,11 @@ public class ARSCDecoder { screenHeightDp = mIn.readShort(); } - short layoutDirection = 0; - if (size >= 38) { - layoutDirection = mIn.readShort(); + char[] localeScript = {'\00'}; + char[] localeVariant = {'\00'}; + if (size >= 48) { + localeScript = this.readScriptOrVariantChar(4).toCharArray(); + localeVariant = this.readScriptOrVariantChar(8).toCharArray(); } int exceedingSize = size - KNOWN_CONFIG_BYTES; @@ -313,29 +315,40 @@ public class ARSCDecoder { } } - return new ResConfigFlags(mcc, mnc, language, country, layoutDirection, + return new ResConfigFlags(mcc, mnc, language, country, orientation, touchscreen, density, keyboard, navigation, inputFlags, screenWidth, screenHeight, sdkVersion, screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp, - screenHeightDp, isInvalid); + screenHeightDp, localeScript, localeVariant, isInvalid); } private char[] unpackLanguageOrRegion(byte in0, byte in1, char base) throws AndrolibException { - if (in0 == 0 && in1 == 0) { - return new char[] {(char) in0, (char) in1}; - } else { - // check high bit, if so we have a packed 3 letter code - if (((in0 >> 7) & 1) == 1) { - int first = in1 & 0x1F; - int second = ((in1 & 0xE0) >> 5) + ((in0 & 0x03) << 3); - int third = (in0 & 0x7C) >> 2; + // check high bit, if so we have a packed 3 letter code + if (((in0 >> 7) & 1) == 1) { + int first = in1 & 0x1F; + int second = ((in1 & 0xE0) >> 5) + ((in0 & 0x03) << 3); + int third = (in0 & 0x7C) >> 2; - // since this function handles languages & regions, we add the value(s) to the base char - // which is usually 'a' or '0' depending on language or region. - return new char[] { (char) (first + base), (char) (second + base), (char) (third + base) }; - } - return new char[] { (char) in0, (char) in1 }; + // since this function handles languages & regions, we add the value(s) to the base char + // which is usually 'a' or '0' depending on language or region. + return new char[] { (char) (first + base), (char) (second + base), (char) (third + base) }; } + return new char[] { (char) in0, (char) in1 }; + } + + private String readScriptOrVariantChar(int length) throws AndrolibException, IOException { + StringBuilder string = new StringBuilder(16); + + while(length-- != 0) { + short ch = mIn.readByte(); + if (ch == 0) { + break; + } + string.append((char) ch); + } + mIn.skipBytes(length); + + return string.toString(); } private void addMissingResSpecs() throws AndrolibException { @@ -434,7 +447,7 @@ public class ARSCDecoder { } private static final Logger LOGGER = Logger.getLogger(ARSCDecoder.class.getName()); - private static final int KNOWN_CONFIG_BYTES = 38; + private static final int KNOWN_CONFIG_BYTES = 48; public static class ARSCData {