X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmode.cpp;h=3842b01e6ea02301b5d3b86e2221d89948dd1409;hb=84a19a9ab6129deb71cdc24b216b74dd8eb80978;hp=1b59a1352f71f9103841bd50757b57bee372ac95;hpb=9ec715957b95578172c136e6706e58e873956689;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/mode.cpp b/src/mode.cpp index 1b59a1352..3842b01e6 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -3,7 +3,7 @@ * +------------------------------------+ * * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev. - * E-mail: + * E-mail: * * * @@ -18,7 +18,7 @@ using namespace std; #include "inspircd_config.h" #include "inspircd.h" -#include "inspircd_io.h" +#include "configreader.h" #include #include #include @@ -54,6 +54,80 @@ extern ServerConfig* Config; extern time_t TIME; +ModeHandler::ModeHandler(char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly) : mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly) +{ +} + +ModeHandler::~ModeHandler() +{ +} + +bool ModeHandler::IsListMode() +{ + return list; +} + +ModeType ModeHandler::GetModeType() +{ + return m_type; +} + +bool ModeHandler::NeedsOper() +{ + return oper; +} + +int ModeHandler::GetNumParams(bool adding) +{ + return adding ? n_params_on : n_params_off; +} + +char ModeHandler::GetModeChar() +{ + return mode; +} + +ModeAction ModeHandler::OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding) +{ + return MODEACTION_DENY; +} + +void ModeHandler::DisplayList(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); +} + +ModeWatcher::ModeWatcher(char modeletter, ModeType type) : mode(modeletter), m_type(type) +{ +} + +ModeWatcher::~ModeWatcher() +{ +} + +char ModeWatcher::GetModeChar() +{ + return mode; +} + +ModeType ModeWatcher::GetModeType() +{ + return m_type; +} + +bool ModeWatcher::BeforeMode(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding, ModeType type) +{ + return true; +} + +void ModeWatcher::AfterMode(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter, bool adding, ModeType type) +{ +} + userrec* ModeParser::SanityChecks(userrec *user,char *dest,chanrec *chan,int status) { userrec *d; @@ -72,29 +146,31 @@ userrec* ModeParser::SanityChecks(userrec *user,char *dest,chanrec *chan,int sta char* ModeParser::Grant(userrec *d,chanrec *chan,int MASK) { - for (unsigned int i = 0; i < d->chans.size(); i++) + if (!chan) + return NULL; + + for (std::vector::const_iterator i = d->chans.begin(); i != d->chans.end(); i++) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (d->chans[i].channel == chan) + if (((ucrec*)(*i))->channel == chan) { - if (d->chans[i].uc_modes & MASK) + if (((ucrec*)(*i))->uc_modes & MASK) { return NULL; } - d->chans[i].uc_modes = d->chans[i].uc_modes | MASK; + ((ucrec*)(*i))->uc_modes = ((ucrec*)(*i))->uc_modes | MASK; switch (MASK) { case UCMODE_OP: - d->chans[i].channel->AddOppedUser((char*)d); + ((ucrec*)(*i))->channel->AddOppedUser(d); break; case UCMODE_HOP: - d->chans[i].channel->AddHalfoppedUser((char*)d); + ((ucrec*)(*i))->channel->AddHalfoppedUser(d); break; case UCMODE_VOICE: - d->chans[i].channel->AddVoicedUser((char*)d); + ((ucrec*)(*i))->channel->AddVoicedUser(d); break; } - log(DEBUG,"grant: %s %s",d->chans[i].channel->name,d->nick); + log(DEBUG,"grant: %s %s",((ucrec*)(*i))->channel->name,d->nick); return d->nick; } } @@ -103,29 +179,31 @@ char* ModeParser::Grant(userrec *d,chanrec *chan,int MASK) char* ModeParser::Revoke(userrec *d,chanrec *chan,int MASK) { - for (unsigned int i = 0; i < d->chans.size(); i++) + if (!chan) + return NULL; + + for (std::vector::const_iterator i = d->chans.begin(); i != d->chans.end(); i++) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (d->chans[i].channel == chan) + if (((ucrec*)(*i))->channel == chan) { - if ((d->chans[i].uc_modes & MASK) == 0) + if ((((ucrec*)(*i))->uc_modes & MASK) == 0) { return NULL; } - d->chans[i].uc_modes ^= MASK; + ((ucrec*)(*i))->uc_modes ^= MASK; switch (MASK) { case UCMODE_OP: - d->chans[i].channel->DelOppedUser((char*)d); + ((ucrec*)(*i))->channel->DelOppedUser(d); break; case UCMODE_HOP: - d->chans[i].channel->DelHalfoppedUser((char*)d); + ((ucrec*)(*i))->channel->DelHalfoppedUser(d); break; case UCMODE_VOICE: - d->chans[i].channel->DelVoicedUser((char*)d); + ((ucrec*)(*i))->channel->DelVoicedUser(d); break; } - log(DEBUG,"revoke: %s %s",d->chans[i].channel->name,d->nick); + log(DEBUG,"revoke: %s %s",((ucrec*)(*i))->channel->name,d->nick); return d->nick; } } @@ -386,10 +464,10 @@ char* ModeParser::TakeBan(userrec *user,char *dest,chanrec *chan,int status) { if (!strcasecmp(i->data,dest)) { - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnDelBan,OnDelBan(user,chan,dest)); - if (MOD_RESULT) - return NULL; + int MOD_RESULT = 0; + FOREACH_RESULT(I_OnDelBan,OnDelBan(user,chan,dest)); + if (MOD_RESULT) + return NULL; chan->bans.erase(i); return dest; } @@ -397,53 +475,143 @@ char* ModeParser::TakeBan(userrec *user,char *dest,chanrec *chan,int status) return NULL; } -// tidies up redundant modes, e.g. +nt-nt+i becomes +-+i, -// a section further down the chain tidies up the +-+- crap. -std::string ModeParser::CompressModes(std::string modes,bool channelmodes) +void ModeParser::Process(char **parameters, int pcnt, userrec *user, bool servermode) { - int counts[127]; - bool active[127]; - memset(counts,0,sizeof(counts)); - memset(active,0,sizeof(active)); - for (unsigned int i = 0; i < modes.length(); i++) + std::string target = parameters[0]; + ModeType type = MODETYPE_USER; + chanrec* targetchannel = FindChan(parameters[0]); + userrec* targetuser = Find(parameters[0]); + + if (pcnt > 1) { - if ((modes[i] == '+') || (modes[i] == '-')) - continue; - if (channelmodes) + if (targetchannel) { - if ((strchr("itnmsp",modes[i])) || ((ModeDefined(modes[i],MT_CHANNEL)) && (ModeDefinedOn(modes[i],MT_CHANNEL)==0) && (ModeDefinedOff(modes[i],MT_CHANNEL)==0))) - { - log(DEBUG,"Tidy mode %c",modes[i]); - counts[(unsigned int)modes[i]]++; - active[(unsigned int)modes[i]] = true; - } + type = MODETYPE_CHANNEL; + } + else if (targetuser) + { + type = MODETYPE_USER; } else { - log(DEBUG,"Tidy mode %c",modes[i]); - counts[(unsigned int)modes[i]]++; - active[(unsigned int)modes[i]] = true; + /* No such nick/channel */ + return; } - } - for (int j = 65; j < 127; j++) - { - if ((counts[j] > 1) && (active[j] == true)) + std::string mode_sequence = parameters[1]; + std::string parameter = ""; + std::ostringstream parameter_list; + std::string output_sequence = ""; + bool adding = true, state_change = false; + int handler_id = 0; + int parameter_counter = 2; /* Index of first parameter */ + + for (std::string::const_iterator modeletter = mode_sequence.begin(); modeletter != mode_sequence.end(); modeletter++) + { + switch (*modeletter) + { + /* NB: + * For + and - mode characters, we don't just stick the character into the output sequence. + * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this + * appearing in the output sequence, we store a flag which says there was a state change, + * which is set on any + or -, however, the + or - that we finish on is only appended to + * the output stream in the event it is followed by a non "+ or -" character, such as o or v. + */ + case '+': + /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick, + * however, will allow the + if it is the first item in the sequence, regardless. + */ + if ((!adding) || (!output_sequence.length())) + state_change = true; + adding = true; + continue; + break; + case '-': + if ((adding) || (!output_sequence.length())) + state_change = true; + adding = false; + continue; + break; + default: + + /* 65 is the ascii value of 'A' */ + handler_id = *modeletter - 65; + + if (modehandlers[handler_id]) + { + bool abort = false; + for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) + { + if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == MODEACTION_DENY) + abort = true; + } + if ((modehandlers[handler_id]->GetModeType() == type) && (!abort)) + { + if (modehandlers[handler_id]->GetNumParams(adding)) + { + if (pcnt < parameter_counter) + { + parameter = parameters[parameter_counter++]; + } + else + { + parameter = ""; + } + } + ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding); + if (ma == MODEACTION_ALLOW) + { + /* We're about to output a valid mode letter - was there previously a pending state-change? */ + if (state_change) + output_sequence.append(adding ? "+" : "-"); + + /* Add the mode letter */ + output_sequence = output_sequence + *modeletter; + + /* Is there a valid parameter for this mode? If so add it to the parameter list */ + if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter != "")) + { + parameter_list << " " << parameter; + } + + /* Call all the AfterMode events in the mode watchers for this mode */ + for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) + { + (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type); + } + + /* Reset the state change flag */ + state_change = false; + } + } + } + break; + } + } + /* Was there at least one valid mode in the sequence? */ + if (output_sequence != "") { - static char v[2]; - v[0] = (unsigned char)j; - v[1] = '\0'; - std::string mode_str = v; - std::string::size_type pos = modes.find(mode_str); - if (pos != std::string::npos) + if (servermode) + { + if (type == MODETYPE_CHANNEL) + { + WriteChannelWithServ(Config->ServerName,targetchannel,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str()); + } + } + else { - log(DEBUG,"all occurances of mode %c to be deleted...",(unsigned char)j); - while (modes.find(mode_str) != std::string::npos) - modes.erase(modes.find(mode_str),1); - log(DEBUG,"New mode line: %s",modes.c_str()); + if (type == MODETYPE_CHANNEL) + { + WriteChannel(targetchannel,user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str()); + FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str())); + } } } } - return modes; +} + +std::string ModeParser::CompressModes(std::string modes,bool channelmodes) +{ + return ""; } void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local) @@ -527,10 +695,10 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int } else { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'o', parameters[param], false, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'o', parameters[param], false, 1)); + if (!MOD_RESULT) + { r = TakeOps(user,parameters[param++],chan,status); } else param++; @@ -547,20 +715,20 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int r = NULL; if (mdir == 1) { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], true, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], true, 1)); + if (!MOD_RESULT) + { r = GiveHops(user,parameters[param++],chan,status); } else param++; } else { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], false, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], false, 1)); + if (!MOD_RESULT) + { r = TakeHops(user,parameters[param++],chan,status); } else param++; @@ -578,20 +746,20 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int r = NULL; if (mdir == 1) { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], true, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], true, 1)); + if (!MOD_RESULT) + { r = GiveVoice(user,parameters[param++],chan,status); } else param++; } else { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], false, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], false, 1)); + if (!MOD_RESULT) + { r = TakeVoice(user,parameters[param++],chan,status); } else param++; @@ -608,20 +776,20 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int r = NULL; if (mdir == 1) { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], true, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], true, 1)); + if (!MOD_RESULT) + { r = AddBan(user,parameters[param++],chan,status); } else param++; } else { - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], false, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], false, 1)); + if (!MOD_RESULT) + { r = TakeBan(user,parameters[param++],chan,status); } else param++; @@ -647,7 +815,7 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int break; previously_set_k = true; - if (!*chan->key) + if (!chan->modes[CM_KEY]) { MOD_RESULT = 0; FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'k', parameters[param], true, 1)); @@ -658,6 +826,7 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int strlcpy(key,parameters[param++],32); outpars[pc++] = key; strlcpy(chan->key,key,MAXBUF); + chan->modes[CM_KEY] = 1; k_set = true; } else param++; @@ -682,6 +851,7 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int { *outl++ = 'k'; *chan->key = 0; + chan->modes[CM_KEY] = 0; outpars[pc++] = key; } } @@ -695,14 +865,15 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int if (previously_set_l) break; previously_unset_l = true; - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', "", false, 0)); - if (!MOD_RESULT) - { - if (chan->limit) + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', "", false, 0)); + if (!MOD_RESULT) + { + if (chan->modes[CM_LIMIT]) { *outl++ = 'l'; chan->limit = 0; + chan->modes[CM_LIMIT] = 0; } } } @@ -732,10 +903,10 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int if (invalid) break; - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', parameters[param], true, 1)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', parameters[param], true, 1)); + if (!MOD_RESULT) + { chan->limit = atoi(parameters[param]); @@ -747,6 +918,7 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int if (chan->limit) { *outl++ = 'l'; + chan->modes[CM_LIMIT] = 1; outpars[pc++] = parameters[param++]; l_set = true; } @@ -754,133 +926,138 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int break; case 'i': - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'i', "", mdir, 0)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'i', "", mdir, 0)); + if (!MOD_RESULT) + { if (mdir) { - if (!(chan->binarymodes & CM_INVITEONLY)) *outl++ = 'i'; - chan->binarymodes |= CM_INVITEONLY; + if (!(chan->modes[CM_INVITEONLY])) *outl++ = 'i'; + chan->modes[CM_INVITEONLY] = 1; } else { - if (chan->binarymodes & CM_INVITEONLY) *outl++ = 'i'; - chan->binarymodes &= ~CM_INVITEONLY; + if (chan->modes[CM_INVITEONLY]) *outl++ = 'i'; + chan->modes[CM_INVITEONLY] = 0; } } break; case 't': - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 't', "", mdir, 0)); - if (!MOD_RESULT) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 't', "", mdir, 0)); + if (!MOD_RESULT) + { if (mdir) - { - if (!(chan->binarymodes & CM_TOPICLOCK)) *outl++ = 't'; - chan->binarymodes |= CM_TOPICLOCK; - } - else - { - if (chan->binarymodes & CM_TOPICLOCK) *outl++ = 't'; - chan->binarymodes &= ~CM_TOPICLOCK; - } + { + if (!(chan->modes[CM_TOPICLOCK])) *outl++ = 't'; + chan->modes[CM_TOPICLOCK] = 1; + } + else + { + if (chan->modes[CM_TOPICLOCK]) *outl++ = 't'; + chan->modes[CM_TOPICLOCK] = 0; + } } break; case 'n': - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'n', "", mdir, 0)); - if (!MOD_RESULT) - { - if (mdir) - { - if (!(chan->binarymodes & CM_NOEXTERNAL)) *outl++ = 'n'; - chan->binarymodes |= CM_NOEXTERNAL; - } - else - { - if (chan->binarymodes & CM_NOEXTERNAL) *outl++ = 'n'; - chan->binarymodes &= ~CM_NOEXTERNAL; - } + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'n', "", mdir, 0)); + if (!MOD_RESULT) + { + if (mdir) + { + if (!(chan->modes[CM_NOEXTERNAL])) *outl++ = 'n'; + chan->modes[CM_NOEXTERNAL] = 1; + } + else + { + if (chan->modes[CM_NOEXTERNAL]) *outl++ = 'n'; + chan->modes[CM_NOEXTERNAL] = 0; + } } break; case 'm': - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'm', "", mdir, 0)); - if (!MOD_RESULT) - { - if (mdir) - { - if (!(chan->binarymodes & CM_MODERATED)) *outl++ = 'm'; - chan->binarymodes |= CM_MODERATED; - } - else - { - if (chan->binarymodes & CM_MODERATED) *outl++ = 'm'; - chan->binarymodes &= ~CM_MODERATED; - } + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'm', "", mdir, 0)); + if (!MOD_RESULT) + { + if (mdir) + { + if (!(chan->modes[CM_MODERATED])) *outl++ = 'm'; + chan->modes[CM_MODERATED] = 1; + } + else + { + if (chan->modes[CM_MODERATED]) *outl++ = 'm'; + chan->modes[CM_MODERATED] = 0; + } } break; case 's': - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 's', "", mdir, 0)); - if (!MOD_RESULT) - { - if (mdir) - { - if (!(chan->binarymodes & CM_SECRET)) *outl++ = 's'; - chan->binarymodes |= CM_SECRET; - if (chan->binarymodes & CM_PRIVATE) - { - chan->binarymodes &= ~CM_PRIVATE; - if (mdir) - { + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 's', "", mdir, 0)); + if (!MOD_RESULT) + { + if (mdir) + { + if (!(chan->modes[CM_SECRET])) *outl++ = 's'; + chan->modes[CM_SECRET] = 1; + if (chan->modes[CM_PRIVATE]) + { + chan->modes[CM_PRIVATE] = 0; + if (mdir) + { *outl++ = '-'; *outl++ = 'p'; *outl++ = '+'; - } - } - } - else - { - if (chan->binarymodes & CM_SECRET) *outl++ = 's'; - chan->binarymodes &= ~CM_SECRET; - } + } + } + } + else + { + if (chan->modes[CM_SECRET]) *outl++ = 's'; + chan->modes[CM_SECRET] = 0; + } } break; case 'p': - MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'p', "", mdir, 0)); - if (!MOD_RESULT) - { - if (mdir) - { - if (!(chan->binarymodes & CM_PRIVATE)) *outl++ = 'p'; - chan->binarymodes |= CM_PRIVATE; - if (chan->binarymodes & CM_SECRET) - { - chan->binarymodes &= ~CM_SECRET; - if (mdir) - { - *outl++ = '-'; *outl++ = 's'; *outl++ = '+'; - } - } - } - else - { - if (chan->binarymodes & CM_PRIVATE) *outl++ = 'p'; - chan->binarymodes &= ~CM_PRIVATE; - } + MOD_RESULT = 0; + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'p', "", mdir, 0)); + if(!MOD_RESULT) + { + if(mdir) + { + if(!(chan->modes[CM_PRIVATE])) + *outl++ = 'p'; + + chan->modes[CM_PRIVATE] = 1; + + if(chan->modes[CM_SECRET]) + { + chan->modes[CM_SECRET] = 0; + + *outl++ = '-'; + *outl++ = 's'; + *outl++ = '+'; + } + } + else + { + if(chan->modes[CM_PRIVATE]) + *outl++ = 'p'; + + chan->modes[CM_PRIVATE] = 0; + } } - break; + break; default: string_list p; p.clear(); - bool x = chan->custom_modes[*modechar-65]; + bool x = chan->modes[*modechar-65]; if ((!x && !mdir) || (x && mdir)) { if (!ModeIsListMode(*modechar,MT_CHANNEL)) @@ -894,7 +1071,7 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int /* A module has claimed this mode */ if (param0) && (mdir)) + if ((ModeDefinedOn(*modechar,MT_CHANNEL)>0) && (mdir)) { p.push_back(parameters[param]); } @@ -918,14 +1095,15 @@ void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int // Using OnRawMode on another modules mode's behavour // will confuse the crap out of admins! just because you CAN // do it, doesnt mean you SHOULD! - MOD_RESULT = 0; + MOD_RESULT = 0; std::string para = ""; if (p.size()) para = p[0]; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, *modechar, para, mdir, pcnt)); - if (!MOD_RESULT) - { - for (int i = 0; i <= MODCOUNT; i++) + + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, *modechar, para, mdir, pcnt)); + if(!MOD_RESULT) + { + for (int i = 0; i <= MODCOUNT; i++) { if (!handled) { @@ -1133,8 +1311,9 @@ bool ModeParser::ProcessModuleUmode(char umode, userrec* source, void* dest, boo void cmd_mode::Handle (char **parameters, int pcnt, userrec *user) { - chanrec* Ptr; + chanrec* chan; userrec* dest = Find(parameters[0]); + int MOD_RESULT; int can_change; int direction = 1; char outpars[MAXBUF]; @@ -1233,9 +1412,22 @@ void cmd_mode::Handle (char **parameters, int pcnt, userrec *user) { charlcat(dmodes,*i,53); charlcat(outpars,*i,MAXMODES); - if (*i == 'o') + switch (*i) { - FOREACH_MOD(I_OnGlobalOper,OnGlobalOper(dest)); + case 'o': + FOREACH_MOD(I_OnGlobalOper,OnGlobalOper(dest)); + break; + case 'i': + dest->modebits |= UM_INVISIBLE; + break; + case 's': + dest->modebits |= UM_SERVERNOTICE; + break; + case 'w': + dest->modebits |= UM_WALLOPS; + break; + default: + break; } } } @@ -1248,10 +1440,23 @@ void cmd_mode::Handle (char **parameters, int pcnt, userrec *user) { charlcat(outpars,*i,MAXMODES); charremove(dmodes,*i); - if (*i == 'o') + switch (*i) { - *dest->oper = 0; - DeleteOper(dest); + case 'o': + *dest->oper = 0; + DeleteOper(dest); + break; + case 'i': + dest->modebits &= ~UM_INVISIBLE; + break; + case 's': + dest->modebits &= ~UM_SERVERNOTICE; + break; + case 'w': + dest->modebits &= ~UM_WALLOPS; + break; + default: + break; } } } @@ -1302,68 +1507,70 @@ void cmd_mode::Handle (char **parameters, int pcnt, userrec *user) } else { - Ptr = FindChan(parameters[0]); - if (Ptr) + chan = FindChan(parameters[0]); + if(chan) { if (pcnt == 1) { /* just /modes #channel */ - WriteServ(user->fd,"324 %s %s +%s",user->nick, Ptr->name, chanmodes(Ptr,has_channel(user,Ptr))); - WriteServ(user->fd,"329 %s %s %d", user->nick, Ptr->name, Ptr->created); + WriteServ(user->fd,"324 %s %s +%s",user->nick, chan->name, chanmodes(chan, chan->HasUser(user))); + WriteServ(user->fd,"329 %s %s %d", user->nick, chan->name, chan->created); return; } else if (pcnt == 2) { char* mode = parameters[1]; + + MOD_RESULT = 0; + if (*mode == '+') mode++; - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnRawMode,OnRawMode(user, Ptr, *mode, "", false, 0)); - if (!MOD_RESULT) - { + + FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, *mode, "", false, 0)); + if(!MOD_RESULT) + { if (*mode == 'b') { - for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++) + for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++) { - WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time); + WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, chan->name, i->data, i->set_by, i->set_time); } - WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name); + WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, chan->name); return; } + if ((ModeDefined(*mode,MT_CHANNEL)) && (ModeIsListMode(*mode,MT_CHANNEL))) { // list of items for an extmode log(DEBUG,"Calling OnSendList for all modules, list output for mode %c",*mode); - FOREACH_MOD(I_OnSendList,OnSendList(user,Ptr,*mode)); + FOREACH_MOD(I_OnSendList,OnSendList(user,chan,*mode)); return; } } } - if (((Ptr) && (!has_channel(user,Ptr))) && (!is_uline(user->server)) && (IS_LOCAL(user))) - { - WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name); - return; - } - - if (Ptr) + if ((IS_LOCAL(user)) && (!is_uline(user->server)) && (!chan->HasUser(user))) { - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user,NULL,Ptr,AC_GENERAL_MODE)); + WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, chan->name); + return; + } + + MOD_RESULT = 0; + FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, chan, AC_GENERAL_MODE)); - if (MOD_RESULT == ACR_DENY) - return; - if (MOD_RESULT == ACR_DEFAULT) + if(MOD_RESULT == ACR_DENY) + return; + + if(MOD_RESULT == ACR_DEFAULT) + { + if ((IS_LOCAL(user)) && (cstatus(user,chan) < STATUS_HOP)) { - if ((cstatus(user,Ptr) < STATUS_HOP) && (IS_LOCAL(user))) - { - WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, Ptr->name); - return; - } + WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name); + return; } - - ServerInstance->ModeGrok->ProcessModes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,false); } + + ServerInstance->ModeGrok->ProcessModes(parameters,user,chan,cstatus(user,chan),pcnt,false,false,false); } else { @@ -1386,8 +1593,8 @@ void ModeParser::ServerMode(char **parameters, int pcnt, userrec *user) if ((dest) && (pcnt > 1)) { - std::string tidied = ServerInstance->ModeGrok->CompressModes(parameters[1],false); - parameters[1] = (char*)tidied.c_str(); + std::string tidied = ServerInstance->ModeGrok->CompressModes(parameters[1],false); + parameters[1] = (char*)tidied.c_str(); char dmodes[MAXBUF]; strlcpy(dmodes,dest->modes,MAXBUF); @@ -1406,8 +1613,8 @@ void ModeParser::ServerMode(char **parameters, int pcnt, userrec *user) switch (*i) { - case ' ': - continue; + case ' ': + continue; case '+': if ((direction != 1) && (next_ok)) @@ -1442,6 +1649,20 @@ void ModeParser::ServerMode(char **parameters, int pcnt, userrec *user) { charlcat(dmodes,*i,MAXBUF); charlcat(outpars,*i,53); + switch (*i) + { + case 'i': + dest->modebits |= UM_INVISIBLE; + break; + case 's': + dest->modebits |= UM_SERVERNOTICE; + break; + case 'w': + dest->modebits |= UM_WALLOPS; + break; + default: + break; + } } } } @@ -1456,6 +1677,20 @@ void ModeParser::ServerMode(char **parameters, int pcnt, userrec *user) { charlcat(outpars,*i,MAXBUF); charremove(dmodes,*i); + switch (*i) + { + case 'i': + dest->modebits &= ~UM_INVISIBLE; + break; + case 's': + dest->modebits &= ~UM_SERVERNOTICE; + break; + case 'w': + dest->modebits &= ~UM_WALLOPS; + break; + default: + break; + } } } } @@ -1463,43 +1698,43 @@ void ModeParser::ServerMode(char **parameters, int pcnt, userrec *user) break; } } - if (*outpars) - { - char b[MAXBUF]; - char* z = b; - - for (char* i = outpars; *i;) - { - *z++ = *i++; - if (((*i == '-') || (*i == '+')) && ((*(i+1) == '-') || (*(i+1) == '+'))) - { - // someones playing silly buggers and trying - // to put a +- or -+ into the line... - i++; - } - if (!*(i+1)) - { - // Someone's trying to make the last character in - // the line be a + or - symbol. - if ((*i == '-') || (*i == '+')) - { - i++; - } - } - } - *z = 0; - - if ((*b) && (!IS_SINGLE(b,'+')) && (!IS_SINGLE(b,'-'))) - { - WriteTo(user, dest, "MODE %s :%s", dest->nick, b); - FOREACH_MOD(I_OnMode,OnMode(user, dest, TYPE_USER, b)); - } - - log(DEBUG,"Stripped mode line"); - log(DEBUG,"Line dest is now %s",dmodes); - strlcpy(dest->modes,dmodes,MAXMODES-1); - - } + if (*outpars) + { + char b[MAXBUF]; + char* z = b; + + for (char* i = outpars; *i;) + { + *z++ = *i++; + if (((*i == '-') || (*i == '+')) && ((*(i+1) == '-') || (*(i+1) == '+'))) + { + // someones playing silly buggers and trying + // to put a +- or -+ into the line... + i++; + } + if (!*(i+1)) + { + // Someone's trying to make the last character in + // the line be a + or - symbol. + if ((*i == '-') || (*i == '+')) + { + i++; + } + } + } + *z = 0; + + if ((*b) && (!IS_SINGLE(b,'+')) && (!IS_SINGLE(b,'-'))) + { + WriteTo(user, dest, "MODE %s :%s", dest->nick, b); + FOREACH_MOD(I_OnMode,OnMode(user, dest, TYPE_USER, b)); + } + + log(DEBUG,"Stripped mode line"); + log(DEBUG,"Line dest is now %s",dmodes); + strlcpy(dest->modes,dmodes,MAXMODES-1); + + } return; }