function handle($notice) { assert($notice instanceof Notice); $this->notice = $notice; $this->user = User::staticGet($notice->profile_id); $this->pushUser(); foreach ($notice->getGroups() as $group) { $oprofile = Ostatus_profile::staticGet('group_id', $group->id); if ($oprofile) { $this->pingReply($oprofile); } else { $this->pushGroup($group->id); } } foreach ($notice->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } if (!empty($this->notice->reply_to)) { $replyTo = Notice::staticGet('id', $this->notice->reply_to); if (!empty($replyTo)) { foreach ($replyTo->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } } } return true; }
function prepare($args) { parent::prepare($args); $id = $this->trimmed('id'); if (!$id) { $this->clientError(_('No ID.')); } $this->group = User_group::staticGet('id', $id); if (empty($this->group)) { $this->clientError(_('No such group.')); } $oprofile = Ostatus_profile::staticGet('group_id', $id); if ($oprofile) { $this->clientError(_m("Can't accept remote posts for a remote group.")); } return true; }
function handle($notice) { assert($notice instanceof Notice); $this->notice = $notice; $this->user = User::staticGet('id', $notice->profile_id); try { $profile = $this->notice->getProfile(); } catch (Exception $e) { common_log(LOG_ERR, "Can't get profile for notice; skipping: " . $e->getMessage()); return true; } $this->pushUser(); foreach ($notice->getGroups() as $group) { $oprofile = Ostatus_profile::staticGet('group_id', $group->id); if ($oprofile) { $this->pingReply($oprofile); } else { $this->pushGroup($group->id); } } foreach ($notice->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } if (!empty($this->notice->reply_to)) { $replyTo = Notice::staticGet('id', $this->notice->reply_to); if (!empty($replyTo)) { foreach ($replyTo->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } } } foreach ($notice->getProfileTags() as $ptag) { $oprofile = Ostatus_profile::staticGet('peopletag_id', $ptag->id); if (!$oprofile) { $this->pushPeopletag($ptag); } } return true; }
function prepare($args) { parent::prepare($args); $id = $this->trimmed('id'); if (!$id) { // TRANS: Client error displayed trying to perform an action without providing an ID. $this->clientError(_m('No ID.')); } $this->peopletag = Profile_list::staticGet('id', $id); if (empty($this->peopletag)) { // TRANS: Client error displayed when referring to a non-existing list. $this->clientError(_m('No such list.')); } $oprofile = Ostatus_profile::staticGet('peopletag_id', $id); if (!empty($oprofile)) { // TRANS: Client error displayed when trying to send a message to a remote list. $this->clientError(_m('Cannot accept remote posts for a remote list.')); } return true; }
function fixProfile($uri) { $oprofile = Ostatus_profile::staticGet('uri', $uri); if (!$oprofile) { print "No OStatus remote profile known for URI {$uri}\n"; return false; } echo "Before:\n"; showProfileInfo($oprofile); $feedurl = $oprofile->feeduri; $client = new HttpClient(); $response = $client->get($feedurl); if ($response->isOk()) { echo "Updating profile from feed: {$feedurl}\n"; $dom = new DOMDocument(); if ($dom->loadXML($response->getBody())) { $feed = $dom->documentElement; $entries = $dom->getElementsByTagNameNS(Activity::ATOM, 'entry'); if ($entries->length) { $entry = $entries->item(0); $activity = new Activity($entry, $feed); $oprofile->checkAuthorship($activity); echo " (ok)\n"; } else { echo " (no entry; skipping)\n"; return false; } } else { echo " (bad feed; skipping)\n"; return false; } } else { echo "Failed feed fetch: {$response->getStatus()} for {$feedurl}\n"; return false; } echo "After:\n"; showProfileInfo($oprofile); return true; }
static function ensureProfileURI($uri) { $oprofile = null; // First, try to query it $oprofile = Ostatus_profile::staticGet('uri', $uri); // If unfound, do discovery stuff if (empty($oprofile)) { if (preg_match("/^(\\w+)\\:(.*)/", $uri, $match)) { $protocol = $match[1]; switch ($protocol) { case 'http': case 'https': $oprofile = Ostatus_profile::ensureProfileURL($uri); break; case 'acct': case 'mailto': $rest = $match[2]; $oprofile = Ostatus_profile::ensureWebfinger($rest); break; default: // TRANS: Server exception. // TRANS: %1$s is a protocol, %2$s is a URI. throw new ServerException(sprintf(_m('Unrecognized URI protocol for profile: %1$s (%2$s).'), $protocol, $uri)); break; } } else { // TRANS: Server exception. %s is a URI. throw new ServerException(sprintf(_m('No URI protocol for profile: %s.'), $uri)); } } return $oprofile; }
static function ensureProfileURI($uri) { $oprofile = null; // First, try to query it $oprofile = Ostatus_profile::staticGet('uri', $uri); // If unfound, do discovery stuff if (empty($oprofile)) { if (preg_match("/^(\\w+)\\:(.*)/", $uri, $match)) { $protocol = $match[1]; switch ($protocol) { case 'http': case 'https': $oprofile = Ostatus_profile::ensureProfileURL($uri); break; case 'acct': case 'mailto': $rest = $match[2]; $oprofile = Ostatus_profile::ensureWebfinger($rest); break; default: throw new ServerException("Unrecognized URI protocol for profile: {$protocol} ({$uri})"); break; } } else { throw new ServerException("No URI protocol for profile: ({$uri})"); } } return $oprofile; }
public function onStartProfileGetAtomFeed($profile, &$feed) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile->id); if (empty($oprofile)) { return true; } $feed = $oprofile->feeduri; return false; }
private function getFeed($profile) { // Ok this is a bit of a hack. ;) if (class_exists('Ostatus_profile')) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile->id); if ($oprofile) { return $oprofile->feeduri; } } var_dump('wtf'); return false; }
/** * Look up, and if necessary create, an Ostatus_profile for the remote * entity with the given webfinger address. * This should never return null -- you will either get an object or * an exception will be thrown. * * @param string $addr webfinger address * @return Ostatus_profile * @throws Exception on error conditions * @throws OStatusShadowException if this reference would obscure a local user/group */ public static function ensureWebfinger($addr) { // First, try the cache $uri = self::cacheGet(sprintf('ostatus_profile:webfinger:%s', $addr)); if ($uri !== false) { if (is_null($uri)) { // Negative cache entry throw new Exception('Not a valid webfinger address.'); } $oprofile = Ostatus_profile::staticGet('uri', $uri); if (!empty($oprofile)) { return $oprofile; } } // Try looking it up $oprofile = Ostatus_profile::staticGet('uri', 'acct:' . $addr); if (!empty($oprofile)) { self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } // Now, try some discovery $disco = new Discovery(); try { $xrd = $disco->lookup($addr); } catch (Exception $e) { // Save negative cache entry so we don't waste time looking it up again. // @fixme distinguish temporary failures? self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null); throw new Exception('Not a valid webfinger address.'); } $hints = array('webfinger' => $addr); $dhints = DiscoveryHints::fromXRD($xrd); $hints = array_merge($hints, $dhints); // If there's an Hcard, let's grab its info if (array_key_exists('hcard', $hints)) { if (!array_key_exists('profileurl', $hints) || $hints['hcard'] != $hints['profileurl']) { $hcardHints = DiscoveryHints::fromHcardUrl($hints['hcard']); $hints = array_merge($hcardHints, $hints); } } // If we got a feed URL, try that if (array_key_exists('feedurl', $hints)) { try { common_log(LOG_INFO, "Discovery on acct:{$addr} with feed URL " . $hints['feedurl']); $oprofile = self::ensureFeedURL($hints['feedurl'], $hints); self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } catch (Exception $e) { common_log(LOG_WARNING, "Failed creating profile from feed URL '{$feedUrl}': " . $e->getMessage()); // keep looking } } // If we got a profile page, try that! if (array_key_exists('profileurl', $hints)) { try { common_log(LOG_INFO, "Discovery on acct:{$addr} with profile URL {$profileUrl}"); $oprofile = self::ensureProfileURL($hints['profileurl'], $hints); self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } catch (OStatusShadowException $e) { // We've ended up with a remote reference to a local user or group. // @fixme ideally we should be able to say who it was so we can // go back and refer to it the regular way throw $e; } catch (Exception $e) { common_log(LOG_WARNING, "Failed creating profile from profile URL '{$profileUrl}': " . $e->getMessage()); // keep looking // // @fixme this means an error discovering from profile page // may give us a corrupt entry using the webfinger URI, which // will obscure the correct page-keyed profile later on. } } // XXX: try hcard // XXX: try FOAF if (array_key_exists('salmon', $hints)) { $salmonEndpoint = $hints['salmon']; // An account URL, a salmon endpoint, and a dream? Not much to go // on, but let's give it a try $uri = 'acct:' . $addr; $profile = new Profile(); $profile->nickname = self::nicknameFromUri($uri); $profile->created = common_sql_now(); if (isset($profileUrl)) { $profile->profileurl = $profileUrl; } $profile_id = $profile->insert(); if (!$profile_id) { common_log_db_error($profile, 'INSERT', __FILE__); throw new Exception("Couldn't save profile for '{$addr}'"); } $oprofile = new Ostatus_profile(); $oprofile->uri = $uri; $oprofile->salmonuri = $salmonEndpoint; $oprofile->profile_id = $profile_id; $oprofile->created = common_sql_now(); if (isset($feedUrl)) { $profile->feeduri = $feedUrl; } $result = $oprofile->insert(); if (!$result) { common_log_db_error($oprofile, 'INSERT', __FILE__); throw new Exception("Couldn't save ostatus_profile for '{$addr}'"); } self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } throw new Exception("Couldn't find a valid profile for '{$addr}'"); }
function onStartUserGroupPermalink($group, &$url) { $oprofile = Ostatus_profile::staticGet('group_id', $group->id); if ($oprofile) { // @fixme this should probably be in the user_group table // @fixme this uri not guaranteed to be a profile page $url = $oprofile->uri; return false; } }
// Not all group entries will have this filled out, though, as it's new! echo "Checking for bogus ostatus_profile entries matching local user_group.uri...\n"; $group = new User_group(); $group->joinAdd(array('uri', 'ostatus_profile:uri')); $group->joinAdd(array('id', 'local_group:group_id')); $group->find(); $count = $group->N; echo "Found {$count}...\n"; while ($group->fetch()) { $uri = $group->uri; echo "group {$group->id} ({$group->nickname}) hidden by {$uri}"; if ($dry) { echo " - skipping\n"; } else { echo " - removing bogus ostatus_profile entry..."; $evil = Ostatus_profile::staticGet('uri', $uri); $evil->delete(); echo " ok\n"; } } echo "\n"; // And there may be user_group entries remaining where we've already killed // the ostatus_profile. These were "harmless" until our lookup started actually // using the uri field, at which point we can clearly see it breaks stuff. echo "Checking for leftover bogus user_group.uri entries obscuring local_group entries...\n"; $group = new User_group(); $group->joinAdd(array('id', 'local_group:group_id'), 'LEFT'); $group->whereAdd('group_id IS NULL'); $marker = mt_rand(31337, 31337000); $groupTemplate = common_local_url('groupbyid', array('id' => $marker)); $encGroup = $group->escape($groupTemplate, true);
function onStartGetProfileFromURI($uri, &$profile) { // XXX: do discovery here instead (OStatus_profile::ensureProfileURI($uri)) $oprofile = Ostatus_profile::staticGet('uri', $uri); if (!empty($oprofile) && !$oprofile->isGroup()) { $profile = $oprofile->localProfile(); return false; } return true; }
function saveMirror() { $mirror = SubMirror::getMirror($this->user, $this->profile); if (!$mirror) { $this->clientError(_m('Requested edit of missing mirror')); } if ($this->delete) { $mirror->delete(); $oprofile = Ostatus_profile::staticGet('profile_id', $this->profile->id); if ($oprofile) { $oprofile->garbageCollect(); } } else { if ($this->style != $mirror->style) { $orig = clone $mirror; $mirror->style = $this->style; $mirror->modified = common_sql_now(); $mirror->update($orig); } } }
function saveMirror() { $mirror = SubMirror::getMirror($this->user, $this->profile); if (!$mirror) { // TRANS: Client error thrown when a mirror request is made and no result is retrieved. $this->clientError(_m('Requested edit of missing mirror.')); } if ($this->delete) { $mirror->delete(); $oprofile = Ostatus_profile::staticGet('profile_id', $this->profile->id); if ($oprofile) { $oprofile->garbageCollect(); } } else { if ($this->style != $mirror->style) { $orig = clone $mirror; $mirror->style = $this->style; $mirror->modified = common_sql_now(); $mirror->update($orig); } } }