| @@ -1251,10 +1251,25 @@ | ||
| 1251 | 1251 | // A token of its own for this page. An earlier token stays valid until it |
| 1252 | 1252 | // expires, so a refresh while the solver runs does not break it. |
| 1253 | 1253 | $challenge_nonce = $this->issue_challenge_token(); |
| 1254 | 1254 | |
| 1255 | - // Get current URL for redirect after verification | |
| 1256 | - $current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ?? '' ) ) . sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '/' ) ); | |
| 1255 | + /* | |
| 1256 | + * Where to send the visitor once the challenge is solved: the page they | |
| 1257 | + * asked for, as they asked for it. The target used to go through | |
| 1258 | + * sanitize_text_field(), which deletes every %XX octet, so a visitor who | |
| 1259 | + * asked for /categor%C3%ADa/ landed on /categora/, a 404, on every page | |
| 1260 | + * whose address has an accent or a non-Latin letter (measured on 1 oct | |
| 1261 | + * 2026 against 3.0.1). The host only picks where the visitor lands: | |
| 1262 | + * process_challenge_response() validates it against the site's own | |
| 1263 | + * before redirecting and falls back to the home page. | |
| 1264 | + */ | |
| 1265 | + $request_uri = Vigilante_IP_Utils::request_uri(); | |
| 1266 | + | |
| 1267 | + if ( '' === $request_uri || '/' !== $request_uri[0] ) { | |
| 1268 | + $request_uri = '/'; | |
| 1269 | + } | |
| 1270 | + | |
| 1271 | + $current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ?? '' ) ) . $request_uri; | |
| 1257 | 1272 | |
| 1258 | 1273 | // Asset URLs (external files for CSP compatibility) |
| 1259 | 1274 | $css_url = VIGILANTE_ASSETS_URL . 'css/under-attack-challenge.css?ver=' . VIGILANTE_VERSION; |
| 1260 | 1275 | $js_url = VIGILANTE_ASSETS_URL . 'js/under-attack-challenge.js?ver=' . VIGILANTE_VERSION; |