From 61804bb7bbd0cea92ba2bbcce15e37a35195341a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 7 Dec 2009 09:10:04 +0000 Subject: [PATCH] Plugin now checks notify handlers before registering subscriptions --- plugins/RSSCloud/LoggingAggregator.php | 5 +- plugins/RSSCloud/RSSCloudNotifier.php | 96 +++++++++++------- plugins/RSSCloud/RSSCloudPlugin.php | 2 + plugins/RSSCloud/RSSCloudRequestNotify.php | 112 ++++++++++----------- 4 files changed, 113 insertions(+), 102 deletions(-) diff --git a/plugins/RSSCloud/LoggingAggregator.php b/plugins/RSSCloud/LoggingAggregator.php index cbdefc36b8..02175f43a8 100644 --- a/plugins/RSSCloud/LoggingAggregator.php +++ b/plugins/RSSCloud/LoggingAggregator.php @@ -1,5 +1,4 @@ challenge . "' />\n"; + echo $this->challenge; } else { @@ -92,7 +90,6 @@ class LoggingAggregatorAction extends Action header('Content-Type: text/xml'); echo '' . "\n"; - } $this->ip = $_SERVER['REMOTE_ADDR']; diff --git a/plugins/RSSCloud/RSSCloudNotifier.php b/plugins/RSSCloud/RSSCloudNotifier.php index c2130b7b83..eb3198b5a4 100644 --- a/plugins/RSSCloud/RSSCloudNotifier.php +++ b/plugins/RSSCloud/RSSCloudNotifier.php @@ -33,59 +33,77 @@ if (!defined('STATUSNET')) { class RSSCloudNotifier { - function postUpdate($endpoint, $feed) { - common_debug("CloudNotifier->notify: $feed"); + function challenge($endpoint, $feed) + { + $code = common_confirmation_code(128); + $params = array('url' => $feed, 'challenge' => $code); + $url = $endpoint . '?' . http_build_query($params); - $params = 'url=' . urlencode($feed); - - $result = $this->httpPost($endpoint, $params); - - // XXX: Make all this use CurlClient (lib/curlclient.php) - - if ($result) { - common_debug('RSSCloud plugin - success notifying cloud endpoint!'); - } else { - common_debug('RSSClous plugin - failure notifying cloud endpoint!'); + try { + $client = new HTTPClient(); + $response = $client->get($url); + } catch (HTTP_Request2_Exception $e) { + common_log(LOG_INFO, 'RSSCloud plugin - failure testing notify handler ' . + $endpoint . ' - ' . $e->getMessage()); + return false; } - return $result; + // Check response is betweet 200 and 299 and body contains challenge data + + $status = $response->getStatus(); + $body = $response->getBody(); + + if ($status >= 200 && $status < 300) { + + if (strpos($body, $code) !== false) { + common_log(LOG_INFO, 'RSSCloud plugin - ' . + "success testing notify handler: $endpoint"); + return true; + } else { + common_log(LOG_INFO, 'RSSCloud plugin - ' . + 'challenge/repsonse failed for notify handler ' . + $endpoint); + common_debug('body = ' . var_export($body, true)); + return false; + } + } else { + common_log(LOG_INFO, 'RSSCloud plugin - ' . + "failure testing notify handler: $endpoint " . + ' - got HTTP ' . $status); + common_debug('body = ' . var_export($body, true)); + return false; + } } - function userAgent() - { - return 'rssCloudPlugin/' . RSSCLOUDPLUGIN_VERSION . - ' StatusNet/' . STATUSNET_VERSION; - } + function postUpdate($endpoint, $feed) { - private function httpPost($url, $params) { + $headers = array(); + $postdata = array('url' => $feed); - $options = array(CURLOPT_URL => $url, - CURLOPT_POST => true, - CURLOPT_POSTFIELDS => $params, - CURLOPT_USERAGENT => $this->userAgent(), - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FAILONERROR => true, - CURLOPT_HEADER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_CONNECTTIMEOUT => 5, - CURLOPT_TIMEOUT => 5); + try { + $client = new HTTPClient(); + $response = $client->post($endpoint, $headers, $postdata); + } catch (HTTP_Request2_Exception $e) { + common_log(LOG_INFO, 'RSSCloud plugin - failure notifying ' . + $endpoint . ' that feed ' . $feed . + ' has changed: ' . $e->getMessage()); + return false; + } - $ch = curl_init(); - curl_setopt_array($ch, $options); + $status = $response->getStatus(); - $response = curl_exec($ch); - - $info = curl_getinfo($ch); - - curl_close($ch); - - if ($info['http_code'] == 200) { + if ($status >= 200 && $status < 300) { + common_log(LOG_INFO, 'RSSCloud plugin - success notifying ' . + $endpoint . ' that feed ' . $feed . ' has changed.'); return true; } else { + common_log(LOG_INFO, 'RSSCloud plugin - failure notifying ' . + $endpoint . ' that feed ' . $feed . + ' has changed: got HTTP ' . $status); + common_debug('body = ' . var_export($response->getBody(), true)); return false; } } } - diff --git a/plugins/RSSCloud/RSSCloudPlugin.php b/plugins/RSSCloud/RSSCloudPlugin.php index 8e57b4a3e0..402fbec2d8 100644 --- a/plugins/RSSCloud/RSSCloudPlugin.php +++ b/plugins/RSSCloud/RSSCloudPlugin.php @@ -112,6 +112,8 @@ class RSSCloudPlugin extends Plugin function onStartApiRss($action) { + // XXX: Add RSS 1.0 user feeds + if (get_class($action) == 'ApiTimelineUserAction') { $attrs = array('domain' => $this->domain, diff --git a/plugins/RSSCloud/RSSCloudRequestNotify.php b/plugins/RSSCloud/RSSCloudRequestNotify.php index 8b5deb1365..135c316f7b 100644 --- a/plugins/RSSCloud/RSSCloudRequestNotify.php +++ b/plugins/RSSCloud/RSSCloudRequestNotify.php @@ -52,7 +52,7 @@ class RSSCloudRequestNotifyAction extends Action $this->protocol = $this->arg('protocol'); $this->procedure = $this->arg('notifyProcedure'); $this->domain = $this->arg('domain'); - + $this->feeds = $this->getFeeds(); return true; @@ -103,29 +103,29 @@ class RSSCloudRequestNotifyAction extends Action } // We have to validate everything before saving anything. - // We only return one success or failure no matter how + // We only return one success or failure no matter how // many feeds the subscriber is trying to subscribe to foreach ($this->feeds as $feed) { - + if (!$this->validateFeed($feed)) { $msg = 'Feed subscription failed - Not a valid feed.'; $this->showResult(false, $msg); return; } - + if (!$this->testNotificationHandler($feed)) { $msg = 'Feed subscription failed - ' . 'notification handler doesn\'t respond correctly.'; $this->showResult(false, $msg); - return; + return; } - + } foreach ($this->feeds as $feed) { $this->saveSubscription($feed); - } + } // XXX: What to do about deleting stale subscriptions? 25 hours seems harsh. // WordPress doesn't ever remove subscriptions. @@ -133,7 +133,7 @@ class RSSCloudRequestNotifyAction extends Action $msg = 'Thanks for the registration. It worked. When the feed(s) update(s) we\'ll notify you. ' . ' Don\'t forget to re-register after 24 hours, your subscription will expire in 25.'; - $this->showResult(true, $msg); + $this->showResult(true, $msg); } function validateFeed($feed) @@ -147,45 +147,45 @@ class RSSCloudRequestNotifyAction extends Action return true; } - function getFeeds() { $feeds = array(); - - while (list($key, $feed) = each ($this->args)) { + + while (list($key, $feed) = each ($this->args)) { if (preg_match('/^url\d*$/', $key)) { $feeds[] = $feed; - } + } } return $feeds; } function testNotificationHandler($feed) - { + { common_debug("RSSCloudPlugin - testNotificationHandler()"); - + $notifier = new RSSCloudNotifier(); - + if (isset($this->domain)) { - - //get - - $this->url = 'http://' . $this->domain . ':' . $this->port . '/' . $this->path; - - common_debug('domain set need to send challenge'); - + + // 'domain' param set, so we have to use GET and send a challenge + + $endpoint = 'http://' . $this->domain . ':' . $this->port . '/' . $this->path; + + common_log(LOG_INFO, 'Testing notification handler with challenge: ' . + $endpoint); + + return $notifier->challenge($endpoint, $feed); + } else { - - //post - - $this->url = 'http://' . $this->ip . ':' . $this->port . '/' . $this->path; - - //return $notifier->postUpdate($endpoint, $feed); - } + $endpoint = 'http://' . $this->ip . ':' . $this->port . '/' . $this->path; - return true; + common_log(LOG_INFO, 'Testing notification handler: ' . + $endpoint); + + return $notifier->postUpdate($endpoint, $feed); + } } @@ -193,6 +193,8 @@ class RSSCloudRequestNotifyAction extends Action { // We only do profile feeds + // XXX: Add cloud element to RSS 1.0 feeds + $path = common_path('api/statuses/user_timeline/'); $valid = '%^' . $path . '(?.*)\.rss$%'; @@ -209,37 +211,31 @@ class RSSCloudRequestNotifyAction extends Action function saveSubscription($feed) { $user = $this->userFromFeed($feed); - - common_debug('user = ' . $user->id); - + $sub = RSSCloudSubscription::getSubscription($user->id, $this->url); - + if ($sub) { - common_debug("already subscribed to that!"); + common_debug("Already subscribed to that!"); } else { - common_debug('No feed for user ' . $user->id . ' notify: ' . $this->url); + + $sub = new RSSCloudSubscription(); + + $sub->subscribed = $user->id; + $sub->url = $this->url; + $sub->created = common_sql_now(); + + // auto timestamp doesn't seem to work for me + + // $sub->modified = common_sql_now(); + + if (!$sub->insert()) { + common_log_db_error($sub, 'INSERT', __FILE__); + return false; + } + + DB_DataObject::debugLevel(); } - - common_debug('RSSPlugin - saveSubscription'); - // turn debugging high - DB_DataObject::debugLevel(5); - - $sub = new RSSCloudSubscription(); - - $sub->subscribed = $user->id; - $sub->url = $this->url; - $sub->created = common_sql_now(); - - // auto timestamp doesn't seem to work for me - - $sub->modified = common_sql_now(); - - if (!$sub->insert()) { - common_log_db_error($sub, 'INSERT', __FILE__); - return false; - } - DB_DataObject::debugLevel(); - + return true; } @@ -253,5 +249,3 @@ class RSSCloudRequestNotifyAction extends Action } - -