]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/OStatus/classes/Ostatus_profile.php
Validate::uri replaced with filter_var for HTTP[S] URL checks
[quix0rs-gnu-social.git] / plugins / OStatus / classes / Ostatus_profile.php
index 8f27d86c8b4f83fd8bc7937ba370f9e1031801e1..4b81de92d895e8d5d7eb4eb3e6c5bb1ba311148a 100644 (file)
@@ -25,7 +25,6 @@ if (!defined('STATUSNET')) {
  * @package OStatusPlugin
  * @maintainer Brion Vibber <brion@status.net>
  */
-
 class Ostatus_profile extends Managed_DataObject
 {
     public $__table = 'ostatus_profile';
@@ -43,11 +42,6 @@ class Ostatus_profile extends Managed_DataObject
     public $created;
     public $modified;
 
-    public /*static*/ function staticGet($k, $v=null)
-    {
-        return parent::staticGet(__CLASS__, $k, $v);
-    }
-
     /**
      * Return table definition for Schema setup and DB_DataObject usage.
      *
@@ -89,7 +83,7 @@ class Ostatus_profile extends Managed_DataObject
     public function localProfile()
     {
         if ($this->profile_id) {
-            return Profile::staticGet('id', $this->profile_id);
+            return Profile::getKV('id', $this->profile_id);
         }
         return null;
     }
@@ -101,7 +95,7 @@ class Ostatus_profile extends Managed_DataObject
     public function localGroup()
     {
         if ($this->group_id) {
-            return User_group::staticGet('id', $this->group_id);
+            return User_group::getKV('id', $this->group_id);
         }
         return null;
     }
@@ -113,7 +107,7 @@ class Ostatus_profile extends Managed_DataObject
     public function localPeopletag()
     {
         if ($this->peopletag_id) {
-            return Profile_list::staticGet('id', $this->peopletag_id);
+            return Profile_list::getKV('id', $this->peopletag_id);
         }
         return null;
     }
@@ -141,7 +135,7 @@ class Ostatus_profile extends Managed_DataObject
      *
      * Assumes that 'activity' namespace has been previously defined.
      *
-     * @fixme replace with wrappers on asActivityObject when it's got everything.
+     * @todo FIXME: Replace with wrappers on asActivityObject when it's got everything.
      *
      * @param string $element one of 'actor', 'subject', 'object', 'target'
      * @return string
@@ -234,7 +228,7 @@ class Ostatus_profile extends Managed_DataObject
      */
     public function garbageCollect()
     {
-        $feedsub = FeedSub::staticGet('uri', $this->feeduri);
+        $feedsub = FeedSub::getKV('uri', $this->feeduri);
         return $feedsub->garbageCollect();
     }
 
@@ -301,7 +295,7 @@ class Ostatus_profile extends Managed_DataObject
                                $actor->getURI(),
                                common_date_iso8601(time()));
 
-            // @fixme consolidate all these NS settings somewhere
+            // @todo FIXME: Consolidate all these NS settings somewhere.
             $attributes = array('xmlns' => Activity::ATOM,
                                 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/',
                                 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0',
@@ -414,7 +408,7 @@ class Ostatus_profile extends Managed_DataObject
 
         if ($feed->localName == 'feed' && $feed->namespaceURI == Activity::ATOM) {
             $this->processAtomFeed($feed, $source);
-        } else if ($feed->localName == 'rss') { // @fixme check namespace
+        } else if ($feed->localName == 'rss') { // @todo FIXME: Check namespace.
             $this->processRssFeed($feed, $source);
         } else {
             // TRANS: Exception.
@@ -463,35 +457,244 @@ class Ostatus_profile extends Managed_DataObject
      * @param DOMElement $entry
      * @param DOMElement $feed for context
      * @param string $source identifier ("push" or "salmon")
+     *
+     * @return Notice Notice representing the new (or existing) activity
      */
     public function processEntry($entry, $feed, $source)
     {
         $activity = new Activity($entry, $feed);
+        return $this->processActivity($activity, $source);
+    }
 
-        if (Event::handle('StartHandleFeedEntryWithProfile', array($activity, $this)) &&
+    public function processActivity($activity, $source)
+    {
+        $notice = null;
+
+        // The "WithProfile" events were added later.
+
+        if (Event::handle('StartHandleFeedEntryWithProfile', array($activity, $this, &$notice)) &&
             Event::handle('StartHandleFeedEntry', array($activity))) {
-            // @todo process all activity objects
-            switch ($activity->objects[0]->type) {
-            case ActivityObject::ARTICLE:
-            case ActivityObject::BLOGENTRY:
-            case ActivityObject::NOTE:
-            case ActivityObject::STATUS:
-            case ActivityObject::COMMENT:
-            case null:
-                if ($activity->verb == ActivityVerb::POST) {
-                    $this->processPost($activity, $source);
-                } else {
-                    common_log(LOG_INFO, "Ignoring activity with unrecognized verb $activity->verb");
+
+            switch ($activity->verb) {
+            case ActivityVerb::POST:
+                // @todo process all activity objects
+                switch ($activity->objects[0]->type) {
+                case ActivityObject::ARTICLE:
+                case ActivityObject::BLOGENTRY:
+                case ActivityObject::NOTE:
+                case ActivityObject::STATUS:
+                case ActivityObject::COMMENT:
+                case null:
+                    $notice = $this->processPost($activity, $source);
+                    break;
+                default:
+                    // TRANS: Client exception.
+                    throw new ClientException(_m('Cannot handle that kind of post.'));
                 }
                 break;
+            case ActivityVerb::SHARE:
+                $notice = $this->processShare($activity, $source);
+                break;
             default:
-                // TRANS: Client exception.
-                throw new ClientException(_m('Cannot handle that kind of post.'));
+                common_log(LOG_INFO, "Ignoring activity with unrecognized verb $activity->verb");
             }
 
             Event::handle('EndHandleFeedEntry', array($activity));
-            Event::handle('EndHandleFeedEntryWithProfile', array($activity, $this));
+            Event::handle('EndHandleFeedEntryWithProfile', array($activity, $this, $notice));
         }
+
+        return $notice;
+    }
+
+    public function processShare($activity, $method)
+    {
+        $notice = null;
+
+        $oprofile = $this->checkAuthorship($activity);
+
+        if (empty($oprofile)) {
+            common_log(LOG_INFO, "No author matched share activity");
+            return null;
+        }
+
+        if (count($activity->objects) != 1) {
+            // TRANS: Client exception thrown when trying to share multiple activities at once.
+            throw new ClientException(_m('Can only handle share activities with exactly one object.'));
+        }
+
+        $shared = $activity->objects[0];
+
+        if (!($shared instanceof Activity)) {
+            // TRANS: Client exception thrown when trying to share a non-activity object.
+            throw new ClientException(_m('Can only handle shared activities.'));
+        }
+
+        $other = Ostatus_profile::ensureActivityObjectProfile($shared->actor);
+
+        // Save the item (or check for a dupe)
+
+        $sharedNotice = $other->processActivity($shared, $method);
+
+        if (empty($sharedNotice)) {
+            $sharedId = ($shared->id) ? $shared->id : $shared->objects[0]->id;
+            // TRANS: Client exception thrown when saving an activity share fails.
+            // TRANS: %s is a share ID.
+            throw new ClientException(sprintf(_m('Failed to save activity %s.'),
+                                              $sharedId));
+        }
+
+        // The id URI will be used as a unique identifier for for the notice,
+        // protecting against duplicate saves. It isn't required to be a URL;
+        // tag: URIs for instance are found in Google Buzz feeds.
+
+        $sourceUri = $activity->id;
+
+        $dupe = Notice::getKV('uri', $sourceUri);
+        if ($dupe) {
+            common_log(LOG_INFO, "OStatus: ignoring duplicate post: $sourceUri");
+            return $dupe;
+        }
+
+        // We'll also want to save a web link to the original notice, if provided.
+
+        $sourceUrl = null;
+        if ($activity->link) {
+            $sourceUrl = $activity->link;
+        } else if ($activity->link) {
+            $sourceUrl = $activity->link;
+        } else if (preg_match('!^https?://!', $activity->id)) {
+            $sourceUrl = $activity->id;
+        }
+
+        // Use summary as fallback for content
+
+        if (!empty($activity->content)) {
+            $sourceContent = $activity->content;
+        } else if (!empty($activity->summary)) {
+            $sourceContent = $activity->summary;
+        } else if (!empty($activity->title)) {
+            $sourceContent = $activity->title;
+        } else {
+            // @todo FIXME: Fetch from $sourceUrl?
+            // TRANS: Client exception. %s is a source URI.
+            throw new ClientException(sprintf(_m('No content for notice %s.'),$sourceUri));
+        }
+
+        // Get (safe!) HTML and text versions of the content
+
+        $rendered = $this->purify($sourceContent);
+        $content = html_entity_decode(strip_tags($rendered), ENT_QUOTES, 'UTF-8');
+
+        $shortened = common_shorten_links($content);
+
+        // If it's too long, try using the summary, and make the
+        // HTML an attachment.
+
+        $attachment = null;
+
+        if (Notice::contentTooLong($shortened)) {
+            $attachment = $this->saveHTMLFile($activity->title, $rendered);
+            $summary = html_entity_decode(strip_tags($activity->summary), ENT_QUOTES, 'UTF-8');
+            if (empty($summary)) {
+                $summary = $content;
+            }
+            $shortSummary = common_shorten_links($summary);
+            if (Notice::contentTooLong($shortSummary)) {
+                $url = common_shorten_url($sourceUrl);
+                $shortSummary = substr($shortSummary,
+                                       0,
+                                       Notice::maxContent() - (mb_strlen($url) + 2));
+                $content = $shortSummary . ' ' . $url;
+
+                // We mark up the attachment link specially for the HTML output
+                // so we can fold-out the full version inline.
+
+                // @todo FIXME i18n: This tooltip will be saved with the site's default language
+                // TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
+                // TRANS: this will usually be replaced with localised text from StatusNet core messages.
+                $showMoreText = _m('Show more');
+                $attachUrl = common_local_url('attachment',
+                                              array('attachment' => $attachment->id));
+                $rendered = common_render_text($shortSummary) .
+                            '<a href="' . htmlspecialchars($attachUrl) .'"'.
+                            ' class="attachment more"' .
+                            ' title="'. htmlspecialchars($showMoreText) . '">' .
+                            '&#8230;' .
+                            '</a>';
+            }
+        }
+
+        $options = array('is_local' => Notice::REMOTE,
+                         'url' => $sourceUrl,
+                         'uri' => $sourceUri,
+                         'rendered' => $rendered,
+                         'replies' => array(),
+                         'groups' => array(),
+                         'peopletags' => array(),
+                         'tags' => array(),
+                         'urls' => array(),
+                         'repeat_of' => $sharedNotice->id,
+                         'scope' => $sharedNotice->scope);
+
+        // Check for optional attributes...
+
+        if (!empty($activity->time)) {
+            $options['created'] = common_sql_date($activity->time);
+        }
+
+        if ($activity->context) {
+            // Any individual or group attn: targets?
+            $replies = $activity->context->attention;
+            $options['groups'] = $this->filterReplies($oprofile, $replies);
+            $options['replies'] = $replies;
+
+            // Maintain direct reply associations
+            // @todo FIXME: What about conversation ID?
+            if (!empty($activity->context->replyToID)) {
+                $orig = Notice::getKV('uri',
+                                          $activity->context->replyToID);
+                if (!empty($orig)) {
+                    $options['reply_to'] = $orig->id;
+                }
+            }
+
+            $location = $activity->context->location;
+            if ($location) {
+                $options['lat'] = $location->lat;
+                $options['lon'] = $location->lon;
+                if ($location->location_id) {
+                    $options['location_ns'] = $location->location_ns;
+                    $options['location_id'] = $location->location_id;
+                }
+            }
+        }
+
+        if ($this->isPeopletag()) {
+            $options['peopletags'][] = $this->localPeopletag();
+        }
+
+        // Atom categories <-> hashtags
+        foreach ($activity->categories as $cat) {
+            if ($cat->term) {
+                $term = common_canonical_tag($cat->term);
+                if ($term) {
+                    $options['tags'][] = $term;
+                }
+            }
+        }
+
+        // Atom enclosures -> attachment URLs
+        foreach ($activity->enclosures as $href) {
+            // @todo FIXME: Save these locally or....?
+            $options['urls'][] = $href;
+        }
+
+        $notice = Notice::saveNew($oprofile->profile_id,
+                                  $content,
+                                  'ostatus',
+                                  $options);
+
+        return $notice;
     }
 
     /**
@@ -499,14 +702,16 @@ class Ostatus_profile extends Managed_DataObject
      * @param Activity $activity
      * @param string $method 'push' or 'salmon'
      * @return mixed saved Notice or false
-     * @fixme break up this function, it's getting nasty long
+     * @todo FIXME: Break up this function, it's getting nasty long
      */
     public function processPost($activity, $method)
     {
+        $notice = null;
+
         $oprofile = $this->checkAuthorship($activity);
 
         if (empty($oprofile)) {
-            return false;
+            return null;
         }
 
         // It's not always an ActivityObject::NOTE, but... let's just say it is.
@@ -517,10 +722,10 @@ class Ostatus_profile extends Managed_DataObject
         // protecting against duplicate saves. It isn't required to be a URL;
         // tag: URIs for instance are found in Google Buzz feeds.
         $sourceUri = $note->id;
-        $dupe = Notice::staticGet('uri', $sourceUri);
+        $dupe = Notice::getKV('uri', $sourceUri);
         if ($dupe) {
             common_log(LOG_INFO, "OStatus: ignoring duplicate post: $sourceUri");
-            return false;
+            return $dupe;
         }
 
         // We'll also want to save a web link to the original notice, if provided.
@@ -542,7 +747,7 @@ class Ostatus_profile extends Managed_DataObject
         } else if (!empty($note->title)) {
             $sourceContent = $note->title;
         } else {
-            // @fixme fetch from $sourceUrl?
+            // @todo FIXME: Fetch from $sourceUrl?
             // TRANS: Client exception. %s is a source URI.
             throw new ClientException(sprintf(_m('No content for notice %s.'),$sourceUri));
         }
@@ -591,7 +796,7 @@ class Ostatus_profile extends Managed_DataObject
             }
         }
 
-        $options = array('is_local' => Notice::REMOTE_OMB,
+        $options = array('is_local' => Notice::REMOTE,
                         'url' => $sourceUrl,
                         'uri' => $sourceUri,
                         'rendered' => $rendered,
@@ -614,9 +819,9 @@ class Ostatus_profile extends Managed_DataObject
             $options['replies'] = $replies;
 
             // Maintain direct reply associations
-            // @fixme what about conversation ID?
+            // @todo FIXME: What about conversation ID?
             if (!empty($activity->context->replyToID)) {
-                $orig = Notice::staticGet('uri',
+                $orig = Notice::getKV('uri',
                                           $activity->context->replyToID);
                 if (!empty($orig)) {
                     $options['reply_to'] = $orig->id;
@@ -650,7 +855,7 @@ class Ostatus_profile extends Managed_DataObject
 
         // Atom enclosures -> attachment URLs
         foreach ($activity->enclosures as $href) {
-            // @fixme save these locally or....?
+            // @todo FIXME: Save these locally or....?
             $options['urls'][] = $href;
         }
 
@@ -697,18 +902,18 @@ class Ostatus_profile extends Managed_DataObject
         $replies = array();
         foreach (array_unique($attention_uris) as $recipient) {
             // Is the recipient a local user?
-            $user = User::staticGet('uri', $recipient);
+            $user = User::getKV('uri', $recipient);
             if ($user) {
-                // @fixme sender verification, spam etc?
+                // @todo FIXME: Sender verification, spam etc?
                 $replies[] = $recipient;
                 continue;
             }
 
             // Is the recipient a local group?
-            // $group = User_group::staticGet('uri', $recipient);
+            // $group = User_group::getKV('uri', $recipient);
             $id = OStatusPlugin::localGroupFromUrl($recipient);
             if ($id) {
-                $group = User_group::staticGet('id', $id);
+                $group = User_group::getKV('id', $id);
                 if ($group) {
                     // Deliver to all members of this local group if allowed.
                     $profile = $sender->localProfile();
@@ -728,7 +933,7 @@ class Ostatus_profile extends Managed_DataObject
                 $oprofile = Ostatus_profile::ensureProfileURI($recipient);
                 if ($oprofile->isGroup()) {
                     // Deliver to local members of this remote group.
-                    // @fixme sender verification?
+                    // @todo FIXME: Sender verification?
                     $groups[] = $oprofile->group_id;
                 } else {
                     // may be canonicalized or something
@@ -806,14 +1011,14 @@ class Ostatus_profile extends Managed_DataObject
 
         // Check if they've got an LRDD header
 
-        $lrdd = LinkHeader::getLink($response, 'lrdd', 'application/xrd+xml');
-
-        if (!empty($lrdd)) {
-
-            $xrd = Discovery::fetchXrd($lrdd);
+        $lrdd = LinkHeader::getLink($response, 'lrdd');
+        try {
+            $xrd = new XML_XRD();
+            $xrd->loadFile($lrdd);
             $xrdHints = DiscoveryHints::fromXRD($xrd);
-
             $hints = array_merge($hints, $xrdHints);
+        } catch (Exception $e) {
+            // No hints available from XRD
         }
 
         // If discovery found a feedurl (probably from LRDD), use it.
@@ -847,7 +1052,7 @@ class Ostatus_profile extends Managed_DataObject
      */
     static function getFromProfileURL($profile_url)
     {
-        $profile = Profile::staticGet('profileurl', $profile_url);
+        $profile = Profile::getKV('profileurl', $profile_url);
 
         if (empty($profile)) {
             return null;
@@ -855,7 +1060,7 @@ class Ostatus_profile extends Managed_DataObject
 
         // Is it a known Ostatus profile?
 
-        $oprofile = Ostatus_profile::staticGet('profile_id', $profile->id);
+        $oprofile = Ostatus_profile::getKV('profile_id', $profile->id);
 
         if (!empty($oprofile)) {
             return $oprofile;
@@ -863,7 +1068,7 @@ class Ostatus_profile extends Managed_DataObject
 
         // Is it a local user?
 
-        $user = User::staticGet('id', $profile->id);
+        $user = User::getKV('id', $profile->id);
 
         if (!empty($user)) {
             // @todo i18n FIXME: use sprintf and add i18n (?)
@@ -921,7 +1126,7 @@ class Ostatus_profile extends Managed_DataObject
      *
      * @param DOMElement $feedEl root element of a loaded Atom feed
      * @param array $hints additional discovery information passed from higher levels
-     * @fixme should this be marked public?
+     * @todo FIXME: Should this be marked public?
      * @return Ostatus_profile
      * @throws Exception
      */
@@ -947,7 +1152,7 @@ class Ostatus_profile extends Managed_DataObject
      *
      * @param DOMElement $feedEl root element of a loaded RSS feed
      * @param array $hints additional discovery information passed from higher levels
-     * @fixme should this be marked public?
+     * @todo FIXME: Should this be marked public?
      * @return Ostatus_profile
      * @throws Exception
      */
@@ -973,7 +1178,7 @@ class Ostatus_profile extends Managed_DataObject
             }
         }
 
-        // @fixme we should check whether this feed has elements
+        // @todo FIXME: We should check whether this feed has elements
         // with different <author> or <dc:creator> elements, and... I dunno.
         // Do something about that.
 
@@ -1011,7 +1216,7 @@ class Ostatus_profile extends Managed_DataObject
                 $this->uri));
         }
 
-        // @fixme this should be better encapsulated
+        // @todo FIXME: This should be better encapsulated
         // ripped from oauthstore.php (for old OMB client)
         $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
         try {
@@ -1025,7 +1230,7 @@ class Ostatus_profile extends Managed_DataObject
             } else {
                 $id = $this->profile_id;
             }
-            // @fixme should we be using different ids?
+            // @todo FIXME: Should we be using different ids?
             $imagefile = new ImageFile($id, $temp_filename);
             $filename = Avatar::filename($id,
                                          image_type_to_extension($imagefile->type),
@@ -1036,7 +1241,7 @@ class Ostatus_profile extends Managed_DataObject
             unlink($temp_filename);
             throw $e;
         }
-        // @fixme hardcoded chmod is lame, but seems to be necessary to
+        // @todo FIXME: Hardcoded chmod is lame, but seems to be necessary to
         // keep from accidentally saving images from command-line (queues)
         // that can't be read from web server, which causes hard-to-notice
         // problems later on:
@@ -1044,11 +1249,7 @@ class Ostatus_profile extends Managed_DataObject
         // http://status.net/open-source/issues/2663
         chmod(Avatar::path($filename), 0644);
 
-        $profile = $this->localProfile();
-        
-        if (!empty($profile)) {
-            $profile->setOriginal($filename);
-        }
+        $self->setOriginal($filename);
 
         $orig = clone($this);
         $this->avatar = $url;
@@ -1122,7 +1323,7 @@ class Ostatus_profile extends Managed_DataObject
         }
         if ($url) {
             $opts = array('allowed_schemes' => array('http', 'https'));
-            if (Validate::uri($url, $opts)) {
+            if (common_valid_http_url($url)) {
                 return $url;
             }
         }
@@ -1187,7 +1388,7 @@ class Ostatus_profile extends Managed_DataObject
     protected static function getActivityObjectProfile($object)
     {
         $uri = self::getActivityObjectProfileURI($object);
-        return Ostatus_profile::staticGet('uri', $uri);
+        return Ostatus_profile::getKV('uri', $uri);
     }
 
     /**
@@ -1218,7 +1419,7 @@ class Ostatus_profile extends Managed_DataObject
     }
 
     /**
-     * @fixme validate stuff somewhere
+     * @todo FIXME: Validate stuff somewhere.
      */
 
     /**
@@ -1243,7 +1444,7 @@ class Ostatus_profile extends Managed_DataObject
             throw new Exception(_m('No profile URI.'));
         }
 
-        $user = User::staticGet('uri', $homeuri);
+        $user = User::getKV('uri', $homeuri);
         if ($user) {
             // TRANS: Exception.
             throw new Exception(_m('Local user cannot be referenced as remote.'));
@@ -1254,9 +1455,9 @@ class Ostatus_profile extends Managed_DataObject
             throw new Exception(_m('Local group cannot be referenced as remote.'));
         }
 
-        $ptag = Profile_list::staticGet('uri', $homeuri);
+        $ptag = Profile_list::getKV('uri', $homeuri);
         if ($ptag) {
-            $local_user = User::staticGet('id', $ptag->tagger);
+            $local_user = User::getKV('id', $ptag->tagger);
             if (!empty($local_user)) {
                 // TRANS: Exception.
                 throw new Exception(_m('Local list cannot be referenced as remote.'));
@@ -1311,7 +1512,7 @@ class Ostatus_profile extends Managed_DataObject
 
             $oprofile->profile_id = $profile->insert();
             if (!$oprofile->profile_id) {
-            // TRANS: Server exception.
+                // TRANS: Server exception.
                 throw new ServerException(_m('Cannot save local profile.'));
             }
         } else if ($object->type == ActivityObject::GROUP) {
@@ -1414,7 +1615,7 @@ class Ostatus_profile extends Managed_DataObject
             $profile->profileurl = $object->link;
         } else if (array_key_exists('profileurl', $hints)) {
             $profile->profileurl = $hints['profileurl'];
-        } else if (Validate::uri($object->id, array('allowed_schemes' => array('http', 'https')))) {
+        } else if (common_valid_http_url($object->id)) {
             $profile->profileurl = $object->id;
         }
 
@@ -1444,7 +1645,7 @@ class Ostatus_profile extends Managed_DataObject
             }
         }
 
-        // @fixme tags/categories
+        // @todo FIXME: tags/categories
         // @todo tags from categories
 
         if ($profile->id) {
@@ -1657,14 +1858,14 @@ class Ostatus_profile extends Managed_DataObject
                 // TRANS: Exception.
                 throw new Exception(_m('Not a valid webfinger address.'));
             }
-            $oprofile = Ostatus_profile::staticGet('uri', $uri);
+            $oprofile = Ostatus_profile::getKV('uri', $uri);
             if (!empty($oprofile)) {
                 return $oprofile;
             }
         }
 
         // Try looking it up
-        $oprofile = Ostatus_profile::staticGet('uri', 'acct:'.$addr);
+        $oprofile = Ostatus_profile::getKV('uri', 'acct:'.$addr);
 
         if (!empty($oprofile)) {
             self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
@@ -1679,7 +1880,7 @@ class Ostatus_profile extends Managed_DataObject
             $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?
+            // @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.'));
@@ -1722,14 +1923,14 @@ class Ostatus_profile extends Managed_DataObject
                 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
+                // @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
                 //
-                // @fixme this means an error discovering from profile page
+                // @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.
             }
@@ -1842,7 +2043,7 @@ class Ostatus_profile extends Managed_DataObject
 
         // First, try to query it
 
-        $oprofile = Ostatus_profile::staticGet('uri', $uri);
+        $oprofile = Ostatus_profile::getKV('uri', $uri);
 
         // If unfound, do discovery stuff