refactor Apkecoder - streamline decode procedure (#3109)

This commit is contained in:
sv99 2023-06-29 00:02:46 +03:00 committed by GitHub
parent 1e400aa995
commit 5cd94d6aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -53,7 +53,7 @@ public class ApkDecoder {
private final static String SMALI_DIRNAME = "smali"; private final static String SMALI_DIRNAME = "smali";
private final static String UNK_DIRNAME = "unknown"; private final static String UNK_DIRNAME = "unknown";
private final static String[] APK_RESOURCES_FILENAMES = new String[] { private final static String[] APK_RESOURCES_FILENAMES = new String[] {
"resources.arsc", "AndroidManifest.xml", "res", "r", "R" }; "resources.arsc", "res", "r", "R" };
private final static String[] APK_MANIFEST_FILENAMES = new String[] { private final static String[] APK_MANIFEST_FILENAMES = new String[] {
"AndroidManifest.xml" }; "AndroidManifest.xml" };
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] { private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {
@ -101,46 +101,17 @@ public class ApkDecoder {
LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName()); LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName());
if (hasResources()) { decodeManifest(outDir);
switch (config.decodeResources) { decodeResources(outDir);
case Config.DECODE_RESOURCES_NONE:
copyResourcesRaw(mApkFile, outDir);
if (config.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
// done after raw decoding of resources because copyToDir overwrites dest files
if (hasManifest()) {
decodeManifestWithResources(mApkFile, outDir, getResTable());
}
}
break;
case Config.DECODE_RESOURCES_FULL:
if (hasManifest()) {
decodeManifestWithResources(mApkFile, outDir, getResTable());
}
decodeResourcesFull(mApkFile, outDir, getResTable());
break;
}
} else {
// if there's no resources.arsc, decode the manifest without looking
// up attribute references
if (hasManifest()) {
if (config.decodeResources == Config.DECODE_RESOURCES_FULL
|| config.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
decodeManifestFull(mApkFile, outDir, getResTable());
}
else {
copyManifestRaw(mApkFile, outDir);
}
}
}
if (hasSources()) { if (hasSources()) {
switch (config.decodeSources) { switch (config.decodeSources) {
case Config.DECODE_SOURCES_NONE: case Config.DECODE_SOURCES_NONE:
copySourcesRaw(mApkFile, outDir, "classes.dex"); copySourcesRaw(outDir, "classes.dex");
break; break;
case Config.DECODE_SOURCES_SMALI: case Config.DECODE_SOURCES_SMALI:
case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES:
decodeSourcesSmali(mApkFile, outDir, "classes.dex"); decodeSourcesSmali(outDir, "classes.dex");
break; break;
} }
} }
@ -153,16 +124,16 @@ public class ApkDecoder {
if (! file.equalsIgnoreCase("classes.dex")) { if (! file.equalsIgnoreCase("classes.dex")) {
switch(config.decodeSources) { switch(config.decodeSources) {
case Config.DECODE_SOURCES_NONE: case Config.DECODE_SOURCES_NONE:
copySourcesRaw(mApkFile, outDir, file); copySourcesRaw(outDir, file);
break; break;
case Config.DECODE_SOURCES_SMALI: case Config.DECODE_SOURCES_SMALI:
decodeSourcesSmali(mApkFile, outDir, file); decodeSourcesSmali(outDir, file);
break; break;
case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES: case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES:
if (file.startsWith("classes") && file.endsWith(".dex")) { if (file.startsWith("classes") && file.endsWith(".dex")) {
decodeSourcesSmali(mApkFile, outDir, file); decodeSourcesSmali(outDir, file);
} else { } else {
copySourcesRaw(mApkFile, outDir, file); copySourcesRaw(outDir, file);
} }
break; break;
} }
@ -171,11 +142,11 @@ public class ApkDecoder {
} }
} }
copyRawFiles(mApkFile, outDir); copyRawFiles(outDir);
copyUnknownFiles(mApkFile, outDir); copyUnknownFiles(outDir);
mUncompressedFiles = new ArrayList<>(); mUncompressedFiles = new ArrayList<>();
recordUncompressedFiles(mApkFile, mUncompressedFiles); recordUncompressedFiles(mUncompressedFiles);
copyOriginalFiles(mApkFile, outDir); copyOriginalFiles(outDir);
writeMetaFile(outDir); writeMetaFile(outDir);
} finally { } finally {
try { try {
@ -276,17 +247,17 @@ public class ApkDecoder {
return sdkInfo; return sdkInfo;
} }
private void copySourcesRaw(ExtFile apkFile, File outDir, String filename) private void copySourcesRaw(File outDir, String filename)
throws AndrolibException { throws AndrolibException {
try { try {
LOGGER.info("Copying raw " + filename + " file..."); LOGGER.info("Copying raw " + filename + " file...");
apkFile.getDirectory().copyToDir(outDir, filename); mApkFile.getDirectory().copyToDir(outDir, filename);
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);
} }
} }
private void decodeSourcesSmali(File apkFile, File outDir, String filename) private void decodeSourcesSmali(File outDir, String filename)
throws AndrolibException { throws AndrolibException {
try { try {
File smaliDir; File smaliDir;
@ -299,7 +270,7 @@ public class ApkDecoder {
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
smaliDir.mkdirs(); smaliDir.mkdirs();
LOGGER.info("Baksmaling " + filename + "..."); LOGGER.info("Baksmaling " + filename + "...");
DexFile dexFile = SmaliDecoder.decode(apkFile, smaliDir, filename, DexFile dexFile = SmaliDecoder.decode(mApkFile, smaliDir, filename,
config.baksmaliDebugMode, config.apiLevel); config.baksmaliDebugMode, config.apiLevel);
int minSdkVersion = dexFile.getOpcodes().api; int minSdkVersion = dexFile.getOpcodes().api;
if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) { if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) {
@ -310,46 +281,52 @@ public class ApkDecoder {
} }
} }
private void copyManifestRaw(ExtFile apkFile, File outDir) private void decodeManifest(File outDir) throws AndrolibException {
throws AndrolibException { if (hasManifest()) {
try { if (config.decodeResources == Config.DECODE_RESOURCES_FULL ||
LOGGER.info("Copying raw manifest..."); config.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
apkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES); if (hasResources()) {
} catch (DirectoryException ex) { mAndRes.decodeManifestWithResources(getResTable(), mApkFile, outDir);
throw new AndrolibException(ex); } else {
// if there's no resources.arsc, decode the manifest without looking
// up attribute references
mAndRes.decodeManifest(getResTable(), mApkFile, outDir);
}
}
else {
try {
LOGGER.info("Copying raw manifest...");
mApkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
}
}
} }
} }
private void decodeManifestFull(ExtFile apkFile, File outDir, ResTable resTable) private void decodeResources(File outDir) throws AndrolibException {
throws AndrolibException { if (hasResources()) {
mAndRes.decodeManifest(resTable, apkFile, outDir); switch (config.decodeResources) {
} case Config.DECODE_RESOURCES_NONE:
try {
private void copyResourcesRaw(ExtFile apkFile, File outDir) LOGGER.info("Copying raw resources...");
throws AndrolibException { mApkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
try { } catch (DirectoryException ex) {
LOGGER.info("Copying raw resources..."); throw new AndrolibException(ex);
apkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES); }
} catch (DirectoryException ex) { break;
throw new AndrolibException(ex); case Config.DECODE_RESOURCES_FULL:
mAndRes.decode(getResTable(), mApkFile, outDir);
break;
}
} }
} }
private void decodeResourcesFull(ExtFile apkFile, File outDir, ResTable resTable) private void copyRawFiles(File outDir)
throws AndrolibException {
mAndRes.decode(resTable, apkFile, outDir);
}
private void decodeManifestWithResources(ExtFile apkFile, File outDir, ResTable resTable)
throws AndrolibException {
mAndRes.decodeManifestWithResources(resTable, apkFile, outDir);
}
private void copyRawFiles(ExtFile apkFile, File outDir)
throws AndrolibException { throws AndrolibException {
LOGGER.info("Copying assets and libs..."); LOGGER.info("Copying assets and libs...");
try { try {
Directory in = apkFile.getDirectory(); Directory in = mApkFile.getDirectory();
if (config.decodeAssets == Config.DECODE_ASSETS_FULL) { if (config.decodeAssets == Config.DECODE_ASSETS_FULL) {
if (in.containsDir("assets")) { if (in.containsDir("assets")) {
@ -379,12 +356,12 @@ public class ApkDecoder {
return false; return false;
} }
private void copyUnknownFiles(ExtFile apkFile, File outDir) private void copyUnknownFiles(File outDir)
throws AndrolibException { throws AndrolibException {
LOGGER.info("Copying unknown files..."); LOGGER.info("Copying unknown files...");
File unknownOut = new File(outDir, UNK_DIRNAME); File unknownOut = new File(outDir, UNK_DIRNAME);
try { try {
Directory unk = apkFile.getDirectory(); Directory unk = mApkFile.getDirectory();
// loop all items in container recursively, ignoring any that are pre-defined by aapt // loop all items in container recursively, ignoring any that are pre-defined by aapt
Set<String> files = unk.getFiles(true); Set<String> files = unk.getFiles(true);
@ -403,7 +380,7 @@ public class ApkDecoder {
} }
} }
private void copyOriginalFiles(ExtFile apkFile, File outDir) private void copyOriginalFiles(File outDir)
throws AndrolibException { throws AndrolibException {
LOGGER.info("Copying original files..."); LOGGER.info("Copying original files...");
File originalDir = new File(outDir, "original"); File originalDir = new File(outDir, "original");
@ -413,7 +390,7 @@ public class ApkDecoder {
} }
try { try {
Directory in = apkFile.getDirectory(); Directory in = mApkFile.getDirectory();
if (in.containsFile("AndroidManifest.xml")) { if (in.containsFile("AndroidManifest.xml")) {
in.copyToDir(originalDir, "AndroidManifest.xml"); in.copyToDir(originalDir, "AndroidManifest.xml");
} }
@ -436,9 +413,9 @@ public class ApkDecoder {
} }
} }
private void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFilesOrExts) throws AndrolibException { private void recordUncompressedFiles(Collection<String> uncompressedFilesOrExts) throws AndrolibException {
try { try {
Directory unk = apkFile.getDirectory(); Directory unk = mApkFile.getDirectory();
Set<String> files = unk.getFiles(true); Set<String> files = unk.getFiles(true);
for (String file : files) { for (String file : files) {