You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FoxMagiskModuleManager/app/src/main/java/com/fox2code/mmm/utils/io/Files.java

192 lines
6.7 KiB
Java

package com.fox2code.mmm.utils.io;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.OpenableColumns;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.topjohnwu.superuser.io.SuFile;
import com.topjohnwu.superuser.io.SuFileInputStream;
import com.topjohnwu.superuser.io.SuFileOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import timber.log.Timber;
public enum Files {
;
private static final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;
// stolen from https://stackoverflow.com/a/25005243
public static @NonNull String getFileName(Context context, Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (index != -1) {
result = cursor.getString(index);
}
}
}
}
if (result == null) {
result = uri.getPath();
int cut = result.lastIndexOf('/');
if (cut != -1) {
result = result.substring(cut + 1);
}
}
return result;
}
// based on https://stackoverflow.com/a/63018108
public static @Nullable Long getFileSize(Context context, Uri uri) {
Long result = null;
try {
String scheme = uri.getScheme();
if (scheme.equals("content")) {
Cursor returnCursor = context.getContentResolver().
query(uri, null, null, null, null);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
long size = returnCursor.getLong(sizeIndex);
returnCursor.close();
result = size;
}
if (scheme.equals("file")) {
result = new File(uri.getPath()).length();
}
} catch (Exception e) {
Timber.e(Log.getStackTraceString(e));
return result;
}
return result;
}
public static void write(File file, byte[] bytes) throws IOException {
try (OutputStream outputStream = new FileOutputStream(file)) {
outputStream.write(bytes);
outputStream.flush();
}
}
public static byte[] read(File file) throws IOException {
try (InputStream inputStream = new FileInputStream(file)) {
return readAllBytes(inputStream);
}
}
public static void writeSU(File file, byte[] bytes) throws IOException {
try (OutputStream outputStream = SuFileOutputStream.open(file)) {
outputStream.write(bytes);
outputStream.flush();
}
}
public static byte[] readSU(File file) throws IOException {
if (file.isFile() && file.canRead()) {
try { // Read as app if su not required
return read(file);
} catch (IOException ignored) {}
}
try (InputStream inputStream = SuFileInputStream.open(file)) {
return readAllBytes(inputStream);
}
}
public static boolean existsSU(File file) {
return file.exists() || new SuFile(file.getAbsolutePath()).exists();
}
public static void copy(InputStream inputStream,OutputStream outputStream) throws IOException {
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
outputStream.write(data, 0, nRead);
}
outputStream.flush();
}
public static void closeSilently(Closeable closeable) {
try {
if (closeable != null) closeable.close();
} catch (IOException ignored) {}
}
public static ByteArrayOutputStream makeBuffer(long capacity) {
// Cap buffer to 1 Gib (or 512 Mib for 32bit) to avoid memory errors
return Files.makeBuffer((int) Math.min(capacity, is64bit ? 0x40000000 : 0x20000000));
}
public static ByteArrayOutputStream makeBuffer(int capacity) {
return new ByteArrayOutputStream(Math.max(0x20, capacity)) {
@NonNull
@Override
public byte[] toByteArray() {
return this.buf.length == this.count ?
this.buf : super.toByteArray();
}
};
}
public static byte[] readAllBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = Files.makeBuffer(inputStream.available());
copy(inputStream, buffer);
return buffer.toByteArray();
}
public static void fixJavaZipHax(byte[] bytes) {
if (bytes.length > 8 && bytes[0x6] == 0x0 && bytes[0x7] == 0x0 && bytes[0x8] == 0x8)
bytes[0x7] = 0x8; // Known hax to prevent java zip file read
}
public static void patchModuleSimple(byte[] bytes,OutputStream outputStream) throws IOException {
fixJavaZipHax(bytes); patchModuleSimple(new ByteArrayInputStream(bytes), outputStream);
}
public static void patchModuleSimple(InputStream inputStream,OutputStream outputStream) throws IOException {
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
int nRead;
byte[] data = new byte[16384];
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
String name = zipEntry.getName();
int i = name.indexOf('/', 1);
if (i == -1) continue;
String newName = name.substring(i + 1);
if (newName.startsWith(".git")) continue; // Skip metadata
zipOutputStream.putNextEntry(new ZipEntry(newName));
while ((nRead = zipInputStream.read(data, 0, data.length)) != -1) {
zipOutputStream.write(data, 0, nRead);
}
zipOutputStream.flush();
zipOutputStream.closeEntry();
zipInputStream.closeEntry();
}
zipOutputStream.finish();
zipOutputStream.flush();
zipOutputStream.close();
zipInputStream.close();
}
}