Merge branch 'master' of git.gnu.io:Quix0r/gnu-social
authorRoland Haeder <roland@mxchange.org>
Tue, 26 May 2015 01:09:12 +0000 (03:09 +0200)
committerRoland Haeder <roland@mxchange.org>
Tue, 26 May 2015 01:09:12 +0000 (03:09 +0200)
Signed-off-by: Roland Haeder <roland@mxchange.org>
Conflicts:
actions/apifriendshipsdestroy.php
actions/apifriendshipsexists.php
actions/apifriendshipsshow.php
actions/replies.php
actions/showstream.php
classes/Notice.php
lib/docfile.php
lib/noticeform.php
plugins/APC/APCPlugin.php
plugins/Adsense/AdsensePlugin.php
plugins/Aim/AimPlugin.php
plugins/Aim/lib/aimmanager.php
plugins/Blog/BlogPlugin.php
plugins/Directory/actions/groupdirectory.php
plugins/Directory/actions/userdirectory.php
plugins/Irc/IrcPlugin.php
plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php
plugins/Irc/lib/ircmanager.php
plugins/OStatus/classes/Ostatus_profile.php
plugins/Share/actions/apitimelineretweetedtome.php
plugins/Spotify/SpotifyPlugin.php
plugins/TinyMCE/TinyMCEPlugin.php
plugins/VideoThumbnails/VideoThumbnailsPlugin.php
plugins/WebFinger/WebFingerPlugin.php
plugins/XCache/XCachePlugin.php
plugins/YammerImport/actions/yammeradminpanel.php
plugins/YammerImport/actions/yammerauth.php
plugins/YammerImport/lib/yammerimporter.php

89 files changed:
1  2 
actions/apifriendshipsexists.php
actions/apifriendshipsshow.php
actions/apitimelineuser.php
actions/doc.php
actions/invite.php
actions/register.php
actions/replies.php
actions/shownotice.php
actions/subscribe.php
classes/Avatar.php
classes/Memcached_DataObject.php
classes/Notice.php
classes/User_group.php
htaccess.sample
index.php
lib/action.php
lib/activityimporter.php
lib/attachmentlistitem.php
lib/default.php
lib/docfile.php
lib/formaction.php
lib/framework.php
lib/imagefile.php
lib/implugin.php
lib/installer.php
lib/menu.php
lib/noticeform.php
lib/noticelistitem.php
lib/plugin.php
lib/router.php
lib/rssaction.php
lib/schemaupdater.php
lib/util.php
plugins/AnonymousFave/actions/anonfavor.php
plugins/AuthCrypt/AuthCryptPlugin.php
plugins/Autocomplete/actions/autocomplete.php
plugins/Bookmark/BookmarkPlugin.php
plugins/Bookmark/actions/newbookmark.php
plugins/Cronish/CronishPlugin.php
plugins/DirectMessage/classes/Message.php
plugins/Directory/actions/groupdirectory.php
plugins/Directory/actions/userdirectory.php
plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php
plugins/DomainStatusNetwork/actions/globalapi.php
plugins/EmailRegistration/actions/emailregister.php
plugins/EmailReminder/scripts/sendemailreminder.php
plugins/EmailSummary/scripts/sendemailsummary.php
plugins/Event/actions/cancelrsvp.php
plugins/Event/actions/newrsvp.php
plugins/FacebookBridge/actions/facebookfinishlogin.php
plugins/Favorite/actions/apifavoritecreate.php
plugins/GNUsocialProfileExtensions/GNUsocialProfileExtensionsPlugin.php
plugins/LinkPreview/actions/oembedproxy.php
plugins/Mapstraction/MapstractionPlugin.php
plugins/OStatus/OStatusPlugin.php
plugins/OStatus/classes/FeedSub.php
plugins/OStatus/classes/Ostatus_profile.php
plugins/OStatus/lib/salmonaction.php
plugins/Oembed/actions/oembed.php
plugins/OpenID/OpenIDPlugin.php
plugins/OpportunisticQM/OpportunisticQMPlugin.php
plugins/OpportunisticQM/lib/opportunisticqueuemanager.php
plugins/Poll/actions/newpoll.php
plugins/Poll/actions/respondpoll.php
plugins/Poll/classes/Poll.php
plugins/Poll/classes/Poll_response.php
plugins/QnA/QnAPlugin.php
plugins/QnA/actions/qnaclosequestion.php
plugins/QnA/actions/qnanewanswer.php
plugins/QnA/actions/qnanewquestion.php
plugins/QnA/actions/qnareviseanswer.php
plugins/QnA/actions/qnavote.php
plugins/QnA/classes/QnA_Answer.php
plugins/QnA/classes/QnA_Question.php
plugins/RSSCloud/RSSCloudPlugin.php
plugins/Realtime/scripts/cleanupchannels.php
plugins/Recaptcha/RecaptchaPlugin.php
plugins/SearchSub/actions/searchsub.php
plugins/Share/actions/apistatusesretweets.php
plugins/Share/actions/apitimelineretweetedbyme.php
plugins/Share/actions/apitimelineretweetedtome.php
plugins/Share/actions/apitimelineretweetsofme.php
plugins/TagSub/actions/tagsub.php
plugins/TwitterBridge/actions/twitterauthorization.php
plugins/VideoThumbnails/VideoThumbnailsPlugin.php
plugins/WikiHowProfile/WikiHowProfilePlugin.php
scripts/commandline.inc.php
scripts/upgrade.php
statistics_plugin

