summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorattilamolnar <attilamolnar@hush.com>2013-07-20 20:59:48 +0200
committerattilamolnar <attilamolnar@hush.com>2013-07-24 18:10:34 +0200
commit1a775c11c27c3b786c6850d8a9efeaf8d9c1d2c0 (patch)
treefba58774f678e3c5d5599d76fc37326510f2e59d
parentc265641c0a9a9b0a4686e1ea313876c16b4700ad (diff)
umode_s Rewrite ProcessNoticeMasks() and remove a few related useless functions
-rw-r--r--include/builtinmodes.h22
-rw-r--r--src/modes/umode_s.cpp132
2 files changed, 63 insertions, 91 deletions
diff --git a/include/builtinmodes.h b/include/builtinmodes.h
index 31b208d52..b1e5c3ccd 100644
--- a/include/builtinmodes.h
+++ b/include/builtinmodes.h
@@ -150,32 +150,24 @@ class ModeUserInvisible : public SimpleUserModeHandler
*/
class ModeUserServerNoticeMask : public ModeHandler
{
- /** Create a displayable mode string for this users snomasks
- * @param user The user whose notice masks to format
- * @return The notice mask character sequence
- */
- std::string FormatNoticeMasks(User* user);
-
/** Process a snomask modifier string, e.g. +abc-de
* @param user The target user
- * @param sm A sequence of notice mask characters
+ * @param input A sequence of notice mask characters
* @return The cleaned mode sequence which can be output,
* e.g. in the above example if masks c and e are not
* valid, this function will return +ab-d
*/
- std::string ProcessNoticeMasks(User* user, const char *sm);
-
- /** Changed a specific notice mask value
- * @param user The target user
- * @param sm The server notice mask to change
- * @param value An on/off value for this mask
- */
- void SetNoticeMask(User* user, unsigned char sm, bool value);
+ std::string ProcessNoticeMasks(User* user, const std::string& input);
public:
ModeUserServerNoticeMask();
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
void OnParameterMissing(User* user, User* dest, Channel* channel);
+
+ /** Create a displayable mode string of the snomasks set on a given user
+ * @param user The user whose notice masks to format
+ * @return The notice mask character sequence
+ */
std::string GetUserParameter(User* user);
};
diff --git a/src/modes/umode_s.cpp b/src/modes/umode_s.cpp
index 2650a31bc..d06ef64cb 100644
--- a/src/modes/umode_s.cpp
+++ b/src/modes/umode_s.cpp
@@ -32,15 +32,11 @@ ModeUserServerNoticeMask::ModeUserServerNoticeMask() : ModeHandler(NULL, "snomas
ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Channel*, std::string &parameter, bool adding)
{
- /* Set the array fields */
if (adding)
{
- /* Fix for bug #310 reported by Smartys */
- if (!dest->IsModeSet(this))
- dest->snomasks.reset();
-
dest->SetMode(this, true);
- parameter = ProcessNoticeMasks(dest, parameter.c_str());
+ // Process the parameter (remove chars we don't understand, remove redundant chars, etc.)
+ parameter = ProcessNoticeMasks(dest, parameter);
return MODEACTION_ALLOW;
}
else
@@ -48,20 +44,28 @@ ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Chan
if (dest->IsModeSet(this))
{
dest->SetMode(this, false);
+ dest->snomasks.reset();
return MODEACTION_ALLOW;
}
}
- /* Allow the change */
+ // Mode not set and trying to unset, deny
return MODEACTION_DENY;
}
std::string ModeUserServerNoticeMask::GetUserParameter(User* user)
{
- std::string masks = FormatNoticeMasks(user);
- if (masks.length())
- masks = "+" + masks;
- return masks;
+ std::string ret;
+ if (!user->IsModeSet(this))
+ return ret;
+
+ ret.push_back('+');
+ for (unsigned char n = 0; n < 64; n++)
+ {
+ if (user->snomasks[n])
+ ret.push_back(n + 'A');
+ }
+ return ret;
}
void ModeUserServerNoticeMask::OnParameterMissing(User* user, User* dest, Channel* channel)
@@ -69,15 +73,14 @@ void ModeUserServerNoticeMask::OnParameterMissing(User* user, User* dest, Channe
user->WriteNotice("*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'.");
}
-std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const char *sm)
+std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const std::string& input)
{
- bool adding = true, oldadding = false;
- const char *c = sm;
- std::string output;
+ bool adding = true;
+ std::bitset<64> curr = user->snomasks;
- while (c && *c)
+ for (std::string::const_iterator i = input.begin(); i != input.end(); ++i)
{
- switch (*c)
+ switch (*i)
{
case '+':
adding = true;
@@ -86,82 +89,59 @@ std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const char
adding = false;
break;
case '*':
- for (unsigned char d = 'a'; d <= 'z'; d++)
+ for (size_t j = 0; j < 64; j++)
{
- if (!ServerInstance->SNO->masks[d - 'a'].Description.empty())
- {
- if ((!user->IsNoticeMaskSet(d) && adding) || (user->IsNoticeMaskSet(d) && !adding))
- {
- if ((oldadding != adding) || (!output.length()))
- output += (adding ? '+' : '-');
-
- SetNoticeMask(user, d, adding);
-
- output += d;
- }
- oldadding = adding;
- char u = toupper(d);
- if ((!user->IsNoticeMaskSet(u) && adding) || (user->IsNoticeMaskSet(u) && !adding))
- {
- if ((oldadding != adding) || (!output.length()))
- output += (adding ? '+' : '-');
-
- SetNoticeMask(user, u, adding);
-
- output += u;
- }
- oldadding = adding;
- }
+ if (ServerInstance->SNO->IsSnomaskUsable(j+'A'))
+ curr[j] = adding;
}
break;
default:
- if (isalpha(*c))
+ // For local users check whether the given snomask is valid and enabled - IsSnomaskUsable() tests both.
+ // For remote users accept what we were told, unless the snomask char is not a letter.
+ if (IS_LOCAL(user))
{
- if ((!user->IsNoticeMaskSet(*c) && adding) || (user->IsNoticeMaskSet(*c) && !adding))
+ if (!ServerInstance->SNO->IsSnomaskUsable(*i))
{
- if ((oldadding != adding) || (!output.length()))
- output += (adding ? '+' : '-');
-
- SetNoticeMask(user, *c, adding);
-
- output += *c;
+ user->WriteNumeric(ERR_UNKNOWNSNOMASK, "%s %c :is unknown snomask char to me", user->nick.c_str(), *i);
+ continue;
}
}
- else
- user->WriteNumeric(ERR_UNKNOWNSNOMASK, "%s %c :is unknown snomask char to me", user->nick.c_str(), *c);
+ else if (!(((*i >= 'a') && (*i <= 'z')) || ((*i >= 'A') && (*i <= 'Z'))))
+ continue;
- oldadding = adding;
+ size_t index = ((*i) - 'A');
+ curr[index] = adding;
break;
}
-
- c++;
}
- std::string s = this->FormatNoticeMasks(user);
- if (s.length() == 0)
+ std::string plus = "+";
+ std::string minus = "-";
+
+ // Apply changes and construct two strings consisting of the newly added and the removed snomask chars
+ for (size_t i = 0; i < 64; i++)
{
- user->SetMode(this, false);
+ bool isset = curr[i];
+ if (user->snomasks[i] != isset)
+ {
+ user->snomasks[i] = isset;
+ std::string& appendhere = (isset ? plus : minus);
+ appendhere.push_back(i+'A');
+ }
}
- return output;
-}
+ // Create the final string that will be shown to the user and sent to servers
+ // Form: "+ABc-de"
+ std::string output;
+ if (plus.length() > 1)
+ output = plus;
-std::string ModeUserServerNoticeMask::FormatNoticeMasks(User* user)
-{
- std::string data;
+ if (minus.length() > 1)
+ output += minus;
- for (unsigned char n = 0; n < 64; n++)
- {
- if (user->snomasks[n])
- data.push_back(n + 65);
- }
-
- return data;
-}
+ // Unset the snomask usermode itself if every snomask was unset
+ if (user->snomasks.none())
+ user->SetMode(this, false);
-void ModeUserServerNoticeMask::SetNoticeMask(User* user, unsigned char sm, bool value)
-{
- if (!isalpha(sm))
- return;
- user->snomasks[sm-65] = value;
+ return output;
}