1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2008 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
14 /* $Core: libIRCDmode */
15 /* $ExtraDeps: $(RELCPPFILES) */
16 /* $ExtraObjects: modes/modeclasses.a */
17 /* $ExtraBuild: @${MAKE} -C "modes" DIRNAME="src/modes" CC="$(CC)" $(MAKEARGS) CPPFILES="$(CPPFILES)" */
20 #include "inspstring.h"
23 #include "modes/cmode_s.h"
25 #include "modes/cmode_p.h"
27 #include "modes/cmode_b.h"
29 #include "modes/cmode_m.h"
30 /* +t (only (half) ops can change topic) */
31 #include "modes/cmode_t.h"
32 /* +n (no external messages) */
33 #include "modes/cmode_n.h"
34 /* +i (invite only) */
35 #include "modes/cmode_i.h"
36 /* +k (keyed channel) */
37 #include "modes/cmode_k.h"
38 /* +l (channel user limit) */
39 #include "modes/cmode_l.h"
41 #include "modes/cmode_o.h"
42 /* +h (channel halfop) */
43 #include "modes/cmode_h.h"
44 /* +v (channel voice) */
45 #include "modes/cmode_v.h"
46 /* +s (server notices) */
47 #include "modes/umode_s.h"
48 /* +w (see wallops) */
49 #include "modes/umode_w.h"
51 #include "modes/umode_i.h"
53 #include "modes/umode_o.h"
54 /* +n (notice mask - our implementation of snomasks) */
55 #include "modes/umode_n.h"
57 ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix, char prefixrequired)
58 : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly), prefix(mprefix), count(0), prefixneeded(prefixrequired)
62 ModeHandler::~ModeHandler()
66 bool ModeHandler::IsListMode()
71 char ModeHandler::GetNeededPrefix()
76 void ModeHandler::SetNeededPrefix(char needsprefix)
78 prefixneeded = needsprefix;
81 unsigned int ModeHandler::GetPrefixRank()
86 unsigned int ModeHandler::GetCount()
91 void ModeHandler::ChangeCount(int modifier)
94 ServerInstance->Log(DEBUG,"Change count for mode %c is now %d", mode, count);
97 ModeType ModeHandler::GetModeType()
102 bool ModeHandler::NeedsOper()
107 char ModeHandler::GetPrefix()
112 int ModeHandler::GetNumParams(bool adding)
114 return adding ? n_params_on : n_params_off;
117 char ModeHandler::GetModeChar()
122 ModeAction ModeHandler::OnModeChange(User*, User*, Channel*, std::string&, bool)
124 return MODEACTION_DENY;
127 ModePair ModeHandler::ModeSet(User*, User* dest, Channel* channel, const std::string&)
131 return std::make_pair(dest->IsModeSet(this->mode), "");
135 return std::make_pair(channel->IsModeSet(this->mode), "");
139 void ModeHandler::DisplayList(User*, Channel*)
143 void ModeHandler::DisplayEmptyList(User*, Channel*)
147 bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string&, const std::string&, Channel*)
149 return (ours < theirs);
152 ModeWatcher::ModeWatcher(InspIRCd* Instance, char modeletter, ModeType type) : ServerInstance(Instance), mode(modeletter), m_type(type)
156 ModeWatcher::~ModeWatcher()
160 char ModeWatcher::GetModeChar()
165 ModeType ModeWatcher::GetModeType()
170 bool ModeWatcher::BeforeMode(User*, User*, Channel*, std::string&, bool, ModeType)
175 void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool, ModeType)
179 User* ModeParser::SanityChecks(User *user, const char *dest, Channel *chan, int)
182 if ((!user) || (!dest) || (!chan) || (!*dest))
186 d = ServerInstance->FindNick(dest);
189 user->WriteServ("401 %s %s :No such nick/channel",user->nick, dest);
195 const char* ModeParser::Grant(User *d,Channel *chan,int MASK)
200 UCListIter n = d->chans.find(chan);
201 if (n != d->chans.end())
203 if (n->second & MASK)
207 n->second = n->second | MASK;
211 n->first->AddOppedUser(d);
214 n->first->AddHalfoppedUser(d);
217 n->first->AddVoicedUser(d);
225 const char* ModeParser::Revoke(User *d,Channel *chan,int MASK)
230 UCListIter n = d->chans.find(chan);
231 if (n != d->chans.end())
233 if ((n->second & MASK) == 0)
241 n->first->DelOppedUser(d);
244 n->first->DelHalfoppedUser(d);
247 n->first->DelVoicedUser(d);
255 void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targetchannel, const char* text)
259 /* Display channel's current mode string */
260 user->WriteServ("324 %s %s +%s",user->nick, targetchannel->name, targetchannel->ChanModes(targetchannel->HasUser(user)));
261 user->WriteServ("329 %s %s %lu", user->nick, targetchannel->name, (unsigned long)targetchannel->age);
266 if (targetuser->Visibility && !targetuser->Visibility->VisibleTo(user))
268 user->WriteServ("401 %s %s :No such nick/channel",user->nick, text);
272 if ((targetuser == user) || (IS_OPER(user)))
274 /* Display user's current mode string */
275 user->WriteServ("221 %s :+%s",targetuser->nick,targetuser->FormatModes());
276 if (IS_OPER(targetuser))
277 user->WriteServ("008 %s +%s :Server notice mask", targetuser->nick, targetuser->FormatNoticeMasks());
282 user->WriteServ("502 %s :Can't change mode for other users", user->nick);
287 /* No such nick/channel */
288 user->WriteServ("401 %s %s :No such nick/channel",user->nick, text);
292 void ModeParser::Process(const char** parameters, int pcnt, User *user, bool servermode)
294 std::string target = parameters[0];
295 ModeType type = MODETYPE_USER;
296 unsigned char mask = 0;
297 Channel* targetchannel = ServerInstance->FindChan(parameters[0]);
298 User* targetuser = ServerInstance->FindNick(parameters[0]);
302 /* Special case for displaying the list for listmodes,
303 * e.g. MODE #chan b, or MODE #chan +b without a parameter
305 if ((targetchannel) && (pcnt == 2))
307 const char* mode = parameters[1];
308 int nonlistmodes_found = 0;
313 memset(&sent, 0, 256);
315 while (mode && *mode)
317 unsigned char mletter = *mode;
325 /* Ensure the user doesnt request the same mode twice,
326 * so they cant flood themselves off out of idiocy.
330 sent[mletter] = true;
338 ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL);
341 if ((mh) && (mh->IsListMode()))
344 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, *mode, "", true, 0));
345 if (MOD_RESULT == ACR_DENY)
351 if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
353 user->WriteServ("482 %s %s :Only half-operators and above may view the +%c list",user->nick, targetchannel->name, *mode++);
354 mh->DisplayEmptyList(user, targetchannel);
358 /** See below for a description of what craq this is :D
360 unsigned char handler_id = (*mode - 65) | mask;
362 for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
364 std::string dummyparam;
366 if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL)))
371 mh->DisplayList(user, targetchannel);
374 nonlistmodes_found++;
379 /* We didnt have any modes that were non-list, we can return here */
380 if (!nonlistmodes_found)
386 this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]);
392 type = MODETYPE_CHANNEL;
395 /* Extra security checks on channel modes
396 * (e.g. are they a (half)op?
399 if ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
401 /* We don't have halfop */
403 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
404 if (MOD_RESULT == ACR_DENY)
410 type = MODETYPE_USER;
412 if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
414 user->WriteServ("502 %s :Can't change mode for other users", user->nick);
420 /* No such nick/channel */
421 user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
425 std::string mode_sequence = parameters[1];
426 std::string parameter;
427 std::ostringstream parameter_list;
428 std::string output_sequence;
429 bool adding = true, state_change = false;
430 unsigned char handler_id = 0;
431 int parameter_counter = 2; /* Index of first parameter */
432 int parameter_count = 0;
433 bool last_successful_state_change = false;
435 /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
436 if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
437 mode_sequence.insert(0, "+");
439 for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
441 unsigned char modechar = *letter;
446 * For + and - mode characters, we don't just stick the character into the output sequence.
447 * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
448 * appearing in the output sequence, we store a flag which says there was a state change,
449 * which is set on any + or -, however, the + or - that we finish on is only appended to
450 * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
453 /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
454 * however, will allow the + if it is the first item in the sequence, regardless.
456 if ((!adding) || (!output_sequence.length()))
459 if (!output_sequence.length())
460 last_successful_state_change = false;
464 if ((adding) || (!output_sequence.length()))
467 if (!output_sequence.length())
468 last_successful_state_change = true;
474 * Watch carefully for the sleight of hand trick.
475 * 65 is the ascii value of 'A'. We take this from
476 * the char we're looking at to get a number between
477 * 1 and 127. We then logic-or it to get the hashed
478 * position, dependent on wether its a channel or
479 * a user mode. This is a little stranger, but a lot
480 * faster, than using a map of pairs.
482 handler_id = (modechar - 65) | mask;
484 if (modehandlers[handler_id])
488 if (modehandlers[handler_id]->GetModeType() == type)
490 if (modehandlers[handler_id]->GetNumParams(adding))
492 /* This mode expects a parameter, do we have any parameters left in our list to use? */
493 if (parameter_counter < pcnt)
495 parameter = parameters[parameter_counter++];
498 if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
503 /* No parameter, continue to the next mode */
509 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, parameter, adding, 1));
510 if (MOD_RESULT == ACR_DENY)
513 if (MOD_RESULT != ACR_ALLOW)
515 /* Check access to this mode character */
516 if ((type == MODETYPE_CHANNEL) && (modehandlers[handler_id]->GetNeededPrefix()))
518 char needed = modehandlers[handler_id]->GetNeededPrefix();
519 ModeHandler* prefixmode = FindPrefix(needed);
522 unsigned int neededrank = prefixmode->GetPrefixRank();
524 /* Compare our rank on the channel against the rank of the required prefix,
525 * allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
526 * in NAMES(X) are not in rank order, we know the most powerful mode is listed
527 * first, so we don't need to iterate, we just look up the first instead.
529 std::string modestring = targetchannel->GetAllPrefixChars(user);
530 if (!modestring.empty())
532 ModeHandler* ourmode = FindPrefix(modestring[0]);
533 if (!ourmode || ourmode->GetPrefixRank() < neededrank)
536 user->WriteServ("482 %s %s :You require channel privilege '%c' or above to execute channel mode '%c'",
537 user->nick, targetchannel->name, needed, modechar);
545 bool had_parameter = !parameter.empty();
547 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
549 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
554 /* A module whacked the parameter completely, and there was one. abort. */
555 if ((had_parameter) && (parameter.empty()))
568 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, "", adding, 0));
569 if (MOD_RESULT == ACR_DENY)
572 /* Fix by brain: mode watchers not being called for parameterless modes */
573 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
575 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
586 /* It's an oper only mode, check if theyre an oper. If they arent,
587 * eat any parameter that came with the mode, and continue to next
589 if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user)))
591 user->WriteServ("481 %s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick,
592 adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
593 modehandlers[handler_id]->GetModeChar());
597 /* Call the handler for the mode */
598 ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
600 if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
602 /* The handler nuked the parameter and they are supposed to have one.
603 * We CANT continue now, even if they actually returned MODEACTION_ALLOW,
604 * so we bail to the next mode character.
609 if (ma == MODEACTION_ALLOW)
611 /* We're about to output a valid mode letter - was there previously a pending state-change? */
614 if (adding != last_successful_state_change)
615 output_sequence.append(adding ? "+" : "-");
616 last_successful_state_change = adding;
619 /* Add the mode letter */
620 output_sequence.push_back(modechar);
622 modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
624 /* Is there a valid parameter for this mode? If so add it to the parameter list */
625 if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
627 parameter_list << " " << parameter;
629 /* Does this mode have a prefix? */
630 if (modehandlers[handler_id]->GetPrefix() && targetchannel)
632 User* user_to_prefix = ServerInstance->FindNick(parameter);
634 targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
635 modehandlers[handler_id]->GetPrefixRank(), adding);
639 /* Call all the AfterMode events in the mode watchers for this mode */
640 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
641 (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type);
643 /* Reset the state change flag */
644 state_change = false;
646 if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
647 || (parameter_count > MAXMODES))
649 /* We cant have a mode sequence this long */
650 letter = mode_sequence.end() - 1;
658 /* No mode handler? Unknown mode character then. */
659 user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick, modechar);
665 /* Was there at least one valid mode in the sequence? */
666 if (!output_sequence.empty())
670 if (type == MODETYPE_CHANNEL)
672 targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str());
673 this->LastParse = targetchannel->name;
677 targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
678 this->LastParse = targetuser->nick;
683 if (type == MODETYPE_CHANNEL)
685 targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
686 FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
687 this->LastParse = targetchannel->name;
691 user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
692 FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
693 this->LastParse = targetuser->nick;
697 LastParse.append(" ");
698 LastParse.append(output_sequence);
699 LastParse.append(parameter_list.str());
704 const std::string& ModeParser::GetLastParse()
709 void ModeParser::CleanMask(std::string &mask)
711 std::string::size_type pos_of_pling = mask.find_first_of('!');
712 std::string::size_type pos_of_at = mask.find_first_of('@');
713 std::string::size_type pos_of_dot = mask.find_first_of('.');
714 std::string::size_type pos_of_colon = mask.find_first_of(':'); /* Because ipv6 addresses are colon delimited */
716 if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos))
718 /* Just a nick, or just a host */
719 if ((pos_of_dot == std::string::npos) && (pos_of_colon == std::string::npos))
721 /* It has no '.' in it, it must be a nick. */
726 /* Got a dot in it? Has to be a host */
727 mask = "*!*@" + mask;
730 else if ((pos_of_pling == std::string::npos) && (pos_of_at != std::string::npos))
732 /* Has an @ but no !, its a user@host */
735 else if ((pos_of_pling != std::string::npos) && (pos_of_at == std::string::npos))
737 /* Has a ! but no @, it must be a nick!ident */
742 bool ModeParser::AddMode(ModeHandler* mh)
744 unsigned char mask = 0;
745 unsigned char pos = 0;
747 /* Yes, i know, this might let people declare modes like '_' or '^'.
748 * If they do that, thats their problem, and if i ever EVER see an
749 * official InspIRCd developer do that, i'll beat them with a paddle!
751 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126))
754 /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
755 * A mode prefix of ':' will fuck up both server to server, and client to server.
756 * A mode prefix of '#' will mess up /whois and /privmsg
758 if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':') || (mh->GetPrefix() == '#'))
761 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
762 pos = (mh->GetModeChar()-65) | mask;
764 if (modehandlers[pos])
767 modehandlers[pos] = mh;
771 bool ModeParser::DelMode(ModeHandler* mh)
773 unsigned char mask = 0;
774 unsigned char pos = 0;
776 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
779 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
780 pos = (mh->GetModeChar()-65) | mask;
782 if (!modehandlers[pos])
785 switch (mh->GetModeType())
788 for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++)
790 mh->RemoveMode(i->second);
793 case MODETYPE_CHANNEL:
794 for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
796 mh->RemoveMode(i->second);
801 modehandlers[pos] = NULL;
806 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
808 unsigned char mask = 0;
809 unsigned char pos = 0;
811 if ((modeletter < 'A') || (modeletter > 'z'))
814 mt == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
815 pos = (modeletter-65) | mask;
817 return modehandlers[pos];
820 std::string ModeParser::UserModeList()
825 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
827 unsigned char pos = (mode-65) | MASK_USER;
829 if (modehandlers[pos])
830 modestr[pointer++] = mode;
832 modestr[pointer++] = 0;
836 std::string ModeParser::ChannelModeList()
841 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
843 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
846 unsigned char pos = (mode-65) | MASK_CHANNEL;
848 if (modehandlers[pos])
849 modestr[pointer++] = mode;
851 modestr[pointer++] = 0;
855 std::string ModeParser::ParaModeList()
860 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
862 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
865 unsigned char pos = (mode-65) | MASK_CHANNEL;
867 if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
868 modestr[pointer++] = mode;
870 modestr[pointer++] = 0;
874 ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
876 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
878 unsigned char pos = (mode-65) | MASK_CHANNEL;
880 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter))
882 return modehandlers[pos];
888 std::string ModeParser::ModeString(User* user, Channel* channel)
893 if (!channel || !user)
896 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
898 unsigned char pos = (mode-65) | MASK_CHANNEL;
899 ModeHandler* mh = modehandlers[pos];
900 if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
903 ret = mh->ModeSet(NULL, user, channel, user->nick);
904 if ((ret.first) && (ret.second == user->nick))
907 pars.append(user->nick);
908 types.push_back(mh->GetModeChar());
916 std::string ModeParser::ChanModes()
918 std::string type1; /* Listmodes EXCEPT those with a prefix */
919 std::string type2; /* Modes that take a param when adding or removing */
920 std::string type3; /* Modes that only take a param when adding */
921 std::string type4; /* Modes that dont take a param */
923 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
925 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
928 unsigned char pos = (mode-65) | MASK_CHANNEL;
929 /* One parameter when adding */
930 if (modehandlers[pos])
932 if (modehandlers[pos]->GetNumParams(true))
934 if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
936 type1 += modehandlers[pos]->GetModeChar();
940 /* ... and one parameter when removing */
941 if (modehandlers[pos]->GetNumParams(false))
943 /* But not a list mode */
944 if (!modehandlers[pos]->GetPrefix())
946 type2 += modehandlers[pos]->GetModeChar();
951 /* No parameters when removing */
952 type3 += modehandlers[pos]->GetModeChar();
958 type4 += modehandlers[pos]->GetModeChar();
964 return type1 + "," + type2 + "," + type3 + "," + type4;
967 bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
969 return one.second > two.second;
972 std::string ModeParser::BuildPrefixes()
974 std::string mletters;
975 std::string mprefixes;
977 std::map<char,char> prefix_to_mode;
979 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
981 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
984 unsigned char pos = (mode-65) | MASK_CHANNEL;
986 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
988 pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank()));
989 prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar();
993 sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison);
995 for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++)
997 mletters = mletters + n->first;
998 mprefixes = mprefixes + prefix_to_mode.find(n->first)->second;
1001 return "(" + mprefixes + ")" + mletters;
1004 bool ModeParser::AddModeWatcher(ModeWatcher* mw)
1006 unsigned char mask = 0;
1007 unsigned char pos = 0;
1012 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1015 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1016 pos = (mw->GetModeChar()-65) | mask;
1018 modewatchers[pos].push_back(mw);
1023 bool ModeParser::DelModeWatcher(ModeWatcher* mw)
1025 unsigned char mask = 0;
1026 unsigned char pos = 0;
1031 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1034 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1035 pos = (mw->GetModeChar()-65) | mask;
1037 ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
1039 if (a == modewatchers[pos].end())
1044 modewatchers[pos].erase(a);
1049 /** This default implementation can remove simple user modes
1051 void ModeHandler::RemoveMode(User* user)
1053 char moderemove[MAXBUF];
1054 const char* parameters[] = { user->nick, moderemove };
1056 if (user->IsModeSet(this->GetModeChar()))
1058 sprintf(moderemove,"-%c",this->GetModeChar());
1059 ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
1063 /** This default implementation can remove simple channel modes
1066 void ModeHandler::RemoveMode(Channel* channel)
1068 char moderemove[MAXBUF];
1069 const char* parameters[] = { channel->name, moderemove };
1071 if (channel->IsModeSet(this->GetModeChar()))
1073 sprintf(moderemove,"-%c",this->GetModeChar());
1074 ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
1078 ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
1080 ModeHandler* modes[] =
1082 new ModeChannelSecret(Instance),
1083 new ModeChannelPrivate(Instance),
1084 new ModeChannelModerated(Instance),
1085 new ModeChannelTopicOps(Instance),
1086 new ModeChannelNoExternal(Instance),
1087 new ModeChannelInviteOnly(Instance),
1088 new ModeChannelKey(Instance),
1089 new ModeChannelLimit(Instance),
1090 new ModeChannelBan(Instance),
1091 new ModeChannelOp(Instance),
1092 new ModeChannelHalfOp(Instance),
1093 new ModeChannelVoice(Instance),
1094 new ModeUserServerNotice(Instance),
1095 new ModeUserWallops(Instance),
1096 new ModeUserInvisible(Instance),
1097 new ModeUserOperator(Instance),
1098 new ModeUserServerNoticeMask(Instance),
1102 /* Clear mode list */
1103 memset(modehandlers, 0, sizeof(modehandlers));
1104 memset(modewatchers, 0, sizeof(modewatchers));
1106 /* Last parse string */
1109 /* Initialise the RFC mode letters */
1110 for (int index = 0; modes[index]; index++)
1111 this->AddMode(modes[index]);