Simple merge
Simple merge
Simple merge
diff --cc actions/doc.php
Simple merge
Simple merge
Simple merge
index 11d9c7c706cc29a777a326fa5b3e96ece2799e56,49098d0950781f62942b29dc0fb131089e70e0fc..c6e5ad841c3921f7a52f37739236a75cb6adad1c
@@@ -229,7 -183,7 +183,7 @@@ class RepliesAction extends ManagedActi
          $this->elementEnd('div');
      }
  
-     function isReadOnly(array $args=array())
 -    public function isReadOnly($args)
++    public function isReadOnly(array $args = array())
      {
          return true;
      }
Simple merge
Simple merge
Simple merge
Simple merge
index 3825e07a0f51745cd770f23c6c6e77491acc7e85,38e31cb2745189ff0a3b41ee1711f48803318e0e..269b846f24d4f71a87b47b328764d83eece2982c
@@@ -1766,13 -1768,12 +1768,12 @@@ class Notice extends Managed_DataObjec
  
          $ids = array();
  
-               foreach ($gis[$this->id] as $gi)
-               {
+               foreach ($gis[$this->id] as $gi) {
                    $ids[] = $gi->group_id;
                }
-               
                $groups = User_group::multiGet('id', $ids);
 -              $this->_groups[$this->id] = $groups->fetchAll();
 +              $this->_setGroups($groups->fetchAll());
                return $this->_groups[$this->id];
      }
  
                  }
              }
  
-             // Only for followers of the author
-             $author = null;
+             if (!$foundOne) {
+                 return false;
+             }
+         }
  
