Files
wordpress-skeleton/blog/wp-content/plugins/pushpress/class-pushpress.php
T
2010-03-03 12:59:55 -05:00

287 lines
7.5 KiB
PHP
Executable File

<?php
class PuSHPress {
var $hubs;
var $http_timeout;
var $http_user_agent;
function PuSHPress( ) { }
function init( ) {
// Let other plugins modify various options
$this->hubs = apply_filters( 'pushpress_hubs', array(
get_bloginfo( 'url' ) . '/?pushpress=hub'
) );
$this->http_timeout = apply_filters( 'pushpress_http_timeout', 5 );
$this->http_user_agent = apply_filters( 'pushpress_http_timeout', 'WordPress/PuSHPress ' . PUSHPRESS_VERSION );
// Make sure the hubs get listed in the RSS2 and Atom feeds
add_action( 'rss2_head', array( &$this, 'hub_link_rss2' ) );
add_action( 'atom_head', array( &$this, 'hub_link_atom' ) );
// Make the built in hub URL work
add_action( 'parse_request', array( &$this, 'parse_wp_request' ) );
// Send out fat pings when a new post is published
add_action( 'publish_post', array( &$this, 'publish_post' ) );
}
function add_callback( $feed_url, $callback, $secret ) {
$subs = get_option( 'pushpress_subscribers' );
$subs[$feed_url][$callback] = array(
'is_active' => TRUE,
'secret' => $secret,
'start_date' => gmdate( 'Y-m-d H:i:s' ),
'unsubscribe' => FALSE,
);
update_option( 'pushpress_subscribers', $subs );
}
function check_required_fields( ) {
// required fields must have values
if ( empty( $_POST['hub_callback'] ) )
$this->return_error( 'hub.callback is empty' );
if ( empty( $_POST['hub_mode'] ) )
$this->return_error( 'hub.mode is empty' );
if ( empty( $_POST['hub_topic'] ) )
$this->return_error( 'hub.topic is empty' );
if ( empty( $_POST['hub_verify'] ) )
$this->return_error( 'hub.verify is empty' );
// mode has a small set of valid values
$_POST['hub_mode'] = strtolower( $_POST['hub_mode'] );
if ( $_POST['hub_mode'] != 'subscribe' ) {
if ( $_POST['hub_mode'] != 'unsubscribe' ) {
$this->return_error( 'hub.mode is invalid' );
}
}
}
function check_topic( ) {
$allowed = FALSE;
if ( $_POST['hub_topic'] == get_bloginfo( 'rss2_url' ) )
$allowed = TRUE;
if ( $_POST['hub_topic'] == get_bloginfo( 'atom_url' ) )
$allowed = TRUE;
if ( $allowed === FALSE ) {
do_action( 'pushpress_topic_failure' );
$msg = 'hub_topic - ' . $_POST['hub_topic'];
$msg .= ' - is value is not allowed. ';
$msg .= 'You may only subscribe to ' . get_bloginfo( 'rss2_url' );
$msg .= ' or ' . get_bloginfo( 'atom_url' );
$this->return_error( $msg );
}
}
function get_subscribers( $feed_url ) {
/*
array(
_rss_url_ => array(
_callback_url_ => array(
'is_active' => true/false,
'secret' => _string_,
'start_date' => _date_gmt_,
'unsubscribe' => true/false
)
),
_atom_url_ => array(
_callback_url_ => array(
'is_active' => true/false,
'secret' => _string_,
'start_date' => _date_gmt_,
'unsubscribe' => true/false
)
)
)
*/
$subs = get_option( 'pushpress_subscribers' );
if ( isset( $subs[$feed_url] ) ) {
return $subs[$feed_url];
} else {
return FALSE;
}
}
function hub_link_atom( ) {
foreach ( (array) $this->hubs as $hub ) {
echo "\t<link rel='hub' href='{$hub}' />\n";
}
}
function hub_link_rss2( ) {
foreach ( (array) $this->hubs as $hub ) {
echo "\t<atom:link rel='hub' href='{$hub}'/>\n";
}
}
function hub_request( ) {
$this->check_required_fields( );
$this->check_topic( );
if ( $_POST['hub_mode'] == 'unsubscribe' ) {
do_action( 'pushpress_unsubscribe_request' );
$this->unsubscribe_callback( $_POST['hub_topic'], $_POST['hub_callback'] );
$this->return_ok( );
}
if ( $_POST['hub_mode'] == 'subscribe' ) {
do_action( 'pushpress_subscribe_request' );
$this->verify_request( );
}
$subs = $this->get_subscribers( $_POST['hub_topic'] );
$secret = '';
if ( !empty( $_POST['hub_secret'] ) )
$secret = $_POST['hub_secret'];
$this->add_callback( $_POST['hub_topic'], $_POST['hub_callback'], $secret );
$this->return_ok( );
}
function parse_wp_request( $wp ) {
if ( !empty( $_GET['pushpress'] ) && $_GET['pushpress'] == 'hub' ) {
$this->hub_request( );
exit;
}
}
function publish_post( $post_id ) {
$subs = $this->get_subscribers( get_bloginfo( 'rss2_url' ) );
foreach ( (array) $subs as $callback => $data ) {
if ( $data['is_active'] == FALSE )
continue;
$this->schedule_ping( $callback, $post_id, 'rss2', $data['secret'] );
}
$subs = $this->get_subscribers( get_bloginfo( 'atom_url' ) );
foreach ( (array) $subs as $callback => $data ) {
if ( $data['is_active'] == FALSE )
continue;
$this->schedule_ping( $callback, $post_id, 'atom', $data['secret'] );
}
}
function return_ok( ) {
header( 'Content-Type: text/plain; charset=utf-8' );
header( 'HTTP/1.0 204 No Content' );
exit;
}
function return_error( $msg ) {
header( 'Content-Type: text/plain; charset=utf-8' );
header( 'HTTP/1.0 400 Bad Request' );
echo $msg;
exit;
}
function schedule_ping( $callback, $post_id, $feed_type, $secret ) {
wp_schedule_single_event(
time( ) - 1,
'pushpress_scheduled_ping',
array( $callback, $post_id, $feed_type, $secret )
);
}
function unsubscribe_callback( $feed_url, $callback ) {
$subs = get_option( 'pushpress_subscribers' );
$subs[$feed_url][$callback]['is_active'] = FALSE;
$subs[$feed_url][$callback]['unsubscribe'] = TRUE;
update_option( 'pushpress_subscribers', $subs );
}
function verify_request( ) {
$challenge = uniqid( mt_rand( ), TRUE );
$challenge .= uniqid( mt_rand( ), TRUE );
$hub_vars = 'hub.lease_seconds=315360000'; // 10 years
$hub_vars .= '&hub.mode=subscribe';
$hub_vars .= '&hub.topic=' . urlencode( $_POST['hub_topic'] );
$hub_vars .= '&hub.challenge=' . urlencode( $challenge );
if ( !empty( $_POST['hub_verify_token'] ) ) {
do_action( 'pushpress_include_verify_token' );
$hub_vars .= '&hub.verify_token=';
$hub_vars .= urlencode( $_POST['hub_verify_token'] );
}
$callback = parse_url( $_POST['hub_callback'] );
$url = $callback['scheme'] . '://';
if ( !empty( $callback['user'] ) ) {
$url .= $callback['user'];
if ( !empty( $callback['pass'] ) )
$url .= ':' . $callback['pass'];
$url .= '@';
}
$url .= $callback['host'];
$port = 80;
if ( !empty( $callback['port'] ) )
$port = (int) $callback['port'];
if ( $callback['scheme'] == 'https' )
$port = 443;
$url .= ':' . $port;
$path = '/';
if ( !empty( $callback['path'] ) ) {
$path = str_replace( '@', '', $callback['path'] );
if ( $path{0} != '/' ) {
$path = '/' . $path;
}
$url .= $path;
}
if ( !empty( $callback['query'] ) ) {
$url .= '?' . $callback['query'];
$url .= '&' . $hub_vars;
} else {
$url .= '?' . $hub_vars;
}
$response = wp_remote_get( $url, array(
'sslverify' => FALSE,
'timeout' => $this->http_timeout,
'user-agent' => $this->http_user_agent,
) );
// look for failure indicators
if ( isset( $response->errors['http_request_failed'][0] ) ) {
do_action( 'pushpress_verify_http_failure' );
$this->return_error( "Error verifying callback URL - {$response->errors['http_request_failed'][0]}" );
}
$status_code = (int) $response['response']['code'];
if ( $status_code < 200 || $status_code > 299 ) {
do_action( 'pushpress_verify_not_2xx_failure' );
$this->return_error( "Error verifying callback URL, HTTP status code: {$status_code}" );
}
if ( trim( $response['body'] ) != $challenge ) {
do_action( 'pushpress_verify_challenge_failure' );
$this->return_error( 'Error verifying callback URL, the challenge token did not match' );
}
} // function verify_request
} // class PuSHPress