OneWheelGeek

OneWheelGeek / kill-subscription.sh

Last active 5 months ago

Like 0

OneWheelGeek revised this gist 5 months ago · bd128cd

1 file changed, 85 insertions, 193 deletions

kill-subscription.sh

Diff is too large to be shown

OneWheelGeek revised this gist 5 months ago · 3d9d5c0

No changes

OneWheelGeek revised this gist 5 months ago · 6a12276

1 file changed, 110 insertions, 60 deletions

kill-subscription.sh

Diff is too large to be shown

OneWheelGeek revised this gist 5 months ago · bb7cafe

1 file changed, 292 insertions, 4 deletions

kill-subscription.sh
@@ -1,4 +1,292 @@
1 - #!/bin/bash
2 - sed -i.bak "/No valid subscription/,+20 s/^/\/\//" \
3 - /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
4 - systemctl restart pveproxy
1 + #!/usr/bin/env bash
2 + set -Eeuo pipefail
3 +
4 + # proxmox-subscription-popup.sh
5 + #
6 + # Safe Proxmox VE 9 popup suppressor with:
7 + # - specific patch only
8 + # - no repair unless --repair is passed
9 + # - colored output
10 + # - backup before patch
11 + # - automatic rollback if patch verification fails
12 + #
13 + # Usage:
14 + # sudo bash proxmox-subscription-popup.sh
15 + # sudo bash proxmox-subscription-popup.sh --undo
16 + # sudo bash proxmox-subscription-popup.sh --repair
17 + # sudo bash proxmox-subscription-popup.sh --status
18 +
19 + SCRIPT_NAME="$(basename "$0")"
20 + JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
21 + STATE_DIR="/root/.proxmox-subscription-popup"
22 + BACKUP_FILE="${STATE_DIR}/proxmoxlib.js.bak"
23 + PATCH_FILE="${STATE_DIR}/subscription-popup.patch"
24 +
25 + DO_REPAIR=0
26 + DO_UNDO=0
27 + DO_STATUS=0
28 +
29 + for arg in "$@"; do
30 + case "$arg" in
31 + --repair) DO_REPAIR=1 ;;
32 + --undo) DO_UNDO=1 ;;
33 + --status) DO_STATUS=1 ;;
34 + -h|--help)
35 + cat <<'EOF'
36 + Usage:
37 + sudo bash proxmox-subscription-popup.sh Apply the patch
38 + sudo bash proxmox-subscription-popup.sh --undo Restore backup if present
39 + sudo bash proxmox-subscription-popup.sh --repair Reinstall owning package, restart proxy
40 + sudo bash proxmox-subscription-popup.sh --status Show current state
41 + EOF
42 + exit 0
43 + ;;
44 + *)
45 + echo "Unknown argument: $arg" >&2
46 + exit 2
47 + ;;
48 + esac
49 + done
50 +
51 + if [[ "${EUID}" -ne 0 ]]; then
52 + echo "Please run as root." >&2
53 + exit 1
54 + fi
55 +
56 + mkdir -p "$STATE_DIR"
57 +
58 + if [[ -t 1 ]]; then
59 + C_RESET=$'\033[0m'
60 + C_BOLD=$'\033[1m'
61 + C_DIM=$'\033[2m'
62 + C_RED=$'\033[1;31m'
63 + C_GREEN=$'\033[1;32m'
64 + C_YELLOW=$'\033[1;33m'
65 + C_BLUE=$'\033[1;34m'
66 + C_MAGENTA=$'\033[1;35m'
67 + C_CYAN=$'\033[1;36m'
68 + else
69 + C_RESET=""
70 + C_BOLD=""
71 + C_DIM=""
72 + C_RED=""
73 + C_GREEN=""
74 + C_YELLOW=""
75 + C_BLUE=""
76 + C_MAGENTA=""
77 + C_CYAN=""
78 + fi
79 +
80 + say() { printf "%b\n" "$*"; }
81 + info() { say "${C_CYAN}▶${C_RESET} $*"; }
82 + ok() { say "${C_GREEN}✔${C_RESET} $*"; }
83 + warn() { say "${C_YELLOW}⚠${C_RESET} $*"; }
84 + fail() { say "${C_RED}✖${C_RESET} $*" >&2; }
85 + title() { say "${C_BOLD}${C_MAGENTA}$*${C_RESET}"; }
86 +
87 + restart_proxy() {
88 + info "Restarting pveproxy..."
89 + systemctl restart pveproxy
90 + ok "pveproxy restarted"
91 + }
92 +
93 + show_browser_hint() {
94 + say
95 + say "${C_BOLD}Browser refresh:${C_RESET} hard refresh the UI after this."
96 + say "Mac: ${C_DIM}Cmd+Shift+R${C_RESET}"
97 + say "Other: ${C_DIM}Ctrl+Shift+R${C_RESET}"
98 + say
99 + }
100 +
101 + detect_owner_pkg() {
102 + dpkg -S "$JS_FILE" 2>/dev/null | head -n1 | cut -d: -f1
103 + }
104 +
105 + is_proxmox() {
106 + command -v pveversion >/dev/null 2>&1
107 + }
108 +
109 + version_major() {
110 + if ! command -v pveversion >/dev/null 2>&1; then
111 + return 1
112 + fi
113 + pveversion | sed -n 's/^pve-manager\/\([0-9]\+\)\..*/\1/p' | head -n1
114 + }
115 +
116 + is_patched() {
117 + grep -Fq "orig_cmd(); return;" "$JS_FILE"
118 + }
119 +
120 + has_expected_original() {
121 + grep -Fq "if (data.status.toLowerCase() !== 'active')" "$JS_FILE" &&
122 + grep -Fq "Ext.Msg.show({" "$JS_FILE"
123 + }
124 +
125 + write_patch_file() {
126 + cat > "$PATCH_FILE" <<'EOF'
127 + --- proxmoxlib.js.orig
128 + +++ proxmoxlib.js
129 + @@ -1,7 +1,8 @@
130 + - checked_command: function(orig_cmd) {
131 + + checked_command: function(orig_cmd) {
132 + + orig_cmd(); return;
133 + Proxmox.Utils.API2Request({
134 + url: '/nodes/localhost/subscription',
135 + method: 'GET',
136 + failure: function(response, opts) {
137 + Ext.Msg.alert(gettext('Error'), response.htmlStatus);
138 + },
139 + EOF
140 + }
141 +
142 + status() {
143 + title "Proxmox subscription popup status"
144 +
145 + if ! is_proxmox; then
146 + fail "This does not look like a Proxmox host."
147 + exit 1
148 + fi
149 +
150 + local major
151 + major="$(version_major || true)"
152 + if [[ -n "$major" ]]; then
153 + info "Detected Proxmox major version: ${C_BOLD}${major}${C_RESET}"
154 + fi
155 +
156 + if [[ ! -f "$JS_FILE" ]]; then
157 + fail "JS file not found: $JS_FILE"
158 + exit 1
159 + fi
160 +
161 + local owner
162 + owner="$(detect_owner_pkg || true)"
163 + if [[ -n "$owner" ]]; then
164 + info "Owning package: ${C_BOLD}${owner}${C_RESET}"
165 + fi
166 +
167 + if is_patched; then
168 + ok "Popup suppression patch appears to be installed."
169 + else
170 + warn "Popup suppression patch does not appear to be installed."
171 + fi
172 +
173 + if [[ -f "$BACKUP_FILE" ]]; then
174 + info "Backup present: ${C_BOLD}${BACKUP_FILE}${C_RESET}"
175 + else
176 + warn "No backup found in ${STATE_DIR}"
177 + fi
178 + }
179 +
180 + repair() {
181 + title "Repairing Proxmox web UI file"
182 +
183 + [[ -f "$JS_FILE" ]] || { fail "Missing file: $JS_FILE"; exit 1; }
184 +
185 + local owner
186 + owner="$(detect_owner_pkg || true)"
187 + [[ -n "$owner" ]] || { fail "Could not determine owning package for $JS_FILE"; exit 1; }
188 +
189 + info "Reinstalling package: ${C_BOLD}${owner}${C_RESET}"
190 + apt-get update
191 + apt-get install --reinstall -y "$owner"
192 +
193 + [[ -f "$JS_FILE" ]] || { fail "File still missing after reinstall"; exit 1; }
194 +
195 + restart_proxy
196 + ok "Repair complete"
197 + show_browser_hint
198 + }
199 +
200 + undo() {
201 + title "Restoring original file"
202 +
203 + [[ -f "$BACKUP_FILE" ]] || { fail "No backup found at $BACKUP_FILE"; exit 1; }
204 + [[ -f "$JS_FILE" ]] || { fail "Target file missing: $JS_FILE"; exit 1; }
205 +
206 + cp -f "$BACKUP_FILE" "$JS_FILE"
207 + ok "Original file restored from backup"
208 +
209 + restart_proxy
210 + show_browser_hint
211 + }
212 +
213 + apply_patch() {
214 + title "Applying safe Proxmox popup patch"
215 +
216 + [[ -f "$JS_FILE" ]] || { fail "Missing file: $JS_FILE"; exit 1; }
217 +
218 + if ! is_proxmox; then
219 + fail "This does not look like a Proxmox host."
220 + exit 1
221 + fi
222 +
223 + local major
224 + major="$(version_major || true)"
225 + if [[ "$major" != "9" ]]; then
226 + warn "This script was requested for Proxmox 9. Detected major version: ${major:-unknown}"
227 + warn "Continuing only if the target code still matches exactly."
228 + else
229 + ok "Detected Proxmox VE 9"
230 + fi
231 +
232 + if is_patched; then
233 + ok "Patch is already installed. Nothing to do."
234 + show_browser_hint
235 + return 0
236 + fi
237 +
238 + if ! has_expected_original; then
239 + fail "The expected original code pattern was not found."
240 + fail "Refusing to patch, because the file layout is not what this script expects."
241 + fail "Use --repair first if the file is damaged, or inspect the current file manually."
242 + exit 1
243 + fi
244 +
245 + if [[ ! -f "$BACKUP_FILE" ]]; then
246 + info "Creating backup at ${C_BOLD}${BACKUP_FILE}${C_RESET}"
247 + cp -a "$JS_FILE" "$BACKUP_FILE"
248 + ok "Backup created"
249 + else
250 + warn "Backup already exists, leaving it untouched"
251 + fi
252 +
253 + local tmp
254 + tmp="$(mktemp)"
255 + cp -a "$JS_FILE" "$tmp"
256 +
257 + write_patch_file
258 +
259 + info "Checking whether patch applies cleanly..."
260 + if ! patch --dry-run "$tmp" "$PATCH_FILE" >/dev/null 2>&1; then
261 + rm -f "$tmp"
262 + fail "Patch dry-run failed. File is not an exact match for this patch."
263 + fail "No changes were made."
264 + exit 1
265 + fi
266 + ok "Patch dry-run succeeded"
267 +
268 + info "Applying patch..."
269 + patch "$JS_FILE" "$PATCH_FILE" >/dev/null
270 + ok "Patch applied"
271 +
272 + if ! is_patched; then
273 + warn "Verification failed after patch; restoring backup"
274 + cp -f "$BACKUP_FILE" "$JS_FILE"
275 + rm -f "$tmp"
276 + fail "Patch did not verify cleanly. Original file restored."
277 + exit 1
278 + fi
279 +
280 + rm -f "$tmp"
281 +
282 + restart_proxy
283 + ok "Subscription popup suppression is in place"
284 + show_browser_hint
285 + }
286 +
287 + case 1 in
288 + $DO_STATUS) status ;;
289 + $DO_UNDO) undo ;;
290 + $DO_REPAIR) repair ;;
291 + *) apply_patch ;;
292 + esac

OneWheelGeek revised this gist 5 months ago · 8bf9b9f

1 file changed, 4 insertions

kill-subscription.sh (file created)
@@ -0,0 +1,4 @@
1 + #!/bin/bash
2 + sed -i.bak "/No valid subscription/,+20 s/^/\/\//" \
3 + /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
4 + systemctl restart pveproxy