code:
<?php
/*
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }

// You have 24 hours to claim your password

define('MAX_RECOVERY_TIME', 24 * 60 * 60);

class RecoverpasswordAction extends Action
{
    var $mode = null;
    var $msg = null;
    var $success = null;

    function handle($args)
    {
        parent::handle($args);
        if (common_logged_in()) {
            // TRANS: Client error displayed trying to recover password while already logged in.
            $this->clientError(_('You are already logged in!'));
        } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            if ($this->arg('recover')) {
                $this->recoverPassword();
            } else if ($this->arg('reset')) {
                $this->resetPassword();
            } else {
                // TRANS: Client error displayed when unexpected data is posted in the password recovery form.
                $this->clientError(_('Unexpected form submission.'));
            }
        } else {
            if ($this->trimmed('code')) {
                $this->checkCode();
            } else {
                $this->showForm();
            }
        }
    }

    function checkCode()
    {
        $code = $this->trimmed('code');
        $confirm = Confirm_address::getKV('code', $code);

        if (!$confirm) {
            // TRANS: Client error displayed when password recovery code is not correct.
            $this->clientError(_('No such recovery code.'));
        }
        if ($confirm->address_type != 'recover') {
            // TRANS: Client error displayed when no proper password recovery code was submitted.
            $this->clientError(_('Not a recovery code.'));
        }

        $user = User::getKV($confirm->user_id);

        if (!$user) {
            // TRANS: Server error displayed trying to recover password without providing a user.
            $this->serverError(_('Recovery code for unknown user.'));
        }

        $touched = strtotime($confirm->modified);
        $email = $confirm->address;

        // Burn this code

        $result = $confirm->delete();

        if (!$result) {
            common_log_db_error($confirm, 'DELETE', __FILE__);
            // TRANS: Server error displayed removing a password recovery code from the database.
            $this->serverError(_('Error with confirmation code.'));
        }

        // These should be reaped, but for now we just check mod time
        // Note: it's still deleted; let's avoid a second attempt!

        if ((time() - $touched) > MAX_RECOVERY_TIME) {
            common_log(LOG_WARNING,
                       'Attempted redemption on recovery code ' .
                       'that is ' . $touched . ' seconds old. ');
            // TRANS: Client error displayed trying to recover password with too old a recovery code.
            $this->clientError(_('This confirmation code is too old. ' .
                                   'Please start again.'));
        }

        // If we used an outstanding confirmation to send the email,
        // it's been confirmed at this point.

        if (!$user->email) {
            $orig = clone($user);
            $user->email = $email;
            // Throws exception on failure.
            $user->updateWithKeys($orig);
        }

        // Success!

        $this->setTempUser($user);
        $this->showPasswordForm();
    }

    function setTempUser(&$user)
    {
        common_ensure_session();
        $_SESSION['tempuser'] = $user->id;
    }

    function getTempUser()
    {
        common_ensure_session();
        $user_id = $_SESSION['tempuser'];
        if ($user_id) {
            $user = User::getKV($user_id);
        }
        return $user;
    }

    function clearTempUser()
    {
        common_ensure_session();
        unset($_SESSION['tempuser']);
    }

    function showPageNotice()
    {
        if ($this->msg) {
            $this->element('div', ($this->success) ? 'success' : 'error', $this->msg);
        } else {
            $this->elementStart('div', 'instructions');
            if ($this->mode == 'recover') {
                $this->element('p', null,
                               // TRANS: Page notice for password recovery page.
                               _('If you have forgotten or lost your' .
                                 ' password, you can get a new one sent to' .
                                 ' the email address you have stored' .
                                 ' in your account.'));
            } else if ($this->mode == 'reset') {
                $this->element('p', null,
                               // TRANS: Page notice for password change page.
                               _('You have been identified. Enter a' .
                                 ' new password below.'));
            }
            $this->elementEnd('div');
        }
    }

    function showForm($msg=null)
    {
        $this->msg = $msg;
        $this->mode = 'recover';
        $this->showPage();
    }

    function showContent()
    {
        if ($this->mode == 'recover') {
            $this->showRecoverForm();
        } else if ($this->mode == 'reset') {
            $this->showResetForm();
        }
    }

    function showRecoverForm()
    {
        $this->elementStart('form', array('method' => 'post',
                                           'id' => 'form_password_recover',
                                           'class' => 'form_settings',
                                           'action' => common_local_url('recoverpassword')));
        $this->elementStart('fieldset');
        // TRANS: Fieldset legend for password recovery page.
        $this->element('legend', null, _('Password recovery'));
        $this->elementStart('ul', 'form_data');
        $this->elementStart('li');
        // TRANS: Field label on password recovery page.
        $this->input('nicknameoremail', _('Nickname or email address'),
                     $this->trimmed('nicknameoremail'),
                     // TRANS: Title for field label on password recovery page.
                     _('Your nickname on this server, ' .
                        'or your registered email address.'));
        $this->elementEnd('li');
        $this->elementEnd('ul');
        $this->element('input', array('name' => 'recover',
                                      'type' => 'hidden',
                                      // TRANS: Field label on password recovery page.
                                      'value' => _('Recover')));
        // TRANS: Button text on password recovery page.
        $this->submit('recover', _m('BUTTON','Recover'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    function title()
    {
        switch ($this->mode) {
         // TRANS: Title for password recovery page in password reset mode.
         case 'reset': return _('Reset password');
         // TRANS: Title for password recovery page in password recover mode.
         case 'recover': return _('Recover password');
         // TRANS: Title for password recovery page in email sent mode.
         case 'sent': return _('Password recovery requested');
         // TRANS: Title for password recovery page in password saved mode.
         case 'saved': return _('Password saved');
         default:
            // TRANS: Title for password recovery page when an unknown action has been specified.
            return _('Unknown action');
        }
    }

    function showPasswordForm($msg=null)
    {
        $this->msg = $msg;
        $this->mode = 'reset';
        $this->showPage();
    }

    function showResetForm()
    {
        $this->elementStart('form', array('method' => 'post',
                                           'id' => 'form_password_change',
                                           'class' => 'form_settings',
                                           'action' => common_local_url('recoverpassword')));
        $this->elementStart('fieldset');
         // TRANS: Fieldset legend for password reset form.
        $this->element('legend', null, _('Password change'));
        $this->hidden('token', common_session_token());
        $this->elementStart('ul', 'form_data');
        $this->elementStart('li');
         // TRANS: Field label for password reset form.
        $this->password('newpassword', _('New password'),
                        // TRANS: Title for field label for password reset form.
                        _('6 or more characters, and do not forget it!'));
        $this->elementEnd('li');
        $this->elementStart('li');
         // TRANS: Field label for password reset form where the password has to be typed again.
        $this->password('confirm', _('Confirm'),
                        // TRANS: Title for field label for password reset form where the password has to be typed again.
                        _('Same as password above.'));
        $this->elementEnd('li');
        $this->elementEnd('ul');
         // TRANS: Button text for password reset form.
        $this->submit('reset', _m('BUTTON','Reset'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    function recoverPassword()
    {
        $nore = $this->trimmed('nicknameoremail');

        if (!$nore) {
            // TRANS: Form instructions for password recovery form.
            $this->showForm(_('Enter a nickname or email address.'));
            return;
        }

        try {
            User::recoverPassword($nore);
            $this->mode = 'sent';
            // TRANS: User notification after an e-mail with instructions was sent from the password recovery form.
            $this->msg = _('Instructions for recovering your password ' .
                           'have been sent to the email address registered to your ' .
                           'account.');
            $this->success = true;
        } catch (Exception $e) {
            $this->success = false;
            $this->msg = $e->getMessage();
        }
        $this->showPage();
    }

    function resetPassword()
    {
        // CSRF protection
        $token = $this->trimmed('token');
        if (!$token || $token != common_session_token()) {
            // TRANS: Form validation error message.
            $this->showForm(_('There was a problem with your session token. Try again, please.'));
            return;
        }

        $user = $this->getTempUser();

        if (!$user) {
            // TRANS: Client error displayed when trying to reset as password without providing a user.
            $this->clientError(_('Unexpected password reset.'));
        }

        $newpassword = $this->trimmed('newpassword');
        $confirm = $this->trimmed('confirm');

        if (!$newpassword || strlen($newpassword) < 6) {
            // TRANS: Reset password form validation error message.
            $this->showPasswordForm(_('Password must be 6 characters or more.'));
            return;
        }
        if ($newpassword != $confirm) {
            // TRANS: Reset password form validation error message.
            $this->showPasswordForm(_('Password and confirmation do not match.'));
            return;
        }

        // OK, we're ready to go

        $original = clone($user);

        $user->password = common_munge_password($newpassword, $user->id);

        if (!$user->update($original)) {
            common_log_db_error($user, 'UPDATE', __FILE__);
            // TRANS: Reset password form validation error message.
            $this->serverError(_('Cannot save new password.'));
        }

        $this->clearTempUser();

        if (!common_set_user($user->nickname)) {
            // TRANS: Server error displayed when something does wrong with the user object during password reset.
            $this->serverError(_('Error setting user.'));
        }

        common_real_login(true);

        $this->mode = 'saved';
        // TRANS: Success message for user after password reset.
        $this->msg = _('New password successfully saved. ' .
                       'You are now logged in.');
        $this->success = true;
        $this->showPage();
    }

    /**
     * A local menu
     *
     * Shows different login/register actions.
     *
     * @return void
     */

    function showLocalNav()
    {
        $nav = new LoginGroupNav($this);
        $nav->show();
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Site access administration panel
 *
 * 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 Action
 * @package   StatusNet
 * @author    Craig Andrews <candrews@integralblue.com>
 * @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);
}

