diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java index a31a3dcd..d2b845db 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java @@ -50,7 +50,7 @@ public class AaptInvoker { } } - public void invokeAapt(File apkFile, File manifest, File resDir, File rawDir, File assetDir, File[] include) + public void invoke(File apkFile, File manifest, File resDir, File rawDir, File assetDir, File[] include) throws AndrolibException { String aaptPath = mConfig.aaptPath; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index 92da8153..e4376045 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -35,7 +35,6 @@ import brut.util.AaptManager; import brut.util.BrutIO; import brut.util.OS; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; @@ -377,7 +376,7 @@ public class ApkBuilder { try { AaptInvoker invoker = new AaptInvoker(mConfig, mApkInfo); - invoker.invokeAapt(tmpFile, manifest, resDir, ninePatch, null, getIncludeFiles()); + invoker.invoke(tmpFile, manifest, resDir, ninePatch, null, getIncludeFiles()); Directory tmpDir = tmpFile.getDirectory(); tmpDir.copyToDir(outDir, "AndroidManifest.xml"); @@ -417,7 +416,7 @@ public class ApkBuilder { try { AaptInvoker invoker = new AaptInvoker(mConfig, mApkInfo); - invoker.invokeAapt(tmpFile, manifest, null, ninePatch, null, getIncludeFiles()); + invoker.invoke(tmpFile, manifest, null, ninePatch, null, getIncludeFiles()); Directory tmpDir = tmpFile.getDirectory(); tmpDir.copyToDir(outDir, "AndroidManifest.xml"); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java index c0f0b357..c4da821d 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java @@ -21,7 +21,6 @@ import brut.androlib.exceptions.AndrolibException; import brut.androlib.res.data.ResConfigFlags; import brut.directory.DirectoryException; import brut.directory.ExtFile; -import brut.directory.FileDirectory; import java.io.*; import java.nio.file.Files; @@ -212,10 +211,10 @@ public class ApkInfo implements YamlSerializable { return apkInfo; } - public static ApkInfo load(File appDir) throws AndrolibException { - try (InputStream in = new FileDirectory(appDir).getFileInput("apktool.yml")) { + public static ApkInfo load(ExtFile apkDir) throws AndrolibException { + try (InputStream in = apkDir.getDirectory().getFileInput("apktool.yml")) { ApkInfo apkInfo = ApkInfo.load(in); - apkInfo.setApkFile(new ExtFile(appDir)); + apkInfo.setApkFile(apkDir); return apkInfo; } catch (DirectoryException | IOException ex) { throw new AndrolibException(ex); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java index 55b8076f..4377a299 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/Framework.java @@ -22,8 +22,8 @@ import brut.androlib.exceptions.CantFindFrameworkResException; import brut.androlib.res.decoder.ARSCDecoder; import brut.androlib.res.data.arsc.ARSCData; import brut.androlib.res.data.arsc.FlagsOffset; +import brut.util.BrutIO; import brut.util.Jar; -import org.apache.commons.io.IOUtils; import java.io.*; import java.nio.file.Files; @@ -50,8 +50,6 @@ public class Framework { } public void installFramework(File frameFile, String tag) throws AndrolibException { - InputStream in = null; - ZipOutputStream out = null; try (ZipFile zip = new ZipFile(frameFile)) { ZipEntry entry = zip.getEntry("resources.arsc"); @@ -59,9 +57,7 @@ public class Framework { throw new AndrolibException("Can't find resources.arsc file"); } - in = zip.getInputStream(entry); - byte[] data = IOUtils.toByteArray(in); - + byte[] data = BrutIO.readAndClose(zip.getInputStream(entry)); ARSCData arsc = ARSCDecoder.decode(new ByteArrayInputStream(data), true, true); publicizeResources(data, arsc.getFlagsOffsets()); @@ -70,39 +66,36 @@ public class Framework { + (tag == null ? "" : '-' + tag) + ".apk"); - out = new ZipOutputStream(Files.newOutputStream(outFile.toPath())); - out.setMethod(ZipOutputStream.STORED); - CRC32 crc = new CRC32(); - crc.update(data); - entry = new ZipEntry("resources.arsc"); - entry.setSize(data.length); - entry.setMethod(ZipEntry.STORED); - entry.setCrc(crc.getValue()); - out.putNextEntry(entry); - out.write(data); - out.closeEntry(); - - //Write fake AndroidManifest.xml file to support original aapt - entry = zip.getEntry("AndroidManifest.xml"); - if (entry != null) { - in = zip.getInputStream(entry); - byte[] manifest = IOUtils.toByteArray(in); - CRC32 manifestCrc = new CRC32(); - manifestCrc.update(manifest); - entry.setSize(manifest.length); - entry.setCompressedSize(-1); - entry.setCrc(manifestCrc.getValue()); + try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(outFile.toPath()))) { + out.setMethod(ZipOutputStream.STORED); + CRC32 crc = new CRC32(); + crc.update(data); + entry = new ZipEntry("resources.arsc"); + entry.setSize(data.length); + entry.setMethod(ZipEntry.STORED); + entry.setCrc(crc.getValue()); out.putNextEntry(entry); - out.write(manifest); + out.write(data); out.closeEntry(); + + // write fake AndroidManifest.xml file to support original aapt + entry = zip.getEntry("AndroidManifest.xml"); + if (entry != null) { + byte[] manifest = BrutIO.readAndClose(zip.getInputStream(entry)); + CRC32 manifestCrc = new CRC32(); + manifestCrc.update(manifest); + entry.setSize(manifest.length); + entry.setCompressedSize(-1); + entry.setCrc(manifestCrc.getValue()); + out.putNextEntry(entry); + out.write(manifest); + out.closeEntry(); + } } LOGGER.info("Framework installed to: " + outFile); } catch (IOException ex) { throw new AndrolibException(ex); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); } } @@ -212,15 +205,12 @@ public class Framework { } if (id == 1) { - try ( - InputStream in = getAndroidFrameworkResourcesAsStream(); - OutputStream out = Files.newOutputStream(apk.toPath()) - ) { - IOUtils.copy(in, out); - return apk; + try { + BrutIO.copyAndClose(getAndroidFrameworkResourcesAsStream(), Files.newOutputStream(apk.toPath())); } catch (IOException ex) { throw new AndrolibException(ex); } + return apk; } throw new CantFindFrameworkResException(id); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java index 3e429c55..72c02e01 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java @@ -25,9 +25,8 @@ import brut.androlib.res.xml.ResValuesXmlSerializable; import brut.androlib.res.xml.ResXmlPatcher; import brut.directory.Directory; import brut.directory.DirectoryException; -import brut.directory.FileDirectory; +import brut.directory.ExtFile; import brut.xmlpull.MXSerializer; -import org.apache.commons.io.IOUtils; import org.xmlpull.v1.XmlSerializer; import java.io.*; @@ -77,27 +76,25 @@ public class ResourcesDecoder { XmlSerializer xmlSerializer = newXmlSerializer(); ResStreamDecoder fileDecoder = new AndroidManifestPullStreamDecoder(axmlParser, xmlSerializer); - Directory inApk, out; - InputStream inputStream = null; - OutputStream outputStream = null; + Directory in, out; try { - inApk = mApkInfo.getApkFile().getDirectory(); - out = new FileDirectory(outDir); + in = mApkInfo.getApkFile().getDirectory(); + out = new ExtFile(outDir).getDirectory(); if (mApkInfo.hasResources()) { LOGGER.info("Decoding AndroidManifest.xml with resources..."); } else { LOGGER.info("Decoding AndroidManifest.xml with only framework resources..."); } - inputStream = inApk.getFileInput("AndroidManifest.xml"); - outputStream = out.getFileOutput("AndroidManifest.xml"); - fileDecoder.decode(inputStream, outputStream); - } catch (DirectoryException ex) { + try ( + InputStream is = in.getFileInput("AndroidManifest.xml"); + OutputStream os = out.getFileOutput("AndroidManifest.xml") + ) { + fileDecoder.decode(is, os); + } + } catch (DirectoryException | IOException ex) { throw new AndrolibException(ex); - } finally { - IOUtils.closeQuietly(inputStream); - IOUtils.closeQuietly(outputStream); } File manifest = new File(outDir, "AndroidManifest.xml"); @@ -171,25 +168,24 @@ public class ResourcesDecoder { Directory in, out, outRes; try { - out = new FileDirectory(outDir); in = mApkInfo.getApkFile().getDirectory(); - outRes = out.createDir("res"); + out = new ExtFile(outDir).getDirectory().createDir("res"); } catch (DirectoryException ex) { throw new AndrolibException(ex); } for (ResPackage pkg : mResTable.listMainPackages()) { - LOGGER.info("Decoding file-resources..."); for (ResResource res : pkg.listFiles()) { - fileDecoder.decode(res, in, outRes, mResFileMapping); + fileDecoder.decode(res, in, out, mResFileMapping); } LOGGER.info("Decoding values */* XMLs..."); for (ResValuesFile valuesFile : pkg.listValuesFiles()) { - generateValuesFile(valuesFile, outRes, xmlSerializer); + generateValuesFile(valuesFile, out, xmlSerializer); } - generatePublicXml(pkg, outRes, xmlSerializer); + + generatePublicXml(pkg, out, xmlSerializer); } AndrolibException decodeError = axmlParser.getFirstError(); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java index 35816fac..08ca7202 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java @@ -22,9 +22,9 @@ import brut.androlib.exceptions.RawXmlEncounteredException; import brut.androlib.res.data.ResResource; import brut.androlib.res.data.value.ResBoolValue; import brut.androlib.res.data.value.ResFileValue; -import brut.directory.DirUtil; import brut.directory.Directory; import brut.directory.DirectoryException; +import brut.directory.DirUtil; import brut.util.BrutIO; import java.io.*; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResRawStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResRawStreamDecoder.java index 38d81c82..6f3917dc 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResRawStreamDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResRawStreamDecoder.java @@ -23,8 +23,7 @@ import java.io.*; public class ResRawStreamDecoder implements ResStreamDecoder { @Override - public void decode(InputStream in, OutputStream out) - throws AndrolibException { + public void decode(InputStream in, OutputStream out) throws AndrolibException { try { IOUtils.copy(in, out); } catch (IOException ex) { diff --git a/brut.j.dir/src/main/java/brut/directory/DirUtil.java b/brut.j.dir/src/main/java/brut/directory/DirUtil.java index c6e96794..d2a361c2 100644 --- a/brut.j.dir/src/main/java/brut/directory/DirUtil.java +++ b/brut.j.dir/src/main/java/brut/directory/DirUtil.java @@ -52,16 +52,16 @@ public class DirUtil { copyToDir(in, out, fileName, fileName); } - public static void copyToDir(Directory in, Directory out, String inFile, String outFile) + public static void copyToDir(Directory in, Directory out, String inFileName, String outFileName) throws DirectoryException { try { - if (in.containsDir(inFile)) { - in.getDir(inFile).copyToDir(out.createDir(outFile)); + if (in.containsDir(inFileName)) { + in.getDir(inFileName).copyToDir(out.createDir(outFileName)); } else { - BrutIO.copyAndClose(in.getFileInput(inFile), out.getFileOutput(outFile)); + BrutIO.copyAndClose(in.getFileInput(inFileName), out.getFileOutput(outFileName)); } } catch (IOException ex) { - throw new DirectoryException("Error copying file: " + inFile, ex); + throw new DirectoryException("Error copying file: " + inFileName, ex); } } @@ -81,28 +81,33 @@ public class DirUtil { public static void copyToDir(Directory in, File out, String fileName) throws DirectoryException { + copyToDir(in, out, fileName, fileName); + } + + public static void copyToDir(Directory in, File out, String inFileName, String outFileName) + throws DirectoryException { try { - if (in.containsDir(fileName)) { - File outDir = new File(out, fileName); + if (in.containsDir(inFileName)) { + File outDir = new File(out, outFileName); OS.rmdir(outDir); - in.getDir(fileName).copyToDir(outDir); - } else if (in.containsFile(fileName)) { - String validFileName = BrutIO.sanitizePath(out, fileName); - if (!validFileName.isEmpty()) { - File outFile = new File(out, validFileName); + in.getDir(inFileName).copyToDir(outDir); + } else if (in.containsFile(inFileName)) { + outFileName = BrutIO.sanitizePath(out, outFileName); + if (!outFileName.isEmpty()) { + File outFile = new File(out, outFileName); //noinspection ResultOfMethodCallIgnored outFile.getParentFile().mkdirs(); - BrutIO.copyAndClose(in.getFileInput(fileName), Files.newOutputStream(outFile.toPath())); + BrutIO.copyAndClose(in.getFileInput(inFileName), Files.newOutputStream(outFile.toPath())); } } else { // Skip if directory/file not found } } catch (FileSystemException ex) { - LOGGER.warning(String.format("Skipping file %s (%s)", fileName, ex.getReason())); + LOGGER.warning(String.format("Skipping file %s (%s)", inFileName, ex.getReason())); } catch (RootUnknownFileException | InvalidUnknownFileException | TraversalUnknownFileException | IOException ex) { - LOGGER.warning(String.format("Skipping file %s (%s)", fileName, ex.getMessage())); + LOGGER.warning(String.format("Skipping file %s (%s)", inFileName, ex.getMessage())); } catch (BrutException ex) { - throw new DirectoryException("Error copying file: " + fileName, ex); + throw new DirectoryException("Error copying file: " + inFileName, ex); } } } diff --git a/brut.j.util/src/main/java/brut/util/BrutIO.java b/brut.j.util/src/main/java/brut/util/BrutIO.java index 8f319a4d..c6d33537 100644 --- a/brut.j.util/src/main/java/brut/util/BrutIO.java +++ b/brut.j.util/src/main/java/brut/util/BrutIO.java @@ -26,6 +26,14 @@ import java.io.*; import java.util.zip.CRC32; public class BrutIO { + public static byte[] readAndClose(InputStream in) throws IOException { + try { + return IOUtils.toByteArray(in); + } finally { + IOUtils.closeQuietly(in); + } + } + public static void copyAndClose(InputStream in, OutputStream out) throws IOException { try { IOUtils.copy(in, out); @@ -60,11 +68,11 @@ public class BrutIO { return modified; } - public static CRC32 calculateCrc(InputStream input) throws IOException { + public static CRC32 calculateCrc(InputStream in) throws IOException { CRC32 crc = new CRC32(); int bytesRead; byte[] buffer = new byte[8192]; - while ((bytesRead = input.read(buffer)) != -1) { + while ((bytesRead = in.read(buffer)) != -1) { crc.update(buffer, 0, bytesRead); } return crc; diff --git a/brut.j.util/src/main/java/brut/util/ExtCountingDataInput.java b/brut.j.util/src/main/java/brut/util/ExtCountingDataInput.java index 95e13182..cbfb7048 100644 --- a/brut.j.util/src/main/java/brut/util/ExtCountingDataInput.java +++ b/brut.j.util/src/main/java/brut/util/ExtCountingDataInput.java @@ -24,6 +24,8 @@ import java.io.IOException; import java.util.logging.Logger; public class ExtCountingDataInput extends ExtDataInput { + private static final Logger LOGGER = Logger.getLogger(ExtCountingDataInput.class.getName()); + private final CountingInputStream mCountIn; public ExtCountingDataInput(LittleEndianDataInputStream in) { @@ -67,6 +69,4 @@ public class ExtCountingDataInput extends ExtDataInput { } return array; } - - private static final Logger LOGGER = Logger.getLogger(ExtCountingDataInput.class.getName()); } diff --git a/brut.j.util/src/main/java/brut/util/Jar.java b/brut.j.util/src/main/java/brut/util/Jar.java index f72f4316..1473dae9 100644 --- a/brut.j.util/src/main/java/brut/util/Jar.java +++ b/brut.j.util/src/main/java/brut/util/Jar.java @@ -17,6 +17,7 @@ package brut.util; import brut.common.BrutException; +import brut.util.BrutIO; import org.apache.commons.io.IOUtils; import java.io.*; @@ -42,8 +43,9 @@ public abstract class Jar { } public static File extractToTmp(String resourcePath, String tmpPrefix, Class clazz) throws BrutException { + InputStream in = null; try { - InputStream in = clazz.getResourceAsStream(resourcePath); + in = clazz.getResourceAsStream(resourcePath); if (in == null) { throw new FileNotFoundException(resourcePath); } @@ -52,14 +54,13 @@ public abstract class Jar { File fileOut = File.createTempFile(tmpPrefix, suffix + ".tmp"); fileOut.deleteOnExit(); - OutputStream out = Files.newOutputStream(fileOut.toPath()); - IOUtils.copy(in, out); - in.close(); - out.close(); + BrutIO.copyAndClose(in, Files.newOutputStream(fileOut.toPath())); return fileOut; } catch (IOException ex) { throw new BrutException("Could not extract resource: " + resourcePath, ex); + } finally { + IOUtils.closeQuietly(in); } } } diff --git a/brut.j.util/src/main/java/brut/util/OS.java b/brut.j.util/src/main/java/brut/util/OS.java index 590a8a33..b0f1e57d 100644 --- a/brut.j.util/src/main/java/brut/util/OS.java +++ b/brut.j.util/src/main/java/brut/util/OS.java @@ -17,7 +17,7 @@ package brut.util; import brut.common.BrutException; -import org.apache.commons.io.IOUtils; +import brut.util.BrutIO; import java.io.*; import java.nio.file.Files; @@ -28,7 +28,6 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; public class OS { - private static final Logger LOGGER = Logger.getLogger(""); public static void rmdir(File dir) throws BrutException { @@ -77,11 +76,7 @@ public class OS { continue; } try { - try (InputStream in = Files.newInputStream(file.toPath())) { - try (OutputStream out = Files.newOutputStream(destFile.toPath())) { - IOUtils.copy(in, out); - } - } + BrutIO.copyAndClose(Files.newInputStream(file.toPath()), Files.newOutputStream(destFile.toPath())); } catch (IOException ex) { throw new BrutException("Could not copy file: " + file, ex); }