WordPress Version: 6.2
/**
* Validates a URL for use in a redirect.
*
* Checks whether the $location is using an allowed host, if it has an absolute
* path. A plugin can therefore set or remove allowed host(s) to or from the
* list.
*
* If the host is not allowed, then the redirect is to $fallback_url supplied.
*
* @since 2.8.1
*
* @param string $location The redirect to validate.
* @param string $fallback_url The value to return if $location is not allowed.
* @return string Redirect-sanitized URL.
*/
function wp_validate_redirect($location, $fallback_url = '')
{
$location = wp_sanitize_redirect(trim($location, " \t\n\r\x00\x08\v"));
// Browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'.
if ('//' === substr($location, 0, 2)) {
$location = 'http:' . $location;
}
// In PHP 5 parse_url() may fail if the URL query part contains 'http://'.
// See https://bugs.php.net/bug.php?id=38143
$cut = strpos($location, '?');
$test = $cut ? substr($location, 0, $cut) : $location;
$lp = parse_url($test);
// Give up if malformed URL.
if (false === $lp) {
return $fallback_url;
}
// Allow only 'http' and 'https' schemes. No 'data:', etc.
if (isset($lp['scheme']) && !('http' === $lp['scheme'] || 'https' === $lp['scheme'])) {
return $fallback_url;
}
if (!isset($lp['host']) && !empty($lp['path']) && '/' !== $lp['path'][0]) {
$path = '';
if (!empty($_SERVER['REQUEST_URI'])) {
$path = dirname(parse_url('http://placeholder' . $_SERVER['REQUEST_URI'], PHP_URL_PATH) . '?');
$path = wp_normalize_path($path);
}
$location = '/' . ltrim($path . '/', '/') . $location;
}
// Reject if certain components are set but host is not.
// This catches URLs like https:host.com for which parse_url() does not set the host field.
if (!isset($lp['host']) && (isset($lp['scheme']) || isset($lp['user']) || isset($lp['pass']) || isset($lp['port']))) {
return $fallback_url;
}
// Reject malformed components parse_url() can return on odd inputs.
foreach (array('user', 'pass', 'host') as $component) {
if (isset($lp[$component]) && strpbrk($lp[$component], ':/?#@')) {
return $fallback_url;
}
}
$wpp = parse_url(home_url());
/**
* Filters the list of allowed hosts to redirect to.
*
* @since 2.3.0
*
* @param string[] $hosts An array of allowed host names.
* @param string $host The host name of the redirect destination; empty string if not set.
*/
$allowed_hosts = (array) apply_filters('allowed_redirect_hosts', array($wpp['host']), isset($lp['host']) ? $lp['host'] : '');
if (isset($lp['host']) && (!in_array($lp['host'], $allowed_hosts, true) && strtolower($wpp['host']) !== $lp['host'])) {
$location = $fallback_url;
}
return $location;
}