From d3d64c27b199622c90075d6f59dd08e44acbb378 Mon Sep 17 00:00:00 2001 From: Adam- Date: Tue, 13 Oct 2009 21:26:38 +0000 Subject: Complete rewrite of everything associated with modes, this breaks saving and reading mlocked modes from the databases until the new databases are implemented git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2560 5417fbe8-f217-4b02-8779-1006273d7864 --- include/extern.h | 57 --- include/modules.h | 7 - include/regchannel.h | 131 ++++++- include/services.h | 587 ++++++++++++++++++++++------ include/users.h | 29 +- lang/cat.l | 4 - lang/de.l | 5 - lang/en_us.l | 4 - lang/es.l | 4 - lang/fr.l | 4 - lang/gr.l | 4 - lang/hun.l | 4 - lang/it.l | 4 - lang/nl.l | 4 - lang/pl.l | 6 - lang/pt.l | 4 - lang/ru.l | 4 - lang/tr.l | 4 - src/Makefile | 3 +- src/botserv.c | 26 +- src/channels.c | 927 ++++++++++++++++++++++++-------------------- src/chanserv.c | 584 ++++++++++++---------------- src/core/cs_access.c | 2 +- src/core/cs_akick.c | 3 +- src/core/cs_ban.c | 4 +- src/core/cs_clear.c | 111 ++---- src/core/cs_drop.c | 4 +- src/core/cs_forbid.c | 21 +- src/core/cs_getkey.c | 5 +- src/core/cs_info.c | 7 +- src/core/cs_modes.c | 138 ++++--- src/core/cs_register.c | 11 +- src/core/cs_set.c | 100 ++--- src/core/cs_xop.c | 4 +- src/core/os_chanlist.c | 29 +- src/core/os_clearmodes.c | 107 +---- src/core/os_userlist.c | 27 +- src/ircd.c | 127 ------ src/modes.cpp | 364 +++++++++++++++++ src/modules.c | 58 --- src/modules/cs_enforce.c | 9 +- src/modules/cs_tban.c | 4 +- src/nickserv.c | 4 +- src/operserv.c | 83 ++-- src/protocol/bahamut.c | 411 +++----------------- src/protocol/inspircd11.c | 423 ++++---------------- src/protocol/inspircd12.cpp | 406 ++++--------------- src/protocol/ratbox.c | 379 +++--------------- src/protocol/unreal32.c | 533 ++++++------------------- src/users.c | 82 +++- 50 files changed, 2487 insertions(+), 3375 deletions(-) create mode 100644 src/modes.cpp diff --git a/include/extern.h b/include/extern.h index 8a767ba39..6faae04c7 100644 --- a/include/extern.h +++ b/include/extern.h @@ -29,15 +29,7 @@ E char *uplink; E IRCDVar *ircd; E IRCDCAPAB *ircdcap; -E char *flood_mode_char_set; -E char *flood_mode_char_remove; E int UseTSMODE; /* hack to get around bahamut clones that don't send TSMODE */ -EI unsigned long umodes[128]; -E char csmodes[128]; -E CMMode cmmodes[128]; -E CBMode cbmodes[128]; -E CBModeInfo *cbmodeinfos; -E CUMode cumodes[128]; E char *IRCDModule; E IRCDProto *ircdproto; @@ -79,27 +71,11 @@ E void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode, char * E Channel *chanlist[1024]; -E void add_ban(Channel * chan, const char *mask); E void chan_adduser2(User * user, Channel * c); -E void add_invite(Channel * chan, const char *mask); E void chan_delete(Channel * c); -E void del_ban(Channel * chan, const char *mask); -E void chan_set_key(Channel * chan, const char *value); -E void set_limit(Channel * chan, const char *value); -E void del_invite(Channel * chan, const char *mask); -E char *get_key(Channel * chan); -E char *get_limit(Channel * chan); E Channel *chan_create(const char *chan, time_t ts); E Channel *join_user_update(User * user, Channel * chan, const char *name, time_t chants); -E void add_exception(Channel * chan, const char *mask); -E void del_exception(Channel * chan, const char *mask); -E char *get_flood(Channel * chan); -E void set_flood(Channel * chan, const char *value); -E char *get_redirect(Channel * chan); -E void set_redirect(Channel * chan, const char *value); - - E void get_channel_stats(long *nrec, long *memuse); E Channel *findchan(const char *chan); E Channel *firstchan(); @@ -151,7 +127,6 @@ E long get_memuse(EList *list); /**** chanserv.c ****/ E ChannelInfo *chanlists[256]; -E CSModeUtil csmodeutils[]; E LevelInfo levelinfo[]; E void get_chanserv_stats(long *nrec, long *memuse); @@ -190,14 +165,6 @@ E int get_idealban(ChannelInfo * ci, User * u, char *ret, int retlen); E AutoKick *is_stuck(ChannelInfo * ci, const char *mask); E void stick_mask(ChannelInfo * ci, AutoKick * akick); E void stick_all(ChannelInfo * ci); -E char *cs_get_flood(ChannelInfo * ci); -E void cs_set_flood(ChannelInfo * ci, const char *value); -E char *cs_get_key(ChannelInfo * ci); -E void cs_set_key(ChannelInfo * ci, const char *value); -E char *cs_get_limit(ChannelInfo * ci); -E void cs_set_limit(ChannelInfo * ci, const char *value); -E char *cs_get_redirect(ChannelInfo * ci); -E void cs_set_redirect(ChannelInfo * ci, const char *value); E int levelinfo_maxwidth; E ChannelInfo *makechan(const char *chan); @@ -481,29 +448,7 @@ E void pmodule_ircd_proto(IRCDProto *); E void pmodule_ircd_var(IRCDVar * ircdvar); E void pmodule_ircd_cap(IRCDCAPAB * cap); E void pmodule_ircd_version(const char *version); -E void pmodule_ircd_cbmodeinfos(CBModeInfo * modeinfos); -E void pmodule_ircd_cumodes(CUMode modes[128]); -E void pmodule_ircd_flood_mode_char_set(const char *mode); -E void pmodule_ircd_flood_mode_char_remove(const char *mode); -E void pmodule_ircd_cbmodes(CBMode modes[128]); -E void pmodule_ircd_cmmodes(CMMode modes[128]); -E void pmodule_ircd_csmodes(char mode[128]); E void pmodule_ircd_useTSMode(int use); -E void pmodule_invis_umode(int mode); -E void pmodule_oper_umode(int mode); -E void pmodule_invite_cmode(int mode); -E void pmodule_secret_cmode(int mode); -E void pmodule_private_cmode(int mode); -E void pmodule_key_mode(int mode); -E void pmodule_limit_mode(int mode); - -E int anope_get_secret_mode(); -E int anope_get_invite_mode(); -E int anope_get_key_mode(); -E int anope_get_limit_mode(); -E int anope_get_private_mode(); -E int anope_get_invis_mode(); -E int anope_get_oper_mode(); /**** language.c ****/ @@ -735,8 +680,6 @@ E void SetOperType(NickCore *nc); E SList akills, sglines, sqlines, szlines; E int DefConModesSet; -E uint32 DefConModesOn; -E uint32 DefConModesOff; E ChannelInfo DefConModesCI; E void operserv(User *u, char *buf); diff --git a/include/modules.h b/include/modules.h index aea9011f7..15b650d72 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1112,13 +1112,6 @@ int destroyMessage(Message *m); /* destroy a Message*/ MDE bool moduleMinVersion(int major,int minor,int patch,int build); /* Checks if the current version of anope is before or after a given verison */ -/*************************************************************************/ -/* Some IRCD protocol module support functions */ - -/** Update the protect deatials, could be either protect or admin etc.. */ -MDE void updateProtectDetails(const char *level_info_protect_word, const char *level_info_protectme_word, const char *fant_protect_add, const char *fant_protect_del, const char *level_protect_word, const char *protect_set_mode, const char *protect_unset_mode); -MDE void updateOwnerDetails(const char *fant_owner_add, const char *fant_owner_del, const char *owner_set_mode, const char *owner_del_mode); - /************************************************************************/ #endif diff --git a/include/regchannel.h b/include/regchannel.h index e3f9cd7fc..247371f05 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -9,8 +9,13 @@ * */ +#include "services.h" + class CoreExport ChannelInfo : public Extensible { + private: + std::map Params; + public: ChannelInfo() { @@ -23,8 +28,7 @@ class CoreExport ChannelInfo : public Extensible bantype = akickcount = 0; levels = NULL; akick = NULL; - mlock_on = mlock_off = mlock_limit = 0; - mlock_key = mlock_flood = mlock_redirect = entry_message = NULL; + entry_message = NULL; c = NULL; bi = NULL; botflags = 0; @@ -63,17 +67,14 @@ class CoreExport ChannelInfo : public Extensible uint16 akickcount; AutoKick *akick; /* List of users to kickban */ - uint32 mlock_on, mlock_off; /* See channel modes below */ - uint32 mlock_limit; /* 0 if no limit */ - char *mlock_key; /* NULL if no key */ - char *mlock_flood; /* NULL if no +f */ - char *mlock_redirect; /* NULL if no +L */ + std::bitset<128> mlock_on; + std::bitset<128> mlock_off; char *entry_message; /* Notice sent on entering channel */ MemoInfo memos; - struct channel_ *c; /* Pointer to channel record (if * + Channel *c; /* Pointer to channel record (if * * channel is currently in use) */ /* For BotServ */ @@ -175,4 +176,118 @@ class CoreExport ChannelInfo : public Extensible while (access.begin() != access.end()) EraseAccess(0); } + + /** Check if a mode is mlocked + * @param Name The mode + * @param status True to check mlock on, false for mlock off + * @return true on success, false on fail + */ + const bool HasMLock(ChannelModeName Name, bool status) + { + if (status) + return mlock_on[(size_t)Name]; + else + return mlock_off[(size_t)Name]; + } + + /** Set a mlock + * @param Name The mode + * @param status True for mlock on, false for mlock off + */ + void SetMLock(ChannelModeName Name, bool status) + { + size_t value = (size_t)Name; + + if (status) + mlock_on[value] = true; + else + mlock_off[value] = true; + } + + /** Remove a mlock + * @param Name The mode + * @param status True for mlock on, false for mlock off + */ + void RemoveMLock(ChannelModeName Name, bool status) + { + size_t value = (size_t)Name; + + if (status) + mlock_on[value] = false; + else + mlock_off[value] = false; + } + + /** Clear all mlocks on the channel + */ + void ClearMLock() + { + mlock_on.reset(); + mlock_off.reset(); + } + + /** Set a channel mode param on the channel + * @param Name The mode + * @param param The param + * @param true on success + */ + bool SetParam(ChannelModeName Name, std::string Value) + { + return Params.insert(std::make_pair(Name, Value)).second; + } + + /** Unset a param from the channel + * @param Name The mode + */ + void UnsetParam(ChannelModeName Name) + { + std::map::iterator it = Params.find(Name); + + if (it != Params.end()) + { + Params.erase(it); + } + } + + /** Get a param from the channel + * @param Name The mode + * @param Target a string to put the param into + * @return true on success + */ + const bool GetParam(ChannelModeName Name, std::string *Target) + { + std::map::iterator it = Params.find(Name); + + (*Target).clear(); + + if (it != Params.end()) + { + *Target = it->second; + return true; + } + + return false; + } + + /** Check if a mode is set and has a param + * @param Name The mode + */ + const bool HasParam(ChannelModeName Name) + { + std::map::iterator it = Params.find(Name); + + if (it != Params.end()) + { + return true; + } + + return false; + } + + /** Clear all the params from the channel + */ + void ClearParams() + { + Params.clear(); + } }; diff --git a/include/services.h b/include/services.h index 758c766e3..f320d8cc6 100644 --- a/include/services.h +++ b/include/services.h @@ -237,6 +237,7 @@ extern int strncasecmp(const char *, const char *, size_t); #include #include #include +#include /** This class can be used on its own to represent an exception, or derived to represent a module-specific exception. * When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or @@ -422,10 +423,9 @@ class CoreExport Extensible /* forward declarations, mostly used by older code */ class User; class ChannelInfo; - +class Channel; typedef struct server_ Server; -typedef struct channel_ Channel; typedef struct c_elist EList; typedef struct c_elist_entry Entry; typedef struct memo_ Memo; @@ -438,14 +438,43 @@ typedef struct sxline_ SXLine; typedef struct hostcore_ HostCore; typedef struct newsitem_ NewsItem; typedef struct exception_ Exception; -typedef struct cbmode_ CBMode; -typedef struct cbmodeinfo_ CBModeInfo; -typedef struct cmmode_ CMMode; -typedef struct csmode_ CSMode; -typedef struct cumode_ CUMode; -typedef struct csmodeutil_ CSModeUtil; typedef struct session_ Session; +enum UserModeName +{ + UMODE_BEGIN, + + /* Usermodes */ + UMODE_SERV_ADMIN, UMODE_BOT, UMODE_CO_ADMIN, UMODE_FILTER, UMODE_HIDEOPER, UMODE_NETADMIN, + UMODE_REGPRIV, UMODE_PROTECTED, UMODE_NO_CTCP, UMODE_WEBTV, UMODE_WHOIS, UMODE_ADMIN, UMODE_DEAF, + UMODE_GLOBOPS, UMODE_HELPOP, UMODE_INVIS, UMODE_OPER, UMODE_PRIV, UMODE_GOD, UMODE_REGISTERED, + UMODE_SNOMASK, UMODE_VHOST, UMODE_WALLOPS, UMODE_CLOAK, UMODE_SSL, UMODE_CALLERID, + + UMODE_END +}; + +enum ChannelModeName +{ + CMODE_BEGIN, + + /* Channel modes */ + CMODE_BLOCKCOLOR, CMODE_FLOOD, CMODE_INVITE, CMODE_KEY, CMODE_LIMIT, CMODE_MODERATED, CMODE_NOEXTERNAL, + CMODE_PRIVATE, CMODE_REGISTERED, CMODE_SECRET, CMODE_TOPIC, CMODE_AUDITORIUM, CMODE_SSL, CMODE_ADMINONLY, + CMODE_NOCTCP, CMODE_FILTER, CMODE_NOKNOCK, CMODE_REDIRECT, CMODE_REGMODERATED, CMODE_NONICK, CMODE_OPERONLY, + CMODE_NOKICK, CMODE_REGISTEREDONLY, CMODE_STRIPCOLOR, CMODE_NONOTICE, CMODE_NOINVITE, CMODE_ALLINVITE, + CMODE_BLOCKCAPS, CMODE_PERM, + + /* b/e/I */ + CMODE_BAN, CMODE_EXCEPT, + CMODE_INVITEOVERRIDE, + + /* v/h/o/a/q */ + CMODE_VOICE, CMODE_HALFOP, CMODE_OP, + CMODE_PROTECT, CMODE_OWNER, + + CMODE_END +}; + #include "bots.h" #include "opertype.h" @@ -460,35 +489,22 @@ struct ircdvars_ { const char *name; /* Name of the IRCd command */ const char *pseudoclient_mode; /* Mode used by BotServ Bots */ int max_symbols; /* Chan Max Symbols */ - const char *modestoremove; /* Channel Modes to remove */ const char *botchanumode; /* Modes set when botserv joins a channel */ int svsnick; /* Supports SVSNICK */ int vhost; /* Supports vhost */ - int owner; /* Supports Owner */ - const char *ownerset; /* Mode to set for owner */ - const char *ownerunset; /* Mode to unset for a owner */ - const char *adminset; /* Mode to set for admin */ - const char *adminunset; /* Mode to unset for admin */ const char *modeonunreg; /* Mode on Unregister */ int sgline; /* Supports SGline */ int sqline; /* Supports SQline */ int szline; /* Supports SZline */ - int halfop; /* Supports HalfOp */ int numservargs; /* Number of Server Args */ int join2set; /* Join 2 Set Modes */ int join2msg; /* Join 2 Message */ - int except; /* exception +e */ int topictsforward; /* TS on Topics Forward */ int topictsbackward; /* TS on Topics Backward */ - uint32 protectedumode; /* What is the Protected Umode */ - int admin; /* Has Admin */ int chansqline; /* Supports Channel Sqlines */ int quitonkill; /* IRCD sends QUIT when kill */ int svsmode_unban; /* svsmode can be used to unban */ - int protect; /* Has protect modes */ int reversekickcheck; /* Can reverse ban check */ - int chanreg; /* channel mode +r for register */ - uint32 regmode; /* Mode to use for +r */ int vident; /* Supports vidents */ int svshold; /* Supports svshold */ int tsonmode; /* Timestamp on mode changes */ @@ -497,28 +513,18 @@ struct ircdvars_ { int umode; /* change user modes */ int nickvhost; /* Users vhost sent during NICK */ int chgreal; /* Change RealName */ - uint32 noknock; /* Channel Mode for no knock */ - uint32 adminmode; /* Admin Only Channel Mode */ - uint32 defmlock; /* Default mlock modes */ - uint32 vhostmode; /* Vhost mode */ - int fmode; /* +f */ - int Lmode; /* +L */ - uint32 chan_fmode; /* Mode */ - uint32 chan_lmode; /* Mode */ + std::bitset<128> DefMLock; /* Default mlock modes */ int check_nick_id; /* On nick change check if they could be identified */ int knock_needs_i; /* Check if we needed +i when setting NOKNOCK */ char *chanmodes; /* If the ircd sends CHANMODE in CAPAB this is where we store it */ int token; /* Does Anope support the tokens for the ircd */ int sjb64; /* Base 64 encode TIMESTAMP */ - int invitemode; /* +I */ int sjoinbanchar; /* use single quotes to define it */ int sjoinexchar; /* use single quotes to define it */ int sjoininvchar; /* use single quotes to define it */ int svsmode_ucmode; /* Can remove User Channel Modes with SVSMODE */ int sglineenforce; - const char *vhostchar; /* char used for vhosting */ int ts6; /* ircd is TS6 */ - int supporthelper; /* +h helper umodes */ int p10; /* ircd is P10 */ char *nickchars; /* character set */ int cidrchanbei; /* channel bans/excepts/invites support CIDR (syntax: +b *!*@192.168.0.0/15) @@ -595,7 +601,6 @@ typedef struct { } MemoInfo; - /*************************************************************************/ // For NickServ @@ -784,17 +789,6 @@ struct badword_ { /*************************************************************************/ -/* ChanServ mode utilities commands */ - -struct csmodeutil_ { - const char *name; /* Name of the ChanServ command */ - const char *bsname; /* Name of the BotServ fantasy command */ - const char *mode; /* Mode (ie. +o) */ - int32 notice; /* Notice flag (for the damn OPNOTICE) */ - int level; /* Level required to use the command */ - int levelself; /* Level required to use the command for himself */ -}; - typedef struct { int what; const char *name; @@ -830,47 +824,17 @@ struct server_ { #define SERVER_ISUPLINK 0x0004 /*************************************************************************/ -#include "users.h" - - -struct cbmode_ { - uint32 flag; /* Long value that represents the mode */ - uint16 flags; /* Flags applying to this mode (CBM_* below) */ - - /* Function to associate a value with the mode */ - void (*setvalue) (Channel *chan, const char *value); - void (*cssetvalue) (ChannelInfo *ci, const char *value); -}; - -#define CBM_MINUS_NO_ARG 0x0001 /* No argument for unset */ -#define CBM_NO_MLOCK 0x0002 /* Can't be MLOCKed */ -#define CBM_NO_USER_MLOCK 0x0004 /* Can't be MLOCKed by non-opers */ - -struct cbmodeinfo_ { - char mode; /* The mode */ - uint32 flag; /* Long value that represents the mode */ - uint16 flags; /* CBM_* above */ - /* Function to retrieve the value associated to the mode (optional) */ - char * (*getvalue) (Channel *chan); - char * (*csgetvalue) (ChannelInfo *ci); -}; - -struct cmmode_ { - void (*addmask) (Channel *chan, const char *mask); - void (*delmask) (Channel *chan, const char *mask); -}; - -struct cumode_ { - int16 status; /* CUS_* below */ - int16 flags; /* CUF_* below */ - - int (*is_valid) (User *user, Channel *chan, int servermode); -}; +#define CUS_OP 0x0001 +#define CUS_VOICE 0x0002 +#define CUS_HALFOP 0x0004 /* Halfop (+h) */ +#define CUS_OWNER 0x0008 /* Owner/Founder (+q) */ +#define CUS_PROTECT 0x0010 /* Protected users (+a) */ +/* #define CUS_DEOPPED 0x0080 */ /* Removed due to IRCd checking it */ -/* Channel user mode flags */ +/*************************************************************************/ -#define CUF_PROTECT_BOTSERV 0x0001 +#include "users.h" /* This structure stocks ban data since it must not be removed when * user is kicked. @@ -918,7 +882,21 @@ struct c_userlist { UserData *ud; }; -struct channel_ { +class CoreExport Channel +{ + private: + /** A map of channel modes with their parameters set on this channel + */ + std::map Params; + + public: + Channel() { } + + ~Channel() + { + Params.clear(); + } + Channel *next, *prev; char name[CHANMAX]; ChannelInfo *ci; /* Corresponding ChannelInfo */ @@ -926,11 +904,8 @@ struct channel_ { char *topic; char topic_setter[NICKMAX]; /* Who set the topic */ time_t topic_time; /* When topic was set */ - uint32 mode; /* Binary modes only */ - uint32 limit; /* 0 if none */ - char *key; /* NULL if none */ - char *redirect; /* +L; NULL if none */ - char *flood; /* +f; NULL if none */ + std::bitset<128> modes; + EList *bans; EList *excepts; EList *invites; @@ -946,6 +921,81 @@ struct channel_ { int16 chanserv_modecount; /* Number of check_mode()'s this sec */ int16 bouncy_modes; /* Did we fail to set modes here? */ int16 topic_sync; /* Is the topic in sync? */ + + /** + * See if a channel has a mode + * @param Name The mode name + * @return true or false + */ + bool HasMode(ChannelModeName Name); + + /** + * Set a mode on a channel + * @param Name The mode name + */ + void SetMode(ChannelModeName Name); + + /** + * Set a mode on a channel + * @param Mode The mode + */ + void SetMode(char Mode); + + /** + * Remove a mode from a channel + * @param Name The mode name + */ + void RemoveMode(ChannelModeName Name); + + /** + * Remove a mode from a channel + * @param Mode The mode + */ + void RemoveMode(char Mode); + + /** Clear all the modes from the channel + * @param client The client unsetting the modes + */ + void ClearModes(char *client = NULL); + + /** Clear all the bans from the channel + * @param client The client unsetting the modes + */ + void ClearBans(char *client = NULL); + + /** Clear all the excepts from the channel + * @param client The client unsetting the modes + */ + void ClearExcepts(char *client = NULL); + + /** Clear all the invites from the channel + * @param client The client unsetting the modes + */ + void ClearInvites(char *client = NULL); + + /** Set a channel mode param on the channel + * @param Name The mode + * @param param The param + * @param true on success + */ + bool SetParam(ChannelModeName Name, std::string ¶m); + + /** Unset a param from the channel + * @param Name The mode + */ + void UnsetParam(ChannelModeName Name); + + /** Get a param from the channel + * @param Name The mode + * @param Target a string to put the param into + * @return true on success + */ + const bool GetParam(ChannelModeName Name, std::string *Target); + + /** Check if a mode is set and has a param + * @param Name The mode + */ + const bool HasParam(ChannelModeName Name); }; struct c_elist { @@ -1055,6 +1105,335 @@ struct exception_ { * calculated at load time and never saved. */ }; +/*************************************************************************/ + +/** The different types of modes +*/ +enum ModeType +{ + /* Regular mode */ + MODE_REGULAR, + /* b/e/I */ + MODE_LIST, + /* k/l etc */ + MODE_PARAM, + /* v/h/o/a/q */ + MODE_STATUS +}; + +/** This class is a user mode, all user modes use this/inherit from this + */ +class UserMode +{ + public: + + /* Mode name */ + UserModeName Name; + /* The mode char */ + char ModeChar; + + /** Default constructor + * @param nName The mode name + * @param mMode A value representing the mode + */ + UserMode(UserModeName mName) + { + this->Name = mName; + } + + /** Default destructor + */ + virtual ~UserMode() { } +}; + +/** This class is a channel mode, all channel modes use this/inherit from this + */ +class ChannelMode +{ + public: + + /* Mode name */ + ChannelModeName Name; + /* Type of mode this is */ + ModeType Type; + /* The mode char */ + char ModeChar; + + /** Default constructor + * @param mName The mode name + * @param mMode A value representing the mode + */ + ChannelMode(ChannelModeName mName) + { + this->Name = mName; + this->Type = MODE_REGULAR; + } + + /** Default destructor + */ + virtual ~ChannelMode() { } + + /** Can a user set this mode, used for mlock + * NOTE: User CAN be NULL, this is for checking if it can be locked with defcon + * @param u The user, or NULL + */ + virtual bool CanSet(User *u) { return true; } +}; + +/** This is a mode for lists, eg b/e/I. These modes should inherit from this + */ +class ChannelModeList : public ChannelMode +{ + public: + + /** Default constructor + * @param mName The mode name + */ + ChannelModeList(ChannelModeName mName) : ChannelMode(mName) + { + this->Type = MODE_LIST; + } + + /** Default destructor + */ + virtual ~ChannelModeList() { } + + /** Is the mask valid + * @param mask The mask + * @return true for yes, false for no + */ + virtual bool IsValid(const char *mask) { return true; } + + /** Add the mask to the channel, this should be overridden + * @param chan The channel + * @param mask The mask + */ + virtual void AddMask(Channel *chan, const char *mask) { } + + /** Delete the mask from the channel, this should be overridden + * @param chan The channel + * @param mask The mask + */ + virtual void DelMask(Channel *chan, const char *mask) { } + +}; + +/** This is a mode with a paramater, eg +k/l. These modes should use/inherit from this +*/ +class ChannelModeParam : public ChannelMode +{ + public: + + /** Default constructor + * @param mName The mode name + * @param mMode A value representing the mode + */ + ChannelModeParam(ChannelModeName mName) : ChannelMode(mName) + { + this->Type = MODE_PARAM; + MinusNoArg = false; + } + + /** Default destructor + */ + virtual ~ChannelModeParam() { } + + /* Should we send an arg when unsetting this mode? */ + bool MinusNoArg; + + /** Is the param valid + * @param value The param + * @return true for yes, false for no + */ + virtual bool IsValid(const char *value) { return true; } +}; + +/** This is a mode that is a channel status, eg +v/h/o/a/q. +*/ +class ChannelModeStatus : public ChannelMode +{ + public: + /** CUS_ values, see below + */ + int16 Status; + /* The symbol, eg @ % + */ + char Symbol; + + /** Default constructor + * @param mName The mode name + * @param mStatus A CUS_ value + */ + ChannelModeStatus(ChannelModeName mName, int16 mStatus, char mSymbol, bool mProtectBotServ = false) : ChannelMode(mName) + { + this->Type = MODE_STATUS; + this->Status = mStatus; + this->Symbol = mSymbol; + this->ProtectBotServ = mProtectBotServ; + } + + /** Default destructor + */ + virtual ~ChannelModeStatus() { } + + /* Should botserv protect itself with this mode? eg if someone -o's botserv it will +o */ + bool ProtectBotServ; +}; + +/** This class manages modes, and has the ability to add channel and + * user modes to Anope to track internally + */ +class CoreExport ModeManager +{ + public: + /* User modes */ + static std::map UserModesByChar; + static std::map UserModesByName; + /* Channel modes */ + static std::map ChannelModesByChar; + static std::map ChannelModesByName; + /* Although there are two different maps for UserModes and ChannelModes + * the pointers in each are the same. This is used to increase + * efficiency. + */ + + /** Add a user mode to Anope + * @param Mode The mode + * @param um A UserMode or UserMode derived class + * @return true on success, false on error + */ + static bool AddUserMode(char Mode, UserMode *um); + + /** Add a channel mode to Anope + * @param Mode The mode + * @param cm A ChannelMode or ChannelMode derived class + * @return true on success, false on error + */ + static bool AddChannelMode(char Mode, ChannelMode *cm); + + /** Find a channel mode + * @param Mode The mode + * @return The mode class + */ + static ChannelMode *FindChannelModeByChar(char Mode); + + /** Find a user mode + * @param Mode The mode + * @return The mode class + */ + static UserMode *FindUserModeByChar(char Mode); + + /** Find a channel mode + * @param Mode The modename + * @return The mode class + */ + static ChannelMode *FindChannelModeByName(ChannelModeName Name); + + /** Find a user mode + * @param Mode The modename + * @return The mode class + */ + static UserMode *FindUserModeByName(UserModeName Name); + + /** Gets the channel mode char for a symbol (eg + returns v) + * @param Value The symbol + * @return The char + */ + static char GetStatusChar(char Value); +}; + +/** Channel mode +b + */ +class ChannelModeBan : public ChannelModeList +{ + public: + ChannelModeBan() : ChannelModeList(CMODE_BAN) { } + + void AddMask(Channel *chan, const char *mask); + + void DelMask(Channel *chan, const char *mask); +}; + +/** Channel mode +e + */ +class ChannelModeExcept : public ChannelModeList +{ + public: + ChannelModeExcept() : ChannelModeList(CMODE_EXCEPT) { } + + void AddMask(Channel *chan, const char *mask); + + void DelMask(Channel *chan, const char *mask); +}; + +/** Channel mode +I + */ +class ChannelModeInvite : public ChannelModeList +{ + public: + ChannelModeInvite() : ChannelModeList(CMODE_INVITEOVERRIDE) { } + + void AddMask(Channel *chan, const char *mask); + + void DelMask(Channel *chan, const char *mask); +}; + +/** Channel mode +k (key) + */ +class ChannelModeKey : public ChannelModeParam +{ + public: + ChannelModeKey() : ChannelModeParam(CMODE_KEY) { } + + bool IsValid(const char *value); +}; + +/** Channel mode +f (flood) + */ +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood() : ChannelModeParam(CMODE_FLOOD) { } + + bool IsValid(const char *value); +}; + +/** This class is used for channel mode +A (Admin only) + * Only opers can mlock it + */ +class ChannelModeAdmin : public ChannelMode +{ + public: + ChannelModeAdmin() : ChannelMode(CMODE_ADMINONLY) { } + + /* Opers only */ + bool CanSet(User *u); +}; + +/** This class is used for channel mode +O (Opers only) + * Only opers can mlock it + */ +class ChannelModeOper : public ChannelMode +{ + public: + ChannelModeOper() : ChannelMode(CMODE_OPERONLY) { } + + /* Opers only */ + bool CanSet(User *u); +}; + +/** This class is used for channel mode +r (registered channel) + * No one may mlock r + */ +class ChannelModeRegistered : public ChannelMode +{ + public: + ChannelModeRegistered() : ChannelMode(CMODE_REGISTERED) { } + + /* No one mlocks +r */ + bool CanSet(User *u); +}; + + /*************************************************************************/ struct session_ { @@ -1064,19 +1443,6 @@ struct session_ { int hits; /* Number of subsequent kills for a host */ }; -/*************************************************************************/ -typedef struct ircd_modes_ { - int user_invis; - int user_oper; - int chan_invite; - int chan_secret; - int chan_private; - int chan_key; - int chan_limit; -} IRCDModes; - - - /*************************************************************************/ /** * DEFCON Defines @@ -1182,24 +1548,6 @@ typedef struct ircd_modes_ { #define BI_NICKSERV 0x0040 #define BI_GLOBAL 0x0080 -#define CUS_OP 0x0001 -#define CUS_VOICE 0x0002 -#define CUS_HALFOP 0x0004 /* Halfop (+h) */ -#define CUS_OWNER 0x0008 /* Owner/Founder (+q) */ -#define CUS_PROTECT 0x0010 /* Protected users (+a) */ -/* #define CUS_DEOPPED 0x0080 */ /* Removed due to IRCd checking it */ - -#define MUT_DEOP 0 -#define MUT_OP 1 -#define MUT_DEVOICE 2 -#define MUT_VOICE 3 -#define MUT_DEHALFOP 4 -#define MUT_HALFOP 5 -#define MUT_DEPROTECT 6 -#define MUT_PROTECT 7 -#define MUT_DEOWNER 8 -#define MUT_OWNER 9 - /*************************************************************************/ /* CAPAB stuffs */ @@ -1338,7 +1686,6 @@ class CoreExport IRCDProto virtual void ProcessUsermodes(User *, int, const char **) = 0; virtual int IsNickValid(const char *) { return 1; } virtual int IsChannelValid(const char *); - virtual int IsFloodModeParamValid(const char *) { return 0; } virtual void SendNumeric(const char *source, int numeric, const char *dest, const char *fmt, ...); /** Sends a message logging a user into an account, where ircds support such a feature. diff --git a/include/users.h b/include/users.h index 1f7f617d3..f54be8982 100644 --- a/include/users.h +++ b/include/users.h @@ -8,6 +8,7 @@ * $Id$ * */ + struct u_chanlist { struct u_chanlist *next, *prev; Channel *chan; @@ -41,7 +42,7 @@ class CoreExport User : public Extensible Server *server; /* Server user is connected to */ time_t timestamp; /* Timestamp of the nick */ time_t my_signon; /* When did _we_ see the user? */ - uint32 mode; /* See below */ + std::bitset<128> modes; NickCore *nc; @@ -161,5 +162,31 @@ class CoreExport User : public Extensible /** Update the last usermask stored for a user, and check to see if they are recognized */ void UpdateHost(); + + /** Check if the user has a mode + * @param Name Mode name + * @return true or false + */ + const bool HasMode(UserModeName Name) const; + + /** Set a mode on the user + * @param Name The mode name + */ + void SetMode(UserModeName Name); + + /* Set a mode on the user + * @param ModeChar The mode char + */ + void SetMode(char ModeChar); + + /** Remove a mode from the user + * @param Name The mode name + */ + void RemoveMode(UserModeName Name); + + /** Remove a mode from the user + * @param ModeChar The mode char + */ + void RemoveMode(char ModeChar); }; diff --git a/lang/cat.l b/lang/cat.l index 98c82b446..dc074e12a 100644 --- a/lang/cat.l +++ b/lang/cat.l @@ -4227,10 +4227,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/lang/de.l b/lang/de.l index e67bf1be6..b14ac8455 100644 --- a/lang/de.l +++ b/lang/de.l @@ -4262,11 +4262,6 @@ CHAN_HELP_CMD_OWNER OWNER Gibt dir Gründer Staus in einen Channel CHAN_HELP_CMD_PROTECT PROTECT Schützt den angegebenen Nicknamen in einen Channel -CHAN_HELP_CMD_ADMIN - ADMIN Schützt den angegebenen Nicknamen in einen Channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Entfernt den Schutz des angegebenen Nicknamens - in einen Channel CHAN_HELP_CMD_DEOP DEOP Enfernt den OP-Status des angegebenen Nicknamens in einen Channel diff --git a/lang/en_us.l b/lang/en_us.l index aedf19e56..56faf0575 100644 --- a/lang/en_us.l +++ b/lang/en_us.l @@ -4075,10 +4075,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/lang/es.l b/lang/es.l index e766c4944..1cbaca52f 100644 --- a/lang/es.l +++ b/lang/es.l @@ -4198,10 +4198,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/lang/fr.l b/lang/fr.l index eb191d42f..7a45ad525 100644 --- a/lang/fr.l +++ b/lang/fr.l @@ -4259,10 +4259,6 @@ CHAN_HELP_CMD_OWNER OWNER Vous donne votre accès owner sur un canal CHAN_HELP_CMD_PROTECT PROTECT Protège le pseudo spécifié sur un canal -CHAN_HELP_CMD_ADMIN - ADMIN Protège le pseudo spécifié sur un canal -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotège le pseudo donné sur un canal CHAN_HELP_CMD_DEOP DEOP Deop le pseudo spécifié sur un canal diff --git a/lang/gr.l b/lang/gr.l index 252dcf99d..5e8045387 100644 --- a/lang/gr.l +++ b/lang/gr.l @@ -4217,10 +4217,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/lang/hun.l b/lang/hun.l index 8b68c3e8a..9b5a2a2dc 100644 --- a/lang/hun.l +++ b/lang/hun.l @@ -4139,10 +4139,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/lang/it.l b/lang/it.l index c53b9821a..8aab2d0d3 100644 --- a/lang/it.l +++ b/lang/it.l @@ -4091,10 +4091,6 @@ CHAN_HELP_CMD_OWNER OWNER Assegna lo stato di owner a un utente (+q) CHAN_HELP_CMD_PROTECT PROTECT Assegna lo stato di protezione a un utente (+a) -CHAN_HELP_CMD_ADMIN - ADMIN Protegge un nick su un canale -CHAN_HELP_CMD_DEADMIN - DEADMIN Sprotegge un nick su un canale CHAN_HELP_CMD_DEOP DEOP Toglie lo stato di operatore a un utente (-o) diff --git a/lang/nl.l b/lang/nl.l index d9b7ead8f..b7f8c0a14 100644 --- a/lang/nl.l +++ b/lang/nl.l @@ -4176,10 +4176,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/lang/pl.l b/lang/pl.l index 4f0b4fe2c..d36181ee9 100644 --- a/lang/pl.l +++ b/lang/pl.l @@ -5199,12 +5199,6 @@ CHAN_HELP_CMD_OWNER CHAN_HELP_CMD_PROTECT PROTECT Chroni wskazan± osobê -CHAN_HELP_CMD_ADMIN - ADMIN Chroni wskazan± osobê - -CHAN_HELP_CMD_DEADMIN - DEADMIN Wy³±cza ochronê wskazanej osoby - CHAN_HELP_CMD_DEOP DEOP Odbiera wskazanej osobie uprawnienia operatora diff --git a/lang/pt.l b/lang/pt.l index 1f355710b..c51b4fa40 100644 --- a/lang/pt.l +++ b/lang/pt.l @@ -4096,10 +4096,6 @@ CHAN_HELP_CMD_OWNER OWNER Concede-lhe status de Owner no canal CHAN_HELP_CMD_PROTECT PROTECT Protege um determinado nick no canal -CHAN_HELP_CMD_ADMIN - ADMIN Protege um determinado nick no canal -CHAN_HELP_CMD_DEADMIN - DEADMIN Desprotege um determinado nick no canal CHAN_HELP_CMD_DEOP DEOP Retira o status de OP de um nick no canal diff --git a/lang/ru.l b/lang/ru.l index 9830c5b18..c3e1f0f6a 100644 --- a/lang/ru.l +++ b/lang/ru.l @@ -4158,10 +4158,6 @@ CHAN_HELP_CMD_OWNER OWNER Çàïðîñ ñòàòóñà âëàäåëüöà íà êàíàëå CHAN_HELP_CMD_PROTECT PROTECT Óñòàíîâêà ðåæèìà çàùèòû (+a) óêàçàííîìó íèêó íà êàíàëå -CHAN_HELP_CMD_ADMIN - ADMIN Óñòàíîâêà ñòàòóñà àäìèíèñòðàòîðà (+a) óêàçàííîìó íèêó íà êàíàëå -CHAN_HELP_CMD_DEADMIN - DEADMIN Ñíÿòèå ðåæèìà àäìèíèñòðàòîðà (-a) ñ óêàçàííîãî íèêà íà êàíàëå CHAN_HELP_CMD_DEOP DEOP Ñíÿòèå ðåæèìà îïåðàòîðà (-o) ñ óêàçàííîãî íèêà íà êàíàëå diff --git a/lang/tr.l b/lang/tr.l index dd4c4f21f..6f689f9fe 100644 --- a/lang/tr.l +++ b/lang/tr.l @@ -4210,10 +4210,6 @@ CHAN_HELP_CMD_OWNER OWNER Gives you owner status on channel CHAN_HELP_CMD_PROTECT PROTECT Protects a selected nick on a channel -CHAN_HELP_CMD_ADMIN - ADMIN Protects a selected nick on a channel -CHAN_HELP_CMD_DEADMIN - DEADMIN Deprotects a selected nick on a channel CHAN_HELP_CMD_DEOP DEOP Deops a selected nick on a channel diff --git a/src/Makefile b/src/Makefile index a54d194c4..2f8845b4d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o comm config.o datafiles.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \ memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \ process.o protocol.o send.o servers.o sessions.o slist.o sockutil.o opertype.o users.o module.o modulemanager.o configreader.o \ - wildcard.o nickcore.o nickalias.o timers.o + wildcard.o nickcore.o nickalias.o timers.o modes.o INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \ ../include/pseudo.h ../include/sysconf.h ../include/config.h \ @@ -33,6 +33,7 @@ services: $(OBJS) $(MAKEBIN) $(CC) $(CFLAGS) $(OBJS) $(ANOPELIBS) $(MLIBS) -o $@ $(LDFLAGS) $(OBJS): Makefile +modes.o: modes.cpp $(INCLUDES) timers.o: timers.cpp $(INCLUDES) nickcore.o: nickcore.cpp $(INCLUDES) nickalias.o: nickalias.cpp $(INCLUDES) diff --git a/src/botserv.c b/src/botserv.c index 3fc4c5c11..0e4f37600 100644 --- a/src/botserv.c +++ b/src/botserv.c @@ -772,12 +772,19 @@ void bot_join(ChannelInfo * ci) } } + std::string Limit; + int limit = 0; + if (ci->c->GetParam(CMODE_LIMIT, &Limit)) + { + limit = atoi(Limit.c_str()); + } + /* Should we be invited? */ - if ((ci->c->mode & anope_get_invite_mode()) - || (ci->c->limit && ci->c->usercount >= ci->c->limit)) + if (ci->c->HasMode(CMODE_INVITE) + || (limit && ci->c->usercount >= limit)) ircdproto->SendNoticeChanops(NULL, ci->c->name, - "%s invited %s into the channel.", - ci->bi->nick, ci->bi->nick); + "%s invited %s into the channel.", + ci->bi->nick, ci->bi->nick); } ircdproto->SendJoin(ci->bi, ci->c->name, ci->c->creation_time); ircdproto->SendBotOp(ci->bi->nick, ci->c->name); @@ -877,7 +884,8 @@ void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, if (!u) return; - if (ircd->protectedumode) { + if ((ModeManager::FindUserModeByName(UMODE_PROTECTED))) + { if (is_protected(u) && (requester != u)) { ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(ACCESS_DENIED)); @@ -889,7 +897,8 @@ void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, && (get_access(u, ci) >= get_access(requester, ci))) return; - if (ircd->except) { + if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) + { if (is_excepted(ci, u) == 1) { ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(BOT_EXCEPT)); @@ -953,7 +962,8 @@ void bot_raw_kick(User * requester, ChannelInfo * ci, char *nick, if (!u || !is_on_chan(ci->c, u)) return; - if (ircd->protectedumode) { + if ((ModeManager::FindUserModeByName(UMODE_PROTECTED))) + { if (is_protected(u) && (requester != u)) { ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(ACCESS_DENIED)); @@ -1007,7 +1017,7 @@ void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode, snprintf(buf, BUFSIZE - 1, "%ld", static_cast(time(NULL))); - if (ircd->protectedumode) { + if ((ModeManager::FindUserModeByName(UMODE_PROTECTED))) { if (is_protected(u) && *mode == '-' && (requester != u)) { ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(ACCESS_DENIED)); diff --git a/src/channels.c b/src/channels.c index f41219109..5984065e0 100644 --- a/src/channels.c +++ b/src/channels.c @@ -20,7 +20,279 @@ Channel *chanlist[1024]; #define HASH(chan) ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0) -/**************************** External Calls *****************************/ +/*************************************************************************/ + +/** + * See if a channel has a mode + * @param Name The mode name + * @return true or false + */ +bool Channel::HasMode(ChannelModeName Name) +{ + return modes[(size_t)Name]; +} + +/** + * Set a mode on a channel + * @param Name The mode name + */ +void Channel::SetMode(ChannelModeName Name) +{ + modes[(size_t)Name] = true; +} + +/** + * Set a mode on a channel + * @param Mode The mode + */ +void Channel::SetMode(char Mode) +{ + ChannelMode *cm; + + if ((cm = ModeManager::FindChannelModeByChar(Mode))) + { + SetMode(cm->Name); + } +} + +/** + * Remove a mode from a channel + * @param Name The mode name + */ +void Channel::RemoveMode(ChannelModeName Name) +{ + modes[(size_t)Name] = false; +} + +/** + * Remove a mode from a channel + * @param Mode The mode + */ +void Channel::RemoveMode(char Mode) +{ + ChannelMode *cm; + + if ((cm = ModeManager::FindChannelModeByChar(Mode))) + { + RemoveMode(cm->Name); + } +} + +/** Set a channel mode param on the channel + * @param Name The mode + * @param param The param + * @param true on success + */ +bool Channel::SetParam(ChannelModeName Name, std::string &Value) +{ + return Params.insert(std::make_pair(Name, Value)).second; +} + +/** Unset a param from the channel + * @param Name The mode + */ +void Channel::UnsetParam(ChannelModeName Name) +{ + std::map::iterator it = Params.find(Name); + + if (it != Params.end()) + { + Params.erase(it); + } +} + +/** Get a param from the channel + * @param Name The mode + * @param Target a string to put the param into + * @return true on success + */ +const bool Channel::GetParam(ChannelModeName Name, std::string *Target) +{ + std::map::iterator it = Params.find(Name); + + (*Target).clear(); + + if (it != Params.end()) + { + *Target = it->second; + return true; + } + + return false; +} + +/** Check if a mode is set and has a param + * @param Name The mode + */ +const bool Channel::HasParam(ChannelModeName Name) +{ + std::map::iterator it = Params.find(Name); + + if (it != Params.end()) + { + return true; + } + + return false; +} + +/*************************************************************************/ + +/** Clear all the modes from the channel + * @param client The client unsetting the modes + */ +void Channel::ClearModes(char *client) +{ + ChannelMode *cm; + ChannelModeParam *cmp; + std::string buf, buf2; + const char *argv[2]; + BotInfo *sender = (client ? findbot(client) : whosends(ci)); + + for (size_t n = CMODE_BEGIN + 1; n != CMODE_END; ++n) + { + cm = ModeManager::FindChannelModeByName((ChannelModeName)n); + + if (cm && this->HasMode(cm->Name)) + { + if (cm->Type == MODE_REGULAR) + { + buf = '-'; + buf += cm->ModeChar; + + argv[0] = buf.c_str(); + + ircdproto->SendMode(sender, this->name, "-%c", cm->ModeChar); + chan_set_modes(sender->nick, this, 1, argv, 0); + } + else if (cm->Type == MODE_PARAM) + { + cmp = static_cast(cm); + + buf = '-'; + buf += cmp->ModeChar; + buf2.clear(); + + if (!cmp->MinusNoArg) + { + buf2 = this->GetParam(cmp->Name, &buf2); + } + + argv[0] = buf.c_str(); + if (!buf2.empty()) + { + argv[1] = buf2.c_str(); + + ircdproto->SendMode(sender, this->name, "-%c %s", cm->ModeChar, buf2.c_str()); + chan_set_modes(sender->nick, this, 2, argv, 0); + } + else + { + argv[1] = NULL; + + ircdproto->SendMode(sender, this->name, "-%c", cm->ModeChar); + chan_set_modes(sender->nick, this, 1, argv, 0); + } + } + } + } + + modes.reset(); +} + +/** Clear all the bans from the channel + * @param client The client unsetting the modes + */ +void Channel::ClearBans(char *client) +{ + Entry *entry, *nexte; + BotInfo *sender = (client ? findbot(client) : whosends(ci)); + ChannelModeList *cml; + std::string buf; + const char *argv[2]; + + cml = static_cast(ModeManager::FindChannelModeByName(CMODE_BAN)); + + if (cml && this->bans && this->bans->count) + { + buf = '-'; + buf += cml->ModeChar; + + for (entry = this->bans->entries; entry; entry = nexte) + { + nexte = entry->next; + + argv[0] = buf.c_str(); + argv[1] = sstrdup(entry->mask); + ircdproto->SendMode(sender, this->name, "%s %s", buf.c_str(), entry->mask); + chan_set_modes(sender->nick, this, 2, argv, 0); + delete [] argv[1]; + } + } +} + +/** Clear all the excepts from the channel + * @param client The client unsetting the modes + */ +void Channel::ClearExcepts(char *client) +{ + Entry *entry, *nexte; + BotInfo *sender = (client ? findbot(client) : whosends(ci)); + ChannelModeList *cml; + std::string buf; + const char *argv[2]; + + cml = static_cast(ModeManager::FindChannelModeByName(CMODE_EXCEPT)); + + if (cml && this->excepts && this->excepts->count) + { + buf = '+'; + buf += cml->ModeChar; + + for (entry = this->excepts->entries; entry; entry = nexte) + { + nexte = entry->next; + + argv[0] = buf.c_str(); + argv[1] = sstrdup(entry->mask); + ircdproto->SendMode(sender, this->name, "%s %s", buf.c_str(), entry->mask); + chan_set_modes(sender->nick, this, 2, argv, 0); + delete [] argv[1]; + } + } +} + +/** Clear all the invites from the channel + * @param client The client unsetting the modes + */ +void Channel::ClearInvites(char *client) +{ + Entry *entry, *nexte; + BotInfo *sender = (client ? findbot(client) : whosends(ci)); + ChannelModeList *cml; + std::string buf; + const char *argv[2]; + + cml = static_cast(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)); + + if (cml && this->invites && this->invites->count) + { + buf = '-'; + buf += cml->ModeChar; + + for (entry = this->invites->entries; entry; entry = nexte) + { + nexte = entry->next; + + argv[0] = buf.c_str(); + argv[1] = sstrdup(entry->mask); + ircdproto->SendMode(sender, this->name, "%s %s", buf.c_str(), entry->mask); + chan_set_modes(sender->nick, this, 2, argv, 0); + delete [] argv[1]; + } + } +} + /*************************************************************************/ void chan_deluser(User * user, Channel * c) @@ -66,33 +338,50 @@ void chan_deluser(User * user, Channel * c) char *chan_get_modes(Channel * chan, int complete, int plus) { static char res[BUFSIZE]; - char *end = res; - - if (chan->mode) { - unsigned int n = 0; - CBModeInfo *cbmi = cbmodeinfos; - - do { - if (chan->mode & cbmi->flag) - *end++ = cbmi->mode; - } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1); - - if (complete) { - cbmi = cbmodeinfos; + char params[BUFSIZE]; + char *end = res, *value, *pend = params, *pend2 = params; + std::string param; + ChannelMode *cm; + ChannelModeParam *cmp; + std::map::iterator it; + + if (!chan->modes.count()) + { + for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it) + { + cm = it->second; - do { - if (cbmi->getvalue && (chan->mode & cbmi->flag) && - (plus || !(cbmi->flags & CBM_MINUS_NO_ARG))) { - char *value = cbmi->getvalue(chan); + if (chan->HasMode(cm->Name)) + { + *end++ = it->first; - if (value) { - *end++ = ' '; - while (*value) - *end++ = *value++; + if (complete) + { + if (cm->Type == MODE_PARAM) + { + cmp = static_cast(cm); + + if (plus || !cmp->MinusNoArg) + { + chan->GetParam(cmp->Name, ¶m); + + if (!param.empty()) + { + value = const_cast(param.c_str()); + + *pend++ = ' '; + + while (*value) + *pend++ = *value++; + } + } } } - } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1); + } } + + while (*pend2) + *end++ = *pend2++; } *end = 0; @@ -156,128 +445,158 @@ void chan_remove_user_status(Channel * chan, User * user, int16 status) /*************************************************************************/ -void chan_set_modes(const char *source, Channel * chan, int ac, const char **av, - int check) +void chan_set_modes(const char *source, Channel *chan, int ac, const char **av, int check) { - int add = 1; - const char *modes = av[0]; + int add = 1, i, real_ac = ac; + ChannelMode *cm; + ChannelModeStatus *cms; + ChannelModeList *cml; + ChannelModeParam *cmp; + const char *modes, **real_av = av; char mode; - CBMode *cbm; - CMMode *cmm; - CUMode *cum; - unsigned char botmode = 0; BotInfo *bi; + unsigned char botmode = 0; User *user; - int i, real_ac = ac; - const char **real_av = av; + + modes = av[0]; if (debug) - alog("debug: Changing modes for %s to %s", chan->name, - merge_args(ac, av)); + alog("debug: Changing modes for %s to %s", chan->name, merge_args(ac, av)); ac--; - while ((mode = *modes++)) { - - switch (mode) { - case '+': - add = 1; - continue; - case '-': - add = 0; - continue; + while ((mode = *modes++)) + { + switch (mode) + { + case '+': + add = 1; + continue; + case '-': + add = 0; + continue; } - if (static_cast(mode) < 0) { - if (debug) - alog("Debug: Malformed mode detected on %s.", chan->name); - continue; - } + if ((cm = ModeManager::FindChannelModeByChar(mode))) + { + /* v/h/o/a/q etc */ + if (cm->Type == MODE_STATUS) + { + cms = static_cast(cm); - if ((cum = &cumodes[static_cast(mode)])->status != 0) { - if (ac == 0) { - alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name); - continue; - } - ac--; - av++; + if (ac == 0) + { + alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name); + continue; + } - if ((cum->flags & CUF_PROTECT_BOTSERV) && !add) { - if ((bi = findbot(*av))) { - if (!botmode || botmode != mode) { - ircdproto->SendMode(bi, chan->name, "+%c %s", - mode, bi->nick); - botmode = mode; - continue; - } else { - botmode = mode; - continue; + ac--; + av++; + + if (cms->ProtectBotServ && !add) + { + if ((bi = findbot(*av))) + { + if (!botmode || botmode != mode) + { + ircdproto->SendMode(bi, chan->name, "+%c %s", mode, bi->nick); + botmode = mode; + continue; + } + else + { + botmode = mode; + continue; + } } } - } else { - if ((bi = findbot(*av))) { + else if ((bi = findbot(*av))) continue; - } - } - if (!(user = finduser(*av)) - && !(ircd->ts6 && (user = find_byuid(*av)))) { - if (debug) { - alog("debug: MODE %s %c%c for nonexistent user %s", - chan->name, (add ? '+' : '-'), mode, *av); + if (!(user = finduser(*av)) && !(ircd->ts6 && (user = find_byuid(*av)))) + { + if (debug) + { + alog("debug: MODE %s %c%c for nonexistent user %s", + chan->name, (add ? '+' : '-'), mode, *av); + } + continue; } - continue; - } - if (debug) - alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'), - mode, chan->name, user->nick); + if (debug) + alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'), + mode, chan->name, user->nick); - if (add) { - chan_set_user_status(chan, user, cum->status); - /* If this does +o, remove any DEOPPED flag */ - } else { - chan_remove_user_status(chan, user, cum->status); + if (add) + chan_set_user_status(chan, user, cms->Status); + /* If this does +o, remove any DEOPPED flag */ + else + chan_remove_user_status(chan, user, cms->Status); } + /* b/e/I etc */ + else if (cm->Type == MODE_LIST) + { + cml = static_cast(cm); + + if (ac == 0) + { + alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name); + continue; + } + + ac--; + av++; - } else if ((cbm = &cbmodes[static_cast(mode)])->flag != 0) { - if (check >= 0) { if (add) - chan->mode |= cbm->flag; + cml->AddMask(chan, *av); else - chan->mode &= ~cbm->flag; + cml->DelMask(chan, *av); } + else + { + if (check >= 0) + { + if (add) + chan->SetMode(mode); + else + chan->RemoveMode(mode); + } + + if (cm->Type == MODE_PARAM) + { + cmp = static_cast(cm); + + if (add || !cmp->MinusNoArg) + { + if (ac == 0) + { + alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name); + continue; + } + + ac--; + av++; + } - if (cbm->setvalue) { - if (add || !(cbm->flags & CBM_MINUS_NO_ARG)) { - if (ac == 0) { - alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name); + if (*av && !cmp->IsValid(*av)) continue; + if (add) + { + std::string Param = *av; + chan->SetParam(cmp->Name, Param); } - ac--; - av++; + else + chan->UnsetParam(cmp->Name); } - cbm->setvalue(chan, add ? *av : NULL); - } - if (check < 0) { - if (add) - chan->mode |= cbm->flag; - else - chan->mode &= ~cbm->flag; - } - } else if ((cmm = &cmmodes[static_cast(mode)])->addmask) { - if (ac == 0) { - alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name); - continue; + if (check < 0) + { + if (add) + chan->SetMode(mode); + else + chan->RemoveMode(mode); + } } - - ac--; - av++; - if (add) - cmm->addmask(chan, *av); - else - cmm->delmask(chan, *av); } } @@ -297,6 +616,7 @@ void chan_set_modes(const char *source, Channel * chan, int ac, const char **av, */ real_ac--; real_av++; + for (i = 0; i < real_ac; i++) { if ((user = finduser(*real_av)) && is_on_chan(chan, user)) @@ -328,19 +648,24 @@ void chan_set_modes(const char *source, Channel * chan, int ac, const char **av, void chan_set_user_status(Channel * chan, User * user, int16 status) { struct u_chanlist *uc; + UserMode *um; + char av[3]; if (debug >= 2) alog("debug: setting user status (%d) on %s for %s", status, user->nick, chan->name); - if (HelpChannel && ircd->supporthelper && (status & CUS_OP) + if (HelpChannel && ((um = ModeManager::FindUserModeByName(UMODE_HELPOP))) && (status & CUS_OP) && (stricmp(chan->name, HelpChannel) == 0) && (!chan->ci || check_access(user, chan->ci, CA_AUTOOP))) { if (debug) { - alog("debug: %s being given +h for having %d status in %s", + alog("debug: %s being given helpop for having %d status in %s", user->nick, status, chan->name); } - common_svsmode(user, "+h", NULL); + + snprintf(av, sizeof(av), "+%c", um->ModeChar); + + common_svsmode(user, av, NULL); } for (uc = user->chans; uc; uc = uc->next) { @@ -429,6 +754,7 @@ void get_channel_stats(long *nrec, long *memuse) struct c_userlist *cu; BanData *bd; int i; + std::string buf; for (i = 0; i < 1024; i++) { for (chan = chanlist[i]; chan; chan = chan->next) { @@ -436,23 +762,17 @@ void get_channel_stats(long *nrec, long *memuse) mem += sizeof(*chan); if (chan->topic) mem += strlen(chan->topic) + 1; - if (chan->key) - mem += strlen(chan->key) + 1; - if (ircd->fmode) { - if (chan->flood) - mem += strlen(chan->flood) + 1; - } - if (ircd->Lmode) { - if (chan->redirect) - mem += strlen(chan->redirect) + 1; - } + if (chan->GetParam(CMODE_KEY, &buf)) + mem += buf.length() + 1; + if (chan->GetParam(CMODE_FLOOD, &buf)) + mem += buf.length() + 1; + if (chan->GetParam(CMODE_REDIRECT, &buf)) + mem += buf.length() + 1; mem += get_memuse(chan->bans); - if (ircd->except) { + if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) mem += get_memuse(chan->excepts); - } - if (ircd->invitemode) { + if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)) mem += get_memuse(chan->invites); - } for (cu = chan->users; cu; cu = cu->next) { mem += sizeof(*cu); if (cu->ud) { @@ -756,12 +1076,13 @@ void do_sjoin(const char *source, int ac, const char **av) Server *serv; struct c_userlist *cu; const char *s = NULL; - char *buf, *end, cubuf[7], *end2; + char *buf, *end, cubuf[7], *end2, value; const char *modes[6]; int is_sqlined = 0; int ts = 0; int is_created = 0; int keep_their_modes = 1; + ChannelModeList *cml; serv = findserver(servlist, source); @@ -792,9 +1113,9 @@ void do_sjoin(const char *source, int ac, const char **av) bot_join(c->ci); } /* Make sure +r is set */ - if (ircd->chanreg && ircd->regmode) + if (ModeManager::FindChannelModeByName(CMODE_REGISTERED)) { - c->mode |= ircd->regmode; + c->SetMode(CMODE_REGISTERED); ircdproto->SendMode(whosends(c->ci), c->name, "+r"); } } @@ -827,8 +1148,12 @@ void do_sjoin(const char *source, int ac, const char **av) if (ircd->sjoinbanchar) { if (*s == ircd->sjoinbanchar && keep_their_modes) { - buf = myStrGetToken(s, ircd->sjoinbanchar, 1); - add_ban(c, buf); + buf = myStrGetToken(s, ircd->sjoinbanchar, 1); + + cml = static_cast(ModeManager::FindChannelModeByName(CMODE_BAN)); + if (cml->IsValid(buf)) + cml->AddMask(c, buf); + delete [] buf; if (!end) break; @@ -839,7 +1164,11 @@ void do_sjoin(const char *source, int ac, const char **av) if (ircd->sjoinexchar) { if (*s == ircd->sjoinexchar && keep_their_modes) { buf = myStrGetToken(s, ircd->sjoinexchar, 1); - add_exception(c, buf); + + cml = static_cast(ModeManager::FindChannelModeByName(CMODE_EXCEPT)); + if (cml->IsValid(buf)) + cml->AddMask(c, buf); + delete [] buf; if (!end) break; @@ -851,7 +1180,11 @@ void do_sjoin(const char *source, int ac, const char **av) if (ircd->sjoininvchar) { if (*s == ircd->sjoininvchar && keep_their_modes) { buf = myStrGetToken(s, ircd->sjoininvchar, 1); - add_invite(c, buf); + + cml = static_cast(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)); + if (cml->IsValid(buf)) + cml->AddMask(c, buf); + delete [] buf; if (!end) break; @@ -860,11 +1193,13 @@ void do_sjoin(const char *source, int ac, const char **av) } } - while (csmodes[static_cast(*s)] != 0) - *end2++ = csmodes[static_cast(*s++)]; + while ((value = ModeManager::GetStatusChar(*s))) + { + *end2++ = value; + *s++; + } *end2 = 0; - if (ircd->ts6) { user = find_byuid(s); if (!user) @@ -944,8 +1279,11 @@ void do_sjoin(const char *source, int ac, const char **av) end2 = cubuf + 1; - while (csmodes[static_cast(*s)] != 0) - *end2++ = csmodes[static_cast(*s++)]; + while ((value = ModeManager::GetStatusChar(*s))) + { + *end2++ = value; + *s++; + } *end2 = 0; if (ircd->ts6) { @@ -1017,8 +1355,11 @@ void do_sjoin(const char *source, int ac, const char **av) end2 = cubuf + 1; - while (csmodes[static_cast(*s)] != 0) - *end2++ = csmodes[static_cast(*s++)]; + while ((value = ModeManager::GetStatusChar(*s))) + { + *end2++ = value; + *s++; + } *end2 = 0; if (ircd->ts6) { @@ -1264,95 +1605,6 @@ void do_topic(const char *source, int ac, const char **av) /**************************** Internal Calls *****************************/ /*************************************************************************/ -void add_ban(Channel * chan, const char *mask) -{ - Entry *ban; - /* check for NULL values otherwise we will segfault */ - if (!chan || !mask) { - if (debug) { - alog("debug: add_ban called with NULL values"); - } - return; - } - - /* Check if the list already exists, if not create it. - * Create a new ban and add it to the list.. ~ Viper */ - if (!chan->bans) - chan->bans = list_create(); - ban = entry_add(chan->bans, mask); - - if (!ban) - fatal("Creating new ban entry failed"); - - /* Check whether it matches a botserv bot after adding internally - * and parsing it through cidr support. ~ Viper */ - if (s_BotServ && BSSmartJoin && chan->ci && chan->ci->bi - && chan->usercount >= BSMinUsers) { - BotInfo *bi = chan->ci->bi; - - if (entry_match(ban, bi->nick, bi->user, bi->host, 0)) { - ircdproto->SendMode(bi, chan->name, "-b %s", mask); - entry_delete(chan->bans, ban); - return; - } - } - - if (debug) - alog("debug: Added ban %s to channel %s", mask, chan->name); -} - -/*************************************************************************/ - -void add_exception(Channel * chan, const char *mask) -{ - Entry *exception; - - if (!chan || !mask) { - if (debug) - alog("debug: add_exception called with NULL values"); - return; - } - - /* Check if the list alread