Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
PranavPurwar authored and root committed Aug 14, 2023
0 parents commit 67f122f
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
Binary file added libs/hook.jar
Binary file not shown.
Binary file added libs/prefs.jar
Binary file not shown.
36 changes: 36 additions & 0 deletions src/main/kotlin/FileUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cosmicide.rewrite.util

import java.io.File

object FileUtil {

@JvmStatic
lateinit var dataDir: File

@JvmStatic
val projectDir
get() = dataDir.resolve("projects")

@JvmStatic
val classpathDir
get() = dataDir.resolve("classpath")

@JvmStatic
val pluginDir
get() = dataDir.resolve("plugins")

@JvmStatic
fun init(dir: File) {
dataDir = dir
projectDir.mkdirs()
classpathDir.mkdirs()
pluginDir.mkdirs()
}
}
53 changes: 53 additions & 0 deletions src/main/kotlin/Hook.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cosmicide.rewrite.plugin.api

import de.robv.android.xposed.XC_MethodHook.MethodHookParam
import org.cosmicide.rewrite.util.MultipleDexClassLoader

/**
* A hook that can be registered with the HookManager.
* @param method The name of the method to hook.
* @param argTypes The types of the arguments of the method to hook.
* @param type The class that contains the method to hook.
*/
open class Hook(
open val method: String,
open vararg val argTypes: Class<*>,
open val type: Class<*>
) {

/**
* @param methodName The name of the method to hook.
* @param args The types of the arguments of the method to hook.
* @param clazz The class that contains the method to hook.
* @param useSharedClassLoader Whether to use the shared ClassLoader that loads all plugins or not. This could be useful if you wanna change the behaviour of other plugins. Make sure to check if the plugin is loaded before using this.
*/
constructor(
methodName: String,
vararg args: Class<*>,
clazz: String,
useSharedClassLoader: Boolean = false
) : this(
method = methodName,
argTypes = args,
type = if (useSharedClassLoader) MultipleDexClassLoader.INSTANCE.loader.loadClass(clazz) else Class.forName(
clazz
)
)

open fun before(param: MethodHookParam) = run {}
open fun after(param: MethodHookParam) = run {}
}
57 changes: 57 additions & 0 deletions src/main/kotlin/HookManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cosmicide.rewrite.plugin.api

import android.content.Context
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import java.lang.ref.WeakReference
import java.lang.reflect.Member

object HookManager {

@JvmStatic
lateinit var context: WeakReference<Context>

@JvmStatic
fun registerHook(hook: Hook) =
XposedBridge.hookMethod(
hook.type.getDeclaredMethod(hook.method, *hook.argTypes),
object : XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam) {
hook.before(param)
}

override fun afterHookedMethod(param: MethodHookParam) {
hook.after(param)
}
})

@JvmStatic
fun invokeOriginal(method: Member, obj: Any?, vararg args: Any?) =
XposedBridge.invokeOriginalMethod(method, obj, args)

@JvmStatic
fun isHooked(method: Member) = XposedBridge.isHooked(method)

@JvmStatic
fun hookAllConstructors(clazz: Class<*>, callback: XC_MethodHook) =
XposedBridge.hookAllConstructors(clazz, callback)

@JvmStatic
fun hookAllMethods(clazz: Class<*>, methodName: String, callback: XC_MethodHook) =
XposedBridge.hookAllMethods(clazz, methodName, callback)

fun deoptimizeMethod(member: Member) = XposedBridge.deoptimizeMethod(member)

fun disableHiddenApiRestrictions() = XposedBridge.disableHiddenApiRestrictions()

fun disableProfileSaver() = XposedBridge.disableProfileSaver()

fun makeClassInheritable(clazz: Class<*>) = XposedBridge.makeClassInheritable(clazz)
}
107 changes: 107 additions & 0 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/


package changedatadirectory

import android.os.Build
import android.util.Log
import android.widget.Toast
import de.Maxr1998.modernpreferences.PreferenceScreen
import de.Maxr1998.modernpreferences.helpers.editText
import de.Maxr1998.modernpreferences.preferences.EditTextPreference
import org.cosmicide.rewrite.plugin.api.HookManager
import org.cosmicide.rewrite.util.FileUtil
import org.cosmicide.rewrite.util.PermissionUtils
import java.io.File

