*/
#include "inspircd.h"
-#include "users.h"
-#include "modules.h"
#include "inspstring.h"
-#include "mode.h"
/* +s (secret) */
#include "modes/cmode_s.h"
void ModeHandler::ChangeCount(int modifier)
{
count += modifier;
+ ServerInstance->Log(DEBUG,"Change count for mode %c is now %d", mode, count);
}
ModeType ModeHandler::GetModeType()
{
}
+void ModeHandler::DisplayEmptyList(userrec* user, chanrec* channel)
+{
+}
+
bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, chanrec* channel)
{
return (ours < theirs);
}
else if (targetuser)
{
- if ((targetuser == user) || (*user->oper))
+ if (targetuser->Visibility && !targetuser->Visibility->VisibleTo(user))
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, text);
+ return;
+ }
+
+ if ((targetuser == user) || (IS_OPER(user)))
{
/* Display user's current mode string */
user->WriteServ("221 %s :+%s",targetuser->nick,targetuser->FormatModes());
- if (*targetuser->oper)
+ if (IS_OPER(targetuser))
user->WriteServ("008 %s +%s :Server notice mask", targetuser->nick, targetuser->FormatNoticeMasks());
return;
}
chanrec* targetchannel = ServerInstance->FindChan(parameters[0]);
userrec* targetuser = ServerInstance->FindNick(parameters[0]);
- LastParse = "";
+ LastParse.clear();
/* Special case for displaying the list for listmodes,
* e.g. MODE #chan b, or MODE #chan +b without a parameter
{
const char* mode = parameters[1];
int nonlistmodes_found = 0;
+ bool sent[256];
mask = MASK_CHANNEL;
+
+ memset(&sent, 0, 256);
while (mode && *mode)
{
+ unsigned char mletter = *mode;
+
if (*mode == '+')
{
mode++;
continue;
}
+ /* Ensure the user doesnt request the same mode twice,
+ * so they cant flood themselves off out of idiocy.
+ */
+ if (!sent[mletter])
+ {
+ sent[mletter] = true;
+ }
+ else
+ {
+ mode++;
+ continue;
+ }
+
ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL);
bool display = true;
if ((mh) && (mh->IsListMode()))
{
+ if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
+ {
+ user->WriteServ("482 %s %s :Only half-operators and above may view the +%c list",user->nick, targetchannel->name, *mode++);
+ mh->DisplayEmptyList(user, targetchannel);
+ continue;
+ }
+
/** See below for a description of what craq this is :D
*/
unsigned char handler_id = (*mode - 65) | mask;
}
std::string mode_sequence = parameters[1];
- std::string parameter = "";
+ std::string parameter;
std::ostringstream parameter_list;
- std::string output_sequence = "";
+ std::string output_sequence;
bool adding = true, state_change = false;
unsigned char handler_id = 0;
int parameter_counter = 2; /* Index of first parameter */
/* Yerk, invalid! */
if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
- parameter = "";
+ parameter.clear();
}
else
{
if (abort)
continue;
}
+ else
+ {
+ /* Fix by brain: mode watchers not being called for parameterless modes */
+ for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
+ {
+ if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
+ {
+ abort = true;
+ break;
+ }
+ }
+
+ if (abort)
+ continue;
+ }
/* It's an oper only mode, check if theyre an oper. If they arent,
* eat any parameter that came with the mode, and continue to next
*/
- if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!*user->oper))
+ if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user)))
{
- user->WriteServ("481 %s :Permission Denied- Only IRC operators may %sset %s mode %c", user->nick,
+ user->WriteServ("481 %s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick,
adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
modehandlers[handler_id]->GetModeChar());
continue;
/* Call the handler for the mode */
ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
- if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter == ""))
+ if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
{
/* The handler nuked the parameter and they are supposed to have one.
* We CANT continue now, even if they actually returned MODEACTION_ALLOW,
/* Add the mode letter */
output_sequence.push_back(modechar);
+ modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
+
/* Is there a valid parameter for this mode? If so add it to the parameter list */
- if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter != ""))
+ if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
{
parameter_list << " " << parameter;
parameter_count++;
break;
}
}
+
/* Was there at least one valid mode in the sequence? */
- if (output_sequence != "")
+ if (!output_sequence.empty())
{
if (servermode)
{
* If they do that, thats their problem, and if i ever EVER see an
* official InspIRCd developer do that, i'll beat them with a paddle!
*/
- if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
+ if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126))
return false;
/* A mode prefix of ',' is not acceptable, it would fuck up server to server.
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
+ if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
+ continue;
+
unsigned char pos = (mode-65) | MASK_CHANNEL;
if (modehandlers[pos])
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
+ if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
+ continue;
+
unsigned char pos = (mode-65) | MASK_CHANNEL;
if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
+ if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
+ continue;
+
unsigned char pos = (mode-65) | MASK_CHANNEL;
/* One parameter when adding */
if (modehandlers[pos])
return type1 + "," + type2 + "," + type3 + "," + type4;
}
-bool ModeParser::PrefixComparison(const prefixtype one, const prefixtype two)
+bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
{
return one.second > two.second;
}
std::string ModeParser::BuildPrefixes()
{
- std::string mletters = "";
- std::string mprefixes = "";
+ std::string mletters;
+ std::string mprefixes;
pfxcontainer pfx;
std::map<char,char> prefix_to_mode;
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
+ if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
+ continue;
+
unsigned char pos = (mode-65) | MASK_CHANNEL;
if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
pos = (mw->GetModeChar()-65) | mask;
modewatchers[pos].push_back(mw);
+
return true;
}
if (channel->IsModeSet(this->GetModeChar()))
{
- userrec* n = new userrec(ServerInstance);
-
sprintf(moderemove,"-%c",this->GetModeChar());
- n->SetFd(FD_MAGIC_NUMBER);
-
- ServerInstance->SendMode(parameters, 2, n);
-
- delete n;
+ ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
}
}
ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
{
+ struct Initializer
+ {
+ char modechar;
+ ModeHandler* handler;
+ };
+
+ Initializer modes[] = {
+ { 's', new ModeChannelSecret(Instance) },
+ { 'p', new ModeChannelPrivate(Instance) },
+ { 'm', new ModeChannelModerated(Instance) },
+ { 't', new ModeChannelTopicOps(Instance) },
+ { 'n', new ModeChannelNoExternal(Instance) },
+ { 'i', new ModeChannelInviteOnly(Instance) },
+ { 'k', new ModeChannelKey(Instance) },
+ { 'l', new ModeChannelLimit(Instance) },
+ { 'b', new ModeChannelBan(Instance) },
+ { 'o', new ModeChannelOp(Instance) },
+ { 'h', new ModeChannelHalfOp(Instance) },
+ { 'v', new ModeChannelVoice(Instance) },
+ { 's', new ModeUserServerNotice(Instance) },
+ { 'w', new ModeUserWallops(Instance) },
+ { 'i', new ModeUserInvisible(Instance) },
+ { 'o', new ModeUserOperator(Instance) },
+ { 'n', new ModeUserServerNoticeMask(Instance) },
+ { 0, NULL }
+ };
+
/* Clear mode list */
memset(modehandlers, 0, sizeof(modehandlers));
memset(modewatchers, 0, sizeof(modewatchers));
/* Last parse string */
- LastParse = "";
+ LastParse.clear();
/* Initialise the RFC mode letters */
-
- /* Start with channel simple modes, no params */
- this->AddMode(new ModeChannelSecret(Instance), 's');
- this->AddMode(new ModeChannelPrivate(Instance), 'p');
- this->AddMode(new ModeChannelModerated(Instance), 'm');
- this->AddMode(new ModeChannelTopicOps(Instance), 't');
- this->AddMode(new ModeChannelNoExternal(Instance), 'n');
- this->AddMode(new ModeChannelInviteOnly(Instance), 'i');
-
- /* Cannel modes with params */
- this->AddMode(new ModeChannelKey(Instance), 'k');
- this->AddMode(new ModeChannelLimit(Instance), 'l');
-
- /* Channel listmodes */
- this->AddMode(new ModeChannelBan(Instance), 'b');
- this->AddMode(new ModeChannelOp(Instance), 'o');
- this->AddMode(new ModeChannelHalfOp(Instance), 'h');
- this->AddMode(new ModeChannelVoice(Instance), 'v');
-
- /* Now for usermodes */
- this->AddMode(new ModeUserServerNotice(Instance), 's');
- this->AddMode(new ModeUserWallops(Instance), 'w');
- this->AddMode(new ModeUserInvisible(Instance), 'i');
- this->AddMode(new ModeUserOperator(Instance), 'o');
- this->AddMode(new ModeUserServerNoticeMask(Instance), 'n');
+ for (int index = 0; modes[index].modechar; index++)
+ this->AddMode(modes[index].handler, modes[index].modechar);
}