]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/mode.cpp
Fix typo opermoth -> opermotd. Thanks Ankit.
[user/henk/code/inspircd.git] / src / mode.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 /* $Core */
15 /* $ExtraDeps: $(RELCPPFILES) */
16 /* $ExtraObjects: modes/modeclasses.a */
17 /* $ExtraBuild: @${MAKE} -C "modes" DIRNAME="src/modes" CC="$(CC)" $(MAKEARGS) CPPFILES="$(CPPFILES)" */
18
19 #include "inspircd.h"
20 #include "inspstring.h"
21
22 /* +s (secret) */
23 #include "modes/cmode_s.h"
24 /* +p (private) */
25 #include "modes/cmode_p.h"
26 /* +b (bans) */
27 #include "modes/cmode_b.h"
28 /* +m (moderated) */
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"
40 /* +o (channel op) */
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 /* +w (see wallops) */
47 #include "modes/umode_w.h"
48 /* +i (invisible) */
49 #include "modes/umode_i.h"
50 /* +o (operator) */
51 #include "modes/umode_o.h"
52 /* +s (server notice masks) */
53 #include "modes/umode_s.h"
54
55 ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix, char prefixrequired)
56         : 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)
57 {
58 }
59
60 ModeHandler::~ModeHandler()
61 {
62 }
63
64 bool ModeHandler::IsListMode()
65 {
66         return list;
67 }
68
69 char ModeHandler::GetNeededPrefix()
70 {
71         return prefixneeded;
72 }
73
74 void ModeHandler::SetNeededPrefix(char needsprefix)
75 {
76         prefixneeded = needsprefix;
77 }
78
79 unsigned int ModeHandler::GetPrefixRank()
80 {
81         return 0;
82 }
83
84 unsigned int ModeHandler::GetCount()
85 {
86         return 0;
87 }
88
89 void ModeHandler::ChangeCount(int modifier)
90 {
91         count += modifier;
92         ServerInstance->Logs->Log("MODE", DEBUG,"Change count for mode %c is now %d", mode, count);
93 }
94
95 ModeType ModeHandler::GetModeType()
96 {
97         return m_type;
98 }
99
100 bool ModeHandler::NeedsOper()
101 {
102         return oper;
103 }
104
105 char ModeHandler::GetPrefix()
106 {
107         return prefix;
108 }
109
110 int ModeHandler::GetNumParams(bool adding)
111 {
112         return adding ? n_params_on : n_params_off;
113 }
114
115 char ModeHandler::GetModeChar()
116 {
117         return mode;
118 }
119
120 std::string ModeHandler::GetUserParameter(User* user)
121 {
122         return "";
123 }
124
125 ModeAction ModeHandler::OnModeChange(User*, User*, Channel*, std::string&, bool, bool)
126 {
127         return MODEACTION_DENY;
128 }
129
130 ModePair ModeHandler::ModeSet(User*, User* dest, Channel* channel, const std::string&)
131 {
132         if (dest)
133         {
134                 return std::make_pair(dest->IsModeSet(this->mode), "");
135         }
136         else
137         {
138                 return std::make_pair(channel->IsModeSet(this->mode), "");
139         }
140 }
141
142 void ModeHandler::DisplayList(User*, Channel*)
143 {
144 }
145
146 void ModeHandler::DisplayEmptyList(User*, Channel*)
147 {
148 }
149
150 void ModeHandler::OnParameterMissing(User* user, User* dest, Channel* channel)
151 {
152 }
153
154 bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string&, const std::string&, Channel*)
155 {
156         return (ours < theirs);
157 }
158
159 SimpleUserModeHandler::SimpleUserModeHandler(InspIRCd* Instance, char modeletter) : ModeHandler(Instance, modeletter, 0, 0, false, MODETYPE_USER, false)
160 {
161 }
162
163 SimpleUserModeHandler::~SimpleUserModeHandler()
164 {
165 }
166
167 SimpleChannelModeHandler::~SimpleChannelModeHandler()
168 {
169 }
170
171 SimpleChannelModeHandler::SimpleChannelModeHandler(InspIRCd* Instance, char modeletter) : ModeHandler(Instance, modeletter, 0, 0, false, MODETYPE_CHANNEL, false)
172 {
173 }
174
175 ModeAction SimpleUserModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool servermode)
176 {
177         if (adding)
178         {
179                 if (!dest->IsModeSet(this->GetModeChar()))
180                 {
181                         dest->SetMode(this->GetModeChar(),true);
182                         return MODEACTION_ALLOW;
183                 }
184         }
185         else
186         {
187                 if (dest->IsModeSet(this->GetModeChar()))
188                 {
189                         dest->SetMode(this->GetModeChar(),false);
190                         return MODEACTION_ALLOW;
191                 }
192         }
193
194         return MODEACTION_DENY;
195 }
196
197
198 ModeAction SimpleChannelModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool servermode)
199 {
200         if (adding)
201         {
202                 if (!channel->IsModeSet(this->GetModeChar()))
203                 {
204                         channel->SetMode(this->GetModeChar(),true);
205                         return MODEACTION_ALLOW;
206                 }
207         }
208         else
209         {
210                 if (channel->IsModeSet(this->GetModeChar()))
211                 {
212                         channel->SetMode(this->GetModeChar(),false);
213                         return MODEACTION_ALLOW;
214                 }
215         }
216
217         return MODEACTION_DENY;
218 }
219
220 ModeWatcher::ModeWatcher(InspIRCd* Instance, char modeletter, ModeType type) : ServerInstance(Instance), mode(modeletter), m_type(type)
221 {
222 }
223
224 ModeWatcher::~ModeWatcher()
225 {
226 }
227
228 char ModeWatcher::GetModeChar()
229 {
230         return mode;
231 }
232
233 ModeType ModeWatcher::GetModeType()
234 {
235         return m_type;
236 }
237
238 bool ModeWatcher::BeforeMode(User*, User*, Channel*, std::string&, bool, ModeType, bool)
239 {
240         return true;
241 }
242
243 void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool, ModeType, bool)
244 {
245 }
246
247 User* ModeParser::SanityChecks(User *user, const char *dest, Channel *chan, int)
248 {
249         User *d;
250         if ((!user) || (!dest) || (!chan) || (!*dest))
251         {
252                 return NULL;
253         }
254         d = ServerInstance->FindNick(dest);
255         if (!d)
256         {
257                 user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), dest);
258                 return NULL;
259         }
260         return d;
261 }
262
263 const char* ModeParser::Grant(User *d,Channel *chan,int MASK)
264 {
265         if (!chan)
266                 return "";
267
268         UCListIter n = d->chans.find(chan);
269         if (n != d->chans.end())
270         {
271                 if (n->second & MASK)
272                 {
273                         return "";
274                 }
275                 n->second = n->second | MASK;
276                 switch (MASK)
277                 {
278                         case UCMODE_OP:
279                                 n->first->AddOppedUser(d);
280                         break;
281                         case UCMODE_HOP:
282                                 n->first->AddHalfoppedUser(d);
283                         break;
284                         case UCMODE_VOICE:
285                                 n->first->AddVoicedUser(d);
286                         break;
287                 }
288                 return d->nick.c_str();
289         }
290         return "";
291 }
292
293 const char* ModeParser::Revoke(User *d,Channel *chan,int MASK)
294 {
295         if (!chan)
296                 return "";
297
298         UCListIter n = d->chans.find(chan);
299         if (n != d->chans.end())
300         {
301                 if ((n->second & MASK) == 0)
302                 {
303                         return "";
304                 }
305                 n->second ^= MASK;
306                 switch (MASK)
307                 {
308                         case UCMODE_OP:
309                                 n->first->DelOppedUser(d);
310                         break;
311                         case UCMODE_HOP:
312                                 n->first->DelHalfoppedUser(d);
313                         break;
314                         case UCMODE_VOICE:
315                                 n->first->DelVoicedUser(d);
316                         break;
317                 }
318                 return d->nick.c_str();
319         }
320         return "";
321 }
322
323 void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targetchannel, const char* text)
324 {
325         if (targetchannel)
326         {
327                 /* Display channel's current mode string */
328                 user->WriteNumeric(RPL_CHANNELMODEIS, "%s %s +%s",user->nick.c_str(), targetchannel->name.c_str(), targetchannel->ChanModes(targetchannel->HasUser(user)));
329                 user->WriteNumeric(RPL_CHANNELCREATED, "%s %s %lu", user->nick.c_str(), targetchannel->name.c_str(), (unsigned long)targetchannel->age);
330                 return;
331         }
332         else if (targetuser)
333         {
334                 if (targetuser->Visibility && !targetuser->Visibility->VisibleTo(user))
335                 {
336                         user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), text);
337                         return;
338                 }
339
340                 if (targetuser == user || user->HasPrivPermission("users/auspex"))
341                 {
342                         /* Display user's current mode string */
343                         user->WriteNumeric(RPL_UMODEIS, "%s :+%s",targetuser->nick.c_str(),targetuser->FormatModes());
344                         if (IS_OPER(targetuser))
345                                 user->WriteNumeric(RPL_SNOMASKIS, "%s +%s :Server notice mask", targetuser->nick.c_str(), targetuser->FormatNoticeMasks());
346                         return;
347                 }
348                 else
349                 {
350                         user->WriteNumeric(ERR_USERSDONTMATCH, "%s :Can't change mode for other users", user->nick.c_str());
351                         return;
352                 }
353         }
354
355         /* No such nick/channel */
356         user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), text);
357         return;
358 }
359
360 void ModeParser::Process(const std::vector<std::string>& parameters, User *user, bool servermode)
361 {
362         std::string target = parameters[0];
363         ModeType type = MODETYPE_USER;
364         unsigned char mask = 0;
365         Channel* targetchannel = ServerInstance->FindChan(parameters[0]);
366         User* targetuser  = ServerInstance->FindNick(parameters[0]);
367
368         LastParse.clear();
369
370         /* Special case for displaying the list for listmodes,
371          * e.g. MODE #chan b, or MODE #chan +b without a parameter
372          */
373         if ((targetchannel) && (parameters.size() == 2))
374         {
375                 const char* mode = parameters[1].c_str();
376                 int nonlistmodes_found = 0;
377
378                 seq++;
379
380                 mask = MASK_CHANNEL;
381                 
382                 while (mode && *mode)
383                 {
384                         unsigned char mletter = *mode;
385
386                         if (*mode == '+')
387                         {
388                                 mode++;
389                                 continue;
390                         }
391                         
392                         /* Ensure the user doesnt request the same mode twice,
393                          * so they cant flood themselves off out of idiocy.
394                          */
395                         if (sent[mletter] != seq)
396                         {
397                                 sent[mletter] = seq;
398                         }
399                         else
400                         {
401                                 mode++;
402                                 continue;
403                         }
404
405                         ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL);
406                         bool display = true;
407
408                         if ((mh) && (mh->IsListMode()))
409                         {
410                                 int MOD_RESULT = 0;
411                                 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, *mode, "", true, 0));
412                                 if (MOD_RESULT == ACR_DENY)
413                                 {
414                                         mode++;
415                                         continue;
416                                 }
417
418                                 if (!user->HasPrivPermission("channels/auspex"))
419                                 {
420                                         if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
421                                         {
422                                                 user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only half-operators and above may view the +%c list",user->nick.c_str(), targetchannel->name.c_str(), *mode++);
423                                                 mh->DisplayEmptyList(user, targetchannel);
424                                                 continue;
425                                         }
426                                 }
427
428                                 /** See below for a description of what craq this is :D
429                                  */
430                                 unsigned char handler_id = (*mode - 65) | mask;
431
432                                 for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
433                                 {
434                                         std::string dummyparam;
435                                         
436                                         if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL)))
437                                                 display = false;
438                                 }
439
440                                 if (display)
441                                         mh->DisplayList(user, targetchannel);
442                         }
443                         else
444                                 nonlistmodes_found++;
445
446                         mode++;
447                 }
448
449                 /* We didnt have any modes that were non-list, we can return here */
450                 if (!nonlistmodes_found)
451                         return;
452         }
453
454         if (parameters.size() == 1)
455         {
456                 this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0].c_str());
457         }
458         else if (parameters.size() > 1)
459         {
460                 bool SkipAccessChecks = false;
461
462                 if (targetchannel)
463                 {
464                         type = MODETYPE_CHANNEL;
465                         mask = MASK_CHANNEL;
466
467                         /* Extra security checks on channel modes
468                          * (e.g. are they a (half)op?
469                          */
470
471                         if ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
472                         {
473                                 /* We don't have halfop */
474                                 int MOD_RESULT = 0;
475                                 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
476                                 if (MOD_RESULT == ACR_DENY)
477                                         return;
478                                 SkipAccessChecks = (MOD_RESULT == ACR_ALLOW);
479                         }
480                 }
481                 else if (targetuser)
482                 {
483                         type = MODETYPE_USER;
484                         mask = MASK_USER;
485                         if (user != targetuser && IS_LOCAL(user) && !ServerInstance->ULine(user->server))
486                         {
487                                 user->WriteNumeric(ERR_USERSDONTMATCH, "%s :Can't change mode for other users", user->nick.c_str());
488                                 return;
489                         }
490                 }
491                 else
492                 {
493                         /* No such nick/channel */
494                         user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
495                         return;
496                 }
497
498                 std::string mode_sequence = parameters[1];
499                 std::string parameter;
500                 std::ostringstream parameter_list;
501                 std::string output_sequence;
502                 bool adding = true, state_change = false;
503                 unsigned char handler_id = 0;
504                 unsigned int parameter_counter = 2; /* Index of first parameter */
505                 unsigned int parameter_count = 0;
506                 bool last_successful_state_change = false;
507
508                 /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
509                 if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
510                         mode_sequence.insert(0, "+");
511
512                 for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
513                 {
514                         unsigned char modechar = *letter;
515
516                         switch (modechar)
517                         {
518                                 /* NB:
519                                  * For + and - mode characters, we don't just stick the character into the output sequence.
520                                  * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
521                                  * appearing in the output sequence, we store a flag which says there was a state change,
522                                  * which is set on any + or -, however, the + or - that we finish on is only appended to
523                                  * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
524                                  */
525                                 case '+':
526                                         /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
527                                          * however, will allow the + if it is the first item in the sequence, regardless.
528                                          */
529                                         if ((!adding) || (!output_sequence.length()))
530                                                 state_change = true;
531                                         adding = true;
532                                         if (!output_sequence.length())
533                                                 last_successful_state_change = false;
534                                         continue;
535                                 break;
536                                 case '-':
537                                         if ((adding) || (!output_sequence.length()))
538                                                 state_change = true;
539                                         adding = false;
540                                         if (!output_sequence.length())
541                                                 last_successful_state_change = true;
542                                         continue;
543                                 break;
544                                 default:
545
546                                         /**
547                                          * Watch carefully for the sleight of hand trick.
548                                          * 65 is the ascii value of 'A'. We take this from
549                                          * the char we're looking at to get a number between
550                                          * 1 and 127. We then logic-or it to get the hashed
551                                          * position, dependent on wether its a channel or
552                                          * a user mode. This is a little stranger, but a lot
553                                          * faster, than using a map of pairs.
554                                          */
555                                         handler_id = (modechar - 65) | mask;
556
557                                         if (modehandlers[handler_id])
558                                         {
559                                                 bool abort = false;
560
561                                                 if (modehandlers[handler_id]->GetModeType() == type)
562                                                 {
563                                                         int MOD_RESULT = 0;
564
565                                                         if (modehandlers[handler_id]->GetNumParams(adding))
566                                                         {
567                                                                 /* This mode expects a parameter, do we have any parameters left in our list to use? */
568                                                                 if (parameter_counter < parameters.size())
569                                                                 {
570                                                                         parameter = parameters[parameter_counter++];
571
572                                                                         /* Yerk, invalid! */
573                                                                         if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
574                                                                                 parameter.clear();
575                                                                 }
576                                                                 else
577                                                                 {
578                                                                         /* No parameter, continue to the next mode */
579                                                                         modehandlers[handler_id]->OnParameterMissing(user, targetuser, targetchannel);
580                                                                         continue;
581                                                                 }
582
583                                                                 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, parameter, adding, 1, servermode));
584                                                         }
585                                                         else
586                                                         {
587                                                                 FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, "", adding, 0, servermode));
588                                                         }
589
590                                                         if (IS_LOCAL(user) && (MOD_RESULT == ACR_DENY))
591                                                                 continue;
592
593                                                         if (!SkipAccessChecks && IS_LOCAL(user) && (MOD_RESULT != ACR_ALLOW))
594                                                         {
595                                                                 /* Check access to this mode character */
596                                                                 if ((type == MODETYPE_CHANNEL) && (modehandlers[handler_id]->GetNeededPrefix()))
597                                                                 {
598                                                                         char needed = modehandlers[handler_id]->GetNeededPrefix();
599                                                                         ModeHandler* prefixmode = FindPrefix(needed);
600
601                                                                         /* If the mode defined by the handler is not '\0', but the handler for it
602                                                                          * cannot be found, they probably dont have the right module loaded to implement
603                                                                          * the prefix they want to compare the mode against, e.g. '&' for m_chanprotect.
604                                                                          * Revert to checking against the minimum core prefix, '%'.
605                                                                          */
606                                                                         if (needed && !prefixmode)
607                                                                                 prefixmode = FindPrefix('%');
608                                                 
609                                                                         unsigned int neededrank = prefixmode->GetPrefixRank();
610                                                                         /* Compare our rank on the channel against the rank of the required prefix,
611                                                                          * allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
612                                                                          * in NAMES(X) are not in rank order, we know the most powerful mode is listed
613                                                                          * first, so we don't need to iterate, we just look up the first instead.
614                                                                          */
615                                                                         std::string modestring = targetchannel->GetAllPrefixChars(user);
616                                                                         char ml = (modestring.empty() ? '\0' : modestring[0]);
617                                                                         ModeHandler* ourmode = FindPrefix(ml);
618                                                                         if (!ourmode || ourmode->GetPrefixRank() < neededrank)
619                                                                         {
620                                                                                 /* Bog off */
621                                                                                 user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have channel privilege %c or above to %sset channel mode %c",
622                                                                                                 user->nick.c_str(), targetchannel->name.c_str(), needed, adding ? "" : "un", modechar);
623                                                                                 continue;
624                                                                         }
625                                                                 }
626                                                         }
627
628                                                         bool had_parameter = !parameter.empty();
629                                                                 
630                                                         for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
631                                                         {
632                                                                 if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type, servermode) == false)
633                                                                 {
634                                                                         abort = true;
635                                                                         break;
636                                                                 }
637                                                                 /* A module whacked the parameter completely, and there was one. abort. */
638                                                                 if ((had_parameter) && (parameter.empty()))
639                                                                 {
640                                                                         abort = true;
641                                                                         break;
642                                                                 }
643                                                         }
644
645                                                         if (abort)
646                                                                 continue;
647
648                                                         /* If it's disabled, they have to be an oper.
649                                                          */
650                                                         if (IS_LOCAL(user) && !IS_OPER(user) && ((type == MODETYPE_CHANNEL ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes)[modehandlers[handler_id]->GetModeChar() - 'A']))
651                                                         {
652                                                                 user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - %s mode %c has been locked by the administrator",
653                                                                                 user->nick.c_str(),
654                                                                                 type == MODETYPE_CHANNEL ? "channel" : "user",
655                                                                                 modehandlers[handler_id]->GetModeChar());
656                                                                 continue;
657                                                         }
658
659                                                         /* It's an oper only mode, check if theyre an oper. If they arent,
660                                                          * eat any parameter that  came with the mode, and continue to next
661                                                          */
662                                                         if (adding && (IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!user->HasModePermission(modehandlers[handler_id]->GetModeChar(), type)))
663                                                         {
664                                                                 if (IS_OPER(user))
665                                                                 {
666                                                                         user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
667                                                                                         user->nick.c_str(),
668                                                                                         user->oper.c_str(),
669                                                                                         type == MODETYPE_CHANNEL ? "channel" : "user",
670                                                                                         modehandlers[handler_id]->GetModeChar());
671                                                                 }
672                                                                 else
673                                                                 {
674                                                                         user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Only operators may set %s mode %c",
675                                                                                         user->nick.c_str(),
676                                                                                         type == MODETYPE_CHANNEL ? "channel" : "user",
677                                                                                         modehandlers[handler_id]->GetModeChar());
678                                                                 }
679                                                                 continue;
680                                                         }
681
682                                                         /* Call the handler for the mode */
683                                                         ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding, servermode);
684
685                                                         if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
686                                                         {
687                                                                 /* The handler nuked the parameter and they are supposed to have one.
688                                                                  * We CANT continue now, even if they actually returned MODEACTION_ALLOW,
689                                                                  * so we bail to the next mode character.
690                                                                  */
691                                                                 continue;
692                                                         }
693
694                                                         if (ma == MODEACTION_ALLOW)
695                                                         {
696                                                                 /* We're about to output a valid mode letter - was there previously a pending state-change? */
697                                                                 if (state_change)
698                                                                 {
699                                                                         if (adding != last_successful_state_change)
700                                                                                 output_sequence.append(adding ? "+" : "-");
701                                                                         last_successful_state_change = adding;
702                                                                 }
703                                                                 
704                                                                 /* Add the mode letter */
705                                                                 output_sequence.push_back(modechar);
706
707                                                                 modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
708
709                                                                 /* Is there a valid parameter for this mode? If so add it to the parameter list */
710                                                                 if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
711                                                                 {
712                                                                         parameter_list << " " << parameter;
713                                                                         parameter_count++;
714                                                                         /* Does this mode have a prefix? */
715                                                                         if (modehandlers[handler_id]->GetPrefix() && targetchannel)
716                                                                         {
717                                                                                 User* user_to_prefix = ServerInstance->FindNick(parameter);
718                                                                                 if (user_to_prefix)
719                                                                                         targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
720                                                                                                         modehandlers[handler_id]->GetPrefixRank(), adding);
721                                                                         }
722                                                                 }
723
724                                                                 /* Call all the AfterMode events in the mode watchers for this mode */
725                                                                 for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
726                                                                         (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type, servermode);
727
728                                                                 /* Reset the state change flag */
729                                                                 state_change = false;
730
731                                                                 if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
732                                                                                 || (parameter_count > ServerInstance->Config->Limits.MaxModes))
733                                                                 {
734                                                                         /* We cant have a mode sequence this long */
735                                                                         letter = mode_sequence.end() - 1;
736                                                                         continue;
737                                                                 }
738                                                         }
739                                                 }
740                                         }
741                                         else
742                                         {
743                                                 /* No mode handler? Unknown mode character then. */
744                                                 user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick.c_str(), modechar);
745                                         }
746                                 break;
747                         }
748                 }
749
750                 /* Was there at least one valid mode in the sequence? */
751                 if (!output_sequence.empty())
752                 {
753                         if (servermode)
754                         {
755                                 if (type == MODETYPE_CHANNEL)
756                                 {
757                                         targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
758                                         this->LastParse = targetchannel->name;
759                                 }
760                                 else
761                                 {
762                                         targetuser->WriteServ("MODE %s %s%s",targetuser->nick.c_str(),output_sequence.c_str(), parameter_list.str().c_str());
763                                         this->LastParse = targetuser->nick;
764                                 }
765                         }
766                         else
767                         {
768                                 if (type == MODETYPE_CHANNEL)
769                                 {
770                                         targetchannel->WriteChannel(user, "MODE %s %s%s", targetchannel->name.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
771                                         FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
772                                         this->LastParse = targetchannel->name;
773                                 }
774                                 else
775                                 {
776                                         user->WriteTo(targetuser, "MODE %s %s%s", targetuser->nick.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
777                                         FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
778                                         this->LastParse = targetuser->nick;
779                                 }
780                         }
781
782                         LastParse.append(" ");
783                         LastParse.append(output_sequence);
784                         LastParse.append(parameter_list.str());
785                 }
786         }
787 }
788
789 const std::string& ModeParser::GetLastParse()
790 {
791         return LastParse;
792 }
793
794 void ModeParser::CleanMask(std::string &mask)
795 {
796         std::string::size_type pos_of_pling = mask.find_first_of('!');
797         std::string::size_type pos_of_at = mask.find_first_of('@');
798         std::string::size_type pos_of_dot = mask.find_first_of('.');
799         std::string::size_type pos_of_colons = mask.find("::"); /* Because ipv6 addresses are colon delimited -- double so it treats extban as nick */
800
801         if (mask.length() >= 2 && mask[1] == ':')
802                 return; // if it's an extban, don't even try guess how it needs to be formed.
803
804         if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos))
805         {
806                 /* Just a nick, or just a host - or clearly ipv6 (starting with :) */
807                 if ((pos_of_dot == std::string::npos) && (pos_of_colons == std::string::npos) && mask[0] != ':')
808                 {
809                         /* It has no '.' in it, it must be a nick. */
810                         mask.append("!*@*");
811                 }
812                 else
813                 {
814                         /* Got a dot in it? Has to be a host */
815                         mask = "*!*@" + mask;
816                 }
817         }
818         else if ((pos_of_pling == std::string::npos) && (pos_of_at != std::string::npos))
819         {
820                 /* Has an @ but no !, its a user@host */
821                  mask = "*!" + mask;
822         }
823         else if ((pos_of_pling != std::string::npos) && (pos_of_at == std::string::npos))
824         {
825                 /* Has a ! but no @, it must be a nick!ident */
826                 mask.append("@*");
827         }
828 }
829
830 bool ModeParser::AddMode(ModeHandler* mh)
831 {
832         unsigned char mask = 0;
833         unsigned char pos = 0;
834
835         /* Yes, i know, this might let people declare modes like '_' or '^'.
836          * If they do that, thats their problem, and if i ever EVER see an
837          * official InspIRCd developer do that, i'll beat them with a paddle!
838          */
839         if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z') || (mh->GetPrefix() > 126))
840                 return false;
841
842         /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
843          * A mode prefix of ':' will fuck up both server to server, and client to server.
844          * A mode prefix of '#' will mess up /whois and /privmsg
845          */
846         if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':') || (mh->GetPrefix() == '#'))
847                 return false;
848
849         mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
850         pos = (mh->GetModeChar()-65) | mask;
851
852         if (modehandlers[pos])
853                 return false;
854
855         modehandlers[pos] = mh;
856         return true;
857 }
858
859 bool ModeParser::DelMode(ModeHandler* mh)
860 {
861         unsigned char mask = 0;
862         unsigned char pos = 0;
863
864         if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
865                 return false;
866
867         mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
868         pos = (mh->GetModeChar()-65) | mask;
869
870         if (!modehandlers[pos])
871                 return false;
872
873         /* Note: We can't stack here, as we have modes potentially being removed across many different channels.
874          * To stack here we have to make the algorithm slower. Discuss.
875          */
876         switch (mh->GetModeType())
877         {
878                 case MODETYPE_USER:
879                         for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++)
880                         {
881                                 mh->RemoveMode(i->second);
882                         }
883                 break;
884                 case MODETYPE_CHANNEL:
885                         for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
886                         {
887                                 mh->RemoveMode(i->second);
888                         }
889                 break;
890         }
891
892         modehandlers[pos] = NULL;
893
894         return true;
895 }
896
897 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
898 {
899         unsigned char mask = 0;
900         unsigned char pos = 0;
901
902         if ((modeletter < 'A') || (modeletter > 'z'))
903                 return NULL;
904
905         mt == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
906         pos = (modeletter-65) | mask;
907
908         return modehandlers[pos];
909 }
910
911 std::string ModeParser::UserModeList()
912 {
913         char modestr[256];
914         int pointer = 0;
915
916         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
917         {
918                 unsigned char pos = (mode-65) | MASK_USER;
919
920                 if (modehandlers[pos])
921                         modestr[pointer++] = mode;
922         }
923         modestr[pointer++] = 0;
924         return modestr;
925 }
926
927 std::string ModeParser::ChannelModeList()
928 {
929         char modestr[256];
930         int pointer = 0;
931
932         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
933         {
934                 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
935                         continue;
936
937                 unsigned char pos = (mode-65) | MASK_CHANNEL;
938
939                 if (modehandlers[pos])
940                         modestr[pointer++] = mode;
941         }
942         modestr[pointer++] = 0;
943         return modestr;
944 }
945
946 std::string ModeParser::ParaModeList()
947 {
948         char modestr[256];
949         int pointer = 0;
950
951         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
952         {
953                 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
954                         continue;
955
956                 unsigned char pos = (mode-65) | MASK_CHANNEL;
957
958                 if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
959                         modestr[pointer++] = mode;
960         }
961         modestr[pointer++] = 0;
962         return modestr;
963 }
964
965 ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
966 {
967         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
968         {
969                 unsigned char pos = (mode-65) | MASK_CHANNEL;
970
971                 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter))
972                 {
973                         return modehandlers[pos];
974                 }
975         }
976         return NULL;
977 }
978
979 std::string ModeParser::ModeString(User* user, Channel* channel, bool nick_suffix)
980 {
981         std::string types;
982         std::string pars;
983
984         if (!channel || !user)
985                 return "";
986
987         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
988         {
989                 unsigned char pos = (mode-65) | MASK_CHANNEL;
990                 ModeHandler* mh = modehandlers[pos];
991                 if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
992                 {
993                         ModePair ret;
994                         ret = mh->ModeSet(NULL, user, channel, user->nick);
995                         if ((ret.first) && (ret.second == user->nick))
996                         {
997                                 if (nick_suffix)
998                                 {
999                                         pars.append(" ");
1000                                         pars.append(user->nick);
1001                                 }
1002                                 types.push_back(mh->GetModeChar());
1003                         }
1004                 }
1005         }
1006
1007         if (nick_suffix)
1008                 return types+pars;
1009         else
1010                 return types;
1011 }
1012
1013 std::string ModeParser::GiveModeList(ModeMasks m)
1014 {
1015         std::string type1;      /* Listmodes EXCEPT those with a prefix */
1016         std::string type2;      /* Modes that take a param when adding or removing */
1017         std::string type3;      /* Modes that only take a param when adding */
1018         std::string type4;      /* Modes that dont take a param */
1019
1020         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
1021         {
1022                 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
1023                         continue;
1024
1025                 unsigned char pos = (mode-65) | m;
1026                  /* One parameter when adding */
1027                 if (modehandlers[pos])
1028                 {       
1029                         if (modehandlers[pos]->GetNumParams(true))
1030                         {
1031                                 if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
1032                                 {
1033                                         type1 += modehandlers[pos]->GetModeChar();
1034                                 }
1035                                 else
1036                                 {
1037                                         /* ... and one parameter when removing */
1038                                         if (modehandlers[pos]->GetNumParams(false))
1039                                         {
1040                                                 /* But not a list mode */
1041                                                 if (!modehandlers[pos]->GetPrefix())
1042                                                 {
1043                                                         type2 += modehandlers[pos]->GetModeChar();
1044                                                 }
1045                                         }
1046                                         else
1047                                         {
1048                                                 /* No parameters when removing */
1049                                                 type3 += modehandlers[pos]->GetModeChar();
1050                                         }
1051                                 }
1052                         }
1053                         else
1054                         {
1055                                 type4 += modehandlers[pos]->GetModeChar();
1056                         }
1057                 }
1058                          
1059         }
1060
1061         return type1 + "," + type2 + "," + type3 + "," + type4;
1062 }
1063
1064 bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
1065 {       
1066         return one.second > two.second;
1067 }
1068
1069 std::string ModeParser::BuildPrefixes()
1070 {
1071         std::string mletters;
1072         std::string mprefixes;
1073         pfxcontainer pfx;
1074         std::map<char,char> prefix_to_mode;
1075
1076         for (unsigned char mode = 'A'; mode <= 'z'; mode++)
1077         {
1078                 if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
1079                         continue;
1080
1081                 unsigned char pos = (mode-65) | MASK_CHANNEL;
1082
1083                 if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
1084                 {
1085                         pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank()));
1086                         prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar();
1087                 }
1088         }
1089
1090         sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison);
1091
1092         for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++)
1093         {
1094                 mletters = mletters + n->first;
1095                 mprefixes = mprefixes + prefix_to_mode.find(n->first)->second;
1096         }
1097
1098         return "(" + mprefixes + ")" + mletters;
1099 }
1100
1101 bool ModeParser::AddModeWatcher(ModeWatcher* mw)
1102 {
1103         unsigned char mask = 0;
1104         unsigned char pos = 0;
1105
1106         if (!mw)
1107                 return false;
1108
1109         if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1110                 return false;
1111
1112         mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1113         pos = (mw->GetModeChar()-65) | mask;
1114
1115         modewatchers[pos].push_back(mw);
1116
1117         return true;
1118 }
1119
1120 bool ModeParser::DelModeWatcher(ModeWatcher* mw)
1121 {
1122         unsigned char mask = 0;
1123         unsigned char pos = 0;
1124
1125         if (!mw)
1126                 return false;
1127
1128         if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
1129                 return false;
1130
1131         mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
1132         pos = (mw->GetModeChar()-65) | mask;
1133
1134         ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
1135
1136         if (a == modewatchers[pos].end())
1137         {
1138                 return false;
1139         }
1140
1141         modewatchers[pos].erase(a);
1142
1143         return true;
1144 }
1145
1146 /** This default implementation can remove simple user modes
1147  */
1148 void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
1149 {
1150         char moderemove[MAXBUF];
1151         std::vector<std::string> parameters;
1152
1153         if (user->IsModeSet(this->GetModeChar()))
1154         {
1155                 if (stack)
1156                 {
1157                         stack->Push(this->GetModeChar());
1158                 }
1159                 else
1160                 {
1161                         sprintf(moderemove,"-%c",this->GetModeChar());
1162                         parameters.push_back(user->nick);
1163                         parameters.push_back(moderemove);
1164                         ServerInstance->Modes->Process(parameters, ServerInstance->FakeClient, false);
1165                 }
1166         }
1167 }
1168
1169 /** This default implementation can remove simple channel modes
1170  * (no parameters)
1171  */
1172 void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack)
1173 {
1174         char moderemove[MAXBUF];
1175         std::vector<std::string> parameters;
1176
1177         if (channel->IsModeSet(this->GetModeChar()))
1178         {
1179                 if (stack)
1180                 {
1181                         stack->Push(this->GetModeChar());
1182                 }
1183                 else
1184                 {
1185                         sprintf(moderemove,"-%c",this->GetModeChar());
1186                         parameters.push_back(channel->name);
1187                         parameters.push_back(moderemove);
1188                         ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
1189                 }
1190         }
1191 }
1192
1193 ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
1194 {
1195         ModeHandler* modes[] =
1196         {
1197                 new ModeChannelSecret(Instance),
1198                 new ModeChannelPrivate(Instance),
1199                 new ModeChannelModerated(Instance),
1200                 new ModeChannelTopicOps(Instance),
1201                 new ModeChannelNoExternal(Instance),
1202                 new ModeChannelInviteOnly(Instance),
1203                 new ModeChannelKey(Instance),
1204                 new ModeChannelLimit(Instance),
1205                 new ModeChannelBan(Instance),
1206                 new ModeChannelOp(Instance),
1207                 new ModeChannelHalfOp(Instance),
1208                 new ModeChannelVoice(Instance),
1209                 new ModeUserWallops(Instance),
1210                 new ModeUserInvisible(Instance),
1211                 new ModeUserOperator(Instance),
1212                 new ModeUserServerNoticeMask(Instance),
1213                 NULL
1214         };
1215
1216         /* Clear mode handler list */
1217         memset(modehandlers, 0, sizeof(modehandlers));
1218
1219         /* Last parse string */
1220         LastParse.clear();
1221
1222         /* Initialise the RFC mode letters */
1223         for (int index = 0; modes[index]; index++)
1224                 this->AddMode(modes[index]);
1225
1226         seq = 0;
1227         memset(&sent, 0, sizeof(sent));
1228 }