/**
 * Administer site access settings
 *
 * @category Action
 * @package  StatusNet
 * @author   Craig Andrews <candrews@integralblue.com>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */

class RedirectAction extends Action
{
    /**
     * These pages are read-only.
     *
     * @param array $args unused.
     *
     * @return boolean read-only flag (false)
     */

    function isReadOnly($args)
    {
        return true;
    }

    /**
     * Handle a request
     *
     * @param array $args array of arguments
     *
     * @return nothing
     */
    function handle($args)
    {
        common_redirect(common_local_url($this->arg('nextAction'), $this->arg('args')));
    }
}

license: mit


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Redirect to the given URL
 *
 * PHP version 5
 *
 * 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  URL
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Redirect to a given URL
 *
 * This is our internal low-budget URL-shortener
 *
 * @category  Action
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

class RedirecturlAction extends Action
{
    protected $id   = null;
    protected $file = null;

    /**
     * For initializing members of the class.
     *
     * @param array $argarray misc. arguments
     *
     * @return boolean true
     */
    function prepare($argarray)
    {
        parent::prepare($argarray);

        $this->id = $this->trimmed('id');

        if (empty($this->id)) {
            // TRANS: Client exception thrown when no ID parameter was provided.
            throw new ClientException(_('No id parameter.'));
        }

        $this->file = File::getKV('id', $this->id);

        if (empty($this->file)) {
            // TRANS: Client exception thrown when an invalid ID parameter was provided for a file.
            // TRANS: %d is the provided ID for which the file is not present (number).
            throw new ClientException(sprintf(_('No such file "%d".'),
                                              $this->id),
                                      404);
        }

        return true;
    }

    /**
     * Handler method
     *
     * @param array $argarray is ignored since it's now passed in in prepare()
     *
     * @return void
     */
    function handle($argarray=null)
    {
        common_redirect($this->file->url, 307);
    }

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

    /**
     * Return last modified, if applicable.
     *
     * MAY override
     *
     * @return string last modified http header
     */
    function lastModified()
    {
        // For comparison with If-Last-Modified
        // If not applicable, return null

        return strtotime($this->file->modified);
    }

    /**
     * Return etag, if applicable.
     *
     * MAY override
     *
     * @return string etag http header
     */
    function etag()
    {
        return 'W/"' . implode(':', array($this->arg('action'),
                                          common_user_cache_hash(),
                                          common_language(),
                                          $this->file->id)) . '"';
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Register a new user account
 *
 * 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  Login
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2008-2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET') && !defined('LACONICA')) {
    exit(1);
}

/**
 * An action for registering a new user account
 *
 * @category Login
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class RegisterAction extends Action
{
    /**
     * Has there been an error?
     */
    var $error = null;

    /**
     * Have we registered?
     */
    var $registered = false;

    /**
     * Are we processing an invite?
     */
    var $invite = null;

    /**
     * Prepare page to run
     *
     *
     * @param $args
     * @return string title
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);
        $this->code = $this->trimmed('code');

        if (empty($this->code)) {
            common_ensure_session();
            if (array_key_exists('invitecode', $_SESSION)) {
                $this->code = $_SESSION['invitecode'];
            }
        }

        if (common_config('site', 'inviteonly') && empty($this->code)) {
            // TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
            $this->clientError(_('Sorry, only invited people can register.'));
        }

        if (!empty($this->code)) {
            $this->invite = Invitation::getKV('code', $this->code);
            if (!$this->invite instanceof Invitation) {
            // TRANS: Client error displayed when trying to register to an invite-only site without a valid invitation.
                $this->clientError(_('Sorry, invalid invitation code.'));
            }
            // Store this in case we need it
            common_ensure_session();
            $_SESSION['invitecode'] = $this->code;
        }

        return true;
    }

    /**
     * Title of the page
     *
     * @return string title
     */
    function title()
    {
        if ($this->registered) {
            // TRANS: Title for registration page after a succesful registration.
            return _('Registration successful');
        } else {
            // TRANS: Title for registration page.
            return _m('TITLE','Register');
        }
    }

