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->Logs->Log("MODE", 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, 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, bool)
175 void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool, ModeType, bool)
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* const* 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]);
390 bool SkipAccessChecks = false;
394 type = MODETYPE_CHANNEL;
397 /* Extra security checks on channel modes
398 * (e.g. are they a (half)op?
401 if ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
403 /* We don't have halfop */
405 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
406 if (MOD_RESULT == ACR_DENY)
408 SkipAccessChecks = (MOD_RESULT == ACR_ALLOW);
413 type = MODETYPE_USER;
415 if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
417 user->WriteServ("502 %s :Can't change mode for other users", user->nick);
423 /* No such nick/channel */
424 user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
428 std::string mode_sequence = parameters[1];
429 std::string parameter;
430 std::ostringstream parameter_list;
431 std::string output_sequence;
432 bool adding = true, state_change = false;
433 unsigned char handler_id = 0;
434 int parameter_counter = 2; /* Index of first parameter */
435 int parameter_count = 0;
436 bool last_successful_state_change = false;
438 /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
439 if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
440 mode_sequence.insert(0, "+");
442 for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
444 unsigned char modechar = *letter;
449 * For + and - mode characters, we don't just stick the character into the output sequence.
450 * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
451 * appearing in the output sequence, we store a flag which says there was a state change,
452 * which is set on any + or -, however, the + or - that we finish on is only appended to
453 * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
456 /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
457 * however, will allow the + if it is the first item in the sequence, regardless.
459 if ((!adding) || (!output_sequence.length()))
462 if (!output_sequence.length())
463 last_successful_state_change = false;
467 if ((adding) || (!output_sequence.length()))
470 if (!output_sequence.length())
471 last_successful_state_change = true;
477 * Watch carefully for the sleight of hand trick.
478 * 65 is the ascii value of 'A'. We take this from
479 * the char we're looking at to get a number between
480 * 1 and 127. We then logic-or it to get the hashed
481 * position, dependent on wether its a channel or
482 * a user mode. This is a little stranger, but a lot
483 * faster, than using a map of pairs.
485 handler_id = (modechar - 65) | mask;
487 if (modehandlers[handler_id])
491 if (modehandlers[handler_id]->GetModeType() == type)
495 if (modehandlers[handler_id]->GetNumParams(adding))
497 /* This mode expects a parameter, do we have any parameters left in our list to use? */
498 if (parameter_counter < pcnt)
500 parameter = parameters[parameter_counter++];
503 if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
508 /* No parameter, continue to the next mode */
512 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, parameter, adding, 1, servermode));
516 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, "", adding, 0, servermode));
519 if (IS_LOCAL(user) && (MOD_RESULT == ACR_DENY))
522 if (!SkipAccessChecks && IS_LOCAL(user) && (MOD_RESULT != ACR_ALLOW))
524 /* Check access to this mode character */
525 if ((type == MODETYPE_CHANNEL) && (modehandlers[handler_id]->GetNeededPrefix()))
527 char needed = modehandlers[handler_id]->GetNeededPrefix();
528 ModeHandler* prefixmode = FindPrefix(needed);
530 /* If the mode defined by the handler is not '\0', but the handler for it
531 * cannot be found, they probably dont have the right module loaded to implement
532 * the prefix they want to compare the mode against, e.g. '&' for m_chanprotect.
533 * Revert to checking against the minimum core prefix, '%'.
535 if (needed && !prefixmode)
536 prefixmode = FindPrefix('%');
538 unsigned int neededrank = prefixmode->GetPrefixRank();
539 /* Compare our rank on the channel against the rank of the required prefix,
540 * allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
541 * in NAMES(X) are not in rank order, we know the most powerful mode is listed
542 * first, so we don't need to iterate, we just look up the first instead.
544 std::string modestring = targetchannel->GetAllPrefixChars(user);
545 char ml = (modestring.empty() ? '\0' : modestring[0]);
546 ModeHandler* ourmode = FindPrefix(ml);
547 if (!ourmode || ourmode->GetPrefixRank() < neededrank)
550 user->WriteServ("482 %s %s :You must have channel privilege %c or above to %sset channel mode %c",
551 user->nick, targetchannel->name, needed, adding ? "" : "un", modechar);
557 bool had_parameter = !parameter.empty();
559 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
561 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type, servermode) == false)
566 /* A module whacked the parameter completely, and there was one. abort. */
567 if ((had_parameter) && (parameter.empty()))
577 /* It's an oper only mode, check if theyre an oper. If they arent,
578 * eat any parameter that came with the mode, and continue to next
580 if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!IS_OPER(user)))
582 user->WriteServ("481 %s :Permission Denied - Only IRC operators may %sset %s mode %c", user->nick,
583 adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
584 modehandlers[handler_id]->GetModeChar());
588 /* Call the handler for the mode */
589 ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding, servermode);
591 if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
593 /* The handler nuked the parameter and they are supposed to have one.
594 * We CANT continue now, even if they actually returned MODEACTION_ALLOW,
595 * so we bail to the next mode character.
600 if (ma == MODEACTION_ALLOW)
602 /* We're about to output a valid mode letter - was there previously a pending state-change? */
605 if (adding != last_successful_state_change)
606 output_sequence.append(adding ? "+" : "-");
607 last_successful_state_change = adding;
610 /* Add the mode letter */
611 output_sequence.push_back(modechar);
613 modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
615 /* Is there a valid parameter for this mode? If so add it to the parameter list */
616 if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
618 parameter_list << " " << parameter;
620 /* Does this mode have a prefix? */
621 if (modehandlers[handler_id]->GetPrefix() && targetchannel)
623 User* user_to_prefix = ServerInstance->FindNick(parameter);
625 targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
626 modehandlers[handler_id]->GetPrefixRank(), adding);
630 /* Call all the AfterMode events in the mode watchers for this mode */
631 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
632 (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type, servermode);
634 /* Reset the state change flag */
635 state_change = false;
637 if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
638 || (parameter_count > MAXMODES))
640 /* We cant have a mode sequence this long */
641 letter = mode_sequence.end() - 1;
649 /* No mode handler? Unknown mode character then. */
650 user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick, modechar);
656 /* Was there at least one valid mode in the sequence? */
657 if (!output_sequence.empty())
661 if (type == MODETYPE_CHANNEL)
663 targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str());
664 this->LastParse = targetchannel->name;
668 targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
669 this->LastParse = targetuser->nick;
674 if (type == MODETYPE_CHANNEL)
676 targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
677 FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
678 this->LastParse = targetchannel->name;
682 user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
683 FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
684 this->LastParse = targetuser->nick;
688 LastParse.append(" ");
689 LastParse.append(output_sequence);
690 LastParse.append(parameter_list.str());
695 const std::string& ModeParser::GetLastParse()
700 void ModeParser::CleanMask(std::string &mask)
702 std::string::size_type pos_of_pling = mask.find_first_of('!');
703 std::string::size_type pos_of_at = mask.find_first_of('@');
704 std::string::size_type pos_of_dot = mask.find_first_of('.');
705 std::string::size_type pos_of_colon = mask.find_first_of(':'); /* Because ipv6 addresses are colon delimited */
707 if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos))
709 /* Just a nick, or just a host */
710 if ((pos_of_dot == std::string::npos) && (pos_of_colon == std::string::npos))
712 /* It has no '.' in it, it must be a nick. */
717 /* Got a dot in it? Has to be a host */
718 mask = "*!*@" + mask;
721 else if ((pos_of_pling == std::string::npos) && (pos_of_at != std::string::npos))
723 /* Has an @ but no !, its a user@host */
726 else if ((pos_of_pling != std::string::npos) && (pos_of_at == std::string::npos))
728 /* Has a ! but no @, it must be a nick!ident */
733 bool ModeParser::AddMode(ModeHandler* mh)
735 unsigned char mask = 0;
736 unsigned char pos = 0;
738 /* Yes, i know, this might let people declare modes like '_' or '^'.
739 * If they do that, thats their problem, and if i ever EVER see an
740 * official InspIRCd developer do that, i'll beat them with a paddle!
742 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126))
745 /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
746 * A mode prefix of ':' will fuck up both server to server, and client to server.
747 * A mode prefix of '#' will mess up /whois and /privmsg
749 if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':') || (mh->GetPrefix() == '#'))
752 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
753 pos = (mh->GetModeChar()-65) | mask;
755 if (modehandlers[pos])
758 modehandlers[pos] = mh;
762 bool ModeParser::DelMode(ModeHandler* mh)
764 unsigned char mask = 0;
765 unsigned char pos = 0;
767 if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
770 mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
771 pos = (mh->GetModeChar()-65) | mask;
773 if (!modehandlers[pos])
776 switch (mh->GetModeType())
779 for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++)
781 mh->RemoveMode(i->second);
784 case MODETYPE_CHANNEL:
785 for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
787 mh->RemoveMode(i->second);
792 modehandlers[pos] = NULL;
797 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
799 unsigned char mask = 0;
800 unsigned char pos = 0;
802 if ((modeletter < 'A') || (modeletter > 'z'))
805 mt == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
806 pos = (modeletter-65) | mask;
808 return modehandlers[pos];
811 std::string ModeParser::UserModeList()
816 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
818 unsigned char pos = (mode-65) | MASK_USER;
820 if (modehandlers[pos])
821 modestr[pointer++] = mode;
823 modestr[pointer++] = 0;
827 std::string ModeParser::ChannelModeList()
832 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
834 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
837 unsigned char pos = (mode-65) | MASK_CHANNEL;
839 if (modehandlers[pos])
840 modestr[pointer++] = mode;
842 modestr[pointer++] = 0;
846 std::string ModeParser::ParaModeList()
851 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
853 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
856 unsigned char pos = (mode-65) | MASK_CHANNEL;
858 if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
859 modestr[pointer++] = mode;
861 modestr[pointer++] = 0;
865 ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
867 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
869 unsigned char pos = (mode-65) | MASK_CHANNEL;
871 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter))
873 return modehandlers[pos];
879 std::string ModeParser::ModeString(User* user, Channel* channel)
884 if (!channel || !user)
887 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
889 unsigned char pos = (mode-65) | MASK_CHANNEL;
890 ModeHandler* mh = modehandlers[pos];
891 if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
894 ret = mh->ModeSet(NULL, user, channel, user->nick);
895 if ((ret.first) && (ret.second == user->nick))
898 pars.append(user->nick);
899 types.push_back(mh->GetModeChar());
907 std::string ModeParser::ChanModes()
909 std::string type1; /* Listmodes EXCEPT those with a prefix */
910 std::string type2; /* Modes that take a param when adding or removing */
911 std::string type3; /* Modes that only take a param when adding */
912 std::string type4; /* Modes that dont take a param */
914 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
916 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
919 unsigned char pos = (mode-65) | MASK_CHANNEL;
920 /* One parameter when adding */
921 if (modehandlers[pos])
923 if (modehandlers[pos]->GetNumParams(true))
925 if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
927 type1 += modehandlers[pos]->GetModeChar();
931 /* ... and one parameter when removing */
932 if (modehandlers[pos]->GetNumParams(false))
934 /* But not a list mode */
935 if (!modehandlers[pos]->GetPrefix())
937 type2 += modehandlers[pos]->GetModeChar();
942 /* No parameters when removing */
943 type3 += modehandlers[pos]->GetModeChar();
949 type4 += modehandlers[pos]->GetModeChar();
955 return type1 + "," + type2 + "," + type3 + "," + type4;
958 bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
960 return one.second > two.second;
963 std::string ModeParser::BuildPrefixes()
965 std::string mletters;
966 std::string mprefixes;
968 std::map<char,char> prefix_to_mode;
970 for (unsigned char mode = 'A'; mode <= 'z'; mode++)
972 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
975 unsigned char pos = (mode-65) | MASK_CHANNEL;
977 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
979 pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank()));
980 prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar();
984 sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison);
986 for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++)
988 mletters = mletters + n->first;
989 mprefixes = mprefixes + prefix_to_mode.find(n->first)->second;
992 return "(" + mprefixes + ")" + mletters;
995 bool ModeParser::AddModeWatcher(ModeWatcher* mw)
997 unsigned char mask = 0;
998 unsigned char pos = 0;
1003 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1006 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1007 pos = (mw->GetModeChar()-65) | mask;
1009 modewatchers[pos].push_back(mw);
1014 bool ModeParser::DelModeWatcher(ModeWatcher* mw)
1016 unsigned char mask = 0;
1017 unsigned char pos = 0;
1022 if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1025 mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1026 pos = (mw->GetModeChar()-65) | mask;
1028 ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
1030 if (a == modewatchers[pos].end())
1035 modewatchers[pos].erase(a);
1040 /** This default implementation can remove simple user modes
1042 void ModeHandler::RemoveMode(User* user)
1044 char moderemove[MAXBUF];
1045 const char* parameters[] = { user->nick, moderemove };
1047 if (user->IsModeSet(this->GetModeChar()))
1049 sprintf(moderemove,"-%c",this->GetModeChar());
1050 ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
1054 /** This default implementation can remove simple channel modes
1057 void ModeHandler::RemoveMode(Channel* channel)
1059 char moderemove[MAXBUF];
1060 const char* parameters[] = { channel->name, moderemove };
1062 if (channel->IsModeSet(this->GetModeChar()))
1064 sprintf(moderemove,"-%c",this->GetModeChar());
1065 ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
1069 ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
1071 ModeHandler* modes[] =
1073 new ModeChannelSecret(Instance),
1074 new ModeChannelPrivate(Instance),
1075 new ModeChannelModerated(Instance),
1076 new ModeChannelTopicOps(Instance),
1077 new ModeChannelNoExternal(Instance),
1078 new ModeChannelInviteOnly(Instance),
1079 new ModeChannelKey(Instance),
1080 new ModeChannelLimit(Instance),
1081 new ModeChannelBan(Instance),
1082 new ModeChannelOp(Instance),
1083 new ModeChannelHalfOp(Instance),
1084 new ModeChannelVoice(Instance),
1085 new ModeUserServerNotice(Instance),
1086 new ModeUserWallops(Instance),
1087 new ModeUserInvisible(Instance),
1088 new ModeUserOperator(Instance),
1089 new ModeUserServerNoticeMask(Instance),
1093 /* Clear mode list */
1094 memset(modehandlers, 0, sizeof(modehandlers));
1095 memset(modewatchers, 0, sizeof(modewatchers));
1097 /* Last parse string */
1100 /* Initialise the RFC mode letters */
1101 for (int index = 0; modes[index]; index++)
1102 this->AddMode(modes[index]);