From ceb21ac7d2166f6c0b900abf90ca655b09f13563 Mon Sep 17 00:00:00 2001 From: relan Date: Sun, 15 Oct 2017 21:52:28 +0300 Subject: [PATCH 1/5] Add FileUtil class Exact copy of android.os.FileUtils functions (from AOSP 7.1.2), only Slog is replaced with Log. --- .../xposed/installer/util/FileUtil.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java new file mode 100644 index 000000000..a0a6d8c6e --- /dev/null +++ b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.robv.android.xposed.installer.util; + +import android.util.Log; + +import java.io.File; + +import de.robv.android.xposed.installer.XposedApp; + +public class FileUtil { + public static boolean deleteContentsAndDir(File dir) { + if (deleteContents(dir)) { + return dir.delete(); + } else { + return false; + } + } + + public static boolean deleteContents(File dir) { + File[] files = dir.listFiles(); + boolean success = true; + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + success &= deleteContents(file); + } + if (!file.delete()) { + Log.w(XposedApp.TAG, "Failed to delete " + file); + success = false; + } + } + } + return success; + } +} From 85605a2ba9b13fc87ed978493bacd72f669faf2b Mon Sep 17 00:00:00 2001 From: relan Date: Sun, 15 Oct 2017 21:58:45 +0300 Subject: [PATCH 2/5] Use the new FileUtil class to delete directories Stop using reflection. --- .../de/robv/android/xposed/installer/XposedApp.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java index abb821164..e51a1162b 100644 --- a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java +++ b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java @@ -20,10 +20,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.lang.reflect.Method; import de.robv.android.xposed.installer.util.AssetUtil; import de.robv.android.xposed.installer.util.DownloadsUtil; +import de.robv.android.xposed.installer.util.FileUtil; import de.robv.android.xposed.installer.util.InstallZipUtil; import de.robv.android.xposed.installer.util.InstallZipUtil.XposedProp; import de.robv.android.xposed.installer.util.NotificationUtil; @@ -129,14 +129,9 @@ private void createDirectories() { mkdirAndChmod("log", 00777); if (Build.VERSION.SDK_INT >= 24) { - try { - Method deleteDir = FileUtils.class.getDeclaredMethod("deleteContentsAndDir", File.class); - deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "bin")); - deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "conf")); - deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "log")); - } catch (ReflectiveOperationException e) { - Log.w(XposedApp.TAG, "Failed to delete obsolete directories", e); - } + FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "bin")); + FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "conf")); + FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "log")); } } From cec28e30263782bd41aed566e2a98fdc1ce8e848 Mon Sep 17 00:00:00 2001 From: relan Date: Sun, 29 Oct 2017 18:09:09 +0300 Subject: [PATCH 3/5] Add FileUtils.setPermissions() methods Those functions can set different permissions for owner and everyone else. For example FileUtils.setPermissions(path, 7, 1) will mean Unix mode 0711: read, write, execute for owner; only execute for group and others. There is no need to set group permissions specifically. When a new app is being installed, Android creates a new Unix user and group for it. Since groups aren't shared, they don't actually participate in access rights checking: when we access our file, "owner" permissions are in effect; when another app accesses our file, "other" permissions are used. --- .../xposed/installer/util/FileUtil.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java index a0a6d8c6e..aacb87f32 100644 --- a/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java +++ b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java @@ -23,6 +23,25 @@ import de.robv.android.xposed.installer.XposedApp; public class FileUtil { + public static boolean setPermissions(String path, int owner, int other) { + return setPermissions(new File(path), owner, other); + } + + public static boolean setPermissions(File path, int owner, int other) { + if (!setPermissions(path, other, false) || !setPermissions(path, owner, true)) { + Log.w(XposedApp.TAG, "Failed to set permissions " + + owner + "/" + other + " for " + path.getPath()); + return false; + } + return true; + } + + private static boolean setPermissions(File path, int perm, boolean ownerOnly) { + return path.setReadable((perm & 4) != 0, ownerOnly) + && path.setWritable((perm & 2) != 0, ownerOnly) + && path.setExecutable((perm & 1) != 0, ownerOnly); + } + public static boolean deleteContentsAndDir(File dir) { if (deleteContents(dir)) { return dir.delete(); From 56e17b615f0c54fd51491f7e0ff5d106ce7cc228 Mon Sep 17 00:00:00 2001 From: relan Date: Sun, 29 Oct 2017 18:10:02 +0300 Subject: [PATCH 4/5] Use the new FileUtil.setPermissions() methods --- .../robv/android/xposed/installer/XposedApp.java | 15 +++++++-------- .../installer/installation/FlashDirectly.java | 2 +- .../android/xposed/installer/util/AssetUtil.java | 13 +++++++------ .../android/xposed/installer/util/ModuleUtil.java | 5 ++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java index e51a1162b..1fe78c128 100644 --- a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java +++ b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java @@ -11,7 +11,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; -import android.os.FileUtils; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.content.FileProvider; @@ -124,9 +123,9 @@ public void onCreate() { } private void createDirectories() { - FileUtils.setPermissions(BASE_DIR, 00711, -1, -1); - mkdirAndChmod("conf", 00771); - mkdirAndChmod("log", 00777); + FileUtil.setPermissions(BASE_DIR, 7, 1); + mkdirAndChmod("conf", 7, 1); + mkdirAndChmod("log", 7, 7); if (Build.VERSION.SDK_INT >= 24) { FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "bin")); @@ -135,10 +134,10 @@ private void createDirectories() { } } - private void mkdirAndChmod(String dir, int permissions) { - dir = BASE_DIR + dir; - new File(dir).mkdir(); - FileUtils.setPermissions(dir, permissions, -1, -1); + private void mkdirAndChmod(String name, int owner, int other) { + File dir = new File(BASE_DIR + name); + dir.mkdir(); + FileUtil.setPermissions(dir, owner, other); } public void reloadXposedProp() { diff --git a/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java b/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java index e230d3fd7..fad7f66d8 100644 --- a/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java +++ b/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java @@ -46,7 +46,7 @@ public void flash(Context context, FlashCallback callback) { ZipEntry entry = zip.getEntry("META-INF/com/google/android/update-binary"); File updateBinaryFile = new File(XposedApp.getInstance().getCacheDir(), "update-binary"); try { - AssetUtil.writeStreamToFile(zip.getInputStream(entry), updateBinaryFile, 0700); + AssetUtil.writeStreamToFile(zip.getInputStream(entry), updateBinaryFile, 7, 0); } catch (IOException e) { Log.e(XposedApp.TAG, "Could not extract update-binary", e); triggerError(callback, FlashCallback.ERROR_INVALID_ZIP); diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java index 63b2bc826..5b71de532 100644 --- a/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java +++ b/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java @@ -2,7 +2,6 @@ import android.content.res.AssetManager; import android.os.Build; -import android.os.FileUtils; import android.util.Log; import java.io.File; @@ -26,12 +25,13 @@ public static String getBinariesFolder() { } } - public static File writeAssetToFile(AssetManager assets, String assetName, File targetFile, int mode) { + public static File writeAssetToFile(AssetManager assets, String assetName, + File targetFile, int owner, int other) { try { if (assets == null) assets = XposedApp.getInstance().getAssets(); InputStream in = assets.open(assetName); - writeStreamToFile(in, targetFile, mode);; + writeStreamToFile(in, targetFile, owner, other); return targetFile; } catch (IOException e) { Log.e(XposedApp.TAG, "could not extract asset", e); @@ -42,7 +42,8 @@ public static File writeAssetToFile(AssetManager assets, String assetName, File } } - public static void writeStreamToFile(InputStream in, File targetFile, int mode) throws IOException { + public static void writeStreamToFile(InputStream in, File targetFile, + int owner, int other) throws IOException { FileOutputStream out = new FileOutputStream(targetFile); byte[] buffer = new byte[1024]; @@ -53,7 +54,7 @@ public static void writeStreamToFile(InputStream in, File targetFile, int mode) in.close(); out.close(); - FileUtils.setPermissions(targetFile.getAbsolutePath(), mode, -1, -1); + FileUtil.setPermissions(targetFile.getAbsolutePath(), owner, other); } public synchronized static void extractBusybox() { @@ -61,7 +62,7 @@ public synchronized static void extractBusybox() { return; AssetManager assets = null; - writeAssetToFile(assets, getBinariesFolder() + "busybox-xposed", BUSYBOX_FILE, 00700); + writeAssetToFile(assets, getBinariesFolder() + "busybox-xposed", BUSYBOX_FILE, 7, 0); } public synchronized static void removeBusybox() { diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java index 9aa8e1de3..e38788b7c 100644 --- a/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java +++ b/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java @@ -9,7 +9,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; -import android.os.FileUtils; import android.util.Log; import android.widget.Toast; @@ -223,8 +222,8 @@ public synchronized void updateModulesList(boolean showToast) { modulesList.close(); enabledModulesList.close(); - FileUtils.setPermissions(MODULES_LIST_FILE, 00664, -1, -1); - FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1); + FileUtil.setPermissions(MODULES_LIST_FILE, 6, 4); + FileUtil.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 6, 4); if (showToast) showToast(R.string.xposed_module_list_updated); From 4a7399ba38c9b8e68142476eb6f076619a61ed83 Mon Sep 17 00:00:00 2001 From: relan Date: Sun, 15 Oct 2017 22:00:38 +0300 Subject: [PATCH 5/5] Delete AndroidHiddenAPI.jar Not needed anymore. --- app/build.gradle | 1 - app/libs/AndroidHiddenAPI.jar | Bin 3191 -> 0 bytes 2 files changed, 1 deletion(-) delete mode 100644 app/libs/AndroidHiddenAPI.jar diff --git a/app/build.gradle b/app/build.gradle index 19deab7cf..ea1abdd01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,5 +33,4 @@ dependencies { implementation 'eu.chainfire:libsuperuser:1.0.0.201608240809' implementation 'com.squareup.picasso:picasso:2.5.2' implementation 'de.psdev.licensesdialog:licensesdialog:1.8.1' - compileOnly fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/app/libs/AndroidHiddenAPI.jar b/app/libs/AndroidHiddenAPI.jar deleted file mode 100644 index 113acc1e39b8151c067fc694a108aa613ae76541..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3191 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