    /**
     * Handle input, produce output
     *
     * Switches on request method; either shows the form or handles its input.
     *
     * Checks if registration is closed and shows an error if so.
     *
     * @param array $args $_REQUEST data
     *
     * @return void
     */
    function handle($args)
    {
        parent::handle($args);

        if (common_config('site', 'closed')) {
            // TRANS: Client error displayed when trying to register to a closed site.
            $this->clientError(_('Registration not allowed.'));
        } else if (common_logged_in()) {
            // TRANS: Client error displayed when trying to register while already logged in.
            $this->clientError(_('Already logged in.'));
        } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $this->tryRegister();
        } else {
            $this->showForm();
        }
    }

    function showScripts()
    {
        parent::showScripts();
        $this->autofocus('nickname');
    }

    /**
     * Try to register a user
     *
     * Validates the input and tries to save a new user and profile
     * record. On success, shows an instructions page.
     *
     * @return void
     */
    function tryRegister()
    {
        if (Event::handle('StartRegistrationTry', array($this))) {
            $token = $this->trimmed('token');
            if (!$token || $token != common_session_token()) {
                // TRANS: Client error displayed when the session token does not match or is not given.
                $this->showForm(_('There was a problem with your session token. '.
                                  'Try again, please.'));
                return;
            }

            $nickname = $this->trimmed('nickname');
            $email    = $this->trimmed('email');
            $fullname = $this->trimmed('fullname');
            $homepage = $this->trimmed('homepage');
            $bio      = $this->trimmed('bio');
            $location = $this->trimmed('location');

            // We don't trim these... whitespace is OK in a password!
            $password = $this->arg('password');
            $confirm  = $this->arg('confirm');

            // invitation code, if any
            $code = $this->trimmed('code');

            if ($code) {
                $invite = Invitation::getKV($code);
            }

            if (common_config('site', 'inviteonly') && !($code && $invite)) {
                // TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
                $this->clientError(_('Sorry, only invited people can register.'));
            }

            // Input scrubbing
            try {
                $nickname = Nickname::normalize($nickname, true);
            } catch (NicknameException $e) {
                $this->showForm($e->getMessage());
                return;
            }
            $email    = common_canonical_email($email);

            if (!$this->boolean('license')) {
                // TRANS: Form validation error displayed when trying to register without agreeing to the site license.
                $this->showForm(_('You cannot register if you do not '.
                                  'agree to the license.'));
            } else if ($email && !Validate::email($email, common_config('email', 'check_domain'))) {
                // TRANS: Form validation error displayed when trying to register without a valid e-mail address.
                $this->showForm(_('Not a valid email address.'));
            } else if ($this->emailExists($email)) {
                // TRANS: Form validation error displayed when trying to register with an already registered e-mail address.
                $this->showForm(_('Email address already exists.'));
            } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
                       !common_valid_http_url($homepage)) {
                // TRANS: Form validation error displayed when trying to register with an invalid homepage URL.
                $this->showForm(_('Homepage is not a valid URL.'));
            } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
                // TRANS: Form validation error displayed when trying to register with a too long full name.
                $this->showForm(_('Full name is too long (maximum 255 characters).'));
            } else if (Profile::bioTooLong($bio)) {
                // TRANS: Form validation error on registration page when providing too long a bio text.
                // TRANS: %d is the maximum number of characters for bio; used for plural.
                $this->showForm(sprintf(_m('Bio is too long (maximum %d character).',
                                           'Bio is too long (maximum %d characters).',
                                           Profile::maxBio()),
                                        Profile::maxBio()));
            } else if (!is_null($location) && mb_strlen($location) > 255) {
                // TRANS: Form validation error displayed when trying to register with a too long location.
                $this->showForm(_('Location is too long (maximum 255 characters).'));
            } else if (strlen($password) < 6) {
                // TRANS: Form validation error displayed when trying to register with too short a password.
                $this->showForm(_('Password must be 6 or more characters.'));
            } else if ($password != $confirm) {
                // TRANS: Form validation error displayed when trying to register with non-matching passwords.
                $this->showForm(_('Passwords do not match.'));
            } else if ($user = User::register(array('nickname' => $nickname,
                                                    'password' => $password,
                                                    'email' => $email,
                                                    'fullname' => $fullname,
                                                    'homepage' => $homepage,
                                                    'bio' => $bio,
                                                    'location' => $location,
                                                    'code' => $code))) {
                if (!($user instanceof User)) {
                    // TRANS: Form validation error displayed when trying to register with an invalid username or password.
                    $this->showForm(_('Invalid username or password.'));
                    return;
                }
                // success!
                if (!common_set_user($user)) {
                    // TRANS: Server error displayed when saving fails during user registration.
                    $this->serverError(_('Error setting user.'));
                }
                // this is a real login
                common_real_login(true);
                if ($this->boolean('rememberme')) {
                    common_debug('Adding rememberme cookie for ' . $nickname);
                    common_rememberme($user);
                }

                // Re-init language env in case it changed (not yet, but soon)
                common_init_language();

                Event::handle('EndRegistrationTry', array($this));

                $this->showSuccess();
            } else {
                // TRANS: Form validation error displayed when trying to register with an invalid username or password.
                $this->showForm(_('Invalid username or password.'));
            }
        }
    }

    /**
     * Does the given email address already exist?
     *
     * Checks a canonical email address against the database.
     *
     * @param string $email email address to check
     *
     * @return boolean true if the address already exists
     */
    function emailExists($email)
    {
        $email = common_canonical_email($email);
        if (!$email || strlen($email) == 0) {
            return false;
        }
        $user = User::getKV('email', $email);
        return is_object($user);
    }

    // overrrided to add entry-title class
    function showPageTitle() {
        if (Event::handle('StartShowPageTitle', array($this))) {
            $this->element('h1', array('class' => 'entry-title'), $this->title());
        }
    }

    // overrided to add h-entry, and content-inner class
    function showContentBlock()
    {
        $this->elementStart('div', array('id' => 'content', 'class' => 'h-entry'));
        $this->showPageTitle();
        $this->showPageNoticeBlock();
        $this->elementStart('div', array('id' => 'content_inner',
                                         'class' => 'e-content'));
        // show the actual content (forms, lists, whatever)
        $this->showContent();
        $this->elementEnd('div');
        $this->elementEnd('div');
    }

    /**
     * Instructions or a notice for the page
     *
     * Shows the error, if any, or instructions for registration.
     *
     * @return void
     */
    function showPageNotice()
    {
        if ($this->registered) {
            return;
        } else if ($this->error) {
            $this->element('p', 'error', $this->error);
        } else {
            $instr =
              // TRANS: Page notice on registration page.
              common_markup_to_html(_('With this form you can create '.
                                      'a new account. ' .
                                      'You can then post notices and '.
                                      'link up to friends and colleagues.'));

            $this->elementStart('div', 'instructions');
            $this->raw($instr);
            $this->elementEnd('div');
        }
    }

    /**
     * Wrapper for showing a page
     *
     * Stores an error and shows the page
     *
     * @param string $error Error, if any
     *
     * @return void
     */
    function showForm($error=null)
    {
        $this->error = $error;
        $this->showPage();
    }

    /**
     * Show the page content
     *
     * Either shows the registration form or, if registration was successful,
     * instructions for using the site.
     *
     * @return void
     */
    function showContent()
    {
        if ($this->registered) {
            $this->showSuccessContent();
        } else {
            $this->showFormContent();
        }
    }

    /**
     * Show the registration form
     *
     * @return void
     */
    function showFormContent()
    {
        $code = $this->trimmed('code');

        $invite = null;

        if ($code) {
            $invite = Invitation::getKV($code);
        }

        if (common_config('site', 'inviteonly') && !($code && $invite)) {
            // TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
            $this->clientError(_('Sorry, only invited people can register.'));
        }

        $this->elementStart('form', array('method' => 'post',
                                          'id' => 'form_register',
                                          'class' => 'form_settings',
                                          'action' => common_local_url('register')));
        $this->elementStart('fieldset');
        // TRANS: Fieldset legend on accout registration page.
        $this->element('legend', null, 'Account settings');
        $this->hidden('token', common_session_token());

        if ($this->code) {
            $this->hidden('code', $this->code);
        }

        $this->elementStart('ul', 'form_data');
        if (Event::handle('StartRegistrationFormData', array($this))) {
            $this->elementStart('li');
            // TRANS: Field label on account registration page.
            $this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
                         // TRANS: Field title on account registration page.
                         _('1-64 lowercase letters or numbers, no punctuation or spaces.'));
            $this->elementEnd('li');
            $this->elementStart('li');
            // TRANS: Field label on account registration page.
            $this->password('password', _('Password'),
                            // TRANS: Field title on account registration page.
                            _('6 or more characters.'));
            $this->elementEnd('li');
            $this->elementStart('li');
            // TRANS: Field label on account registration page. In this field the password has to be entered a second time.
            $this->password('confirm', _m('PASSWORD','Confirm'),
                         // TRANS: Field title on account registration page.
                         _('Same as password above.'));
            $this->elementEnd('li');
            $this->elementStart('li');
            if ($this->invite && $this->invite->address_type == 'email') {
                // TRANS: Field label on account registration page.
                $this->input('email', _m('LABEL','Email'), $this->invite->address,
                             // TRANS: Field title on account registration page.
                             _('Used only for updates, announcements, '.
                               'and password recovery.'));
            } else {
                // TRANS: Field label on account registration page.
                $this->input('email', _m('LABEL','Email'), $this->trimmed('email'),
                             // TRANS: Field title on account registration page.
                             _('Used only for updates, announcements, '.
                               'and password recovery.'));
            }
            $this->elementEnd('li');
            $this->elementStart('li');
            // TRANS: Field label on account registration page.
            $this->input('fullname', _('Full name'),
                         $this->trimmed('fullname'),
                     // TRANS: Field title on account registration page.
                     _('Longer name, preferably your "real" name.'));
            $this->elementEnd('li');
            $this->elementStart('li');
            // TRANS: Field label on account registration page.
            $this->input('homepage', _('Homepage'),
                         $this->trimmed('homepage'),
                         // TRANS: Field title on account registration page.
                         _('URL of your homepage, blog, '.
                           'or profile on another site.'));
            $this->elementEnd('li');
            $this->elementStart('li');
            $maxBio = Profile::maxBio();
            if ($maxBio > 0) {
                // TRANS: Text area title in form for account registration. Plural
                // TRANS: is decided by the number of characters available for the
                // TRANS: biography (%d).
                $bioInstr = sprintf(_m('Describe yourself and your interests in %d character.',
                                       'Describe yourself and your interests in %d characters.',
                                       $maxBio),
                                    $maxBio);
            } else {
                // TRANS: Text area title on account registration page.
                $bioInstr = _('Describe yourself and your interests.');
            }
            // TRANS: Text area label on account registration page.
            $this->textarea('bio', _('Bio'),
                            $this->trimmed('bio'),
                            $bioInstr);
            $this->elementEnd('li');
            $this->elementStart('li');
            // TRANS: Field label on account registration page.
            $this->input('location', _('Location'),
                         $this->trimmed('location'),
                         // TRANS: Field title on account registration page.
                         _('Where you are, like "City, '.
                           'State (or Region), Country".'));
            $this->elementEnd('li');
            Event::handle('EndRegistrationFormData', array($this));
            $this->elementStart('li', array('id' => 'settings_rememberme'));
            // TRANS: Checkbox label on account registration page.
            $this->checkbox('rememberme', _('Remember me'),
                            $this->boolean('rememberme'),
                            // TRANS: Checkbox title on account registration page.
                            _('Automatically login in the future; '.
                              'not for shared computers!'));
            $this->elementEnd('li');
            $attrs = array('type' => 'checkbox',
                           'id' => 'license',
                           'class' => 'checkbox',
                           'name' => 'license',
                           'value' => 'true');
            if ($this->boolean('license')) {
                $attrs['checked'] = 'checked';
            }
            $this->elementStart('li');
            $this->element('input', $attrs);
            $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
            $this->raw($this->licenseCheckbox());
            $this->elementEnd('label');
            $this->elementEnd('li');
        }
        $this->elementEnd('ul');
        // TRANS: Button text to register a user on account registration page.
        $this->submit('submit', _m('BUTTON','Register'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    function licenseCheckbox()
    {
        $out = '';
        switch (common_config('license', 'type')) {
        case 'private':
            $out .= htmlspecialchars(sprintf(
                // TRANS: Copyright checkbox label in registration dialog, for private sites.
                // TRANS: %1$s is the StatusNet sitename.
                _('I understand that content and data of %1$s are private and confidential.'),
                common_config('site', 'name')));
            // fall through
        case 'allrightsreserved':
            if ($out != '') {
                $out .= ' ';
            }
            if (common_config('license', 'owner')) {
                $out .= htmlspecialchars(sprintf(
                    // TRANS: Copyright checkbox label in registration dialog, for all rights reserved with a specified copyright owner.
                    // TRANS: %1$s is the license owner.
                    _('My text and files are copyright by %1$s.'),
                    common_config('license', 'owner')));
            } else {
                // TRANS: Copyright checkbox label in registration dialog, for all rights reserved with ownership left to contributors.
                $out .= htmlspecialchars(_('My text and files remain under my own copyright.'));
            }
            // TRANS: Copyright checkbox label in registration dialog, for all rights reserved.
            $out .= ' ' . _('All rights reserved.');
            break;
        case 'cc': // fall through
        default:
            // TRANS: Copyright checkbox label in registration dialog, for Creative Commons-style licenses.
            $message = _('My text and files are available under %s ' .
                         'except this private data: password, ' .
                         'email address, IM address, and phone number.');
            $link = '<a href="' .
                    htmlspecialchars(common_config('license', 'url')) .
                    '">' .
                    htmlspecialchars(common_config('license', 'title')) .
                    '</a>';
            $out .= sprintf(htmlspecialchars($message), $link);
        }
        return $out;
    }

    /**
     * Show some information about registering for the site
     *
     * Save the registration flag, run showPage
     *
     * @return void
     */
    function showSuccess()
    {
        $this->registered = true;
        $this->showPage();
    }

    /**
     * Show some information about registering for the site
     *
     * Gives some information and options for new registrees.
     *
     * @return void
     */
    function showSuccessContent()
    {
        if (Event::handle('StartRegisterSuccess', array($this))) {
            $nickname = $this->arg('nickname');

            $profileurl = common_local_url('showstream',
                                           array('nickname' => $nickname));

            $this->elementStart('div', 'success');
            // TRANS: Text displayed after successful account registration.
            // TRANS: %1$s is the registered nickname, %2$s is the profile URL.
            // TRANS: This message contains Markdown links in the form [link text](link)
            // TRANS: and variables in the form %%%%variable%%%%. Please mind the syntax.
            $instr = sprintf(_('Congratulations, %1$s! And welcome to %%%%site.name%%%%. '.
                               'From here, you may want to...'. "\n\n" .
                               '* Go to [your profile](%2$s) '.
                               'and post your first message.' .  "\n" .
                               '* Add a [Jabber/GTalk address]'.
                               '(%%%%action.imsettings%%%%) '.
                               'so you can send notices '.
                               'through instant messages.' . "\n" .
                               '* [Search for people](%%%%action.peoplesearch%%%%) '.
                               'that you may know or '.
                               'that share your interests. ' . "\n" .
                               '* Update your [profile settings]'.
                               '(%%%%action.profilesettings%%%%)'.
                               ' to tell others more about you. ' . "\n" .
                               '* Read over the [online docs](%%%%doc.help%%%%)'.
                               ' for features you may have missed. ' . "\n\n" .
                               'Thanks for signing up and we hope '.
                               'you enjoy using this service.'),
                             $nickname, $profileurl);

            $this->raw(common_markup_to_html($instr));

            $have_email = $this->trimmed('email');
            if ($have_email) {
                // TRANS: Instruction text on how to deal with the e-mail address confirmation e-mail.
                $emailinstr = _('(You should receive a message by email '.
                                'momentarily, with ' .
                                'instructions on how to confirm '.
                                'your email address.)');
                $this->raw(common_markup_to_html($emailinstr));
            }
            $this->elementEnd('div');

            Event::handle('EndRegisterSuccess', array($this));
        }
    }

    /**
     * Show the login group nav menu
     *
     * @return void
     */
    function showLocalNav()
    {
        if (common_logged_in()) {
            parent::showLocalNav();
        } else {
            $nav = new LoginGroupNav($this);
            $nav->show();
        }
    }

    /**
     * Show a bit of login context
     *
     * @return nothing
     */
    function showProfileBlock()
    {
        if (common_logged_in()) {
            parent::showProfileBlock();
        }
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008-2010, StatusNet, Inc.
 *
 * Subscription action.
 *
 * 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/>.
 *
 * PHP version 5
 *
 * @category  Action
 * @package   StatusNet
 * @author    Shashi Gowda <connect2shashi@gmail.com>
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    exit(1);
}

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

/**
 * Subscription action
 *
 * Subscribing to a profile. Does not work for OMB 0.1 remote subscriptions,
 * but may work for other remote subscription protocols, like OStatus.
 *
 * Takes parameters:
 *
 *    - subscribeto: a profile ID
 *    - token: session token to prevent CSRF attacks
 *    - ajax: boolean; whether to return Ajax or full-browser results
 *
 * Only works if the current user is logged in.
 *
 * @category  Action
 * @package   StatusNet
 * @author    Shashi Gowda <connect2shashi@gmail.com>
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
 * @link      http://status.net/
 */
class RemovepeopletagAction extends Action
{
    var $user;
    var $tagged;
    var $peopletag;

    /**
     * Check pre-requisites and instantiate attributes
     *
     * @param Array $args array of arguments (URL, GET, POST)
     *
     * @return boolean success flag
     */
    function prepare($args)
    {
        parent::prepare($args);

        // CSRF protection

        $token = $this->trimmed('token');

        if (!$token || $token != common_session_token()) {
            // TRANS: Client error displayed when the session token does not match or is not given.
            $this->clientError(_('There was a problem with your session token.'.
                                 ' Try again, please.'));
        }

        // Only for logged-in users

        $this->user = common_current_user();

        if (empty($this->user)) {
            // TRANS: Error message displayed when trying to perform an action that requires a logged in user.
            $this->clientError(_('Not logged in.'));
        }

        // Profile to subscribe to

        $tagged_id = $this->arg('tagged');

        $this->tagged = Profile::getKV('id', $tagged_id);

        if (empty($this->tagged)) {
            // TRANS: Client error displayed when referring to a non-existing profile.
            $this->clientError(_('No such profile.'));
        }

        $id = $this->arg('peopletag_id');
        $this->peopletag = Profile_list::getKV('id', $id);

        if (empty($this->peopletag)) {
            // TRANS: Client error displayed trying to reference a non-existing list.
            $this->clientError(_('No such list.'));
        }

        return true;
    }

    /**
     * Handle request
     *
     * Does the subscription and returns results.
     *
     * @param Array $args unused.
     *
     * @return void
     */
    function handle($args)
    {
        // Throws exception on error

        $ptag = Profile_tag::unTag($this->user->id, $this->tagged->id,
                                $this->peopletag->tag);

        if (!$ptag) {
            $user = User::getKV('id', $this->tagged->id);
            if ($user) {
                $this->clientError(
                        // TRANS: Client error displayed when an unknown error occurs while delisting a user.
                        // TRANS: %s is a username.
                        sprintf(_('There was an unexpected error while delisting %s.'),
                        $user->nickname));
            } else {
                // TRANS: Client error displayed when an unknown error occurs while listing a user.
                // TRANS: %s is a profile URL.
                $this->clientError(sprintf(_('There was a problem listing %s. ' .
                                      'The remote server is probably not responding correctly, ' .
                                      'please try retrying later.'), $this->profile->profileurl));
            }
        }
        if ($this->boolean('ajax')) {
            $this->startHTML('text/xml;charset=utf-8');
            $this->elementStart('head');
            // TRANS: Title after removing a user from a list.
            $this->element('title', null, _('Unlisted'));
            $this->elementEnd('head');
            $this->elementStart('body');
            $unsubscribe = new TagButton($this, $this->tagged, $this->peopletag);
            $unsubscribe->show();
            $this->elementEnd('body');
            $this->endHTML();
        } else {
            $url = common_local_url('subscriptions',
                                    array('nickname' => $this->user->nickname));
            common_redirect($url, 303);
        }
    }
}


code:
<?php
/**
 * Repeat action.
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 *
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

if (!defined('GNUSOCIAL')) { exit(1); }

/**
 * Repeat action
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class RepeatAction extends FormAction
{
    protected $needPost = true; // At least for now, until repeat interface is available

    protected $notice = null;   // Notice that is being repeated.
    protected $repeat = null;   // The resulting repeat object/notice.

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

        $id = $this->trimmed('notice');

        if (empty($id)) {
            // TRANS: Client error displayed when trying to repeat a notice while not providing a notice ID.
            $this->clientError(_('No notice specified.'));
        }

        $this->notice = Notice::getKV('id', $id);

        if (!$this->notice instanceof Notice) {
            // TRANS: Client error displayed when trying to repeat a non-existing notice.
            $this->clientError(_('Notice not found.'));
        }

        $this->repeat = $this->notice->repeat($this->scoped, 'web');
        if (!$this->repeat instanceof Notice) {
            // TRANS: Error when unable to repeat a notice for unknown reason.
            $this->clientError(_('Could not repeat notice for unknown reason. Please contact the webmaster!'));
        }

        return true;
    }

    /**
     * Class handler.
     *
     * @param array $args query arguments
     *
     * @return void
     */
    protected function showContent()
    {
        $this->element('p', array('id' => 'repeat_response',
                                  'class' => 'repeated'),
                            // TRANS: Confirmation text after repeating a notice.
                            _('Repeated!'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * List of replies
 *
 * 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  Personal
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2008-2011 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') && !defined('LACONICA')) {
    exit(1);
}

require_once INSTALLDIR.'/lib/personalgroupnav.php';
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/feedlist.php';

/**
 * List of replies
 *
 * @category Personal
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class RepliesAction extends Action
{
    var $page = null;
    var $notice;

    /**
     * Prepare the object
     *
     * Check the input values and initialize the object.
     * Shows an error page on bad input.
     *
     * @param array $args $_REQUEST data
     *
     * @return boolean success flag
     */
    function prepare($args)
    {
        parent::prepare($args);

        $nickname = common_canonical_nickname($this->arg('nickname'));

        $this->user = User::getKV('nickname', $nickname);

        if (!$this->user) {
            // TRANS: Client error displayed when trying to reply to a non-exsting user.
            $this->clientError(_('No such user.'));
        }

        $profile = $this->user->getProfile();

        if (!$profile) {
            // TRANS: Error message displayed when referring to a user without a profile.
            $this->serverError(_('User has no profile.'));
        }

        $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;

        common_set_returnto($this->selfUrl());

        $stream = new ReplyNoticeStream($this->user->id,
                                        Profile::current());

        $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE,
                                            NOTICES_PER_PAGE + 1);

        if($this->page > 1 && $this->notice->N == 0){
            // TRANS: Client error when page not found (404)
            $this->clientError(_('No such page.'), 404);
        }

        return true;
    }

    /**
     * Handle a request
     *
     * Just show the page. All args already handled.
     *
     * @param array $args $_REQUEST data
     *
     * @return void
     */
    function handle($args)
    {
        parent::handle($args);
        $this->showPage();
    }

    /**
     * Title of the page
     *
     * Includes name of user and page number.
     *
     * @return string title of page
     */
    function title()
    {
        if ($this->page == 1) {
            // TRANS: Title for first page of replies for a user.
            // TRANS: %s is a user nickname.
            return sprintf(_("Replies to %s"), $this->user->nickname);
        } else {
            // TRANS: Title for all but the first page of replies for a user.
            // TRANS: %1$s is a user nickname, %2$d is a page number.
            return sprintf(_('Replies to %1$s, page %2$d'),
                           $this->user->nickname,
                           $this->page);
        }
    }

    /**
     * Feeds for the <head> section
     *
     * @return void
     */
    function getFeeds()
    {
        return array(new Feed(Feed::JSON,
                              common_local_url('ApiTimelineMentions',
                                               array(
                                                    'id' => $this->user->nickname,
                                                    'format' => 'as')),
                              // TRANS: Link for feed with replies for a user.
                              // TRANS: %s is a user nickname.
                              sprintf(_('Replies feed for %s (Activity Streams JSON)'),
                                      $this->user->nickname)),
                     new Feed(Feed::RSS1,
                              common_local_url('repliesrss',
                                               array('nickname' => $this->user->nickname)),
                              // TRANS: Link for feed with replies for a user.
                              // TRANS: %s is a user nickname.
                              sprintf(_('Replies feed for %s (RSS 1.0)'),
                                      $this->user->nickname)),
                     new Feed(Feed::RSS2,
                              common_local_url('ApiTimelineMentions',
                                               array(
                                                    'id' => $this->user->nickname,
                                                    'format' => 'rss')),
                              // TRANS: Link for feed with replies for a user.
                              // TRANS: %s is a user nickname.
                              sprintf(_('Replies feed for %s (RSS 2.0)'),
                                      $this->user->nickname)),
                     new Feed(Feed::ATOM,
                              common_local_url('ApiTimelineMentions',
                                               array(
                                                    'id' => $this->user->nickname,
                                                    'format' => 'atom')),
                              // TRANS: Link for feed with replies for a user.
                              // TRANS: %s is a user nickname.
                              sprintf(_('Replies feed for %s (Atom)'),
                                    $this->user->nickname)));
    }

    /**
     * Show the content
     *
     * A list of notices that are replies to the user, plus pagination.
     *
     * @return void
     */
    function showContent()
    {
        $nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));

        $cnt = $nl->show();
        if (0 === $cnt) {
            $this->showEmptyListMessage();
        }

        $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
                          $this->page, 'replies',
                          array('nickname' => $this->user->nickname));
    }

    function showEmptyListMessage()
    {
        // TRANS: Empty list message for page with replies for a user.
        // TRANS: %1$s and %s$s are the user nickname.
        $message = sprintf(_('This is the timeline showing replies to %1$s but %2$s hasn\'t received a notice to them yet.'),
                           $this->user->nickname,
                           $this->user->nickname) . ' ';

        if (common_logged_in()) {
            $current_user = common_current_user();
            if ($this->user->id === $current_user->id) {
                // TRANS: Empty list message for page with replies for a user for the logged in user.
                // TRANS: This message contains a Markdown link in the form [link text](link).
                $message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).');
            } else {
                // TRANS: Empty list message for page with replies for a user for all logged in users but the user themselves.
                // TRANS: %1$s, %2$s and %3$s are a user nickname. This message contains a Markdown link in the form [link text](link).
                $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
            }
        }
        else {
            // TRANS: Empty list message for page with replies for a user for not logged in users.
            // TRANS: %1$s is a user nickname. This message contains a Markdown link in the form [link text](link).
            $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname);
        }

        $this->elementStart('div', 'guide');
        $this->raw(common_markup_to_html($message));
        $this->elementEnd('div');
    }

    function isReadOnly($args)
    {
        return true;
    }
}


