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 622e9c30..5f1372e4 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 @@ -256,8 +256,8 @@ public class ARSCDecoder { short mcc = mIn.readShort(); short mnc = mIn.readShort(); - char[] language = new char[] { (char) mIn.readByte(), (char) mIn.readByte() }; - char[] country = new char[] { (char) mIn.readByte(), (char) mIn.readByte() }; + char[] language = this.unpackLanguageOrRegion(mIn.readByte(), mIn.readByte(), 'a'); + char[] country = this.unpackLanguageOrRegion(mIn.readByte(), mIn.readByte(), '0'); byte orientation = mIn.readByte(); byte touchscreen = mIn.readByte(); @@ -320,6 +320,24 @@ public class ARSCDecoder { screenHeightDp, 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; + + // 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 void addMissingResSpecs() throws AndrolibException { int resId = mResId & 0xffff0000; diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java index 4ee4e694..dbac5bc8 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java @@ -182,6 +182,11 @@ public class BuildAndDecodeTest { compareValuesFiles("values-watch/strings.xml"); } + @Test + public void bcp47tagTest() throws BrutException, IOException { + compareValuesFiles("values-ast-rES/strings.xml"); + } + @Test public void drawableNoDpiTest() throws BrutException, IOException { compareResFolder("drawable-nodpi"); diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/values-ast-rES/strings.xml b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/values-ast-rES/strings.xml new file mode 100644 index 00000000..35eaf5ef --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/values-ast-rES/strings.xml @@ -0,0 +1,4 @@ + + + test1 + \ No newline at end of file