I think your problem here is the esc_url() function which is used to sanitize a lot of the URLs used in wp-core.
If you have a look at the function definition in formatting.php you’ll see that the regex in line 2627 is filtering out [
and ]
.
But fortunately you can also see that in line 2656 there is a filter supplied which allows you to overwrite this behavior. So you’ll be able to fix this through attaching a custom function to the clean_url
filter.
** EDIT2 **
It seems like redirect URLs are sanitized in another function. Fortunately this is a pluggable function, so we are able to overwrite it. I edited the code to take this into account. You can use the following code snippet through creating a mu-plugins
folder inside your wp-content
folder and placing a PHP file (I named mine fix_ipv6_siteurl.php
) inside that folder.
<?php
add_filter('clean_url', 'wpse_120978_custom_esc_url', 10, 3);
function wpse_120978_custom_esc_url( $url, $original_url, $_context ) {
if( !strpos($original_url, '[') ) {
return $url;
}
$url = $original_url;
if ( '' == $url )
return $url;
$url = preg_replace('|[^a-z0-9-[]~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
$strip = array('%0d', '%0a', '%0D', '%0A');
$url = _deep_replace($strip, $url);
$url = str_replace(';//', '://', $url);
/* If the URL doesn't appear to contain a scheme, we
* presume it needs http:// appended (unless a relative
* link starting with / or a php file).
*/
if ( strpos($url, ':') === false &&
substr( $url, 0, 1 ) != "https://wordpress.stackexchange.com/" && substr( $url, 0, 1 ) != '#' && !preg_match('/^[a-z0-9-]+?\.php/i', $url) )
$url="http://" . $url;
// Replace ampersands and single quotes only when displaying.
if ( 'display' == $_context ) {
$url = wp_kses_normalize_entities( $url );
$url = str_replace( '&', '&', $url );
$url = str_replace( "'", ''', $url );
}
if ( !is_array($protocols) )
$protocols = array ('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn');
if ( wp_kses_bad_protocol( $url, $protocols ) != $url )
return '';
return $url;
}
if ( !function_exists('wp_sanitize_redirect') ) :
/**
* Sanitizes a URL for use in a redirect.
*
* @since 2.3
*
* @return string redirect-sanitized URL
**/
function wp_sanitize_redirect($location) {
$location = preg_replace('|[^a-z0-9-[]~+_.?#=&;,/:%!]|i', '', $location);
$location = wp_kses_no_null($location);
// remove %0d and %0a from location
$strip = array('%0d', '%0a', '%0D', '%0A');
$location = _deep_replace($strip, $location);
return $location;
}
endif;
(The previous code from the functions.php can be removed.)