code:
<?php
/*
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }

require_once(INSTALLDIR.'/lib/rssaction.php');

// Formatting of RSS handled by Rss10Action

class RepliesrssAction extends Rss10Action
{
    var $user = null;

    function prepare($args)
    {
        parent::prepare($args);
        $nickname = $this->trimmed('nickname');
        $this->user = User::getKV('nickname', $nickname);

        if (!$this->user) {
            // TRANS: Client error displayed when providing a non-existing nickname in a RSS 1.0 action.
            $this->clientError(_('No such user.'));
        } else {
            $this->notices = $this->getNotices($this->limit);
            return true;
        }
    }

    function getNotices($limit=0)
    {
        $user = $this->user;

        $notice = $user->getReplies(0, ($limit == 0) ? 48 : $limit);

        $notices = array();

        while ($notice->fetch()) {
            $notices[] = clone($notice);
        }

        return $notices;
    }

    function getChannel()
    {
        $user = $this->user;
        $c = array('url' => common_local_url('repliesrss',
                                             array('nickname' =>
                                                   $user->nickname)),
                   // TRANS: RSS reply feed title. %s is a user nickname.
                   'title' => sprintf(_("Replies to %s"), $user->nickname),
                   'link' => common_local_url('replies',
                                              array('nickname' =>
                                                    $user->nickname)),
                   // TRANS: RSS reply feed description.
                   // TRANS: %1$s is a user nickname, %2$s is the StatusNet site name.
                   'description' => sprintf(_('Replies to %1$s on %2$s.'),
                                              $user->nickname, common_config('site', 'name')));
        return $c;
    }

    function getImage()
    {
        $profile = $this->user->getProfile();
        return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
    }

    function isReadOnly($args)
    {
        return true;
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Restore a backup of your own account from the browser
 *
 * PHP version 5
 *
 * 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  Account
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Restore a backup of your own account from the browser
 *
 * @category  Account
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class RestoreaccountAction extends Action
{
    private $success = false;
    private $inprogress = false;

    /**
     * Returns the title of the page
     *
     * @return string page title
     */
    function title()
    {
        // TRANS: Page title for page where a user account can be restored from backup.
        return _('Restore account');
    }

    /**
     * For initializing members of the class.
     *
     * @param array $argarray misc. arguments
     *
     * @return boolean true
     */
    function prepare($argarray)
    {
        parent::prepare($argarray);

        $cur = common_current_user();

        if (empty($cur)) {
            // TRANS: Client exception displayed when trying to restore an account while not logged in.
            throw new ClientException(_('Only logged-in users can restore their account.'), 403);
        }

        if (!$cur->hasRight(Right::RESTOREACCOUNT)) {
            // TRANS: Client exception displayed when trying to restore an account without having restore rights.
            throw new ClientException(_('You may not restore your account.'), 403);
        }

        return true;
    }

    /**
     * Handler method
     *
     * @param array $argarray is ignored since it's now passed in in prepare()
     *
     * @return void
     */
    function handle($argarray=null)
    {
        parent::handle($argarray);

        if ($this->isPost()) {
            $this->restoreAccount();
        } else {
            $this->showPage();
        }
        return;
    }

    /**
     * Queue a file for restoration
     *
     * Uses the UserActivityStream class; may take a long time!
     *
     * @return void
     */
    function restoreAccount()
    {
        $this->checkSessionToken();

        if (!isset($_FILES['restorefile']['error'])) {
            // TRANS: Client exception displayed trying to restore an account while something went wrong uploading a file.
            throw new ClientException(_('No uploaded file.'));
        }

        switch ($_FILES['restorefile']['error']) {
        case UPLOAD_ERR_OK: // success, jump out
            break;
        case UPLOAD_ERR_INI_SIZE:
            // TRANS: Client exception thrown when an uploaded file is larger than set in php.ini.
            throw new ClientException(_('The uploaded file exceeds the ' .
                'upload_max_filesize directive in php.ini.'));
            return;
        case UPLOAD_ERR_FORM_SIZE:
            throw new ClientException(
                // TRANS: Client exception.
                _('The uploaded file exceeds the MAX_FILE_SIZE directive' .
                ' that was specified in the HTML form.'));
            return;
        case UPLOAD_ERR_PARTIAL:
            @unlink($_FILES['restorefile']['tmp_name']);
            // TRANS: Client exception.
            throw new ClientException(_('The uploaded file was only' .
                ' partially uploaded.'));
            return;
        case UPLOAD_ERR_NO_FILE:
            // TRANS: Client exception. No file; probably just a non-AJAX submission.
            throw new ClientException(_('No uploaded file.'));
            return;
        case UPLOAD_ERR_NO_TMP_DIR:
            // TRANS: Client exception thrown when a temporary folder is not present to store a file upload.
            throw new ClientException(_('Missing a temporary folder.'));
            return;
        case UPLOAD_ERR_CANT_WRITE:
            // TRANS: Client exception thrown when writing to disk is not possible during a file upload operation.
            throw new ClientException(_('Failed to write file to disk.'));
            return;
        case UPLOAD_ERR_EXTENSION:
            // TRANS: Client exception thrown when a file upload operation has been stopped by an extension.
            throw new ClientException(_('File upload stopped by extension.'));
            return;
        default:
            common_log(LOG_ERR, __METHOD__ . ": Unknown upload error " .
                $_FILES['restorefile']['error']);
            // TRANS: Client exception thrown when a file upload operation has failed with an unknown reason.
            throw new ClientException(_('System error uploading file.'));
            return;
        }

        $filename = $_FILES['restorefile']['tmp_name'];

        try {
            if (!file_exists($filename)) {
                // TRANS: Server exception thrown when an expected file upload could not be found.
                throw new ServerException(_("No such file '$filename'."));
            }

            if (!is_file($filename)) {
                // TRANS: Server exception thrown when an expected file upload is not an actual file.
                throw new ServerException(_("Not a regular file: '$filename'."));
            }

            if (!is_readable($filename)) {
                // TRANS: Server exception thrown when an expected file upload could not be read.
                throw new ServerException(_("File '$filename' not readable."));
            }

            common_debug(sprintf("Getting backup from file '%s'.", $filename));

            $xml = file_get_contents($filename);

            // This check is costly but we should probably give
            // the user some info ahead of time.
            $doc = new DOMDocument();

            // Disable PHP warnings so we don't spew low-level XML errors to output...
            // would be nice if we can just get exceptions instead.
            $old_err = error_reporting();
            error_reporting($old_err & ~E_WARNING);
            $doc->loadXML($xml);
            error_reporting($old_err);

            $feed = $doc->documentElement;

            if (!$feed ||
                $feed->namespaceURI != Activity::ATOM ||
                $feed->localName != 'feed') {
                // TRANS: Client exception thrown when a feed is not an Atom feed.
                throw new ClientException(_("Not an Atom feed."));
            }

            // Enqueue for processing.

            $qm = QueueManager::get();
            $qm->enqueue(array(common_current_user(), $xml, false), 'feedimp');

            if ($qm instanceof UnQueueManager) {
                // No active queuing means we've actually just completed the job!
                $this->success = true;
            } else {
                // We've fed data into background queues, and it's probably still running.
                $this->inprogress = true;
            }
            $this->showPage();

        } catch (Exception $e) {
            // Delete the file and re-throw
            @unlink($_FILES['restorefile']['tmp_name']);
            throw $e;
        }
    }

    /**
     * Show a little form so that the person can upload a file to restore
     *
     * @return void
     */
    function showContent()
    {
        if ($this->success) {
            $this->element('p', null,
                           // TRANS: Success message when a feed has been restored.
                           _('Feed has been restored. Your old posts should now appear in search and your profile page.'));
        } else if ($this->inprogress) {
            $this->element('p', null,
                           // TRANS: Message when a feed restore is in progress.
                           _('Feed will be restored. Please wait a few minutes for results.'));
        } else {
            $form = new RestoreAccountForm($this);
            $form->show();
        }
    }

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

    /**
     * Return last modified, if applicable.
     *
     * MAY override
     *
     * @return string last modified http header
     */
    function lastModified()
    {
        // For comparison with If-Last-Modified
        // If not applicable, return null
        return null;
    }

    /**
     * Return etag, if applicable.
     *
     * MAY override
     *
     * @return string etag http header
     */
    function etag()
    {
        return null;
    }
}