-             if ($scope & Notice::FOLLOWER_SCOPE) {
+         if ($scope & Notice::FOLLOWER_SCOPE || $this->getProfile()->isPrivateStream()) {
  
-                 try {
-                     $author = $this->getProfile();
-                 } catch (Exception $e) {
-                     return false;
-                 }
-         
-                 if (!Subscription::exists($profile, $author)) {
-                     return false;
-                 }
+             if (!Subscription::exists($profile, $this->getProfile())) {
+                 return false;
              }
-             return !$this->isHiddenSpam($profile);
          }
+         return !$this->isHiddenSpam($profile);
      }
  
 -    function isHiddenSpam($profile) {
 +    function isHiddenSpam(Profile $profile=null) {
  
          // Hide posts by silenced users from everyone but moderators.
  
        return $scope;
      }
  
 -      static function fillProfiles($notices)
 +      static function fillProfiles(array $notices)
        {
                $map = self::getProfiles($notices);
-               
                foreach ($notices as $entry=>$notice) {
              try {
                        if (array_key_exists($notice->profile_id, $map)) {
                foreach ($notices as $notice) {
                        $ids[] = $notice->profile_id;
                }
-               
                $ids = array_unique($ids);
-               
-               return Profile::pivotGet('id', $ids); 
+               return Profile::pivotGet('id', $ids);
        }
  
 -      static function fillGroups(&$notices)
 +      static function fillGroups(array &$notices)
        {
          $ids = self::_idsOf($notices);
-               
          $gis = Group_inbox::listGet('notice_id', $ids);
-               
          $gids = array();
  
-               foreach ($gis as $id => $gi)
-               {
+               foreach ($gis as $id => $gi) {
                    foreach ($gi as $g)
                    {
                        $gids[] = $g->group_id;
                return array_keys($ids);
      }
  
 -    static function fillAttachments(&$notices)
 +    static function fillAttachments(array &$notices)
      {
          $ids = self::_idsOf($notices);
          $f2pMap = File_to_post::listGet('post_id', $ids);
-               
                $fileIds = array();
-               
                foreach ($f2pMap as $noticeId => $f2ps) {
              foreach ($f2ps as $f2p) {
-                 $fileIds[] = $f2p->file_id;    
+                 $fileIds[] = $f2p->file_id;
              }
          }
  
Simple merge
diff --cc htaccess.sample
Simple merge
diff --cc index.php
Simple merge
diff --cc lib/action.php
Simple merge
Simple merge
Simple merge
diff --cc lib/default.php
Simple merge
diff --cc lib/docfile.php
index 2e2afbd014de511f6c3acb75fa04eee8e56e9006,3331bcd19dc262597b97c9bebc00d8f60fae7350..583f7ebc9b3190353763ca2439f9d42f1815511c
@@@ -105,8 -113,8 +105,8 @@@ class DocFil
          $paths = array(INSTALLDIR.'/local/doc-src/',
                         INSTALLDIR.'/doc-src/');
  
-         $site = StatusNet::currentSite();
+         $site = GNUsocial::currentSite();
 -        
 +
          if (!empty($site)) {
              array_unshift($paths, INSTALLDIR.'/local/doc-src/'.$site.'/');
          }
          $paths = array(INSTALLDIR.'/local/mail-src/',
                         INSTALLDIR.'/mail-src/');
  
-         $site = StatusNet::currentSite();
+         $site = GNUsocial::currentSite();
 -        
 +
          if (!empty($site)) {
              array_unshift($paths, INSTALLDIR.'/local/mail-src/'.$site.'/');
          }
Simple merge
index 6e71fea62cbf5773852aa66725772e27192d4cf7,b71f365c244cd0e3320142c87be199dc219f1550..6fe6028f6e229699a1cfbf1152b51a1cf3ccf1ac
@@@ -102,31 -102,9 +102,31 @@@ function addPlugin($name, array $attrs=
  
  function _have_config()
  {
-     return StatusNet::haveConfig();
+     return GNUsocial::haveConfig();
  }
  
 +function common_get_temp_dir()
 +{
 +    // Try to get it from php.ini first
 +    $temp_path = trim(ini_get('upload_tmp_dir'));
 +
 +    // Is it empty?
 +    if (strlen($temp_path) == 0) {
 +        // Then try sys_get_temp_dir()
 +        $temp_path = trim(sys_get_temp_dir());
 +
 +        // Still empty?
 +        if (strlen($temp_path) == 0) {
 +            // Then set it to /tmp (ugly)
 +            // @TODO Hard-coded non-Windows stuff!
 +            $temp_path = '/tmp';
 +        }
 +    }
 +
 +    // Return found path
 +    return $temp_path;
 +}
 +
  function GNUsocial_class_autoload($cls)
  {
      if (file_exists(INSTALLDIR.'/classes/' . $cls . '.php')) {
Simple merge
index 9542d4d206d604633691360ad05cc391a26fc4b3,5b0f3dbe092fa42dbd73d01dc3e727392151d1bb..ff6eed3aa508b46327b9071c20a4531804c1f2cd
@@@ -528,11 -530,16 +530,16 @@@ abstract class ImPlugin extends Plugi
       *
       * @return boolean hook return
       */
 -    function onEndInitializeQueueManager($manager)
 +    function onEndInitializeQueueManager(QueueManager $manager)
      {
-         $manager->connect($this->transport . '-in', new ImReceiverQueueHandler($this), 'im');
-         $manager->connect($this->transport, new ImQueueHandler($this));
-         $manager->connect($this->transport . '-out', new ImSenderQueueHandler($this), 'im');
+         // If we don't require CLI mode, or if we do and GNUSOCIAL_CLI _is_ set, then connect the transports
+         // This check is made mostly because some IM plugins can't deliver to transports unless they
+         // have continously running daemons (such as XMPP) and we can't have that over HTTP requests.
+         if (!$this->requires_cli || defined('GNUSOCIAL_CLI')) {
+             $manager->connect($this->transport . '-in', new ImReceiverQueueHandler($this), 'im');
+             $manager->connect($this->transport, new ImQueueHandler($this));
+             $manager->connect($this->transport . '-out', new ImSenderQueueHandler($this), 'im');
+         }
          return true;
      }
  
Simple merge
diff --cc lib/menu.php
Simple merge
index f1f322ae332de9d75ba55e8199613155dd0d17df,f9b2309119485aa12c72ee0df0f0fa2f133c35ce..4ad6190131e6bad475023b7ac510f7c1bcdceeb6
@@@ -105,10 -103,8 +103,8 @@@ class NoticeForm extends For
  
          // When creating a notice form we don't want to collide with
          // possibly existing HTML elements, as naming conventions are similar.
 -        $this->id_suffix = rand();
 +        $this->id_suffix = mt_rand();
  
-         parent::__construct($action);
          if (is_null($options)) {
              $options = array();
          }
                      'type' => 'checkbox',
                      'class' => 'checkbox',
                      'id' => $this->id() . '-notice_data-geo',
 -                    'checked' => true, // ?
 +                    'checked' => false, // Must be unchecked by default
                  ));
-                 $this->out->text(' ');
-                 // TRANS: Field label to add location to a notice.
-                 $this->out->text(_('Share my location'));
-                 $this->out->elementEnd('label');
+                 $this->out->element('label', array('class' => 'notice_data-geo',
+                                                    'for'   => $this->id().'-notice_data-geo'),
+                                     // TRANS: Checkbox label to allow sharing geo location in notices.
+                                     _('Share my location'));
                                 
                  $this->out->elementEnd('div');
                  // TRANS: Text to not share location for a notice in notice form.
Simple merge
diff --cc lib/plugin.php
Simple merge
diff --cc lib/router.php
Simple merge
Simple merge
Simple merge
diff --cc lib/util.php
Simple merge
Simple merge
Simple merge
Simple merge
index faf38378ecbb73f00bf968f67daac65e214410e2,d47a254940e45dcc099c8004f810bb599706b2d1..b283ce8da6460cba97e48774f843b62c87860ffb
@@@ -57,9 -57,9 +57,9 @@@ class GlobalApiAction extends Actio
       * @return boolean continuation flag
       */
  
 -    function prepare($args)
 +    function prepare(array $args=array())
      {
-         StatusNet::setApi(true); // reduce exception reports to aid in debugging
+         GNUsocial::setApi(true); // reduce exception reports to aid in debugging
  
          parent::prepare($args);
  
Simple merge
Simple merge
index 095cfe03d7cbe765b891f97433e9576756f022c7,97b0942441e94a8a93bcb9663ae13c26294fed51..c0473fb597633a75929b96edc397e7153ed2039f
@@@ -46,10 -46,10 +46,10 @@@ if (!defined('STATUSNET') && !defined('
   */
  class OembedproxyAction extends OembedAction
  {
 -    function handle($args)
 +    function handle(array $args=array())
      {
          // Trigger short error responses; not a human-readable web page.
-         StatusNet::setApi(true);
+         GNUsocial::setApi(true);
  
          // We're not a general oEmbed proxy service; limit to valid sessions.
          $token = $this->trimmed('token');
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,7af4cd3ec6649959832917de0019e43188df2ee0..82e86b9264689c453f6ddd56c8f3c050de8feaa3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,126 +1,126 @@@
 -    function prepare($args)
+ <?php
+ /**
+  * StatusNet, the distributed open-source microblogging tool
+  *
+  * Show up to 100 repeats of a notice
+  *
+  * PHP version 5
+  *
+  * LICENCE: This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Affero General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Affero General Public License for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  * @category  API
+  * @package   StatusNet
+  * @author    Evan Prodromou <evan@status.net>
+  * @copyright 2009 StatusNet, Inc.
+  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link      http://status.net/
+  */
+ if (!defined('STATUSNET')) {
+     exit(1);
+ }
+ /**
+  * Show up to 100 repeats of a notice
+  *
+  * @category API
+  * @package  StatusNet
+  * @author   Evan Prodromou <evan@status.net>
+  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link     http://status.net/
+  */
+ class ApiStatusesRetweetsAction extends ApiAuthAction
+ {
+     const MAXCOUNT = 100;
+     var $original = null;
+     var $cnt      = self::MAXCOUNT;
+     /**
+      * Take arguments for running
+      *
+      * @param array $args $_REQUEST args
+      *
+      * @return boolean success flag
+      */
 -    function handle($args)
++    function prepare(array $args=array())
+     {
+         parent::prepare($args);
+         $id = $this->trimmed('id');
+         $this->original = Notice::getKV('id', $id);
+         if (empty($this->original)) {
+             // TRANS: Client error displayed trying to display redents of a non-exiting notice.
+             $this->clientError(_('No such notice.'),
+                                400, $this->format);
+             return false;
+         }
+         $cnt = $this->trimmed('count');
+         if (empty($cnt) || !is_integer($cnt)) {
+             $cnt = 100;
+         } else {
+             $this->cnt = min((int)$cnt, self::MAXCOUNT);
+         }
+         return true;
+     }
+     /**
+      * Handle the request
+      *
+      * Make a new notice for the update, save it, and show it
+      *
+      * @param array $args $_REQUEST data (unused)
+      *
+      * @return void
+      */
 -    function isReadOnly($args)
++    function handle(array $args=array())
+     {
+         parent::handle($args);
+         $strm = $this->original->repeatStream($this->cnt);
+         switch ($this->format) {
+         case 'xml':
+             $this->showXmlTimeline($strm);
+             break;
+         case 'json':
+             $this->showJsonTimeline($strm);
+             break;
+         default:
+             // TRANS: Client error displayed when coming across a non-supported API method.
+             $this->clientError(_('API method not found.'), $code = 404);
+             break;
+         }
+     }
+     /**
+      * Return true if read only.
+      *
+      * MAY override
+      *
+      * @param array $args other arguments
+      *
+      * @return boolean is read only action?
+      */
++    function isReadOnly(array $args=array())
+     {
+         return true;
+     }
+ }
index 0000000000000000000000000000000000000000,01f3fe378b17bc948aadbaf587fa0774187e60e6..4ad4e269af5544bfa563e227f0547400eb979f41
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,84 +1,84 @@@
 -    function prepare($args)
+ <?php
+ /**
+  * StatusNet, the distributed open-source microblogging tool
+  *
+  * Show authenticating user's most recent repeats
+  *
+  * PHP version 5
+  *
+  * LICENCE: This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Affero General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Affero General Public License for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  * @category  API
+  * @package   StatusNet
+  * @author    Evan Prodromou <evan@status.net>
+  * @copyright 2009 StatusNet, Inc.
+  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link      http://status.net/
+  */
+ if (!defined('STATUSNET')) {
+     exit(1);
+ }
+ /**
+  * Show authenticating user's most recent repeats
+  *
+  * @category API
+  * @package  StatusNet
+  * @author   Evan Prodromou <evan@status.net>
+  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link     http://status.net/
+  */
+ class ApiTimelineRetweetedByMeAction extends ApiAuthAction
+ {
+     const DEFAULTCOUNT = 20;
+     const MAXCOUNT     = 200;
+     const MAXNOTICES   = 3200;
+     var $repeats  = null;
+     var $cnt      = self::DEFAULTCOUNT;
+     var $page     = 1;
+     var $since_id = null;
+     var $max_id   = null;
+     /**
+      * Take arguments for running
+      *
+      * @param array $args $_REQUEST args
+      *
+      * @return boolean success flag
+      *
+      */
 -    function isReadOnly($args)
++    function prepare(array $args=array())
+     {
+         parent::prepare($args);
+         // TRANS: Server error displayed calling unimplemented API method for 'retweeted by me'.
+         $this->serverError(_('Unimplemented.'), 503);
+         return false;
+     }
+     /**
+      * Return true if read only.
+      *
+      * @param array $args other arguments
+      *
+      * @return boolean is read only action?
+      */
++    function isReadOnly(array $args=array())
+     {
+         return true;
+     }
+ }
index 0000000000000000000000000000000000000000,92d4b358fe4168dbaf6b452c4de6b5547e16ebbe..14091eedee256cd66df8ab7b144f75e38b526a3e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,162 +1,162 @@@
 -    function isReadOnly($args)
+ <?php
+ /**
+  * StatusNet, the distributed open-source microblogging tool
+  *
+  * Show most recent notices that are repeats in user's inbox
+  *
+  * PHP version 5
+  *
+  * LICENCE: This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Affero General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Affero General Public License for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  * @category  API
+  * @package   StatusNet
+  * @author    Evan Prodromou <evan@status.net>
+  * @copyright 2009 StatusNet, Inc.
+  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link      http://status.net/
+  */
+ if (!defined('GNUSOCIAL')) { exit(1); }
+ /**
+  * Show most recent notices that are repeats in user's inbox
+  *
+  * @category API
+  * @package  StatusNet
+  * @author   Evan Prodromou <evan@status.net>
+  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link     http://status.net/
+  */
+ class ApiTimelineRetweetedToMeAction extends ApiAuthAction
+ {
+     const DEFAULTCOUNT = 20;
+     const MAXCOUNT     = 200;
+     const MAXNOTICES   = 3200;
+     var $repeats  = null;
+     var $cnt      = self::DEFAULTCOUNT;
+     var $page     = 1;
+     var $since_id = null;
+     var $max_id   = null;
+     /**
+      * Take arguments for running
+      *
+      * @param array $args $_REQUEST args
+      *
+      * @return boolean success flag
+      */
+     protected function prepare(array $args=array())
+     {
+         parent::prepare($args);
+         $cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1);
+         $page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt));
+         $since_id = $this->int('since_id');
+         $max_id = $this->int('max_id');
+         return true;
+     }
+     /**
+      * Handle the request
+      *
+      * show a timeline of the user's repeated notices
+      *
+      * @return void
+      */
+     protected function handle()
+     {
+         parent::handle();
+         $offset = ($this->page-1) * $this->cnt;
+         $limit  = $this->cnt;
+         // TRANS: Title for Atom feed "repeated to me". %s is the user nickname.
+         $title      = sprintf(_("Repeated to %s"), $this->scoped->getNickname());
+         $subtitle   = sprintf(
+             // @todo FIXME: $profile is not defined.
+             // TRANS: Subtitle for API action that shows most recent notices that are repeats in user's inbox.
+             // TRANS: %1$s is the sitename, %2$s is a user nickname, %3$s is a user profile name.
+             _('%1$s notices that were to repeated to %2$s / %3$s.'),
+             $sitename, $this->scoped->getNickname(), $profile->getBestName()
+         );
+         $taguribase = TagURI::base();
+         $id         = "tag:$taguribase:RepeatedToMe:" . $this->scoped->id;
+         $link = common_local_url(
+             'all',
+              array('nickname' => $this->scoped->getNickname())
+         );
+         $strm = $this->scoped->repeatedToMe($offset, $limit, $this->since_id, $this->max_id);
+         switch ($this->format) {
+         case 'xml':
+             $this->showXmlTimeline($strm);
+             break;
+         case 'json':
+             $this->showJsonTimeline($strm);
+             break;
+         case 'atom':
+             header('Content-Type: application/atom+xml; charset=utf-8');
+             $atom = new AtomNoticeFeed($this->scoped->getUser());
+             $atom->setId($id);
+             $atom->setTitle($title);
+             $atom->setSubtitle($subtitle);
+             $atom->setUpdated('now');
+             $atom->addLink($link);
+             $id = $this->arg('id');
+             $atom->setSelfLink($self);
+             $atom->addEntryFromNotices($strm);
+             $this->raw($atom->getString());
+             break;
+         case 'as':
+             header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
+             $doc = new ActivityStreamJSONDocument($this->scoped->getUser());
+             $doc->setTitle($title);
+             $doc->addLink($link, 'alternate', 'text/html');
+             $doc->addItemsFromNotices($strm);
+             $this->raw($doc->asString());
+             break;
+         default:
+             // TRANS: Client error displayed when coming across a non-supported API method.
+             $this->clientError(_('API method not found.'), $code = 404);
+             break;
+         }
+     }
+     /**
+      * Return true if read only.
+      *
+      * MAY override
+      *
+      * @param array $args other arguments
+      *
+      * @return boolean is read only action?
+      */
++    function isReadOnly(array $args=array())
+     {
+         return true;
+     }
+ }
index 0000000000000000000000000000000000000000,fe90213665074e7e6b4e430946c22200c4c6925e..49990a53358acf17a7f56bf5434a16d2c373135c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,172 +1,172 @@@
 -    function prepare($args)
+ <?php
+ /**
+  * StatusNet, the distributed open-source microblogging tool
+  *
+  * Show authenticating user's most recent notices that have been repeated
+  *
+  * PHP version 5
+  *
+  * LICENCE: This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Affero General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Affero General Public License for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  * @category  API
+  * @package   StatusNet
+  * @author    Evan Prodromou <evan@status.net>
+  * @copyright 2009 StatusNet, Inc.
+  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link      http://status.net/
+  */
+ if (!defined('STATUSNET')) {
+     exit(1);
+ }
+ /**
+  * Show authenticating user's most recent notices that have been repeated
+  *
+  * @category API
+  * @package  StatusNet
+  * @author   Evan Prodromou <evan@status.net>
+  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+  * @link     http://status.net/
+  */
+ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction
+ {
+     const DEFAULTCOUNT = 20;
+     const MAXCOUNT     = 200;
+     const MAXNOTICES   = 3200;
+     var $repeats  = null;
+     var $cnt      = self::DEFAULTCOUNT;
+     var $page     = 1;
+     var $since_id = null;
+     var $max_id   = null;
+     /**
+      * Take arguments for running
+      *
+      * @param array $args $_REQUEST args
+      *
+      * @return boolean success flag
+      */
 -    function handle($args)
++    function prepare(array $args=array())
+     {
+         parent::prepare($args);
+         $cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1);
+         $page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt));
+         $since_id = $this->int('since_id');
+         $max_id = $this->int('max_id');
+         return true;
+     }
+     /**
+      * Handle the request
+      *
+      * show a timeline of the user's repeated notices
+      *
+      * @param array $args $_REQUEST data (unused)
+      *
+      * @return void
+      */
 -    function isReadOnly($args)
++    function handle(array $args=array())
+     {
+         parent::handle($args);
+         $offset = ($this->page-1) * $this->cnt;
+         $limit  = $this->cnt;
+         // TRANS: Title of list of repeated notices of the logged in user.
+         // TRANS: %s is the nickname of the logged in user.
+         $title      = sprintf(_("Repeats of %s"), $this->auth_user->nickname);
+         $sitename   = common_config('site', 'name');
+         $profile = $this->auth_user->getProfile();
+         $subtitle   = sprintf(
+             // TRANS: Subtitle of API time with retweets of me.
+             // TRANS: %1$s is the StatusNet sitename, %2$s is the user nickname, %3$s is the user profile name.
+             _('%1$s notices that %2$s / %3$s has repeated.'),
+             $sitename, $this->auth_user->nickname, $profile->getBestName()
+         );
+         $taguribase = TagURI::base();
+         $id         = "tag:$taguribase:RepeatsOfMe:" . $this->auth_user->id;
+         $link = common_local_url(
+             'all',
+              array('nickname' => $this->auth_user->nickname)
+         );
+         // This is a really bad query for some reason
+         if (!common_config('performance', 'high')) {
+             $strm = $this->auth_user->repeatsOfMe($offset, $limit, $this->since_id, $this->max_id);
+         } else {
+             $strm = new Notice();
+             $strm->whereAdd('0 = 1');
+             $strm->find();
+         }
+         switch ($this->format) {
+         case 'xml':
+             $this->showXmlTimeline($strm);
+             break;
+         case 'json':
+             $this->showJsonTimeline($strm);
+             break;
+         case 'atom':
+             header('Content-Type: application/atom+xml; charset=utf-8');
+             $atom = new AtomNoticeFeed($this->auth_user);
+             $atom->setId($id);
+             $atom->setTitle($title);
+             $atom->setSubtitle($subtitle);
+             $atom->setUpdated('now');
+             $atom->addLink($link);
+             $atom->setSelfLink($this->getSelfUri());
+             $atom->addEntryFromNotices($strm);
+             $this->raw($atom->getString());
+             break;
+         case 'as':
+             header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
+             $doc = new ActivityStreamJSONDocument($this->auth_user);
+             $doc->setTitle($title);
+             $doc->addLink($link, 'alternate', 'text/html');
+             $doc->addItemsFromNotices($strm);
+             $this->raw($doc->asString());
+             break;
+         default:
+             // TRANS: Client error displayed when coming across a non-supported API method.
+             $this->clientError(_('API method not found.'), 404);
+             break;
+         }
+     }
+     /**
+      * Return true if read only.
+      *
+      * MAY override
+      *
+      * @param array $args other arguments
+      *
+      * @return boolean is read only action?
+      */
++    function isReadOnly(array $args=array())
+     {
+         return true;
+     }
+ }
Simple merge
index 1244187b873bb40ec0d2dd7f00fd16c766530e1b,0000000000000000000000000000000000000000..5f2e1d86eafaedfadab8b2d2e2e6f39d12a33401
mode 100644,000000..100644
--- /dev/null
@@@ -1,248 -1,0 +1,250 @@@
 +<?php
 +/*
 + * StatusNet - a distributed open-source microblogging tool
 + * Copyright (C) 2008, 2009, StatusNet, Inc.
 + *
 + * This program is free software: you can redistribute it and/or modify
 + * it under the terms of the GNU Affero General Public License as published by
 + * the Free Software Foundation, either version 3 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU Affero General Public License for more details.
 + *
 + * You should have received a copy of the GNU Affero General Public License
 + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + */
 +
 +// -*- mode: php -*-
 +
 +# Abort if called from a web server
 +
 +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
 +    print "This script must be run from the command line\n";
 +    exit();
 +}
 +
 +define('GNUSOCIAL', true);
 +define('STATUSNET', true); //compatibility
 +
++define('GNUSOCIAL_CLI', true);  // to know we're in a CLI environment
++
 +// Set various flags so we don't time out on long-running processes
 +
 +ini_set("max_execution_time", "0");
 +ini_set("max_input_time", "0");
 +set_time_limit(0);
 +mb_internal_encoding('UTF-8');
 +error_reporting(0);
 +# DEBUG: error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED);
 +
 +// Add extlib to our path so we can get Console_Getopt
 +
 +$_extra_path = array(INSTALLDIR.'/extlib/');
 +
 +set_include_path(implode(PATH_SEPARATOR, $_extra_path) . PATH_SEPARATOR . get_include_path());
 +
 +require_once 'Console/Getopt.php';
 +
 +// Note: $shortoptions and $longoptions should be pre-defined!
 +
 +$_default_shortoptions = 'qvhc:s:p:';
 +
 +$_default_longoptions = array('quiet', 'verbose', 'help', 'conf=', 'server=', 'path=');
 +
 +if (isset($shortoptions)) {
 +    $shortoptions .= $_default_shortoptions;
 +} else {
 +    $shortoptions = $_default_shortoptions;
 +}
 +
 +if (isset($longoptions)) {
 +    $longoptions = array_merge($longoptions, $_default_longoptions);
 +} else {
 +    $longoptions = $_default_longoptions;
 +}
 +
 +$parser = new Console_Getopt();
 +
 +$result = $parser->getopt($argv, $shortoptions, $longoptions);
 +
 +if (PEAR::isError($result)) {
 +    print $result->getMessage()."\n";
 +    exit(1);
 +} else {
 +    list($options, $args) = $result;
 +}
 +
 +function show_help()
 +{
 +    global $helptext;
 +
 +    $_default_help_text = <<<END_OF_DEFAULT
 +      General options:
 +
 +    -q --quiet           Quiet (little output)
 +    -v --verbose         Verbose (lots of output)
 +    -c --conf=<filename> Use <filename> as config file
 +    -s --server=<name>   Use <name> as server name
 +    -p --path=<path>     Use <path> as path name
 +    -h --help            Show this message and quit.
 +
 +END_OF_DEFAULT;
 +    if (isset($helptext)) {
 +        print $helptext;
 +    }
 +    print $_default_help_text;
 +    exit(0);
 +}
 +
 +foreach ($options as $option) {
 +
 +    switch ($option[0]) {
 +     case '--server':
 +     case 's':
 +        $server = $option[1];
 +        break;
 +
 +     case '--path':
 +     case 'p':
 +        $path = $option[1];
 +        break;
 +
 +     case '--conf':
 +     case 'c':
 +        $conffile = $option[1];
 +        break;
 +
 +     case '--help':
 +     case 'h':
 +        show_help();
 +    }
 +}
 +
 +require_once INSTALLDIR . '/lib/common.php';
 +
 +set_error_handler('common_error_handler');
 +
 +// Set up the language infrastructure so we can localize anything that
 +// needs to be sent out to users, such as mail notifications.
 +common_init_language();
 +
 +function _make_matches($opt, $alt)
 +{
 +    $matches = array();
 +
 +    if (strlen($opt) > 1 && 0 != strncmp($opt, '--', 2)) {
 +        $matches[] = '--'.$opt;
 +    } else {
 +        $matches[] = $opt;
 +    }
 +
 +    if (!empty($alt)) {
 +        if (strlen($alt) > 1 && 0 != strncmp($alt, '--', 2)) {
 +            $matches[] = '--'.$alt;
 +        } else {
 +            $matches[] = $alt;
 +        }
 +    }
 +
 +    return $matches;
 +}
 +
 +function have_option($opt, $alt=null)
 +{
 +    global $options;
 +
 +    $matches = _make_matches($opt, $alt);
 +
 +    foreach ($options as $option) {
 +        if (in_array($option[0], $matches)) {
 +            return true;
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +function get_option_value($opt, $alt=null)
 +{
 +    global $options;
 +
 +    $matches = _make_matches($opt, $alt);
 +
 +    foreach ($options as $option) {
 +        if (in_array($option[0], $matches)) {
 +            return $option[1];
 +        }
 +    }
 +
 +    return null;
 +}
 +
 +class NoUserArgumentException extends Exception
 +{
 +}
 +
 +function getUser()
 +{
 +    $user = null;
 +
 +    if (have_option('i', 'id')) {
 +        $id = get_option_value('i', 'id');
 +        $user = User::getKV('id', $id);
 +        if (empty($user)) {
 +            throw new Exception("Can't find user with id '$id'.");
 +        }
 +    } else if (have_option('n', 'nickname')) {
 +        $nickname = get_option_value('n', 'nickname');
 +        $user = User::getKV('nickname', $nickname);
 +        if (empty($user)) {
 +            throw new Exception("Can't find user with nickname '$nickname'");
 +        }
 +    } else {
 +        throw new NoUserArgumentException("No user argument specified.");
 +    }
 +
 +    return $user;
 +}
 +
 +/** "Printf not quiet" */
 +
 +function printfnq()
 +{
 +    if (have_option('q', 'quiet')) {
 +        return null;
 +    }
 +
 +    $cargs  = func_num_args();
 +
 +    if ($cargs == 0) {
 +        return 0;
 +    }
 +
 +    $args   = func_get_args();
 +    $format = array_shift($args);
 +
 +    return vprintf($format, $args);
 +}
 +
 +/** "Print when verbose" */
 +
 +function printfv()
 +{
 +    if (!have_option('v', 'verbose')) {
 +        return null;
 +    }
 +
 +    $cargs  = func_num_args();
 +
 +    if ($cargs == 0) {
 +        return 0;
 +    }
 +
 +    $args   = func_get_args();
 +    $format = array_shift($args);
 +
 +    return vprintf($format, $args);
 +}
Simple merge
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..441a38c20487faf6078e70f1055f20a5412a2fa1
new file mode 160000 (submodule)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++Subproject commit 441a38c20487faf6078e70f1055f20a5412a2fa1