Last active 1 month ago

Revision bd128cd5694d52497a1d36f4fa8e9e1e04b15eac

kill-subscription.sh Raw
1#!/usr/bin/env bash
2set -Eeuo pipefail
3
4# proxmox-subscription-popup.sh
5#
6# Safe-ish Proxmox VE 9 subscription popup suppressor using sed.
7#
8# Usage:
9# sudo bash proxmox-subscription-popup.sh
10# sudo bash proxmox-subscription-popup.sh --status
11# sudo bash proxmox-subscription-popup.sh --undo
12# sudo bash proxmox-subscription-popup.sh --repair
13
14JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
15STATE_DIR="/root/.proxmox-subscription-popup"
16BACKUP_FILE="${STATE_DIR}/proxmoxlib.js.bak"
17
18DO_STATUS=0
19DO_UNDO=0
20DO_REPAIR=0
21
22for arg in "$@"; do
23 case "$arg" in
24 --status) DO_STATUS=1 ;;
25 --undo) DO_UNDO=1 ;;
26 --repair) DO_REPAIR=1 ;;
27 -h|--help)
28 cat <<'EOF'
29Usage:
30 sudo bash proxmox-subscription-popup.sh
31 Apply popup suppression patch
32
33 sudo bash proxmox-subscription-popup.sh --status
34 Show status
35
36 sudo bash proxmox-subscription-popup.sh --undo
37 Restore original file
38
39 sudo bash proxmox-subscription-popup.sh --repair
40 Reinstall the owning package
41EOF
42 exit 0
43 ;;
44 *)
45 echo "Unknown argument: $arg" >&2
46 exit 2
47 ;;
48 esac
49done
50
51if [ "$(id -u)" -ne 0 ]; then
52 echo "Please run as root." >&2
53 exit 1
54fi
55
56mkdir -p "$STATE_DIR"
57
58if [[ -t 1 ]]; then
59 C_RESET=$'\033[0m'
60 C_BOLD=$'\033[1m'
61 C_RED=$'\033[1;31m'
62 C_GREEN=$'\033[1;32m'
63 C_YELLOW=$'\033[1;33m'
64 C_CYAN=$'\033[1;36m'
65 C_MAGENTA=$'\033[1;35m'
66else
67 C_RESET=""
68 C_BOLD=""
69 C_RED=""
70 C_GREEN=""
71 C_YELLOW=""
72 C_CYAN=""
73 C_MAGENTA=""
74fi
75
76say() { printf "%b\n" "$*"; }
77info() { say "${C_CYAN}${C_RESET} $*"; }
78ok() { say "${C_GREEN}${C_RESET} $*"; }
79warn() { say "${C_YELLOW}${C_RESET} $*"; }
80fail() { say "${C_RED}${C_RESET} $*" >&2; }
81title() { say "${C_BOLD}${C_MAGENTA}$*${C_RESET}"; }
82
83trap 'fail "Script failed on line ${LINENO}"' ERR
84
85require_file() {
86 [[ -f "$JS_FILE" ]] || {
87 fail "Missing file: $JS_FILE"
88 exit 1
89 }
90}
91
92detect_owner_pkg() {
93 dpkg -S "$JS_FILE" 2>/dev/null | head -n1 | cut -d: -f1
94}
95
96restart_proxy() {
97 info "Restarting pveproxy..."
98 systemctl restart pveproxy
99 ok "pveproxy restarted"
100}
101
102show_hint() {
103 say
104 say "${C_BOLD}Hard refresh the browser afterwards:${C_RESET}"
105 say " Mac: Cmd+Shift+R"
106 say " Other: Ctrl+Shift+R"
107 say
108}
109
110is_patched() {
111 grep -Fq "orig_cmd();" "$JS_FILE" &&
112 grep -Fq "return;" "$JS_FILE"
113}
114
115has_expected_original() {
116 grep -Fq "checked_command: function (orig_cmd) {" "$JS_FILE" &&
117 grep -Fq "url: '/nodes/localhost/subscription'" "$JS_FILE" &&
118 grep -Fq "res.data.status.toLowerCase() !== 'active'" "$JS_FILE"
119}
120
121status() {
122 title "Proxmox subscription popup status"
123
124 require_file
125
126 if has_expected_original; then
127 ok "Expected original code pattern found"
128 else
129 warn "Expected original code pattern NOT found"
130 fi
131
132 if is_patched; then
133 ok "Patch appears to be installed"
134 else
135 warn "Patch does not appear to be installed"
136 fi
137
138 if [[ -f "$BACKUP_FILE" ]]; then
139 ok "Backup exists at $BACKUP_FILE"
140 else
141 warn "No backup exists"
142 fi
143}
144
145undo() {
146 title "Restoring original file"
147
148 [[ -f "$BACKUP_FILE" ]] || {
149 fail "No backup file found at $BACKUP_FILE"
150 exit 1
151 }
152
153 cp -f "$BACKUP_FILE" "$JS_FILE"
154 ok "Original file restored"
155
156 restart_proxy
157 show_hint
158}
159
160repair() {
161 title "Repairing Proxmox UI"
162
163 local owner
164 owner="$(detect_owner_pkg)"
165
166 [[ -n "$owner" ]] || {
167 fail "Could not determine owning package"
168 exit 1
169 }
170
171 info "Reinstalling package: $owner"
172 apt-get update
173 apt-get install --reinstall -y "$owner"
174
175 restart_proxy
176 ok "Repair complete"
177 show_hint
178}
179
180apply_patch() {
181 title "Applying subscription popup suppression"
182
183 require_file
184
185 if is_patched; then
186 ok "Patch already appears to be installed"
187 show_hint
188 return 0
189 fi
190
191 if ! has_expected_original; then
192 fail "Expected original code pattern not found."
193 fail "Refusing to patch because the file does not look like the expected Proxmox VE 9 file."
194 fail "Run with --repair first if the file is damaged."
195 exit 1
196 fi
197
198 if [[ ! -f "$BACKUP_FILE" ]]; then
199 info "Creating backup at $BACKUP_FILE"
200 cp -a "$JS_FILE" "$BACKUP_FILE"
201 ok "Backup created"
202 else
203 warn "Backup already exists; leaving it untouched"
204 fi
205
206 info "Inserting short-circuit into checked_command()"
207
208 sed -i '/checked_command: function (orig_cmd) {/a\
209 orig_cmd();\
210 return;' "$JS_FILE"
211
212 if ! is_patched; then
213 warn "Patch verification failed; restoring backup"
214 cp -f "$BACKUP_FILE" "$JS_FILE"
215 fail "Patch did not verify cleanly. Original restored."
216 exit 1
217 fi
218
219 ok "Patch successfully applied"
220
221 info "Snippet after patch:"
222 grep -A4 'checked_command: function (orig_cmd)' "$JS_FILE" || true
223
224 restart_proxy
225 ok "Subscription popup suppression is active"
226 show_hint
227}
228
229case 1 in
230 $DO_STATUS) status ;;
231 $DO_UNDO) undo ;;
232 $DO_REPAIR) repair ;;
233 *) apply_patch ;;
234esac