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