From 8de13540075d69b584ecb61b0f2307b6fefcb59a Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Thu, 15 Feb 2018 18:05:23 -0500 Subject: [PATCH] aapt2: ZipUtils class to replicate the building of final zip --- .../main/java/brut/directory/ZipUtils.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 brut.j.dir/src/main/java/brut/directory/ZipUtils.java diff --git a/brut.j.dir/src/main/java/brut/directory/ZipUtils.java b/brut.j.dir/src/main/java/brut/directory/ZipUtils.java new file mode 100644 index 00000000..7898b19d --- /dev/null +++ b/brut.j.dir/src/main/java/brut/directory/ZipUtils.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2017 Ryszard Wiśniewski + * Copyright (C) 2017 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.directory; + +import brut.common.BrutException; +import brut.util.BrutIO; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; + +import java.io.*; +import java.util.Collection; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ZipUtils { + + private static Collection mDoNotCompress; + + public static void zipFolders(final File folder, final File zip, final File assets, final Collection doNotCompress) + throws BrutException, IOException { + + mDoNotCompress = doNotCompress; + ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zip)); + zipFolders(folder, zipOutputStream); + + // We manually set the assets because we need to retain the folder structure + if (assets != null) { + processFolder(assets, zipOutputStream, assets.getPath().length() - 6); + } + zipOutputStream.close(); + } + + private static void zipFolders(final File folder, final ZipOutputStream outputStream) + throws BrutException, IOException { + processFolder(folder, outputStream, folder.getPath().length() + 1); + } + + private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength) + throws BrutException, IOException { + for (final File file : folder.listFiles()) { + if (file.isFile()) { + final ZipEntry zipEntry = new ZipEntry(BrutIO.sanitizeUnknownFile(folder, file.getPath().substring(prefixLength))); + + // aapt binary by default takes in parameters via -0 arsc to list extensions that shouldn't be + // compressed. We will replicate that behavior + final String extension = FilenameUtils.getExtension(file.getAbsolutePath()); + if (mDoNotCompress != null && (mDoNotCompress.contains(extension) || mDoNotCompress.contains(zipEntry.getName()))) { + zipEntry.setMethod(ZipEntry.STORED); + zipEntry.setSize(file.length()); + BufferedInputStream unknownFile = new BufferedInputStream(new FileInputStream(file)); + CRC32 crc = BrutIO.calculateCrc(unknownFile); + zipEntry.setCrc(crc.getValue()); + unknownFile.close(); + } else { + zipEntry.setMethod(ZipEntry.DEFLATED); + } + + zipOutputStream.putNextEntry(zipEntry); + try (FileInputStream inputStream = new FileInputStream(file)) { + IOUtils.copy(inputStream, zipOutputStream); + } + zipOutputStream.closeEntry(); + } else if (file.isDirectory()) { + processFolder(file, zipOutputStream, prefixLength); + } + } + } +}