Skip to content

Commit

Permalink
added webui for kernelsu
Browse files Browse the repository at this point in the history
  • Loading branch information
j-hc committed May 21, 2024
1 parent a9d3ea3 commit e827b7e
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 52 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
b.sh
test*
magisk/system/bin/*
magisk/webroot/*
*.log
zygisk-rust
aidl/*.aidl*
aidl/*.aidl*
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ Detaches installed apps from Play Store against its aggressive updating policy w
Hooks libbinder with zygisk

### Usage
* Enable zygisk in Magisk **or** [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext) module if you are using KernelSU
* Enable zygisk in Magisk **or** [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext) module if you are on KernelSU
* Flash zygisk-detach module
* Reboot
* Run the cli in termux: `su -c detach`
or use [zygisk-detach-app](https://github.com/j-hc/zygisk-detach-app) if you dont wanna use the terminal
or use [zygisk-detach-app](https://github.com/j-hc/zygisk-detach-app) if you dont wanna use the terminal
or use the WebUI if you are on KernelSU
* Select apps you wish to detach. Changes are applied immediately, no need to reboot.

### Notes
Expand Down
7 changes: 2 additions & 5 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ version = "0.1.0"
edition = "2021"

[dependencies]
termion = "3"

[profile.dev]
panic = "abort"
termion = "4"

[profile.release-pr]
inherits = "release"
lto = true
panic = "abort"
codegen-units = 1
strip = true
opt-level = 3
opt-level = 3
175 changes: 136 additions & 39 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,102 @@ fn main() -> ExitCode {
}));

let mut args = std::env::args().skip(1);
if matches!(args.next().as_deref(), Some("--serialize")) {
let Some(dtxt) = args.next() else {
eprintln!("detach.txt path not supplied.");
return ExitCode::FAILURE;
};
let Some(dbin) = args.next() else {
eprintln!("detach.bin path not supplied.");
return ExitCode::FAILURE;
};

if let Err(err) = serialize_txt(&dtxt, &dbin) {
eprintln!("ERROR: {err}");
return ExitCode::FAILURE;
} else {
println!("Serialized detach.txt");
return ExitCode::SUCCESS;
if let Some(cmd) = args.next().as_deref() {
match cmd {
"serialize" => {
let Some(dtxt) = args.next() else {
eprintln!("ERROR: detach.txt path not supplied.");
return ExitCode::FAILURE;
};
let Some(dbin) = args.next() else {
eprintln!("ERROR: detach.bin path not supplied.");
return ExitCode::FAILURE;
};
if let Err(err) = serialize_txt(&dtxt, &dbin) {
eprintln!("ERROR: {err}");
return ExitCode::FAILURE;
} else {
println!("Serialized detach.txt");
return ExitCode::SUCCESS;
}
}
"detachall" => {
let Some(pkg_names) = args.next() else {
eprintln!("ERROR: package names not supplied.");
return ExitCode::FAILURE;
};
if pkg_names.is_empty() {
println!("Emptied the detach.bin");
return ExitCode::SUCCESS;
}
let mut f = fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(MODULE_DETACH)
.expect("open detach.bin");
for n in pkg_names.split(' ') {
bin_serialize(n, &mut f).expect("write to detach.bin");
}
detach_bin_changed();
println!("Changes are applied. No need for a reboot!");
return ExitCode::SUCCESS;
}
"detach" => {
let Some(pkg_name) = args.next() else {
eprintln!("ERROR: package name not supplied.");
return ExitCode::FAILURE;
};
if detach_by_name(&pkg_name).expect("detach.txt") {
println!("Changes are applied. No need for a reboot!");
} else {
println!("{} {}", "already detached:", pkg_name);
}
return ExitCode::SUCCESS;
}
"reattach" => {
let Some(pkg_name) = args.next() else {
eprintln!("ERROR: package name not supplied.");
return ExitCode::FAILURE;
};
if reattach_by_name(&pkg_name).expect("detach.txt") {
println!("{} {}", "re-attached:", pkg_name);
}
return ExitCode::SUCCESS;
}
"list" => {
let mut detach_txt = match fs::OpenOptions::new()
.write(true)
.read(true)
.open(MODULE_DETACH)
{
Ok(f) => f,
Err(e) => {
eprintln!("ERROR: {e}");
return ExitCode::FAILURE;
}
};
let mut content = Vec::new();
match detach_txt.read_to_end(&mut content) {
Ok(l) if l == 0 => return ExitCode::SUCCESS,
Ok(_) => {}
Err(e) => {
eprintln!("ERROR: {e}");
return ExitCode::FAILURE;
}
};
for (app, _) in get_detached_apps(&content) {
println!("{app}");
}
return ExitCode::SUCCESS;
}
_ => {}
}
}

#[cfg(target_os = "android")]
if let Ok(true) = check_denylist() {
eprintln!("Stop putting Play Store in denylist!");
}
let _ = check_denylist();

let mut menus = Menus::new();
let ret = match interactive(&mut menus) {
Ok(()) => ExitCode::SUCCESS,
Expand All @@ -106,7 +180,8 @@ fn main() -> ExitCode {
ret
}

fn check_denylist() -> io::Result<bool> {
#[cfg(target_os = "android")]
fn check_denylist() -> io::Result<()> {
let op = Command::new("magisk")
.args(["--denylist", "ls"])
.stdout(std::process::Stdio::piped())
Expand All @@ -118,10 +193,9 @@ fn check_denylist() -> io::Result<bool> {
.args(["--denylist", "rm", "com.android.vending"])
.spawn()?
.wait()?;
Ok(true)
} else {
Ok(false)
eprintln!("Do not put Play Store in denylist!");
}
Ok(())
}

fn detach_bin_changed() {
Expand Down Expand Up @@ -196,7 +270,7 @@ fn reattach_menu(menus: &mut Menus) -> IOResult<()> {
let mut content = Vec::new();
detach_txt.read_to_end(&mut content)?;
detach_txt.seek(io::SeekFrom::Start(0))?;
let detached_apps = get_detached_apps(menus, &content);
let detached_apps = get_detached_apps(&content);
let detach_len = detached_apps.len();
if detach_len == 0 {
text!(menus, "detach.bin is empty");
Expand All @@ -221,7 +295,26 @@ fn reattach_menu(menus: &mut Menus) -> IOResult<()> {
Ok(())
}

fn get_detached_apps(menus: &mut Menus, detach_txt: &[u8]) -> Vec<(String, Range<usize>)> {
fn reattach_by_name(pkg_name: &str) -> IOResult<bool> {
let mut detach_txt = fs::OpenOptions::new()
.write(true)
.read(true)
.open(MODULE_DETACH)?;
let mut content = Vec::new();
detach_txt.read_to_end(&mut content)?;
detach_txt.seek(io::SeekFrom::Start(0))?;
let detached_apps = get_detached_apps(&content);
let Some(reattach_app) = detached_apps.iter().find(|(name, _)| name == pkg_name) else {
return Ok(false);
};
content.drain(reattach_app.1.clone());
detach_txt.set_len(0)?;
detach_txt.write_all(&content)?;
detach_bin_changed();
Ok(true)
}

fn get_detached_apps(detach_txt: &[u8]) -> Vec<(String, Range<usize>)> {
let mut i = 0;
let mut detached = Vec::new();
while i < detach_txt.len() {
Expand All @@ -230,7 +323,6 @@ fn get_detached_apps(menus: &mut Menus, detach_txt: &[u8]) -> Vec<(String, Range
i += SZ_LEN;
let Some(encoded_name) = &detach_txt.get(i..i + len as usize) else {
eprintln!("Corrupted detach.bin. Reset and try again.");
let _ = menus.cursor_show();
std::process::exit(1);
};
let name = String::from_utf8(encoded_name.iter().step_by(2).cloned().collect()).unwrap();
Expand Down Expand Up @@ -353,28 +445,33 @@ fn detach_menu(menus: &mut Menus) -> IOResult<()> {
)?;
menus.cursor_hide()?;
if let Some(detach_app) = selected {
let mut f = fs::OpenOptions::new()
.create(true)
.append(true)
.read(true)
.open(MODULE_DETACH)?;
let mut buf: Vec<u8> = Vec::new();
f.read_to_end(&mut buf)?;
if !get_detached_apps(menus, &buf)
.iter()
.any(|(s, _)| s == detach_app)
{
bin_serialize(detach_app, &mut f)?;
if detach_by_name(detach_app)? {
textln!(menus, "{} {}", "detach:".green(), detach_app);
textln!(menus, "Changes are applied. No need for a reboot!");
detach_bin_changed();
} else {
textln!(menus, "{} {}", "already detached:".green(), detach_app);
}
}
Ok(())
}

fn detach_by_name(detach_app: &str) -> IOResult<bool> {
let mut f = fs::OpenOptions::new()
.create(true)
.append(true)
.read(true)
.open(MODULE_DETACH)?;
let mut buf: Vec<u8> = Vec::new();
f.read_to_end(&mut buf)?;
if !get_detached_apps(&buf).iter().any(|(s, _)| s == detach_app) {
bin_serialize(detach_app, &mut f)?;
detach_bin_changed();
Ok(true)
} else {
Ok(false)
}
}

fn _kill_store_am() -> IOResult<()> {
Command::new("am")
.args(["force-stop", "com.android.vending"])
Expand Down
2 changes: 1 addition & 1 deletion cli/src/menus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ macro_rules! text {
($dst:expr, $($arg:tt)*) => {{
write!(
$dst.stdout,
"{}{}{}{}\r",
"\r{}{}{}{}\r",
cursor::Up(1),
clear::CurrentLine,
format_args!($($arg)*),
Expand Down
4 changes: 4 additions & 0 deletions ksu-webui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
package-lock.json
.parcel-cache
dist
11 changes: 11 additions & 0 deletions ksu-webui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "ksu-webui",
"version": "1.0.0",
"author": "j-hc",
"dependencies": {
"kernelsu": "^1.0.6"
},
"devDependencies": {
"parcel": "^2.12.0"
}
}
33 changes: 33 additions & 0 deletions ksu-webui/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="styles.css" type="text/css">
<script type="module" crossorigin src="index.js" type="text/javascript"></script>
</head>

<body>
<div class="card">
<input type="text" class="search-input" id="search" placeholder="Search">
</div>

<div id="apps-list"></div>

<div class="floating-card">
<button class="floating-btn" id="detach">Detach</button>
</div>

<template id="app-template">
<div class="card">
<div class="content">
<p class="name"></p>
<input type="checkbox" class="checkbox">
</div>
</div>
</template>
</body>

</html>
Loading

0 comments on commit e827b7e

Please sign in to comment.