@@ -410,59 +410,75 @@ public function getMicroTime()
410410 /**
411411 * Redirect
412412 *
413- * @param string $url
414- * @param int $count_attempts
415- * @param string $type $ type
416- * @param string $responseCode
413+ * @param string $url Target URL for redirection
414+ * @param int $count_attempts Number of redirect attempts (to prevent loops)
415+ * @param string $type Redirect type: REDIRECT_REFRESH, REDIRECT_META, REDIRECT_HEADER (default)
416+ * @param string|int $responseCode HTTP 30x response code
417417 * @return bool|null
418418 * @global string $base_url
419419 * @global string $site_url
420420 */
421- public function sendRedirect ($ url , $ count_attempts = 0 , $ type = '' , $ responseCode = '' )
421+ public function sendRedirect (string $ url , int $ count_attempts = 0 , string $ type = '' , string | int $ responseCode = '' ): ? bool
422422 {
423- $ header = '' ;
424- if (empty ($ url )) {
423+ if (empty ($ url )) {
425424 return false ;
426425 }
427- if ($ count_attempts == 1 ) {
428- // append the redirect count string to the url
429- $ currentNumberOfRedirects = isset ($ _REQUEST ['err ' ]) ? $ _REQUEST ['err ' ] : 0 ;
426+
427+ // Prevent redirect loops
428+ if ($ count_attempts === 1 ) {
429+ $ currentNumberOfRedirects = isset ($ _REQUEST ['err ' ]) ? (int )$ _REQUEST ['err ' ] : 0 ;
430+
430431 if ($ currentNumberOfRedirects > 3 ) {
431432 $ this ->getService ('ExceptionHandler ' )->messageQuit (
432433 'Redirection attempt failed - please ensure the document you \'re trying to redirect to exists. ' .
433- '<p>Redirection URL: <i> ' . $ url . '</i></p> '
434+ '<p>Redirection URL: <i> ' . htmlspecialchars ( $ url) . '</i></p> '
434435 );
435- } else {
436- $ currentNumberOfRedirects += 1 ;
437- if (Str::contains ($ url , '? ' )) {
438- $ url .= "&err= $ currentNumberOfRedirects " ;
439- } else {
440- $ url .= "?err= $ currentNumberOfRedirects " ;
441- }
442436 }
437+
438+ $ currentNumberOfRedirects ++;
439+ $ url .= (str_contains ($ url , '? ' ) ? '& ' : '? ' ) . "err= $ currentNumberOfRedirects " ;
443440 }
441+
442+ // Define redirect header
443+ $ header = '' ;
444444 if ($ type === 'REDIRECT_REFRESH ' ) {
445445 $ header = 'Refresh: 0;URL= ' . $ url ;
446446 } elseif ($ type === 'REDIRECT_META ' ) {
447- $ header = '<META HTTP-EQUIV="Refresh" CONTENT="0; URL= ' . $ url . '" /> ' ;
448- echo $ header ;
447+ echo '<META HTTP-EQUIV="Refresh" CONTENT="0; URL= ' . htmlspecialchars ($ url ) . '" /> ' ;
449448 exit ;
450- } elseif ($ type === 'REDIRECT_HEADER ' || empty ($ type )) {
451- // check if url has /$base_url
452- if (substr ($ url , 0 , strlen (MODX_BASE_URL )) == MODX_BASE_URL ) {
453- // append $site_url to make it work with Location:
454- $ url = MODX_SITE_URL . substr ($ url , strlen (MODX_BASE_URL ));
455- }
456- if (!Str::contains ($ url , "\n" )) {
457- $ header = 'Location: ' . $ url ;
458- } else {
459- $ this ->getService ('ExceptionHandler ' )->messageQuit ('No newline allowed in redirect url. ' );
449+ } else { // default: REDIRECT_HEADER
450+ if (str_contains ($ url , "\n" ) || str_contains ($ url , "\r" )) {
451+ $ this ->getService ('ExceptionHandler ' )->messageQuit ('No newline allowed in redirect URL. ' );
460452 }
453+
454+ if (!str_starts_with ($ url , 'http:// ' ) && !str_starts_with ($ url , 'https:// ' )) {
455+ $ url = rtrim (EVO_SITE_URL , '/ ' ) . '/ ' . ltrim ($ url , '/ ' );
456+ }
457+
458+ $ header = 'Location: ' . $ url ;
461459 }
462- if ($ responseCode && (Str::contains ($ responseCode , '30 ' ))) {
463- header ($ responseCode );
460+
461+ // Handle HTTP response code
462+ $ responseCodes = [
463+ 300 => 'Multiple Choices ' ,
464+ 301 => 'Moved Permanently ' ,
465+ 302 => 'Found ' ,
466+ 303 => 'See Other ' ,
467+ 304 => 'Not Modified ' ,
468+ 305 => 'Use Proxy ' ,
469+ 306 => 'Switch Proxy ' ,
470+ 307 => 'Temporary Redirect ' ,
471+ 308 => 'Permanent Redirect ' ,
472+ ];
473+
474+ $ code = (int )$ responseCode ;
475+ if (!isset ($ responseCodes [$ code ])) {
476+ $ code = 302 ;
464477 }
465478
479+ header ('HTTP/1.1 ' . $ code . ' ' . $ responseCodes [$ code ]);
480+
481+ // Set redirection header if applicable
466482 if (!empty ($ header )) {
467483 header ($ header );
468484 }
0 commit comments