function prepare($args) { parent::prepare($args); $this->uri = $this->trimmed('uri'); $this->uri = Discovery::normalize($this->uri); if (Discovery::isWebfinger($this->uri)) { $parts = explode('@', substr(urldecode($this->uri), 5)); if (count($parts) == 2) { list($nick, $domain) = $parts; // @fixme confirm the domain too // @fixme if domain checking is added, ensure that it will not // cause problems with sites that have changed domains! $nick = common_canonical_nickname($nick); $this->user = User::staticGet('nickname', $nick); } } else { $this->user = User::staticGet('uri', $this->uri); if (empty($this->user)) { // try and get it by profile url $profile = Profile::staticGet('profileurl', $this->uri); if (!empty($profile)) { $this->user = User::staticGet('id', $profile->id); } } } if (!$this->user) { $this->clientError(_m('No such user.'), 404); return false; } return true; }
function handle() { $nick = $this->user->nickname; $profile = $this->user->getProfile(); if (empty($this->xrd)) { $xrd = new XRD(); } else { $xrd = $this->xrd; } if (empty($xrd->subject)) { $xrd->subject = Discovery::normalize($this->uri); } // Possible aliases for the user $uris = array($this->user->uri, $profile->profileurl); // FIXME: Webfinger generation code should live somewhere on its own $path = common_config('site', 'path'); if (empty($path)) { $uris[] = sprintf('acct:%s@%s', $nick, common_config('site', 'server')); } foreach ($uris as $uri) { if ($uri != $xrd->subject) { $xrd->alias[] = $uri; } } $xrd->links[] = array('rel' => Discovery::PROFILEPAGE, 'type' => 'text/html', 'href' => $profile->profileurl); $xrd->links[] = array('rel' => Discovery::UPDATESFROM, 'href' => common_local_url('ApiTimelineUser', array('id' => $this->user->id, 'format' => 'atom')), 'type' => 'application/atom+xml'); // hCard $xrd->links[] = array('rel' => Discovery::HCARD, 'type' => 'text/html', 'href' => common_local_url('hcard', array('nickname' => $nick))); // XFN $xrd->links[] = array('rel' => 'http://gmpg.org/xfn/11', 'type' => 'text/html', 'href' => $profile->profileurl); // FOAF $xrd->links[] = array('rel' => 'describedby', 'type' => 'application/rdf+xml', 'href' => common_local_url('foaf', array('nickname' => $nick))); // Salmon $salmon_url = common_local_url('usersalmon', array('id' => $this->user->id)); $xrd->links[] = array('rel' => Salmon::REL_SALMON, 'href' => $salmon_url); // XXX : Deprecated - to be removed. $xrd->links[] = array('rel' => Salmon::NS_REPLIES, 'href' => $salmon_url); $xrd->links[] = array('rel' => Salmon::NS_MENTIONS, 'href' => $salmon_url); // Get this user's keypair $magickey = Magicsig::staticGet('user_id', $this->user->id); if (!$magickey) { // No keypair yet, let's generate one. $magickey = new Magicsig(); $magickey->generate($this->user->id); } $xrd->links[] = array('rel' => Magicsig::PUBLICKEYREL, 'href' => 'data:application/magic-public-key,' . $magickey->toString(false)); // TODO - finalize where the redirect should go on the publisher $url = common_local_url('ostatussub') . '?profile={uri}'; $xrd->links[] = array('rel' => 'http://ostatus.org/schema/1.0/subscribe', 'template' => $url); $url = common_local_url('tagprofile') . '?uri={uri}'; $xrd->links[] = array('rel' => 'http://ostatus.org/schema/1.0/tag', 'template' => $url); header('Content-type: application/xrd+xml'); print $xrd->toXML(); }
protected function setXRD() { parent::setXRD(); // Check to see if a $config['webfinger']['owner'] has been set // and then make sure 'subject' is set to that primary identity. if ($owner = common_config('webfinger', 'owner')) { $this->xrd->aliases[] = $this->xrd->subject; $this->xrd->subject = Discovery::normalize($owner); } else { $this->xrd->subject = $this->resource; } }
protected function prepare(array $args = array()) { parent::prepare($args); // throws exception if resource is empty $this->resource = Discovery::normalize($this->trimmed('resource')); try { if (Event::handle('StartGetWebFingerResource', array($this->resource, &$this->target, $this->args))) { Event::handle('EndGetWebFingerResource', array($this->resource, &$this->target, $this->args)); } } catch (NoSuchUserException $e) { throw new ServerException($e->getMessage(), 404); } if (!$this->target instanceof WebFingerResource) { // TRANS: Error message when an object URI which we cannot find was requested throw new ServerException(_m('Resource not found in local database.'), 404); } return true; }
function prepare($args) { $this->user = User::siteOwner(); if (!$this->user) { $this->clientError(_('No such user.'), 404); return false; } $nick = common_canonical_nickname($this->user->nickname); $acct = 'acct:' . $nick . '@' . common_config('site', 'server'); $this->xrd = new XRD(); // Check to see if a $config['webfinger']['owner'] has been set if ($owner = common_config('webfinger', 'owner')) { $this->xrd->subject = Discovery::normalize($owner); $this->xrd->alias[] = $acct; } else { $this->xrd->subject = $acct; } return true; }
function prepare($args) { parent::prepare($args); $this->uri = $this->trimmed('uri'); $this->uri = Discovery::normalize($this->uri); if (Discovery::isWebfinger($this->uri)) { $parts = explode('@', substr(urldecode($this->uri), 5)); if (count($parts) == 2) { list($nick, $domain) = $parts; // @fixme confirm the domain too $nick = common_canonical_nickname($nick); $this->user = User::staticGet('nickname', $nick); } } else { $this->user = User::staticGet('uri', $this->uri); } if (!$this->user) { $this->clientError(_('用户不存在'), 404); return false; } return true; }
function handle() { $nick = $this->user->nickname; if (empty($this->xrd)) { $xrd = new XRD(); } else { $xrd = $this->xrd; } if (empty($xrd->subject)) { $xrd->subject = Discovery::normalize($this->uri); } $xrd->alias[] = $this->user->uri; $xrd->links[] = array('rel' => Discovery::PROFILEPAGE, 'type' => 'text/html', 'href' => $this->user->uri); $xrd->links[] = array('rel' => Discovery::UPDATESFROM, 'href' => common_local_url('ApiTimelineUser', array('id' => $this->user->id, 'format' => 'atom')), 'type' => 'application/atom+xml'); // hCard $xrd->links[] = array('rel' => Discovery::HCARD, 'type' => 'text/html', 'href' => common_local_url('hcard', array('nickname' => $nick))); // XFN $xrd->links[] = array('rel' => 'http://gmpg.org/xfn/11', 'type' => 'text/html', 'href' => $this->user->uri); // FOAF $xrd->links[] = array('rel' => 'describedby', 'type' => 'application/rdf+xml', 'href' => common_local_url('foaf', array('nickname' => $nick))); // Salmon $salmon_url = common_local_url('usersalmon', array('id' => $this->user->id)); $xrd->links[] = array('rel' => Salmon::NS_REPLIES, 'href' => $salmon_url); $xrd->links[] = array('rel' => Salmon::NS_MENTIONS, 'href' => $salmon_url); // Get this user's keypair $magickey = Magicsig::staticGet('user_id', $this->user->id); if (!$magickey) { // No keypair yet, let's generate one. $magickey = new Magicsig(); $magickey->generate($this->user->id); } $xrd->links[] = array('rel' => Magicsig::PUBLICKEYREL, 'href' => 'data:application/magic-public-key,' . $magickey->toString(false)); // TODO - finalize where the redirect should go on the publisher $url = common_local_url('ostatussub') . '?profile={uri}'; $xrd->links[] = array('rel' => 'http://ostatus.org/schema/1.0/subscribe', 'template' => $url); header('Content-type: text/xml'); print $xrd->toXML(); }
function handle($object) { list($user, $remote, $password) = $object; $remote = Discovery::normalize($remote); $oprofile = Ostatus_profile::ensureProfileURI($remote); if (empty($oprofile)) { // TRANS: Exception thrown when an account could not be located when it should be moved. // TRANS: %s is the remote site. throw new Exception(sprintf(_("Cannot locate account %s."), $remote)); } list($svcDocUrl, $username) = self::getServiceDocument($remote); $sink = new ActivitySink($svcDocUrl, $username, $password); $this->log(LOG_INFO, "Moving user {$user->nickname} " . "to {$remote}."); $stream = new UserActivityStream($user); // Reverse activities to run in correct chron order $acts = array_reverse($stream->activities); $this->log(LOG_INFO, "Got " . count($acts) . " activities " . "for {$user->nickname}."); $qm = QueueManager::get(); foreach ($acts as $act) { $qm->enqueue(array($act, $sink, $user->uri, $remote), 'actmove'); } $this->log(LOG_INFO, "Finished moving user {$user->nickname} " . "to {$remote}."); }
/** * 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 // TRANS: Exception. throw new Exception(_m('Not a valid webfinger address.')); } $oprofile = Ostatus_profile::getKV('uri', $uri); if ($oprofile instanceof Ostatus_profile) { return $oprofile; } } // Try looking it up $oprofile = Ostatus_profile::getKV('uri', Discovery::normalize($addr)); if ($oprofile instanceof Ostatus_profile) { self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->getUri()); 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. // @todo FIXME: Distinguish temporary failures? self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null); // TRANS: Exception. throw new Exception(_m('Not a valid webfinger address.')); } $hints = array_merge(array('webfinger' => $addr), DiscoveryHints::fromXRD($xrd)); // 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 $feedUrl = null; if (array_key_exists('feedurl', $hints)) { $feedUrl = $hints['feedurl']; 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->getUri()); 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! $profileUrl = null; if (array_key_exists('profileurl', $hints)) { $profileUrl = $hints['profileurl']; 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->getUri()); return $oprofile; } catch (OStatusShadowException $e) { // We've ended up with a remote reference to a local user or group. // @todo 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 // // @todo 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 (!is_null($profileUrl)) { $profile->profileurl = $profileUrl; } $profile_id = $profile->insert(); if ($profile_id === false) { common_log_db_error($profile, 'INSERT', __FILE__); // TRANS: Exception. %s is a webfinger address. throw new Exception(sprintf(_m('Could not save profile for "%s".'), $addr)); } $oprofile = new Ostatus_profile(); $oprofile->uri = $uri; $oprofile->salmonuri = $salmonEndpoint; $oprofile->profile_id = $profile_id; $oprofile->created = common_sql_now(); if (!is_null($feedUrl)) { $oprofile->feeduri = $feedUrl; } $result = $oprofile->insert(); if ($result === false) { $profile->delete(); common_log_db_error($oprofile, 'INSERT', __FILE__); // TRANS: Exception. %s is a webfinger address. throw new Exception(sprintf(_m('Could not save OStatus profile for "%s".'), $addr)); } self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->getUri()); return $oprofile; } // TRANS: Exception. %s is a webfinger address. throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'), $addr)); }
public static function isWebfinger($user_id) { $uri = Discovery::normalize($user_id); return substr($uri, 0, 5) == 'acct:'; }