WordPress failing to redirect with protected Posts

I recently had a fairly obscure problem on a WordPress site and I wanted to write about it on the off chance it saves somebody else a few frustrating hours.

The problem

Whenever a password was entered into a protected posts password box the form would submit successfully, start to redirect, then die on a blank screen. If the webpage was refreshed the password protected post was unlocked (indicating it was likely a redirect problem not an auth problem).

The Cause

It turns out that WordPress ends up using a helper function called wp_get_raw_referer() to retrieve the address of the previous page. If we take a look at it we see it first checks for a WordPress custom variable called ‘_wp_http_referer’ then the default $_SERVER variable ‘HTTP_REFERER’ before retiring false if neither are set. All perfectly reasonable.

How this affects password protected posts?

The default WordPress password form on posts doesn’t contain the custom ‘_wp_http_referer’ field meaning WordPress is always relying on ‘HTTP_REFERER’ for redirecting. The problem with this is that ‘HTTP_REFERER’ is famously unreliable as it’s set by the user agent, meaning it can be wrong or even missing altogether, as in my case. When navigating from an HTTPS to HTTP page web browsers don’t set the ‘HTTP_REFERER’ field for ancient security reasons (there is a work around in modern browsers involving meta tags). So, as the password protected page redirects you through the WordPress login page to handle the form, if you’re WordPress admin is behind SSL (‘FORCE_ADMIN_SSL includes the login page) but your front-end isn’t (because you’re serving ads or whatnot) the redirect on the password protect page dies on a blank screen as the ‘HTTP_REFERER’ field is stripped out after the wp-login page.

The Solution

Luckily, the fix is easy. We just need to add the ‘_wp_http_referer’ field to the password protect form then we don’t rely on ‘HTTP_REFERER’ at all. Simply add this to your functions.php file and it will do just that.

/**
 * Add a redirect field for password protect forms when
 * HTTP_REFERER isn't set
 *
 * @access public
 * @param string $form_html
 * @return string
 */
public function wpa_add__wp_http_referer( $form_html ) {
 if ( empty( $_SERVER['HTTP_REFERER'] ) ) {
	 $form_html = str_ireplace( '</form>', '<input type="hidden" name="_wp_http_referer" value="' . esc_url( get_the_permalink() ) . '"></form>', $form_html );
 }

 return $form_html;
}
add_filter( 'the_password_form', array( $this, 'wpa_add__wp_http_referer' ), 10, 1 );

It’s fairly obscure I admit but hopefully it will help someone and save them a few hours debugging!

Rename and clean WordPress media filenames

For the most part WordPress does a decent job of renaming and cleaning up attachment media filenames, but sometimes it’s just not quite good enough. When it comes to UTF8 characters or accents it tends to just ignore them as they’re (mostly) considered web safe.

This can become an issue when third party services crawl your site and struggle with the encoding e.g. Facebook’s Sharing Debugger which is where I had trouble. Of course it’s also not great for SEO. In an Ideal world you want the featured image filename to closely mirror the post title, not be “Screenshot 2016-08-05T22:03:22.jpg”.

Cleaner Filenames

If all you want to do is clean up your filenames and remove UTF8 characters and accents then just place this code in your functions.php (will only clean up all new filenames). This code was originally posted by Vaughn Royko.

Update: I’ve also released it as a super simple plugin for those that prefer it. Check it out on WordPress.org here.


/**
 * Produces cleaner filenames for uploads
 *
 * @param  string $filename
 * @return string
 */
function wpartisan_sanitize_file_name( $filename ) {

	$sanitized_filename = remove_accents( $filename ); // Convert to ASCII

	// Standard replacements
	$invalid = array(
		' '   => '-',
		'%20' => '-',
		'_'   => '-',
	);
	$sanitized_filename = str_replace( array_keys( $invalid ), array_values( $invalid ), $sanitized_filename );

	$sanitized_filename = preg_replace('/[^A-Za-z0-9-\. ]/', '', $sanitized_filename); // Remove all non-alphanumeric except .
	$sanitized_filename = preg_replace('/\.(?=.*\.)/', '', $sanitized_filename); // Remove all but last .
	$sanitized_filename = preg_replace('/-+/', '-', $sanitized_filename); // Replace any more than one - in a row
	$sanitized_filename = str_replace('-.', '.', $sanitized_filename); // Remove last - if at the end
	$sanitized_filename = strtolower( $sanitized_filename ); // Lowercase

	return $sanitized_filename;
}

add_filter( 'sanitize_file_name', 'wpartisan_sanitize_file_name', 10, 1 );

So what does it do:

File: ~My WordPress Upload~.jpg
Default WordPress: My-WordPress-Upload.jpg
Custom Solution: my-wordpress-upload.jpg

File: ÐÕçument full of $$$.pdf
Default WordPress: ÐÕçument-full-of-.pdf
Custom Solution: document-full-of.pdf

File: Really%20Ugly%20Filename-_-That_-_Is_Too Common…..png
Default WordPress: Really-Ugly-Filename-_-That_-_Is_Too-Common…..png
Custom Solution: really-ugly-filename-that-is-too-common.png

Complete SEO Solution

If you want a more complete solution we’re currently develop a plugin to do just that. It’ll be able to:

– Sanitize and clean all new media upload filenames
– Optionally sanitize and clean all existing media filenames
– Allow manual renaming of all existing media
– Auto renaming of filenames based on post title, even when the post is updated