code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Upload an avatar
 *
 * 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  Settings
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Zach Copley <zach@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);
}

define('MAX_ORIGINAL', 480);

/**
 * Upload an avatar
 *
 * We use jCrop plugin for jQuery to crop the image after upload.
 *
 * @category Settings
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Zach Copley <zach@status.net>
 * @author   Sarven Capadisli <csarven@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 AvatarsettingsAction extends SettingsAction
{
    var $mode = null;
    var $imagefile = null;
    var $filename = null;

    /**
     * Title of the page
     *
     * @return string Title of the page
     */
    function title()
    {
        // TRANS: Title for avatar upload page.
        return _('Avatar');
    }

    /**
     * Instructions for use
     *
     * @return instructions for use
     */
    function getInstructions()
    {
        // TRANS: Instruction for avatar upload page.
        // TRANS: %s is the maximum file size, for example "500b", "10kB" or "2MB".
        return sprintf(_('You can upload your personal avatar. The maximum file size is %s.'),
                       ImageFile::maxFileSize());
    }

    /**
     * Content area of the page
     *
     * Shows a form for uploading an avatar.
     *
     * @return void
     */

    function showContent()
    {
        if ($this->mode == 'crop') {
            $this->showCropForm();
        } else {
            $this->showUploadForm();
        }
    }

    function showUploadForm()
    {
        $user = common_current_user();

        $profile = $user->getProfile();

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

        $this->elementStart('form', array('enctype' => 'multipart/form-data',
                                          'method' => 'post',
                                          'id' => 'form_settings_avatar',
                                          'class' => 'form_settings',
                                          'action' =>
                                          common_local_url('avatarsettings')));
        $this->elementStart('fieldset');
        // TRANS: Avatar upload page form legend.
        $this->element('legend', null, _('Avatar settings'));
        $this->hidden('token', common_session_token());

        if (Event::handle('StartAvatarFormData', array($this))) {
            $this->elementStart('ul', 'form_data');
            try {
                $original = Avatar::getUploaded($profile);

                $this->elementStart('li', array('id' => 'avatar_original',
                                                'class' => 'avatar_view'));
                // TRANS: Header on avatar upload page for thumbnail of originally uploaded avatar (h2).
                $this->element('h2', null, _("Original"));
                $this->elementStart('div', array('id'=>'avatar_original_view'));
                $this->element('img', array('src' => $original->displayUrl(),
                                            'width' => $original->width,
                                            'height' => $original->height,
                                            'alt' => $user->nickname));
                $this->elementEnd('div');
                $this->elementEnd('li');
            } catch (NoAvatarException $e) {
                // No original avatar found!
            }

            try {
                $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
                $this->elementStart('li', array('id' => 'avatar_preview',
                                                'class' => 'avatar_view'));
                // TRANS: Header on avatar upload page for thumbnail of to be used rendition of uploaded avatar (h2).
                $this->element('h2', null, _("Preview"));
                $this->elementStart('div', array('id'=>'avatar_preview_view'));
                $this->element('img', array('src' => $avatar->displayUrl(),
                                            'width' => AVATAR_PROFILE_SIZE,
                                            'height' => AVATAR_PROFILE_SIZE,
                                            'alt' => $user->nickname));
                $this->elementEnd('div');
                if (!empty($avatar->filename)) {
                    // TRANS: Button on avatar upload page to delete current avatar.
                    $this->submit('delete', _m('BUTTON','Delete'));
                }
                $this->elementEnd('li');
            } catch (NoAvatarException $e) {
                // No previously uploaded avatar to preview.
            }

            $this->elementStart('li', array ('id' => 'settings_attach'));
            $this->element('input', array('name' => 'MAX_FILE_SIZE',
                                          'type' => 'hidden',
                                          'id' => 'MAX_FILE_SIZE',
                                          'value' => ImageFile::maxFileSizeInt()));
            $this->element('input', array('name' => 'avatarfile',
                                          'type' => 'file',
                                          'id' => 'avatarfile'));
            $this->elementEnd('li');
            $this->elementEnd('ul');

            $this->elementStart('ul', 'form_actions');
            $this->elementStart('li');
                // TRANS: Button on avatar upload page to upload an avatar.
            $this->submit('upload', _m('BUTTON','Upload'));
            $this->elementEnd('li');
            $this->elementEnd('ul');
        }
        Event::handle('EndAvatarFormData', array($this));

        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    function showCropForm()
    {
        $user = common_current_user();

        $profile = $user->getProfile();

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

        $this->elementStart('form', array('method' => 'post',
                                          'id' => 'form_settings_avatar',
                                          'class' => 'form_settings',
                                          'action' =>
                                          common_local_url('avatarsettings')));
        $this->elementStart('fieldset');
        // TRANS: Avatar upload page crop form legend.
        $this->element('legend', null, _('Avatar settings'));
        $this->hidden('token', common_session_token());

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

        $this->elementStart('li',
                            array('id' => 'avatar_original',
                                  'class' => 'avatar_view'));
        // TRANS: Header on avatar upload crop form for thumbnail of originally uploaded avatar (h2).
        $this->element('h2', null, _('Original'));
        $this->elementStart('div', array('id'=>'avatar_original_view'));
        $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
                                    'width' => $this->filedata['width'],
                                    'height' => $this->filedata['height'],
                                    'alt' => $user->nickname));
        $this->elementEnd('div');
        $this->elementEnd('li');

        $this->elementStart('li',
                            array('id' => 'avatar_preview',
                                  'class' => 'avatar_view'));
        // TRANS: Header on avatar upload crop form for thumbnail of to be used rendition of uploaded avatar (h2).
        $this->element('h2', null, _('Preview'));
        $this->elementStart('div', array('id'=>'avatar_preview_view'));
        $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
                                    'width' => AVATAR_PROFILE_SIZE,
                                    'height' => AVATAR_PROFILE_SIZE,
                                    'alt' => $user->nickname));
        $this->elementEnd('div');

        foreach (array('avatar_crop_x', 'avatar_crop_y',
                       'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
            $this->element('input', array('name' => $crop_info,
                                          'type' => 'hidden',
                                          'id' => $crop_info));
        }

        // TRANS: Button on avatar upload crop form to confirm a selected crop as avatar.
        $this->submit('crop', _m('BUTTON','Crop'));

        $this->elementEnd('li');
        $this->elementEnd('ul');
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    /**
     * Handle a post
     *
     * We mux on the button name to figure out what the user actually wanted.
     *
     * @return void
     */
    function handlePost()
    {
        // Workaround for PHP returning empty $_POST and $_FILES when POST
        // length > post_max_size in php.ini

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

        // 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->showForm(_('There was a problem with your session token. '.
                               'Try again, please.'));
            return;
        }

        if (Event::handle('StartAvatarSaveForm', array($this))) {
            if ($this->arg('upload')) {
                $this->uploadAvatar();
                } else if ($this->arg('crop')) {
                    $this->cropAvatar();
                } else if ($this->arg('delete')) {
                    $this->deleteAvatar();
                } else {
                    // TRANS: Unexpected validation error on avatar upload form.
                    $this->showForm(_('Unexpected form submission.'));
                }
            Event::handle('EndAvatarSaveForm', array($this));
        }
    }

    /**
     * Handle an image upload
     *
     * Does all the magic for handling an image upload, and crops the
     * image by default.
     *
     * @return void
     */
    function uploadAvatar()
    {
        try {
            $imagefile = ImageFile::fromUpload('avatarfile');
        } catch (Exception $e) {
            $this->showForm($e->getMessage());
            return;
        }
        if ($imagefile === null) {
            // TRANS: Validation error on avatar upload form when no file was uploaded.
            $this->showForm(_('No file uploaded.'));
            return;
        }

        $cur = common_current_user();
        $type = $imagefile->preferredType();
        $filename = Avatar::filename($cur->id,
                                     image_type_to_extension($type),
                                     null,
                                     'tmp'.common_timestamp());

        $filepath = Avatar::path($filename);
        $imagefile = $imagefile->copyTo($filepath);

        $filedata = array('filename' => $filename,
                          'filepath' => $filepath,
                          'width' => $imagefile->width,
                          'height' => $imagefile->height,
                          'type' => $type);

        $_SESSION['FILEDATA'] = $filedata;

        $this->filedata = $filedata;

        $this->mode = 'crop';

        // TRANS: Avatar upload form instruction after uploading a file.
        $this->showForm(_('Pick a square area of the image to be your avatar.'),
                        true);
    }

    /**
     * Handle the results of jcrop.
     *
     * @return void
     */
    public function cropAvatar()
    {
        $filedata = $_SESSION['FILEDATA'];

        if (!$filedata) {
            // TRANS: Server error displayed if an avatar upload went wrong somehow server side.
            $this->serverError(_('Lost our file data.'));
        }

        $file_d = ($filedata['width'] > $filedata['height'])
                     ? $filedata['height'] : $filedata['width'];

        $dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x'):0;
        $dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0;
        $dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$file_d;
        $dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$file_d;
        $size = intval(min($dest_w, $dest_h, MAX_ORIGINAL));

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

        $imagefile = new ImageFile($user->id, $filedata['filepath']);
        $filename = $imagefile->resize($size, $dest_x, $dest_y, $dest_w, $dest_h);

        if ($profile->setOriginal($filename)) {
            @unlink($filedata['filepath']);
            unset($_SESSION['FILEDATA']);
            $this->mode = 'upload';
            // TRANS: Success message for having updated a user avatar.
            $this->showForm(_('Avatar updated.'), true);
        } else {
            // TRANS: Error displayed on the avatar upload page if the avatar could not be updated for an unknown reason.
            $this->showForm(_('Failed updating avatar.'));
        }
    }

    /**
     * Get rid of the current avatar.
     *
     * @return void
     */
    function deleteAvatar()
    {
        $user = common_current_user();
        $profile = $user->getProfile();

        Avatar::deleteFromProfile($profile);

        // TRANS: Success message for deleting a user avatar.
        $this->showForm(_('Avatar deleted.'), true);
    }

    /**
     * Add the jCrop stylesheet
     *
     * @return void
     */

    function showStylesheets()
    {
        parent::showStylesheets();
        $this->cssLink('js/extlib/jquery-jcrop/css/jcrop.css','base','screen, projection, tv');
    }

    /**
     * Add the jCrop scripts
     *
     * @return void
     */
    function showScripts()
    {
        parent::showScripts();

        if ($this->mode == 'crop') {
            $this->script('extlib/jquery-jcrop/jcrop.js');
            $this->script('jcrop.go.js');
        }

        $this->autofocus('avatarfile');
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Download a backup of your own account to 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);
}

