Bypass Password Protected Posts
You are, unfortunately right about the lack of filters, and hacking the core is inevitable. One solutions that seems to work revolves around the sanitize_post_field()
function which fires off a number of interesting filters if its $context
argument is not set to raw
.
The template function that is responsible for deciding whether to show the password field or the content is http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/post-template.php#L556
Notice how nice it would be to void the post_password
? Let's dig in...
See how the post is acquired through the get_post()
function:
http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/post.php#L370
The function contains no filters or actions to hook into, but sanitize_post_field()
contains some filters that can be hooked into, and post_password
goes through that function.
Please refer to the function http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/post.php#L1676
Notice, however, that if $context == 'raw';
the function returns, and none of the filters are fired off. So a little core hack is required that will make the flow of the code reach those filters.
// wp-includes/post.php, line 557
-- $post = get_post($post);
++ $post = get_post($post, null, 'display');
Will force the $context
to be anything but raw
. This will permit to do something along the following lines:
function wpse31407_bypass_password( $value, $post_id, $context ) {
$allowed_ips = array( '127.0.0.1', '255.255.255.255', ... );
if (in_array( $_SERVER['REMOTE_ADDR'], $allowed_ips )) return '';
else return $value;
}
add_filter( 'post_password', 'wpse31407_bypass_password', null, 3 );
This will effectively remove the password, so the test http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/post-template.php#L556 if ( empty($post->post_password) )
is evaluated to true
allowing you to bypass the password. There should be no implications by getting the post with a display
context, as it is used only for the retrieval of the post_password
.
You can as well create your own filter in the core around the post_password_required()
function mentioned above, not to overcomplicate things, maybe. Up to you.
Bypass Private Posts
Now, as for private posts, refer to this bit or query.php http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/query.php#L2649 as this is where the found post get stripped off of private entries.
And you'd be tempted to hook into the http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/query.php#L2625 posts_results
filter and go in and alter the post_status
for each post from private
to public
... however, as you may have seen the get_post_status()
function works on its own copy of a post that it gets from get_post()
... ...which again has no filters but sanitize_post_field()
does, which again requires a $context
of anything but raw
. So again:
// wp-includes/post.php, line 563
-- $post = get_post($post);
++ $post = get_post($post, null, 'display');
And hook into a filter to trick the function into thinking that the post is published by doing this:
function wpse31407_bypass_private( $value, $post_id, $context ) {
$allowed_ips = array( '127.0.0.1', '255.255.255.255', ... );
if (in_array( $_SERVER['REMOTE_ADDR'], $allowed_ips )) return 'publish';
else return $value;
}
add_filter( 'post_status', 'wpse31407_bypass_private', null, 3 );
Or wrap your own filter around the get_post_status()
function.
Conclusion
Once you understand which parts of the core are responsible for blocking the posts you can attempt to modify them however you require, so I hope my long answer helps to an extent, and someone follows up with more tips and perhaps better solutions. Great question, got me digging and thinking.