Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
composer.lock
17 changes: 17 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "developer/rsscloud",
"description": "RSS Cloud plugin for WordPress",
"require-dev": {
"wp-coding-standards/wpcs": "^3.0",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"scripts": {
"lint": "phpcs",
"lint:fix": "phpcbf"
}
}
23 changes: 20 additions & 3 deletions data-storage.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
<?php
if ( !function_exists( 'rsscloud_get_hub_notifications' ) ) {
function rsscloud_get_hub_notifications( ) {
/**
* Data storage functions for RSS Cloud hub notifications.
*
* @package RSSCloud
*/

if ( ! function_exists( 'rsscloud_get_hub_notifications' ) ) {
/**
* Retrieve the current set of hub notifications from the database.
*
* @return mixed The hub notifications option value.
*/
function rsscloud_get_hub_notifications() {
return get_option( 'rsscloud_hub_notifications' );
}
}

if ( !function_exists( 'rsscloud_update_hub_notifications' ) ) {
if ( ! function_exists( 'rsscloud_update_hub_notifications' ) ) {
/**
* Update the hub notifications in the database.
*
* @param array $notifications The notifications data to save.
* @return bool True if the value was updated, false otherwise.
*/
function rsscloud_update_hub_notifications( $notifications ) {
return update_option( 'rsscloud_hub_notifications', (array) $notifications );
}
Expand Down
142 changes: 97 additions & 45 deletions notification-request.php
Original file line number Diff line number Diff line change
@@ -1,88 +1,140 @@
<?php
function rsscloud_hub_process_notification_request( ) {
// Get the current set of notifications
$notify = rsscloud_get_hub_notifications( );
if ( empty( $notify ) )
$notify = array( );

// Must provide at least one URL to get notifications about
if ( empty( $_POST['url1'] ) )
/**
* Process RSS Cloud notification subscription requests.
*
* @package RSSCloud
*/

/**
* Process an incoming notification subscription request.
*
* Handles the RSS Cloud protocol subscription request via POST. Validates
* the request, tests the callback URL, and registers the subscription.
*
* This is a public API endpoint implementing the RSS Cloud protocol,
* so nonce verification is intentionally not used.
*/
function rsscloud_hub_process_notification_request() {
// Get the current set of notifications.
$notify = rsscloud_get_hub_notifications();
if ( empty( $notify ) ) {
$notify = array();
}

// Must provide at least one URL to get notifications about.
if ( empty( $_POST['url1'] ) ) {
rsscloud_notify_result( 'false', 'No feed for url1.' );
}

// Only support http-post
// Only support http-post.
$protocol = 'http-post';
if ( !empty( $_POST['protocol'] ) && strtolower( $_POST['protocol'] ) !== 'http-post' ) {
do_action( 'rsscloud_protocol_not_post' );
rsscloud_notify_result( 'false', 'Only http-post notifications are supported at this time.' );
if ( ! empty( $_POST['protocol'] ) ) {
$post_protocol = sanitize_text_field( wp_unslash( $_POST['protocol'] ) );
if ( 'http-post' !== strtolower( $post_protocol ) ) {
do_action( 'rsscloud_protocol_not_post' );
rsscloud_notify_result( 'false', 'Only http-post notifications are supported at this time.' );
}
}

// Assume port 80
// Assume port 80.
$port = 80;
if ( !empty( $_POST['port'] ) )
if ( ! empty( $_POST['port'] ) ) {
$port = (int) $_POST['port'];
}

// Path is required
if ( empty( $_POST['path'] ) )
// Path is required.
if ( empty( $_POST['path'] ) ) {
rsscloud_notify_result( 'false', 'No path provided.' );
}

$path = str_replace( '@', '', $_POST['path'] );
if ( $path[0] != '/' )
$path = str_replace( '@', '', sanitize_text_field( wp_unslash( $_POST['path'] ) ) );
if ( '/' !== $path[0] ) {
$path = '/' . $path;
}

// Figure out what the blog and notification URLs are
// Figure out what the blog and notification URLs are.
$rss2_url = get_bloginfo( 'rss2_url' );
if ( defined( 'RSSCLOUD_FEED_URL' ) )
if ( defined( 'RSSCLOUD_FEED_URL' ) ) {
$rss2_url = RSSCLOUD_FEED_URL;
}

$notify_url = $_SERVER['REMOTE_ADDR'] . ':' . $port . $path;
$remote_addr = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
$notify_url = $remote_addr . ':' . $port . $path;

if ( !empty( $_POST['domain'] ) ) {
$domain = str_replace( '@', '', $_POST['domain'] );
if ( ! empty( $_POST['domain'] ) ) {
$domain = str_replace( '@', '', sanitize_text_field( wp_unslash( $_POST['domain'] ) ) );
$notify_url = $domain . ':' . $port . $path;
if ( false === strpos( $notify_url, 'http://' ) )
if ( false === strpos( $notify_url, 'http://' ) ) {
$notify_url = 'http://' . $notify_url;

$challenge = rsscloud_generate_challenge( );

$result = wp_safe_remote_get( $notify_url . '?url=' . esc_url( $_POST['url1'] ) . '&challenge=' . $challenge, array( 'method' => 'GET', 'timeout' => RSSCLOUD_HTTP_TIMEOUT, 'user-agent' => RSSCLOUD_USER_AGENT, 'port' => $port, ) );
}

$challenge = rsscloud_generate_challenge();

$post_url1 = sanitize_text_field( wp_unslash( $_POST['url1'] ) );
$result = wp_safe_remote_get(
$notify_url . '?url=' . esc_url( $post_url1 ) . '&challenge=' . $challenge,
array(
'method' => 'GET',
'timeout' => RSSCLOUD_HTTP_TIMEOUT,
'user-agent' => RSSCLOUD_USER_AGENT,
'port' => $port,
)
);
} else {
if ( false === strpos( $notify_url, 'http://' ) )
if ( false === strpos( $notify_url, 'http://' ) ) {
$notify_url = 'http://' . $notify_url;

$result = wp_safe_remote_post( $notify_url, array( 'method' => 'POST', 'timeout' => RSSCLOUD_HTTP_TIMEOUT, 'user-agent' => RSSCLOUD_USER_AGENT, 'port' => $port, 'body' => array( 'url' => $_POST['url1'] ) ) );
}

$post_url1 = sanitize_text_field( wp_unslash( $_POST['url1'] ) );
$result = wp_safe_remote_post(
$notify_url,
array(
'method' => 'POST',
'timeout' => RSSCLOUD_HTTP_TIMEOUT,
'user-agent' => RSSCLOUD_USER_AGENT,
'port' => $port,
'body' => array( 'url' => $post_url1 ),
)
);
}

if ( isset( $result->errors['http_request_failed'][0] ) )
if ( isset( $result->errors['http_request_failed'][0] ) ) {
rsscloud_notify_result( 'false', 'Error testing notification URL : ' . $result->errors['http_request_failed'][0] );
}

$status_code = (int) $result['response']['code'];

if ( $status_code < 200 || $status_code > 299 )
if ( $status_code < 200 || $status_code > 299 ) {
rsscloud_notify_result( 'false', 'Error testing notification URL. The URL returned HTTP status code: ' . $result['response']['code'] . ' - ' . $result['response']['message'] . '.' );
}

// challenge must match for domain requests
if ( !empty( $_POST['domain'] ) ) {
if ( empty( $result['body'] ) || $result['body'] != $challenge )
// Challenge must match for domain requests.
if ( ! empty( $_POST['domain'] ) ) {
if ( empty( $result['body'] ) || $result['body'] !== $challenge ) {
rsscloud_notify_result( 'false', 'The response body did not match the challenge string' );

}
}

// Passed all the tests, add this to the list of notifications for
// Passed all the tests, add this to the list of notifications.
foreach ( $_POST as $key => $feed_url ) {
if ( !preg_match( '|url\d+|', $key ) )
if ( ! preg_match( '|url\d+|', $key ) ) {
continue;
}

$feed_url = sanitize_text_field( wp_unslash( $feed_url ) );

// Only allow requests for the RSS2 posts feed
if ( $feed_url != $rss2_url )
// Only allow requests for the RSS2 posts feed.
if ( $feed_url !== $rss2_url ) {
rsscloud_notify_result( 'false', "You can only request updates for {$rss2_url}" );
}

$notify[$feed_url][$notify_url]['protocol'] = $protocol;
$notify[$feed_url][$notify_url]['status'] = 'active';
$notify[$feed_url][$notify_url]['failure_count'] = 0;
$notify[ $feed_url ][ $notify_url ]['protocol'] = $protocol;
$notify[ $feed_url ][ $notify_url ]['status'] = 'active';
$notify[ $feed_url ][ $notify_url ]['failure_count'] = 0;
}

do_action( 'rsscloud_add_notify_subscription' );

rsscloud_update_hub_notifications( $notify );
rsscloud_notify_result( 'true', 'Registration successful.' );
} // function rsscloud_hub_notify
}
22 changes: 22 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<ruleset name="RSS Cloud">
<description>WordPress Coding Standards for RSS Cloud plugin.</description>

<rule ref="WordPress"/>

<arg name="extensions" value="php"/>
<arg name="colors"/>
<arg value="sp"/>

<file>.</file>
<exclude-pattern>/vendor/*</exclude-pattern>

<config name="testVersion" value="8.0-"/>
<config name="minimum_wp_version" value="2.8"/>
<config name="text_domain" value="rsscloud"/>

<!-- notification-request.php is a public RSS Cloud protocol endpoint; nonce verification does not apply. -->
<rule ref="WordPress.Security.NonceVerification.Missing">
<exclude-pattern>/notification-request.php</exclude-pattern>
</rule>
</ruleset>
Loading