diff --git a/nginx/srv1361159.hstgr.cloud b/nginx/srv1361159.hstgr.cloud
index 1ea5f43..6cb19e4 100644
--- a/nginx/srv1361159.hstgr.cloud
+++ b/nginx/srv1361159.hstgr.cloud
@@ -65,6 +65,12 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
+ # รูปใต้ /Game/img/ (ยกเว้น characters ด้านบน) — ห้าม try_files ไป index.html เมื่อไม่เจอไฟล์ (ไม่งั้น ได้ HTML แล้วแตกเงียบ ๆ)
+ location ^~ /Game/img/ {
+ alias /var/www/html/Game/public/img/;
+ try_files $uri =404;
+ access_log off;
+ }
# Game — API ต้องรับ body ใหญ่ (รูปพื้นหลัง base64) จึงตั้ง 20M
location /Game/api/ {
client_max_body_size 20M;
diff --git a/www/html/Admin/admin.js b/www/html/Admin/admin.js
index 6d1b43b..ec38c39 100644
--- a/www/html/Admin/admin.js
+++ b/www/html/Admin/admin.js
@@ -3357,9 +3357,33 @@
return pathPart.replace(/ /g, '%20') + query;
}
+ function decodeAssetUrlPercentRuns(t) {
+ var s = String(t || '');
+ var q = s.indexOf('?');
+ var base = q === -1 ? s : s.slice(0, q);
+ var query = q === -1 ? '' : s.slice(q);
+ for (var i = 0; i < 2; i++) {
+ try {
+ var d = decodeURIComponent(base);
+ if (d === base) break;
+ base = d;
+ } catch (e) {
+ break;
+ }
+ }
+ return base + query;
+ }
+
+ function normalizeGameAssetUrlForWebAdmin(t) {
+ var s = String(t || '');
+ s = s.replace(/^\/Game\/public\/img\//i, '/Game/img/');
+ s = s.replace(/^Game\/public\/img\//i, 'Game/img/');
+ return s;
+ }
+
/** ให้สอดคล้องกับ server sanitizeGauntletAssetUrl + กัน placeholder .... */
function normalizeMegaVirusAssetUrl(v) {
- var t = v != null ? String(v).trim().replace(/\/+$/, '') : '';
+ var t = v != null ? normalizeGameAssetUrlForWebAdmin(decodeAssetUrlPercentRuns(String(v).trim())).replace(/\/+$/, '') : '';
if (!t || t.length > 500) return '';
if (/\.{4,}/.test(t)) return '';
if (/[\t\n\r<>"'`]/.test(t)) return '';
diff --git a/www/html/Admin/index.html b/www/html/Admin/index.html
index 304806e..64d0126 100644
--- a/www/html/Admin/index.html
+++ b/www/html/Admin/index.html
@@ -620,9 +620,9 @@
Fallback ใช้เมื่อช่อง P ว่าง หรือ รูปต่อที่นั่งโหลดไม่สำเร็จ (404) · ห้ามใส่จุดสี่จุดจาก placeholder (....) — ต้องเป็น path ไฟล์จริง · English: Fallback when a P slot is empty or its image fails to load; .... is rejected.
Fallback ใช้เมื่อช่อง P ว่าง หรือ รูปต่อที่นั่งโหลดไม่สำเร็จ (404) · ใช้ URL แบบ /Game/img/... เท่านั้น — ไม่ใช่ /Game/public/img/... (public ไม่ปรากฏใน URL) · English: Use /Game/img/... only, not /Game/public/img/....