Fixed Infractions with 0 time result in a mismatch between infractions and profile points

Firnagzen

Member
If an infraction is issued with 0 time (0 days/weeks etc), this results in a mismatch between the points displayed on the user's profile page (next to Last Activity, Messages, Likes etc) and the actual infractions still active against them. The bug is caused by library/XenForo/DataWriter/Warning.php:
Code:
	protected function _preSave()
	{
		...

		if ($this->get('expiry_date') > 0 AND $this->get('expiry_date') <= XenForo_Application::$time)
		{
			$this->set('is_expired', 1);
		}
	}
Code:
	protected function _postSave()
	{
		if ($this->isInsert() || ($this->get('is_expired') == 0 && $this->getExisting('is_expired') == 1))
		{
                        ...

			if ($this->get('points'))
			{
				$userDw = XenForo_DataWriter::create('XenForo_DataWriter_User', XenForo_DataWriter::ERROR_SILENT);
				if ($userDw->setExistingData($this->get('user_id')))
				{
					$userDw->set('warning_points', $userDw->get('warning_points') + $this->get('points'));
					$userDw->save();
				}
			}}
This infraction is never actually expired using the _warningExpiredOrDeleted function, since that is only called on warnings that have is_expired set false. Thus the points are written to the user's profile display block, but never removed. A trivial fix would be to add a check before adding the points to the profile.
 
Last edited:

Isil`Zha

Active member
I'll add that this usually comes up with a mod didn't realize the expire time field had focus at some point while they were filling out a warning, and they accidentally enter a letter, which ends up changing it to zero.
 

Xon

Well-known member
I'm fairly sure this will interact very poorly with the "While at or above points threshold" option on a warning action resulting in an account where the warning appears to have expired but the warning actions are still applying.
 

Mike

XenForo developer
Staff member
I've worked around this by essentially just not allowing a warning to be inserted already expired; the warning will be given an expiry time of 1 hour in the future then.

The natural action would be to block specific behaviors if the warning is inserted expired, but this would naturally block some of the content-related actions. The code clearly doesn't expect a warning to be expired at insertion, so we can just block that instead.
 
  • Like
Reactions: Xon
Top