Remove JNI; use native Java zipadjust
This commit is contained in:
parent
f37f330670
commit
19af5f9e0b
@ -10,10 +10,6 @@ android {
|
||||
targetSdkVersion 27
|
||||
versionCode 91
|
||||
versionName "5.5.5"
|
||||
ndk {
|
||||
moduleName 'zipadjust'
|
||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
}
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
argument('butterknife.debuggable', 'false')
|
||||
@ -36,11 +32,6 @@ android {
|
||||
preDexLibraries true
|
||||
javaMaxHeapSize "2g"
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path 'src/main/jni/CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ public class FlashActivity extends Activity {
|
||||
reboot.setVisibility(View.GONE);
|
||||
|
||||
logs = new ArrayList<>();
|
||||
CallbackList console = new CallbackList<String>(new ArrayList<>()) {
|
||||
CallbackList<String> console = new CallbackList<String>(new ArrayList<>()) {
|
||||
@Override
|
||||
public void onAddElement(String s) {
|
||||
logs.add(s);
|
||||
|
@ -123,7 +123,7 @@ public class HideManager extends ParallelTask<Void, Void, Boolean> {
|
||||
apk.getOutputStream(je).write(xml);
|
||||
|
||||
// Sign the APK
|
||||
ZipUtils.signZip(apk, repack, false);
|
||||
ZipUtils.signZip(apk, repack);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
|
@ -120,14 +120,8 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
|
||||
// First remove top folder in Github source zip, temp1 -> temp2
|
||||
removeTopFolder(temp1, temp2);
|
||||
|
||||
// Then sign the zip for the first time, temp2 -> temp1
|
||||
ZipUtils.signZip(temp2, temp1, false);
|
||||
|
||||
// Adjust the zip to prevent unzip issues, temp1 -> temp2
|
||||
ZipUtils.zipAdjust(temp1.getPath(), temp2.getPath());
|
||||
|
||||
// Finally, sign the whole zip file again, temp2 -> target
|
||||
ZipUtils.signZip(temp2, mFile, true);
|
||||
// Then sign the zip
|
||||
ZipUtils.signZip(temp2, mFile);
|
||||
|
||||
// Delete temp files
|
||||
temp1.delete();
|
||||
|
@ -1,10 +1,7 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import com.topjohnwu.crypto.JarMap;
|
||||
import com.topjohnwu.crypto.SignAPK;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -18,12 +15,6 @@ import java.util.zip.ZipInputStream;
|
||||
|
||||
public class ZipUtils {
|
||||
|
||||
static {
|
||||
System.loadLibrary("zipadjust");
|
||||
}
|
||||
|
||||
public native static void zipAdjust(String filenameIn, String filenameOut);
|
||||
|
||||
public static void unzip(File zip, File folder, String path, boolean junkPath) throws Exception {
|
||||
InputStream in = new BufferedInputStream(new FileInputStream(zip));
|
||||
unzip(in, folder, path, junkPath);
|
||||
@ -57,25 +48,25 @@ public class ZipUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void signZip(InputStream is, File output, boolean minSign) throws Exception {
|
||||
public static void signZip(InputStream is, File output) throws Exception {
|
||||
try (JarMap map = new JarMap(is, false)) {
|
||||
signZip(map, output, minSign);
|
||||
signZip(map, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void signZip(File input, File output, boolean minSign) throws Exception {
|
||||
public static void signZip(File input, File output) throws Exception {
|
||||
try (JarMap map = new JarMap(input, false)) {
|
||||
signZip(map, output, minSign);
|
||||
signZip(map, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void signZip(JarMap input, File output, boolean minSign) throws Exception {
|
||||
public static void signZip(JarMap input, File output) throws Exception {
|
||||
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(output))) {
|
||||
signZip(input, out, minSign);
|
||||
signZip(input, out);
|
||||
}
|
||||
}
|
||||
|
||||
public static void signZip(JarMap input, OutputStream output, boolean minSign) throws Exception {
|
||||
SignAPK.signZip(null, null, input, output, minSign);
|
||||
public static void signZip(JarMap input, OutputStream output) throws Exception {
|
||||
SignAPK.signZip(null, null, input, output);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
add_library(zipadjust SHARED
|
||||
jni_glue.c
|
||||
zipadjust.c)
|
||||
find_library(libz z)
|
||||
find_library(liblog log)
|
||||
target_link_libraries(zipadjust ${libz} ${liblog})
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// Java entry point
|
||||
//
|
||||
|
||||
#include <jni.h>
|
||||
#include "zipadjust.h"
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_topjohnwu_magisk_utils_ZipUtils_zipAdjust(JNIEnv *env, jclass type, jstring filenameIn_,
|
||||
jstring filenameOut_) {
|
||||
const char *filenameIn = (*env)->GetStringUTFChars(env, filenameIn_, 0);
|
||||
const char *filenameOut = (*env)->GetStringUTFChars(env, filenameOut_, 0);
|
||||
|
||||
// TODO
|
||||
zipadjust(filenameIn, filenameOut, 0);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, filenameIn_, filenameIn);
|
||||
(*env)->ReleaseStringUTFChars(env, filenameOut_, filenameOut);
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <unistd.h>
|
||||
#include "zipadjust.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
#endif
|
||||
|
||||
#pragma pack(1)
|
||||
struct local_header_struct {
|
||||
uint32_t signature;
|
||||
uint16_t extract_version;
|
||||
uint16_t flags;
|
||||
uint16_t compression_method;
|
||||
uint16_t last_modified_time;
|
||||
uint16_t last_modified_date;
|
||||
uint32_t crc32;
|
||||
uint32_t size_compressed;
|
||||
uint32_t size_uncompressed;
|
||||
uint16_t length_filename;
|
||||
uint16_t length_extra;
|
||||
// filename
|
||||
// extra
|
||||
};
|
||||
typedef struct local_header_struct local_header_t;
|
||||
|
||||
#pragma pack(1)
|
||||
struct data_descriptor_struct {
|
||||
uint32_t signature;
|
||||
uint32_t crc32;
|
||||
uint32_t size_compressed;
|
||||
uint32_t size_uncompressed;
|
||||
};
|
||||
typedef struct data_descriptor_struct data_descriptor_t;
|
||||
|
||||
#pragma pack(1)
|
||||
struct central_header_struct {
|
||||
uint32_t signature;
|
||||
uint16_t version_made;
|
||||
uint16_t version_needed;
|
||||
uint16_t flags;
|
||||
uint16_t compression_method;
|
||||
uint16_t last_modified_time;
|
||||
uint16_t last_modified_date;
|
||||
uint32_t crc32;
|
||||
uint32_t size_compressed;
|
||||
uint32_t size_uncompressed;
|
||||
uint16_t length_filename;
|
||||
uint16_t length_extra;
|
||||
uint16_t length_comment;
|
||||
uint16_t disk_start;
|
||||
uint16_t attr_internal;
|
||||
uint32_t attr_external;
|
||||
uint32_t offset;
|
||||
// filename
|
||||
// extra
|
||||
// comment
|
||||
};
|
||||
typedef struct central_header_struct central_header_t;
|
||||
|
||||
#pragma pack(1)
|
||||
struct central_footer_struct {
|
||||
uint32_t signature;
|
||||
uint16_t disk_number;
|
||||
uint16_t disk_number_central_directory;
|
||||
uint16_t central_directory_entries_this_disk;
|
||||
uint16_t central_directory_entries_total;
|
||||
uint32_t central_directory_size;
|
||||
uint32_t central_directory_offset;
|
||||
uint16_t length_comment;
|
||||
// comment
|
||||
};
|
||||
typedef struct central_footer_struct central_footer_t;
|
||||
|
||||
#define MAGIC_LOCAL_HEADER 0x04034b50
|
||||
#define MAGIC_DATA_DESCRIPTOR 0x08074b50
|
||||
#define MAGIC_CENTRAL_HEADER 0x02014b50
|
||||
#define MAGIC_CENTRAL_FOOTER 0x06054b50
|
||||
|
||||
static int xerror(char* message) {
|
||||
LOGE("%s\n", message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xseekread(int fd, off_t offset, void* buf, size_t bytes) {
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return xerror("Seek failed");
|
||||
if (read(fd, buf, bytes) != bytes) return xerror("Read failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xseekwrite(int fd, off_t offset, void* buf, size_t bytes) {
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return xerror("Seek failed");
|
||||
if (write(fd, buf, bytes) != bytes) return xerror("Write failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xfilecopy(int fdIn, int fdOut, off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
if ((offsetIn != (off_t)-1) && (lseek(fdIn, offsetIn, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
if ((offsetOut != (off_t)-1) && (lseek(fdOut, offsetOut, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
|
||||
int CHUNK = 256 * 1024;
|
||||
void* buf = malloc(CHUNK);
|
||||
if (buf == NULL) return xerror("malloc failed");
|
||||
size_t left = bytes;
|
||||
while (left > 0) {
|
||||
size_t wanted = (left < CHUNK) ? left : CHUNK;
|
||||
size_t r = read(fdIn, buf, wanted);
|
||||
if (r <= 0) return xerror("Read failed");
|
||||
if (write(fdOut, buf, r) != r) return xerror("Write failed");
|
||||
left -= r;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xdecompress(int fdIn, int fdOut, off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
if ((offsetIn != (off_t)-1) && (lseek(fdIn, offsetIn, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
if ((offsetOut != (off_t)-1) && (lseek(fdOut, offsetOut, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
|
||||
int CHUNK = 256 * 1024;
|
||||
|
||||
int ret;
|
||||
unsigned have;
|
||||
z_stream strm;
|
||||
unsigned char in[CHUNK];
|
||||
unsigned char out[CHUNK];
|
||||
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
ret = inflateInit2(&strm, -15);
|
||||
if (ret != Z_OK) return xerror("ret != Z_OK");
|
||||
|
||||
do {
|
||||
strm.avail_in = read(fdIn, in, CHUNK);
|
||||
if (strm.avail_in == 0) break;
|
||||
strm.next_in = in;
|
||||
|
||||
do {
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = out;
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR) return xerror("Stream error");
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
ret = Z_DATA_ERROR;
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
(void)inflateEnd(&strm);
|
||||
return xerror("DICT/DATA/MEM error");
|
||||
}
|
||||
|
||||
have = CHUNK - strm.avail_out;
|
||||
if (write(fdOut, out, have) != have) {
|
||||
(void)inflateEnd(&strm);
|
||||
return xerror("Write failed");
|
||||
}
|
||||
} while (strm.avail_out == 0);
|
||||
} while (ret != Z_STREAM_END);
|
||||
(void)inflateEnd(&strm);
|
||||
|
||||
return ret == Z_STREAM_END ? 1 : 0;
|
||||
}
|
||||
|
||||
int zipadjust(const char* filenameIn, const char* filenameOut, int decompress) {
|
||||
int ok = 0;
|
||||
|
||||
int fin = open(filenameIn, O_RDONLY | O_BINARY);
|
||||
if (fin > 0) {
|
||||
unsigned int size = lseek(fin, 0, SEEK_END);
|
||||
lseek(fin, 0, SEEK_SET);
|
||||
LOGD("%d bytes\n", size);
|
||||
|
||||
char filename[1024];
|
||||
|
||||
central_footer_t central_footer;
|
||||
uint32_t central_directory_in_position = 0;
|
||||
uint32_t central_directory_in_size = 0;
|
||||
uint32_t central_directory_out_size = 0;
|
||||
|
||||
int i;
|
||||
for (i = size - 4; i >= 0; i--) {
|
||||
uint32_t magic = 0;
|
||||
if (!xseekread(fin, i, &magic, sizeof(uint32_t))) return 0;
|
||||
if (magic == MAGIC_CENTRAL_FOOTER) {
|
||||
LOGD("central footer @ %08X\n", i);
|
||||
if (!xseekread(fin, i, ¢ral_footer, sizeof(central_footer_t))) return 0;
|
||||
|
||||
central_header_t central_header;
|
||||
if (!xseekread(fin, central_footer.central_directory_offset, ¢ral_header, sizeof(central_header_t))) return 0;
|
||||
if ( central_header.signature == MAGIC_CENTRAL_HEADER ) {
|
||||
central_directory_in_position = central_footer.central_directory_offset;
|
||||
central_directory_in_size = size - central_footer.central_directory_offset;
|
||||
LOGD("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (central_directory_in_position == 0) return 0;
|
||||
|
||||
unsigned char* central_directory_in = (unsigned char*)malloc(central_directory_in_size);
|
||||
unsigned char* central_directory_out = (unsigned char*)malloc(central_directory_in_size);
|
||||
if (!xseekread(fin, central_directory_in_position, central_directory_in, central_directory_in_size)) return 0;
|
||||
memset(central_directory_out, 0, central_directory_in_size);
|
||||
|
||||
unlink(filenameOut);
|
||||
int fout = open(filenameOut, O_CREAT | O_WRONLY | O_BINARY, 0644);
|
||||
if (fout > 0) {
|
||||
|
||||
uintptr_t central_directory_in_index = 0;
|
||||
uintptr_t central_directory_out_index = 0;
|
||||
|
||||
central_header_t* central_header = NULL;
|
||||
|
||||
uint32_t out_index = 0;
|
||||
|
||||
while (1) {
|
||||
central_header = (central_header_t*)¢ral_directory_in[central_directory_in_index];
|
||||
if (central_header->signature != MAGIC_CENTRAL_HEADER) break;
|
||||
|
||||
filename[central_header->length_filename] = (char)0;
|
||||
memcpy(filename, ¢ral_directory_in[central_directory_in_index + sizeof(central_header_t)], central_header->length_filename);
|
||||
LOGD("%s (%d --> %d) [%08X] (%d)\n", filename, central_header->size_uncompressed, central_header->size_compressed, central_header->crc32, central_header->length_extra + central_header->length_comment);
|
||||
|
||||
local_header_t local_header;
|
||||
if (!xseekread(fin, central_header->offset, &local_header, sizeof(local_header_t))) return 0;
|
||||
|
||||
// save and update to next index before we clobber the data
|
||||
uint16_t compression_method_old = central_header->compression_method;
|
||||
uint32_t size_compressed_old = central_header->size_compressed;
|
||||
uint32_t offset_old = central_header->offset;
|
||||
uint32_t length_extra_old = central_header->length_extra;
|
||||
central_directory_in_index += sizeof(central_header_t) + central_header->length_filename + central_header->length_extra + central_header->length_comment;
|
||||
|
||||
// copying, rewriting, and correcting local and central headers so all the information matches, and no data descriptors are necessary
|
||||
central_header->offset = out_index;
|
||||
central_header->flags = central_header->flags & !8;
|
||||
if (decompress && (compression_method_old == 8)) {
|
||||
central_header->compression_method = 0;
|
||||
central_header->size_compressed = central_header->size_uncompressed;
|
||||
}
|
||||
central_header->length_extra = 0;
|
||||
central_header->length_comment = 0;
|
||||
local_header.compression_method = central_header->compression_method;
|
||||
local_header.flags = central_header->flags;
|
||||
local_header.crc32 = central_header->crc32;
|
||||
local_header.size_uncompressed = central_header->size_uncompressed;
|
||||
local_header.size_compressed = central_header->size_compressed;
|
||||
local_header.length_extra = 0;
|
||||
|
||||
if (!xseekwrite(fout, out_index, &local_header, sizeof(local_header_t))) return 0;
|
||||
out_index += sizeof(local_header_t);
|
||||
if (!xseekwrite(fout, out_index, &filename[0], central_header->length_filename)) return 0;
|
||||
out_index += central_header->length_filename;
|
||||
|
||||
if (decompress && (compression_method_old == 8)) {
|
||||
if (!xdecompress(fin, fout, offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
|
||||
} else {
|
||||
if (!xfilecopy(fin, fout, offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
|
||||
}
|
||||
out_index += local_header.size_compressed;
|
||||
|
||||
memcpy(¢ral_directory_out[central_directory_out_index], central_header, sizeof(central_header_t) + central_header->length_filename);
|
||||
central_directory_out_index += sizeof(central_header_t) + central_header->length_filename;
|
||||
}
|
||||
|
||||
central_directory_out_size = central_directory_out_index;
|
||||
central_footer.central_directory_size = central_directory_out_size;
|
||||
central_footer.central_directory_offset = out_index;
|
||||
central_footer.length_comment = 0;
|
||||
if (!xseekwrite(fout, out_index, central_directory_out, central_directory_out_size)) return 0;
|
||||
out_index += central_directory_out_size;
|
||||
if (!xseekwrite(fout, out_index, ¢ral_footer, sizeof(central_footer_t))) return 0;
|
||||
|
||||
LOGD("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
|
||||
LOGD("central footer @ %08X\n", out_index);
|
||||
|
||||
close(fout);
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
free(central_directory_in);
|
||||
free(central_directory_out);
|
||||
close(fin);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#ifndef MAGISKMANAGER_ZIPADJUST_H_H
|
||||
#define MAGISKMANAGER_ZIPADJUST_H_H
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
int zipadjust(const char* filenameIn, const char* filenameOut, int decompress);
|
||||
|
||||
#define LOG_TAG "zipadjust"
|
||||
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||
|
||||
#endif //MAGISKMANAGER_ZIPADJUST_H_H
|
Loading…
Reference in New Issue
Block a user