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)
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)
62 ModeHandler::~ModeHandler()
66 bool ModeHandler::IsListMode()
71 unsigned int ModeHandler::GetPrefixRank()
76 unsigned int ModeHandler::GetCount()
81 void ModeHandler::ChangeCount(int modifier)
84 ServerInstance->Log(DEBUG,"Change count for mode %c is now %d", mode, count);
87 ModeType ModeHandler::GetModeType()
92 bool ModeHandler::NeedsOper()
97 char ModeHandler::GetPrefix()
102 int ModeHandler::GetNumParams(bool adding)
104 return adding ? n_params_on : n_params_off;
107 char ModeHandler::GetModeChar()
112 ModeAction ModeHandler::OnModeChange(User*, User*, Channel*, std::string&, bool)
114 return MODEACTION_DENY;
117 ModePair ModeHandler::ModeSet(User*, User* dest, Channel* channel, const std::string&)
121 return std::make_pair(dest->IsModeSet(this->mode), "");
125 return std::make_pair(channel->IsModeSet(this->mode), "");
129 void ModeHandler::DisplayList(User*, Channel*)
133 void ModeHandler::DisplayEmptyList(User*, Channel*)
137 bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string&, const std::string&, Channel*)
139 return (ours < theirs);
142 ModeWatcher::ModeWatcher(InspIRCd* Instance, char modeletter, ModeType type) : ServerInstance(Instance), mode(modeletter), m_type(type)
146 ModeWatcher::~ModeWatcher()
150 char ModeWatcher::GetModeChar()
155 ModeType ModeWatcher::GetModeType()
160 bool ModeWatcher::BeforeMode(User*, User*, Channel*, std::string&, bool, ModeType)
165 void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool, ModeType)
169 User* ModeParser::SanityChecks(User *user, const char *dest, Channel *chan, int)
172 if ((!user) || (!dest) || (!chan) || (!*dest))
176 d = ServerInstance->FindNick(dest);
179 user->WriteServ("401 %s %s :No such nick/channel",user->nick, dest);
185 const char* ModeParser::Grant(User *d,Channel *chan,int MASK)
190 UCListIter n = d->chans.find(chan);
191 if (n != d->chans.end())
193 if (n->second & MASK)
197 n->second = n->second | MASK;
201 n->first->AddOppedUser(d);
204 n->first->AddHalfoppedUser(d);
207 n->first->AddVoicedUser(d);
215 const char* ModeParser::Revoke(User *d,Channel *chan,int MASK)
220 UCListIter n = d->chans.find(chan);
221 if (n != d->chans.end())
223 if ((n->second & MASK) == 0)
231 n->first->DelOppedUser(d);
234 n->first->DelHalfoppedUser(d);
237 n->first->DelVoicedUser(d);
245 void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targetchannel, const char* text)
249 /* Display channel's current mode string */
250 user->WriteServ("324 %s %s +%s",user->nick, targetchannel->name, targetchannel->ChanModes(targetchannel->HasUser(user)));
251 user->WriteServ("329 %s %s %lu", user->nick, targetchannel->name, (unsigned long)targetchannel->age);
256 if (targetuser->Visibility && !targetuser->Visibility->VisibleTo(user))
258 user->WriteServ("401 %s %s :No such nick/channel",user->nick, text);
262 if ((targetuser == user) || (IS_OPER(user)))
264 /* Display user's current mode string */
265 user->WriteServ("221 %s :+%s",targetuser->nick,targetuser->FormatModes());
266 if (IS_OPER(targetuser))
267 user->WriteServ("008 %s +%s :Server notice mask", targetuser->nick, targetuser->FormatNoticeMasks());
272 user->WriteServ("502 %s :Can't change mode for other users", user->nick);
277 /* No such nick/channel */
278 user->WriteServ("401 %s %s :No such nick/channel",user->nick, text);
282 void ModeParser::Process(const char** parameters, int pcnt, User *user, bool servermode)
284 std::string target = parameters[0];
285 ModeType type = MODETYPE_USER;
286 unsigned char mask = 0;
287 Channel* targetchannel = ServerInstance->FindChan(parameters[0]);
288 User* targetuser = ServerInstance->FindNick(parameters[0]);
292 /* Special case for displaying the list for listmodes,
293 * e.g. MODE #chan b, or MODE #chan +b without a parameter
295 if ((targetchannel) && (pcnt == 2))
297 const char* mode = parameters[1];
298 int nonlistmodes_found = 0;
303 memset(&sent, 0, 256);
305 while (mode && *mode)
307 unsigned char mletter = *mode;
310 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, *mode, "", true, 0));
311 if (MOD_RESULT == ACR_DENY)
320 /* Ensure the user doesnt request the same mode twice,
321 * so they cant flood themselves off out of idiocy.
325 sent[mletter] = true;
333 ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL);
336 if ((mh) && (mh->IsListMode()))
338 if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
340 user->WriteServ("482 %s %s :Only half-operators and above may view the +%c list",user->nick, targetchannel->name, *mode++);
341 mh->DisplayEmptyList(user, targetchannel);
345 /** See below for a description of what craq this is :D
347 unsigned char handler_id = (*mode - 65) | mask;
349 for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
351 std::string dummyparam;
353 if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL)))
358 mh->DisplayList(user, targetchannel);
361 nonlistmodes_found++;
366 /* We didnt have any modes that were non-list, we can return here */
367 if (!nonlistmodes_found)
373 this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]);
379 type = MODETYPE_CHANNEL;
382 /* Extra security checks on channel modes
383 * (e.g. are they a (half)op?
386 if ((IS_LOCAL(user)) && (targetchannel->GetStatus(user) < STATUS_HOP))
388 /* We don't have halfop */
390 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
391 if (MOD_RESULT == ACR_DENY)
394 if (MOD_RESULT == ACR_DEFAULT)
396 /* Are we a uline or is it a servermode? */
397 if ((!ServerInstance->ULine(user->server)) && (!servermode))
399 /* Not enough permission:
400 * NOT a uline and NOT a servermode,
401 * OR, NOT halfop or above.
403 user->WriteServ("482 %s %s :You're not a channel %soperator",user->nick, targetchannel->name,
404 ServerInstance->Config->AllowHalfop ? "(half)" : "");
412 type = MODETYPE_USER;
414 if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
416 user->WriteServ("502 %s :Can't change mode for other users", user->nick);
422 /* No such nick/channel */
423 user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
427 std::string mode_sequence = parameters[1];
428 std::string parameter;
429 std::ostringstream parameter_list;
430 std::string output_sequence;
431 bool adding = true, state_change = false;
432 unsigned char handler_id = 0;
433 int parameter_counter = 2; /* Index of first parameter */
434 int parameter_count = 0;
435 bool last_successful_state_change = false;
437 /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
438 if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
439 mode_sequence.insert(0, "+");
441 for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
443 unsigned char modechar = *letter;
448 * For + and - mode characters, we don't just stick the character into the output sequence.
449 * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
450 * appearing in the output sequence, we store a flag which says there was a state change,
451 * which is set on any + or -, however, the + or - that we finish on is only appended to
452 * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
455 /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
456 * however, will allow the + if it is the first item in the sequence, regardless.
458 if ((!adding) || (!output_sequence.length()))
461 if (!output_sequence.length())
462 last_successful_state_change = false;
466 if ((adding) || (!output_sequence.length()))
469 if (!output_sequence.length())
470 last_successful_state_change = true;
476 * Watch carefully for the sleight of hand trick.
477 * 65 is the ascii value of 'A'. We take this from
478 * the char we're looking at to get a number between
479 * 1 and 127. We then logic-or it to get the hashed
480 * position, dependent on wether its a channel or
481 * a user mode. This is a little stranger, but a lot
482 * faster, than using a map of pairs.
484 handler_id = (modechar - 65) | mask;
486 if (modehandlers[handler_id])
490 if (modehandlers[handler_id]->GetModeType() == type)
492 if (modehandlers[handler_id]->GetNumParams(adding))
494 /* This mode expects a parameter, do we have any parameters left in our list to use? */
495 if (parameter_counter < pcnt)
497 parameter = parameters[parameter_counter++];
500 if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
505 /* No parameter, continue to the next mode */
510 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, parameter, adding, 1));
511 if (MOD_RESULT == ACR_DENY)
514 bool had_parameter = !parameter.empty();
516 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
518 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
523 /* A module whacked the parameter completely, and there was one. abort. */
524 if ((had_parameter) && (parameter.empty()))
537 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, "", adding, 0));
538 if (MOD_RESULT == ACR_DENY)
541 /* Fix by brain: mode watchers not being called for parameterless modes */
542 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
544 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
555 /* It's an oper only mode, check if theyre an oper. If they arent,
556 * eat any parameter that came with the mode, and continue to next
558 if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user)))
560 user->WriteServ("481 %s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick,
561 adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
562 modehandlers[handler_id]->GetModeChar());
566 /* Call the handler for the mode */
567 ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
569 if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
571 /* The handler nuked the parameter and they are supposed to have one.
572 * We CANT continue now, even if they actually returned MODEACTION_ALLOW,
573 * so we bail to the next mode character.
578 if (ma == MODEACTION_ALLOW)
580 /* We're about to output a valid mode letter - was there previously a pending state-change? */
583 if (adding != last_successful_state_change)
584 output_sequence.append(adding ? "+" : "-");
585 last_successful_state_change = adding;
588 /* Add the mode letter */
589 output_sequence.push_back(modechar);
591 modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
593 /* Is there a valid parameter for this mode? If so add it to the parameter list */
594 if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
596 parameter_list << " " << parameter;
598 /* Does this mode have a prefix? */
599 if (modehandlers[handler_id]->GetPrefix() && targetchannel)
601 User* user_to_prefix = ServerInstance->FindNick(parameter);
603 targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
604 modehandlers[handler_id]->GetPrefixRank(), adding);
608 /* Call all the AfterMode events in the mode watchers for this mode */
609 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
610 (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type);
612 /* Reset the state change flag */
613 state_change = false;
615 if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
616 || (parameter_count > MAXMODES))
618 /* We cant have a mode sequence this long */
619 letter = mode_sequence.end() - 1;
627 /* No mode handler? Unknown mode character then. */
628 user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick, modechar);
634 /* Was there at least one valid mode in the sequence? */
635 if (!output_sequence.empty())
639 if (type == MODETYPE_CHANNEL)
641 targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str());
642 this->LastParse = targetchannel->name;
646 targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
647 this->LastParse = targetuser->nick;
652 if (type == MODETYPE_CHANNEL)
654 targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
655 FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
656 this->LastParse = targetchannel->name;
660 user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
661 FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
662 this->LastParse = targetuser->nick;
666 LastParse.append(" ");
667 LastParse.append(output_sequence);
668 LastParse.append(parameter_list.str());
673 const std::string& ModeParser::GetLastParse()
678 void ModeParser::CleanMask(std::string &mask)
680 std::string::size_type pos_of_pling = mask.find_first_of('!');
681 std::string::size_type pos_of_at = mask.find_first_of('@');
682 std::string::size_type pos_of_dot = mask.find_first_of('.');
683 std::string::size_type pos_of_colon = mask.find_first_of(':'); /* Because ipv6 addresses are colon delimited */
685 if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos))
687 /* Just a nick, or just a host */
688 if ((pos_of_dot == std::string::npos) && (pos_of_colon == std::string::npos))
690 /* It has no '.' in it, it must be a nick. */
695 /* Got a dot in it? Has to be a host */
696 mask = "*!*@" + mask;
699 else if ((pos_of_pling == std::string::npos) && (pos_of_at != std::string::npos))
701 /* Has an @ but no !, its a user@host */
704 else if ((pos_of_pling != std::string::npos) && (pos_of_at == std::string::npos))
706 /* Has a ! but no @, it must be a nick!ident */
711 bool ModeParser::AddMode(ModeHandler* mh)
713 unsigned char mask = 0;
714 unsigned char pos = 0;
716 /* Yes, i know, this might let people declare modes like '_' or '^'.
717 * If they do that, thats their problem, and if i ever EVER see an
718 * official InspIRCd developer do that, i'll beat them with a paddle!
720 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126))
723 /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
724 * A mode prefix of ':' will fuck up both server to server, and client to server.
725 * A mode prefix of '#' will mess up /whois and /privmsg
727 if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':') || (mh->GetPrefix() == '#'))
730 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
731 pos = (mh->GetModeChar()-65) | mask;
733 if (modehandlers[pos])
736 modehandlers[pos] = mh;
740 bool ModeParser::DelMode(ModeHandler* mh)
742 unsigned char mask = 0;
743 unsigned char pos = 0;
745 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
748 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
749 pos = (mh->GetModeChar()-65) | mask;
751 if (!modehandlers[pos])
754 switch (mh->GetModeType())
757 for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
759 mh->RemoveMode(i->second);
762 case MODETYPE_CHANNEL:
763 for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
765 mh->RemoveMode(i->second);
770 modehandlers[pos] = NULL;
775 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
777 unsigned char mask = 0;
778 unsigned char pos = 0;
780 if ((modeletter < 'A') || (modeletter > 'z'))
783 mt == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
784 pos = (modeletter-65) | mask;
786 return modehandlers[pos];
789 std::string ModeParser::UserModeList()
794 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
796 unsigned char pos = (mode-65) | MASK_USER;
798 if (modehandlers[pos])
799 modestr[pointer++] = mode;
801 modestr[pointer++] = 0;
805 std::string ModeParser::ChannelModeList()
810 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
812 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
815 unsigned char pos = (mode-65) | MASK_CHANNEL;
817 if (modehandlers[pos])
818 modestr[pointer++] = mode;
820 modestr[pointer++] = 0;
824 std::string ModeParser::ParaModeList()
829 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
831 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
834 unsigned char pos = (mode-65) | MASK_CHANNEL;
836 if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
837 modestr[pointer++] = mode;
839 modestr[pointer++] = 0;
843 ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
845 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
847 unsigned char pos = (mode-65) | MASK_CHANNEL;
849 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter))
851 return modehandlers[pos];
857 std::string ModeParser::ModeString(User* user, Channel* channel)
862 if (!channel || !user)
865 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
867 unsigned char pos = (mode-65) | MASK_CHANNEL;
868 ModeHandler* mh = modehandlers[pos];
869 if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
872 ret = mh->ModeSet(NULL, user, channel, user->nick);
873 if ((ret.first) && (ret.second == user->nick))
876 pars.append(user->nick);
877 types.push_back(mh->GetModeChar());
885 std::string ModeParser::ChanModes()
887 std::string type1; /* Listmodes EXCEPT those with a prefix */
888 std::string type2; /* Modes that take a param when adding or removing */
889 std::string type3; /* Modes that only take a param when adding */
890 std::string type4; /* Modes that dont take a param */
892 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
894 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
897 unsigned char pos = (mode-65) | MASK_CHANNEL;
898 /* One parameter when adding */
899 if (modehandlers[pos])
901 if (modehandlers[pos]->GetNumParams(true))
903 if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
905 type1 += modehandlers[pos]->GetModeChar();
909 /* ... and one parameter when removing */
910 if (modehandlers[pos]->GetNumParams(false))
912 /* But not a list mode */
913 if (!modehandlers[pos]->GetPrefix())
915 type2 += modehandlers[pos]->GetModeChar();
920 /* No parameters when removing */
921 type3 += modehandlers[pos]->GetModeChar();
927 type4 += modehandlers[pos]->GetModeChar();
933 return type1 + "," + type2 + "," + type3 + "," + type4;
936 bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
938 return one.second > two.second;
941 std::string ModeParser::BuildPrefixes()
943 std::string mletters;
944 std::string mprefixes;
946 std::map<char,char> prefix_to_mode;
948 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
950 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
953 unsigned char pos = (mode-65) | MASK_CHANNEL;
955 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
957 pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank()));
958 prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar();
962 sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison);
964 for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++)
966 mletters = mletters + n->first;
967 mprefixes = mprefixes + prefix_to_mode.find(n->first)->second;
970 return "(" + mprefixes + ")" + mletters;
973 bool ModeParser::AddModeWatcher(ModeWatcher* mw)
975 unsigned char mask = 0;
976 unsigned char pos = 0;
981 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
984 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
985 pos = (mw->GetModeChar()-65) | mask;
987 modewatchers[pos].push_back(mw);
992 bool ModeParser::DelModeWatcher(ModeWatcher* mw)
994 unsigned char mask = 0;
995 unsigned char pos = 0;
1000 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1003 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1004 pos = (mw->GetModeChar()-65) | mask;
1006 ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
1008 if (a == modewatchers[pos].end())
1013 modewatchers[pos].erase(a);
1018 /** This default implementation can remove simple user modes
1020 void ModeHandler::RemoveMode(User* user)
1022 char moderemove[MAXBUF];
1023 const char* parameters[] = { user->nick, moderemove };
1025 if (user->IsModeSet(this->GetModeChar()))
1027 sprintf(moderemove,"-%c",this->GetModeChar());
1028 ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
1032 /** This default implementation can remove simple channel modes
1035 void ModeHandler::RemoveMode(Channel* channel)
1037 char moderemove[MAXBUF];
1038 const char* parameters[] = { channel->name, moderemove };
1040 if (channel->IsModeSet(this->GetModeChar()))
1042 sprintf(moderemove,"-%c",this->GetModeChar());
1043 ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
1047 ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
1049 ModeHandler* modes[] =
1051 new ModeChannelSecret(Instance),
1052 new ModeChannelPrivate(Instance),
1053 new ModeChannelModerated(Instance),
1054 new ModeChannelTopicOps(Instance),
1055 new ModeChannelNoExternal(Instance),
1056 new ModeChannelInviteOnly(Instance),
1057 new ModeChannelKey(Instance),
1058 new ModeChannelLimit(Instance),
1059 new ModeChannelBan(Instance),
1060 new ModeChannelOp(Instance),
1061 new ModeChannelHalfOp(Instance),
1062 new ModeChannelVoice(Instance),
1063 new ModeUserServerNotice(Instance),
1064 new ModeUserWallops(Instance),
1065 new ModeUserInvisible(Instance),
1066 new ModeUserOperator(Instance),
1067 new ModeUserServerNoticeMask(Instance),
1071 /* Clear mode list */
1072 memset(modehandlers, 0, sizeof(modehandlers));
1073 memset(modewatchers, 0, sizeof(modewatchers));
1075 /* Last parse string */
1078 /* Initialise the RFC mode letters */
1079 for (int index = 0; modes[index]; index++)
1080 this->AddMode(modes[index]);