diff options
Diffstat (limited to 'src/modes')
-rw-r--r-- | src/modes/umode_s.cpp | 101 |
1 files changed, 99 insertions, 2 deletions
diff --git a/src/modes/umode_s.cpp b/src/modes/umode_s.cpp index f5631c695..2650a31bc 100644 --- a/src/modes/umode_s.cpp +++ b/src/modes/umode_s.cpp @@ -40,7 +40,7 @@ ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Chan dest->snomasks.reset(); dest->SetMode(this, true); - parameter = dest->ProcessNoticeMasks(parameter.c_str()); + parameter = ProcessNoticeMasks(dest, parameter.c_str()); return MODEACTION_ALLOW; } else @@ -58,7 +58,7 @@ ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Chan std::string ModeUserServerNoticeMask::GetUserParameter(User* user) { - std::string masks = user->FormatNoticeMasks(); + std::string masks = FormatNoticeMasks(user); if (masks.length()) masks = "+" + masks; return masks; @@ -68,3 +68,100 @@ 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) +{ + bool adding = true, oldadding = false; + const char *c = sm; + std::string output; + + while (c && *c) + { + switch (*c) + { + case '+': + adding = true; + break; + case '-': + adding = false; + break; + case '*': + for (unsigned char d = 'a'; d <= 'z'; d++) + { + 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; + } + } + break; + default: + if (isalpha(*c)) + { + if ((!user->IsNoticeMaskSet(*c) && adding) || (user->IsNoticeMaskSet(*c) && !adding)) + { + if ((oldadding != adding) || (!output.length())) + output += (adding ? '+' : '-'); + + SetNoticeMask(user, *c, adding); + + output += *c; + } + } + else + user->WriteNumeric(ERR_UNKNOWNSNOMASK, "%s %c :is unknown snomask char to me", user->nick.c_str(), *c); + + oldadding = adding; + break; + } + + c++; + } + + std::string s = this->FormatNoticeMasks(user); + if (s.length() == 0) + { + user->SetMode(this, false); + } + + return output; +} + +std::string ModeUserServerNoticeMask::FormatNoticeMasks(User* user) +{ + std::string data; + + for (unsigned char n = 0; n < 64; n++) + { + if (user->snomasks[n]) + data.push_back(n + 65); + } + + return data; +} + +void ModeUserServerNoticeMask::SetNoticeMask(User* user, unsigned char sm, bool value) +{ + if (!isalpha(sm)) + return; + user->snomasks[sm-65] = value; +} |