Skip to content

Commit

Permalink
refactor Apkecoder - streamline decode procedure (#3109)
Browse files Browse the repository at this point in the history
  • Loading branch information
sv99 committed Jun 28, 2023
1 parent 1e400aa commit 5cd94d6
Showing 1 changed file with 60 additions and 83 deletions.
143 changes: 60 additions & 83 deletions brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class ApkDecoder {
private final static String SMALI_DIRNAME = "smali";
private final static String UNK_DIRNAME = "unknown";
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[] {
"AndroidManifest.xml" };
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {
Expand Down Expand Up @@ -101,46 +101,17 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory

LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName());

if (hasResources()) {
switch (config.decodeResources) {
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);
}
}
}
decodeManifest(outDir);
decodeResources(outDir);

if (hasSources()) {
switch (config.decodeSources) {
case Config.DECODE_SOURCES_NONE:
copySourcesRaw(mApkFile, outDir, "classes.dex");
copySourcesRaw(outDir, "classes.dex");
break;
case Config.DECODE_SOURCES_SMALI:
case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES:
decodeSourcesSmali(mApkFile, outDir, "classes.dex");
decodeSourcesSmali(outDir, "classes.dex");
break;
}
}
Expand All @@ -153,16 +124,16 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
if (! file.equalsIgnoreCase("classes.dex")) {
switch(config.decodeSources) {
case Config.DECODE_SOURCES_NONE:
copySourcesRaw(mApkFile, outDir, file);
copySourcesRaw(outDir, file);
break;
case Config.DECODE_SOURCES_SMALI:
decodeSourcesSmali(mApkFile, outDir, file);
decodeSourcesSmali(outDir, file);
break;
case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES:
if (file.startsWith("classes") && file.endsWith(".dex")) {
decodeSourcesSmali(mApkFile, outDir, file);
decodeSourcesSmali(outDir, file);
} else {
copySourcesRaw(mApkFile, outDir, file);
copySourcesRaw(outDir, file);
}
break;
}
Expand All @@ -171,11 +142,11 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
}
}

copyRawFiles(mApkFile, outDir);
copyUnknownFiles(mApkFile, outDir);
copyRawFiles(outDir);
copyUnknownFiles(outDir);
mUncompressedFiles = new ArrayList<>();
recordUncompressedFiles(mApkFile, mUncompressedFiles);
copyOriginalFiles(mApkFile, outDir);
recordUncompressedFiles(mUncompressedFiles);
copyOriginalFiles(outDir);
writeMetaFile(outDir);
} finally {
try {
Expand Down Expand Up @@ -276,17 +247,17 @@ private Map<String, String> getMinSdkInfo() {
return sdkInfo;
}

private void copySourcesRaw(ExtFile apkFile, File outDir, String filename)
private void copySourcesRaw(File outDir, String filename)
throws AndrolibException {
try {
LOGGER.info("Copying raw " + filename + " file...");
apkFile.getDirectory().copyToDir(outDir, filename);
mApkFile.getDirectory().copyToDir(outDir, filename);
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
}
}

private void decodeSourcesSmali(File apkFile, File outDir, String filename)
private void decodeSourcesSmali(File outDir, String filename)
throws AndrolibException {
try {
File smaliDir;
Expand All @@ -299,7 +270,7 @@ private void decodeSourcesSmali(File apkFile, File outDir, String filename)
//noinspection ResultOfMethodCallIgnored
smaliDir.mkdirs();
LOGGER.info("Baksmaling " + filename + "...");
DexFile dexFile = SmaliDecoder.decode(apkFile, smaliDir, filename,
DexFile dexFile = SmaliDecoder.decode(mApkFile, smaliDir, filename,
config.baksmaliDebugMode, config.apiLevel);
int minSdkVersion = dexFile.getOpcodes().api;
if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) {
Expand All @@ -310,46 +281,52 @@ private void decodeSourcesSmali(File apkFile, File outDir, String filename)
}
}

private void copyManifestRaw(ExtFile apkFile, File outDir)
throws AndrolibException {
try {
LOGGER.info("Copying raw manifest...");
apkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
private void decodeManifest(File outDir) throws AndrolibException {
if (hasManifest()) {
if (config.decodeResources == Config.DECODE_RESOURCES_FULL ||
config.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
if (hasResources()) {
mAndRes.decodeManifestWithResources(getResTable(), mApkFile, outDir);
} 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)
throws AndrolibException {
mAndRes.decodeManifest(resTable, apkFile, outDir);
}

private void copyResourcesRaw(ExtFile apkFile, File outDir)
throws AndrolibException {
try {
LOGGER.info("Copying raw resources...");
apkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
private void decodeResources(File outDir) throws AndrolibException {
if (hasResources()) {
switch (config.decodeResources) {
case Config.DECODE_RESOURCES_NONE:
try {
LOGGER.info("Copying raw resources...");
mApkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
}
break;
case Config.DECODE_RESOURCES_FULL:
mAndRes.decode(getResTable(), mApkFile, outDir);
break;
}
}
}

private void decodeResourcesFull(ExtFile apkFile, File outDir, ResTable resTable)
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)
private void copyRawFiles(File outDir)
throws AndrolibException {
LOGGER.info("Copying assets and libs...");
try {
Directory in = apkFile.getDirectory();
Directory in = mApkFile.getDirectory();

if (config.decodeAssets == Config.DECODE_ASSETS_FULL) {
if (in.containsDir("assets")) {
Expand Down Expand Up @@ -379,12 +356,12 @@ private boolean isAPKFileNames(String file) {
return false;
}

private void copyUnknownFiles(ExtFile apkFile, File outDir)
private void copyUnknownFiles(File outDir)
throws AndrolibException {
LOGGER.info("Copying unknown files...");
File unknownOut = new File(outDir, UNK_DIRNAME);
try {
Directory unk = apkFile.getDirectory();
Directory unk = mApkFile.getDirectory();

// loop all items in container recursively, ignoring any that are pre-defined by aapt
Set<String> files = unk.getFiles(true);
Expand All @@ -403,7 +380,7 @@ private void copyUnknownFiles(ExtFile apkFile, File outDir)
}
}

private void copyOriginalFiles(ExtFile apkFile, File outDir)
private void copyOriginalFiles(File outDir)
throws AndrolibException {
LOGGER.info("Copying original files...");
File originalDir = new File(outDir, "original");
Expand All @@ -413,7 +390,7 @@ private void copyOriginalFiles(ExtFile apkFile, File outDir)
}

try {
Directory in = apkFile.getDirectory();
Directory in = mApkFile.getDirectory();
if (in.containsFile("AndroidManifest.xml")) {
in.copyToDir(originalDir, "AndroidManifest.xml");
}
Expand All @@ -436,9 +413,9 @@ private void copyOriginalFiles(ExtFile apkFile, File outDir)
}
}

private void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFilesOrExts) throws AndrolibException {
private void recordUncompressedFiles(Collection<String> uncompressedFilesOrExts) throws AndrolibException {
try {
Directory unk = apkFile.getDirectory();
Directory unk = mApkFile.getDirectory();
Set<String> files = unk.getFiles(true);

for (String file : files) {
Expand Down

0 comments on commit 5cd94d6

Please sign in to comment.