public function checkUpdates(FeedSub $feedsub) { $request = new HTTPClient(); $feed = $request->get($feedsub->uri); if (!$feed->isOk()) { throw new ServerException('FeedSub could not fetch id=' . $feedsub->id . ' (Error ' . $feed->getStatus() . ': ' . $feed->getBody()); } $feedsub->receive($feed->getBody(), null); }
public function onFeedUnsubscribe(FeedSub $feedsub) { if (!$feedsub->isPuSH()) { // removes sub_state setting and such $feedsub->confirmUnsubscribe(); return false; } return true; }
function handle($data) { $feedsub_id = $data['feedsub_id']; $feedsub = FeedSub::getKV('id', $feedsub_id); if ($feedsub instanceof FeedSub) { try { common_log(LOG_INFO, "Renewing feed subscription\n\tExp.: {$feedsub->sub_end}\n\tFeed: {$feedsub->uri}\n\tHub: {$feedsub->huburi}"); $feedsub->renew(); } catch (Exception $e) { common_log(LOG_ERR, "Exception during PuSH renew processing for {$feedsub->uri}: " . $e->getMessage()); } } else { common_log(LOG_ERR, "Discarding renew for unknown feed subscription id {$feedsub_id}"); } return true; }
/** * Handler for GET verification requests from the hub. */ function handleGet() { $mode = $this->arg('hub_mode'); $topic = $this->arg('hub_topic'); $challenge = $this->arg('hub_challenge'); $lease_seconds = $this->arg('hub_lease_seconds'); $verify_token = $this->arg('hub_verify_token'); common_log(LOG_INFO, __METHOD__ . ": sub verification mode: {$mode} topic: {$topic} challenge: {$challenge} lease_seconds: {$lease_seconds} verify_token: {$verify_token}"); if ($mode != 'subscribe' && $mode != 'unsubscribe') { // TRANS: Client exception. %s is an invalid value for hub.mode. throw new ClientException(sprintf(_m('Bad hub.mode "$s".', $mode)), 404); } $feedsub = FeedSub::staticGet('uri', $topic); if (!$feedsub) { // TRANS: Client exception. %s is an invalid feed name. throw new ClientException(sprintf(_m('Bad hub.topic feed "%s".'), $topic), 404); } if ($feedsub->verify_token !== $verify_token) { // TRANS: Client exception. %1$s the invalid token, %2$s is the topic for which the invalid token was given. throw new ClientException(sprintf(_m('Bad hub.verify_token %1$s for %2$s.'), $token, $topic), 404); } if ($mode == 'subscribe') { // We may get re-sub requests legitimately. if ($feedsub->sub_state != 'subscribe' && $feedsub->sub_state != 'active') { // TRANS: Client exception. %s is an invalid topic. throw new ClientException(sprintf(_m('Unexpected subscribe request for %s.'), $topic), 404); } } else { if ($feedsub->sub_state != 'unsubscribe') { // TRANS: Client exception. %s is an invalid topic. throw new ClientException(sprintf(_m('Unexpected unsubscribe request for %s.'), $topic), 404); } } if ($mode == 'subscribe') { if ($feedsub->sub_state == 'active') { common_log(LOG_INFO, __METHOD__ . ': sub update confirmed'); } else { common_log(LOG_INFO, __METHOD__ . ': sub confirmed'); } $feedsub->confirmSubscribe($lease_seconds); } else { common_log(LOG_INFO, __METHOD__ . ": unsub confirmed; deleting sub record for {$topic}"); $feedsub->confirmUnsubscribe(); } print $challenge; }
public function handle($item) { $feedsub = FeedSub::getKV('id', $item['id']); if (!$feedsub instanceof FeedSub) { // Removed from the feedsub table I guess return true; } if (!$feedsub->sub_state == 'nohub') { // We're not supposed to poll this (either it's PuSH or it's unsubscribed) return true; } try { FeedPoll::checkUpdates($feedsub); } catch (Exception $e) { common_log(LOG_ERR, "Failed to check feedsub id= " . $feedsub->id . ' ("' . $e->getMessage() . '")'); } return true; }
function handle($data) { assert(is_array($data)); $feedsub_id = $data['feedsub_id']; $post = $data['post']; $hmac = $data['hmac']; $feedsub = FeedSub::staticGet('id', $feedsub_id); if ($feedsub) { try { $feedsub->receive($post, $hmac); } catch (Exception $e) { common_log(LOG_ERR, "Exception during PuSH input processing for {$feedsub->uri}: " . $e->getMessage()); } } else { common_log(LOG_ERR, "Discarding POST to unknown feed subscription id {$feedsub_id}"); } return true; }
/** * Handler for GET verification requests from the hub. */ function handleGet() { $mode = $this->arg('hub_mode'); $topic = $this->arg('hub_topic'); $challenge = $this->arg('hub_challenge'); $lease_seconds = $this->arg('hub_lease_seconds'); $verify_token = $this->arg('hub_verify_token'); if ($mode != 'subscribe' && $mode != 'unsubscribe') { throw new ClientException("Bad hub.mode {$mode}", 404); } $feedsub = FeedSub::staticGet('uri', $topic); if (!$feedsub) { // @todo i18n FIXME: added i18n and use sprintf when using parameters. throw new ClientException("Bad hub.topic feed {$topic}.", 404); } if ($feedsub->verify_token !== $verify_token) { // @todo i18n FIXME: added i18n and use sprintf when using parameters. throw new ClientException("Bad hub.verify_token {$token} for {$topic}.", 404); } if ($mode == 'subscribe') { // We may get re-sub requests legitimately. if ($feedsub->sub_state != 'subscribe' && $feedsub->sub_state != 'active') { // @todo i18n FIXME: added i18n and use sprintf when using parameters. throw new ClientException("Unexpected subscribe request for {$topic}.", 404); } } else { if ($feedsub->sub_state != 'unsubscribe') { // @todo i18n FIXME: added i18n and use sprintf when using parameters. throw new ClientException("Unexpected unsubscribe request for {$topic}.", 404); } } if ($mode == 'subscribe') { if ($feedsub->sub_state == 'active') { common_log(LOG_INFO, __METHOD__ . ': sub update confirmed'); } else { common_log(LOG_INFO, __METHOD__ . ': sub confirmed'); } $feedsub->confirmSubscribe($lease_seconds); } else { common_log(LOG_INFO, __METHOD__ . ": unsub confirmed; deleting sub record for {$topic}"); $feedsub->confirmUnsubscribe(); } print $challenge; }
public function onCronDaily() { try { $sub = FeedSub::renewalCheck(); } catch (NoResultException $e) { common_log(LOG_INFO, "There were no expiring feeds."); return; } $qm = QueueManager::get(); while ($sub->fetch()) { $item = array('feedsub_id' => $sub->id); $qm->enqueue($item, 'pushrenew'); } }
Mainly intended for testing funky feed formats. --skip=N Ignore the first N items in the feed. --count=N Only process up to N items from the feed, after skipping. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; if (empty($args[0]) || !Validate::uri($args[0])) { print "{$helptext}"; exit(1); } $feedurl = $args[0]; $skip = have_option('skip') ? intval(get_option_value('skip')) : 0; $count = have_option('count') ? intval(get_option_value('count')) : 0; $sub = FeedSub::staticGet('uri', $feedurl); if (!$sub) { print "Feed {$feedurl} is not subscribed.\n"; exit(1); } $xml = file_get_contents($feedurl); if ($xml === false) { print "Bad fetch.\n"; exit(1); } $feed = new DOMDocument(); if (!$feed->loadXML($xml)) { print "Bad XML.\n"; exit(1); } if ($skip || $count) {
--skip=N Ignore the first N items in the feed. --count=N Only process up to N items from the feed, after skipping. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; $validate = new Validate(); if (empty($args[0]) || !$validate->uri($args[0])) { print "{$helptext}"; exit(1); } $feedurl = $args[0]; $skip = have_option('skip') ? intval(get_option_value('skip')) : 0; $count = have_option('count') ? intval(get_option_value('count')) : 0; $sub = FeedSub::getKV('uri', $feedurl); if (!$sub) { print "Feed {$feedurl} is not subscribed.\n"; exit(1); } // Fetch the URL try { $xml = HTTPClient::quickGet($feedurl, 'text/html,application/xhtml+xml'); } catch (Exception $e) { echo sprintf("Could not fetch feedurl %s (%d).\n", $e->getMessage(), $e->getCode()); exit(1); } $feed = new DOMDocument(); if (!$feed->loadXML($xml)) { print "Bad XML.\n"; exit(1);
/** * Check if this remote profile has any active local subscriptions, and * if not drop the PuSH subscription feed. * * @return boolean */ public function garbageCollect() { $feedsub = FeedSub::staticGet('uri', $this->feeduri); return $feedsub->garbageCollect(); }
/** * Make sure necessary tables are filled out. */ function onCheckSchema() { $schema = Schema::get(); $schema->ensureTable('ostatus_profile', Ostatus_profile::schemaDef()); $schema->ensureTable('ostatus_source', Ostatus_source::schemaDef()); $schema->ensureTable('feedsub', FeedSub::schemaDef()); $schema->ensureTable('hubsub', HubSub::schemaDef()); $schema->ensureTable('magicsig', Magicsig::schemaDef()); return true; }
/** * Check if this remote profile has any active local subscriptions, and * if not drop the PuSH subscription feed. * * @return boolean true if subscription is removed, false if there are still subscribers to the feed * @throws Exception of various kinds on failure. */ public function garbageCollect() { $feedsub = FeedSub::getKV('uri', $this->feeduri); if ($feedsub instanceof FeedSub) { return $feedsub->garbageCollect(); } // Since there's no FeedSub we can assume it's already garbage collected return true; }
public function updateUriKeys($profile_uri, array $hints = array()) { $orig = clone $this; common_debug('URIFIX These identities both say they are each other: "' . $orig->uri . '" and "' . $profile_uri . '"'); $this->uri = $profile_uri; if (array_key_exists('feedurl', $hints)) { if (!empty($this->feeduri)) { common_debug('URIFIX Changing FeedSub [' . $feedsub->id . '] feeduri "' . $feedsub->uri . '" to "' . $hints['feedurl']); $feedsub = FeedSub::getKV('uri', $this->feeduri); $feedorig = clone $feedsub; $feedsub->uri = $hints['feedurl']; $feedsub->updateWithKeys($feedorig); } else { common_debug('URIFIX Old Ostatus_profile did not have feedurl set, ensuring feed: ' . $hints['feedurl']); FeedSub::ensureFeed($hints['feedurl']); } $this->feeduri = $hints['feedurl']; } if (array_key_exists('salmon', $hints)) { common_debug('URIFIX Changing Ostatus_profile salmonuri from "' . $this->salmonuri . '" to "' . $hints['salmon'] . '"'); $this->salmonuri = $hints['salmon']; } common_debug('URIFIX Updating Ostatus_profile URI for ' . $orig->uri . ' to ' . $this->uri); $this->updateWithKeys($orig, 'uri'); // 'uri' is the primary key column common_debug('URIFIX Subscribing/renewing feedsub for Ostatus_profile ' . $this->uri); $this->subscribe(); }
*/ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); $helptext = <<<END_OF_HELP pollfeed.php feeduri Poll the feed, assuming it has sub_state 'nohub'. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; require_once __DIR__ . '/../lib/feedpoll.php'; if (empty($args[0]) || !Validate::uri($args[0])) { echo "{$helptext}\n"; exit(1); } $uri = $args[0]; $feedsub = FeedSub::getKV('uri', $uri); if (!$feedsub instanceof FeedSub) { echo "No FeedSub feed known for URI {$uri}\n"; exit(1); } if ($feedsub->sub_state != 'nohub') { echo "Feed is a PuSH feed, so we will not poll it.\n"; exit(1); } showSub($feedsub); try { FeedPoll::checkUpdates($feedsub); } catch (Exception $e) { echo "Could not check updates for feed: " . $e->getMessage(); echo $e->getTraceAsString(); exit(1);
} print "\n"; print "Pinging hub {$sub->huburi} with new subscription for {$sub->uri}\n"; $ok = $sub->subscribe(); if ($ok) { print "ok\n"; } else { print "Could not confirm.\n"; } $o2 = Ostatus_profile::staticGet('uri', $uri); print "\n"; print "New profile state:\n"; showProfile($o2); print "\n"; print "New feed state:\n"; $sub2 = FeedSub::ensureFeed($feedurl); showSub($sub2); function showProfile($oprofile) { print " Feed URL: {$oprofile->feeduri}\n"; print " Salmon URL: {$oprofile->salmonuri}\n"; print " Avatar URL: {$oprofile->avatar}\n"; print " Profile ID: {$oprofile->profile_id}\n"; print " Group ID: {$oprofile->group_id}\n"; print " Record created: {$oprofile->created}\n"; print " Record modified: {$oprofile->modified}\n"; } function showSub($sub) { print " Subscription state: {$sub->sub_state}\n"; print " Verify token: {$sub->verify_token}\n";
and are older than one hour. If the hub hasn't answered back in an hour the hub is probably either broken or doesn't exist.' Options: -d --dry-run look but don't mess with it END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; $dry = false; if (have_option('d') || have_option('dry-run')) { $dry = true; } echo "Looking for feed subscriptions with dirty no good huburis...\n"; $feedsub = new FeedSub(); $feedsub->sub_state = 'subscribe'; $feedsub->whereAdd('created < DATE_SUB(NOW(), INTERVAL 1 HOUR)'); $feedsub->find(); $cnt = 0; while ($feedsub->fetch()) { echo "----------------------------------------------------------------------------------------\n"; echo ' feed: ' . $feedsub->uri . "\n" . ' hub uri: ' . $feedsub->huburi . "\n" . ' subscribe date: ' . date('r', strtotime($feedsub->created)) . "\n"; if (!$dry) { $feedsub->delete(); echo " (DELETED)\n"; } else { echo " (WOULD BE DELETED)\n"; } echo "----------------------------------------------------------------------------------------\n"; $cnt++;
/** * @param string $feeduri * @return FeedSub * @throws FeedSubException if feed is invalid or lacks PuSH setup */ public static function ensureFeed($feeduri) { $current = self::staticGet('uri', $feeduri); if ($current) { return $current; } $discover = new FeedDiscovery(); $discover->discoverFromFeedURL($feeduri); $huburi = $discover->getHubLink(); if (!$huburi && !common_config('feedsub', 'fallback_hub')) { throw new FeedSubNoHubException(); } $feedsub = new FeedSub(); $feedsub->uri = $feeduri; $feedsub->huburi = $huburi; $feedsub->sub_state = 'inactive'; $feedsub->created = common_sql_now(); $feedsub->modified = common_sql_now(); $result = $feedsub->insert(); if (empty($result)) { throw new FeedDBException($feedsub); } return $feedsub; }
public static function renewalCheck() { $fs = new FeedSub(); // the "" empty string check is because we historically haven't saved unsubscribed feeds as NULL $fs->whereAdd('sub_end IS NOT NULL AND sub_end!="" AND sub_end < NOW() - INTERVAL 1 day'); if (!$fs->find()) { // find can be both false and 0, depending on why nothing was found throw new NoResultException($fs); } return $fs; }
* along with this program. If not, see <http://www.gnu.org/licenses/>. */ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); $longoptions = array('delete-inactive'); $shortoptions = 'd'; $helptext = <<<END_OF_HELP gcfeeds.php [options] Clean up feeds that no longer have subscribers. -d --delete-inactive Delete inactive feeds from feedsub table. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; $delete_inactive = have_option('d', 'delete-inactive'); $delcount = 0; $feedsub = new FeedSub(); $feedsub->find(); while ($feedsub->fetch()) { try { echo $feedsub->getUri() . " ({$feedsub->sub_state})"; if ($feedsub->garbageCollect()) { if ($delete_inactive) { $delcount++; $feedsub->delete(); echo " DELETED"; } echo " INACTIVE\n"; } else { echo " ACTIVE\n"; } } catch (NoProfileException $e) {
Mainly intended for testing funky feed formats. --skip=N Ignore the first N items in the feed. --count=N Only process up to N items from the feed, after skipping. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; if (empty($args[0]) || !Validate::uri($args[0])) { print "{$helptext}"; exit(1); } $feedurl = $args[0]; $skip = have_option('skip') ? intval(get_option_value('skip')) : 0; $count = have_option('count') ? intval(get_option_value('count')) : 0; $sub = FeedSub::staticGet('topic', $feedurl); if (!$sub) { print "Feed {$feedurl} is not subscribed.\n"; exit(1); } $xml = file_get_contents($feedurl); if ($xml === false) { print "Bad fetch.\n"; exit(1); } $feed = new DOMDocument(); if (!$feed->loadXML($xml)) { print "Bad XML.\n"; exit(1); } if ($skip || $count) {
/** * Send a PuSH unsubscription request to the hub for this feed. * The hub will later send us a confirmation POST to /main/push/callback. * * @return bool true on success, false on failure * @throws ServerException if feed state is not valid */ public function unsubscribe() { $feedsub = FeedSub::staticGet('uri', $this->feeduri); if (!$feedsub || $feedsub->sub_state == '' || $feedsub->sub_state == 'inactive') { // No active PuSH subscription, we can just leave it be. return true; } else { // PuSH subscription is either active or in an indeterminate state. // Send an unsubscribe. return $feedsub->unsubscribe(); } }
* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); $helptext = <<<END_OF_HELP resub-feed.php Resubscribe to any soon expiring feeds. Default time to expiration is 1 day. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; try { $sub = FeedSub::renewalCheck(); } catch (NoResultException $e) { echo 'There were no expiring feeds.'; exit; } while ($sub->fetch()) { echo "Renewing feed subscription\n\tExp.: {$sub->sub_end}\n\tFeed: {$sub->uri}\n\tHub: {$sub->huburi}\n"; $sub->renew(); } echo "Done!";
* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); $helptext = <<<END_OF_HELP gcfeeds.php [options] Clean up feeds that no longer have subscribers. END_OF_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; $feedsub = new FeedSub(); while ($feedsub->fetch()) { print $feedsub->uri . "(" . $feedsub->sub_state . ")"; $result = $feedsub->garbageCollect(); if ($result) { print " INACTIVE\n"; } else { print " ACTIVE\n"; } }