mirror of
https://github.com/revanced/Apktool.git
synced 2024-11-07 05:06:59 +01:00
Merge pull request #1758 from iBotPeaches/issue-1272
Prevent "too long" commands on Windows.
This commit is contained in:
commit
335d51c0f6
@ -19,7 +19,6 @@ package brut.androlib;
|
|||||||
import brut.androlib.meta.MetaInfo;
|
import brut.androlib.meta.MetaInfo;
|
||||||
import brut.androlib.meta.UsesFramework;
|
import brut.androlib.meta.UsesFramework;
|
||||||
import brut.androlib.res.AndrolibResources;
|
import brut.androlib.res.AndrolibResources;
|
||||||
import brut.androlib.res.data.ResConfigFlags;
|
|
||||||
import brut.androlib.res.data.ResPackage;
|
import brut.androlib.res.data.ResPackage;
|
||||||
import brut.androlib.res.data.ResTable;
|
import brut.androlib.res.data.ResTable;
|
||||||
import brut.androlib.res.data.ResUnknownFiles;
|
import brut.androlib.res.data.ResUnknownFiles;
|
||||||
@ -41,8 +40,6 @@ import java.util.zip.ZipFile;
|
|||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
@ -161,28 +158,15 @@ public class Androlib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFilesOrExts) throws AndrolibException {
|
public void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFiles) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
Directory unk = apkFile.getDirectory();
|
Directory unk = apkFile.getDirectory();
|
||||||
Set<String> files = unk.getFiles(true);
|
Set<String> files = unk.getFiles(true);
|
||||||
String ext;
|
|
||||||
|
|
||||||
for (String file : files) {
|
for (String file : files) {
|
||||||
if (isAPKFileNames(file) && !NO_COMPRESS_PATTERN.matcher(file).find()) {
|
if (isAPKFileNames(file) && !NO_COMPRESS_PATTERN.matcher(file).find()) {
|
||||||
if (unk.getCompressionLevel(file) == 0) {
|
if (unk.getCompressionLevel(file) == 0 && !uncompressedFiles.contains(file)) {
|
||||||
|
uncompressedFiles.add(file);
|
||||||
if (StringUtils.countMatches(file, ".") > 1) {
|
|
||||||
ext = file;
|
|
||||||
} else {
|
|
||||||
ext = FilenameUtils.getExtension(file);
|
|
||||||
if (ext.isEmpty()) {
|
|
||||||
ext = file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! uncompressedFilesOrExts.contains(ext)) {
|
|
||||||
uncompressedFilesOrExts.add(ext);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,6 +261,7 @@ public class Androlib {
|
|||||||
apkOptions.isFramework = meta.isFrameworkApk;
|
apkOptions.isFramework = meta.isFrameworkApk;
|
||||||
apkOptions.resourcesAreCompressed = meta.compressionType;
|
apkOptions.resourcesAreCompressed = meta.compressionType;
|
||||||
apkOptions.doNotCompress = meta.doNotCompress;
|
apkOptions.doNotCompress = meta.doNotCompress;
|
||||||
|
apkOptions.noCompressAssets = meta.noCompressAssets;
|
||||||
|
|
||||||
mAndRes.setSdkInfo(meta.sdkInfo);
|
mAndRes.setSdkInfo(meta.sdkInfo);
|
||||||
mAndRes.setPackageId(meta.packageInfo);
|
mAndRes.setPackageId(meta.packageInfo);
|
||||||
@ -308,8 +293,8 @@ public class Androlib {
|
|||||||
buildApk(appDir, outFile);
|
buildApk(appDir, outFile);
|
||||||
|
|
||||||
// we must go after the Apk is built, and copy the files in via Zip
|
// we must go after the Apk is built, and copy the files in via Zip
|
||||||
// this is because Aapt won't add files it doesn't know (ex unknown files)
|
// this is because Aapt won't add files it doesn't know (ex unknown files & uncompressed assets)
|
||||||
buildUnknownFiles(appDir, outFile, meta);
|
buildUnknownAndUncompressedAssets(appDir, outFile, meta);
|
||||||
|
|
||||||
// we copied the AndroidManifest.xml to AndroidManifest.xml.orig so we can edit it
|
// we copied the AndroidManifest.xml to AndroidManifest.xml.orig so we can edit it
|
||||||
// lets restore the unedited one, to not change the original
|
// lets restore the unedited one, to not change the original
|
||||||
@ -603,12 +588,16 @@ public class Androlib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildUnknownFiles(File appDir, File outFile, MetaInfo meta)
|
public void buildUnknownAndUncompressedAssets(File appDir, File outFile, MetaInfo meta)
|
||||||
throws AndrolibException {
|
throws AndrolibException {
|
||||||
|
if (meta.unknownFiles == null && meta.noCompressAssets == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (meta.unknownFiles != null) {
|
if (meta.unknownFiles != null) {
|
||||||
LOGGER.info("Copying unknown files/dir...");
|
LOGGER.info("Copying unknown files/dir...");
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> files = meta.unknownFiles;
|
|
||||||
File tempFile = new File(outFile.getParent(), outFile.getName() + ".apktool_temp");
|
File tempFile = new File(outFile.getParent(), outFile.getName() + ".apktool_temp");
|
||||||
boolean renamed = outFile.renameTo(tempFile);
|
boolean renamed = outFile.renameTo(tempFile);
|
||||||
if (!renamed) {
|
if (!renamed) {
|
||||||
@ -619,8 +608,9 @@ public class Androlib {
|
|||||||
ZipFile inputFile = new ZipFile(tempFile);
|
ZipFile inputFile = new ZipFile(tempFile);
|
||||||
ZipOutputStream actualOutput = new ZipOutputStream(new FileOutputStream(outFile))
|
ZipOutputStream actualOutput = new ZipOutputStream(new FileOutputStream(outFile))
|
||||||
) {
|
) {
|
||||||
copyExistingFiles(inputFile, actualOutput);
|
copyExistingFiles(inputFile, actualOutput, meta.noCompressAssets);
|
||||||
copyUnknownFiles(appDir, actualOutput, files);
|
copyUncompressedAssetFiles(appDir, actualOutput, meta.noCompressAssets);
|
||||||
|
copyUnknownFiles(appDir, actualOutput, meta.unknownFiles);
|
||||||
} catch (IOException | BrutException ex) {
|
} catch (IOException | BrutException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
@ -628,13 +618,16 @@ public class Androlib {
|
|||||||
// Remove our temporary file.
|
// Remove our temporary file.
|
||||||
tempFile.delete();
|
tempFile.delete();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void copyExistingFiles(ZipFile inputFile, ZipOutputStream outputFile) throws IOException {
|
private void copyExistingFiles(ZipFile inputFile, ZipOutputStream outputFile, Collection<String> assets)
|
||||||
|
throws IOException {
|
||||||
// First, copy the contents from the existing outFile:
|
// First, copy the contents from the existing outFile:
|
||||||
Enumeration<? extends ZipEntry> entries = inputFile.entries();
|
Enumeration<? extends ZipEntry> entries = inputFile.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
ZipEntry entry = new ZipEntry(entries.nextElement());
|
ZipEntry entry = new ZipEntry(entries.nextElement());
|
||||||
|
if (assets != null && assets.contains(entry.getName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// We can't reuse the compressed size because it depends on compression sizes.
|
// We can't reuse the compressed size because it depends on compression sizes.
|
||||||
entry.setCompressedSize(-1);
|
entry.setCompressedSize(-1);
|
||||||
@ -651,25 +644,26 @@ public class Androlib {
|
|||||||
|
|
||||||
private void copyUnknownFiles(File appDir, ZipOutputStream outputFile, Map<String, String> files)
|
private void copyUnknownFiles(File appDir, ZipOutputStream outputFile, Map<String, String> files)
|
||||||
throws BrutException, IOException {
|
throws BrutException, IOException {
|
||||||
|
|
||||||
File unknownFileDir = new File(appDir, UNK_DIRNAME);
|
File unknownFileDir = new File(appDir, UNK_DIRNAME);
|
||||||
|
if (files == null || files.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// loop through unknown files
|
// loop through unknown files
|
||||||
for (Map.Entry<String,String> unknownFileInfo : files.entrySet()) {
|
for (Map.Entry<String,String> unknownFileInfo : files.entrySet()) {
|
||||||
File inputFile = new File(unknownFileDir, BrutIO.sanitizeUnknownFile(unknownFileDir, unknownFileInfo.getKey()));
|
String normalizedPath = BrutIO.normalizePath(unknownFileInfo.getKey());
|
||||||
|
String cleanedPath = BrutIO.sanitizeUnknownFile(unknownFileDir, normalizedPath);
|
||||||
|
File inputFile = new File(unknownFileDir, cleanedPath);
|
||||||
if (inputFile.isDirectory()) {
|
if (inputFile.isDirectory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZipEntry newEntry = new ZipEntry(unknownFileInfo.getKey());
|
ZipEntry newEntry = new ZipEntry(cleanedPath);
|
||||||
int method = Integer.parseInt(unknownFileInfo.getValue());
|
int method = Integer.parseInt(unknownFileInfo.getValue());
|
||||||
LOGGER.fine(String.format("Copying unknown file %s with method %d", unknownFileInfo.getKey(), method));
|
LOGGER.fine(String.format("Copying unknown file %s with method %d", unknownFileInfo.getKey(), method));
|
||||||
if (method == ZipEntry.STORED) {
|
if (method == ZipEntry.STORED) {
|
||||||
newEntry.setMethod(ZipEntry.STORED);
|
newEntry = getStoredZipEntry(cleanedPath, inputFile);
|
||||||
newEntry.setSize(inputFile.length());
|
|
||||||
newEntry.setCompressedSize(-1);
|
|
||||||
BufferedInputStream unknownFile = new BufferedInputStream(new FileInputStream(inputFile));
|
|
||||||
CRC32 crc = BrutIO.calculateCrc(unknownFile);
|
|
||||||
newEntry.setCrc(crc.getValue());
|
|
||||||
} else {
|
} else {
|
||||||
newEntry.setMethod(ZipEntry.DEFLATED);
|
newEntry.setMethod(ZipEntry.DEFLATED);
|
||||||
}
|
}
|
||||||
@ -680,6 +674,46 @@ public class Androlib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyUncompressedAssetFiles(File appDir, ZipOutputStream outputFile, Collection<String> files)
|
||||||
|
throws BrutException, IOException {
|
||||||
|
|
||||||
|
if (files == null || files.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File assetFileDir = new File(appDir, ASSET_DIRNAME);
|
||||||
|
|
||||||
|
for (String asset : files) {
|
||||||
|
String normalizedPath = BrutIO.normalizePath(asset);
|
||||||
|
String cleanedPath = BrutIO.sanitizeUnknownFile(assetFileDir, normalizedPath);
|
||||||
|
|
||||||
|
File inputFile = new File(appDir, cleanedPath);
|
||||||
|
if (inputFile.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.fine(String.format("Copying uncompressed asset: %s", normalizedPath));
|
||||||
|
ZipEntry newEntry = getStoredZipEntry(normalizedPath, inputFile);
|
||||||
|
outputFile.putNextEntry(newEntry);
|
||||||
|
BrutIO.copy(inputFile, outputFile);
|
||||||
|
outputFile.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ZipEntry getStoredZipEntry(String cleanedPath, File inputFile)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
ZipEntry newEntry = new ZipEntry(cleanedPath);
|
||||||
|
newEntry.setMethod(ZipEntry.STORED);
|
||||||
|
newEntry.setSize(inputFile.length());
|
||||||
|
newEntry.setCompressedSize(-1);
|
||||||
|
BufferedInputStream unknownFile = new BufferedInputStream(new FileInputStream(inputFile));
|
||||||
|
CRC32 crc = BrutIO.calculateCrc(unknownFile);
|
||||||
|
newEntry.setCrc(crc.getValue());
|
||||||
|
|
||||||
|
return newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
public void buildApk(File appDir, File outApk) throws AndrolibException {
|
public void buildApk(File appDir, File outApk) throws AndrolibException {
|
||||||
LOGGER.info("Building apk file...");
|
LOGGER.info("Building apk file...");
|
||||||
if (outApk.exists()) {
|
if (outApk.exists()) {
|
||||||
@ -777,6 +811,7 @@ public class Androlib {
|
|||||||
private final static String SMALI_DIRNAME = "smali";
|
private final static String SMALI_DIRNAME = "smali";
|
||||||
private final static String APK_DIRNAME = "build/apk";
|
private final static String APK_DIRNAME = "build/apk";
|
||||||
private final static String UNK_DIRNAME = "unknown";
|
private final static String UNK_DIRNAME = "unknown";
|
||||||
|
private final static String ASSET_DIRNAME = "assets";
|
||||||
private final static String[] APK_RESOURCES_FILENAMES = new String[] {
|
private final static String[] APK_RESOURCES_FILENAMES = new String[] {
|
||||||
"resources.arsc", "AndroidManifest.xml", "res" };
|
"resources.arsc", "AndroidManifest.xml", "res" };
|
||||||
private final static String[] APK_RESOURCES_WITHOUT_RES_FILENAMES = new String[] {
|
private final static String[] APK_RESOURCES_WITHOUT_RES_FILENAMES = new String[] {
|
||||||
@ -791,6 +826,6 @@ public class Androlib {
|
|||||||
// Taken from AOSP's frameworks/base/tools/aapt/Package.cpp
|
// Taken from AOSP's frameworks/base/tools/aapt/Package.cpp
|
||||||
private final static Pattern NO_COMPRESS_PATTERN = Pattern.compile("\\.(" +
|
private final static Pattern NO_COMPRESS_PATTERN = Pattern.compile("\\.(" +
|
||||||
"jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|imy|xmf|mp4|" +
|
"jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|imy|xmf|mp4|" +
|
||||||
"m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|mkv)$");
|
"m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|mkv|arsc)$");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ public class ApkDecoder {
|
|||||||
|
|
||||||
private void putFileCompressionInfo(MetaInfo meta) throws AndrolibException {
|
private void putFileCompressionInfo(MetaInfo meta) throws AndrolibException {
|
||||||
if (mUncompressedFiles != null && !mUncompressedFiles.isEmpty()) {
|
if (mUncompressedFiles != null && !mUncompressedFiles.isEmpty()) {
|
||||||
meta.doNotCompress = mUncompressedFiles;
|
meta.noCompressAssets = mUncompressedFiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,10 @@ public class ApkOptions {
|
|||||||
public boolean isFramework = false;
|
public boolean isFramework = false;
|
||||||
public boolean resourcesAreCompressed = false;
|
public boolean resourcesAreCompressed = false;
|
||||||
public boolean useAapt2 = false;
|
public boolean useAapt2 = false;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Collection<String> doNotCompress;
|
public Collection<String> doNotCompress;
|
||||||
|
public Collection<String> noCompressAssets;
|
||||||
|
|
||||||
public String frameworkFolderLocation = null;
|
public String frameworkFolderLocation = null;
|
||||||
public String frameworkTag = null;
|
public String frameworkTag = null;
|
||||||
|
@ -37,7 +37,10 @@ public class MetaInfo {
|
|||||||
public boolean sharedLibrary;
|
public boolean sharedLibrary;
|
||||||
public boolean sparseResources;
|
public boolean sparseResources;
|
||||||
public Map<String, String> unknownFiles;
|
public Map<String, String> unknownFiles;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Collection<String> doNotCompress;
|
public Collection<String> doNotCompress;
|
||||||
|
public Collection<String> noCompressAssets;
|
||||||
|
|
||||||
private static Yaml getYaml() {
|
private static Yaml getYaml() {
|
||||||
DumperOptions options = new DumperOptions();
|
DumperOptions options = new DumperOptions();
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package brut.androlib.res.data;
|
package brut.androlib.res.data;
|
||||||
|
|
||||||
|
import brut.util.BrutIO;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ public class ResUnknownFiles {
|
|||||||
private final Map<String, String> mUnknownFiles = new LinkedHashMap<>();
|
private final Map<String, String> mUnknownFiles = new LinkedHashMap<>();
|
||||||
|
|
||||||
public void addUnknownFileInfo(String file, String value) {
|
public void addUnknownFileInfo(String file, String value) {
|
||||||
mUnknownFiles.put(file, value);
|
mUnknownFiles.put(BrutIO.normalizePath(file), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getUnknownFiles() {
|
public Map<String, String> getUnknownFiles() {
|
||||||
|
@ -31,6 +31,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
||||||
@ -45,11 +46,11 @@ public class BaseTest {
|
|||||||
|
|
||||||
Map<String, String> controlFiles = control.unknownFiles;
|
Map<String, String> controlFiles = control.unknownFiles;
|
||||||
Map<String, String> testFiles = test.unknownFiles;
|
Map<String, String> testFiles = test.unknownFiles;
|
||||||
assertTrue(controlFiles.size() == testFiles.size());
|
assertEquals(controlFiles.size(), testFiles.size());
|
||||||
|
|
||||||
// Make sure that the compression methods are still the same
|
// Make sure that the compression methods are still the same
|
||||||
for (Map.Entry<String, String> controlEntry : controlFiles.entrySet()) {
|
for (Map.Entry<String, String> controlEntry : controlFiles.entrySet()) {
|
||||||
assertTrue(controlEntry.getValue().equals(testFiles.get(controlEntry.getKey())));
|
assertEquals(controlEntry.getValue(), testFiles.get(controlEntry.getKey()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ public class DoubleExtensionUnknownFileTest extends BaseTest {
|
|||||||
apkDecoder.decode();
|
apkDecoder.decode();
|
||||||
|
|
||||||
MetaInfo metaInfo = new Androlib().readMetaFile(decodedApk);
|
MetaInfo metaInfo = new Androlib().readMetaFile(decodedApk);
|
||||||
for (String string : metaInfo.doNotCompress) {
|
for (String string : metaInfo.noCompressAssets) {
|
||||||
if (StringUtils.countMatches(string, ".") > 1) {
|
if (StringUtils.countMatches(string, ".") > 1) {
|
||||||
assertTrue(string.equalsIgnoreCase("assets/bin/Data/sharedassets1.assets.split0"));
|
assertTrue(string.equalsIgnoreCase("assets/bin/Data/sharedassets1.assets.split0"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user