/**
 * Download a backup of your own account to the browser
 *
 * We go through some hoops to make this only respond to POST, since
 * it's kind of expensive and there's probably some downside to having
 * your account in all kinds of search engines.
 *
 * @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 BackupaccountAction extends Action
{
    /**
     * Returns the title of the page
     *
     * @return string page title
     */
    function title()
    {
        // TRANS: Title for backup account page.
        return _('Backup 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 thrown when trying to backup an account while not logged in.
            throw new ClientException(_('Only logged-in users can backup their account.'), 403);
        }

        if (!$cur->hasRight(Right::BACKUPACCOUNT)) {
            // TRANS: Client exception thrown when trying to backup an account without having backup rights.
            throw new ClientException(_('You may not backup 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->sendFeed();
        } else {
            $this->showPage();
        }
        return;
    }

    /**
     * Send a feed of the user's activities to the browser
     *
     * Uses the UserActivityStream class; may take a long time!
     *
     * @return void
     */

    function sendFeed()
    {
        $cur = common_current_user();

        $stream = new UserActivityStream($cur, true, UserActivityStream::OUTPUT_RAW);

        header('Content-Disposition: attachment; filename='.$cur->nickname.'.atom');
        header('Content-Type: application/atom+xml; charset=utf-8');

        // @fixme atom feed logic is in getString...
        // but we just want it to output to the outputter.
        $this->raw($stream->getString());
    }

    /**
     * Show a little form so that the person can request a backup.
     *
     * @return void
     */

    function showContent()
    {
        $form = new BackupAccountForm($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 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 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 BackupAccountForm extends Form
{
    /**
     * Class of the form.
     *
     * @return string the form's class
     */
    function formClass()
    {
        return 'form_profile_backup';
    }

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

    /**
     * Output form data
     *
     * Really, just instructions for doing a backup.
     *
     * @return void
     */
    function formData()
    {
        $msg =
            // TRANS: Information displayed on the backup account page.
            _('You can backup your account data in '.
              'Activity Streams '.
              'format. This is an experimental feature and provides an '.
              'incomplete backup; private account '.
              'information like email and IM addresses is not backed up. '.
              'Additionally, uploaded files and direct messages are not '.
              'backed up.');
        $this->out->elementStart('p');
        $this->out->raw($msg);
        $this->out->elementEnd('p');
    }

    /**
     * Buttons for the form
     *
     * In this case, a single submit button
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit('submit',
                           // TRANS: Submit button to backup an account on the backup account page.
                           _m('BUTTON', 'Backup'),
                           'submit',
                           null,
                           // TRANS: Title for submit button to backup an account on the backup account page.
                           _('Backup your account.'));
    }
}

license: mit


code:
<?php
/**
 * Block a user action class.
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Robin Millette <millette@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('STATUSNET') && !defined('LACONICA')) {
    exit(1);
}

/**
 * Block a user action class.
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Robin Millette <millette@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class BlockAction extends ProfileFormAction
{
    var $profile = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @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->hasBlocked($this->profile)) {
            // TRANS: Client error displayed when blocking a user that has already been blocked.
            $this->clientError(_('You already blocked that user.'));
        }

        return true;
    }

    /**
     * Handle request
     *
     * @param array $args $_REQUEST args; handled in prepare()
     *
     * @return void
     */
    function handle($args)
    {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            if ($this->arg('no')) {
                $this->returnToPrevious();
            } elseif ($this->arg('yes')) {
                $this->handlePost();
                $this->returnToPrevious();
            } else {
                $this->showPage();
            }
        } else {
            $this->showPage();
        }
    }

    function showContent() {
        $this->areYouSureForm();
    }

    function title() {
        // TRANS: Title for block user page.
        return _('Block user');
    }

    function showNoticeForm() {
        // nop
    }

    /**
     * Confirm with user.
     *
     * Shows a confirmation form.
     *
     * @return void
     */
    function areYouSureForm()
    {
        // @fixme if we ajaxify the confirmation form, skip the preview on ajax hits
        $profile = new ArrayWrapper(array($this->profile));
        $preview = new ProfileList($profile, $this);
        $preview->show();

        $id = $this->profile->id;
        $this->elementStart('form', array('id' => 'block-' . $id,
                                           'method' => 'post',
                                           'class' => 'form_settings form_entity_block',
                                           'action' => common_local_url('block')));
        $this->elementStart('fieldset');
        $this->hidden('token', common_session_token());
        // TRANS: Legend for block user form.
        $this->element('legend', _('Block user'));
        $this->element('p', null,
                       // TRANS: Explanation of consequences when blocking a user on the block user page.
                       _('Are you sure you want to block this user? '.
                         'Afterwards, they will be unsubscribed from you, '.
                         'unable to subscribe to you in the future, and '.
                         'you will not be notified of any @-replies from them.'));
        $this->element('input', array('id' => 'blockto-' . $id,
                                      'name' => 'profileid',
                                      'type' => 'hidden',
                                      'value' => $id));
        foreach ($this->args as $k => $v) {
            if (substr($k, 0, 9) == 'returnto-') {
                $this->hidden($k, $v);
            }
        }
        $this->submit('form_action-no',
                      // TRANS: Button label on the user block form.
                      _m('BUTTON','No'),
                      'submit form_action-primary',
                      'no',
                      // TRANS: Submit button title for 'No' when blocking a user.
                      _('Do not block this user.'));
        $this->submit('form_action-yes',
                      // TRANS: Button label on the user block form.
                      _m('BUTTON','Yes'),
                      'submit form_action-secondary',
                      'yes',
                      // TRANS: Submit button title for 'Yes' when blocking a user.
                      _('Block this user.'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    /**
     * Actually block a user.
     *
     * @return void
     */

    function handlePost()
    {
        $cur = common_current_user();

        if (Event::handle('StartBlockProfile', array($cur, $this->profile))) {
            $result = $cur->block($this->profile);
            if ($result) {
                Event::handle('EndBlockProfile', array($cur, $this->profile));
            }
        }

        if (!$result) {
            // TRANS: Server error displayed when blocking a user fails.
            $this->serverError(_('Failed to save block information.'));
        }
    }

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

    /**
     * Override for form session token checks; on our first hit we're just
     * requesting confirmation, which doesn't need a token. We need to be
     * able to take regular GET requests from email!
     *
     * @throws ClientException if token is bad on POST request or if we have
     *         confirmation parameters which could trigger something.
     */
    function checkSessionToken()
    {
        if ($_SERVER['REQUEST_METHOD'] == 'POST' ||
            $this->arg('yes') ||
            $this->arg('no')) {

            return parent::checkSessionToken();
        }
    }

    /**
     * If we reached this form without returnto arguments, return to the
     * current user's subscription list.
     *
     * @return string URL
     */
    function defaultReturnTo()
    {
        $user = common_current_user();
        if ($user) {
            return common_local_url('subscribers',
                                    array('nickname' => $user->nickname));
        } else {
            return common_local_url('public');
        }
    }
}


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

/**
 * List of profiles blocked from this group
 *
 * @category Group
 * @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 BlockedfromgroupAction extends GroupAction
{
    var $page = null;

    function isReadOnly($args)
    {
        return true;
    }

    protected function prepare(array $args=array())
    {
        parent::prepare($args);
        $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;

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

        // Permanent redirect on non-canonical nickname

        if ($nickname_arg != $nickname) {
            $args = array('nickname' => $nickname);
            if ($this->page != 1) {
                $args['page'] = $this->page;
            }
            common_redirect(common_local_url('blockedfromgroup', $args), 301);
        }

        if (!$nickname) {
            // TRANS: Client error displayed when requesting a list of blocked users for a group without providing a group nickname.
            $this->clientError(_('No nickname.'), 404);
        }

        $local = Local_group::getKV('nickname', $nickname);

        if (!$local) {
            // TRANS: Client error displayed when requesting a list of blocked users for a non-local group.
            $this->clientError(_('No such group.'), 404);
        }

        $this->group = User_group::getKV('id', $local->group_id);

        if (!$this->group) {
            // TRANS: Client error displayed when requesting a list of blocked users for a non-existing group.
            $this->clientError(_('No such group.'), 404);
        }

        return true;
    }

    function title()
    {
        if ($this->page == 1) {
            // TRANS: Title for first page with list of users blocked from a group.
            // TRANS: %s is a group nickname.
            return sprintf(_('%s blocked profiles'),
                           $this->group->nickname);
        } else {
            // TRANS: Title for any but the first page with list of users blocked from a group.
            // TRANS: %1$s is a group nickname, %2$d is a page number.
            return sprintf(_('%1$s blocked profiles, page %2$d'),
                           $this->group->nickname,
                           $this->page);
        }
    }

    protected function handle()
    {
        parent::handle();
        $this->showPage();
    }

    function showPageNotice()
    {
        $this->element('p', 'instructions',
                       // TRANS: Instructions for list of users blocked from a group.
                       _('A list of the users blocked from joining this group.'));
    }

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

        $cnt = 0;

        $blocked = $this->group->getBlocked($offset, $limit);

        if ($blocked) {
            $blocked_list = new GroupBlockList($blocked, $this->group, $this);
            $cnt = $blocked_list->show();
        }

        $blocked->free();

        $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
                          $this->page, 'blockedfromgroup',
                          array('nickname' => $this->group->nickname));
    }
}

class GroupBlockList extends ProfileList
{
    var $group = null;

    function __construct($profile, $group, $action)
    {
        parent::__construct($profile, $action);

        $this->group = $group;
    }

    function newListItem($profile)
    {
        return new GroupBlockListItem($profile, $this->group, $this->action);
    }
}

class GroupBlockListItem extends ProfileListItem
{
    var $group = null;

    function __construct($profile, $group, $action)
    {
        parent::__construct($profile, $action);

        $this->group = $group;
    }

    function showActions()
    {
        $this->startActions();
        $this->showGroupUnblockForm();
        $this->endActions();
    }

    function showGroupUnblockForm()
    {
        $user = common_current_user();

        if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) {
            $this->out->elementStart('li', 'entity_block');
            $bf = new GroupUnblockForm($this->out, $this->profile, $this->group,
                                       array('action' => 'blockedfromgroup',
                                             'nickname' => $this->group->nickname));
            $bf->show();
            $this->out->elementEnd('li');
        }
    }
}

/**
 * Form for unblocking a user from a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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      UnblockForm
 */
class GroupUnblockForm extends Form
{
    /**
     * Profile of user to block
     */

    var $profile = null;

    /**
     * Group to block the user from
     */

    var $group = null;

    /**
     * Return-to args
     */

    var $args = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out     output channel
     * @param Profile       $profile profile of user to block
     * @param User_group    $group   group to block user from
     * @param array         $args    return-to args
     */
    function __construct($out=null, $profile=null, $group=null, $args=null)
    {
        parent::__construct($out);

        $this->profile = $profile;
        $this->group   = $group;
        $this->args    = $args;
    }

    /**
     * ID of the form
     *
     * @return int ID of the form
     */
    function id()
    {
        // This should be unique for the page.
        return 'unblock-' . $this->profile->id;
    }

    /**
     * class of the form
     *
     * @return string class of the form
     */
    function formClass()
    {
        return 'form_group_unblock';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        return common_local_url('groupunblock');
    }

    /**
     * Legend of the Form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend for unblocking a user from a group.
        $this->out->element('legend', null, _('Unblock user from group'));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->hidden('unblockto-' . $this->profile->id,
                           $this->profile->id,
                           'unblockto');
        $this->out->hidden('unblockgroup-' . $this->group->id,
                           $this->group->id,
                           'unblockgroup');
        if ($this->args) {
            foreach ($this->args as $k => $v) {
                $this->out->hidden('returnto-' . $k, $v);
            }
        }
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit('submit',
                           // TRANS: Button text for unblocking a user from a group.
                           _m('BUTTON','Unblock'),
                           'submit',
                           null,
                           // TRANS: Tooltip for button for unblocking a user from a group.
                           _('Unblock this user'));
    }
}


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

/**
 * Leave a group
 *
 * This is the action for leaving a group. It works more or less like the subscribe action
 * for users.
 *
 * @category Group
 * @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 CancelgroupAction extends Action
{
    var $group = null;

    /**
     * Prepare to run
     */
    function prepare($args)
    {
        parent::prepare($args);

        if (!common_logged_in()) {
            // TRANS: Client error displayed when trying to leave a group while not logged in.
            $this->clientError(_('You must be logged in to leave a group.'));
        }

        $nickname_arg = $this->trimmed('nickname');
        $id = intval($this->arg('id'));
        if ($id) {
            $this->group = User_group::getKV('id', $id);
        } else if ($nickname_arg) {
            $nickname = common_canonical_nickname($nickname_arg);

            // Permanent redirect on non-canonical nickname
            if ($nickname_arg != $nickname) {
                $args = array('nickname' => $nickname);
                common_redirect(common_local_url('leavegroup', $args), 301);
            }

            $local = Local_group::getKV('nickname', $nickname);

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

            $this->group = User_group::getKV('id', $local->group_id);
        } else {
            // TRANS: Client error displayed when trying to leave a group without providing a group name or group ID.
            $this->clientError(_('No nickname or ID.'), 404);
        }

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

        $cur = common_current_user();
        if (empty($cur)) {
            // TRANS: Client error displayed when trying to leave a group while not logged in.
            $this->clientError(_('Must be logged in.'), 403);
        }
        if ($this->arg('profile_id')) {
            if ($cur->isAdmin($this->group)) {
                $this->profile = Profile::getKV('id', $this->arg('profile_id'));
            } else {
                // TRANS: Client error displayed when trying to approve or cancel a group join request without
                // TRANS: being a group administrator.
                $this->clientError(_('Only group admin can approve or cancel join requests.'), 403);
            }
        } else {
            $this->profile = $cur->getProfile();
        }

        $this->request = Group_join_queue::pkeyGet(array('profile_id' => $this->profile->id,
                                                         'group_id' => $this->group->id));

        if (empty($this->request)) {
            // TRANS: Client error displayed when trying to approve a non-existing group join request.
            // TRANS: %s is a user nickname.
            $this->clientError(sprintf(_('%s is not in the moderation queue for this group.'), $this->profile->nickname), 403);
        }
        return true;
    }

    /**
     * Handle the request
     *
     * On POST, add the current user to the group
     *
     * @param array $args unused
     *
     * @return void
     */
    function handle($args)
    {
        parent::handle($args);

        try {
            $this->request->abort();
        } catch (Exception $e) {
            common_log(LOG_ERR, "Exception canceling group sub: " . $e->getMessage());
            // TRANS: Server error displayed when cancelling a queued group join request fails.
            // TRANS: %1$s is the leaving user's nickname, $2$s is the group nickname for which the leave failed.
            $this->serverError(sprintf(_('Could not cancel request for user %1$s to join group %2$s.'),
                                       $this->profile->nickname, $this->group->nickname));
            return;
        }

        if ($this->boolean('ajax')) {
            $this->startHTML('text/xml;charset=utf-8');
            $this->elementStart('head');
            // TRANS: Title for leave group page after leaving.
            // TRANS: %s$s is the leaving user's name, %2$s is the group name.
            $this->element('title', null, sprintf(_m('TITLE','%1$s left group %2$s'),
                                                  $this->profile->nickname,
                                                  $this->group->nickname));
            $this->elementEnd('head');
            $this->elementStart('body');
            $jf = new JoinForm($this, $this->group);
            $jf->show();
            $this->elementEnd('body');
            $this->endHTML();
        } else {
            common_redirect(common_local_url('groupmembers', array('nickname' => $this->group->nickname)), 303);
        }
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Cancel the subscription of a profile
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Group
 * @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('GNUSOCIAL')) { exit(1); }

/**
 * Cancel the subscription of a profile
 *
 * @category Subscription
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Mikael Nordfeldth <mmn@hethane.se>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class CancelsubscriptionAction extends FormAction
{
    protected $needPost = true;

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

        $profile_id = $this->int('unsubscribeto');
        $this->target = Profile::getKV('id', $profile_id);
        if (!$this->target instanceof Profile) {
            throw new NoProfileException($profile_id);
        }

        return true;
    }

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

        try {
            $request = Subscription_queue::pkeyGet(array('subscriber' => $this->scoped->id,
                                                         'subscribed' => $this->target->id));
            if ($request instanceof Subscription_queue) {
                $request->abort();
            }
        } catch (AlreadyFulfilledException $e) {
            common_debug('Tried to cancel a non-existing pending subscription');
        }

        if (StatusNet::isAjax()) {
            $this->startHTML('text/xml;charset=utf-8');
            $this->elementStart('head');
            // TRANS: Title after unsubscribing from a group.
            $this->element('title', null, _m('TITLE','Unsubscribed'));
            $this->elementEnd('head');
            $this->elementStart('body');
            $subscribe = new SubscribeForm($this, $this->target);
            $subscribe->show();
            $this->elementEnd('body');
            $this->endHTML();
            exit();
        } else {
            common_redirect(common_local_url('subscriptions',
                                             array('nickname' => $this->scoped->nickname)),
                            303);
        }
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Confirm an address
 *
 * 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  Confirm
 * @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);
}

/**
 * Confirm an address
 *
 * When users change their SMS, email, Jabber, or other addresses, we send out
 * a confirmation code to make sure the owner of that address approves. This class
 * accepts those codes.
 *
 * @category Confirm
 * @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 ConfirmaddressAction extends Action
{
    /** type of confirmation. */

    var $address;

    /**
     * Accept a confirmation code
     *
     * Checks the code and confirms the address in the
     * user record
     *
     * @param args $args $_REQUEST array
     *
     * @return void
     */
    function handle($args)
    {
        parent::handle($args);
        if (!common_logged_in()) {
            common_set_returnto($this->selfUrl());
            common_redirect(common_local_url('login'));
        }
        $code = $this->trimmed('code');
        if (!$code) {
            // TRANS: Client error displayed when not providing a confirmation code in the contact address confirmation action.
            $this->clientError(_('No confirmation code.'));
        }
        $confirm = Confirm_address::getKV('code', $code);
        if (!$confirm) {
            // TRANS: Client error displayed when providing a non-existing confirmation code in the contact address confirmation action.
            $this->clientError(_('Confirmation code not found.'));
        }
        $cur = common_current_user();
        if ($cur->id != $confirm->user_id) {
            // TRANS: Client error displayed when not providing a confirmation code for another user in the contact address confirmation action.
            $this->clientError(_('That confirmation code is not for you!'));
        }
        $type = $confirm->address_type;
        $transports = array();
        Event::handle('GetImTransports', array(&$transports));
        if (!in_array($type, array('email', 'sms')) && !in_array($type, array_keys($transports))) {
            // TRANS: Server error for an unknown address type, which can be 'email', 'sms', or the name of an IM network (such as 'xmpp' or 'aim')
            $this->serverError(sprintf(_('Unrecognized address type %s'), $type));
        }
        $this->address = $confirm->address;
        $cur->query('BEGIN');
        if (in_array($type, array('email', 'sms')))
        {
            if ($cur->$type == $confirm->address) {
                // TRANS: Client error for an already confirmed email/jabber/sms address.
                $this->clientError(_('That address has already been confirmed.'));
            }

            $orig_user = clone($cur);

            $cur->$type = $confirm->address;

            if ($type == 'sms') {
                $cur->carrier  = ($confirm->address_extra)+0;
                $carrier       = Sms_carrier::getKV($cur->carrier);
                $cur->smsemail = $carrier->toEmailAddress($cur->sms);
            }

            // Throws exception on failure.
            $cur->updateWithKeys($orig_user);

            if ($type == 'email') {
                $cur->emailChanged();
            }

        } else {

            $user_im_prefs = new User_im_prefs();
            $user_im_prefs->transport = $confirm->address_type;
            $user_im_prefs->user_id = $cur->id;
            if ($user_im_prefs->find() && $user_im_prefs->fetch()) {
                if($user_im_prefs->screenname == $confirm->address){
                    // TRANS: Client error for an already confirmed IM address.
                    $this->clientError(_('That address has already been confirmed.'));
                }
                $user_im_prefs->screenname = $confirm->address;
                $result = $user_im_prefs->update();

                if (!$result) {
                    common_log_db_error($user_im_prefs, 'UPDATE', __FILE__);
                    // TRANS: Server error displayed when updating IM preferences fails.
                    $this->serverError(_('Could not update user IM preferences.'));
                }
            }else{
                $user_im_prefs = new User_im_prefs();
                $user_im_prefs->screenname = $confirm->address;
                $user_im_prefs->transport = $confirm->address_type;
                $user_im_prefs->user_id = $cur->id;
                $result = $user_im_prefs->insert();

                if (!$result) {
                    common_log_db_error($user_im_prefs, 'INSERT', __FILE__);
                    // TRANS: Server error displayed when adding IM preferences fails.
                    $this->serverError(_('Could not insert user IM preferences.'));
                }
            }

        }

        $result = $confirm->delete();

        if (!$result) {
            common_log_db_error($confirm, 'DELETE', __FILE__);
            // TRANS: Server error displayed when an address confirmation code deletion from the
            // TRANS: database fails in the contact address confirmation action.
            $this->serverError(_('Could not delete address confirmation.'));
        }

        $cur->query('COMMIT');
        $this->showPage();
    }

    /**
     * Title of the page
     *
     * @return string title
     */
    function title()
    {
        // TRANS: Title for the contact address confirmation action.
        return _('Confirm address');
    }

    /**
     * Show a confirmation message.
     *
     * @return void
     */
    function showContent()
    {
        $cur  = common_current_user();

        $this->element('p', null,
                       // TRANS: Success message for the contact address confirmation action.
                       // TRANS: %s can be 'email', 'jabber', or 'sms'.
                       sprintf(_('The address "%s" has been '.
                                 'confirmed for your account.'),
                               $this->address));
    }
}


code:
<?php
/**
 * Display a conversation in the browser
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Mikael Nordfeldth <mmn@hethane.se>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 *
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 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); }

/**
 * Conversation tree in the browser
 *
 * Will always try to show the entire conversation, since that's how our
 * ConversationNoticeStream works.
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Mikael Nordfeldth <mmn@hethane.se>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class ConversationAction extends ManagedAction
{
    var $conv        = null;
    var $page        = null;
    var $notices     = null;

    /**
     * Initialization.
     *
     * @param array $args Web and URL arguments
     *
     * @return boolean false if id not passed in
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);
        $convId = $this->int('id');

        $this->conv = Conversation::getKV('id', $convId);
        if (!$this->conv instanceof Conversation) {
            throw new ClientException('Could not find specified conversation');
        }

        return true;
    }

    /**
     * Returns the page title
     *
     * @return string page title
     */
    function title()
    {
        // TRANS: Title for page with a conversion (multiple notices in context).
        return _('Conversation');
    }

    /**
     * Show content.
     *
     * NoticeList extended classes do most heavy lifting. Plugins can override.
     *
     * @return void
     */
    function showContent()
    {
        if (Event::handle('StartShowConversation', array($this, $this->conv, $this->scoped))) {
            $notices = $this->conv->getNotices();
            $nl = new FullThreadedNoticeList($notices, $this, $this->scoped);
            $cnt = $nl->show();
        }
        Event::handle('EndShowConversation', array($this, $this->conv, $this->scoped));
    }

    function isReadOnly()
    {
        return true;
    }

    function getFeeds()
    {

        return array(new Feed(Feed::JSON,
                              common_local_url('apiconversation',
                                               array(
                                                    'id' => $this->conv->id,
                                                    'format' => 'as')),
                              // TRANS: Title for link to notice feed.
                              // TRANS: %s is a user nickname.
                              _('Conversation feed (Activity Streams JSON)')),
                     new Feed(Feed::RSS2,
                              common_local_url('apiconversation',
                                               array(
                                                    'id' => $this->conv->id,
                                                    'format' => 'rss')),
                              // TRANS: Title for link to notice feed.
                              // TRANS: %s is a user nickname.
                              _('Conversation feed (RSS 2.0)')),
                     new Feed(Feed::ATOM,
                              common_local_url('apiconversation',
                                               array(
                                                    'id' => $this->conv->id,
                                                    'format' => 'atom')),
                              // TRANS: Title for link to notice feed.
                              // TRANS: %s is a user nickname.
                              _('Conversation feed (Activity Streams JSON)')));
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Delete your own account
 *
 * 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);
}

/**
 * Action to delete your own account
 *
 * Note that this is distinct from DeleteuserAction, which see. I thought
 * that making that action do both things (delete another user and delete the
 * current user) would open a lot of holes. I'm open to refactoring, however.
 *
 * @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 DeleteaccountAction extends Action
{
    private $_complete = false;
    private $_error    = null;

    /**
     * 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 trying to delete a user account while not logged in.
            throw new ClientException(_("Only logged-in users ".
                                        "can delete their account."), 403);
        }

        if (!$cur->hasRight(Right::DELETEACCOUNT)) {
            // TRANS: Client exception displayed trying to delete a user account without have the rights to do that.
            throw new ClientException(_("You cannot delete 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->deleteAccount();
        } else {
            $this->showPage();
        }
        return;
    }

    /**
     * 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;
    }

    /**
     * Delete the current user's account
     *
     * Checks for the "I am sure." string to make sure the user really
     * wants to delete their account.
     *
     * Then, marks the account as deleted and begins the deletion process
     * (actually done by a back-end handler).
     *
     * If successful it logs the user out, and shows a brief completion message.
     *
     * @return void
     */
    function deleteAccount()
    {
        $this->checkSessionToken();
        // !!! If this string is changed, it also needs to be changed in DeleteAccountForm::formData()
        // TRANS: Confirmation text for user deletion. The user has to type this exactly the same, including punctuation.
        $iamsure = _('I am sure.');
        if ($this->trimmed('iamsure') != $iamsure ) {
            // TRANS: Notification for user about the text that must be input to be able to delete a user account.
            // TRANS: %s is the text that needs to be input.
            $this->_error = sprintf(_('You must write "%s" exactly in the box.'), $iamsure);
            $this->showPage();
            return;
        }

        $cur = common_current_user();

        // Mark the account as deleted and shove low-level deletion tasks
        // to background queues. Removing a lot of posts can take a while...

        if (!$cur->hasRole(Profile_role::DELETED)) {
            $cur->grantRole(Profile_role::DELETED);
        }

        $qm = QueueManager::get();
        $qm->enqueue($cur, 'deluser');

        // The user is really-truly logged out

        common_set_user(null);
        common_real_login(false); // not logged in
        common_forgetme(); // don't log back in!

        $this->_complete = true;
        $this->showPage();
    }

    /**
     * Shows the page content.
     *
     * If the deletion is complete, just shows a completion message.
     *
     * Otherwise, shows the deletion form.
     *
     * @return void
     *
     */
    function showContent()
    {
        if ($this->_complete) {
            $this->element('p', 'confirmation',
                           // TRANS: Confirmation that a user account has been deleted.
                           _('Account deleted.'));
            return;
        }

        if (!empty($this->_error)) {
            $this->element('p', 'error', $this->_error);
            $this->_error = null;
        }

        $form = new DeleteAccountForm($this);
        $form->show();
    }

    /**
     * Show the title of the page
     *
     * @return string title
     */

    function title()
    {
        // TRANS: Page title for page on which a user account can be deleted.
        return _('Delete account');
    }
}

/**
 * Form for deleting your account
 *
 * Note that this mostly is here to keep you from accidentally deleting your
 * 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 DeleteAccountForm extends Form
{
    /**
     * Class of the form.
     *
     * @return string the form's class
     */
    function formClass()
    {
        return 'form_profile_delete';
    }

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

    /**
     * Output form data
     *
     * Instructions plus an 'i am sure' entry box.
     *
     * @return void
     */
    function formData()
    {
        $cur = common_current_user();

        // TRANS: Form text for user deletion form.
        $msg = '
' . _('This will permanently delete '.
                 'your account data from this server.') . '
';

        if ($cur->hasRight(Right::BACKUPACCOUNT)) {
            // TRANS: Additional form text for user deletion form shown if a user has account backup rights.
            // TRANS: %s is a URL to the backup page.
            $msg .= '
' . sprintf(_('You are strongly advised to '.
                              'back up your data'.
                              ' before deletion.'),
                           common_local_url('backupaccount')) . '
';
        }

        $this->out->elementStart('p');
        $this->out->raw($msg);
        $this->out->elementEnd('p');

        // !!! If this string is changed, it also needs to be changed in class DeleteaccountAction.
        // TRANS: Confirmation text for user deletion. The user has to type this exactly the same, including punctuation.
        $iamsure = _("I am sure.");
        $this->out->input('iamsure',
                          // TRANS: Field label for delete account confirmation entry.
                          _('Confirm'),
                          null,
                          // TRANS: Input title for the delete account field.
                          // TRANS: %s is the text that needs to be input.
                          sprintf(_('Enter "%s" to confirm that '.
                            'you want to delete your account.'),$iamsure ));
    }

    /**
     * Buttons for the form
     *
     * In this case, a single submit button
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit('submit',
                           // TRANS: Button text for user account deletion.
                           _m('BUTTON', 'Delete'),
                           'submit',
                           null,
                           // TRANS: Button title for user account deletion.
                           _('Permanently delete your account.'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Action class to delete an OAuth application
 *
 * 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    Zach Copley <zach@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

/**
 * Delete an OAuth appliction
 *
 * @category Action
 * @package  StatusNet
 * @author   Zach Copley <zach@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class DeleteapplicationAction extends Action
{
    var $app = null;

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

        if (!common_logged_in()) {
            // TRANS: Client error displayed trying to delete an application while not logged in.
            $this->clientError(_('You must be logged in to delete an application.'));
        }

        $id        = (int)$this->arg('id');
        $this->app = Oauth_application::getKV('id', $id);

        if (empty($this->app)) {
            // TRANS: Client error displayed trying to delete an application that does not exist.
            $this->clientError(_('Application not found.'));
        }

        $cur = common_current_user();

        if ($cur->id != $this->app->owner) {
            // TRANS: Client error displayed trying to delete an application the current user does not own.
            $this->clientError(_('You are not the owner of this application.'), 401);
        }

        return true;
    }

    /**
     * Handle request
     *
     * Shows a page with list of favorite notices
     *
     * @param array $args $_REQUEST args; handled in prepare()
     *
     * @return void
     */
    function handle($args)
    {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {

            // 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.'));
            }

            if ($this->arg('no')) {
                common_redirect(common_local_url('showapplication',
                                                 array('id' => $this->app->id)), 303);
            } elseif ($this->arg('yes')) {
                $this->handlePost();
                common_redirect(common_local_url('oauthappssettings'), 303);
            } else {
                $this->showPage();
            }
        }
    }

    function showContent() {
        $this->areYouSureForm();
    }

    function title() {
        // TRANS: Title for delete application page.
        return _('Delete application');
    }

    function showNoticeForm() {
        // nop
    }

    /**
     * Confirm with user.
     *
     * Shows a confirmation form.
     *
     * @return void
     */
    function areYouSureForm()
    {
        $id = $this->app->id;
        $this->elementStart('form', array('id' => 'deleteapplication-' . $id,
                                          'method' => 'post',
                                          'class' => 'form_settings form_entity_block',
                                          'action' => common_local_url('deleteapplication',
                                                                       array('id' => $this->app->id))));
        $this->elementStart('fieldset');
        $this->hidden('token', common_session_token());
        // TRANS: Fieldset legend on delete application page.
        $this->element('legend', _('Delete application'));
        $this->element('p', null,
                       // TRANS: Confirmation text on delete application page.
                       _('Are you sure you want to delete this application? '.
                         'This will clear all data about the application from the '.
                         'database, including all existing user connections.'));
        $this->submit('form_action-no',
                      // TRANS: Button label on the delete application form.
                      _m('BUTTON','No'),
                      'submit form_action-primary',
                      'no',
                      // TRANS: Submit button title for 'No' when deleting an application.
                      _('Do not delete this application.'));
        $this->submit('form_action-yes',
                      // TRANS: Button label on the delete application form.
                      _m('BUTTON','Yes'),
                      'submit form_action-secondary',
                      // TRANS: Submit button title for 'Yes' when deleting an application.
                      'yes', _('Delete this application.'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    /**
     * Actually delete the app
     *
     * @return void
     */
    function handlePost()
    {
        $this->app->delete();
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Delete a group
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Group
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Brion Vibber <brion@status.net>
 * @copyright 2008-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') && !defined('LACONICA')) {
    exit(1);
}

/**
 * Delete a group
 *
 * This is the action for deleting a group.
 *
 * @category Group
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Brion Vibber <brion@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/
 * @fixme merge more of this code with related variants
 */
class DeletegroupAction extends RedirectingAction
{
    var $group = null;

    /**
     * Prepare to run
     *
     * @fixme merge common setup code with other group actions
     * @fixme allow group admins to delete their own groups
     */
    function prepare($args)
    {
        parent::prepare($args);

        if (!common_logged_in()) {
            // TRANS: Client error when trying to delete group while not logged in.
            $this->clientError(_('You must be logged in to delete a group.'));
        }

        $nickname_arg = $this->trimmed('nickname');
        $id = intval($this->arg('id'));
        if ($id) {
            $this->group = User_group::getKV('id', $id);
        } else if ($nickname_arg) {
            $nickname = common_canonical_nickname($nickname_arg);

            // Permanent redirect on non-canonical nickname

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

            $local = Local_group::getKV('nickname', $nickname);

            if (!$local) {
                // TRANS: Client error when trying to delete a non-local group.
                $this->clientError(_('No such group.'), 404);
            }

            $this->group = User_group::getKV('id', $local->group_id);
        } else {
            // TRANS: Client error when trying to delete a group without providing a nickname or ID for the group.
            $this->clientError(_('No nickname or ID.'), 404);
        }

        if (!$this->group) {
            // TRANS: Client error when trying to delete a non-existing group.
            $this->clientError(_('No such group.'), 404);
        }

        $cur = common_current_user();
        if (!$cur->hasRight(Right::DELETEGROUP)) {
            // TRANS: Client error when trying to delete a group without having the rights to delete it.
            $this->clientError(_('You are not allowed to delete this group.'), 403);
        }

        return true;
    }

    /**
     * Handle the request
     *
     * On POST, delete the group.
     *
     * @param array $args unused
     *
     * @return void
     */
    function handle($args)
    {
        parent::handle($args);
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            if ($this->arg('no')) {
                $this->returnToPrevious();
                return;
            } elseif ($this->arg('yes')) {
                $this->handlePost();
                return;
            }
        }
        $this->showPage();
    }

    function handlePost()
    {
        $cur = common_current_user();

        try {
            if (Event::handle('StartDeleteGroup', array($this->group))) {
                $this->group->delete();
                Event::handle('EndDeleteGroup', array($this->group));
            }
        } catch (Exception $e) {
            // TRANS: Server error displayed if a group could not be deleted.
            // TRANS: %s is the name of the group that could not be deleted.
            $this->serverError(sprintf(_('Could not delete group %s.'),
                                       $this->group->nickname));
        }

        if ($this->boolean('ajax')) {
            $this->startHTML('text/xml;charset=utf-8');
            $this->elementStart('head');
            // TRANS: Message given after deleting a group.
            // TRANS: %s is the deleted group's name.
            $this->element('title', null, sprintf(_('Deleted group %s'),
                                                  $this->group->nickname));
            $this->elementEnd('head');
            $this->elementStart('body');
            // @fixme add a sensible AJAX response form!
            $this->elementEnd('body');
            $this->endHTML();
        } else {
            // @fixme if we could direct to the page on which this group
            // would have shown... that would be awesome
            common_redirect(common_local_url('groups'), 303);
        }
    }

    function title() {
        // TRANS: Title of delete group page.
        return _('Delete group');
    }

    function showContent() {
        $this->areYouSureForm();
        $block = new GroupProfileBlock($this, $this->group);
        $block->show();
    }

    /**
     * Confirm with user.
     * Ripped from DeleteuserAction
     *
     * Shows a confirmation form.
     *
     * @fixme refactor common code for things like this
     * @return void
     */
    function areYouSureForm()
    {
        $id = $this->group->id;
        $this->elementStart('form', array('id' => 'deletegroup-' . $id,
                                           'method' => 'post',
                                           'class' => 'form_settings form_entity_block',
                                           'action' => common_local_url('deletegroup', array('id' => $this->group->id))));
        $this->elementStart('fieldset');
        $this->hidden('token', common_session_token());
        // TRANS: Form legend for deleting a group.
        $this->element('legend', _('Delete group'));
        if (Event::handle('StartDeleteGroupForm', array($this, $this->group))) {
            $this->element('p', null,
                           // TRANS: Warning in form for deleleting a group.
                           _('Are you sure you want to delete this group? '.
                             'This will clear all data about the group from the '.
                             'database, without a backup. ' .
                             'Public posts to this group will still appear in ' .
                             'individual timelines.'));
            foreach ($this->args as $k => $v) {
                if (substr($k, 0, 9) == 'returnto-') {
                    $this->hidden($k, $v);
                }
            }
            Event::handle('EndDeleteGroupForm', array($this, $this->group));
        }
        $this->submit('form_action-no',
                      // TRANS: Button label on the delete group form.
                      _m('BUTTON','No'),
                      'submit form_action-primary',
                      'no',
                      // TRANS: Submit button title for 'No' when deleting a group.
                      _('Do not delete this group.'));
        $this->submit('form_action-yes',
                      // TRANS: Button label on the delete group form.
                      _m('BUTTON','Yes'),
                      'submit form_action-secondary',
                      'yes',
                      // TRANS: Submit button title for 'Yes' when deleting a group.
                      _('Delete this group.'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Class for deleting a notice
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Personal
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@status.net>
 * @copyright 2008 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);
}

// @todo FIXME: documentation needed.
class DeletenoticeAction extends Action
{
    var $error        = null;
    var $user         = null;
    var $notice       = null;
    var $profile      = null;
    var $user_profile = null;

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

        $this->user   = common_current_user();

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

        $notice_id    = $this->trimmed('notice');
        $this->notice = Notice::getKV($notice_id);

        if (!$this->notice) {
            // TRANS: Error message displayed trying to delete a non-existing notice.
            common_user_error(_('No such notice.'));
            exit;
        }

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

        return true;
    }

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

        if ($this->notice->profile_id != $this->user_profile->id &&
                   !$this->user->hasRight(Right::DELETEOTHERSNOTICE)) {
            // TRANS: Error message displayed trying to delete a notice that was not made by the current user.
            common_user_error(_('Cannot delete this notice.'));
            exit;
        }
        // XXX: Ajax!

        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $this->deleteNotice();
        } else if ($_SERVER['REQUEST_METHOD'] == 'GET') {
            $this->showForm();
        }
    }

    /**
     * Show the page notice
     *
     * Shows instructions for the page
     *
     * @return void
     */
    function showPageNotice()
    {
        $instr  = $this->getInstructions();
        $output = common_markup_to_html($instr);

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

    function getInstructions()
    {
        // TRANS: Instructions for deleting a notice.
        return _('You are about to permanently delete a notice. ' .
                 'Once this is done, it cannot be undone.');
    }

    function title()
    {
        // TRANS: Page title when deleting a notice.
        return _('Delete notice');
    }

    /**
     * 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();
    }

    /**
     * Insert delete notice form into the content
     *
     * @return void
     */
    function showContent()
    {
        $this->elementStart('form', array('id' => 'form_notice_delete',
                                          'class' => 'form_settings',
                                          'method' => 'post',
                                          'action' => common_local_url('deletenotice')));
        $this->elementStart('fieldset');
        // TRANS: Fieldset legend for the delete notice form.
        $this->element('legend', null, _('Delete notice'));
        $this->hidden('token', common_session_token());
        $this->hidden('notice', $this->trimmed('notice'));
        // TRANS: Message for the delete notice form.
        $this->element('p', null, _('Are you sure you want to delete this notice?'));
        $this->submit('form_action-no',
                      // TRANS: Button label on the delete notice form.
                      _m('BUTTON','No'),
                      'submit form_action-primary',
                      'no',
                      // TRANS: Submit button title for 'No' when deleting a notice.
                      _('Do not delete this notice.'));
        $this->submit('form_action-yes',
                      // TRANS: Button label on the delete notice form.
                      _m('BUTTON','Yes'),
                      'submit form_action-secondary',
                      'yes',
                      // TRANS: Submit button title for 'Yes' when deleting a notice.
                      _('Delete this notice.'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    function deleteNotice()
    {
        // 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->showForm(_('There was a problem with your session token. ' .
                              'Try again, please.'));
            return;
        }

        if ($this->arg('yes')) {
            if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
                $this->notice->delete();
                Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
            }
        }

        $url = common_get_returnto();

        if ($url) {
            common_set_returnto(null);
        } else {
            $url = common_local_url('public');
        }

        common_redirect($url, 303);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Action class to delete a user
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  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') && !defined('LACONICA')) {
    exit(1);
}

/**
 * Delete 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 DeleteuserAction extends ProfileFormAction
{
    var $user = null;

    /**
     * Take arguments for running
     *
     * @param array $args $_REQUEST args
     *
     * @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::DELETEUSER)) {
            // TRANS: Client error displayed when trying to delete a user without having the right to delete users.
            $this->clientError(_('You cannot delete users.'));
        }

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

        if (empty($this->user)) {
            // TRANS: Client error displayed when trying to delete a non-local user.
            $this->clientError(_('You can only delete local users.'));
        }

        return true;
    }

    /**
     * Handle request
     *
     * Shows a page with list of favorite notices
     *
     * @param array $args $_REQUEST args; handled in prepare()
     *
     * @return void
     */
    function handle($args)
    {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            if ($this->arg('no')) {
                $this->returnToPrevious();
            } elseif ($this->arg('yes')) {
                $this->handlePost();
                $this->returnToPrevious();
            } else {
                $this->showPage();
            }
        }
    }

    function showContent() {
        $this->areYouSureForm();
        $block = new AccountProfileBlock($this, $this->profile);
        $block->show();
    }

    function title() {
        // TRANS: Title of delete user page.
        return _m('TITLE','Delete user');
    }

    function showNoticeForm() {
        // nop
    }

    /**
     * Confirm with user.
     *
     * Shows a confirmation form.
     *
     * @return void
     */
    function areYouSureForm()
    {
        $id = $this->profile->id;
        $this->elementStart('form', array('id' => 'deleteuser-' . $id,
                                           'method' => 'post',
                                           'class' => 'form_settings form_entity_block',
                                           'action' => common_local_url('deleteuser')));
        $this->elementStart('fieldset');
        $this->hidden('token', common_session_token());
        // TRANS: Fieldset legend on delete user page.
        $this->element('legend', _('Delete user'));
        if (Event::handle('StartDeleteUserForm', array($this, $this->user))) {
            $this->element('p', null,
                           // TRANS: Information text to request if a user is certain that the described action has to be performed.
                           _('Are you sure you want to delete this user? '.
                             'This will clear all data about the user from the '.
                             'database, without a backup.'));
            $this->element('input', array('id' => 'deleteuserto-' . $id,
                                          'name' => 'profileid',
                                          'type' => 'hidden',
                                          'value' => $id));
            foreach ($this->args as $k => $v) {
                if (substr($k, 0, 9) == 'returnto-') {
                    $this->hidden($k, $v);
                }
            }
            Event::handle('EndDeleteUserForm', array($this, $this->user));
        }
        $this->submit('form_action-no',
                      // TRANS: Button label on the delete user form.
                      _m('BUTTON','No'),
                      'submit form_action-primary',
                      'no',
                      // TRANS: Submit button title for 'No' when deleting a user.
                      _('Do not delete this user.'));
        $this->submit('form_action-yes',
                      // TRANS: Button label on the delete user form.
                      _m('BUTTON','Yes'),
                      'submit form_action-secondary',
                      'yes',
                      // TRANS: Submit button title for 'Yes' when deleting a user.
                      _('Delete this user.'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    /**
     * Actually delete a user.
     *
     * @return void
     */
    function handlePost()
    {
        if (Event::handle('StartDeleteUser', array($this, $this->user))) {
            // Mark the account as deleted and shove low-level deletion tasks
            // to background queues. Removing a lot of posts can take a while...
            if (!$this->user->hasRole(Profile_role::DELETED)) {
                $this->user->grantRole(Profile_role::DELETED);
            }

            $qm = QueueManager::get();
            $qm->enqueue($this->user, 'deluser');

            Event::handle('EndDeleteUser', array($this, $this->user));
        }
    }
}