Skip to content

Commit

Permalink
Fix raw decoding error for apk without resources
Browse files Browse the repository at this point in the history
  • Loading branch information
REAndroid committed Apr 11, 2024
1 parent 3bcb302 commit 8b7788e
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 69 deletions.
16 changes: 6 additions & 10 deletions src/main/java/com/reandroid/apk/ApkModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import com.reandroid.archive.writer.ApkStreamWriter;
import com.reandroid.arsc.ApkFile;
import com.reandroid.arsc.array.PackageArray;
import com.reandroid.arsc.base.Block;
import com.reandroid.arsc.chunk.Chunk;
import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.chunk.TableBlock;
import com.reandroid.arsc.chunk.TypeBlock;
Expand Down Expand Up @@ -351,7 +349,7 @@ private Integer safeParseInteger(String versionString) {
}
}

public void setPreferredFramework(Integer version) throws IOException {
public void setPreferredFramework(Integer version) {
if(version != null && version.equals(preferredFramework)){
return;
}
Expand Down Expand Up @@ -719,6 +717,7 @@ public void setManifest(AndroidManifestBlock manifestBlock){
ZipEntryMap archive = getZipEntryMap();
if(manifestBlock==null){
mManifestBlock = null;
mManifestOriginalSource = null;
archive.remove(AndroidManifestBlock.FILE_NAME);
return;
}
Expand All @@ -734,6 +733,7 @@ public void setTableBlock(TableBlock tableBlock){
ZipEntryMap archive = getZipEntryMap();
if(tableBlock == null){
mTableBlock = null;
mTableOriginalSource = null;
archive.remove(TableBlock.FILE_NAME);
return;
}
Expand Down Expand Up @@ -964,15 +964,11 @@ public TableStringPool getVolatileTableStringPool() throws IOException{
}
TableBlock loadTableBlock() throws IOException {
InputSource inputSource = getInputSource(TableBlock.FILE_NAME);
if(inputSource==null){
if(inputSource == null){
throw new IOException("Entry not found: "+TableBlock.FILE_NAME);
}
TableBlock tableBlock;
if(inputSource instanceof SplitJsonTableInputSource){
tableBlock=((SplitJsonTableInputSource)inputSource).getTableBlock();
}else if(inputSource instanceof SingleJsonTableInputSource){
tableBlock=((SingleJsonTableInputSource)inputSource).getTableBlock();
}else if(inputSource instanceof BlockInputSource){
if(inputSource instanceof BlockInputSource){
tableBlock = (TableBlock) ((BlockInputSource<?>) inputSource).getBlock();
}else {
setTableOriginalSource(inputSource);
Expand All @@ -983,7 +979,7 @@ TableBlock loadTableBlock() throws IOException {
BlockInputSource<TableBlock> blockInputSource=new BlockInputSource<>(inputSource.getName(), tableBlock);
blockInputSource.setMethod(inputSource.getMethod());
blockInputSource.setSort(inputSource.getSort());
zipEntryMap.add(blockInputSource);
getZipEntryMap().add(blockInputSource);
tableBlock.setApkFile(this);
return tableBlock;
}
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/com/reandroid/apk/ApkModuleEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public void scanDirectory(File mainDirectory) throws IOException{
sortFiles();
refreshTable();
dropEmptyManifest();
droNullTableBlock();
dropNullTableBlock();
onScanDirectoryComplete();
}
public void encodeBinaryManifest(File mainDirectory){
File file = new File(mainDirectory, AndroidManifestBlock.FILE_NAME_BIN);
Expand All @@ -65,6 +66,8 @@ public void encodeBinaryManifest(File mainDirectory){
public abstract ApkModule getApkModule();


void onScanDirectoryComplete(){
}
void refreshTable(){
logMessage("Refreshing resource table ...");
getApkModule().refreshTable();
Expand All @@ -83,15 +86,21 @@ private void dropEmptyManifest(){
logMessage("Removed empty: " + AndroidManifest.FILE_NAME);
}
}
private void droNullTableBlock(){
private void dropNullTableBlock(){
ApkModule apkModule = getApkModule();
if(!apkModule.hasTableBlock()){
return;
}
TableBlock tableBlock = apkModule.getTableBlock();
TableBlock loadedTableBlock = apkModule.getLoadedTableBlock();
TableBlock tableBlock = loadedTableBlock;
if(tableBlock == null){
tableBlock = apkModule.getTableBlock(false);
}
if(tableBlock.isEmpty() && tableBlock.isNull()){
apkModule.setTableBlock(null);
logMessage("Removed null: " + TableBlock.FILE_NAME);
logMessage("Removed empty: " + TableBlock.FILE_NAME);
}else if(loadedTableBlock == null){
apkModule.discardTableBlockChanges();
}
}
private void sortFiles(){
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/reandroid/apk/ApkModuleJsonEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
import java.io.IOException;
import java.util.List;

public class ApkModuleJsonEncoder extends ApkModuleEncoder{
public class ApkModuleJsonEncoder extends ApkModuleEncoder {

private ApkModule apkModule;
public ApkModuleJsonEncoder(){
super();
Expand Down Expand Up @@ -89,7 +90,6 @@ private boolean scanTableSplitJson(File mainDirectory) {
return false;
}
SplitJsonTableInputSource inputSource = new SplitJsonTableInputSource(resourcesDir);
inputSource.setApkLogger(getApkLogger());
getApkModule().add(inputSource);
return true;
}
Expand All @@ -101,7 +101,6 @@ private boolean scanTableSingleJson(File mainDirectory) {
}
SingleJsonTableInputSource inputSource = SingleJsonTableInputSource
.fromFile(resourcesDir, file);
inputSource.setApkLogger(getApkLogger());
getApkModule().add(inputSource);
return true;
}
Expand Down
36 changes: 32 additions & 4 deletions src/main/java/com/reandroid/apk/ApkModuleRawEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,23 @@
import java.io.File;

public class ApkModuleRawEncoder extends ApkModuleEncoder {

private final ApkModule apkModule;
private boolean mKeepOriginal;

public ApkModuleRawEncoder(){
ZipEntryMap zipEntryMap = new ZipEntryMap();
String name = "encoded_raw" + String.valueOf(zipEntryMap.hashCode()).substring(1);
this.apkModule = new ApkModule(name, zipEntryMap);
}

public void setKeepOriginal(boolean keepOriginal) {
this.mKeepOriginal = keepOriginal;
}
public boolean isKeepOriginal() {
return mKeepOriginal;
}

@Override
public void buildResources(File mainDirectory) {
addTableBlock(mainDirectory);
Expand All @@ -44,27 +55,44 @@ public void encodeBinaryManifest(File mainDirectory){
if(!file.isFile()){
file = new File(mainDirectory, AndroidManifestBlock.FILE_NAME);
if(!file.isFile() || !AndroidManifestBlock.isResXmlBlock(file)){
logMessage("Warn: File not found: " + AndroidManifestBlock.FILE_NAME_BIN);
logMessage("WARN: Missing file " + AndroidManifestBlock.FILE_NAME_BIN);
return;
}
}
logMessage("Loaded binary manifest: " + file.getName());
FileInputSource inputSource = new FileInputSource(file, AndroidManifestBlock.FILE_NAME);
getApkModule().add(inputSource);
ApkModule apkModule = getApkModule();
apkModule.add(inputSource);
if(isKeepOriginal()){
apkModule.discardManifestChanges();
}
}
private void addTableBlock(File mainDirectory){
File file = new File(mainDirectory, TableBlock.FILE_NAME);
if(!file.isFile()){
logMessage("Warn: File not found: " + TableBlock.FILE_NAME);
return;
}
getApkModule().setLoadDefaultFramework(false);
InputSource inputSource = new FileInputSource(file, TableBlock.FILE_NAME);
getApkModule().add(inputSource);
ApkModule apkModule = getApkModule();
apkModule.add(inputSource);
if(isKeepOriginal()){
apkModule.discardManifestChanges();
}
}
@Override
void refreshTable(){
if(getApkModule().getLoadedTableBlock() != null){
if(!isKeepOriginal() && getApkModule().getLoadedTableBlock() != null){
super.refreshTable();
}
}
@Override
void onScanDirectoryComplete() {
if(isKeepOriginal()){
ApkModule apkModule = getApkModule();
apkModule.discardTableBlockChanges();
apkModule.discardManifestChanges();
}
}
}
41 changes: 15 additions & 26 deletions src/main/java/com/reandroid/apk/SingleJsonTableInputSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.reandroid.apk;

import com.reandroid.archive.BlockInputSource;
import com.reandroid.archive.FileInputSource;
import com.reandroid.archive.InputSource;
import com.reandroid.arsc.chunk.TableBlock;
Expand All @@ -23,14 +24,24 @@

import java.io.*;

public class SingleJsonTableInputSource extends InputSource {
public class SingleJsonTableInputSource extends BlockInputSource<TableBlock> {

private final InputSource inputSource;
private TableBlock mCache;
private APKLogger apkLogger;

public SingleJsonTableInputSource(InputSource inputSource) {
super(TableBlock.FILE_NAME);
super(TableBlock.FILE_NAME, null);
this.inputSource = inputSource;
}

@Override
public TableBlock getBlock() {
try {
return getTableBlock();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
@Override
public long write(OutputStream outputStream) throws IOException {
return getTableBlock().writeBytes(outputStream);
Expand All @@ -55,8 +66,7 @@ public TableBlock getTableBlock() throws IOException{
if(mCache != null){
return mCache;
}
logMessage("Building resources table: " + inputSource.getAlias());
TableBlock tableBlock=newInstance();
TableBlock tableBlock = new TableBlock();
InputStream inputStream = inputSource.openStream();
try{
JsonStringPoolBuilder poolBuilder = new JsonStringPoolBuilder();
Expand All @@ -70,30 +80,9 @@ public TableBlock getTableBlock() throws IOException{
mCache = tableBlock;
return tableBlock;
}
TableBlock newInstance(){
return new TableBlock();
}
public static SingleJsonTableInputSource fromFile(File rootDir, File jsonFile){
String path = ApkUtil.jsonToArchiveResourcePath(rootDir, jsonFile);
FileInputSource fileInputSource = new FileInputSource(jsonFile, path);
return new SingleJsonTableInputSource(fileInputSource);
}
void setApkLogger(APKLogger logger) {
this.apkLogger = logger;
}
private void logMessage(String msg) {
if(apkLogger!=null){
apkLogger.logMessage(msg);
}
}
private void logError(String msg, Throwable tr) {
if(apkLogger!=null){
apkLogger.logError(msg, tr);
}
}
private void logVerbose(String msg) {
if(apkLogger!=null){
apkLogger.logVerbose(msg);
}
}
}
36 changes: 14 additions & 22 deletions src/main/java/com/reandroid/apk/SplitJsonTableInputSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,29 @@
*/
package com.reandroid.apk;

import com.reandroid.archive.InputSource;
import com.reandroid.archive.BlockInputSource;
import com.reandroid.arsc.chunk.TableBlock;

import java.io.*;

public class SplitJsonTableInputSource extends InputSource {
public class SplitJsonTableInputSource extends BlockInputSource<TableBlock> {
private final File resourcesDirectory;
private TableBlock mCache;
private APKLogger apkLogger;

public SplitJsonTableInputSource(File resourcesDirectory) {
super(TableBlock.FILE_NAME);
super(TableBlock.FILE_NAME, null);
this.resourcesDirectory =resourcesDirectory;
}

@Override
public TableBlock getBlock() {
try {
return getTableBlock();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}

@Override
public long write(OutputStream outputStream) throws IOException {
return getTableBlock().writeBytes(outputStream);
Expand Down Expand Up @@ -57,22 +67,4 @@ public TableBlock getTableBlock() throws IOException {
mCache = tableBlock;
return tableBlock;
}
public void setApkLogger(APKLogger logger) {
this.apkLogger = logger;
}
void logMessage(String msg) {
if(apkLogger!=null){
apkLogger.logMessage(msg);
}
}
private void logError(String msg, Throwable tr) {
if(apkLogger!=null){
apkLogger.logError(msg, tr);
}
}
private void logVerbose(String msg) {
if(apkLogger!=null){
apkLogger.logVerbose(msg);
}
}
}

0 comments on commit 8b7788e

Please sign in to comment.