From 34a2d03b31fc92bbb032a3ef7e388ec16b0212b3 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Mon, 19 Feb 2018 06:45:48 -0500 Subject: [PATCH] Support for applications with an empty resources.arsc file - fixes #1730 --- .../src/main/java/brut/androlib/Androlib.java | 14 +++- .../brut/androlib/EmptyResourcesArscTest.java | 72 ++++++++++++++++++ .../brut/apktool/issue1730/issue1730.apk | Bin 0 -> 2894 bytes 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 brut.apktool/apktool-lib/src/test/java/brut/androlib/EmptyResourcesArscTest.java create mode 100644 brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1730/issue1730.apk diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index ba0a6763..f12fe5cb 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -478,9 +478,17 @@ public class Androlib { ninePatch, null, parseUsesFramework(usesFramework)); Directory tmpDir = new ExtFile(apkFile).getDirectory(); - tmpDir.copyToDir(apkDir, - tmpDir.containsDir("res") ? APK_RESOURCES_FILENAMES - : APK_RESOURCES_WITHOUT_RES_FILENAMES); + + // Sometimes an application is built with a resources.arsc file with no resources, + // Apktool assumes it will have a rebuilt arsc file, when it doesn't. So if we + // encounter a copy error, move to a warning and continue on. (#1730) + try { + tmpDir.copyToDir(apkDir, + tmpDir.containsDir("res") ? APK_RESOURCES_FILENAMES + : APK_RESOURCES_WITHOUT_RES_FILENAMES); + } catch (DirectoryException ex) { + LOGGER.warning(ex.getMessage()); + } // delete tmpDir apkFile.delete(); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/EmptyResourcesArscTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/EmptyResourcesArscTest.java new file mode 100644 index 00000000..337b9e9e --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/EmptyResourcesArscTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2018 Ryszard Wiśniewski + * Copyright (C) 2018 Connor Tumbleson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package brut.androlib; + +import brut.directory.ExtFile; +import brut.common.BrutException; +import brut.util.OS; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.util.logging.Logger; + +import static org.junit.Assert.assertTrue; + +/** + * @author Connor Tumbleson + */ +public class EmptyResourcesArscTest { + @BeforeClass + public static void beforeClass() throws Exception { + TestUtils.cleanFrameworkFile(); + sTmpDir = new ExtFile(OS.createTempDirectory()); + sTestOrigDir = new ExtFile(sTmpDir, "issue1730-orig"); + sTestNewDir = new ExtFile(sTmpDir, "issue1730-new"); + LOGGER.info("Unpacking issue1730.apk..."); + TestUtils.copyResourceDir(EmptyResourcesArscTest.class, "brut/apktool/issue1730", sTestOrigDir); + + File testApk = new File(sTestOrigDir, "issue1730.apk"); + + LOGGER.info("Decoding issue1730.apk..."); + ApkDecoder apkDecoder = new ApkDecoder(testApk); + apkDecoder.setOutDir(sTestNewDir); + apkDecoder.decode(); + + LOGGER.info("Building issue1730.apk..."); + ApkOptions apkOptions = new ApkOptions(); + new Androlib(apkOptions).build(sTestNewDir, testApk); + } + + @AfterClass + public static void afterClass() throws BrutException { + OS.rmdir(sTmpDir); + } + + @Test + public void buildAndDecodeTest() throws BrutException { + assertTrue(sTestNewDir.isDirectory()); + assertTrue(sTestOrigDir.isDirectory()); + } + + private static ExtFile sTmpDir; + private static ExtFile sTestOrigDir; + private static ExtFile sTestNewDir; + + private final static Logger LOGGER = Logger.getLogger(EmptyResourcesArscTest.class.getName()); +} \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1730/issue1730.apk b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1730/issue1730.apk new file mode 100644 index 0000000000000000000000000000000000000000..45a38efea06d26cd59624352befb38a036c86f1d GIT binary patch literal 2894 zcmdT`i9gh97ypeI3|T@#Jrn z+|?EPM#1s)!qB!wX?$c*N;Ir*!t<%^*!)QGdMg$|LaKqLVxkKun z`uV&JZ`;$yu4(KWDny-tUVz4~Vqz&9^C-?^D=RfuhF|%(*ms6MIoHrFnkcVO?$nW- zT9fid2MN!%DixT(><+1BOQle+zMXsT%5LUqmOP5vI+q+_Y zO)Y)(#DqubGBW+~!^#_ZS{_9H?QyRUU1hTq%t7-D>)i(udf(qS*hBkpWW~yPWnpf$ zZIM;+m?FF%YQ1za#C<_`ska`^?vx&RQAPKE@NvF^bv!D0djANoGK6`7pFTfOw)|}A zJh?uW+sfy>9pyjKnY;PU;5go61>y*Hm?GFqUpwrj@O*$XXc570&5OsnnCsX&Sna}_ zJJ?!bon6p)s~LP-t36H!&0UYv(e7yLEGOu88w`!owcFdYxS@p=gusLCI2}8bEuM=n z><$f)d^Ji(+lkGXm!*VjVTISVU>~q&wM+_NO%c$Dgh!-DB;fB!w7Pgr#eppz0s{ak zFbRsEXK=7rFq-PcxR8$bQ^P7Y^P?HOupgUC2Ws&d-WhjiEnUY8MRz(#olUDsHwv{O zY$ISQD_Jd7^TlKC_s(8&lpD6tdJl2koO)z?T#Ovi#Q|fwrF)%tx3h+JT)wCcDc?nM zrF?HG{(w^5Cm}n0W`1J8c;tG)wN~ypS3Y8SLfMQRZINX&mMn=CPsm!Rtq z>*&W|nPST3>kS+A8B&9y9x-)8@(519EE(z=xPDNCe`d!JaCs-7b_&=pcCx{AY8yi| zTI}Ef!}FO3V7ZNGT|g#QK5%netkf-->JWYkT`l7u)7d~ALRZU1Lzt(Vhj!h{Av-|{ zlTbZ5aZ>~&0)q5E7gKv;G!!2@aZLQ}y1k9)F4?eH(;+~t@^~q4w4o~g;_q_2$;SGN zV`c}K31hN*W^eAD-3$LT*|iY-xl?9ue1F7l4&5ddbLL7^&DAH5;IB+%rsv6zW%N|z z6$6v&rMdDy&REY6XhVhJ9#-!*MT+MbM8+*xA2Si)QnN><#mI@C9pSNph7H7u@DxUUKF{P4tOSvVe%291~K`5~Ts`${*iYNM4# zn%2?e12X443y)hGqGgALwVJ;f&e_5qQ8}Bg)Osd!QT-eG!`w8?D=NutHyFr^XYu@& z-isZ{!jkBght2`5RZgr6RlnwOypjei^3%KYtWXwjpX>S)taJvZ9UM>jMI6~BXnqa* z#o&#Uf+F1PXxEO8PPUP$?b(laU5ftz}&6mciy3%R-NA!meqd8zNbW4Ux>Y<_Y>LoMwrUB%<;Ec zeAZ-O>d#xvnChguiv?MJ)JA)Lu2+y=0TIb++~ zoPTygXB0=4(NNX7s#jqdh+LAyYoS9o^%{@LaK_sdd>XNPbt9-R^XZ^QpAk*7z(H3} zOFGX}HQUzi#mz0bMs0<@)tVaal$HmIemsMzxpMX3b9HxrmR(sNy}_yC;1AOCSyRSr z{LG7mT}G(trBF?!3B>x7+#0(wmQPJ?3I8@q5~p}XzYs65plwD9f|lo{c62WqKNq>R zAhC_M`qspDQ%c9dtTfJ@)NskfIN?~cbt$jGd|cjPR)Z7AaJ<{*uMxF7Dg=QqyR>l` z>z&wDTgN9~<(0gYjGsVL6Z@_$AGoV8oZVNkXN2@=+h7YSo>r^AKfcBAe2r4uWL_w zFhvBA{(^uY00B0G;~N2;|FcC9kVBx&1Yrsg0Gt5OfF}?L4(b=n3$(pJZy*o?goB7b z=%<5-FQ~un`zG%H`4X{KEKv6Sq1V>`svYS2vv&W&zNxDt4zk7*QD|BCPijPT7{|5xr`xBRoy{yKOC%