code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Create a group via the API
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Make a new group. Sets the authenticated user as the administrator of the group.
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupCreateAction extends ApiAuthAction
{
    protected $needPost = true;

    var $group       = null;
    var $nickname    = null;
    var $fullname    = null;
    var $homepage    = null;
    var $description = null;
    var $location    = null;
    var $aliasstring = null;
    var $aliases     = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->nickname    = Nickname::normalize($this->arg('nickname'), true);
        $this->fullname    = $this->arg('full_name');
        $this->homepage    = $this->arg('homepage');
        $this->description = $this->arg('description');
        $this->location    = $this->arg('location');
        $this->aliasstring = $this->arg('aliases');

        return true;
    }

    /**
     * Handle the request
     *
     * Save the new group
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        if (empty($this->user)) {
            // TRANS: Client error given when a user was not found (404).
            $this->clientError(_('No such user.'), 404);
        }

        if ($this->validateParams() == false) {
            return;
        }

        $group = User_group::register(array('nickname' => $this->nickname,
                                            'fullname' => $this->fullname,
                                            'homepage' => $this->homepage,
                                            'description' => $this->description,
                                            'location' => $this->location,
                                            'aliases'  => $this->aliases,
                                            'userid'   => $this->user->id,
                                            'local'    => true));

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlGroup($group);
            break;
        case 'json':
            $this->showSingleJsonGroup($group);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * Validate params for the new group
     *
     * @return void
     */
    function validateParams()
    {
        if (!is_null($this->homepage)
                && strlen($this->homepage) > 0
                && !common_valid_http_url($this->homepage)) {
            // TRANS: Client error in form for group creation.
            $this->clientError(_('Homepage is not a valid URL.'), 403);

        } elseif (!is_null($this->fullname)
                && mb_strlen($this->fullname) > 255) {
            // TRANS: Client error in form for group creation.
            $this->clientError(_('Full name is too long (maximum 255 characters).'), 403);

        } elseif (User_group::descriptionTooLong($this->description)) {
            // TRANS: Client error shown when providing too long a description during group creation.
            // TRANS: %d is the maximum number of allowed characters.
            $this->clientError(sprintf(_m('Description is too long (maximum %d character).',
                                'Description is too long (maximum %d characters).',
                                User_group::maxDescription()), User_group::maxDescription()), 403);

        } elseif (!is_null($this->location)
                && mb_strlen($this->location) > 255) {
            // TRANS: Client error shown when providing too long a location during group creation.
            $this->clientError(_('Location is too long (maximum 255 characters).'), 403);
        }

        if (!empty($this->aliasstring)) {
            $this->aliases = array_map(
                array('Nickname', 'normalize'), // static call to Nickname::normalize
                array_unique(preg_split('/[\s,]+/', $this->aliasstring))
            );
        } else {
            $this->aliases = array();
        }

        if (count($this->aliases) > common_config('group', 'maxaliases')) {
            $this->clientError(sprintf(
                    // TRANS: Client error shown when providing too many aliases during group creation.
                    // TRANS: %d is the maximum number of allowed aliases.
                    _m('Too many aliases! Maximum %d allowed.',
                       'Too many aliases! Maximum %d allowed.',
                       common_config('group', 'maxaliases')),
                    common_config('group', 'maxaliases')),
                403);
        }

        // Everything looks OK

        return true;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Check to see whether a user a member of a group
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Returns whether a user is a member of a specified group.
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupIsMemberAction extends ApiBareAuthAction
{
    var $group   = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */

    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->target = $this->getTargetProfile(null);
        $this->group  = $this->getTargetGroup(null);

        return true;
    }

    /**
     * Handle the request
     *
     * Save the new message
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        if (empty($this->target)) {
            // TRANS: Client error displayed when checking group membership for a non-existing user.
            $this->clientError(_('No such user.'), 404);
        }

        if (empty($this->group)) {
            // TRANS: Client error displayed when checking group membership for a non-existing group.
            $this->clientError(_('Group not found.'), 404);
        }

        $is_member = $this->target->isMember($this->group);

        switch($this->format) {
        case 'xml':
            $this->initDocument('xml');
            $this->element('is_member', null, $is_member);
            $this->endDocument('xml');
            break;
        case 'json':
            $this->initDocument('json');
            $this->showJsonObjects(array('is_member' => $is_member));
            $this->endDocument('json');
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'));
        }
    }

    /**
     * Return true if read only.
     *
     * MAY override
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return true;
    }
}

repo_name: andremichelle/gnu

license: mit


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Join a group via the API
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Joins the authenticated user to the group speicified by ID
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupJoinAction extends ApiAuthAction
{
    protected $needPost = true;

    var $group   = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->group = $this->getTargetGroup($this->arg('id'));

        return true;
    }

    /**
     * Handle the request
     *
     * Join the authenticated user to the group
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        if (empty($this->scoped)) {
            // TRANS: Client error displayed when trying to have a non-existing user join a group.
            $this->clientError(_('No such user.'), 404);
        }

        if (empty($this->group)) {
            // TRANS: Client error displayed when trying to join a group that does not exist.
            $this->clientError(_('Group not found.'), 404);
        }

        if ($this->scoped->isMember($this->group)) {
            // TRANS: Server error displayed when trying to join a group the user is already a member of.
            $this->clientError(_('You are already a member of that group.'), 403);
        }

        if (Group_block::isBlocked($this->group, $this->scoped)) {
            // TRANS: Server error displayed when trying to join a group the user is blocked from joining.
            $this->clientError(_('You have been blocked from that group by the admin.'), 403);
        }

        try {
            $this->scoped->joinGroup($this->group);
        } catch (Exception $e) {
            // TRANS: Server error displayed when joining a group failed in the database.
            // TRANS: %1$s is the joining user's nickname, $2$s is the group nickname for which the join failed.
            $this->serverError(sprintf(_('Could not join user %1$s to group %2$s.'),
                                       $this->scoped->nickname, $this->group->nickname));
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlGroup($this->group);
            break;
        case 'json':
            $this->showSingleJsonGroup($this->group);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Leave a group via the API
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Removes the authenticated user from the group specified by ID
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupLeaveAction extends ApiAuthAction
{
    protected $needPost = true;

    var $group   = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->group = $this->getTargetGroup($this->arg('id'));

        return true;
    }

    /**
     * Handle the request
     *
     * Save the new message
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        if (!$this->scoped instanceof Profile) {
            // TRANS: Client error displayed when trying to have a non-existing user leave a group.
            $this->clientError(_('No such user.'), 404);
        }

        if (!$this->group instanceof User_group) {
            // TRANS: Client error displayed when trying to leave a group that does not exist.
            $this->clientError(_('Group not found.'), 404);
        }

        $member = new Group_member();

        $member->group_id   = $this->group->id;
        $member->profile_id = $this->scoped->id;

        if (!$member->find(true)) {
            // TRANS: Server error displayed when trying to leave a group the user is not a member of.
            $this->serverError(_('You are not a member of this group.'));
        }

        try {
            $this->user->leaveGroup($this->group);
        } catch (Exception $e) {
            // TRANS: Server error displayed when leaving a group failed in the database.
            // TRANS: %1$s is the leaving user's nickname, $2$s is the group nickname for which the leave failed.
            $this->serverError(sprintf(_('Could not remove user %1$s from group %2$s.'),
                                       $this->scoped->getNickname(), $this->group->nickname));
        }
        switch($this->format) {
        case 'xml':
            $this->showSingleXmlGroup($this->group);
            break;
        case 'json':
            $this->showSingleJsonGroup($this->group);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Check to see whether a user a member of a group
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Returns whether a user is a member of a specified group.
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupListAction extends ApiBareAuthAction
{
    var $groups   = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        //TODO: Make sure this doesn't leak unwantedly for federated users
        $this->target = $this->getTargetProfile(null);

        if (!($this->target instanceof Profile)) {
            // TRANS: Client error displayed when user not found for an action.
            $this->clientError(_('No such user.'), 404);
        }

        $this->groups = $this->getGroups();

        return true;
    }

    /**
     * Handle the request
     *
     * Show the user's groups
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        $sitename   = common_config('site', 'name');
        // TRANS: Used as title in check for group membership. %s is a user name.
        $title      = sprintf(_("%s's groups"), $this->target->nickname);
        $taguribase = TagURI::base();
        $id         = "tag:$taguribase:Groups";
        $link       = common_local_url(
            'usergroups',
            array('nickname' => $this->target->nickname)
        );

        $subtitle   = sprintf(
            // TRANS: Used as subtitle in check for group membership. %1$s is the site name, %2$s is a user name.
            _('%1$s groups %2$s is a member of.'),
            $sitename,
            $this->target->nickname
        );

        switch($this->format) {
        case 'xml':
            $this->showXmlGroups($this->groups);
            break;
        case 'rss':
            $this->showRssGroups($this->groups, $title, $link, $subtitle);
            break;
        case 'atom':
            $selfuri = common_local_url('ApiGroupList', array('id'=>$this->target->id, 'format'=>'atom'));
            $this->showAtomGroups(
                $this->groups,
                $title,
                $id,
                $link,
                $subtitle,
                $selfuri
            );
            break;
        case 'json':
            $this->showJsonGroups($this->groups);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * Get groups
     *
     * @return array groups
     */
    function getGroups()
    {
        $groups = array();

        $group = $this->target->getGroups(
            ($this->page - 1) * $this->count,
            $this->count,
            $this->since_id,
            $this->max_id
        );

        while ($group->fetch()) {
            $groups[] = clone($group);
        }

        return $groups;
    }

    /**
     * Is this action read only?
     *
     * @param array $args other arguments
     *
     * @return boolean true
     */
    function isReadOnly($args)
    {
        return true;
    }

    /**
     * When was this feed last modified?
     *
     * @return string datestamp of the latest group the user has joined
     */

    function lastModified()
    {
        if (!empty($this->groups) && (count($this->groups) > 0)) {
            return strtotime($this->groups[0]->created);
        }

        return null;
    }

    /**
     * An entity tag for this list of groups
     *
     * Returns an Etag based on the action name, language, user ID and
     * timestamps of the first and last group the user has joined
     *
     * @return string etag
     */
    function etag()
    {
        if (!empty($this->groups) && (count($this->groups) > 0)) {

            $last = count($this->groups) - 1;

            return '"' . implode(
                ':',
                array($this->arg('action'),
                      common_user_cache_hash($this->auth_user),
                      common_language(),
                      $this->target->id,
                      strtotime($this->groups[0]->created),
                      strtotime($this->groups[$last]->created))
            )
            . '"';
        }

        return null;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Show the newest groups
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Returns of the lastest 20 groups for the site
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupListAllAction extends ApiPrivateAuthAction
{
    var $groups   = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    function prepare(array $args = array())
    {
        parent::prepare($args);

        $this->user   = $this->getTargetUser(null);
        $this->groups = $this->getGroups();

        return true;
    }

    /**
     * Handle the request
     *
     * Show the user's groups
     *
     * @param array $args $_REQUEST data (unused)
     *
     * @return void
     */
    function handle()
    {
        parent::handle();

        $sitename   = common_config('site', 'name');
        // TRANS: Message is used as a title when listing the lastest 20 groups. %s is a site name.
        $title      = sprintf(_("%s groups"), $sitename);
        $taguribase = TagURI::base();
        $id         = "tag:$taguribase:Groups";
        $link       = common_local_url('groups');
        // TRANS: Message is used as a subtitle when listing the latest 20 groups. %s is a site name.
        $subtitle   = sprintf(_("groups on %s"), $sitename);

        switch($this->format) {
        case 'xml':
            $this->showXmlGroups($this->groups);
            break;
        case 'rss':
            $this->showRssGroups($this->groups, $title, $link, $subtitle);
            break;
        case 'atom':
            $selfuri = common_root_url() .
                'api/statusnet/groups/list_all.atom';
            $this->showAtomGroups(
                $this->groups,
                $title,
                $id,
                $link,
                $subtitle,
                $selfuri
            );
            break;
        case 'json':
            $this->showJsonGroups($this->groups);
            break;
        default:
            $this->clientError(
                // TRANS: Client error displayed when coming across a non-supported API method.
                _('API method not found.'),
                404,
                $this->format
            );
            break;
        }
    }

    /**
     * Get groups
     *
     * @return array groups
     */
    function getGroups()
    {
        $qry = 'SELECT user_group.* '.
          'from user_group join local_group on user_group.id = local_group.group_id '.
          'order by created desc ';
        $offset = intval($this->page - 1) * intval($this->count);
        $limit = intval($this->count);
        if (common_config('db', 'type') == 'pgsql') {
            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
        } else {
            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
        }
        $group = new User_group();

        $group->query($qry);

        $groups = array();
        while ($group->fetch()) {
            $groups[] = clone($group);
        }

        return $groups;
    }

    /**
     * Is this action read only?
     *
     * @param array $args other arguments
     *
     * @return boolean true
     */
    function isReadOnly($args)
    {
        return true;
    }

    /**
     * When was this feed last modified?
     *
     * @return string datestamp of the site's latest group
     */
    function lastModified()
    {
        if (!empty($this->groups) && (count($this->groups) > 0)) {
            return strtotime($this->groups[0]->created);
        }

        return null;
    }

    /**
     * An entity tag for this list of groups
     *
     * Returns an Etag based on the action name, language, and
     * timestamps of the first and last group the user has joined
     *
     * @return string etag
     */
    function etag()
    {
        if (!empty($this->groups) && (count($this->groups) > 0)) {

            $last = count($this->groups) - 1;

            return '"' . implode(
                ':',
                array($this->arg('action'),
                      common_user_cache_hash($this->auth_user),
                      common_language(),
                      strtotime($this->groups[0]->created),
                      strtotime($this->groups[$last]->created))
            )
            . '"';
        }

        return null;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * List a group's members
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * List 20 newest members of the group specified by name or ID.
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@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 ApiGroupMembershipAction extends ApiPrivateAuthAction
{
    var $group    = null;
    var $profiles = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->group    = $this->getTargetGroup($this->arg('id'));
        if (empty($this->group)) {
            // TRANS: Client error displayed trying to show group membership on a non-existing group.
            $this->clientError(_('Group not found.'), 404);
        }

        $this->profiles = $this->getProfiles();

        return true;
    }

    /**
     * Handle the request
     *
     * Show the members of the group
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        // XXX: RSS and Atom

        switch($this->format) {
        case 'xml':
            $this->showTwitterXmlUsers($this->profiles);
            break;
        case 'json':
            $this->showJsonUsers($this->profiles);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * Fetch the members of a group
     *
     * @return array $profiles list of profiles
     */
    function getProfiles()
    {
        $profiles = array();

        $profile = $this->group->getMembers(
            ($this->page - 1) * $this->count,
            $this->count,
            $this->since_id,
            $this->max_id
        );

        while ($profile->fetch()) {
            $profiles[] = clone($profile);
        }

        return $profiles;
    }

    /**
     * Is this action read only?
     *
     * @param array $args other arguments
     *
     * @return boolean true
     */
    function isReadOnly($args)
    {
        return true;
    }

    /**
     * When was this list of profiles last modified?
     *
     * @return string datestamp of the lastest profile in the group
     */
    function lastModified()
    {
        if (!empty($this->profiles) && (count($this->profiles) > 0)) {
            return strtotime($this->profiles[0]->created);
        }

        return null;
    }

    /**
     * An entity tag for this list of groups
     *
     * Returns an Etag based on the action name, language
     * the group id, and timestamps of the first and last
     * user who has joined the group
     *
     * @return string etag
     */
    function etag()
    {
        if (!empty($this->profiles) && (count($this->profiles) > 0)) {

            $last = count($this->profiles) - 1;

            return '"' . implode(
                ':',
                array($this->arg('action'),
                      common_user_cache_hash($this->auth_user),
                      common_language(),
                      $this->group->id,
                      strtotime($this->profiles[0]->created),
                      strtotime($this->profiles[$last]->created))
            )
            . '"';
        }

        return null;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Update a group's profile
 *
 * 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    Zach Copley <zach@status.net>
 * @copyright 2010 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);
}

/**
 * API analog to the group edit page
 *
 * @category API
 * @package  StatusNet
 * @author   Zach Copley <zach@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 ApiGroupProfileUpdateAction extends ApiAuthAction
{
    protected $needPost = true;
    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     *
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->nickname    = Nickname::normalize($this->trimmed('nickname'));

        $this->fullname    = $this->trimmed('fullname');
        $this->homepage    = $this->trimmed('homepage');
        $this->description = $this->trimmed('description');
        $this->location    = $this->trimmed('location');
        $this->aliasstring = $this->trimmed('aliases');

        $this->user  = $this->auth_user;
        $this->group = $this->getTargetGroup($this->arg('id'));

        return true;
    }

    /**
     * Handle the request
     *
     * See which request params have been set, and update the profile
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        if (!in_array($this->format, array('xml', 'json'))) {
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }

        if (empty($this->user)) {
            // TRANS: Client error displayed when not providing a user or an invalid user.
            $this->clientError(_('No such user.'), 404);
        }

        if (empty($this->group)) {
            // TRANS: Client error displayed when not providing a group or an invalid group.
            $this->clientError(_('Group not found.'), 404);
        }

        if (!$this->user->isAdmin($this->group)) {
            // TRANS: Client error displayed when trying to edit a group without being an admin.
            $this->clientError(_('You must be an admin to edit the group.'), 403);
        }

        $this->group->query('BEGIN');

        $orig = clone($this->group);

        try {

            if (common_config('profile', 'changenick') == true && $this->group->nickname !== $this->nickname) {
                try {
                    $this->group->nickname = Nickname::normalize($this->nickname, true);
                } catch (NicknameException $e) {
                    throw new ApiValidationException($e->getMessage());
                }
                $this->group->mainpage = common_local_url('showgroup',
                                            array('nickname' => $this->group->nickname));
            }

            if (!empty($this->fullname)) {
                $this->validateFullname();
                $this->group->fullname = $this->fullname;
            }

            if (!empty($this->homepage)) {
                $this->validateHomepage();
                $this->group->homepage = $this->homepage;
            }

            if (!empty($this->description)) {
                $this->validateDescription();
                $this->group->description = $this->decription;
            }

            if (!empty($this->location)) {
                $this->validateLocation();
                $this->group->location = $this->location;
            }

        } catch (ApiValidationException $ave) {
            $this->clientError($ave->getMessage(), 400);
        }

        $result = $this->group->update($orig);

        if (!$result) {
            common_log_db_error($this->group, 'UPDATE', __FILE__);
            // TRANS: Server error displayed when group update fails.
            $this->serverError(_('Could not update group.'));
        }

        $aliases = array();

        try {
            if (!empty($this->aliasstring)) {
                $aliases = $this->validateAliases();
            }
        } catch (ApiValidationException $ave) {
            $this->clientError($ave->getMessage(), 403);
        }

        $result = $this->group->setAliases($aliases);

        if (!$result) {
            // TRANS: Server error displayed when adding group aliases fails.
            $this->serverError(_('Could not create aliases.'));
        }

        $this->group->query('COMMIT');

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlGroup($this->group);
            break;
        case 'json':
            $this->showSingleJsonGroup($this->group);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    function validateHomepage()
    {
        if (!is_null($this->homepage)
                && (strlen($this->homepage) > 0)
                && !common_valid_http_url($this->homepage)) {
            throw new ApiValidationException(
                // TRANS: API validation exception thrown when homepage URL does not validate.
                _('Homepage is not a valid URL.')
            );
        }
    }

    function validateFullname()
    {
        if (!is_null($this->fullname) && mb_strlen($this->fullname) > 255) {
            throw new ApiValidationException(
                // TRANS: API validation exception thrown when full name does not validate.
                _('Full name is too long (maximum 255 characters).')
            );
        }
    }

    function validateDescription()
    {
        if (User_group::descriptionTooLong($this->description)) {
            // TRANS: API validation exception thrown when description does not validate.
            // TRANS: %d is the maximum description length and used for plural.
            throw new ApiValidationException(sprintf(_m('Description is too long (maximum %d character).',
                                                        'Description is too long (maximum %d characters).',
                                                        User_group::maxDescription()),
                                                     User_group::maxDescription()));
        }
    }

    function validateLocation()
    {
        if (!is_null($this->location) && mb_strlen($this->location) > 255) {
            throw new ApiValidationException(
                // TRANS: API validation exception thrown when location does not validate.
                _('Location is too long (maximum 255 characters).')
            );
        }
    }

    function validateAliases()
    {
        try {
            $aliases = array_map(array('Nickname', 'normalize'),
                            array_unique(preg_split('/[\s,]+/', $this->aliasstring)));
        } catch (NicknameException $e) {
            throw new ApiValidationException(sprintf('Error processing aliases: %s', $e->getMessage()));
        }

        if (count($aliases) > common_config('group', 'maxaliases')) {
            // TRANS: API validation exception thrown when aliases do not validate.
            // TRANS: %d is the maximum number of aliases and used for plural.
            throw new ApiValidationException(sprintf(_m('Too many aliases! Maximum %d allowed.',
                                                        'Too many aliases! Maximum %d allowed.',
                                                        common_config('group', 'maxaliases')),
                                                     common_config('group', 'maxaliases')));
        }

        return $aliases;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Show information about a group
 *
 * 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    Craig Andrews <candrews@integralblue.com>
 * @author    Evan Prodromou <evan@status.net>
 * @author    Jeffery To <jeffery.to@gmail.com>
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

/**
 * Outputs detailed information about the group specified by ID
 *
 * @category API
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @author   Evan Prodromou <evan@status.net>
 * @author   Jeffery To <jeffery.to@gmail.com>
 * @author   Zach Copley <zach@status.net>
 * @author   Michele <macno@macno.org>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class ApiGroupShowAction extends ApiPrivateAuthAction
{
    var $group = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->group = $this->getTargetGroup($this->arg('id'));

        if (empty($this->group)) {
            $alias = Group_alias::getKV(
                'alias',
                common_canonical_nickname($this->arg('id'))
            );
            if (!empty($alias)) {
                $args = array('id' => $alias->group_id, 'format' => $this->format);
                common_redirect(common_local_url('ApiGroupShow', $args), 301);
            } else {
                // TRANS: Client error displayed when trying to show a group that could not be found.
                $this->clientError(_('Group not found.'), 404);
            }
            return;
        }

        return true;
    }

    /**
     * Handle the request
     *
     * Check the format and show the user info
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlGroup($this->group);
            break;
        case 'json':
            $this->showSingleJsonGroup($this->group);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * When was this group last modified?
     *
     * @return string datestamp of the latest notice in the stream
     */
    function lastModified()
    {
        if (!empty($this->group)) {
            return strtotime($this->group->modified);
        }

        return null;
    }

    /**
     * An entity tag for this group
     *
     * Returns an Etag based on the action name, language, and
     * timestamps of the notice
     *
     * @return string etag
     */
    function etag()
    {
        if (!empty($this->group)) {

            return '"' . implode(
                ':',
                array($this->arg('action'),
                      common_user_cache_hash($this->auth_user),
                      common_language(),
                      $this->group->id,
                      strtotime($this->group->modified))
            )
            . '"';
        }

        return null;
    }

    /**
     * Return true if read only.
     *
     * MAY override
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return true;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Test that you can connect to the API
 *
 * 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>
 * @author    Zach Copley <zach@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); }

/**
 * Returns the string "ok" in the requested format with a 200 OK HTTP status code.
 *
 * @category API
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Zach Copley <zach@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 ApiHelpTestAction extends ApiPrivateAuthAction
{
    protected function handle()
    {
        parent::handle();

        if ($this->format == 'xml') {
            $this->initDocument('xml');
            $this->element('ok', null, 'true');
            $this->endDocument('xml');
        } elseif ($this->format == 'json') {
            $this->initDocument('json');
            print '"ok"';
            $this->endDocument('json');
        } else {
            // TRANS: Client error displayed when coming across a non-supported API method.
            throw new ClientException(_('API method not found.'), 404);
        }
    }

    /**
     * Return true if read only.
     *
     * MAY override
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return true;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Show, update or delete a list.
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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);
}

class ApiListAction extends ApiBareAuthAction
{
    /**
     * The list in question in the current request
     */
    var $list   = null;

    /**
     * Is this an update request?
     */
    var $update = false;

    /**
     * Is this a delete request?
     */
    var $delete = false;

    /**
     * Set the flags for handling the request. Show list if this is a GET
     * request, update it if it is POST, delete list if method is DELETE
     * or if method is POST and an argument _method is set to DELETE. Act
     * like we don't know if the current user has no access to the list.
     *
     * Takes parameters:
     *     - user: the user id or nickname
     *     - id:   the id of the tag or the tag itself
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->delete = ($_SERVER['REQUEST_METHOD'] == 'DELETE' ||
                            ($this->trimmed('_method') == 'DELETE' &&
                             $_SERVER['REQUEST_METHOD'] == 'POST'));

        // update list if method is POST or PUT and $this->delete is not true
        $this->update = (!$this->delete &&
                         in_array($_SERVER['REQUEST_METHOD'], array('POST', 'PUT')));

        $this->user = $this->getTargetUser($this->arg('user'));
        $this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));

        if (empty($this->list)) {
            // TRANS: Client error displayed when referring to a non-existing list.
            $this->clientError(_('List not found.'), 404);
        }

        return true;
    }

    /**
     * Handle the request
     *
     * @return boolean success flag
     */
    protected function handle()
    {
        parent::handle();

        if($this->delete) {
            $this->handleDelete();
            return true;
        }

        if($this->update) {
            $this->handlePut();
            return true;
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($this->list);
            break;
        case 'json':
            $this->showSingleJsonList($this->list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * require authentication if it is a write action or user is ambiguous
     *
     */
    function requiresAuth()
    {
        return parent::requiresAuth() ||
            $this->create || $this->delete;
    }

    /**
     * Update a list
     *
     * @return boolean success
     */
    function handlePut()
    {
        if($this->auth_user->id != $this->list->tagger) {
            // TRANS: Client error displayed when trying to update another user's list.
            $this->clientError(_('You cannot update lists that do not belong to you.'), 401);
        }

        $new_list = clone($this->list);
        $new_list->tag = common_canonical_tag($this->arg('name'));
        $new_list->description = common_canonical_tag($this->arg('description'));
        $new_list->private = ($this->arg('mode') === 'private') ? true : false;

        $result = $new_list->update($this->list);

        if(!$result) {
            // TRANS: Client error displayed when an unknown error occurs updating a list.
            $this->clientError(_('An error occured.'), 503);
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($new_list);
            break;
        case 'json':
            $this->showSingleJsonList($new_list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * Delete a list
     *
     * @return boolean success
     */
    function handleDelete()
    {
        if($this->auth_user->id != $this->list->tagger) {
            // TRANS: Client error displayed when trying to delete another user's list.
            $this->clientError(_('You cannot delete lists that do not belong to you.'), 401);
        }

        $record = clone($this->list);
        $this->list->delete();

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($record);
            break;
        case 'json':
            $this->showSingleJsonList($record);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * Indicate that this resource is not read-only.
     *
     * @return boolean is_read-only=false
     */
    function isReadOnly($args)
    {
        return false;
    }

    /**
     * When was the list (people tag) last updated?
     *
     * @return String time_last_modified
     */
    function lastModified()
    {
        if(!empty($this->list)) {
            return strtotime($this->list->modified);
        }
        return null;
    }

    /**
     * An entity tag for this list
     *
     * Returns an Etag based on the action name, language, user ID and
     * timestamps of the first and last list the user has joined
     *
     * @return string etag
     */
    function etag()
    {
        if (!empty($this->list)) {

            return '"' . implode(
                ':',
                array($this->arg('action'),
                      common_language(),
                      $this->user->id,
                      strtotime($this->list->created),
                      strtotime($this->list->modified))
            )
            . '"';
        }

        return null;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * API method to check if a user belongs to a list.
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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);
}

/**
 * Action handler for Twitter list_memeber methods
 *
 * @category API
 * @package  StatusNet
 * @author   Shashi Gowda <connect2shashi@gmail.com>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 * @see      ApiBareAuthAction
 */
class ApiListMemberAction extends ApiBareAuthAction
{
    /**
     * Set the flags for handling the request. Show the profile if this
     * is a GET request AND the profile is a member of the list, add a member
     * if it is a POST, remove the profile from the list if method is DELETE
     * or if method is POST and an argument _method is set to DELETE. Act
     * like we don't know if the current user has no access to the list.
     *
     * Takes parameters:
     *     - user: the user id or nickname
     *     - list_id: the id of the tag or the tag itself
     *     - id: the id of the member being looked for/added/removed
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->target = $this->getTargetProfile($this->arg('id'));
        $this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));

        if (empty($this->list)) {
            // TRANS: Client error displayed when referring to a non-existing list.
            $this->clientError(_('List not found.'), 404);
        }

        if (!($this->target instanceof Profile)) {
            // TRANS: Client error displayed when referring to a non-existing user.
            $this->clientError(_('No such user.'), 404);
        }
        return true;
    }

    /**
     * Handle the request
     *
     * @return boolean success flag
     */
    protected function handle()
    {
        parent::handle();

        $arr = array('tagger' => $this->list->tagger,
                      'tag' => $this->list->tag,
                      'tagged' => $this->target->id);
        $ptag = Profile_tag::pkeyGet($arr);

        if(empty($ptag)) {
            // TRANS: Client error displayed when referring to a non-list member.
            $this->clientError(_('The specified user is not a member of this list.'));
        }

        $user = $this->twitterUserArray($this->target, true);

        switch($this->format) {
        case 'xml':
            $this->showTwitterXmlUser($user, 'user', true);
            break;
        case 'json':
            $this->showSingleJsonUser($user);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
        return true;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * List/add/remove list members.
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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);
}

require_once INSTALLDIR . '/lib/apilistusers.php';

class ApiListMembersAction extends ApiListUsersAction
{
    /**
     * Add a user to a list (tag someone)
     *
     * @return boolean success
     */
    function handlePost()
    {
        if($this->auth_user->id != $this->list->tagger) {
            // TRANS: Client error displayed when trying to add members to a list without having the right to do so.
            $this->clientError(_('You are not allowed to add members to this list.'), 401);
        }

        if (!($this->target instanceof Profile)) {
            // TRANS: Client error displayed when trying to modify list members without specifying them.
            $this->clientError(_('You must specify a member.'));
        }

        $result = Profile_tag::setTag($this->auth_user->id,
                        $this->target->id, $this->list->tag);

        if(empty($result)) {
            // TRANS: Client error displayed when an unknown error occurs viewing list members.
            $this->clientError(_('An error occured.'), 500);
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($this->list);
            break;
        case 'json':
            $this->showSingleJsonList($this->list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    /**
     * Remove a user from a list (untag someone)
     *
     * @return boolean success
     */
    function handleDelete()
    {
        if($this->auth_user->id != $this->list->tagger) {
            // TRANS: Client error displayed when trying to remove members from a list without having the right to do so.
            $this->clientError(_('You are not allowed to remove members from this list.'), 401);
        }

        if (!($this->target instanceof Profile)) {
            // TRANS: Client error displayed when trying to modify list members without specifying them.
            $this->clientError(_('You must specify a member.'));
        }

        $args = array('tagger' => $this->auth_user->id,
                      'tagged' => $this->target->id,
                      'tag' => $this->list->tag);
        $ptag = Profile_tag::pkeyGet($args);

        if (empty($ptag)) {
            // TRANS: Client error displayed when trying to remove a list member that is not part of a list.
            $this->clientError(_('The user you are trying to remove from the list is not a member.'));
        }

        if (!$ptag->delete()) {
            // TRANS: Client error displayed when an unknown error occurs viewing list members.
            $this->clientError(_('An error occured.'), 500);
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($this->list);
            break;
        case 'json':
            $this->showSingleJsonList($this->list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }

        return true;
    }

    /**
     * List the members of a list (people tagged)
     */
    function getUsers()
    {
        $fn = array($this->list, 'getTagged');
        list($this->users, $this->next_cursor, $this->prev_cursor) =
            Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Get a list of lists a user belongs to. (people tags for a user)
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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);
}

/**
 * Action handler for API method to list lists a user belongs to.
 * (people tags for a user)
 *
 * @category API
 * @package  StatusNet
 * @author   Shashi Gowda <connect2shashi@gmail.com>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 * @see      ApiBareAuthAction
 */
class ApiListMembershipsAction extends ApiBareAuthAction
{
    var $lists = array();
    var $cursor = -1;
    var $next_cursor = 0;
    var $prev_cursor = 0;

    /**
     * Prepare for running the action
     * Take arguments for running:s
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     *
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->cursor = (int) $this->arg('cursor', -1);
        $user = $this->getTargetUser($this->arg('user'));

        if (!($user instanceof User)) {
            // TRANS: Client error displayed trying to perform an action related to a non-existing user.
            $this->clientError(_('No such user.'), 404);
        }
        $this->target = $user->getProfile();

        $this->getLists();

        return true;
    }

    /**
     * Handle the request
     *
     * Show the lists
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        switch($this->format) {
        case 'xml':
            $this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
            break;
        case 'json':
            $this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'));
        }
    }

    /**
     * Return true if read only.
     *
     * MAY override
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return true;
    }

    function getLists()
    {
        $fn = array($this->target, 'getOtherTags');

        # 20 lists
        list($this->lists, $this->next_cursor, $this->prev_cursor) =
                Profile_list::getAtCursor($fn, array($this->scoped), $this->cursor, 20);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * List existing lists or create a new list.
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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);
}

/**
 * Action handler for Twitter list_memeber methods
 *
 * @category API
 * @package  StatusNet
 * @author   Shashi Gowda <connect2shashi@gmail.com>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 * @see      ApiBareAuthAction
 */
class ApiListsAction extends ApiBareAuthAction
{
    var $lists   = null;
    var $cursor = 0;
    var $next_cursor = 0;
    var $prev_cursor = 0;
    var $create = false;

    /**
     * Set the flags for handling the request. List lists created by user if this
     * is a GET request, create a new list if it is a POST request.
     *
     * Takes parameters:
     *     - user: the user id or nickname
     * Parameters for POST request
     *     - name: name of the new list (the people tag itself)
     *     - mode: (optional) mode for the new list private/public
     *     - description: (optional) description for the list
     *
     * @return boolean success flag
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->create = ($_SERVER['REQUEST_METHOD'] == 'POST');

        if (!$this->create) {

            $this->user = $this->getTargetUser($this->arg('user'));

            if (!($user instanceof User)) {
                // TRANS: Client error displayed trying to perform an action related to a non-existing user.
                $this->clientError(_('No such user.'), 404);
            }
            $this->target = $user->getProfile();
            $this->getLists();
        }

        return true;
    }

    /**
     * require authentication if it is a write action or user is ambiguous
     *
     */
    function requiresAuth()
    {
        return parent::requiresAuth() ||
            $this->create || $this->delete;
    }

    /**
     * Handle request:
     *     Show the lists the user has created if the request method is GET
     *     Create a new list by diferring to handlePost() if it is POST.
     */
    protected function handle()
    {
        parent::handle();

        if($this->create) {
            return $this->handlePost();
        }

        switch($this->format) {
        case 'xml':
            $this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
            break;
        case 'json':
            $this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
            break;
        default:
            $this->clientError(
                // TRANS: Client error displayed when coming across a non-supported API method.
                _('API method not found.'),
                404,
                $this->format
            );
            break;
        }
    }

    /**
     * Create a new list
     *
     * @return boolean success
     */
    function handlePost()
    {
        $name=$this->arg('name');
        if(empty($name)) {
            // mimick twitter
            // TRANS: Client error displayed when trying to create a list without a name.
            print _("A list must have a name.");
            exit(1);
        }

        // twitter creates a new list by appending a number to the end
        // if the list by the given name already exists
        // it makes more sense to return the existing list instead

        $private = null;
        if ($this->arg('mode') === 'public') {
            $private = false;
        } else if ($this->arg('mode') === 'private') {
            $private = true;
        }

        $list = Profile_list::ensureTag($this->auth_user->id,
                                        $this->arg('name'),
                                        $this->arg('description'),
                                        $private);
        if (empty($list)) {
            return false;
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($list);
            break;
        case 'json':
            $this->showSingleJsonList($list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
        return true;
    }

    /**
     * Get lists
     */
    function getLists()
    {
        $cursor = (int) $this->arg('cursor', -1);

        // twitter fixes count at 20
        // there is no argument named count
        $count = 20;
        $fn = array($this->target, 'getLists');

        list($this->lists,
             $this->next_cursor,
             $this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->scoped), $cursor, $count);
    }

    function isReadOnly($args)
    {
        return false;
    }

    function lastModified()
    {
        if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
            return strtotime($this->lists[0]->created);
        }

        return null;
    }

    /**
     * An entity tag for this list of lists
     *
     * Returns an Etag based on the action name, language, user ID and
     * timestamps of the first and last list the user has joined
     *
     * @return string etag
     */
    function etag()
    {
        if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {

            $last = count($this->lists) - 1;

            return '"' . implode(
                ':',
                array($this->arg('action'),
                      common_language(),
                      $this->target->id,
                      strtotime($this->lists[0]->created),
                      strtotime($this->lists[$last]->created))
            )
            . '"';
        }

        return null;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Check if a user is subscribed to a list
 *
 * 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
 * @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);
}

class ApiListSubscriberAction extends ApiBareAuthAction
{
    var $list   = null;

    function prepare(array $args = array())
    {
        parent::prepare($args);

        $this->target = $this->getTargetProfile($this->arg('id'));
        $this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));

        if (empty($this->list)) {
            // TRANS: Client error displayed trying to perform an action related to a non-existing list.
            $this->clientError(_('List not found.'), 404);
        }

        if (!($this->target instanceof Profile)) {
            // TRANS: Client error displayed trying to perform an action related to a non-existing user.
            $this->clientError(_('No such user.'), 404);
        }
        return true;
    }

    function handle()
    {
        parent::handle();

        $arr = array('profile_tag_id' => $this->list->id,
                      'profile_id' => $this->target->id);
        $sub = Profile_tag_subscription::pkeyGet($arr);

        if(empty($sub)) {
            // TRANS: Client error displayed when a membership check for a user is nagative.
            $this->clientError(_('The specified user is not a subscriber of this list.'));
        }

        $user = $this->twitterUserArray($this->target, true);

        switch($this->format) {
        case 'xml':
            $this->showTwitterXmlUser($user, 'user', true);
            break;
        case 'json':
            $this->showSingleJsonUser($user);
            break;
        default:
            $this->clientError(
                // TRANS: Client error displayed when coming across a non-supported API method.
                _('API method not found.'),
                404,
                $this->format
            );
            break;
        }
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Show/add/remove list subscribers.
 *
 * 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
 * @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);
}

require_once INSTALLDIR . '/lib/apilistusers.php';

class ApiListSubscribersAction extends ApiListUsersAction
{
    /**
     * Subscribe to list
     *
     * @return boolean success
     */
    function handlePost()
    {
        $result = Profile_tag_subscription::add($this->list,
                            $this->auth_user);

        if(empty($result)) {
            // TRANS: Client error displayed when an unknown error occurs in the list subscribers action.
            $this->clientError(_('An error occured.'), 500);
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($this->list);
            break;
        case 'json':
            $this->showSingleJsonList($this->list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
    }

    function handleDelete()
    {
        $args = array('profile_tag_id' => $this->list->id,
                      'profile_id' => $this->auth_user->id);
        $ptag = Profile_tag_subscription::pkeyGet($args);

        if(empty($ptag)) {
            // TRANS: Client error displayed when trying to unsubscribe from a non-subscribed list.
            $this->clientError(_('You are not subscribed to this list.'));
        }

        $result = Profile_tag_subscription::remove($this->list, $this->auth_user);

        if (empty($result)) {
            // TRANS: Client error displayed when an unknown error occurs unsubscribing from a list.
            $this->clientError(_('An error occured.'), 500);
        }

        switch($this->format) {
        case 'xml':
            $this->showSingleXmlList($this->list);
            break;
        case 'json':
            $this->showSingleJsonList($this->list);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'), 404);
        }
        return true;
    }

    function getUsers()
    {
        $fn = array($this->list, 'getSubscribers');
        list($this->users, $this->next_cursor, $this->prev_cursor) =
            Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Get a list of lists a user is subscribed to.
 *
 * 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
 * @copyright 2009 StatusNet, Inc.
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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);
}

class ApiListSubscriptionsAction extends ApiBareAuthAction
{
    var $lists = array();
    var $cursor = -1;
    var $next_cursor = 0;
    var $prev_cursor = 0;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @return boolean success flag
     *
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        $this->cursor = (int) $this->arg('cursor', -1);
        $user = $this->getTargetUser($this->arg('user'));
        if (!($user instanceof User)) {
            // TRANS: Client error displayed trying to perform an action related to a non-existing user.
            $this->clientError(_('No such user.'), 404);
        }
        $this->target = $user->getProfile();
        $this->getLists();

        return true;
    }

    /**
     * Handle the request
     *
     * Show the lists
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();

        switch($this->format) {
        case 'xml':
            $this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
            break;
        case 'json':
            $this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
            break;
        default:
            // TRANS: Client error displayed when coming across a non-supported API method.
            $this->clientError(_('API method not found.'));
        }
    }

    /**
     * Return true if read only.
     *
     * MAY override
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return true;
    }

    function getLists()
    {
        $fn = array($this->target, 'getTagSubscriptions');
        # 20 lists
        list($this->lists, $this->next_cursor, $this->prev_cursor) =
                Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Upload an image via the API
 *
 * 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
 * @author    Zach Copley <zach@status.net>
 * @copyright 2010 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); }

/**
 * Upload an image via the API.  Returns a shortened URL for the image
 * to the user. Apparently modelled after a former Twitpic API.
 *
 * @category API
 * @package  StatusNet
 * @author   Zach Copley <zach@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 ApiMediaUploadAction extends ApiAuthAction
{
    protected $needPost = true;

    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        // fallback to xml for older clients etc
        if (empty($this->format)) {
            $this->format = 'xml';
        }
        if (!in_array($this->format, ['json', 'xml'])) {
            throw new ClientException('This API call does not support the format '._ve($this->format));
        }
        return true;
    }

    protected function handle()
    {
        parent::handle();

        // Workaround for PHP returning empty $_POST and $_FILES when POST
        // length > post_max_size in php.ini

        if (empty($_FILES)
            && empty($_POST)
            && ($_SERVER['CONTENT_LENGTH'] > 0)
        ) {
            // TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit.
            // TRANS: %s is the number of bytes of the CONTENT_LENGTH.
            $msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
                      'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
                      intval($_SERVER['CONTENT_LENGTH']));
            throw new ClientException(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
        }

        try {
            $upload = MediaFile::fromUpload('media', $this->scoped);
        } catch (NoUploadedMediaException $e) {
            common_debug('No media file was uploaded to the _FILES array');
            $fh = tmpfile();
            if ($this->arg('media')) {
                common_debug('Found media parameter which we hope contains a media file!');
                fwrite($fh, $this->arg('media'));
            } elseif ($this->arg('media_data')) {
                common_debug('Found media_data parameter which we hope contains a base64-encoded media file!');
                fwrite($fh, base64_decode($this->arg('media_data')));
            } else {
                common_debug('No media|media_data POST parameter was supplied');
                fclose($fh);
                throw $e;
            }
            common_debug('MediaFile importing the uploaded file with fromFilehandle');
            $upload = MediaFile::fromFilehandle($fh, $this->scoped);
        }

        common_debug('MediaFile completed and saved us fileRecord with id=='._ve($upload->fileRecord->id));
        // Thumbnails will be generated/cached on demand when accessed (such as with /attachment/:id/thumbnail)
        $this->showResponse($upload);
    }

    /**
     * Show a Twitpic-like response with the ID of the media file
     * and a (hopefully) shortened URL for it.
     *
     * @param MediaFile $upload  the uploaded file
     *
     * @return void
     */
    protected function showResponse(MediaFile $upload)
    {
        $this->initDocument($this->format);
        switch ($this->format) {
        case 'json':
            return $this->showResponseJson($upload);
        case 'xml':
            return $this->showResponseXml($upload);
        default:
            throw new ClientException('This API call does not support the format '._ve($this->format));
        }
        $this->endDocument($this->format);
    }

    protected function showResponseJson(MediaFile $upload)
    {
        $enc = $upload->fileRecord->getEnclosure();

        // note that we use media_id instead of mediaid which XML users might've gotten used to (nowadays we service media_id in both!)
        $output = [
                'media_id' => $upload->fileRecord->id,
                'media_id_string' => (string)$upload->fileRecord->id,
                'media_url' => $upload->shortUrl(),
                'size' => $upload->fileRecord->size,
                ];
        if (common_get_mime_media($enc->mimetype) === 'image') {
            $output['image'] = [
                                'w' => $enc->width,
                                'h' => $enc->height,
                                'image_type' => $enc->mimetype,
                                ];
        }
        print json_encode($output);
    }

    protected function showResponseXml(MediaFile $upload)
    {
        $this->elementStart('rsp', array('stat' => 'ok', 'xmlns:atom'=>Activity::ATOM));
        $this->element('mediaid', null, $upload->fileRecord->id);
        $this->element('mediaurl', null, $upload->shortUrl());
        $this->element('media_url', null, $upload->shortUrl());
        $this->element('size', null, $upload->fileRecord->size);

        $enclosure = $upload->fileRecord->getEnclosure();
        $this->element('atom:link', array('rel'  => 'enclosure',
                                          'href' => $enclosure->url,
                                          'type' => $enclosure->mimetype));

        // Twitter specific metadata expected in response since Twitter's Media upload API v1.1 (even though Twitter doesn't use XML)
        $this->element('media_id', null, $upload->fileRecord->id);
        $this->element('media_id_string', null, (string)$upload->fileRecord->id);
        if (common_get_mime_media($enclosure->mimetype) === 'image') {
            $this->element('image', ['w'=>$enclosure->width, 'h'=>$enclosure->height, 'image_type'=>$enclosure->mimetype]);
        }
        $this->elementEnd('rsp');
    }

    /**
     * Overrided clientError to show a more Twitpic-like error
     *
     * @param String $msg an error message
     */
    function clientError($msg, $code=400, $format=null)
    {
        $this->initDocument($this->format);
        switch ($this->format) {
        case 'json':
            $error = ['errors' => array()];
            $error['errors'][] = ['message'=>$msg, 'code'=>131];
            print json_encode($error);
            break;
        case 'xml':
            $this->elementStart('rsp', array('stat' => 'fail'));

            // @todo add in error code
            $errAttr = array('msg' => $msg);

            $this->element('err', $errAttr, null);
            $this->elementEnd('rsp');
            break;
        }
        $this->endDocument($this->format);
        exit;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Action for getting OAuth token credentials (exchange an authorized
 * request token for an access token)
 *
 * 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    Zach Copley <zach@status.net>
 * @copyright 2010 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); }

/**
 * Action for getting OAuth token credentials (exchange an authorized
 * request token for an access token)
 *
 * @category API
 * @package  StatusNet
 * @author   Zach Copley <zach@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 ApiOAuthAccessTokenAction extends ApiOAuthAction
{
    protected $reqToken = null;
    protected $verifier = null;

    /**
     * Class handler.
     *
     * @param array $args array of arguments
     *
     * @return void
     */
    function handle()
    {
        parent::handle();

        $datastore   = new ApiGNUsocialOAuthDataStore();
        $server      = new OAuthServer($datastore);
        $hmac_method = new OAuthSignatureMethod_HMAC_SHA1();

        $server->add_signature_method($hmac_method);

        $atok = $app = null;

        // XXX: Insist that oauth_token and oauth_verifier be populated?
        // Spec doesn't say they MUST be.

        try {
            $req  = OAuthRequest::from_request();

            $this->reqToken = $req->get_parameter('oauth_token');
            $this->verifier = $req->get_parameter('oauth_verifier');

            $app  = $datastore->getAppByRequestToken($this->reqToken);
            $atok = $server->fetch_access_token($req);
        } catch (Exception $e) {
            common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
            common_debug(var_export($req, true));
            $code = $e->getCode();
            $this->clientError($e->getMessage(), empty($code) ? 401 : $code, 'text');
        }

        if (empty($atok)) {
            // Token exchange failed -- log it

            $msg = sprintf(
                'API OAuth - Failure exchanging OAuth request token for access token, '
                    . 'request token = %s, verifier = %s',
                $this->reqToken,
                $this->verifier
            );

            common_log(LOG_WARNING, $msg);
            // TRANS: Client error given from the OAuth API when the request token or verifier is invalid.
            $this->clientError(_('Invalid request token or verifier.'), 400, 'text');
        } else {
            common_log(
                LOG_INFO,
                sprintf(
                    "Issued access token '%s' for application %d (%s).",
                    $atok->key,
                    $app->id,
                    $app->name
                )
            );
            $this->showAccessToken($atok);
        }
    }

    /*
     * Display OAuth token credentials
     *
     * @param OAuthToken token the access token
     */
    function showAccessToken($token)
    {
        header('Content-Type: application/x-www-form-urlencoded');
        print $token;
    }
}