1 /*
2 * InspIRCd -- Internet Relay Chat Daemon
3 *
4 * Copyright (C) 2013-2016 Attila Molnar <attilamolnar@hush.com>
5 * Copyright (C) 2012-2013, 2017-2021 Sadie Powell <sadie@witchery.services>
6 * Copyright (C) 2012 Robby <robby@chatbelgie.be>
7 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
8 * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
9 * Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
10 * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
11 * Copyright (C) 2006-2008, 2010 Craig Edwards <brain@inspircd.org>
12 *
13 * This file is part of InspIRCd. InspIRCd is free software: you can
14 * redistribute it and/or modify it under the terms of the GNU General Public
15 * License as published by the Free Software Foundation, version 2.
16 *
17 * This program is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
20 * details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26
27 #pragma once
28
29 #include "ctables.h"
30 #include "modechange.h"
31
32 /**
33 * Holds the values for different type of modes
34 * that can exist, USER or CHANNEL type.
35 */
36 enum ModeType
37 {
38 /** User mode */
39 MODETYPE_USER = 0,
40 /** Channel mode */
41 MODETYPE_CHANNEL = 1
42 };
43
44 /**
45 * Holds mode actions - modes can be allowed or denied.
46 */
47 enum ModeAction
48 {
49 MODEACTION_DENY = 0, /* Drop the mode change, AND a parameter if its a parameterized mode */
50 MODEACTION_ALLOW = 1 /* Allow the mode */
51 };
52
53 /**
54 * These fixed values can be used to proportionally compare module-defined prefixes to known values.
55 * For example, if your module queries a Channel, and is told that user 'joebloggs' has the prefix
56 * '$', and you dont know what $ means, then you can compare it to these three values to determine
57 * its worth against them. For example if '$' had a value of 15000, you would know it is of higher
58 * status than voice, but lower status than halfop.
59 * No two modes should have equal prefix values.
60 */
61 enum PrefixModeValue
62 {
63 /* +v */
64 VOICE_VALUE = 10000,
65 /* +h */
66 HALFOP_VALUE = 20000,
67 /* +o */
68 OP_VALUE = 30000
69 };
70
71 enum ParamSpec
72 {
73 /** No parameters */
74 PARAM_NONE,
75 /** Parameter required on mode setting only */
76 PARAM_SETONLY,
77 /** Parameter always required */
78 PARAM_ALWAYS
79 };
80
81 class PrefixMode;
82 class ListModeBase;
83 class ParamModeBase;
84
85 /** Each mode is implemented by ONE ModeHandler class.
86 * You must derive ModeHandler and add the child class to
87 * the list of modes handled by the ircd, using
88 * ModeParser::AddMode. When the mode you implement is
89 * set by a user, the virtual function OnModeChange is
90 * called. If you specify a value greater than 0 for
91 * parameters_on or parameters_off, then when the mode is
92 * set or unset respectively, std::string ¶meter will
93 * contain the parameter given by the user, else it will
94 * contain an empty string. You may alter this parameter
95 * string, and if you alter it to an empty string, and your
96 * mode is expected to have a parameter, then this is
97 * equivalent to returning MODEACTION_DENY.
98 */
99 class CoreExport ModeHandler : public ServiceProvider
100 {
101 public:
102 typedef size_t Id;
103
104 enum Class
105 {
106 MC_PREFIX,
107 MC_LIST,
108 MC_PARAM,
109 MC_OTHER
110 };
111
112 private:
113 /** The opaque id of this mode assigned by the mode parser
114 */
115 Id modeid;
116
117 protected:
118 /** What kind of parameters does the mode take?
119 */
120 ParamSpec parameters_taken;
121
122 /**
123 * The mode letter you're implementing.
124 */
125 char mode;
126
127 /**
128 * True if the mode requires oper status
129 * to set.
130 */
131 bool oper;
132
133 /**
134 * Mode is a 'list' mode. The behaviour
135 * of your mode is now set entirely within
136 * the class as of the 1.1 api, rather than
137 * inside the mode parser as in the 1.0 api,
138 * so the only use of this value (along with
139 * IsListMode()) is for the core to determine
140 * whether your module can produce 'lists' or not
141 * (e.g. banlists, etc)
142 */
143 bool list;
144
145 /**
146 * The mode type, either MODETYPE_USER or
147 * MODETYPE_CHANNEL.
148 */
149 ModeType m_type;
150
151 /** The object type of this mode handler
152 */
153 const Class type_id;
154
155 /** The prefix rank required to set this mode on channels. */
156 unsigned int ranktoset;
157
158 /** The prefix rank required to unset this mode on channels. */
159 unsigned int ranktounset;
160
161 /** If non-empty then the syntax of the parameter for this mode. */
162 std::string syntax;
163
164 public:
165 /**
166 * The constructor for ModeHandler initializes the mode handler.
167 * The constructor of any class you derive from ModeHandler should
168 * probably call this constructor with the parameters set correctly.
169 * @param me The module which created this mode
170 * @param name A one-word name for the mode
171 * @param modeletter The mode letter you wish to handle
172 * @param params Parameters taken by the mode
173 * @param type Type of the mode (MODETYPE_USER or MODETYPE_CHANNEL)
174 * @param mclass The object type of this mode handler, one of ModeHandler::Class
175 */
176 ModeHandler(Module* me, const std::string& name, char modeletter, ParamSpec params, ModeType type, Class mclass = MC_OTHER);
177 CullResult cull() CXX11_OVERRIDE;
178 virtual ~ModeHandler();
179
180 /** Register this object in the ModeParser
181 */
182 void RegisterService() CXX11_OVERRIDE;
183
184 /**
185 * Returns true if the mode is a list mode
186 */
IsListMode()187 bool IsListMode() const { return list; }
188
189 /**
190 * Check whether this mode is a prefix mode
191 * @return non-NULL if this mode is a prefix mode, NULL otherwise
192 */
193 PrefixMode* IsPrefixMode();
194
195 /**
196 * Check whether this mode is a prefix mode
197 * @return non-NULL if this mode is a prefix mode, NULL otherwise
198 */
199 const PrefixMode* IsPrefixMode() const;
200
201 /**
202 * Check whether this mode handler inherits from ListModeBase
203 * @return non-NULL if this mode handler inherits from ListModeBase, NULL otherwise
204 */
205 ListModeBase* IsListModeBase();
206
207 /**
208 * Check whether this mode handler inherits from ListModeBase
209 * @return non-NULL if this mode handler inherits from ListModeBase, NULL otherwise
210 */
211 const ListModeBase* IsListModeBase() const;
212
213 /**
214 * Check whether this mode handler inherits from ParamModeBase
215 * @return non-NULL if this mode handler inherits from ParamModeBase, NULL otherwise
216 */
217 ParamModeBase* IsParameterMode();
218
219 /**
220 * Check whether this mode handler inherits from ParamModeBase
221 * @return non-NULL if this mode handler inherits from ParamModeBase, NULL otherwise
222 */
223 const ParamModeBase* IsParameterMode() const;
224
225 /**
226 * Returns the mode's type
227 */
GetModeType()228 inline ModeType GetModeType() const { return m_type; }
229 /**
230 * Returns true if the mode can only be set/unset by an oper
231 */
NeedsOper()232 inline bool NeedsOper() const { return oper; }
233 /**
234 * Check if the mode needs a parameter for adding or removing
235 * @param adding True to check if the mode needs a parameter when setting, false to check if the mode needs a parameter when unsetting
236 * @return True if the mode needs a parameter for the specified action, false if it doesn't
237 */
238 bool NeedsParam(bool adding) const;
239 /**
240 * Returns the mode character this handler handles.
241 * @return The mode character
242 */
GetModeChar()243 char GetModeChar() const { return mode; }
244
245 /** Return the id of this mode which is used in User::modes and
246 * Channel::modes as the index to determine whether a mode is set.
247 */
GetId()248 Id GetId() const { return modeid; }
249
250 /** For user modes, return the current parameter, if any
251 */
252 virtual std::string GetUserParameter(const User* user) const;
253
254 /**
255 * Called when a channel mode change access check for your mode occurs.
256 * @param source Contains the user setting the mode.
257 * @param channel contains the destination channel the modes are being set on.
258 * @param parameter The parameter for your mode. This is modifiable.
259 * @param adding This value is true when the mode is being set, or false when it is being unset.
260 * @return allow, deny, or passthru to check against the required level
261 */
262 virtual ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding);
263
264 /**
265 * Called when a mode change for your mode occurs.
266 * @param source Contains the user setting the mode.
267 * @param dest For usermodes, contains the destination user the mode is being set on. For channelmodes, this is an undefined value.
268 * @param channel For channel modes, contains the destination channel the modes are being set on. For usermodes, this is an undefined value.
269 * @param parameter The parameter for your mode, if you indicated that your mode requires a parameter when being set or unset. Note that
270 * if you alter this value, the new value becomes the one displayed and send out to the network, also, if you set this to an empty string
271 * but you specified your mode REQUIRES a parameter, this is equivalent to returning MODEACTION_DENY and will prevent the mode from being
272 * displayed.
273 * @param adding This value is true when the mode is being set, or false when it is being unset.
274 * @return MODEACTION_ALLOW to allow the mode, or MODEACTION_DENY to prevent the mode, also see the description of 'parameter'.
275 */
276 virtual ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding); /* Can change the mode parameter as its a ref */
277
278 /**
279 * If your mode is a listmode, then this method will be called for displaying an item list, e.g. on MODE \#channel +modechar
280 * without any parameter or other modes in the command.
281 * @param user The user issuing the command
282 * @param channel The channel they're requesting an item list of (e.g. a banlist, or an exception list etc)
283 */
284 virtual void DisplayList(User* user, Channel* channel);
285
286 /** In the event that the mode should be given a parameter, and no parameter was provided, this method is called.
287 * This allows you to give special information to the user, or handle this any way you like.
288 * @param user The user issuing the mode change
289 * @param dest For user mode changes, the target of the mode. For channel mode changes, NULL.
290 * @param channel For channel mode changes, the target of the mode. For user mode changes, NULL.
291 */
292 virtual void OnParameterMissing(User* user, User* dest, Channel* channel);
293
294 /** Called when a user attempts to set a mode and the parameter is invalid.
295 * @param user The user issuing the mode change
296 * @param targetchannel Either the channel target or NULL if changing a user mode.
297 * @param targetuser Either the user target or NULL if changing a channel mode.
298 * @param parameter The invalid parameter.
299 */
300 virtual void OnParameterInvalid(User* user, Channel* targetchannel, User* targetuser, const std::string& parameter);
301
302
303 /**
304 * If your mode is a listmode, this method will be called to display an empty list (just the end of list numeric)
305 * @param user The user issuing the command
306 * @param channel The channel they're requesting an item list of (e.g. a banlist, or an exception list etc)
307 */
308 virtual void DisplayEmptyList(User* user, Channel* channel);
309
310 /**
311 * If your mode needs special action during a server sync to determine which side wins when comparing timestamps,
312 * override this function and use it to return true or false. The default implementation just returns true if
313 * theirs < ours. This will only be called for non-listmodes with parameters, when adding the mode and where
314 * theirs == ours (therefore the default implementation will always return false).
315 * @param their_param Their parameter if the mode has a parameter
316 * @param our_param Our parameter if the mode has a parameter
317 * @param channel The channel we are checking against
318 * @return True if the other side wins the merge, false if we win the merge for this mode.
319 */
320 virtual bool ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel* channel);
321
322 /**
323 * When a MODETYPE_USER mode handler is being removed, the core will call this method for every user on the server.
324 * The usermode will be removed using the appropriate server mode using InspIRCd::SendMode().
325 * @param user The user which the server wants to remove your mode from
326 */
327 void RemoveMode(User* user);
328
329 /**
330 * When a MODETYPE_CHANNEL mode handler is being removed, the server will call this method for every channel on the server.
331 * The mode handler has to populate the given modestacker with mode changes that remove the mode from the channel.
332 * The default implementation of this method can remove all kinds of channel modes except listmodes.
333 * In the case of listmodes, the entire list of items must be added to the modestacker (which is handled by ListModeBase,
334 * so if you inherit from it or your mode can be removed by the default implementation then you do not have to implement
335 * this function).
336 * @param channel The channel which the server wants to remove your mode from
337 * @param changelist Mode change list to populate with the removal of this mode
338 */
339 virtual void RemoveMode(Channel* channel, Modes::ChangeList& changelist);
340
341 /** Retrieves the level required to modify this mode.
342 * @param adding Whether the mode is being added or removed.
343 */
GetLevelRequired(bool adding)344 inline unsigned int GetLevelRequired(bool adding) const
345 {
346 return adding ? ranktoset : ranktounset;
347 }
348
349 /** Retrieves the syntax of the parameter for this mode. */
GetSyntax()350 const std::string& GetSyntax() const { return syntax; }
351
352 friend class ModeParser;
353 };
354
355 /**
356 * Prefix modes are channel modes that grant a specific rank to members having prefix mode set.
357 * They require a parameter when setting and unsetting; the parameter is always a member of the channel.
358 * A prefix mode may be set on any number of members on a channel, but for a given member a given prefix
359 * mode is either set or not set, in other words members cannot have the same prefix mode set more than once.
360 *
361 * A rank of a member is defined as the rank given by the 'strongest' prefix mode that member has.
362 * Other parts of the IRCd use this rank to determine whether a channel action is allowable for a user or not.
363 * The rank of a prefix mode is constant, i.e. the same rank value is given to all users having that prefix mode set.
364 *
365 * Note that it is possible that the same action requires a different rank on a different channel;
366 * for example changing the topic on a channel having +t set requires a rank that is >= than the rank of a halfop,
367 * but there is no such restriction when +t isn't set.
368 */
369 class CoreExport PrefixMode : public ModeHandler
370 {
371 protected:
372 /** The prefix character granted by this mode. '@' for op, '+' for voice, etc.
373 * If 0, this mode does not have a visible prefix character.
374 */
375 char prefix;
376
377 /** The prefix rank of this mode, used to compare prefix
378 * modes
379 */
380 unsigned int prefixrank;
381
382 /** Whether a client with this prefix can remove it from themself. */
383 bool selfremove;
384
385 public:
386 /**
387 * Constructor
388 * @param Creator The module creating this mode
389 * @param Name The user-friendly one word name of the prefix mode, e.g.: "op", "voice"
390 * @param ModeLetter The mode letter of this mode
391 * @param Rank Rank given by this prefix mode, see explanation above
392 * @param PrefixChar Prefix character, or 0 if the mode has no prefix character
393 */
394 PrefixMode(Module* Creator, const std::string& Name, char ModeLetter, unsigned int Rank = 0, char PrefixChar = 0);
395
396 /**
397 * Called when a channel mode change access check for your mode occurs.
398 * @param source Contains the user setting the mode.
399 * @param channel contains the destination channel the modes are being set on.
400 * @param parameter The parameter for your mode. This is modifiable.
401 * @param adding This value is true when the mode is being set, or false when it is being unset.
402 * @return allow, deny, or passthru to check against the required level
403 */
404 ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding) CXX11_OVERRIDE;
405
406 /**
407 * Handles setting and unsetting the prefix mode.
408 * Finds the given member of the given channel, if it's not found an error message is sent to 'source'
409 * and MODEACTION_DENY is returned. Otherwise the mode change is attempted.
410 * @param source Source of the mode change, an error message is sent to this user if the target is not found
411 * @param dest Unused
412 * @param channel The channel the mode change is happening on
413 * @param param The nickname or uuid of the target user
414 * @param adding True when the mode is being set, false when it is being unset
415 * @return MODEACTION_ALLOW if the change happened, MODEACTION_DENY if no change happened
416 * The latter occurs either when the member cannot be found or when the member already has this prefix set
417 * (when setting) or doesn't have this prefix set (when unsetting).
418 */
419 ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& param, bool adding) CXX11_OVERRIDE;
420
421 /**
422 * Updates the configuration of this prefix.
423 * @param rank The prefix rank of this mode.
424 * @param setrank The prefix rank required to set this mode on channels.
425 * @param unsetrank The prefix rank required to set this unmode on channels.
426 * @param selfrm Whether a client with this prefix can remove it from themself.
427 */
428 void Update(unsigned int rank, unsigned int setrank, unsigned int unsetrank, bool selfrm);
429
430 /**
431 * Removes this prefix mode from all users on the given channel
432 * @param channel The channel which the server wants to remove your mode from
433 * @param changelist Mode change list to populate with the removal of this mode
434 */
435 void RemoveMode(Channel* channel, Modes::ChangeList& changelist) CXX11_OVERRIDE;
436
437
438 /**
439 * Determines whether a user with this prefix mode can remove it.
440 */
CanSelfRemove()441 bool CanSelfRemove() const { return selfremove; }
442
443 /**
444 * Mode prefix or 0. If this is defined, you should
445 * also implement GetPrefixRank() to return an integer
446 * value for this mode prefix.
447 */
GetPrefix()448 char GetPrefix() const { return prefix; }
449
450 /**
451 * Get the 'value' of this modes prefix.
452 * determines which to display when there are multiple.
453 * The mode with the highest value is ranked first. See the
454 * PrefixModeValue enum and Channel::GetPrefixValue() for
455 * more information.
456 */
GetPrefixRank()457 unsigned int GetPrefixRank() const { return prefixrank; }
458 };
459
460 /** A prebuilt mode handler which handles a simple user mode, e.g. no parameters, usable by any user, with no extra
461 * behaviour to the mode beyond the basic setting and unsetting of the mode, not allowing the mode to be set if it
462 * is already set and not allowing it to be unset if it is already unset.
463 * An example of a simple user mode is user mode +w.
464 */
465 class CoreExport SimpleUserModeHandler : public ModeHandler
466 {
467 public:
468 SimpleUserModeHandler(Module* Creator, const std::string& Name, char modeletter, bool operonly = false)
ModeHandler(Creator,Name,modeletter,PARAM_NONE,MODETYPE_USER)469 : ModeHandler(Creator, Name, modeletter, PARAM_NONE, MODETYPE_USER)
470 {
471 oper = operonly;
472 }
473
474 ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE;
475 };
476
477 /** A prebuilt mode handler which handles a simple channel mode, e.g. no parameters, usable by any user, with no extra
478 * behaviour to the mode beyond the basic setting and unsetting of the mode, not allowing the mode to be set if it
479 * is already set and not allowing it to be unset if it is already unset.
480 * An example of a simple channel mode is channel mode +s.
481 */
482 class CoreExport SimpleChannelModeHandler : public ModeHandler
483 {
484 public:
485 SimpleChannelModeHandler(Module* Creator, const std::string& Name, char modeletter, bool operonly = false)
ModeHandler(Creator,Name,modeletter,PARAM_NONE,MODETYPE_CHANNEL)486 : ModeHandler(Creator, Name, modeletter, PARAM_NONE, MODETYPE_CHANNEL)
487 {
488 oper = operonly;
489 }
490
491 ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE;
492 };
493
494 /**
495 * The ModeWatcher class can be used to alter the behaviour of a mode implemented
496 * by the core or by another module. To use ModeWatcher, derive a class from it,
497 * and attach it to the mode using Server::AddModeWatcher and Server::DelModeWatcher.
498 * A ModeWatcher will be called both before and after the mode change.
499 */
500 class CoreExport ModeWatcher : public classbase
501 {
502 private:
503 /**
504 * The mode name this class is watching
505 */
506 const std::string mode;
507
508 /**
509 * The mode type being watched (user or channel)
510 */
511 ModeType m_type;
512
513 public:
514 ModuleRef creator;
515 /**
516 * The constructor initializes the mode and the mode type
517 */
518 ModeWatcher(Module* creator, const std::string& modename, ModeType type);
519 /**
520 * The default destructor does nothing.
521 */
522 virtual ~ModeWatcher();
523
524 /**
525 * Get the mode name being watched
526 * @return The mode name being watched
527 */
GetModeName()528 const std::string& GetModeName() const { return mode; }
529
530 /**
531 * Get the mode type being watched
532 * @return The mode type being watched (user or channel)
533 */
GetModeType()534 ModeType GetModeType() const { return m_type; }
535
536 /**
537 * Before the mode character is processed by its handler, this method will be called.
538 * @param source The sender of the mode
539 * @param dest The target user for the mode, if you are watching a user mode
540 * @param channel The target channel for the mode, if you are watching a channel mode
541 * @param parameter The parameter of the mode, if the mode is supposed to have a parameter.
542 * If you alter the parameter you are given, the mode handler will see your altered version
543 * when it handles the mode.
544 * @param adding True if the mode is being added and false if it is being removed
545 * @return True to allow the mode change to go ahead, false to abort it. If you abort the
546 * change, the mode handler (and ModeWatcher::AfterMode()) will never see the mode change.
547 */
548 virtual bool BeforeMode(User* source, User* dest, Channel* channel, std::string& parameter, bool adding);
549 /**
550 * After the mode character has been processed by the ModeHandler, this method will be called.
551 * @param source The sender of the mode
552 * @param dest The target user for the mode, if you are watching a user mode
553 * @param channel The target channel for the mode, if you are watching a channel mode
554 * @param parameter The parameter of the mode, if the mode is supposed to have a parameter.
555 * You cannot alter the parameter here, as the mode handler has already processed it.
556 * @param adding True if the mode is being added and false if it is being removed
557 */
558 virtual void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding);
559 };
560
561 /** The mode parser handles routing of modes and handling of mode strings.
562 * It marshalls, controls and maintains both ModeWatcher and ModeHandler classes,
563 * parses client to server MODE strings for user and channel modes, and performs
564 * processing for the 004 mode list numeric, amongst other things.
565 */
566 class CoreExport ModeParser : public fakederef<ModeParser>
567 {
568 public:
569 /** The maximum number of modes which can be created. */
570 static const ModeHandler::Id MODEID_MAX = 64;
571
572 /** The maximum length of a mode parameter. */
573 static const size_t MODE_PARAM_MAX = 250;
574
575 /** Type of the container that maps mode names to ModeHandlers
576 */
577 typedef TR1NS::unordered_map<std::string, ModeHandler*, irc::insensitive, irc::StrHashComp> ModeHandlerMap;
578
579 private:
580 /** Type of the container that maps mode names to ModeWatchers
581 */
582 typedef insp::flat_multimap<std::string, ModeWatcher*> ModeWatcherMap;
583
584 /** Last item in the ModeType enum
585 */
586 static const unsigned int MODETYPE_LAST = 2;
587
588 /** Mode handlers for each mode, to access a handler subtract
589 * 65 from the ascii value of the mode letter.
590 * The upper bit of the value indicates if its a usermode
591 * or a channel mode, so we have 256 of them not 64.
592 */
593 ModeHandler* modehandlers[MODETYPE_LAST][128];
594
595 /** An array of mode handlers indexed by the mode id
596 */
597 ModeHandler* modehandlersbyid[MODETYPE_LAST][MODEID_MAX];
598
599 /** A map of mode handlers keyed by their name
600 */
601 ModeHandlerMap modehandlersbyname[MODETYPE_LAST];
602
603 /** Lists of mode handlers by type
604 */
605 struct
606 {
607 /** List of mode handlers that inherit from ListModeBase
608 */
609 std::vector<ListModeBase*> list;
610
611 /** List of mode handlers that inherit from PrefixMode
612 */
613 std::vector<PrefixMode*> prefix;
614 } mhlist;
615
616 /** Mode watcher classes
617 */
618 ModeWatcherMap modewatchermap;
619
620 /** Last processed mode change
621 */
622 Modes::ChangeList LastChangeList;
623
624 /** Attempts to apply a mode change to a user or channel
625 * @param user The user who triggered the mode change.
626 * @param usertarget If non-NULL then the user to change the modes of.
627 * @param chantarget If non-NULL then the channel to change the modes of.
628 * @param mcitem The actual mode change to attempt.
629 * @param skipacl Whether to skip access checks for the mode change.
630 */
631 ModeAction TryMode(User* user, User* usertarget, Channel* chantarget, Modes::Change& mcitem, bool skipacl);
632
633 /** Allocates an unused id for the given mode type, throws a ModuleException if out of ids.
634 * @param mt The type of the mode to allocate the id for
635 * @return The id
636 */
637 ModeHandler::Id AllocateModeId(ModeType mt);
638
639 public:
640 typedef std::vector<ListModeBase*> ListModeList;
641 typedef std::vector<PrefixMode*> PrefixModeList;
642
643 typedef unsigned int ModeProcessFlag;
644 enum ModeProcessFlags
645 {
646 /** If only this flag is specified, the mode change will be global
647 * and parameter modes will have their parameters explicitly set
648 * (not merged). This is the default.
649 */
650 MODE_NONE = 0,
651
652 /** If this flag is set then the parameters of non-listmodes will be
653 * merged according to their conflict resolution rules.
654 * Does not affect user modes, channel modes without a parameter and
655 * listmodes.
656 */
657 MODE_MERGE = 1,
658
659 /** If this flag is set then the linking module will ignore the mode change
660 * and not send it to other servers. The mode change will be processed
661 * locally and sent to local user(s) as usual.
662 */
663 MODE_LOCALONLY = 2,
664
665 /** If this flag is set then the mode change will be subject to access checks.
666 * For more information see the documentation of the PrefixMode class,
667 * ModeHandler::ranktoset and ModeHandler::AccessCheck().
668 * Modules may explicitly allow a mode change regardless of this flag by returning
669 * MOD_RES_ALLOW from the OnPreMode hook. Only affects channel mode changes.
670 */
671 MODE_CHECKACCESS = 4
672 };
673
674 ModeParser();
675 ~ModeParser();
676
677 static bool IsModeChar(char chr);
678
679 /** Tidy a banmask. This makes a banmask 'acceptable' if fields are left out.
680 * E.g.
681 *
682 * nick -> nick!*@*
683 *
684 * nick!ident -> nick!ident@*
685 *
686 * host.name -> *!*\@host.name
687 *
688 * ident\@host.name -> *!ident\@host.name
689 *
690 * This method can be used on both IPV4 and IPV6 user masks.
691 */
692 static void CleanMask(std::string &mask);
693
694 /** Gets the last mode change to be processed. */
GetLastChangeList()695 const Modes::ChangeList& GetLastChangeList() const { return LastChangeList; }
696
697 /** Add a mode to the mode parser.
698 * Throws a ModuleException if the mode cannot be added.
699 */
700 void AddMode(ModeHandler* mh);
701
702 /** Delete a mode from the mode parser.
703 * When a mode is deleted, the mode handler will be called
704 * for every user (if it is a user mode) or for every channel
705 * (if it is a channel mode) to unset the mode on all objects.
706 * This prevents modes staying in the system which no longer exist.
707 * @param mh The mode handler to remove
708 * @return True if the mode was successfully removed.
709 */
710 bool DelMode(ModeHandler* mh);
711
712 /** Add a mode watcher.
713 * A mode watcher is triggered before and after a mode handler is
714 * triggered. See the documentation of class ModeWatcher for more
715 * information.
716 * @param mw The ModeWatcher you want to add
717 */
718 void AddModeWatcher(ModeWatcher* mw);
719
720 /** Delete a mode watcher.
721 * A mode watcher is triggered before and after a mode handler is
722 * triggered. See the documentation of class ModeWatcher for more
723 * information.
724 * @param mw The ModeWatcher you want to delete
725 * @return True if the ModeWatcher was deleted correctly
726 */
727 bool DelModeWatcher(ModeWatcher* mw);
728
729 /** Process a list of mode changes entirely. If the mode changes do not fit into one MODE line
730 * then multiple MODE lines are generated.
731 * @param user The source of the mode change, can be a server user.
732 * @param targetchannel Channel to apply the mode change on. NULL if changing modes on a channel.
733 * @param targetuser User to apply the mode change on. NULL if changing modes on a user.
734 * @param changelist Modes to change in form of a Modes::ChangeList.
735 * @param flags Optional flags controlling how the mode change is processed,
736 * defaults to MODE_NONE.
737 */
738 void Process(User* user, Channel* targetchannel, User* targetuser, Modes::ChangeList& changelist, ModeProcessFlag flags = MODE_NONE);
739
740 /** Process a single MODE line's worth of mode changes, taking max modes and line length limits
741 * into consideration. Return value indicates how many modes were processed.
742 * @param user The source of the mode change, can be a server user.
743 * @param targetchannel Channel to apply the mode change on. NULL if changing modes on a channel.
744 * @param targetuser User to apply the mode change on. NULL if changing modes on a user.
745 * @param changelist Modes to change in form of a Modes::ChangeList. May not process
746 * the entire list due to MODE line length and max modes limitations.
747 * @param flags Optional flags controlling how the mode change is processed,
748 * defaults to MODE_NONE.
749 * @param beginindex Index of the first element in changelist to process. Mode changes before
750 * the element with this index are ignored.
751 * @return Number of mode changes processed from changelist.
752 */
753 unsigned int ProcessSingle(User* user, Channel* targetchannel, User* targetuser, Modes::ChangeList& changelist, ModeProcessFlag flags = MODE_NONE, unsigned int beginindex = 0);
754
755 /** Turn a list of parameters compatible with the format of the MODE command into
756 * Modes::ChangeList form. All modes are processed, regardless of max modes. Unknown modes
757 * are skipped.
758 * @param user The source of the mode change, can be a server user. Error numerics are sent to
759 * this user.
760 * @param type MODETYPE_USER if this is a user mode change or MODETYPE_CHANNEL if this
761 * is a channel mode change.
762 * @param parameters List of strings describing the mode change to convert to a ChangeList.
763 * Must be using the same format as the parameters of a MODE command.
764 * @param changelist ChangeList object to populate.
765 * @param beginindex Index of the first element that is part of the MODE list in the parameters
766 * container. Defaults to 1.
767 * @param endindex Index of the first element that is not part of the MODE list. By default,
768 * the entire container is considered part of the MODE list.
769 */
770 void ModeParamsToChangeList(User* user, ModeType type, const std::vector<std::string>& parameters, Modes::ChangeList& changelist, unsigned int beginindex = 1, unsigned int endindex = UINT_MAX);
771
772 /** Find the mode handler for a given mode name and type.
773 * @param modename The mode name to search for.
774 * @param mt Type of mode to search for, user or channel.
775 * @return A pointer to a ModeHandler class, or NULL of there isn't a handler for the given mode name.
776 */
777 ModeHandler* FindMode(const std::string& modename, ModeType mt);
778
779 /** Find the mode handler for a given mode and type.
780 * @param modeletter mode letter to search for
781 * @param mt type of mode to search for, user or channel
782 * @returns a pointer to a ModeHandler class, or NULL of there isn't a handler for the given mode
783 */
784 ModeHandler* FindMode(unsigned const char modeletter, ModeType mt);
785
786 /** Find the mode handler for the given prefix mode
787 * @param modeletter The mode letter to search for
788 * @return A pointer to the PrefixMode or NULL if the mode wasn't found or it isn't a prefix mode
789 */
790 PrefixMode* FindPrefixMode(unsigned char modeletter);
791
792 /** Find a mode handler by its prefix.
793 * If there is no mode handler with the given prefix, NULL will be returned.
794 * @param pfxletter The prefix to find, e.g. '@'
795 * @return The mode handler which handles this prefix, or NULL if there is none.
796 */
797 PrefixMode* FindPrefix(unsigned const char pfxletter);
798
799 /** Generates a list of modes, comma separated by type:
800 * 1; Listmodes EXCEPT those with a prefix
801 * 2; Modes that take a param when adding or removing
802 * 3; Modes that only take a param when adding
803 * 4; Modes that dont take a param
804 */
805 std::string GiveModeList(ModeType mt);
806
807 /** This returns the PREFIX=(ohv)@%+ section of the 005 numeric, or
808 * just the "@%+" part if the parameter false
809 */
810 std::string BuildPrefixes(bool lettersAndModes = true);
811
812 /** Get a list of all mode handlers that inherit from ListModeBase
813 * @return A list containing ListModeBase modes
814 */
GetListModes()815 const ListModeList& GetListModes() const { return mhlist.list; }
816
817 /** Get a list of all prefix modes
818 * @return A list containing all prefix modes
819 */
GetPrefixModes()820 const PrefixModeList& GetPrefixModes() const { return mhlist.prefix; }
821
822 /** Get a mode name -> ModeHandler* map containing all modes of the given type
823 * @param mt Type of modes to return, MODETYPE_USER or MODETYPE_CHANNEL
824 * @return A map of mode handlers of the given type
825 */
GetModes(ModeType mt)826 const ModeHandlerMap& GetModes(ModeType mt) const { return modehandlersbyname[mt]; }
827
828 /** Show the list of a list mode to a user. Modules can deny the listing.
829 * @param user User to show the list to.
830 * @param chan Channel to show the list of.
831 * @param mh List mode to show the list of.
832 */
833 void ShowListModeList(User* user, Channel* chan, ModeHandler* mh);
834 };
835
IsPrefixMode()836 inline PrefixMode* ModeHandler::IsPrefixMode()
837 {
838 return (this->type_id == MC_PREFIX ? static_cast<PrefixMode*>(this) : NULL);
839 }
840
IsPrefixMode()841 inline const PrefixMode* ModeHandler::IsPrefixMode() const
842 {
843 return (this->type_id == MC_PREFIX ? static_cast<const PrefixMode*>(this) : NULL);
844 }
845
IsListModeBase()846 inline ListModeBase* ModeHandler::IsListModeBase()
847 {
848 return (this->type_id == MC_LIST ? reinterpret_cast<ListModeBase*>(this) : NULL);
849 }
850
IsListModeBase()851 inline const ListModeBase* ModeHandler::IsListModeBase() const
852 {
853 return (this->type_id == MC_LIST ? reinterpret_cast<const ListModeBase*>(this) : NULL);
854 }
855
IsParameterMode()856 inline ParamModeBase* ModeHandler::IsParameterMode()
857 {
858 return (this->type_id == MC_PARAM ? reinterpret_cast<ParamModeBase*>(this) : NULL);
859 }
860
IsParameterMode()861 inline const ParamModeBase* ModeHandler::IsParameterMode() const
862 {
863 return (this->type_id == MC_PARAM ? reinterpret_cast<const ParamModeBase*>(this) : NULL);
864 }
865