X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmode.cpp;h=3bdcb1a300cd49448434a240531d8ee09061c883;hb=dc7927e17cffb2ee3c50ef9f037ed873d378f679;hp=c865ebe2f7ed2519d20e1e825cd16b4676d4a467;hpb=6050df73f498d05597fb37c6157868df1f6f4db2;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/mode.cpp b/src/mode.cpp index c865ebe2f..3bdcb1a30 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -16,17 +16,10 @@ using namespace std; -#include "inspircd_config.h" #include "inspircd.h" -#include "configreader.h" -#include -#include "hash_map.h" -#include "connection.h" #include "users.h" #include "modules.h" #include "inspstring.h" - -#include "commands.h" #include "mode.h" /* +s (secret) */ @@ -53,7 +46,6 @@ using namespace std; #include "modes/cmode_h.h" /* +v (channel voice) */ #include "modes/cmode_v.h" - /* +s (server notices) */ #include "modes/umode_s.h" /* +w (see wallops) */ @@ -65,8 +57,8 @@ using namespace std; /* +n (notice mask - our implementation of snomasks) */ #include "modes/umode_n.h" -ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly) - : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly) +ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix) + : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly), prefix(mprefix) { } @@ -79,6 +71,11 @@ bool ModeHandler::IsListMode() return list; } +unsigned int ModeHandler::GetPrefixRank() +{ + return 0; +} + ModeType ModeHandler::GetModeType() { return m_type; @@ -89,6 +86,11 @@ bool ModeHandler::NeedsOper() return oper; } +char ModeHandler::GetPrefix() +{ + return prefix; +} + int ModeHandler::GetNumParams(bool adding) { return adding ? n_params_on : n_params_off; @@ -249,7 +251,8 @@ void ModeParser::DisplayCurrentModes(userrec *user, userrec* targetuser, chanrec { /* Display user's current mode string */ user->WriteServ("221 %s :+%s",targetuser->nick,targetuser->FormatModes()); - user->WriteServ("008 %s :+%s", targetuser->nick, targetuser->FormatNoticeMasks()); + if (*targetuser->oper) + user->WriteServ("008 %s +%s :Server notice mask", targetuser->nick, targetuser->FormatNoticeMasks()); return; } @@ -273,9 +276,10 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool */ if ((targetchannel) && (pcnt == 2)) { + ServerInstance->Log(DEBUG,"Spool list"); const char* mode = parameters[1]; if (*mode == '+') - mode++; + mode++; unsigned char handler_id = ((*mode) - 65) | MASK_CHANNEL; ModeHandler* mh = modehandlers[handler_id]; if ((mh) && (mh->IsListMode())) @@ -287,10 +291,13 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool if (pcnt == 1) { + ServerInstance->Log(DEBUG,"Mode list request"); this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]); } else if (pcnt > 1) { + ServerInstance->Log(DEBUG,"More than one parameter"); + if (targetchannel) { type = MODETYPE_CHANNEL; @@ -337,10 +344,16 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool unsigned char handler_id = 0; int parameter_counter = 2; /* Index of first parameter */ + /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */ + if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-')) + mode_sequence.insert(0, "+"); + for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++) { unsigned char modechar = *letter; + ServerInstance->Log(DEBUG,"Process letter %c", modechar); + switch (modechar) { /* NB: @@ -395,6 +408,10 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool if (parameter_counter < pcnt) { parameter = parameters[parameter_counter++]; + + /* Yerk, invalid! */ + if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos)) + parameter = ""; } else { @@ -407,7 +424,12 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool * eat any parameter that came with the mode, and continue to next */ if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!*user->oper)) + { + 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); @@ -432,7 +454,17 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool /* 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; + /* Does this mode have a prefix? */ + if (modehandlers[handler_id]->GetPrefix() && targetchannel) + { + userrec* user_to_prefix = ServerInstance->FindNick(parameter); + if (user_to_prefix) + targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(), + modehandlers[handler_id]->GetPrefixRank(), adding); + } + } /* 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++) @@ -462,7 +494,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool } else { - targetuser->WriteServ("MODE %s %s",targetuser->nick,output_sequence.c_str()); + targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str()); } } else @@ -475,7 +507,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool } else { - user->WriteTo(targetuser,"MODE %s %s",targetuser->nick,output_sequence.c_str()); + user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str()); FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence)); } } @@ -483,17 +515,6 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool } } - -void cmd_mode::Handle (const char** parameters, int pcnt, userrec *user) -{ - if (!user) - return; - - ServerInstance->Modes->Process(parameters, pcnt, user, false); - - return; -} - void ModeParser::CleanMask(std::string &mask) { std::string::size_type pos_of_pling = mask.find_first_of('!'); @@ -539,6 +560,12 @@ bool ModeParser::AddMode(ModeHandler* mh, unsigned const char modeletter) if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) return false; + /* A mode prefix of ',' is not acceptable, it would fuck up server to server. + * A mode prefix of ':' will fuck up both server to server, and client to server. + */ + if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':')) + return false; + mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; pos = (mh->GetModeChar()-65) | mask; @@ -550,6 +577,41 @@ bool ModeParser::AddMode(ModeHandler* mh, unsigned const char modeletter) return true; } +bool ModeParser::DelMode(ModeHandler* mh) +{ + unsigned char mask = 0; + unsigned char pos = 0; + + if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) + return false; + + mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; + pos = (mh->GetModeChar()-65) | mask; + + if (!modehandlers[pos]) + return false; + + switch (mh->GetModeType()) + { + case MODETYPE_USER: + for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++) + { + mh->RemoveMode(i->second); + } + break; + case MODETYPE_CHANNEL: + for (chan_hash::iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++) + { + mh->RemoveMode(i->second); + } + break; + } + + modehandlers[pos] = NULL; + + return true; +} + ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt) { unsigned char mask = 0; @@ -612,6 +674,127 @@ std::string ModeParser::ParaModeList() return modestr; } +ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter) +{ + for (unsigned char mode = 'A'; mode <= 'z'; mode++) + { + unsigned char pos = (mode-65) | MASK_CHANNEL; + + if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter)) + { + return modehandlers[pos]; + } + } + return NULL; +} + +std::string ModeParser::ModeString(userrec* user, chanrec* channel) +{ + std::string types; + std::string pars; + + for (unsigned char mode = 'A'; mode <= 'z'; mode++) + { + unsigned char pos = (mode-65) | MASK_CHANNEL; + ModeHandler* mh = modehandlers[pos]; + if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false))) + { + ModePair ret; + ret = mh->ModeSet(NULL, user, channel, user->nick); + if (ret.first) + { + pars.append(" "); + pars.append(user->nick); + types.push_back(mh->GetModeChar()); + } + } + } + + return types+pars; +} + +std::string ModeParser::ChanModes() +{ + std::string type1; /* Listmodes EXCEPT those with a prefix */ + std::string type2; /* Modes that take a param when adding or removing */ + std::string type3; /* Modes that only take a param when adding */ + std::string type4; /* Modes that dont take a param */ + + for (unsigned char mode = 'A'; mode <= 'z'; mode++) + { + unsigned char pos = (mode-65) | MASK_CHANNEL; + /* One parameter when adding */ + if (modehandlers[pos]) + { + if (modehandlers[pos]->GetNumParams(true)) + { + if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix())) + { + type1 += modehandlers[pos]->GetModeChar(); + } + else + { + /* ... and one parameter when removing */ + if (modehandlers[pos]->GetNumParams(false)) + { + /* But not a list mode */ + if (!modehandlers[pos]->GetPrefix()) + { + type2 += modehandlers[pos]->GetModeChar(); + } + } + else + { + /* No parameters when removing */ + type3 += modehandlers[pos]->GetModeChar(); + } + } + } + else + { + type4 += modehandlers[pos]->GetModeChar(); + } + } + + } + + return type1 + "," + type2 + "," + type3 + "," + type4; +} + +bool ModeParser::PrefixComparison(const prefixtype one, const prefixtype two) +{ + return one.second > two.second; +} + +std::string ModeParser::BuildPrefixes() +{ + std::string mletters = ""; + std::string mprefixes = ""; + pfxcontainer pfx; + std::map prefix_to_mode; + + for (unsigned char mode = 'A'; mode <= 'z'; mode++) + { + unsigned char pos = (mode-65) | MASK_CHANNEL; + + if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix())) + { + pfx.push_back(std::make_pair(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank())); + prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar(); + } + } + + sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison); + + for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++) + { + mletters = mletters + n->first; + mprefixes = mprefixes + prefix_to_mode.find(n->first)->second; + } + + return "(" + mprefixes + ")" + mletters; +} + bool ModeParser::AddModeWatcher(ModeWatcher* mw) { unsigned char mask = 0; @@ -657,6 +840,47 @@ bool ModeParser::DelModeWatcher(ModeWatcher* mw) return true; } +/** This default implementation can remove simple user modes + */ +void ModeHandler::RemoveMode(userrec* user) +{ + char moderemove[MAXBUF]; + const char* parameters[] = { user->nick, moderemove }; + + if (user->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; + } +} + +/** This default implementation can remove simple channel modes + * (no parameters) + */ +void ModeHandler::RemoveMode(chanrec* channel) +{ + char moderemove[MAXBUF]; + const char* parameters[] = { channel->name, moderemove }; + + 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; + } +} + ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance) { /* Clear mode list */ @@ -691,27 +915,3 @@ ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance) this->AddMode(new ModeUserServerNoticeMask(Instance), 'n'); } -bool ModeParser::InsertMode(std::string &output, const char* mode, unsigned short section) -{ - unsigned short currsection = 1; - unsigned int pos = output.find("CHANMODES=", 0) + 10; // +10 for the length of "CHANMODES=" - - if(section > 4 || section == 0) - { - ServerInstance->Log(DEBUG, "InsertMode: CHANMODES doesn't have a section %dh :/", section); - return false; - } - - for(; pos < output.size(); pos++) - { - if(section == currsection) - break; - - if(output[pos] == ',') - currsection++; - } - - output.insert(pos, mode); - return true; -} -