if ($this->validateFeed()) {
$this->preview = true;
$this->profile = Ostatus_profile::ensureProfile($this->munger);
+ if (!$this->profile) {
+ throw new ServerException("Feed profile was not saved properly.");
+ }
// If not already in use, subscribe to updates via the hub
if ($this->profile->sub_start) {
// And subscribe the current user to the local profile
$user = common_current_user();
- $profile = $this->profile->getLocalProfile();
- if (!$profile) {
- throw new ServerException("Feed profile was not saved properly.");
- }
if ($this->profile->isGroup()) {
- if ($user->isMember($profile)) {
+ $group = $this->profile->localGroup();
+ if ($user->isMember($group)) {
$this->showForm(_m('Already a member!'));
} elseif (Group_member::join($this->profile->group_id, $user->id)) {
$this->showForm(_m('Joined remote group!'));
$this->showForm(_m('Remote group join failed!'));
}
} else {
- if ($user->isSubscribed($profile)) {
+ $local = $this->profile->localProfile();
+ if ($user->isSubscribed($local)) {
$this->showForm(_m('Already subscribed!'));
- } elseif ($user->subscribeTo($profile)) {
+ } elseif ($user->subscribeTo($local)) {
$this->showForm(_m('Feed subscribed!'));
} else {
$this->showForm(_m('Feed subscription failed!'));
throw new ServerException("Bogus hub callback: unknown feed", 404);
}
- # Can't currently set the token in our sub api
- #if ($feedinfo->verify_token !== $verify_token) {
- # common_log(LOG_WARNING, __METHOD__ . ": bogus hub callback with bad token \"$verify_token\" for feed $topic");
- # throw new ServerError("Bogus hub callback: bad token", 404);
- #}
-
+ if ($profile->verify_token !== $verify_token) {
+ common_log(LOG_WARNING, __METHOD__ . ": bogus hub callback with bad token \"$verify_token\" for feed $topic");
+ throw new ServerError("Bogus hub callback: bad token", 404);
+ }
+
+ if ($mode != $profile->sub_state) {
+ common_log(LOG_WARNING, __METHOD__ . ": bogus hub callback with bad mode \"$mode\" for feed $topic in state \"{$profile->sub_state}\"");
+ throw new ServerException("Bogus hub callback: mode doesn't match subscription state.", 404);
+ }
+
// OK!
if ($mode == 'subscribe') {
common_log(LOG_INFO, __METHOD__ . ': sub confirmed');
- $profile->sub_start = common_sql_date(time());
- if ($lease_seconds > 0) {
- $profile->sub_end = common_sql_date(time() + $lease_seconds);
- } else {
- $profile->sub_end = null;
- }
- $profile->update();
+ $profile->confirmSubscribe($lease_seconds);
} else {
common_log(LOG_INFO, __METHOD__ . ": unsub confirmed; deleting sub record for $topic");
- $profile->delete();
+ $profile->confirmUnsubscribe();
}
-
print $challenge;
}
}
* Fetch the StatusNet-side profile for this feed
* @return Profile
*/
- public function getLocalProfile()
+ public function localProfile()
{
- return Profile::staticGet('id', $this->profile_id);
+ if ($this->profile_id) {
+ return Profile::staticGet('id', $this->profile_id);
+ }
+ return null;
+ }
+
+ /**
+ * Fetch the StatusNet-side profile for this feed
+ * @return Profile
+ */
+ public function localGroup()
+ {
+ if ($this->group_id) {
+ return User_group::staticGet('id', $this->group_id);
+ }
+ return null;
}
/**
*/
public static function ensureProfile($munger)
{
- $entity = $munger->ostatusProfile();
+ $profile = $munger->ostatusProfile();
- $current = self::staticGet('feeduri', $entity->feeduri);
+ $current = self::staticGet('feeduri', $profile->feeduri);
if ($current) {
// @fixme we should probably update info as necessary
return $current;
}
- $entity->query('BEGIN');
+ $profile->query('BEGIN');
// Awful hack! Awful hack!
- $entity->verify = common_good_rand(16);
- $entity->secret = common_good_rand(32);
+ $profile->verify = common_good_rand(16);
+ $profile->secret = common_good_rand(32);
try {
- $profile = $munger->profile();
- $result = $profile->insert();
- if (empty($result)) {
- throw new FeedDBException($profile);
- }
-
- $avatar = $munger->getAvatar();
- if ($avatar) {
- // @fixme this should be better encapsulated
- // ripped from oauthstore.php (for old OMB client)
- $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
- copy($avatar, $temp_filename);
- $imagefile = new ImageFile($profile->id, $temp_filename);
- $filename = Avatar::filename($profile->id,
- image_type_to_extension($imagefile->type),
- null,
- common_timestamp());
- rename($temp_filename, Avatar::path($filename));
- $profile->setOriginal($filename);
- }
+ $local = $munger->profile();
- $entity->profile_id = $profile->id;
if ($entity->isGroup()) {
$group = new User_group();
- $group->nickname = $profile->nickname . '@remote'; // @fixme
- $group->fullname = $profile->fullname;
- $group->homepage = $profile->homepage;
- $group->location = $profile->location;
- $group->created = $profile->created;
+ $group->nickname = $local->nickname . '@remote'; // @fixme
+ $group->fullname = $local->fullname;
+ $group->homepage = $local->homepage;
+ $group->location = $local->location;
+ $group->created = $local->created;
$group->insert();
-
- if ($avatar) {
- $group->setOriginal($filename);
+ if (empty($result)) {
+ throw new FeedDBException($group);
}
-
- $entity->group_id = $group->id;
+ $profile->group_id = $group->id;
+ } else {
+ $result = $local->insert();
+ if (empty($result)) {
+ throw new FeedDBException($local);
+ }
+ $profile->profile_id = $local->id;
}
- $result = $entity->insert();
+ $profile->created = sql_common_date();
+ $profile->lastupdate = sql_common_date();
+ $result = $profile->insert();
if (empty($result)) {
- throw new FeedDBException($entity);
+ throw new FeedDBException($profile);
}
$entity->query('COMMIT');
$entity->query('ROLLBACK');
return false;
}
+
+ $avatar = $munger->getAvatar();
+ if ($avatar) {
+ try {
+ $this->updateAvatar($avatar);
+ } catch (Exception $e) {
+ common_log(LOG_ERR, "Exception setting OStatus avatar: " .
+ $e->getMessage());
+ }
+ }
+
return $entity;
}
+ /**
+ * Download and update given avatar image
+ * @param string $url
+ * @throws Exception in various failure cases
+ */
+ public function updateAvatar($url)
+ {
+ // @fixme this should be better encapsulated
+ // ripped from oauthstore.php (for old OMB client)
+ $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
+ copy($url, $temp_filename);
+ $imagefile = new ImageFile($profile->id, $temp_filename);
+ $filename = Avatar::filename($profile->id,
+ image_type_to_extension($imagefile->type),
+ null,
+ common_timestamp());
+ rename($temp_filename, Avatar::path($filename));
+ if ($this->isGroup()) {
+ $group = $this->localGroup();
+ $group->setOriginal($filename);
+ } else {
+ $profile = $this->localProfile();
+ $profile->setOriginal($filename);
+ }
+ }
+
/**
* Damn dirty hack!
*/
}
}
+ /**
+ * Save PuSH subscription confirmation.
+ * Sets approximate lease start and end times and finalizes state.
+ *
+ * @param int $lease_seconds provided hub.lease_seconds parameter, if given
+ */
+ public function confirmSubscribe($lease_seconds=0)
+ {
+ $original = clone($this);
+
+ $this->sub_state = 'active';
+ $this->sub_start = common_sql_date(time());
+ if ($lease_seconds > 0) {
+ $this->sub_end = common_sql_date(time() + $lease_seconds);
+ } else {
+ $this->sub_end = null;
+ }
+ $this->lastupdate = common_sql_date();
+
+ return $this->update($original);
+ }
+
+ /**
+ * Save PuSH unsubscription confirmation.
+ * Wipes active PuSH sub info and resets state.
+ */
+ public function confirmUnsubscribe()
+ {
+ $original = clone($this);
+
+ $this->verify_token = null;
+ $this->secret = null;
+ $this->sub_state = null;
+ $this->sub_start = null;
+ $this->sub_end = null;
+ $this->lastupdate = common_sql_date();
+
+ return $this->update($original);
+ }
+
/**
* Send an unsubscription request to the hub for this feed.
* The hub will later send us a confirmation POST to /main/push/callback.