Files

424 lines
13 KiB
Bash

#!/system/bin/sh
# ============================================================
# WSA WebDAV Control Panel
# ============================================================
# Usage:
# sh app.sh Interactive menu
# sh app.sh -verbose Interactive menu (verbose)
# sh app.sh <command> Direct command
# sh app.sh -verbose <command> Direct command (verbose)
#
# Commands:
# start, stop, restart, status, health, log, config,
# port, root, connections, auto-start, clear, help
# ============================================================
PKG="com.wsa.webdav"
DATA_DIR="/data/data/$PKG/files"
RECV="$PKG/.AdbCommandReceiver"
ACT_PREFIX="com.wsa.webdav"
RESULT_ACT="$ACT_PREFIX.RESULT"
RESULT_FILE="$DATA_DIR/result.json"
CONFIG_PATH="$DATA_DIR/config.json"
DEFAULT_PORT=8088
VERBOSE=0
JSON_OUT=0
# --- Colors ---
c_r='\033[0;31m'
c_g='\033[0;32m'
c_y='\033[0;33m'
c_b='\033[0;34m'
c_c='\033[0;36m'
c_w='\033[1;37m'
c_d='\033[0m'
# --- Helpers ---
ok() { printf "${c_g}[OK]${c_d} %s\n" "$1"; }
err() { printf "${c_r}[ERR]${c_d} %s\n" "$1"; }
info() { printf "${c_c}[INFO]${c_d} %s\n" "$1"; }
warn() { printf "${c_y}[WARN]${c_d} %s\n" "$1"; }
vlog() { [ "$VERBOSE" -eq 1 ] && printf "${c_b}[*]${c_d} %s\n" "$1" || true; }
# Extract JSON field without jq
json_val() {
echo "$1" | sed 's/[{}]//g' | tr ',' '\n' | grep "\"$2\"" | head -1 | sed 's/.*"'"$2"'"[[:space:]]*:[[:space:]]*//' | sed 's/[",]//g' | sed 's/^ *//;s/ *$//'
}
# Send broadcast command, return result from file
send_cmd() {
local action="$1"
shift
local t1=$(date +%s%N 2>/dev/null || echo 0)
rm -f "$RESULT_FILE" 2>/dev/null
local out
out=$(am broadcast -a "$ACT_PREFIX.$action" "$@" -n "$RECV" 2>&1)
local t2=$(date +%s%N 2>/dev/null || echo 0)
vlog "Broadcast: $action | am output: $out"
[ "$VERBOSE" -eq 1 ] && [ "$t1" != "0" ] && vlog "Time: $(( (t2 - t1) / 1000000 ))ms"
sleep 0.2
if [ -f "$RESULT_FILE" ]; then
local result=$(cat "$RESULT_FILE" 2>/dev/null)
rm -f "$RESULT_FILE" 2>/dev/null
vlog "Result: $result"
echo "$result"
else
echo "$out"
fi
}
# Check if port is open
port_open() {
local port=${1:-$DEFAULT_PORT}
local hex_port=$(printf "%04X" "$port")
grep -q ":${hex_port}" /proc/net/tcp /proc/net/tcp6 2>/dev/null && return 0 || return 1
}
# Format uptime from ms
fmt_uptime() {
local ms=$1
local s=$(( ms / 1000 ))
local m=$(( s / 60 ))
local h=$(( m / 60 ))
if [ "$h" -gt 0 ]; then
echo "${h}h $(( m % 60 ))m"
elif [ "$m" -gt 0 ]; then
echo "${m}m $(( s % 60 ))s"
else
echo "${s}s"
fi
}
get_port() {
if [ -f "$CONFIG_PATH" ]; then
local p=$(cat "$CONFIG_PATH" 2>/dev/null | tr -d ' \r\n' | grep -o '"port":[0-9]*' | head -1 | sed 's/"port"://')
[ -n "$p" ] && [ "$p" -gt 0 ] 2>/dev/null && echo "$p" && return
fi
echo "$DEFAULT_PORT"
}
# ============================================================
# Commands
# ============================================================
cmd_start() {
info "Starting WebDAV server..."
send_cmd "START" > /dev/null
sleep 1
local port=$(get_port)
if port_open "$port"; then
ok "Server running on 127.0.0.1:$port"
else
am start -n "$PKG/.MainActivity" > /dev/null 2>&1
sleep 2
if port_open "$port"; then
ok "Server running on 127.0.0.1:$port"
else
err "Server may not have started. Check: sh app.sh log"
fi
fi
}
cmd_stop() {
info "Stopping WebDAV server..."
send_cmd "STOP" > /dev/null
sleep 1
ok "Stop command sent"
}
cmd_restart() {
info "Restarting WebDAV server..."
send_cmd "RESTART" > /dev/null
sleep 2
local port=$(get_port)
if port_open "$port"; then
ok "Server restarted on 127.0.0.1:$port"
else
warn "Restarting... check status in a moment"
fi
}
cmd_status() {
local port=$(get_port)
local running="stopped"
port_open "$port" && running="running"
if [ "$running" = "running" ]; then
ok "Server: RUNNING"
else
err "Server: STOPPED"
fi
info "Port: $port"
if [ -f "$CONFIG_PATH" ]; then
local auto_start=$(grep -o '"auto_start":[^,}]*' "$CONFIG_PATH" 2>/dev/null | sed 's/.*://')
[ "$auto_start" = "true" ] && info "Auto-start: ON" || info "Auto-start: OFF"
fi
local root_out
root_out=$(send_cmd "ROOT_STATUS" 2>/dev/null)
local root_avail=$(echo "$root_out" | grep -o '"root_available"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
[ "$root_avail" = "true" ] && info "Root: available" || info "Root: unavailable"
}
cmd_health() {
info "Checking health..."
local out=$(send_cmd "HEALTH" 2>/dev/null)
local port_open_v=$(echo "$out" | grep -o '"port_open"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
local mem_used=$(echo "$out" | grep -o '"memory_used_mb"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
local mem_max=$(echo "$out" | grep -o '"memory_max_mb"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
local threads=$(echo "$out" | grep -o '"threads"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
local root_v=$(echo "$out" | grep -o '"root_available"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
[ "$port_open_v" = "true" ] && ok "Port: open" || err "Port: closed"
info "Memory: ${mem_used}MB / ${mem_max}MB"
info "Threads: $threads"
[ "$root_v" = "true" ] && ok "Root: available" || info "Root: unavailable"
[ "$VERBOSE" -eq 1 ] && info "Raw: $out"
}
cmd_log() {
local lines=${1:-50}
local logfile="$DATA_DIR/server.log"
if [ -f "$logfile" ]; then
info "Last $lines log lines:"
echo "---"
tail -"$lines" "$logfile"
echo "---"
else
warn "Log file not found"
fi
}
cmd_clear() {
send_cmd "LOG_CLEAR" > /dev/null 2>&1
logcat -c 2>/dev/null
ok "Logs cleared"
}
cmd_config() {
if [ -f "$CONFIG_PATH" ]; then
info "Config: $CONFIG_PATH"
echo "---"
cat "$CONFIG_PATH"
echo ""
echo "---"
else
warn "Config file not found at $CONFIG_PATH"
info "Fetching from service..."
send_cmd "CONFIG_SHOW" 2>/dev/null
fi
}
cmd_port() {
local new_port=$1
if [ -z "$new_port" ]; then
local port=$(get_port)
info "Current port: $port"
return
fi
if ! [ "$new_port" -gt 0 ] 2>/dev/null; then
err "Invalid port: $new_port"
return
fi
info "Setting port to $new_port (will restart)..."
send_cmd "SET_PORT" --ei port "$new_port" > /dev/null
sleep 2
if port_open "$new_port"; then
ok "Server running on port $new_port"
else
warn "Port changed, server may be restarting..."
fi
}
cmd_root() {
info "Checking root access..."
local out=$(send_cmd "ROOT_STATUS" 2>/dev/null)
local avail=$(echo "$out" | grep -o '"root_available"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
local configured=$(echo "$out" | grep -o '"root_configured"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
[ "$avail" = "true" ] && ok "Root: available" || err "Root: unavailable"
[ "$configured" = "true" ] && info "Root access: enabled" || info "Root access: disabled"
if [ "$avail" != "true" ]; then
info "Attempting to reacquire root..."
send_cmd "REACQUIRE_ROOT" > /dev/null 2>&1
sleep 1
out=$(send_cmd "ROOT_STATUS" 2>/dev/null)
avail=$(echo "$out" | grep -o '"root_available":[^,}]*' | sed 's/.*://')
[ "$avail" = "true" ] && ok "Root acquired!" || warn "Root still unavailable"
fi
[ "$VERBOSE" -eq 1 ] && info "Raw: $out"
}
cmd_connections() {
local out=$(send_cmd "CONNECTIONS" 2>/dev/null)
local threads=$(echo "$out" | grep -o '"active_threads"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
local running=$(echo "$out" | grep -o '"server_running"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*://' | sed 's/[",]//g; s/^ *//;s/ *$//')
[ "$running" = "true" ] && ok "Server: running" || err "Server: stopped"
info "Active threads: $threads"
[ "$VERBOSE" -eq 1 ] && info "Raw: $out"
}
cmd_autostart() {
local state=$1
case "$state" in
on|1|true|enable)
send_cmd "ENABLE_AUTO_START" > /dev/null 2>&1
ok "Auto-start: enabled"
;;
off|0|false|disable)
send_cmd "DISABLE_AUTO_START" > /dev/null 2>&1
ok "Auto-start: disabled"
;;
*)
if [ -f "$CONFIG_PATH" ]; then
local val=$(grep -o '"auto_start":[^,}]*' "$CONFIG_PATH" 2>/dev/null | sed 's/.*://')
info "Auto-start: $val"
fi
;;
esac
}
cmd_help() {
echo "${c_w}WSA WebDAV Control Panel${c_d}"
echo ""
echo "Usage: sh app.sh [-verbose] <command> [args]"
echo ""
echo "Commands:"
echo " start Start the WebDAV server"
echo " stop Stop the server"
echo " restart Restart the server"
echo " status Show server status"
echo " health Health check (memory, threads)"
echo " log [N] Show last N log lines (default 50)"
echo " clear Clear logs"
echo " config Show configuration"
echo " port [NNNN] Show or set port"
echo " root Check root access"
echo " connections Show active connections"
echo " auto-start [on|off] Toggle auto-start"
echo " help Show this help"
echo ""
echo "Flags:"
echo " -verbose Verbose output"
echo " -json Raw JSON output"
echo ""
echo "Interactive: sh app.sh (no arguments)"
}
# ============================================================
# Interactive Menu
# ============================================================
show_menu() {
echo ""
echo "${c_w}+--------------------------------------+${c_d}"
echo "${c_w}| WSA WebDAV Control Panel |${c_d}"
echo "${c_w}+--------------------------------------+${c_d}"
echo "${c_d} ${c_c}[1]${c_d} Start Server"
echo "${c_d} ${c_c}[2]${c_d} Stop Server"
echo "${c_d} ${c_c}[3]${c_d} Restart Server"
echo "${c_d} ${c_c}[4]${c_d} Server Status"
echo "${c_d} ${c_c}[5]${c_d} Health Check"
echo "${c_d} ${c_c}[6]${c_d} View Logs"
echo "${c_d} ${c_c}[7]${c_d} Show Config"
echo "${c_d} ${c_c}[8]${c_d} Change Port"
echo "${c_d} ${c_c}[9]${c_d} Root Status"
echo "${c_d} ${c_c}[10]${c_d} Connections"
echo "${c_d} ${c_c}[11]${c_d} Toggle Auto-Start"
echo "${c_d} ${c_c}[12]${c_d} Clear Logs"
echo "${c_d} ${c_c}[0]${c_d} Exit"
echo "${c_w}+--------------------------------------+${c_d}"
echo ""
}
run_menu() {
while true; do
show_menu
printf "${c_w}Choice: ${c_d}"
read choice
echo ""
case "$choice" in
1) cmd_start ;;
2) cmd_stop ;;
3) cmd_restart ;;
4) cmd_status ;;
5) cmd_health ;;
6)
printf "Lines (default 50): "
read n
cmd_log "${n:-50}"
;;
7) cmd_config ;;
8)
printf "New port (empty to show): "
read p
cmd_port "$p"
;;
9) cmd_root ;;
10) cmd_connections ;;
11)
printf "Auto-start [on/off]: "
read s
cmd_autostart "$s"
;;
12) cmd_clear ;;
0|"")
ok "Bye"
exit 0
;;
*) err "Invalid choice: $choice" ;;
esac
echo ""
printf "${c_d}Press Enter to continue..."
read dummy
done
}
# ============================================================
# Main
# ============================================================
# Parse flags
CMDS=""
for arg in "$@"; do
case "$arg" in
-verbose|-v) VERBOSE=1 ;;
-json|-j) JSON_OUT=1 ;;
*) CMDS="$CMDS $arg" ;;
esac
done
CMDS=$(echo "$CMDS" | xargs) # trim
if [ -z "$CMDS" ]; then
[ "$VERBOSE" -eq 1 ] && info "Verbose mode enabled"
run_menu
else
# Direct command mode
set -- $CMDS
cmd=$1
shift
case "$cmd" in
start|s) cmd_start ;;
stop|q) cmd_stop ;;
restart|r) cmd_restart ;;
status|st) cmd_status ;;
health|h) cmd_health ;;
log|l) cmd_log "$@" ;;
clear|cl) cmd_clear ;;
config|c) cmd_config ;;
port|p) cmd_port "$@" ;;
root|ro) cmd_root ;;
connections|cn) cmd_connections ;;
auto-start|as) cmd_autostart "$@" ;;
help|--help|-h) cmd_help ;;
*) err "Unknown command: $cmd"; cmd_help ;;
esac
fi