Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

the activity controller does not have a sanitize method!

Hi, I have had this error a couple of times now and it freezes the forum. A pop up box tries to open but it just hangs and I have to navigate away from the forum page, it's fine when I come back.

This time it was caused by this.
I was in my profile as an admin. I clicked on the cross to delete an activity and I then get the message: "the activity controller does not have a sanitize method"
I have attached a screen grab of the problem. Any help would be appreciated.

Comments

  • I noticed this too.

    It relates to this fix

    https://github.com/vanilla/vanilla/commit/a428a867ccee453097f7dbf2e76dd47fd81da349#commitcomment-14899543

    @linc seems this slipped through the net. Would this be somethign you could include in the next update?

    grep is your friend.

  • Cool, thanks for getting back so quickly! This should have been in an update then really. I'll add the extra code and give it a go.

  • Ok now I get a "view not found" error. Still hangs as well.

  • LincLinc Detroit Admin

    There's still a problem with this in master too, so thanks for the heads up. I'll work on a fix next week and backport it to 2.2. I'm expecting to release 2.2.1 in early January.

  • @Linc there are also some fixes to do with the editor, I wonder if you would consider those too.

    grep is your friend.

  • LincLinc Detroit Admin

    Sure, gimme a GitHub issue with commit links to backport the ones you're requesting.

  • Ok thanks @Linc I'll wait for the update. Not due to launch until January but I know the crowd will break it for sure! Have an excellent festive season ;-)

  • x00x00 MVP
    edited December 2015

    It was actually this commit

    https://github.com/vanilla/vanilla/commit/740694233c6379d47292e0a9a3f48237952f1da4#commitcomment-14899605

    I never saw or made an issue but there is a permanent error when uploading.

    TypeError: editor.textarea is undefined
    http://localhost/test/forumtest22/plugins/editor/js/editor.js?v=1.7.2
    Line 1210

    Basically the progress bar doesn't hidden becuase of the wrong selector is referenced.

    @beckyvb probably knows the status of the overall editor situation.

    grep is your friend.

  • It would be cool if we could get back the vanilla comment to gitub issue menu option. I really loved that feature. Not to be a nag ;)

    grep is your friend.

  • TofTof
    edited January 2016

    hi,

    I also have the same bug.

    With current Vanilla 2.2

    I tried to make the changes that are in this post.

    The file class.activitycontroller.php is different this link: https://github.com/vanilla/vanilla/commit/a428a867ccee453097f7dbf2e76dd47fd81da349#commitcomment-14899543

    And the file editor.js is different this link :
    https://github.com/vanilla/vanilla/commit/740694233c6379d47292e0a9a3f48237952f1da4#diff-4cdf1a850be5a6b9c69af45f60dbf08b

    I remind you that I am under 2 vanilla

    thank you for your answer

    This is my class.activitycontroller.php

    `<?php
    /**
    * Manages the activity stream.
    *
    * @copyright 2009-2015 Vanilla Forums Inc.
    * @license http://www.opensource.org/licenses/gpl-2.0.php GNU GPL v2
    * @package Dashboard
    * @since 2.0
    */

    /**
    * Handles /activity endpoint.
    */
    class ActivityController extends Gdn_Controller {

    /**  @var array Models to include. */
    public $Uses = array('Database', 'Form', 'ActivityModel');
    
    /** @var ActivityModel */
    public $ActivityModel;
    
    /**
     * Create some virtual properties.
     *
     * @param $Name
     * @return Gdn_DataSet
     */
    public function __get($Name) {
        switch ($Name) {
            case 'CommentData':
                Deprecated('ActivityController->CommentData', "ActivityController->data('Activities')");
                $Result = new Gdn_DataSet(array(), DATASET_TYPE_OBJECT);
                return $Result;
            case 'ActivityData':
                Deprecated('ActivityController->ActivityData', "ActivityController->data('Activities')");
                $Result = new Gdn_DataSet($this->data('Activities'), DATASET_TYPE_ARRAY);
                $Result->datasetType(DATASET_TYPE_OBJECT);
                return $Result;
        }
    }
    
    /**
     * Include JS, CSS, and modules used by all methods.
     *
     * Always called by dispatcher before controller's requested method.
     *
     * @since 2.0.0
     * @access public
     */
    public function initialize() {
        $this->Head = new HeadModule($this);
        $this->addJsFile('jquery.js');
        $this->addJsFile('jquery.livequery.js');
        $this->addJsFile('jquery.form.js');
        $this->addJsFile('jquery.popup.js');
        $this->addJsFile('jquery.gardenhandleajaxform.js');
        $this->addJsFile('global.js');
    
        $this->addCssFile('style.css');
        $this->addCssFile('vanillicon.css', 'static');
    
        // Add Modules
        $this->addModule('GuestModule');
        $this->addModule('SignedInModule');
    
        parent::initialize();
        Gdn_Theme::section('ActivityList');
        $this->setData('Breadcrumbs', array(array('Name' => t('Activity'), 'Url' => '/activity')));
    }
    
    /**
     * Display a single activity item & comments.
     *
     * Email notifications regarding activities link to this method.
     *
     * @since 2.0.0
     * @access public
     *
     * @param int $ActivityID Unique ID of activity item to display.
     */
    public function item($ActivityID = 0) {
        $this->addJsFile('activity.js');
        $this->title(t('Activity Item'));
    
        if (!is_numeric($ActivityID) || $ActivityID < 0) {
            $ActivityID = 0;
        }
    
        $this->ActivityData = $this->ActivityModel->getWhere(array('ActivityID' => $ActivityID));
        $this->setData('Comments', $this->ActivityModel->getComments(array($ActivityID)));
        $this->setData('Activities', $this->ActivityData);
    
        $this->render();
    }
    
    /**
     * Default activity stream.
     *
     * @since 2.0.0
     * @access public
     *
     * @param int $Offset Number of activity items to skip.
     */
    public function index($Filter = false, $Page = false) {
        switch (strtolower($Filter)) {
            case 'mods':
                $this->title(t('Recent Moderator Activity'));
                $this->permission('Garden.Moderation.Manage');
                $NotifyUserID = ActivityModel::NOTIFY_MODS;
                break;
            case 'admins':
                $this->title(t('Recent Admin Activity'));
                $this->permission('Garden.Settings.Manage');
                $NotifyUserID = ActivityModel::NOTIFY_ADMINS;
                break;
            case '':
            case 'feed': // rss feed
                $Filter = 'public';
                $this->title(t('Recent Activity'));
                $this->permission('Garden.Activity.View');
                $NotifyUserID = ActivityModel::NOTIFY_PUBLIC;
                break;
            default:
                throw notFoundException();
        }
    
        // Which page to load
        list($Offset, $Limit) = offsetLimit($Page, c('Garden.Activities.PerPage', 30));
        $Offset = is_numeric($Offset) ? $Offset : 0;
        if ($Offset < 0) {
            $Offset = 0;
        }
    
        // Page meta.
        $this->addJsFile('activity.js');
    
        if ($this->Head) {
            $this->Head->addRss(url('/activity/feed.rss', true), $this->Head->title());
        }
    
        // Comment submission
        $Session = Gdn::session();
        $Comment = $this->Form->getFormValue('Comment');
        $Activities = $this->ActivityModel->getWhere(array('NotifyUserID' => $NotifyUserID), $Offset, $Limit)->resultArray();
        $this->ActivityModel->joinComments($Activities);
    
        $this->setData('Filter', strtolower($Filter));
        $this->setData('Activities', $Activities);
    
        $this->addModule('ActivityFilterModule');
    
        $this->View = 'all';
        $this->render();
    }
    
    public function deleteComment($ID, $TK, $Target = '') {
        $session = Gdn::session();
        if (!$session->validateTransientKey($TK)) {
            throw permissionException();
        }
    
        if (!is_numeric($ID)) {
            throw Gdn_UserException('Invalid ID');
        }
    
        $comment = $this->ActivityModel->getComment($ID);
        if (!$comment) {
            throw notFoundException('Comment');
        }
    
        $activity = $this->ActivityModel->getID(val('ActivityID', $comment));
        if (!$activity) {
            throw notFoundException('Activity');
        }
    
        if (!$this->ActivityModel->canDelete($activity)) {
            throw permissionException();
        }
        $this->ActivityModel->deleteComment($ID);
        if ($this->deliveryType() === DELIVERY_TYPE_ALL) {
            redirect($Target);
        }
    
        $this->render('Blank', 'Utility', 'Dashboard');
    }
    
    /**
     * Delete an activity item.
     *
     * @since 2.0.0
     * @access public
     *
     * @param int $ActivityID Unique ID of item to delete.
     * @param string $TransientKey Verify intent.
     */
    public function delete($ActivityID = '', $TransientKey = '') {
        $session = Gdn::session();
        if (!$session->validateTransientKey($TransientKey)) {
            throw permissionException();
        }
    
        if (!is_numeric($ActivityID)) {
            throw Gdn_UserException('Invalid ID');
        }
    
        if (!$this->ActivityModel->canDelete($this->ActivityModel->getID($ActivityID))) {
            throw permissionException();
        }
    
        $this->ActivityModel->delete($ActivityID);
    
        if ($this->_DeliveryType === DELIVERY_TYPE_ALL) {
            redirect(GetIncomingValue('Target', $this->SelfUrl));
        }
    
        // Still here? Getting a 404.
        $this->ControllerName = 'Home';
        $this->View = 'FileNotFound';
        $this->render();
    }
    
    /**
     * Comment on an activity item.
     *
     * @since 2.0.0
     * @access public
     */
    public function comment() {
        $this->permission('Garden.Profiles.Edit');
    
        $Session = Gdn::session();
        $this->Form->setModel($this->ActivityModel);
        $NewActivityID = 0;
    
        // Form submitted
        if ($this->Form->authenticatedPostBack()) {
            $Body = $this->Form->getValue('Body', '');
            $ActivityID = $this->Form->getValue('ActivityID', '');
            if (is_numeric($ActivityID) && $ActivityID > 0) {
                $ActivityComment = array(
                    'ActivityID' => $ActivityID,
                    'Body' => $Body,
                    'Format' => 'Text');
    
                $ID = $this->ActivityModel->comment($ActivityComment);
    
                if ($ID == SPAM || $ID == UNAPPROVED) {
                    $this->StatusMessage = t('ActivityCommentRequiresApproval', 'Your comment will appear after it is approved.');
                    $this->render('Blank', 'Utility');
                    return;
                }
    
                $this->Form->setValidationResults($this->ActivityModel->validationResults());
                if ($this->Form->errorCount() > 0) {
                    throw new Exception($this->ActivityModel->Validation->resultsText());
    
                    $this->errorMessage($this->Form->errors());
                }
            }
        }
    
        // Redirect back to the sending location if this isn't an ajax request
        if ($this->_DeliveryType === DELIVERY_TYPE_ALL) {
            $Target = $this->Form->getValue('Return');
            if (!$Target) {
                $Target = '/activity';
            }
            redirect($Target);
        } else {
            // Load the newly added comment.
            $this->setData('Comment', $this->ActivityModel->getComment($ID));
    
            // Set it in the appropriate view.
            $this->View = 'comment';
        }
    
        // And render
        $this->render();
    }
    
    /**
     *
     * 
     * @param bool $Notify
     * @param bool $UserID
     */
    public function post($Notify = false, $UserID = false) {
        if (is_numeric($Notify)) {
            $UserID = $Notify;
            $Notify = false;
        }
    
        if (!$UserID) {
            $UserID = Gdn::session()->UserID;
        }
    
        switch ($Notify) {
            case 'mods':
                $this->permission('Garden.Moderation.Manage');
                $NotifyUserID = ActivityModel::NOTIFY_MODS;
                break;
            case 'admins':
                $this->permission('Garden.Settings.Manage');
                $NotifyUserID = ActivityModel::NOTIFY_ADMINS;
                break;
            default:
                $this->permission('Garden.Profiles.Edit');
                $NotifyUserID = ActivityModel::NOTIFY_PUBLIC;
                break;
        }
    
        $Activities = array();
    
        if ($this->Form->authenticatedPostBack()) {
            $Data = $this->Form->formValues();
            $Data = $this->ActivityModel->filterForm($Data);
            if (!isset($Data['Format']) || strcasecmp($Data['Format'], 'Raw') == 0) {
                $Data['Format'] = c('Garden.InputFormatter');
            }
    
            if ($UserID != Gdn::session()->UserID) {
                // This is a wall post.
                $Activity = array(
                    'ActivityType' => 'WallPost',
                    'ActivityUserID' => $UserID,
                    'RegardingUserID' => Gdn::session()->UserID,
                    'HeadlineFormat' => t('HeadlineFormat.WallPost', '{RegardingUserID,you} &rarr; {ActivityUserID,you}'),
                    'Story' => $Data['Comment'],
                    'Format' => $Data['Format'],
                    'Data' => array('Bump' => true)
                );
            } else {
                // This is a status update.
                $Activity = array(
                    'ActivityType' => 'Status',
                    'HeadlineFormat' => t('HeadlineFormat.Status', '{ActivityUserID,user}'),
                    'Story' => $Data['Comment'],
                    'Format' => $Data['Format'],
                    'NotifyUserID' => $NotifyUserID,
                    'Data' => array('Bump' => true)
                );
                $this->setJson('StatusMessage', Gdn_Format::plainText($Activity['Story'], $Activity['Format']));
            }
    
            $Activity = $this->ActivityModel->save($Activity, false, array('CheckSpam' => true));
            if ($Activity == SPAM || $Activity == UNAPPROVED) {
                $this->StatusMessage = t('ActivityRequiresApproval', 'Your post will appear after it is approved.');
                $this->render('Blank', 'Utility');
                return;
            }
    
            if ($Activity) {
                if ($UserID == Gdn::session()->UserID && $NotifyUserID == ActivityModel::NOTIFY_PUBLIC) {
                    Gdn::userModel()->setField(Gdn::session()->UserID, 'About', Gdn_Format::plainText($Activity['Story'], $Activity['Format']));
                }
    
                $Activities = array($Activity);
                ActivityModel::joinUsers($Activities);
                $this->ActivityModel->calculateData($Activities);
            } else {
                $this->Form->setValidationResults($this->ActivityModel->validationResults());
    
                $this->StatusMessage = $this->ActivityModel->Validation->resultsText();
    

    // $this->render('Blank', 'Utility');
    }
    }

        if ($this->deliveryType() == DELIVERY_TYPE_ALL) {
            $Target = $this->Request->get('Target', '/activity');
            if (isSafeUrl($Target)) {
                redirect($Target);
            } else {
                redirect(url('/activity'));
            }
        }
    
        $this->setData('Activities', $Activities);
        $this->render('Activities');
    }
    

    }`

Sign In or Register to comment.