1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2007 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;
315 /* Ensure the user doesnt request the same mode twice,
316 * so they cant flood themselves off out of idiocy.
320 sent[mletter] = true;
328 ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL);
331 if ((mh) && (mh->IsListMode()))
333 if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
335 user->WriteServ("482 %s %s :Only half-operators and above may view the +%c list",user->nick, targetchannel->name, *mode++);
336 mh->DisplayEmptyList(user, targetchannel);
340 /** See below for a description of what craq this is :D
342 unsigned char handler_id = (*mode - 65) | mask;
344 for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
346 std::string dummyparam;
348 if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL)))
353 mh->DisplayList(user, targetchannel);
356 nonlistmodes_found++;
361 /* We didnt have any modes that were non-list, we can return here */
362 if (!nonlistmodes_found)
368 this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]);
374 type = MODETYPE_CHANNEL;
377 /* Extra security checks on channel modes
378 * (e.g. are they a (half)op?
381 if ((IS_LOCAL(user)) && (targetchannel->GetStatus(user) < STATUS_HOP))
383 /* We don't have halfop */
385 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
386 if (MOD_RESULT == ACR_DENY)
389 if (MOD_RESULT == ACR_DEFAULT)
391 /* Are we a uline or is it a servermode? */
392 if ((!ServerInstance->ULine(user->server)) && (!servermode))
394 /* Not enough permission:
395 * NOT a uline and NOT a servermode,
396 * OR, NOT halfop or above.
398 user->WriteServ("482 %s %s :You're not a channel %soperator",user->nick, targetchannel->name,
399 ServerInstance->Config->AllowHalfop ? "(half)" : "");
407 type = MODETYPE_USER;
409 if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
411 user->WriteServ("502 %s :Can't change mode for other users", user->nick);
417 /* No such nick/channel */
418 user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
422 std::string mode_sequence = parameters[1];
423 std::string parameter;
424 std::ostringstream parameter_list;
425 std::string output_sequence;
426 bool adding = true, state_change = false;
427 unsigned char handler_id = 0;
428 int parameter_counter = 2; /* Index of first parameter */
429 int parameter_count = 0;
430 bool last_successful_state_change = false;
432 /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
433 if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
434 mode_sequence.insert(0, "+");
436 for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
438 unsigned char modechar = *letter;
443 * For + and - mode characters, we don't just stick the character into the output sequence.
444 * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
445 * appearing in the output sequence, we store a flag which says there was a state change,
446 * which is set on any + or -, however, the + or - that we finish on is only appended to
447 * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
450 /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
451 * however, will allow the + if it is the first item in the sequence, regardless.
453 if ((!adding) || (!output_sequence.length()))
456 if (!output_sequence.length())
457 last_successful_state_change = false;
461 if ((adding) || (!output_sequence.length()))
464 if (!output_sequence.length())
465 last_successful_state_change = true;
471 * Watch carefully for the sleight of hand trick.
472 * 65 is the ascii value of 'A'. We take this from
473 * the char we're looking at to get a number between
474 * 1 and 127. We then logic-or it to get the hashed
475 * position, dependent on wether its a channel or
476 * a user mode. This is a little stranger, but a lot
477 * faster, than using a map of pairs.
479 handler_id = (modechar - 65) | mask;
481 if (modehandlers[handler_id])
485 if (modehandlers[handler_id]->GetModeType() == type)
487 if (modehandlers[handler_id]->GetNumParams(adding))
489 /* This mode expects a parameter, do we have any parameters left in our list to use? */
490 if (parameter_counter < pcnt)
492 parameter = parameters[parameter_counter++];
495 if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
500 /* No parameter, continue to the next mode */
504 bool had_parameter = !parameter.empty();
506 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
508 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
513 /* A module whacked the parameter completely, and there was one. abort. */
514 if ((had_parameter) && (parameter.empty()))
526 /* Fix by brain: mode watchers not being called for parameterless modes */
527 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
529 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
540 /* It's an oper only mode, check if theyre an oper. If they arent,
541 * eat any parameter that came with the mode, and continue to next
543 if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user)))
545 user->WriteServ("481 %s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick,
546 adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
547 modehandlers[handler_id]->GetModeChar());
551 /* Call the handler for the mode */
552 ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
554 if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
556 /* The handler nuked the parameter and they are supposed to have one.
557 * We CANT continue now, even if they actually returned MODEACTION_ALLOW,
558 * so we bail to the next mode character.
563 if (ma == MODEACTION_ALLOW)
565 /* We're about to output a valid mode letter - was there previously a pending state-change? */
568 if (adding != last_successful_state_change)
569 output_sequence.append(adding ? "+" : "-");
570 last_successful_state_change = adding;
573 /* Add the mode letter */
574 output_sequence.push_back(modechar);
576 modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
578 /* Is there a valid parameter for this mode? If so add it to the parameter list */
579 if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
581 parameter_list << " " << parameter;
583 /* Does this mode have a prefix? */
584 if (modehandlers[handler_id]->GetPrefix() && targetchannel)
586 User* user_to_prefix = ServerInstance->FindNick(parameter);
588 targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
589 modehandlers[handler_id]->GetPrefixRank(), adding);
593 /* Call all the AfterMode events in the mode watchers for this mode */
594 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
595 (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type);
597 /* Reset the state change flag */
598 state_change = false;
600 if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
601 || (parameter_count > MAXMODES))
603 /* We cant have a mode sequence this long */
604 letter = mode_sequence.end() - 1;
612 /* No mode handler? Unknown mode character then. */
613 user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick, modechar);
619 /* Was there at least one valid mode in the sequence? */
620 if (!output_sequence.empty())
624 if (type == MODETYPE_CHANNEL)
626 targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str());
627 this->LastParse = targetchannel->name;
631 targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
632 this->LastParse = targetuser->nick;
637 if (type == MODETYPE_CHANNEL)
639 targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
640 FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
641 this->LastParse = targetchannel->name;
645 user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
646 FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
647 this->LastParse = targetuser->nick;
651 LastParse.append(" ");
652 LastParse.append(output_sequence);
653 LastParse.append(parameter_list.str());
658 const std::string& ModeParser::GetLastParse()
663 void ModeParser::CleanMask(std::string &mask)
665 std::string::size_type pos_of_pling = mask.find_first_of('!');
666 std::string::size_type pos_of_at = mask.find_first_of('@');
667 std::string::size_type pos_of_dot = mask.find_first_of('.');
668 std::string::size_type pos_of_colon = mask.find_first_of(':'); /* Because ipv6 addresses are colon delimited */
670 if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos))
672 /* Just a nick, or just a host */
673 if ((pos_of_dot == std::string::npos) && (pos_of_colon == std::string::npos))
675 /* It has no '.' in it, it must be a nick. */
680 /* Got a dot in it? Has to be a host */
681 mask = "*!*@" + mask;
684 else if ((pos_of_pling == std::string::npos) && (pos_of_at != std::string::npos))
686 /* Has an @ but no !, its a user@host */
689 else if ((pos_of_pling != std::string::npos) && (pos_of_at == std::string::npos))
691 /* Has a ! but no @, it must be a nick!ident */
696 bool ModeParser::AddMode(ModeHandler* mh)
698 unsigned char mask = 0;
699 unsigned char pos = 0;
701 /* Yes, i know, this might let people declare modes like '_' or '^'.
702 * If they do that, thats their problem, and if i ever EVER see an
703 * official InspIRCd developer do that, i'll beat them with a paddle!
705 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126))
708 /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
709 * A mode prefix of ':' will fuck up both server to server, and client to server.
710 * A mode prefix of '#' will mess up /whois and /privmsg
712 if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':') || (mh->GetPrefix() == '#'))
715 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
716 pos = (mh->GetModeChar()-65) | mask;
718 if (modehandlers[pos])
721 modehandlers[pos] = mh;
725 bool ModeParser::DelMode(ModeHandler* mh)
727 unsigned char mask = 0;
728 unsigned char pos = 0;
730 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
733 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
734 pos = (mh->GetModeChar()-65) | mask;
736 if (!modehandlers[pos])
739 switch (mh->GetModeType())
742 for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
744 mh->RemoveMode(i->second);
747 case MODETYPE_CHANNEL:
748 for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
750 mh->RemoveMode(i->second);
755 modehandlers[pos] = NULL;
760 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
762 unsigned char mask = 0;
763 unsigned char pos = 0;
765 if ((modeletter < 'A') || (modeletter > 'z'))
768 mt == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
769 pos = (modeletter-65) | mask;
771 return modehandlers[pos];
774 std::string ModeParser::UserModeList()
779 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
781 unsigned char pos = (mode-65) | MASK_USER;
783 if (modehandlers[pos])
784 modestr[pointer++] = mode;
786 modestr[pointer++] = 0;
790 std::string ModeParser::ChannelModeList()
795 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
797 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
800 unsigned char pos = (mode-65) | MASK_CHANNEL;
802 if (modehandlers[pos])
803 modestr[pointer++] = mode;
805 modestr[pointer++] = 0;
809 std::string ModeParser::ParaModeList()
814 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
816 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
819 unsigned char pos = (mode-65) | MASK_CHANNEL;
821 if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
822 modestr[pointer++] = mode;
824 modestr[pointer++] = 0;
828 ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
830 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
832 unsigned char pos = (mode-65) | MASK_CHANNEL;
834 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter))
836 return modehandlers[pos];
842 std::string ModeParser::ModeString(User* user, Channel* channel)
847 if (!channel || !user)
850 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
852 unsigned char pos = (mode-65) | MASK_CHANNEL;
853 ModeHandler* mh = modehandlers[pos];
854 if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
857 ret = mh->ModeSet(NULL, user, channel, user->nick);
858 if ((ret.first) && (ret.second == user->nick))
861 pars.append(user->nick);
862 types.push_back(mh->GetModeChar());
870 std::string ModeParser::ChanModes()
872 std::string type1; /* Listmodes EXCEPT those with a prefix */
873 std::string type2; /* Modes that take a param when adding or removing */
874 std::string type3; /* Modes that only take a param when adding */
875 std::string type4; /* Modes that dont take a param */
877 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
879 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
882 unsigned char pos = (mode-65) | MASK_CHANNEL;
883 /* One parameter when adding */
884 if (modehandlers[pos])
886 if (modehandlers[pos]->GetNumParams(true))
888 if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
890 type1 += modehandlers[pos]->GetModeChar();
894 /* ... and one parameter when removing */
895 if (modehandlers[pos]->GetNumParams(false))
897 /* But not a list mode */
898 if (!modehandlers[pos]->GetPrefix())
900 type2 += modehandlers[pos]->GetModeChar();
905 /* No parameters when removing */
906 type3 += modehandlers[pos]->GetModeChar();
912 type4 += modehandlers[pos]->GetModeChar();
918 return type1 + "," + type2 + "," + type3 + "," + type4;
921 bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
923 return one.second > two.second;
926 std::string ModeParser::BuildPrefixes()
928 std::string mletters;
929 std::string mprefixes;
931 std::map<char,char> prefix_to_mode;
933 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
935 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
938 unsigned char pos = (mode-65) | MASK_CHANNEL;
940 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
942 pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank()));
943 prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar();
947 sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison);
949 for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++)
951 mletters = mletters + n->first;
952 mprefixes = mprefixes + prefix_to_mode.find(n->first)->second;
955 return "(" + mprefixes + ")" + mletters;
958 bool ModeParser::AddModeWatcher(ModeWatcher* mw)
960 unsigned char mask = 0;
961 unsigned char pos = 0;
966 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
969 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
970 pos = (mw->GetModeChar()-65) | mask;
972 modewatchers[pos].push_back(mw);
977 bool ModeParser::DelModeWatcher(ModeWatcher* mw)
979 unsigned char mask = 0;
980 unsigned char pos = 0;
985 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
988 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
989 pos = (mw->GetModeChar()-65) | mask;
991 ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
993 if (a == modewatchers[pos].end())
998 modewatchers[pos].erase(a);
1003 /** This default implementation can remove simple user modes
1005 void ModeHandler::RemoveMode(User* user)
1007 char moderemove[MAXBUF];
1008 const char* parameters[] = { user->nick, moderemove };
1010 if (user->IsModeSet(this->GetModeChar()))
1012 sprintf(moderemove,"-%c",this->GetModeChar());
1013 ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
1017 /** This default implementation can remove simple channel modes
1020 void ModeHandler::RemoveMode(Channel* channel)
1022 char moderemove[MAXBUF];
1023 const char* parameters[] = { channel->name, moderemove };
1025 if (channel->IsModeSet(this->GetModeChar()))
1027 sprintf(moderemove,"-%c",this->GetModeChar());
1028 ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
1032 ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
1034 ModeHandler* modes[] =
1036 new ModeChannelSecret(Instance),
1037 new ModeChannelPrivate(Instance),
1038 new ModeChannelModerated(Instance),
1039 new ModeChannelTopicOps(Instance),
1040 new ModeChannelNoExternal(Instance),
1041 new ModeChannelInviteOnly(Instance),
1042 new ModeChannelKey(Instance),
1043 new ModeChannelLimit(Instance),
1044 new ModeChannelBan(Instance),
1045 new ModeChannelOp(Instance),
1046 new ModeChannelHalfOp(Instance),
1047 new ModeChannelVoice(Instance),
1048 new ModeUserServerNotice(Instance),
1049 new ModeUserWallops(Instance),
1050 new ModeUserInvisible(Instance),
1051 new ModeUserOperator(Instance),
1052 new ModeUserServerNoticeMask(Instance),
1056 /* Clear mode list */
1057 memset(modehandlers, 0, sizeof(modehandlers));
1058 memset(modewatchers, 0, sizeof(modewatchers));
1060 /* Last parse string */
1063 /* Initialise the RFC mode letters */
1064 for (int index = 0; modes[index]; index++)
1065 this->AddMode(modes[index]);