#!/bin/sh
# rpcd exec plugin: bridges LuCI (ubus, ACL-gated by acl.d/luci-app-ednovas)
# to the loopback-only agent API. Modern LuCI calls ubus object "ednovas"
# method "api" with {path, method, body}; the agent itself is unreachable
# from the network, so a valid router login is the only way in.

. /usr/share/libubox/jshn.sh

case "$1" in
list)
	echo '{"api":{"path":"str","method":"str","body":"str"}}'
	;;
call)
	case "$2" in
	api)
		read -r input
		json_load "$input" 2>/dev/null
		json_get_var path path
		json_get_var method method
		json_get_var body body

		# Only agent API paths, conservative charset (no spaces, quotes or
		# escapes can reach the URL).
		case "$path" in
		/api/*) ;;
		*) echo '{"error":"invalid path"}'; exit 0 ;;
		esac
		case "$path" in
		*[!A-Za-z0-9/_?=\&.-]*) echo '{"error":"invalid path"}'; exit 0 ;;
		esac

		port="$(uci -q get ednovas.main.api_port)"
		sep='?'
		case "$path" in *\?*) sep='&' ;; esac
		url="http://127.0.0.1:${port:-9091}${path}${sep}flat=1"

		out=""
		if [ "$method" = "POST" ]; then
			tmp="/tmp/.ednovas-rpc.$$"
			# NOT ${body:-{}}: POSIX ends the expansion at the FIRST '}', so
			# that form appends a stray '}' to every non-empty body.
			[ -n "$body" ] || body='{}'
			printf '%s' "$body" > "$tmp"
			if command -v curl >/dev/null 2>&1; then
				out="$(curl -s -m 50 -X POST -H 'Content-Type: application/json' --data-binary @"$tmp" "$url" 2>/dev/null)"
			else
				out="$(uclient-fetch -q -O - --timeout=50 --post-file="$tmp" "$url" 2>/dev/null)"
			fi
			rm -f "$tmp"
		else
			if command -v curl >/dev/null 2>&1; then
				out="$(curl -s -m 30 "$url" 2>/dev/null)"
			else
				out="$(uclient-fetch -q -O - --timeout=30 "$url" 2>/dev/null)"
			fi
		fi
		[ -n "$out" ] || out='{"error":"服务未运行或未响应，请稍后重试（或 SSH 执行 /etc/init.d/ednovas restart）"}'
		printf '%s\n' "$out"
		;;
	esac
	;;
esac
