summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/conf/modules.conf.example21
-rw-r--r--src/modules/m_blockcaps.cpp63
2 files changed, 60 insertions, 24 deletions
diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example
index eb6bfd475..65bb3b9cb 100644
--- a/docs/conf/modules.conf.example
+++ b/docs/conf/modules.conf.example
@@ -245,19 +245,22 @@
#
#-#-#-#-#-#-#-#-#-#-#- BLOCKCAPS CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#
# #
-# percent - What percentage of the text must be caps before #
-# text will be blocked. #
+# percent - The percentage of a message which must be upper #
+# case before it will be blocked. #
# #
-# minlen - The minimum length a line must be for the block #
-# percent to have any effect. #
+# minlen - The minimum length a message must be before it #
+# will be blocked. #
# #
-# capsmap - A list of chars to be considered CAPS. Can be used #
-# to add CAPS characters for your language. Also you #
-# can add things like ! and space to further lock #
-# down on caps usage. #
+# lowercase - The characters which will be considered lower #
+# case. #
+# #
+# uppercase - The characters which will be considered upper #
+# case. #
+#
#<blockcaps percent="50"
# minlen="5"
-# capsmap="ABCDEFGHIJKLMNOPQRSTUVWXYZ! ">
+# lowercase="abcdefghijklmnopqrstuvwxyz"
+# uppercase="ABCDEFGHIJKLMNOPQRSTUVWXYZ">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Block color module: Blocking color-coded messages with chan mode +c.
diff --git a/src/modules/m_blockcaps.cpp b/src/modules/m_blockcaps.cpp
index b5347e9ad..c36eeabff 100644
--- a/src/modules/m_blockcaps.cpp
+++ b/src/modules/m_blockcaps.cpp
@@ -29,7 +29,8 @@ class ModuleBlockCAPS : public Module
SimpleChannelModeHandler bc;
unsigned int percent;
unsigned int minlen;
- std::bitset<UCHAR_MAX> capsmap;
+ std::bitset<UCHAR_MAX> lowercase;
+ std::bitset<UCHAR_MAX> uppercase;
public:
ModuleBlockCAPS()
@@ -47,7 +48,7 @@ public:
{
if (target_type == TYPE_CHANNEL)
{
- if ((!IS_LOCAL(user)) || (text.length() < minlen) || (text == "\1ACTION\1") || (text == "\1ACTION"))
+ if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
Channel* c = (Channel*)dest;
@@ -58,17 +59,43 @@ public:
if (!c->GetExtBanStatus(user, 'B').check(!c->IsModeSet(bc)))
{
- std::string::size_type caps = 0;
- unsigned int offset = 0;
- // Ignore the beginning of the text if it's a CTCP ACTION (/me)
- if (!text.compare(0, 8, "\1ACTION ", 8))
- offset = 8;
+ // If the message is a CTCP then we skip it unless it is
+ // an ACTION in which case we strip the prefix and suffix.
+ std::string::const_iterator text_begin = text.begin();
+ std::string::const_iterator text_end = text.end();
+ if (text[0] == '\1')
+ {
+ // If the CTCP is not an action then skip it.
+ if (text.compare(0, 8, "\1ACTION ", 8))
+ return MOD_RES_PASSTHRU;
+
+ // Skip the CTCP message characters.
+ text_begin += 8;
+ if (*text.rbegin() == '\1')
+ text_end -= 1;
+ }
+
+ // If the message is shorter than the minimum length
+ // then we don't need to do anything else.
+ size_t length = std::distance(text_begin, text_end);
+ if (length < minlen)
+ return MOD_RES_PASSTHRU;
- for (std::string::const_iterator i = text.begin() + offset; i != text.end(); ++i)
- if (capsmap.test(*i))
- caps += 1;
+ // Count the characters to see how many upper case and
+ // ignored (non upper or lower) characters there are.
+ size_t upper = 0;
+ for (std::string::const_iterator iter = text_begin; iter != text_end; ++iter)
+ {
+ if (uppercase.test(*iter))
+ upper += 1;
+ else if (!lowercase.test(*iter))
+ length -= 1;
+ }
- if (((caps * 100) / text.length()) >= percent)
+ // Calculate the percentage which is upper case. If the
+ // message was entirely symbols then it can't contain
+ // any upper case letters.
+ if (length > 0 && round((upper * 100) / length) >= percent)
{
user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, InspIRCd::Format("Your message cannot contain %d%% or more capital letters if it's longer than %d characters", percent, minlen));
return MOD_RES_DENY;
@@ -83,10 +110,16 @@ public:
ConfigTag* tag = ServerInstance->Config->ConfValue("blockcaps");
percent = tag->getInt("percent", 100, 1, 100);
minlen = tag->getInt("minlen", 1, 1, ServerInstance->Config->Limits.MaxLine);
- std::string hmap = tag->getString("capsmap", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- capsmap.reset();
- for (std::string::iterator n = hmap.begin(); n != hmap.end(); n++)
- capsmap.set(*n);
+
+ lowercase.reset();
+ const std::string lower = tag->getString("lowercase", "abcdefghijklmnopqrstuvwxyz");
+ for (std::string::const_iterator iter = lower.begin(); iter != lower.end(); ++iter)
+ lowercase.set(*iter);
+
+ uppercase.reset();
+ const std::string upper = tag->getString("uppercase", tag->getString("capsmap", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+ for (std::string::const_iterator iter = upper.begin(); iter != upper.end(); ++iter)
+ uppercase.set(*iter);
}
Version GetVersion() CXX11_OVERRIDE