object Main {

private val pref = HookManager.context.get()!!.getSharedPreferences("datadir", 0)

@JvmStatic
fun main(args: Array<String>) {
val context = HookManager.context.get()!!
val isGranted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
PermissionUtils.hasPermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE)
} else {
PermissionUtils.hasPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (isGranted.not()) {
Toast.makeText(
context,
"Couldn't change data dir due to missing storage permission, check settings to grant it.",
Toast.LENGTH_LONG
).show()
return
}
val dataDir = pref.getString("data_directory", null)
if (dataDir != null && File(dataDir).exists()) {
Log.d("Plugin", "Data directory already set to $dataDir")
updateDirectory(File(dataDir))
}
Log.d("Plugin", "Loaded plugin ChangeDataDirectory")
}

private fun updateDirectory(dir: File) {
val oldDir = FileUtil.dataDir
Log.d("Plugin", "Updating data directory to $dir")
dir.mkdirs()
FileUtil.init(dir)
// Copy plugins from old directory
Toast.makeText(
HookManager.context.get(),
"Copying data from old directory...",
Toast.LENGTH_SHORT
).show()
oldDir.listFiles()?.forEach { file ->
if (file.isFile) {
file.copyTo(FileUtil.dataDir.resolve(file.name), overwrite = true)
} else {
file.copyRecursively(FileUtil.dataDir.resolve(file.name), overwrite = true)
}
}
Log.d(
"Plugin",
"dataDir: ${FileUtil.dataDir.exists()} classpath: ${FileUtil.classpathDir.exists()} project: ${FileUtil.projectDir.exists()}"
)
}

@JvmStatic
fun registerPreferences(builder: PreferenceScreen.Builder) {
val context = HookManager.context.get()!!

builder.apply {
editText("data_directory") {
title = "Data directory"
summary = "Current: ${FileUtil.dataDir}"
defaultValue = FileUtil.dataDir.absolutePath

textChangeListener = EditTextPreference.OnTextChangeListener { _, text ->
val dir = text.toString()
val file = File(dir)
if (file.isFile) {
Toast.makeText(
context,
"Data directory must be a directory",
Toast.LENGTH_SHORT
).show()
return@OnTextChangeListener false
}
if (file.mkdirs().not()) {
Toast.makeText(context, "Couldn't create directory", Toast.LENGTH_SHORT)
.show()
return@OnTextChangeListener false
}
pref.edit().putString("data_directory", text.toString()).apply()
updateDirectory(file)
true
}
}
}
}
}
44 changes: 44 additions & 0 deletions src/main/kotlin/MultipleDexClassLoader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cosmicide.rewrite.util

import dalvik.system.BaseDexClassLoader
import java.io.File

/**
* Basically a class to load multiple dex files
*
* @source https://github.com/Blokkok/blokkok-modsys/blob/main/module-system/src/main/java/com/blokkok/modsys/MultipleDexClassLoader.kt
*/
class MultipleDexClassLoader(
private val librarySearchPath: String? = null,
classLoader: ClassLoader = ClassLoader.getSystemClassLoader()
) {
val loader by lazy {
BaseDexClassLoader("", null, librarySearchPath, classLoader)
}

// we're calling an internal API for adding the dex path, might not be good
private val addDexPath = BaseDexClassLoader::class.java
.getMethod("addDexPath", String::class.java)

fun loadDex(dexPath: String): BaseDexClassLoader {
addDexPath.invoke(loader, dexPath)

return loader
}

fun loadDex(dexFile: File) {
loadDex(dexFile.absolutePath)
}

companion object {
@JvmStatic
val INSTANCE = MultipleDexClassLoader(classLoader = Companion::class.java.classLoader!!)
}
}
17 changes: 17 additions & 0 deletions src/main/kotlin/PermissionUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cosmicide.rewrite.util

import android.content.pm.PackageManager
import org.cosmicide.rewrite.plugin.api.HookManager

object PermissionUtils {

fun hasPermission(permission: String) = true

}
25 changes: 25 additions & 0 deletions src/main/kotlin/Plugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* This file is part of Cosmic IDE.
* Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cosmicide.rewrite.plugin.api

data class Plugin(
val name: String,
val version: String,
val author: String,
val description: String,
val source: String,
var raw: String = """
{
"name": "$name",
"version": "$version",
"author": "$author",
"description": "$description",
"source": "$source"
}
""".trimIndent()
)
Loading

0 comments on commit 67f122f

Please sign in to comment.