Example #1
0
 /**
  * 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));
 }
 /**
  * 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 updateWebfinger($addr)
 {
     $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);
         // TRANS: Exception.
         throw new Exception(_m('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.
         }
     }
     throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'), $addr));
 }