/**
 * A form for backing up the account.
 *
 * @category  Account
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class RestoreAccountForm extends Form
{
    function __construct($out=null) {
        parent::__construct($out);
        $this->enctype = 'multipart/form-data';
    }

    /**
     * Class of the form.
     *
     * @return string the form's class
     */
    function formClass()
    {
        return 'form_profile_restore';
    }

    /**
     * URL the form posts to
     *
     * @return string the form's action URL
     */
    function action()
    {
        return common_local_url('restoreaccount');
    }

    /**
     * Output form data
     *
     * Really, just instructions for doing a backup.
     *
     * @return void
     */
    function formData()
    {
        $this->out->elementStart('p', 'instructions');

        // TRANS: Form instructions for feed restore.
        $this->out->raw(_('You can upload a backed-up timeline in '.
                          'Activity Streams format.'));

        $this->out->elementEnd('p');

        $this->out->elementStart('ul', 'form_data');

        $this->out->elementStart('li', array ('id' => 'settings_attach'));
        $this->out->element('input', array('name' => 'restorefile',
                                           'type' => 'file',
                                           'id' => 'restorefile'));
        $this->out->elementEnd('li');

        $this->out->elementEnd('ul');
    }

    /**
     * Buttons for the form
     *
     * In this case, a single submit button
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit('submit',
                           // TRANS: Submit button to confirm upload of a user backup file for account restore.
                           _m('BUTTON', 'Upload'),
                           'submit',
                           null,
                           // TRANS: Title for submit button to confirm upload of a user backup file for account restore.
                           _('Upload the file'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Action class to sandbox an abusive 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  Action
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    exit(1);
}

/**
 * Sandbox a user.
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class RevokeRoleAction extends ProfileFormAction
{
    /**
     * Check parameters
     *
     * @param array $args action arguments (URL, GET, POST)
     *
     * @return boolean success flag
     */
    function prepare($args)
    {
        if (!parent::prepare($args)) {
            return false;
        }

        $this->role = $this->arg('role');
        if (!Profile_role::isValid($this->role)) {
            // TRANS: Client error displayed when trying to revoke an invalid role.
            $this->clientError(_('Invalid role.'));
        }
        if (!Profile_role::isSettable($this->role)) {
            // TRANS: Client error displayed when trying to revoke a reserved role.
            $this->clientError(_('This role is reserved and cannot be set.'));
        }

        $cur = common_current_user();

        assert(!empty($cur)); // checked by parent

        if (!$cur->hasRight(Right::REVOKEROLE)) {
            // TRANS: Client error displayed when trying to revoke a role without having the right to do that.
            $this->clientError(_('You cannot revoke user roles on this site.'));
        }

        assert(!empty($this->profile)); // checked by parent

        if (!$this->profile->hasRole($this->role)) {
            // TRANS: Client error displayed when trying to revoke a role that is not set.
            $this->clientError(_('User does not have this role.'));
        }

        return true;
    }

    /**
     * Sandbox a user.
     *
     * @return void
     */
    function handlePost()
    {
        $this->profile->revokeRole($this->role);
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * robots.txt generator
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 *
 * 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/>.
 */

if (!defined('STATUSNET')) {
    exit(1);
}

/**
 * Prints out a static robots.txt
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class RobotstxtAction extends Action
{
    /**
     * Handles requests
     *
     * Since this is a relatively static document, we
     * don't do a prepare()
     *
     * @param array $args GET, POST, and URL params; unused.
     *
     * @return void
     */
    function handle($args)
    {
        if (Event::handle('StartRobotsTxt', array($this))) {

            header('Content-Type: text/plain');

            print "User-Agent: *\n";

            if (common_config('site', 'private')) {

                print "Disallow: /\n";
            } else {
                $disallow = common_config('robotstxt', 'disallow');

                foreach ($disallow as $dir) {
                    print "Disallow: /$dir/\n";
                }

                $crawldelay = common_config('robotstxt', 'crawldelay');

                if (!empty($crawldelay)) {
                    print "Crawl-delay: " . $crawldelay . "\n";
                }
            }

            Event::handle('EndRobotsTxt', array($this));
        }
    }

    /**
     * Return true; this page doesn't touch the DB.
     *
     * @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
 * Copyright (C) 2008-2010, StatusNet, Inc.
 *
 * Really Simple Discovery (RSD) for API access
 *
 * PHP version 5
 *
 * 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>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 *
 */

if (!defined('STATUSNET')) {
    exit(1);
}

/**
 * RSD action class
 *
 * Really Simple Discovery (RSD) is a simple (to a fault, maybe)
 * discovery tool for blog APIs.
 *
 * http://tales.phrasewise.com/rfc/rsd
 *
 * Anil Dash suggested that RSD be used for services that implement
 * the Twitter API:
 *
 * http://dashes.com/anil/2009/12/the-twitter-api-is-finished.html
 *
 * It's in use now for WordPress.com blogs:
 *
 * http://matt.wordpress.com/xmlrpc.php?rsd
 *
 * I (evan@status.net) have tried to stay faithful to the premise of
 * RSD, while adding information useful to StatusNet client developers.
 * In particular:
 *
 * - There is a link from each user's profile page to their personal
 *   RSD feed. A personal rsd.xml includes a 'blogID' element that is
 *   their username.
 * - There is a link from the public root to '/rsd.xml', a public RSD
 *   feed. It's identical to the personal rsd except it doesn't include
 *   a blogId.
 * - I've added a setting to the API to indicate that OAuth support is
 *   available.
 *
 * @category API
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class RsdAction extends Action
{
    /**
     * Optional attribute for the personal rsd.xml file.
     */
    var $user = null;

    /**
     * Prepare the action for use.
     *
     * Check for a nickname; redirect if non-canonical; if
     * not provided, assume public rsd.xml.
     *
     * @param array $args GET, POST, and URI arguments.
     *
     * @return boolean success flag
     */
    function prepare($args)
    {
        parent::prepare($args);

        // optional argument

        $nickname_arg = $this->arg('nickname');

        if (empty($nickname_arg)) {
            $this->user = null;
        } else {
            $nickname = common_canonical_nickname($nickname_arg);

            // Permanent redirect on non-canonical nickname

            if ($nickname_arg != $nickname) {
                common_redirect(common_local_url('rsd', array('nickname' => $nickname)), 301);
            }

            $this->user = User::getKV('nickname', $nickname);

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

        return true;
    }

    /**
     * Action handler.
     *
     * Outputs the XML format for an RSD file. May include
     * personal information if this is a personal file
     * (based on whether $user attribute is set).
     *
     * @param array $args array of arguments
     *
     * @return nothing
     */
    function handle($args)
    {
        header('Content-Type: application/rsd+xml');

        $this->startXML();

        $rsdNS = 'http://archipelago.phrasewise.com/rsd';
        $this->elementStart('rsd', array('version' => '1.0',
                                         'xmlns' => $rsdNS));
        $this->elementStart('service');
        // TRANS: Engine name for RSD.
        $this->element('engineName', null, _('StatusNet'));
        $this->element('engineLink', null, 'http://status.net/');
        $this->elementStart('apis');
        if (Event::handle('StartRsdListApis', array($this, $this->user))) {

            $blogID   = (empty($this->user)) ? '' : $this->user->nickname;
            $apiAttrs = array('name' => 'Twitter',
                              'preferred' => 'true',
                              'apiLink' => $this->_apiRoot(),
                              'blogID' => $blogID);

            $this->elementStart('api', $apiAttrs);
            $this->elementStart('settings');
            $this->element('docs', null,
                           'http://status.net/wiki/TwitterCompatibleAPI');
            $this->element('setting', array('name' => 'OAuth'),
                           'true');
            $this->elementEnd('settings');
            $this->elementEnd('api');

            // Atom API

            if (empty($this->user)) {
                $service = common_local_url('ApiAtomService');
            } else {
                $service = common_local_url('ApiAtomService', array('id' => $this->user->nickname));
            }

            $this->element('api', array('name' => 'Atom',
                                        'preferred' => 'false',
                                        'apiLink' => $service,
                                        'blogID' => $blogID));

            Event::handle('EndRsdListApis', array($this, $this->user));
        }
        $this->elementEnd('apis');
        $this->elementEnd('service');
        $this->elementEnd('rsd');

        $this->endXML();

        return true;
    }

    /**
     * Returns last-modified date for use in caching
     *
     * Per-user rsd.xml is dated to last change of user
     * (in case of nickname change); public has no date.
     *
     * @return string date of last change of this page
     */
    function lastModified()
    {
        if (!empty($this->user)) {
            return $this->user->modified;
        } else {
            return null;
        }
    }

    /**
     * Flag to indicate if this action is read-only
     *
     * It is; it doesn't change the DB.
     *
     * @param array $args ignored
     *
     * @return boolean true
     */
    function isReadOnly($args)
    {
        return true;
    }

    /**
     * Return current site's API root
     *
     * Varies based on URL parameters, like if fancy URLs are
     * turned on.
     *
     * @return string API root URI for this site
     */
    private function _apiRoot()
    {
        if (common_config('site', 'fancy')) {
            return common_path('api/', true);
        } else {
            return common_path('index.php/api/', true);
        }
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Action class to sandbox an abusive 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  Action
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    exit(1);
}

/**
 * Sandbox a user.
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class SandboxAction extends ProfileFormAction
{
    /**
     * Check parameters
     *
     * @param array $args action arguments (URL, GET, POST)
     *
     * @return boolean success flag
     */
    function prepare($args)
    {
        if (!parent::prepare($args)) {
            return false;
        }

        $cur = common_current_user();

        assert(!empty($cur)); // checked by parent

        if (!$cur->hasRight(Right::SANDBOXUSER)) {
            // TRANS: Client error displayed trying to sandbox users on a site where the feature is not enabled.
            $this->clientError(_('You cannot sandbox users on this site.'));
        }

        assert(!empty($this->profile)); // checked by parent

        if ($this->profile->isSandboxed()) {
            // TRANS: Client error displayed trying to sandbox an already sandboxed user.
            $this->clientError(_('User is already sandboxed.'));
        }

        return true;
    }

    /**
     * Sandbox a user.
     *
     * @return void
     */
    function handlePost()
    {
        $this->profile->sandbox();
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Action for showing profiles self-tagged with a given tag
 *
 * 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  Action
 * @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('STATUSNET') && !defined('LACONICA')) {
    exit(1);
}

/**
 * This class outputs a paginated list of profiles self-tagged with a given tag
 *
 * @category Output
 * @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/
 *
 * @see      Action
 */
class SelftagAction extends Action
{
    var $tag  = null;
    var $page = null;

    /**
     * For initializing members of the class.
     *
     * @param array $argarray misc. arguments
     *
     * @return boolean true
     */
    function prepare($argarray)
    {
        parent::prepare($argarray);

        $this->tag = $this->trimmed('tag');

        if (!common_valid_profile_tag($this->tag)) {
            // TRANS: Client error displayed when trying to list a profile with an invalid list.
            // TRANS: %s is the invalid list name.
            $this->clientError(sprintf(_('Not a valid list: %s.'),
                $this->tag));
            return;
        }

        $this->page = ($this->arg('page')) ? $this->arg('page') : 1;

        common_set_returnto($this->selfUrl());

        return true;
    }

    /**
     * Handler method
     *
     * @param array $argarray is ignored since it's now passed in in prepare()
     *
     * @return boolean is read only action?
     */
    function handle($argarray)
    {
        parent::handle($argarray);
        $this->showPage();
    }

    /**
     * Whips up a query to get a list of profiles based on the provided
     * people tag and page, initalizes a ProfileList widget, and displays
     * it to the user.
     *
     * @return nothing
     */
    function showContent()
    {
        $profile = new Profile();

        $offset = ($this->page - 1) * PROFILES_PER_PAGE;
        $limit  = PROFILES_PER_PAGE + 1;

        if (common_config('db', 'type') == 'pgsql') {
            $lim = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
        } else {
            $lim = ' LIMIT ' . $offset . ', ' . $limit;
        }

        // XXX: memcached this

        $qry =  'SELECT profile.* ' .
                'FROM profile JOIN ( profile_tag, profile_list ) ' .
                'ON profile.id = profile_tag.tagger ' .
                'AND profile_tag.tagger = profile_list.tagger ' .
                'AND profile_list.tag = profile_tag.tag ' .
                'WHERE profile_tag.tagger = profile_tag.tagged ' .
                "AND profile_tag.tag = '%s' ";

        $user = common_current_user();
        if (empty($user)) {
            $qry .= 'AND profile_list.private = false ';
        } else {
            $qry .= 'AND (profile_list.tagger = ' . $user->id .
                    ' OR profile_list.private = false) ';
        }

        $qry .= 'ORDER BY profile_tag.modified DESC%s';

        $profile->query(sprintf($qry, $this->tag, $lim));

        $ptl = new SelfTagProfileList($profile, $this); // pass the ammunition
        $cnt = $ptl->show();

        $this->pagination($this->page > 1,
                          $cnt > PROFILES_PER_PAGE,
                          $this->page,
                          'selftag',
                          array('tag' => $this->tag));
    }

    /**
     * Returns the page title
     *
     * @return string page title
     */
    function title()
    {
        // TRANS: Page title for page showing self tags.
        // TRANS: %1$s is a tag, %2$d is a page number.
        return sprintf(_('Users self-tagged with %1$s, page %2$d'),
            $this->tag, $this->page);
    }
}

class SelfTagProfileList extends ProfileList
{
    function newListItem($profile)
    {
        return new SelfTagProfileListItem($profile, $this->action);
    }
}

class SelfTagProfileListItem extends ProfileListItem
{
    function linkAttributes()
    {
        $aAttrs = parent::linkAttributes();

        if (common_config('nofollow', 'selftag')) {
            $aAttrs['rel'] .= ' nofollow';
        }

        return $aAttrs;
    }

    function homepageAttributes()
    {
        $aAttrs = parent::linkAttributes();

        if (common_config('nofollow', 'selftag')) {
            $aAttrs['rel'] = 'nofollow';
        }

        return $aAttrs;
    }

    function showTags()
    {
        $selftags = new SelfTagsWidget($this->out, $this->profile, $this->profile);
        $selftags->show();

        $user = common_current_user();

        if (!empty($user) && $user->id != $this->profile->id &&
                $user->getProfile()->canTag($this->profile)) {
            $yourtags = new PeopleTagsWidget($this->out, $user, $this->profile);
            $yourtags->show();
        }
    }
}