From 7d84f6d1c1fddac8c294ffc1c184a79ac5a4a357 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 8 Mar 2021 15:06:54 +0100 Subject: [PATCH] Enforce `user.conversation.floodControlTime` Resolves #135 --- .../ConversationMessageAction.class.php | 15 +++++- files/lib/form/ConversationAddForm.class.php | 3 +- .../ConversationHandler.class.php | 52 +++++++++++++------ language/de.xml | 1 + language/en.xml | 1 + 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/files/lib/data/conversation/message/ConversationMessageAction.class.php b/files/lib/data/conversation/message/ConversationMessageAction.class.php index 5394fd7..858872e 100644 --- a/files/lib/data/conversation/message/ConversationMessageAction.class.php +++ b/files/lib/data/conversation/message/ConversationMessageAction.class.php @@ -13,8 +13,11 @@ use wcf\data\IMessageQuoteAction; use wcf\data\smiley\SmileyCache; use wcf\system\attachment\AttachmentHandler; use wcf\system\bbcode\BBCodeHandler; +use wcf\system\conversation\ConversationHandler; +use wcf\system\exception\NamedUserException; use wcf\system\exception\PermissionDeniedException; use wcf\system\exception\UserInputException; +use wcf\system\flood\FloodControl; use wcf\system\html\input\HtmlInputProcessor; use wcf\system\message\censorship\Censorship; use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; @@ -290,6 +293,12 @@ class ConversationMessageAction extends AbstractDatabaseObjectAction implements */ public function validateQuickReply() { + try { + ConversationHandler::getInstance()->enforceFloodControl(true); + } catch (NamedUserException $e) { + throw new UserInputException('message', $e->getMessage()); + } + QuickReplyManager::getInstance()->setDisallowedBBCodes(\explode( ',', WCF::getSession()->getPermission('user.message.disallowedBBCodes') @@ -302,13 +311,17 @@ class ConversationMessageAction extends AbstractDatabaseObjectAction implements */ public function quickReply() { - return QuickReplyManager::getInstance()->createMessage( + $returnValues = QuickReplyManager::getInstance()->createMessage( $this, $this->parameters, ConversationAction::class, CONVERSATION_LIST_DEFAULT_SORT_ORDER, 'conversationMessageList' ); + + FloodControl::getInstance()->registerContent('com.woltlab.wcf.conversation.message'); + + return $returnValues; } /** diff --git a/files/lib/form/ConversationAddForm.class.php b/files/lib/form/ConversationAddForm.class.php index cdfa9d5..c3478be 100644 --- a/files/lib/form/ConversationAddForm.class.php +++ b/files/lib/form/ConversationAddForm.class.php @@ -121,7 +121,7 @@ class ConversationAddForm extends MessageForm )); } - ConversationHandler::getInstance()->enforceFloodControl(); + ConversationHandler::getInstance()->enforceFloodControl(false); if (isset($_REQUEST['userID'])) { $userID = \intval($_REQUEST['userID']); @@ -300,6 +300,7 @@ class ConversationAddForm extends MessageForm MessageQuoteManager::getInstance()->saved(); FloodControl::getInstance()->registerContent('com.woltlab.wcf.conversation'); + FloodControl::getInstance()->registerContent('com.woltlab.wcf.conversation.message'); $this->saved(); diff --git a/files/lib/system/conversation/ConversationHandler.class.php b/files/lib/system/conversation/ConversationHandler.class.php index 82ae57d..3490d20 100644 --- a/files/lib/system/conversation/ConversationHandler.class.php +++ b/files/lib/system/conversation/ConversationHandler.class.php @@ -150,24 +150,44 @@ class ConversationHandler extends SingletonFactory /** * Enforces the flood control. */ - public function enforceFloodControl() - { - $limit = WCF::getSession()->getPermission('user.conversation.maxStartedConversationsPer24Hours'); - if ($limit == -1) { - return; - } elseif ($limit == 0) { - // `0` is not a valid value, but the interface logic does not permit and exclusion - // while also allowing the special value `-1`. Therefore, `0` behaves like the - // 'canStartConversation' permission added in WoltLab Suite 5.2. - throw new PermissionDeniedException(); + public function enforceFloodControl( + bool $isReply = false + ) { + if (!$isReply) { + // 1. Check for the maximum conversations per 24 hours. + $limit = WCF::getSession()->getPermission('user.conversation.maxStartedConversationsPer24Hours'); + if ($limit == 0) { + // `0` is not a valid value, but the interface logic does not permit and exclusion + // while also allowing the special value `-1`. Therefore, `0` behaves like the + // 'canStartConversation' permission added in WoltLab Suite 5.2. + throw new PermissionDeniedException(); + } + + if ($limit != -1) { + $count = FloodControl::getInstance()->countContent('com.woltlab.wcf.conversation', new \DateInterval('P1D')); + if ($count['count'] >= $limit) { + throw new NamedUserException(WCF::getLanguage()->getDynamicVariable( + 'wcf.conversation.error.floodControl', + [ + 'limit' => $count['count'], + 'notBefore' => $count['earliestTime'] + 86400, + ] + )); + } + } } - $count = FloodControl::getInstance()->countContent('com.woltlab.wcf.conversation', new \DateInterval('P1D')); - if ($count['count'] >= $limit) { - throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.error.floodControl', [ - 'limit' => $count['count'], - 'notBefore' => $count['earliestTime'] + 86400, - ])); + // 2. Check the time between conversation messages. + $floodControlTime = WCF::getSession()->getPermission('user.conversation.floodControlTime'); + $lastTime = FloodControl::getInstance()->getLastTime('com.woltlab.wcf.conversation.message'); + if ($lastTime !== null && $lastTime > TIME_NOW - $floodControlTime) { + throw new NamedUserException(WCF::getLanguage()->getDynamicVariable( + 'wcf.conversation.message.error.floodControl', + [ + 'lastMessageTime' => $lastTime, + 'waitTime' => $lastTime + $floodControlTime - TIME_NOW, + ] + )); } } } diff --git a/language/de.xml b/language/de.xml index 3921007..ee510a3 100644 --- a/language/de.xml +++ b/language/de.xml @@ -142,6 +142,7 @@ {@$notBefore|time}, bevor {if LANGUAGE_USE_INFORMAL_VARIANT}du{else}Sie{/if} eine neue Konversation {if LANGUAGE_USE_INFORMAL_VARIANT}startest{else}starten{/if}.]]> + getSession()->getPermission('user.conversation.floodControlTime') 1='Sekunde' other='# Sekunden'} versendet. {if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst{else}Sie können{/if} erst in {plural value=$waitTime 1='Sekunde' other='# Sekunden'} eine neue Nachricht verfassen.]]> diff --git a/language/en.xml b/language/en.xml index 0048a0d..e22804e 100644 --- a/language/en.xml +++ b/language/en.xml @@ -142,6 +142,7 @@ {@$notBefore|time} before you start a new conversation.]]> + getSession()->getPermission('user.conversation.floodControlTime') 1='second' other='# seconds'}. You must wait at least {plural value=$waitTime 1='second' other='# seconds'} before attempting to write a new message.]]> -- 2.20.1