]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch 'testing' into 0.9.x
authorEvan Prodromou <evan@status.net>
Sat, 20 Mar 2010 21:11:42 +0000 (16:11 -0500)
committerEvan Prodromou <evan@status.net>
Sat, 20 Mar 2010 21:11:42 +0000 (16:11 -0500)
Conflicts:
lib/activity.php

1  2 
plugins/OStatus/classes/Ostatus_profile.php

index 562ab3bde51f13927e44d1f9be9c72ee60049917,efb12a2dd34fd554e8e5520c867c0a663bcee949..d2e046a602579ab18534d446198ceb746fa0c53f
@@@ -388,11 -388,17 +388,17 @@@ class Ostatus_profile extends Memcached
      {
          $feed = $doc->documentElement;
  
-         if ($feed->localName != 'feed' || $feed->namespaceURI != Activity::ATOM) {
-             common_log(LOG_ERR, __METHOD__ . ": not an Atom feed, ignoring");
-             return;
+         if ($feed->localName == 'feed' && $feed->namespaceURI == Activity::ATOM) {
+             $this->processAtomFeed($feed, $source);
+         } else if ($feed->localName == 'rss') { // @fixme check namespace
+             $this->processRssFeed($feed, $source);
+         } else {
+             throw new Exception("Unknown feed format.");
          }
+     }
  
+     public function processAtomFeed(DOMElement $feed, $source)
+     {
          $entries = $feed->getElementsByTagNameNS(Activity::ATOM, 'entry');
          if ($entries->length == 0) {
              common_log(LOG_ERR, __METHOD__ . ": no entries in feed update, ignoring");
          }
      }
  
+     public function processRssFeed(DOMElement $rss, $source)
+     {
+         $channels = $rss->getElementsByTagName('channel');
+         if ($channels->length == 0) {
+             throw new Exception("RSS feed without a channel.");
+         } else if ($channels->length > 1) {
+             common_log(LOG_WARNING, __METHOD__ . ": more than one channel in an RSS feed");
+         }
+         $channel = $channels->item(0);
+         $items = $channel->getElementsByTagName('item');
+         for ($i = 0; $i < $items->length; $i++) {
+             $item = $items->item($i);
+             $this->processEntry($item, $channel, $source);
+         }
+     }
      /**
       * Process a posted entry from this feed source.
       *
                  return false;
              }
          } else {
-             // Individual user feeds may contain only posts from themselves.
-             // Authorship is validated against the profile URI on upper layers,
-             // through PuSH setup or Salmon signature checks.
-             $actorUri = self::getActorProfileURI($activity);
-             if ($actorUri == $this->uri) {
-                 // Check if profile info has changed and update it
-                 $this->updateFromActivityObject($activity->actor);
+             $actor = $activity->actor;
+             if (empty($actor)) {
+                 // OK here! assume the default
+             } else if ($actor->id == $this->uri || $actor->link == $this->uri) {
+                 $this->updateFromActivityObject($actor);
              } else {
-                 common_log(LOG_WARNING, "OStatus: skipping post with bad author: got $actorUri expected $this->uri");
-                 return false;
+                 throw new Exception("Got an actor '{$actor->title}' ({$actor->id}) on single-user feed for {$this->uri}");
              }
              $oprofile = $this;
          }
  
+         // It's not always an ActivityObject::NOTE, but... let's just say it is.
+         $note = $activity->object;
          // 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->object->id;
+         $sourceUri = $note->id;
          $dupe = Notice::staticGet('uri', $sourceUri);
          if ($dupe) {
              common_log(LOG_INFO, "OStatus: ignoring duplicate post: $sourceUri");
  
          // We'll also want to save a web link to the original notice, if provided.
          $sourceUrl = null;
-         if ($activity->object->link) {
-             $sourceUrl = $activity->object->link;
+         if ($note->link) {
+             $sourceUrl = $note->link;
          } else if ($activity->link) {
              $sourceUrl = $activity->link;
-         } else if (preg_match('!^https?://!', $activity->object->id)) {
-             $sourceUrl = $activity->object->id;
+         } else if (preg_match('!^https?://!', $note->id)) {
+             $sourceUrl = $note->id;
+         }
+         // Use summary as fallback for content
+         if (!empty($note->content)) {
+             $sourceContent = $note->content;
+         } else if (!empty($note->summary)) {
+             $sourceContent = $note->summary;
+         } else if (!empty($note->title)) {
+             $sourceContent = $note->title;
+         } else {
+             // @fixme fetch from $sourceUrl?
+             throw new ClientException("No content for notice {$sourceUri}");
          }
  
          // Get (safe!) HTML and text versions of the content
-         $rendered = $this->purify($activity->object->content);
+         $rendered = $this->purify($sourceContent);
          $content = html_entity_decode(strip_tags($rendered));
  
          $shortened = common_shorten_links($content);
          $attachment = null;
  
          if (Notice::contentTooLong($shortened)) {
-             $attachment = $this->saveHTMLFile($activity->object->title, $rendered);
-             $summary = $activity->object->summary;
+             $attachment = $this->saveHTMLFile($note->title, $rendered);
+             $summary = html_entity_decode(strip_tags($note->summary));
              if (empty($summary)) {
                  $summary = $content;
              }
              $shortSummary = common_shorten_links($summary);
              if (Notice::contentTooLong($shortSummary)) {
 -                $url = common_shorten_url(common_local_url('attachment',
 -                                                           array('attachment' => $attachment->id)));
 +                $url = common_shorten_url($sourceUrl);
                  $shortSummary = substr($shortSummary,
                                         0,
                                         Notice::maxContent() - (mb_strlen($url) + 2));
 -                $shortSummary .= '… ' . $url;
 -                $content = $shortSummary;
 -                $rendered = common_render_text($content);
 +                $content = $shortSummary . ' ' . $url;
 +
 +                // We mark up the attachment link specially for the HTML output
 +                // so we can fold-out the full version inline.
 +                $attachUrl = common_local_url('attachment',
 +                                              array('attachment' => $attachment->id));
 +                $rendered = common_render_text($shortSummary) .
 +                            '<a href="' . htmlspecialchars($attachUrl) .'"'.
 +                            ' class="attachment more"' .
 +                            ' title="'. htmlspecialchars(_m('Show more')) . '">' .
 +                            '&#8230;' .
 +                            '</a>';
              }
          }
  
              throw new FeedSubNoHubException();
          }
  
-         // Try to get a profile from the feed activity:subject
+         $feedEl = $discover->root;
+         if ($feedEl->tagName == 'feed') {
+             return self::ensureAtomFeed($feedEl, $hints);
+         } else if ($feedEl->tagName == 'channel') {
+             return self::ensureRssChannel($feedEl, $hints);
+         } else {
+             throw new FeedSubBadXmlException($feeduri);
+         }
+     }
  
-         $feedEl = $discover->feed->documentElement;
+     public static function ensureAtomFeed($feedEl, $hints)
+     {
+         // Try to get a profile from the feed activity:subject
  
          $subject = ActivityUtils::child($feedEl, Activity::SUBJECT, Activity::SPEC);
  
          // Sheesh. Not a very nice feed! Let's try fingerpoken in the
          // entries.
  
-         $entries = $discover->feed->getElementsByTagNameNS(Activity::ATOM, 'entry');
+         $entries = $feedEl->getElementsByTagNameNS(Activity::ATOM, 'entry');
  
          if (!empty($entries) && $entries->length > 0) {
  
          throw new FeedSubException("Can't find enough profile information to make a feed.");
      }
  
+     public static function ensureRssChannel($feedEl, $hints)
+     {
+         // @fixme we should check whether this feed has elements
+         // with different <author> or <dc:creator> elements, and... I dunno.
+         // Do something about that.
+         $obj = ActivityObject::fromRssChannel($feedEl);
+         return self::ensureActivityObjectProfile($obj, $hints);
+     }
      /**
       * Download and update given avatar image
       *
              return $hints['nickname'];
          }
  
-         // Try the definitive ID
+         // Try the profile url (like foo.example.com or example.com/user/foo)
+         $profileUrl = ($object->link) ? $object->link : $hints['profileurl'];
+         if (!empty($profileUrl)) {
+             $nickname = self::nicknameFromURI($profileUrl);
+         }
+         // Try the URI (may be a tag:, http:, acct:, ...
  
-         $nickname = self::nicknameFromURI($object->id);
+         if (empty($nickname)) {
+             $nickname = self::nicknameFromURI($object->id);
+         }
  
          // Try a Webfinger if one was passed (way) down
  
          throw new Exception("Couldn't find a valid profile for '$addr'");
      }
  
 +    /**
 +     * Store the full-length scrubbed HTML of a remote notice to an attachment
 +     * file on our server. We'll link to this at the end of the cropped version.
 +     *
 +     * @param string $title plaintext for HTML page's title
 +     * @param string $rendered HTML fragment for HTML page's body
 +     * @return File
 +     */
      function saveHTMLFile($title, $rendered)
      {
          $final = sprintf("<!DOCTYPE html>\n<html><head><title>%s</title></head>".
 -                         '<body><div>%s</div></body></html>',
 +                         '<body>%s</body></html>',
                           htmlspecialchars($title),
                           $rendered);