|
|||
|
|||
|
#include <mode.h>
Inheritance diagram for ModeParser:


Public Member Functions | |
| ModeParser (InspIRCd *Instance) | |
| The constructor initializes all the RFC basic modes by using ModeParserAddMode(). | |
| userrec * | SanityChecks (userrec *user, const char *dest, chanrec *chan, int status) |
| Used to check if user 'd' should be allowed to do operation 'MASK' on channel 'chan'. | |
| const char * | Grant (userrec *d, chanrec *chan, int MASK) |
| Grant a built in privilage (e.g. | |
| const char * | Revoke (userrec *d, chanrec *chan, int MASK) |
| Revoke a built in privilage (e.g. | |
| const std::string & | GetLastParse () |
| Get the last string to be processed, as it was sent to the user or channel. | |
| bool | AddMode (ModeHandler *mh, unsigned const char modeletter) |
| Add a mode to the mode parser. | |
| bool | DelMode (ModeHandler *mh) |
| Delete a mode from the mode parser. | |
| bool | AddModeWatcher (ModeWatcher *mw) |
| Add a mode watcher. | |
| bool | DelModeWatcher (ModeWatcher *mw) |
| Delete a mode watcher. | |
| void | Process (const char **parameters, int pcnt, userrec *user, bool servermode) |
| Process a set of mode changes from a server or user. | |
| ModeHandler * | FindMode (unsigned const char modeletter, ModeType mt) |
| Find the mode handler for a given mode and type. | |
| ModeHandler * | FindPrefix (unsigned const char pfxletter) |
| Find a mode handler by its prefix. | |
| std::string | UserModeList () |
| Returns a list of mode characters which are usermodes. | |
| std::string | ChannelModeList () |
| Returns a list of channel mode characters which are listmodes. | |
| std::string | ParaModeList () |
| Returns a list of channel mode characters which take parameters. | |
| std::string | ChanModes () |
| Generates the CHANMODES= 005 sequence. | |
| std::string | BuildPrefixes () |
| This returns the PREFIX=(ohv)%+ section of the 005 numeric. | |
| std::string | ModeString (userrec *user, chanrec *channel) |
| This returns the privilages of a user upon a channel, in the format of a mode change. | |
Static Public Member Functions | |
| static void | CleanMask (std::string &mask) |
| Tidy a banmask. | |
| static bool | PrefixComparison (prefixtype one, prefixtype two) |
| Used by this class internally during std::sort and 005 generation. | |
Private Member Functions | |
| void | DisplayCurrentModes (userrec *user, userrec *targetuser, chanrec *targetchannel, const char *text) |
| Displays the current modes of a channel or user. | |
Private Attributes | |
| InspIRCd * | ServerInstance |
| Creator/owner pointer. | |
| ModeHandler * | modehandlers [256] |
| Mode handlers for each mode, to access a handler subtract 65 from the ascii value of the mode letter. | |
| std::vector< ModeWatcher * > | modewatchers [256] |
| Mode watcher classes arranged in the same way as the mode handlers, except for instead of having 256 of them we have 256 lists of them. | |
| std::string | LastParse |
| The string representing the last set of modes to be parsed. | |
It marshalls, controls and maintains both ModeWatcher and ModeHandler classes, parses client to server MODE strings for user and channel modes, and performs processing for the 004 mode list numeric, amongst other things.
Definition at line 369 of file mode.h.
|
|
The constructor initializes all the RFC basic modes by using ModeParserAddMode().
Definition at line 1036 of file mode.cpp. References AddMode(), LastParse, modehandlers, and modewatchers. 01036 : ServerInstance(Instance) 01037 { 01038 struct Initializer 01039 { 01040 char modechar; 01041 ModeHandler* handler; 01042 }; 01043 01044 Initializer modes[] = { 01045 { 's', new ModeChannelSecret(Instance) }, 01046 { 'p', new ModeChannelPrivate(Instance) }, 01047 { 'm', new ModeChannelModerated(Instance) }, 01048 { 't', new ModeChannelTopicOps(Instance) }, 01049 { 'n', new ModeChannelNoExternal(Instance) }, 01050 { 'i', new ModeChannelInviteOnly(Instance) }, 01051 { 'k', new ModeChannelKey(Instance) }, 01052 { 'l', new ModeChannelLimit(Instance) }, 01053 { 'b', new ModeChannelBan(Instance) }, 01054 { 'o', new ModeChannelOp(Instance) }, 01055 { 'h', new ModeChannelHalfOp(Instance) }, 01056 { 'v', new ModeChannelVoice(Instance) }, 01057 { 's', new ModeUserServerNotice(Instance) }, 01058 { 'w', new ModeUserWallops(Instance) }, 01059 { 'i', new ModeUserInvisible(Instance) }, 01060 { 'o', new ModeUserOperator(Instance) }, 01061 { 'n', new ModeUserServerNoticeMask(Instance) }, 01062 { 0, NULL } 01063 }; 01064 01065 /* Clear mode list */ 01066 memset(modehandlers, 0, sizeof(modehandlers)); 01067 memset(modewatchers, 0, sizeof(modewatchers)); 01068 01069 /* Last parse string */ 01070 LastParse.clear(); 01071 01072 /* Initialise the RFC mode letters */ 01073 for (int index = 0; modes[index].modechar; index++) 01074 this->AddMode(modes[index].handler, modes[index].modechar); 01075 }
|
|
||||||||||||
|
Add a mode to the mode parser. The modeletter parameter is purely to save on doing a lookup in the function, as strictly it could be obtained via ModeHandler::GetModeChar().
Definition at line 694 of file mode.cpp. References ModeHandler::GetModeChar(), ModeHandler::GetModeType(), ModeHandler::GetPrefix(), MASK_CHANNEL, MASK_USER, modehandlers, and MODETYPE_USER. Referenced by InspIRCd::AddMode(), and ModeParser(). 00695 { 00696 unsigned char mask = 0; 00697 unsigned char pos = 0; 00698 00699 /* Yes, i know, this might let people declare modes like '_' or '^'. 00700 * If they do that, thats their problem, and if i ever EVER see an 00701 * official InspIRCd developer do that, i'll beat them with a paddle! 00702 */ 00703 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126)) 00704 return false; 00705 00706 /* A mode prefix of ',' is not acceptable, it would fuck up server to server. 00707 * A mode prefix of ':' will fuck up both server to server, and client to server. 00708 * A mode prefix of '#' will mess up /whois and /privmsg 00709 */ 00710 if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':') || (mh->GetPrefix() == '#')) 00711 return false; 00712 00713 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; 00714 pos = (mh->GetModeChar()-65) | mask; 00715 00716 if (modehandlers[pos]) 00717 return false; 00718 00719 modehandlers[pos] = mh; 00720 return true; 00721 }
|
|
|
Add a mode watcher. A mode watcher is triggered before and after a mode handler is triggered. See the documentation of class ModeWatcher for more information.
Definition at line 956 of file mode.cpp. References ModeWatcher::GetModeChar(), ModeWatcher::GetModeType(), MASK_CHANNEL, MASK_USER, MODETYPE_USER, and modewatchers. Referenced by InspIRCd::AddModeWatcher(). 00957 { 00958 unsigned char mask = 0; 00959 unsigned char pos = 0; 00960 00961 if (!mw) 00962 return false; 00963 00964 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z')) 00965 return false; 00966 00967 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; 00968 pos = (mw->GetModeChar()-65) | mask; 00969 00970 modewatchers[pos].push_back(mw); 00971 00972 return true; 00973 }
|
|
|
This returns the PREFIX=(ohv)%+ section of the 005 numeric.
Definition at line 924 of file mode.cpp. References ServerConfig::AllowHalfop, InspIRCd::Config, ModeHandler::GetPrefix(), MASK_CHANNEL, modehandlers, PrefixComparison(), and ServerInstance. Referenced by InspIRCd::BuildISupport(), TreeSocket::Capab(), and TreeSocket::SendCapabilities(). 00925 { 00926 std::string mletters; 00927 std::string mprefixes; 00928 pfxcontainer pfx; 00929 std::map<char,char> prefix_to_mode; 00930 00931 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00932 { 00933 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h')) 00934 continue; 00935 00936 unsigned char pos = (mode-65) | MASK_CHANNEL; 00937 00938 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix())) 00939 { 00940 pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank())); 00941 prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar(); 00942 } 00943 } 00944 00945 sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison); 00946 00947 for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++) 00948 { 00949 mletters = mletters + n->first; 00950 mprefixes = mprefixes + prefix_to_mode.find(n->first)->second; 00951 } 00952 00953 return "(" + mprefixes + ")" + mletters; 00954 }
|
|
|
Generates the CHANMODES= 005 sequence.
Definition at line 868 of file mode.cpp. References ServerConfig::AllowHalfop, InspIRCd::Config, ModeHandler::GetModeChar(), MASK_CHANNEL, modehandlers, and ServerInstance. Referenced by InspIRCd::BuildISupport(), and TreeSocket::SendCapabilities(). 00869 { 00870 std::string type1; /* Listmodes EXCEPT those with a prefix */ 00871 std::string type2; /* Modes that take a param when adding or removing */ 00872 std::string type3; /* Modes that only take a param when adding */ 00873 std::string type4; /* Modes that dont take a param */ 00874 00875 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00876 { 00877 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h')) 00878 continue; 00879 00880 unsigned char pos = (mode-65) | MASK_CHANNEL; 00881 /* One parameter when adding */ 00882 if (modehandlers[pos]) 00883 { 00884 if (modehandlers[pos]->GetNumParams(true)) 00885 { 00886 if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix())) 00887 { 00888 type1 += modehandlers[pos]->GetModeChar(); 00889 } 00890 else 00891 { 00892 /* ... and one parameter when removing */ 00893 if (modehandlers[pos]->GetNumParams(false)) 00894 { 00895 /* But not a list mode */ 00896 if (!modehandlers[pos]->GetPrefix()) 00897 { 00898 type2 += modehandlers[pos]->GetModeChar(); 00899 } 00900 } 00901 else 00902 { 00903 /* No parameters when removing */ 00904 type3 += modehandlers[pos]->GetModeChar(); 00905 } 00906 } 00907 } 00908 else 00909 { 00910 type4 += modehandlers[pos]->GetModeChar(); 00911 } 00912 } 00913 00914 } 00915 00916 return type1 + "," + type2 + "," + type3 + "," + type4; 00917 }
|
|
|
Returns a list of channel mode characters which are listmodes. This is used in the 004 numeric when users connect. Definition at line 788 of file mode.cpp. References ServerConfig::AllowHalfop, InspIRCd::Config, MASK_CHANNEL, modehandlers, and ServerInstance. Referenced by userrec::FullConnect(). 00789 { 00790 char modestr[256]; 00791 int pointer = 0; 00792 00793 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00794 { 00795 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h')) 00796 continue; 00797 00798 unsigned char pos = (mode-65) | MASK_CHANNEL; 00799 00800 if (modehandlers[pos]) 00801 modestr[pointer++] = mode; 00802 } 00803 modestr[pointer++] = 0; 00804 return modestr; 00805 }
|
|
|
Tidy a banmask. This makes a banmask 'acceptable' if fields are left out. E.g. nick -> nick!*@* nick!ident -> nick!ident@* host.name -> *!*.name ident@host.name -> *!ident.name This method can be used on both IPV4 and IPV6 user masks. Definition at line 661 of file mode.cpp. Referenced by cmd_silence::Handle(), and ListModeBase::OnModeChange(). 00662 { 00663 std::string::size_type pos_of_pling = mask.find_first_of('!'); 00664 std::string::size_type pos_of_at = mask.find_first_of('@'); 00665 std::string::size_type pos_of_dot = mask.find_first_of('.'); 00666 std::string::size_type pos_of_colon = mask.find_first_of(':'); /* Because ipv6 addresses are colon delimited */ 00667 00668 if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos)) 00669 { 00670 /* Just a nick, or just a host */ 00671 if ((pos_of_dot == std::string::npos) && (pos_of_colon == std::string::npos)) 00672 { 00673 /* It has no '.' in it, it must be a nick. */ 00674 mask.append("!*@*"); 00675 } 00676 else 00677 { 00678 /* Got a dot in it? Has to be a host */ 00679 mask = "*!*@" + mask; 00680 } 00681 } 00682 else if ((pos_of_pling == std::string::npos) && (pos_of_at != std::string::npos)) 00683 { 00684 /* Has an @ but no !, its a user@host */ 00685 mask = "*!" + mask; 00686 } 00687 else if ((pos_of_pling != std::string::npos) && (pos_of_at == std::string::npos)) 00688 { 00689 /* Has a ! but no @, it must be a nick!ident */ 00690 mask.append("@*"); 00691 } 00692 }
|
|
|
|
Delete a mode watcher. A mode watcher is triggered before and after a mode handler is triggered. See the documentation of class ModeWatcher for more information.
Definition at line 975 of file mode.cpp. References ModeWatcher::GetModeChar(), ModeWatcher::GetModeType(), MASK_CHANNEL, MASK_USER, MODETYPE_USER, and modewatchers. Referenced by InspIRCd::DelModeWatcher(), ModuleBanRedirect::~ModuleBanRedirect(), and ModuleInvisible::~ModuleInvisible(). 00976 { 00977 unsigned char mask = 0; 00978 unsigned char pos = 0; 00979 00980 if (!mw) 00981 return false; 00982 00983 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z')) 00984 return false; 00985 00986 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; 00987 pos = (mw->GetModeChar()-65) | mask; 00988 00989 ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw); 00990 00991 if (a == modewatchers[pos].end()) 00992 { 00993 return false; 00994 } 00995 00996 modewatchers[pos].erase(a); 00997 00998 return true; 00999 }
|
|
||||||||||||||||||||
|
Displays the current modes of a channel or user. Used by ModeParser::Process. Definition at line 243 of file mode.cpp. References classbase::age, chanrec::ChanModes(), userrec::FormatModes(), userrec::FormatNoticeMasks(), chanrec::HasUser(), IS_OPER, chanrec::name, userrec::nick, userrec::Visibility, VisData::VisibleTo(), and userrec::WriteServ(). Referenced by Process(). 00244 { 00245 if (targetchannel) 00246 { 00247 /* Display channel's current mode string */ 00248 user->WriteServ("324 %s %s +%s",user->nick, targetchannel->name, targetchannel->ChanModes(targetchannel->HasUser(user))); 00249 user->WriteServ("329 %s %s %lu", user->nick, targetchannel->name, (unsigned long)targetchannel->age); 00250 return; 00251 } 00252 else if (targetuser) 00253 { 00254 if (targetuser->Visibility && !targetuser->Visibility->VisibleTo(user)) 00255 { 00256 user->WriteServ("401 %s %s :No such nick/channel",user->nick, text); 00257 return; 00258 } 00259 00260 if ((targetuser == user) || (IS_OPER(user))) 00261 { 00262 /* Display user's current mode string */ 00263 user->WriteServ("221 %s :+%s",targetuser->nick,targetuser->FormatModes()); 00264 if (IS_OPER(targetuser)) 00265 user->WriteServ("008 %s +%s :Server notice mask", targetuser->nick, targetuser->FormatNoticeMasks()); 00266 return; 00267 } 00268 else 00269 { 00270 user->WriteServ("502 %s :Can't change mode for other users", user->nick); 00271 return; 00272 } 00273 } 00274 00275 /* No such nick/channel */ 00276 user->WriteServ("401 %s %s :No such nick/channel",user->nick, text); 00277 return; 00278 }
|
|
||||||||||||
|
Find the mode handler for a given mode and type.
Definition at line 758 of file mode.cpp. References MASK_CHANNEL, MASK_USER, modehandlers, and MODETYPE_USER. Referenced by userrec::DecrementModes(), TreeSocket::IntroduceClient(), InspIRCd::ModeCount(), Process(), TreeSocket::RemoveStatus(), and chanrec::SetDefaultModes(). 00759 { 00760 unsigned char mask = 0; 00761 unsigned char pos = 0; 00762 00763 if ((modeletter < 'A') || (modeletter > 'z')) 00764 return NULL; 00765 00766 mt == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; 00767 pos = (modeletter-65) | mask; 00768 00769 return modehandlers[pos]; 00770 }
|
|
|
Find a mode handler by its prefix. If there is no mode handler with the given prefix, NULL will be returned.
Definition at line 826 of file mode.cpp. References MASK_CHANNEL, and modehandlers. Referenced by chanrec::ForceChan(), and TreeSocket::ForceJoin(). 00827 { 00828 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00829 { 00830 unsigned char pos = (mode-65) | MASK_CHANNEL; 00831 00832 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter)) 00833 { 00834 return modehandlers[pos]; 00835 } 00836 } 00837 return NULL; 00838 }
|
|
|
Get the last string to be processed, as it was sent to the user or channel. Use this to display a string you just sent to be parsed, as the actual output may be different to what you sent after it has been 'cleaned up' by the parser.
Definition at line 656 of file mode.cpp. References LastParse. Referenced by cmd_samode::Handle(), ModuleTimedBans::OnBackgroundTimer(), and ModuleOverride::OnPostCommand(). 00657 { 00658 return LastParse; 00659 }
|
|
||||||||||||||||
|
Grant a built in privilage (e.g. ops, halfops, voice) to a user on a channel Definition at line 183 of file mode.cpp. References userrec::chans, userrec::nick, UCMODE_HOP, UCMODE_OP, and UCMODE_VOICE. 00184 { 00185 if (!chan) 00186 return ""; 00187 00188 UCListIter n = d->chans.find(chan); 00189 if (n != d->chans.end()) 00190 { 00191 if (n->second & MASK) 00192 { 00193 return ""; 00194 } 00195 n->second = n->second | MASK; 00196 switch (MASK) 00197 { 00198 case UCMODE_OP: 00199 n->first->AddOppedUser(d); 00200 break; 00201 case UCMODE_HOP: 00202 n->first->AddHalfoppedUser(d); 00203 break; 00204 case UCMODE_VOICE: 00205 n->first->AddVoicedUser(d); 00206 break; 00207 } 00208 return d->nick; 00209 } 00210 return ""; 00211 }
|
|
||||||||||||
|
This returns the privilages of a user upon a channel, in the format of a mode change. For example, if a user has privilages +avh, this will return the string "avh nick nick nick". This is used by the core when cycling a user to refresh their hostname. You may use it for similar purposes.
Definition at line 840 of file mode.cpp. References ModeHandler::GetModeChar(), ModeHandler::GetNumParams(), MASK_CHANNEL, modehandlers, ModeHandler::ModeSet(), and userrec::nick. Referenced by userrec::ChangeDisplayedHost(), userrec::ChangeIdent(), chanrec::ForceChan(), and InvisibleMode::OnModeChange(). 00841 { 00842 std::string types; 00843 std::string pars; 00844 00845 if (!channel || !user) 00846 return ""; 00847 00848 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00849 { 00850 unsigned char pos = (mode-65) | MASK_CHANNEL; 00851 ModeHandler* mh = modehandlers[pos]; 00852 if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false))) 00853 { 00854 ModePair ret; 00855 ret = mh->ModeSet(NULL, user, channel, user->nick); 00856 if ((ret.first) && (ret.second == user->nick)) 00857 { 00858 pars.append(" "); 00859 pars.append(user->nick); 00860 types.push_back(mh->GetModeChar()); 00861 } 00862 } 00863 } 00864 00865 return types+pars; 00866 }
|
|
|
Returns a list of channel mode characters which take parameters. This is used in the 004 numeric when users connect. Definition at line 807 of file mode.cpp. References ServerConfig::AllowHalfop, InspIRCd::Config, MASK_CHANNEL, modehandlers, and ServerInstance. Referenced by userrec::FullConnect(). 00808 { 00809 char modestr[256]; 00810 int pointer = 0; 00811 00812 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00813 { 00814 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h')) 00815 continue; 00816 00817 unsigned char pos = (mode-65) | MASK_CHANNEL; 00818 00819 if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true))) 00820 modestr[pointer++] = mode; 00821 } 00822 modestr[pointer++] = 0; 00823 return modestr; 00824 }
|
|
||||||||||||
|
Used by this class internally during std::sort and 005 generation.
Definition at line 919 of file mode.cpp. Referenced by BuildPrefixes(), and chanrec::SetPrefix().
|
|
||||||||||||||||||||
|
Process a set of mode changes from a server or user.
Definition at line 280 of file mode.cpp. References AC_GENERAL_MODE, ACR_DEFAULT, ACR_DENY, ServerConfig::AllowHalfop, ModeHandler::ChangeCount(), InspIRCd::Config, DisplayCurrentModes(), ModeHandler::DisplayEmptyList(), ModeHandler::DisplayList(), InspIRCd::FindChan(), FindMode(), InspIRCd::FindNick(), FOREACH_MOD, FOREACH_RESULT, ModeHandler::GetModeChar(), chanrec::GetStatus(), ServerConfig::HideModeLists, I_OnAccessCheck, I_OnMode, IS_LOCAL, IS_OPER, ModeHandler::IsListMode(), LastParse, MASK_CHANNEL, MASK_USER, MAXMODES, MODEACTION_ALLOW, modehandlers, MODETYPE_CHANNEL, MODETYPE_USER, modewatchers, chanrec::name, userrec::nick, ModeHandler::OnModeChange(), userrec::server, ServerInstance, ServerConfig::ServerName, chanrec::SetPrefix(), STATUS_HOP, TYPE_CHANNEL, TYPE_USER, InspIRCd::ULine(), chanrec::WriteChannel(), chanrec::WriteChannelWithServ(), userrec::WriteServ(), and userrec::WriteTo(). Referenced by InvisibleDeOper::BeforeMode(), cmd_mode::Handle(), and InspIRCd::SendMode(). 00281 { 00282 std::string target = parameters[0]; 00283 ModeType type = MODETYPE_USER; 00284 unsigned char mask = 0; 00285 chanrec* targetchannel = ServerInstance->FindChan(parameters[0]); 00286 userrec* targetuser = ServerInstance->FindNick(parameters[0]); 00287 00288 LastParse.clear(); 00289 00290 /* Special case for displaying the list for listmodes, 00291 * e.g. MODE #chan b, or MODE #chan +b without a parameter 00292 */ 00293 if ((targetchannel) && (pcnt == 2)) 00294 { 00295 const char* mode = parameters[1]; 00296 int nonlistmodes_found = 0; 00297 bool sent[256]; 00298 00299 mask = MASK_CHANNEL; 00300 00301 memset(&sent, 0, 256); 00302 00303 while (mode && *mode) 00304 { 00305 unsigned char mletter = *mode; 00306 00307 if (*mode == '+') 00308 { 00309 mode++; 00310 continue; 00311 } 00312 00313 /* Ensure the user doesnt request the same mode twice, 00314 * so they cant flood themselves off out of idiocy. 00315 */ 00316 if (!sent[mletter]) 00317 { 00318 sent[mletter] = true; 00319 } 00320 else 00321 { 00322 mode++; 00323 continue; 00324 } 00325 00326 ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL); 00327 bool display = true; 00328 00329 if ((mh) && (mh->IsListMode())) 00330 { 00331 if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP)) 00332 { 00333 user->WriteServ("482 %s %s :Only half-operators and above may view the +%c list",user->nick, targetchannel->name, *mode++); 00334 mh->DisplayEmptyList(user, targetchannel); 00335 continue; 00336 } 00337 00340 unsigned char handler_id = (*mode - 65) | mask; 00341 00342 for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) 00343 { 00344 std::string dummyparam; 00345 00346 if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL))) 00347 display = false; 00348 } 00349 00350 if (display) 00351 mh->DisplayList(user, targetchannel); 00352 } 00353 else 00354 nonlistmodes_found++; 00355 00356 mode++; 00357 } 00358 00359 /* We didnt have any modes that were non-list, we can return here */ 00360 if (!nonlistmodes_found) 00361 return; 00362 } 00363 00364 if (pcnt == 1) 00365 { 00366 this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]); 00367 } 00368 else if (pcnt > 1) 00369 { 00370 if (targetchannel) 00371 { 00372 type = MODETYPE_CHANNEL; 00373 mask = MASK_CHANNEL; 00374 00375 /* Extra security checks on channel modes 00376 * (e.g. are they a (half)op? 00377 */ 00378 00379 if ((IS_LOCAL(user)) && (targetchannel->GetStatus(user) < STATUS_HOP)) 00380 { 00381 /* We don't have halfop */ 00382 int MOD_RESULT = 0; 00383 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE)); 00384 if (MOD_RESULT == ACR_DENY) 00385 return; 00386 00387 if (MOD_RESULT == ACR_DEFAULT) 00388 { 00389 /* Are we a uline or is it a servermode? */ 00390 if ((!ServerInstance->ULine(user->server)) && (!servermode)) 00391 { 00392 /* Not enough permission: 00393 * NOT a uline and NOT a servermode, 00394 * OR, NOT halfop or above. 00395 */ 00396 user->WriteServ("482 %s %s :You're not a channel %soperator",user->nick, targetchannel->name, 00397 ServerInstance->Config->AllowHalfop ? "(half)" : ""); 00398 return; 00399 } 00400 } 00401 } 00402 } 00403 else if (targetuser) 00404 { 00405 type = MODETYPE_USER; 00406 mask = MASK_USER; 00407 if ((user != targetuser) && (!ServerInstance->ULine(user->server))) 00408 { 00409 user->WriteServ("502 %s :Can't change mode for other users", user->nick); 00410 return; 00411 } 00412 } 00413 else 00414 { 00415 /* No such nick/channel */ 00416 user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]); 00417 return; 00418 } 00419 00420 std::string mode_sequence = parameters[1]; 00421 std::string parameter; 00422 std::ostringstream parameter_list; 00423 std::string output_sequence; 00424 bool adding = true, state_change = false; 00425 unsigned char handler_id = 0; 00426 int parameter_counter = 2; /* Index of first parameter */ 00427 int parameter_count = 0; 00428 bool last_successful_state_change = false; 00429 00430 /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */ 00431 if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-')) 00432 mode_sequence.insert(0, "+"); 00433 00434 for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++) 00435 { 00436 unsigned char modechar = *letter; 00437 00438 switch (modechar) 00439 { 00440 /* NB: 00441 * For + and - mode characters, we don't just stick the character into the output sequence. 00442 * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this 00443 * appearing in the output sequence, we store a flag which says there was a state change, 00444 * which is set on any + or -, however, the + or - that we finish on is only appended to 00445 * the output stream in the event it is followed by a non "+ or -" character, such as o or v. 00446 */ 00447 case '+': 00448 /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick, 00449 * however, will allow the + if it is the first item in the sequence, regardless. 00450 */ 00451 if ((!adding) || (!output_sequence.length())) 00452 state_change = true; 00453 adding = true; 00454 if (!output_sequence.length()) 00455 last_successful_state_change = false; 00456 continue; 00457 break; 00458 case '-': 00459 if ((adding) || (!output_sequence.length())) 00460 state_change = true; 00461 adding = false; 00462 if (!output_sequence.length()) 00463 last_successful_state_change = true; 00464 continue; 00465 break; 00466 default: 00467 00477 handler_id = (modechar - 65) | mask; 00478 00479 if (modehandlers[handler_id]) 00480 { 00481 bool abort = false; 00482 00483 if (modehandlers[handler_id]->GetModeType() == type) 00484 { 00485 if (modehandlers[handler_id]->GetNumParams(adding)) 00486 { 00487 /* This mode expects a parameter, do we have any parameters left in our list to use? */ 00488 if (parameter_counter < pcnt) 00489 { 00490 parameter = parameters[parameter_counter++]; 00491 00492 /* Yerk, invalid! */ 00493 if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos)) 00494 parameter.clear(); 00495 } 00496 else 00497 { 00498 /* No parameter, continue to the next mode */ 00499 continue; 00500 } 00501 00502 bool had_parameter = !parameter.empty(); 00503 00504 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) 00505 { 00506 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false) 00507 { 00508 abort = true; 00509 break; 00510 } 00511 /* A module whacked the parameter completely, and there was one. abort. */ 00512 if ((had_parameter) && (parameter.empty())) 00513 { 00514 abort = true; 00515 break; 00516 } 00517 } 00518 00519 if (abort) 00520 continue; 00521 } 00522 else 00523 { 00524 /* Fix by brain: mode watchers not being called for parameterless modes */ 00525 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) 00526 { 00527 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false) 00528 { 00529 abort = true; 00530 break; 00531 } 00532 } 00533 00534 if (abort) 00535 continue; 00536 } 00537 00538 /* It's an oper only mode, check if theyre an oper. If they arent, 00539 * eat any parameter that came with the mode, and continue to next 00540 */ 00541 if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user))) 00542 { 00543 user->WriteServ("481 %s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick, 00544 adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user", 00545 modehandlers[handler_id]->GetModeChar()); 00546 continue; 00547 } 00548 00549 /* Call the handler for the mode */ 00550 ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding); 00551 00552 if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty())) 00553 { 00554 /* The handler nuked the parameter and they are supposed to have one. 00555 * We CANT continue now, even if they actually returned MODEACTION_ALLOW, 00556 * so we bail to the next mode character. 00557 */ 00558 continue; 00559 } 00560 00561 if (ma == MODEACTION_ALLOW) 00562 { 00563 /* We're about to output a valid mode letter - was there previously a pending state-change? */ 00564 if (state_change) 00565 { 00566 if (adding != last_successful_state_change) 00567 output_sequence.append(adding ? "+" : "-"); 00568 last_successful_state_change = adding; 00569 } 00570 00571 /* Add the mode letter */ 00572 output_sequence.push_back(modechar); 00573 00574 modehandlers[handler_id]->ChangeCount(adding ? 1 : -1); 00575 00576 /* Is there a valid parameter for this mode? If so add it to the parameter list */ 00577 if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty())) 00578 { 00579 parameter_list << " " << parameter; 00580 parameter_count++; 00581 /* Does this mode have a prefix? */ 00582 if (modehandlers[handler_id]->GetPrefix() && targetchannel) 00583 { 00584 userrec* user_to_prefix = ServerInstance->FindNick(parameter); 00585 if (user_to_prefix) 00586 targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(), 00587 modehandlers[handler_id]->GetPrefixRank(), adding); 00588 } 00589 } 00590 00591 /* Call all the AfterMode events in the mode watchers for this mode */ 00592 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) 00593 (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type); 00594 00595 /* Reset the state change flag */ 00596 state_change = false; 00597 00598 if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100) 00599 || (parameter_count > MAXMODES)) 00600 { 00601 /* We cant have a mode sequence this long */ 00602 letter = mode_sequence.end() - 1; 00603 continue; 00604 } 00605 } 00606 } 00607 } 00608 else 00609 { 00610 /* No mode handler? Unknown mode character then. */ 00611 user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick, modechar); 00612 } 00613 break; 00614 } 00615 } 00616 00617 /* Was there at least one valid mode in the sequence? */ 00618 if (!output_sequence.empty()) 00619 { 00620 if (servermode) 00621 { 00622 if (type == MODETYPE_CHANNEL) 00623 { 00624 targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str()); 00625 this->LastParse = targetchannel->name; 00626 } 00627 else 00628 { 00629 targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str()); 00630 this->LastParse = targetuser->nick; 00631 } 00632 } 00633 else 00634 { 00635 if (type == MODETYPE_CHANNEL) 00636 { 00637 targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str()); 00638 FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str())); 00639 this->LastParse = targetchannel->name; 00640 } 00641 else 00642 { 00643 user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str()); 00644 FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str())); 00645 this->LastParse = targetuser->nick; 00646 } 00647 } 00648 00649 LastParse.append(" "); 00650 LastParse.append(output_sequence); 00651 LastParse.append(parameter_list.str()); 00652 } 00653 } 00654 }
|
|
||||||||||||||||
|
Revoke a built in privilage (e.g. ops, halfops, voice) to a user on a channel Definition at line 213 of file mode.cpp. References userrec::chans, userrec::nick, UCMODE_HOP, UCMODE_OP, and UCMODE_VOICE. 00214 { 00215 if (!chan) 00216 return ""; 00217 00218 UCListIter n = d->chans.find(chan); 00219 if (n != d->chans.end()) 00220 { 00221 if ((n->second & MASK) == 0) 00222 { 00223 return ""; 00224 } 00225 n->second ^= MASK; 00226 switch (MASK) 00227 { 00228 case UCMODE_OP: 00229 n->first->DelOppedUser(d); 00230 break; 00231 case UCMODE_HOP: 00232 n->first->DelHalfoppedUser(d); 00233 break; 00234 case UCMODE_VOICE: 00235 n->first->DelVoicedUser(d); 00236 break; 00237 } 00238 return d->nick; 00239 } 00240 return ""; 00241 }
|
|
||||||||||||||||||||
|
Used to check if user 'd' should be allowed to do operation 'MASK' on channel 'chan'. for example, should 'user A' be able to 'op' on 'channel B'. Definition at line 167 of file mode.cpp. References InspIRCd::FindNick(), userrec::nick, ServerInstance, and userrec::WriteServ(). 00168 { 00169 userrec *d; 00170 if ((!user) || (!dest) || (!chan) || (!*dest)) 00171 { 00172 return NULL; 00173 } 00174 d = ServerInstance->FindNick(dest); 00175 if (!d) 00176 { 00177 user->WriteServ("401 %s %s :No such nick/channel",user->nick, dest); 00178 return NULL; 00179 } 00180 return d; 00181 }
|
|
|
Returns a list of mode characters which are usermodes. This is used in the 004 numeric when users connect. Definition at line 772 of file mode.cpp. References MASK_USER, and modehandlers. Referenced by userrec::FullConnect(). 00773 { 00774 char modestr[256]; 00775 int pointer = 0; 00776 00777 for (unsigned char mode = 'A'; mode <= 'z'; mode++) 00778 { 00779 unsigned char pos = (mode-65) | MASK_USER; 00780 00781 if (modehandlers[pos]) 00782 modestr[pointer++] = mode; 00783 } 00784 modestr[pointer++] = 0; 00785 return modestr; 00786 }
|
|
|
The string representing the last set of modes to be parsed. Use GetLastParse() to get this value, to be used for display purposes. Definition at line 395 of file mode.h. Referenced by GetLastParse(), ModeParser(), and Process(). |
|
|
Mode handlers for each mode, to access a handler subtract 65 from the ascii value of the mode letter. The upper bit of the value indicates if its a usermode or a channel mode, so we have 256 of them not 64. Definition at line 381 of file mode.h. Referenced by AddMode(), BuildPrefixes(), ChanModes(), ChannelModeList(), DelMode(), FindMode(), FindPrefix(), ModeParser(), ModeString(), ParaModeList(), Process(), and UserModeList(). |
|
|
Mode watcher classes arranged in the same way as the mode handlers, except for instead of having 256 of them we have 256 lists of them.
Definition at line 386 of file mode.h. Referenced by AddModeWatcher(), DelModeWatcher(), ModeParser(), and Process(). |
|
|
Creator/owner pointer.
Definition at line 375 of file mode.h. Referenced by BuildPrefixes(), ChanModes(), ChannelModeList(), DelMode(), ParaModeList(), Process(), and SanityChecks(). |