From d7d01bdc5c667a1fafd95241282b58e03b4caa5b Mon Sep 17 00:00:00 2001 From: rburchell Date: Mon, 9 Feb 2009 21:01:05 +0000 Subject: Squashed commit: merge next (1.9.1) back to trunk. SVN users, NOTE: THIS WILL NOT BUILD, NOR SHOULD YOU RUN IT YET. git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@1953 5417fbe8-f217-4b02-8779-1006273d7864 --- TODO | 35 +- data/example.conf | 2 +- include/extern.h | 49 +- include/modules.h | 162 +++-- include/services.h | 43 +- include/users.h | 50 +- lang/cat.l | 2 - lang/de.l | 2 - lang/en_us.l | 2 - lang/es.l | 2 - lang/fr.l | 2 - lang/gr.l | 2 - lang/hun.l | 2 - lang/it.l | 2 - lang/nl.l | 2 - lang/pl.l | 2 - lang/pt.l | 2 - lang/ru.l | 2 - lang/tr.l | 2 - src/actions.c | 43 +- src/botserv.c | 18 +- src/channels.c | 37 +- src/chanserv.c | 24 +- src/commands.c | 132 ++--- src/core/bs_act.c | 102 ++-- src/core/bs_assign.c | 115 ++-- src/core/bs_badwords.c | 323 ++++++---- src/core/bs_bot.c | 178 +++--- src/core/bs_botlist.c | 110 ++-- src/core/bs_fantasy.c | 79 --- src/core/bs_fantasy_kick.c | 87 --- src/core/bs_fantasy_kickban.c | 89 --- src/core/bs_fantasy_owner.c | 78 --- src/core/bs_fantasy_seen.c | 128 ---- src/core/bs_help.c | 44 +- src/core/bs_info.c | 451 +++++++------- src/core/bs_kick.c | 598 +++++++++---------- src/core/bs_say.c | 112 ++-- src/core/bs_set.c | 300 +++++----- src/core/bs_unassign.c | 75 +-- src/core/cs_access.c | 748 +++++++++++------------ src/core/cs_akick.c | 852 ++++++++++++++------------- src/core/cs_ban.c | 317 +++++----- src/core/cs_clear.c | 596 ++++++++++--------- src/core/cs_drop.c | 145 +++-- src/core/cs_forbid.c | 153 ++--- src/core/cs_getkey.c | 105 ++-- src/core/cs_getpass.c | 124 ++-- src/core/cs_help.c | 94 +-- src/core/cs_identify.c | 131 +++-- src/core/cs_info.c | 301 ++++------ src/core/cs_invite.c | 111 ++-- src/core/cs_kick.c | 173 +++--- src/core/cs_logout.c | 2 +- src/core/cs_register.c | 4 +- src/core/cs_sendpass.c | 2 +- src/core/cs_set.c | 12 +- src/core/cs_topic.c | 2 +- src/core/cs_xop.c | 2 +- src/core/he_help.c | 63 +- src/core/hs_del.c | 86 +-- src/core/hs_delall.c | 98 +-- src/core/hs_group.c | 140 +++-- src/core/hs_help.c | 49 +- src/core/hs_list.c | 260 ++++---- src/core/hs_off.c | 77 +-- src/core/hs_on.c | 106 ++-- src/core/hs_set.c | 257 ++++---- src/core/hs_setall.c | 255 ++++---- src/core/ms_cancel.c | 112 ++-- src/core/ms_check.c | 144 ++--- src/core/ms_del.c | 271 +++++---- src/core/ms_help.c | 52 +- src/core/ms_info.c | 370 ++++++------ src/core/ms_list.c | 220 +++---- src/core/ms_read.c | 224 +++---- src/core/ms_rsend.c | 135 +++-- src/core/ms_send.c | 54 +- src/core/ms_sendall.c | 101 ++-- src/core/ms_set.c | 446 +++++++------- src/core/ms_staff.c | 96 +-- src/core/ns_access.c | 246 ++++---- src/core/ns_alist.c | 258 ++++---- src/core/ns_drop.c | 202 ++++--- src/core/ns_forbid.c | 171 +++--- src/core/ns_getemail.c | 99 ++-- src/core/ns_getpass.c | 125 ++-- src/core/ns_ghost.c | 136 +++-- src/core/ns_group.c | 512 ++++++++-------- src/core/ns_help.c | 74 ++- src/core/ns_identify.c | 231 ++++---- src/core/ns_info.c | 423 +++++++------ src/core/ns_list.c | 336 +++++------ src/core/ns_logout.c | 162 ++--- src/core/ns_recover.c | 171 +++--- src/core/ns_register.c | 757 +++++++++++++----------- src/core/ns_release.c | 149 +++-- src/core/ns_saset.c | 918 ++++++++++++++++------------- src/core/ns_sendpass.c | 139 ++--- src/core/ns_set.c | 820 ++++++++++++++------------ src/core/ns_status.c | 90 +-- src/core/ns_suspend.c | 262 +++++---- src/core/ns_update.c | 77 ++- src/core/os_admin.c | 258 ++++---- src/core/os_akill.c | 381 ++++++------ src/core/os_chankill.c | 158 +++-- src/core/os_chanlist.c | 132 +++-- src/core/os_clearmodes.c | 427 +++++++------- src/core/os_defcon.c | 192 +++--- src/core/os_global.c | 69 ++- src/core/os_help.c | 51 +- src/core/os_ignore.c | 198 ++++--- src/core/os_jupe.c | 87 +-- src/core/os_kick.c | 103 ++-- src/core/os_logonnews.c | 94 --- src/core/os_mode.c | 104 ++-- src/core/os_modinfo.c | 118 ++-- src/core/os_modlist.c | 298 +++++----- src/core/os_modload.c | 94 +-- src/core/os_modunload.c | 92 +-- src/core/os_news.c | 336 +++++++++++ src/core/os_noop.c | 116 ++-- src/core/os_oline.c | 114 ++-- src/core/os_oper.c | 263 ++++++--- src/core/os_opernews.c | 87 --- src/core/os_quit.c | 64 +- src/core/os_randomnews.c | 54 -- src/core/os_raw.c | 64 +- src/core/os_reload.c | 68 ++- src/core/os_restart.c | 76 +-- src/core/os_session.c | 380 +++++++++++- src/core/os_set.c | 336 +++++++---- src/core/os_shutdown.c | 64 +- src/core/os_sqline.c | 355 ++++++----- src/core/os_staff.c | 142 ++--- src/core/os_stats.c | 587 +++++++++--------- src/core/os_svsnick.c | 150 ++--- src/core/os_szline.c | 339 ++++++----- src/core/os_umode.c | 126 ++-- src/core/os_update.c | 49 +- src/core/os_userlist.c | 136 ++--- src/core/ss_main.c | 45 +- src/hostserv.c | 7 +- src/init.c | 49 +- src/main.c | 224 +------ src/memory.c | 16 - src/messages.c | 2 +- src/misc.c | 2 +- src/module.cpp | 14 +- src/modulemanager.cpp | 18 +- src/modules.c | 102 +--- src/modules/cs_appendtopic.c | 266 ++++----- src/modules/cs_enforce.c | 778 ++++++++++++------------ src/modules/cs_tban.c | 210 +++---- src/modules/hs_request.c | 1308 +++++++++++++++++++++-------------------- src/modules/ns_maxemail.c | 166 +++--- src/modules/os_info.c | 955 +++++++++++++++--------------- src/news.c | 158 ----- src/nickserv.c | 14 +- src/process.c | 8 +- src/protocol/bahamut.c | 1 - src/protocol/inspircd11.c | 1 - src/protocol/inspircd12.cpp | 31 +- src/protocol/ratbox.c | 11 +- src/protocol/unreal32.c | 11 +- src/sessions.c | 305 ---------- src/users.c | 275 ++++----- src/windows.cpp | 27 + 168 files changed, 14760 insertions(+), 14344 deletions(-) delete mode 100644 src/core/bs_fantasy.c delete mode 100644 src/core/bs_fantasy_kick.c delete mode 100644 src/core/bs_fantasy_kickban.c delete mode 100644 src/core/bs_fantasy_owner.c delete mode 100644 src/core/bs_fantasy_seen.c delete mode 100644 src/core/os_logonnews.c create mode 100644 src/core/os_news.c delete mode 100644 src/core/os_opernews.c delete mode 100644 src/core/os_randomnews.c create mode 100644 src/windows.cpp diff --git a/TODO b/TODO index 396f2d920..4aabf74a8 100644 --- a/TODO +++ b/TODO @@ -35,26 +35,37 @@ Legend: 1.9.1 ----- [ ] Remove modules_unload_all fini + hack that goes with it - [ ] signal handling cleanup + [x] signal handling cleanup [ ] Move a (lot) of stuff to class members as a defined interface rather than copypasta everywhere (ns_set, ns_saset!) -[ ] Redo database insanity. - [ ] Move database load/save to a module - [ ] realtime SQL/whatever module using events - [ ] flatfile save on a periodic timer - [ ] SANE password encryption - prefix password with the method it was encrypted with, allowing for *seamless* upgrading to different methods - [ ] Salted SHA256 (contact Special for this) - [ ] New database format (text, not binary - works very well for merging and so on) [ ] burn do_sjoin with fire -[ ] Seamless fantasy support for all ChanServ commands, instead of requiring bs_fantasy_* +[x] Seamless fantasy support for all ChanServ commands, instead of requiring bs_fantasy_* + Remaining issues: + ? [ ] Allow fantasy to be disabled from some commands (e.g. FORBID?) seems unnecessary, really. + [ ] (think on this carefully): some commands (e.g. !help) need to strip the pre-provided channelname from them. + [ ] (will require wider re-work): allow replies/notifications to fantasy commands to go to the channel via notice [ ] HelpServ must die (1.9.1?) -[ ] Command parser cleanup - [ ] mod_current_buffer needs to go away and be replaced by a proper parser. Commands should then indicate how they want the buffer split. +[-] Command parser cleanup: mod_current_buffer needs to go away and be replaced by a proper parser. Commands should then indicate how they want the buffer split. [ ] Fix permanent channels support properly. This will require removing do_sjoin(). [ ] Make NS ENFORCE/RELEASE stuff more sane, redo timers -[ ] Add support for +k, +q, etc type umodes +[x] Add support for +k, +q, etc type umodes + Remaining issues: + ? [ ] Also deny kills with usermode +q at Unreal, bearing in mind that AKILL on yourself is prevented that way. + ? [ ] Add a force parameter to SendSVSKill/SendKick. + [ ] No check at modechange yet, maybe it's better to define in what circumstances it shall block, first. + [ ] Check whether there is a similar usermode in other IRCds and add them to the refering protocol. + [ ] Check for blocked KICK in e.g /cs kick. +[x] Support operoverride and such things (stop reversing mode changes from nonopped people where unnecessary) - done by Liber 1.9.2 ----- +[ ] Redo database insanity. + [ ] Move database load/save to a module + [ ] realtime SQL/whatever module using events (possibly ongoing) + [ ] flatfile save on a periodic timer + [ ] SANE password encryption - prefix password with the method it was encrypted with, allowing for *seamless* upgrading to different methods + [ ] Salted SHA256 (contact Special for this) + [ ] New database format (text, not binary - works very well for merging and so on) +[ ] IRCd capability support: don't rely on CAPAB, provide an interface to turn capabilities on specifically [ ] Socket subsystem needs some serious loving [ ] Multiple sockets [ ] Asynchronous, using select() (multiple engines? not really needed..) diff --git a/data/example.conf b/data/example.conf index b66a2cb52..7f8951927 100644 --- a/data/example.conf +++ b/data/example.conf @@ -974,7 +974,7 @@ botserv * The core modules to load for BotServ. This is a space separated list that corresponds * to the base names of the modules for BotServ. This directive is optional, but highly recommended. */ - modules = "bs_help bs_botlist bs_assign bs_set bs_kick bs_badwords bs_act bs_info bs_say bs_unassign bs_bot bs_fantasy bs_fantasy_kick bs_fantasy_kickban bs_fantasy_owner bs_fantasy_seen bs_fantasy_unban" + modules = "bs_help bs_botlist bs_assign bs_set bs_kick bs_badwords bs_act bs_info bs_say bs_unassign bs_bot" /* * The default bot options for newly registered channel. Note that changing these options diff --git a/include/extern.h b/include/extern.h index a12c3448a..a455a4a0b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -137,10 +137,10 @@ E Entry *entry_create(char *mask); E Entry *entry_add(EList *list, const char *mask); E void entry_delete(EList *list, Entry *e); E EList *list_create(); -E int entry_match(Entry *e, char *nick, char *user, char *host, uint32 ip); -E int entry_match_mask(Entry *e, char *mask, uint32 ip); -E Entry *elist_match(EList *list, char *nick, char *user, char *host, uint32 ip); -E Entry *elist_match_mask(EList *list, char *mask, uint32 ip); +E int entry_match(Entry *e, const char *nick, const char *user, const char *host, uint32 ip); +E int entry_match_mask(Entry *e, const char *mask, uint32 ip); +E Entry *elist_match(EList *list, const char *nick, const char *user, const char *host, uint32 ip); +E Entry *elist_match_mask(EList *list, const char *mask, uint32 ip); E Entry *elist_match_user(EList *list, User *u); E Entry *elist_find_mask(EList *list, const char *mask); E long get_memuse(EList *list); @@ -942,7 +942,6 @@ E User *do_nick(const char *source, const char *nick, const char *username, cons const char *server, const char *realname, time_t ts, uint32 svid, uint32 ip, const char *vhost, const char *uid); E void do_umode(const char *source, int ac, const char **av); -E void do_umode2(const char *source, int ac, const char **av); E void do_quit(const char *source, int ac, const char **av); E void do_kill(const char *source, const char *reason); @@ -950,54 +949,16 @@ E int is_oper(User * user); E int is_protected(User * user); E int is_excepted(ChannelInfo * ci, User * user); -E int is_excepted_mask(ChannelInfo * ci, char *mask); +E int is_excepted_mask(ChannelInfo * ci, const char *mask); E int match_usermask(const char *mask, User * user); -E int match_userip(const char *mask, User * user, char *host); E void split_usermask(const char *mask, char **nick, char **user, char **host); E char *create_mask(User * u); -#ifdef USE_MYSQL -/**** mysql.c ****/ -E MYSQL *mysql; -E MYSQL_RES *mysql_res; -E MYSQL_FIELD *mysql_fields; -E MYSQL_ROW mysql_row; - -E int db_mysql_init(); -E int db_mysql_open(); -E int db_mysql_close(); -E int db_mysql_query(char *sql); -E char *db_mysql_quote(char *sql); -E char *db_mysql_quote_buffer(char *sql, int size); -E int db_mysql_try(const char *fmt, ...); -E int db_mysql_save_ns_core(NickCore * nc); -E int db_mysql_save_ns_alias(NickAlias * na); -E int db_mysql_save_ns_req(NickRequest * nr); -E int db_mysql_save_cs_info(ChannelInfo * ci); -E int db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime, - SList * ak, SList * sgl, SList * sql, - SList * szl); -E int db_mysql_save_news(NewsItem * ni); -E int db_mysql_save_exceptions(Exception * e); -E int db_mysql_save_hs_core(HostCore * hc); -E int db_mysql_save_bs_core(BotInfo * bi); -E int db_mysql_load_bs_dbase(); -E int db_mysql_load_hs_dbase(); -E int db_mysql_load_ns_dbase(); -E int db_mysql_load_ns_req_dbase(); -E int db_mysql_load_cs_dbase(); -E int db_mysql_load_os_dbase(); -E int db_mysql_load_exceptions(); -E int db_mysql_load_news(); -E unsigned int mysql_rand(); -#endif /******************************************************************************/ -E char *common_get_vident(User *u); -E char *common_get_vhost(User *u); E const char* base64enc(long i); E long base64dec(char *b64); E long base64dects(const char *ts); diff --git a/include/modules.h b/include/modules.h index 5c4eaa67c..eb0b8c4a6 100644 --- a/include/modules.h +++ b/include/modules.h @@ -20,30 +20,24 @@ /* Cross OS compatibility macros */ #ifdef _WIN32 -typedef HMODULE ano_module_t; - -#define ano_modopen(file) LoadLibrary(file) -/* ano_moderr in modules.c */ -#define ano_modsym(file, symbol) (HMODULE)GetProcAddress(file, symbol) -#define ano_modclose(file) FreeLibrary(file) ? 0 : 1 -#define ano_modclearerr() SetLastError(0) -#define MODULE_EXT ".so" - + typedef HMODULE ano_module_t; + + #define dlopen(file, unused) LoadLibrary(file) + MDE const char *dlerror(); + #define dlsym(file, symbol) (HMODULE)GetProcAddress(file, symbol) + #define dlclose(file) FreeLibrary(file) ? 0 : 1 + #define ano_modclearerr() SetLastError(0) + #define MODULE_EXT ".so" #else -typedef void * ano_module_t; - -#define ano_modopen(file) dlopen(file, RTLD_LAZY) -#define ano_moderr() dlerror() -#define ano_modsym(file, symbol) dlsym(file, symbol) -#define ano_modclose(file) dlclose(file) -/* We call dlerror() here because it clears the module error after being - * called. This previously read 'errno = 0', but that didn't work on - * all POSIX-compliant architectures. This way the error is guaranteed - * to be cleared, POSIX-wise. -GD - */ -#define ano_modclearerr() dlerror() -#define MODULE_EXT ".so" + typedef void * ano_module_t; + /* We call dlerror() here because it clears the module error after being + * called. This previously read 'errno = 0', but that didn't work on + * all POSIX-compliant architectures. This way the error is guaranteed + * to be cleared, POSIX-wise. -GD + */ + #define ano_modclearerr() dlerror() + #define MODULE_EXT ".so" #endif @@ -51,8 +45,13 @@ typedef void * ano_module_t; #define CMD_HASH(x) (((x)[0]&31)<<5 | ((x)[1]&31)) /* Will gen a hash from a string :) */ #define MAX_CMD_HASH 1024 -#define MOD_STOP 1 -#define MOD_CONT 0 +/** The return value from commands. + */ +enum CommandReturn +{ + MOD_CONT, + MOD_STOP +}; #define HOSTSERV HS_cmdTable /* using HOSTSERV etc. looks nicer than HS_cmdTable for modules */ #define BOTSERV BS_cmdTable @@ -122,7 +121,6 @@ typedef enum { MOD_OP_LOAD, MOD_OP_UNLOAD } ModuleOperation; /*************************************************************************/ /* Structure for information about a *Serv command. */ -typedef struct Command_ Command; struct CommandHash; typedef struct ModuleLang_ ModuleLang; typedef struct ModuleHash_ ModuleHash; @@ -148,6 +146,86 @@ struct ModuleLang_ { char **argv; }; +/** Every services command is a class, inheriting from Command. + */ +class Command +{ + public: + size_t MaxParams; + size_t MinParams; + std::string name; + + /** Create a new command. + * @param min_params The minimum number of parameters the parser will require to execute this command + * @param max_params The maximum number of parameters the parser will create, after max_params, all will be combined into the last argument. + * NOTE: If max_params is not set (default), there is no limit to the max number of params. + */ + Command(const std::string &sname, size_t min_params, size_t max_params = 0) : MaxParams(max_params), MinParams(min_params), name(sname) + { + this->has_priv = NULL; + this->help_param1 = NULL; + this->help_param2 = NULL; + this->help_param3 = NULL; + this->help_param4 = NULL; + this->core = 0; + this->next = NULL; + this->mod_name = NULL; + this->service = NULL; + this->all_help = NULL; + this->regular_help = NULL; + this->oper_help = NULL; + this->admin_help = NULL; + this->root_help = NULL; + } + + ~Command() + { + this->has_priv = NULL; + if (this->mod_name) { + delete [] this->mod_name; + } + if (this->service) { + delete [] this->service; + } + this->next = NULL; + } + + /** Execute this command. + * @param u The user executing the command. + */ + virtual CommandReturn Execute(User *u, std::vector &) { return MOD_CONT; } + + /** Requested when the user is requesting help on this command. Help on this command should be sent to the user. + * @param u The user requesting help + * @param subcommand The subcommand the user is requesting help on, or an empty string. (e.g. /ns help set foo bar lol gives a subcommand of "FOO BAR LOL") + * @return true if help was provided to the user, false otherwise. + */ + virtual bool OnHelp(User *u, const std::string &subcommand) { return false; } + + /** Requested when the user provides bad syntax to this command (not enough params, etc). + * @param u The user executing the command. + */ + virtual void OnBadSyntax(User *u) { } + + int (*has_priv)(User *u); /* Returns 1 if user may use command, else 0 */ + + char *help_param1; + char *help_param2; + char *help_param3; + char *help_param4; + + /* Module related stuff */ + int core; /* Can this command be deleted? */ + char *mod_name; /* Name of the module who owns us, NULL for core's */ + char *service; /* Service we provide this command for */ + int (*all_help)(User *u); + int (*regular_help)(User *u); + int (*oper_help)(User *u); + int (*admin_help)(User *u); + int (*root_help)(User *u); + + Command *next; /* Next command responsible for the same command */ +}; /** Every module in Anope is actually a class. */ class CoreExport Module @@ -398,38 +476,6 @@ struct ModuleHash_ { ModuleHash *next; }; -struct Command_ { - char *name; - int (*routine)(User *u); - int (*has_priv)(User *u); /* Returns 1 if user may use command, else 0 */ - - /* Regrettably, these are hard-coded to correspond to current privilege - * levels (v4.0). Suggestions for better ways to do this are - * appreciated. - */ - int helpmsg_all; /* Displayed to all users; -1 = no message */ - int helpmsg_reg; /* Displayed to regular users only */ - int helpmsg_oper; /* Displayed to Services operators only */ - int helpmsg_admin; /* Displayed to Services admins only */ - int helpmsg_root; /* Displayed to Services root only */ - char *help_param1; - char *help_param2; - char *help_param3; - char *help_param4; - - /* Module related stuff */ - int core; /* Can this command be deleted? */ - char *mod_name; /* Name of the module who owns us, NULL for core's */ - char *service; /* Service we provide this command for */ - int (*all_help)(User *u); - int (*regular_help)(User *u); - int (*oper_help)(User *u); - int (*admin_help)(User *u); - int (*root_help)(User *u); - - Command *next; /* Next command responsible for the same command */ -}; - struct CommandHash { char *name; /* Name of the command */ Command *c; /* Actual command */ @@ -494,8 +540,6 @@ extern MDE char *mod_current_buffer; /*************************************************************************/ /*************************************************************************/ /* Command Managment Functions */ -MDE Command *createCommand(const char *name,int (*func)(User *u),int (*has_priv)(User *u),int help_all, int help_reg, int help_oper, int help_admin,int help_root); -MDE int destroyCommand(Command *c); /* destroy a command */ Command *findCommand(CommandHash *cmdTable[], const char *name); /* Find a command */ /*************************************************************************/ diff --git a/include/services.h b/include/services.h index 46e21728b..76a2878fa 100644 --- a/include/services.h +++ b/include/services.h @@ -542,7 +542,6 @@ struct ircdcapab_ { uint32 vhost; uint32 ssj3; uint32 nick2; - uint32 umode2; uint32 vl; uint32 tlkext; uint32 dodkey; @@ -1173,7 +1172,7 @@ typedef struct ircd_modes_ { #define CUS_HALFOP 0x0004 /* Halfop (+h) */ #define CUS_OWNER 0x0008 /* Owner/Founder (+q) */ #define CUS_PROTECT 0x0010 /* Protected users (+a) */ -#define CUS_DEOPPED 0x0080 /* User has been specifically deopped */ +/* #define CUS_DEOPPED 0x0080 */ /* Removed due to IRCd checking it */ #define MUT_DEOP 0 #define MUT_OP 1 @@ -1218,12 +1217,11 @@ struct capabinfo_ { #define CAPAB_TOKEN 0x00400000 #define CAPAB_SSJ3 0x00800000 #define CAPAB_NICK2 0x01000000 -#define CAPAB_UMODE2 0x02000000 -#define CAPAB_VL 0x04000000 -#define CAPAB_TLKEXT 0x08000000 -#define CAPAB_CHANMODE 0x10000000 -#define CAPAB_SJB64 0x20000000 -#define CAPAB_NICKCHARS 0x40000000 +#define CAPAB_VL 0x02000000 +#define CAPAB_TLKEXT 0x04000000 +#define CAPAB_CHANMODE 0x08000000 +#define CAPAB_SJB64 0x10000000 +#define CAPAB_NICKCHARS 0x20000000 /*************************************************************************/ @@ -1311,14 +1309,24 @@ private: virtual void SendTopic(BotInfo *, const char *, const char *, const char *, time_t) = 0; virtual void SendVhostDel(User *) { } virtual void SendAkill(const char *, const char *, const char *, time_t, time_t, const char *) = 0; - virtual void SendSVSKill(const char *source, const char *user, const char *fmt, ...) + virtual bool CanSVSKill(const char *source, const char *user, const char *buf) + { + return true; + } + virtual bool SendSVSKill(const char *source, const char *user, const char *fmt, ...) { va_list args; char buf[BUFSIZE] = ""; va_start(args, fmt); vsnprintf(buf, BUFSIZE - 1, fmt, args); va_end(args); - SendSVSKillInternal(source, user, buf); + + if (CanSVSKill(source, user, buf)) + { + SendSVSKillInternal(source, user, buf); + } + + return false; } virtual void SendSVSMode(User *, int, const char **) = 0; virtual void SendMode(BotInfo *bi, const char *dest, const char *fmt, ...) @@ -1331,14 +1339,25 @@ private: SendModeInternal(bi, dest, buf); } virtual void SendClientIntroduction(const char *, const char *, const char *, const char *, const char *, const char *uid) = 0; - virtual void SendKick(BotInfo *bi, const char *chan, const char *user, const char *fmt, ...) + virtual bool CanKick(BotInfo *bi, const char *chan, const char *user, const char *buf) + { + return true; + } + virtual bool SendKick(BotInfo *bi, const char *chan, const char *user, const char *fmt, ...) { va_list args; char buf[BUFSIZE] = ""; va_start(args, fmt); vsnprintf(buf, BUFSIZE - 1, fmt, args); va_end(args); - SendKickInternal(bi, chan, user, buf); + + if (CanKick(bi, chan, user, buf)) + { + SendKickInternal(bi, chan, user, buf); + return true; + } + + return false; } virtual void SendNoticeChanops(BotInfo *bi, const char *dest, const char *fmt, ...) { diff --git a/include/users.h b/include/users.h index 9c0c85824..a8ab1b9e8 100644 --- a/include/users.h +++ b/include/users.h @@ -22,17 +22,19 @@ struct u_chaninfolist { /* Online user and channel data. */ class CoreExport User : public Extensible { - public: // XXX: exposing a tiny bit too much + private: + std::string vident; + std::string ident; + std::string uid; +public: // XXX: exposing a tiny bit too much User *next, *prev; char nick[NICKMAX]; - char *username; /* ident */ char *host; /* User's real hostname */ char *hostip; /* User's IP number */ char *vhost; /* User's virtual hostname */ std::string chost; /* User's cloaked hostname */ - char *vident; /* User's virtual ident */ char *realname; /* Realname */ Server *server; /* Server user is connected to */ char *nickTrack; /* Nick Tracking */ @@ -40,7 +42,6 @@ class CoreExport User : public Extensible time_t my_signon; /* When did _we_ see the user? */ time_t svid; /* Services ID */ uint32 mode; /* See below */ - char *uid; /* Univeral ID */ NickAlias *na; @@ -62,14 +63,16 @@ class CoreExport User : public Extensible /** Create a new user object, initialising necessary fields and * adds it to the hash * - * @parameter nick The nickname of the user account. + * @param nick The nickname of the user. + * @param uid The unique identifier of the user. */ - User(const std::string &nick); + User(const std::string &nick, const std::string &uid); /** Destroy a user. */ ~User(); + /** Update the nickname of a user record accordingly, should be * called from ircd protocol. */ @@ -77,13 +80,48 @@ class CoreExport User : public Extensible /** Update the displayed (vhost) of a user record. * This is used (if set) instead of real host. + * @param host The new displayed host to give the user. */ void SetDisplayedHost(const std::string &host); + /** Get the displayed vhost of a user record. + * @return The displayed vhost of the user, where ircd-supported, or the user's real host. + */ + const std::string GetDisplayedHost() const; + + + /** Retrieves the UID of the user, where applicable, if set. + * This is not used on some IRCds, but is for a lot e.g. P10, TS6 protocols. + * @return The UID of the user. + */ + const std::string &GetUID() const; + + /** Update the displayed ident (username) of a user record. + * @param ident The new ident to give this user. + */ + void SetVIdent(const std::string &ident); + + /** Get the displayed ident (username) of this user. + * @return The displayed ident of this user. + */ + const std::string &GetVIdent() const; + + /** Update the real ident (username) of a user record. + * @param ident The new ident to give this user. + * NOTE: Where possible, you should use the Get/SetVIdent() equivilants. */ void SetIdent(const std::string &ident); + /** Get the real ident (username) of this user. + * @return The displayed ident of this user. + * NOTE: Where possible, you should use the Get/SetVIdent() equivilants. + */ + const std::string &GetIdent() const; + + + + /** Updates the realname of the user record. */ void SetRealname(const std::string &realname); diff --git a/lang/cat.l b/lang/cat.l index 4037c5c53..a0a0c7cc8 100644 --- a/lang/cat.l +++ b/lang/cat.l @@ -5746,8 +5746,6 @@ OPER_HELP_STATS L'opció RESET estableix el nombre màxim d'usuaris al nombre d'usuaris actualment presents en la xarxa. - - UPTIME pot ser utilitzat com a sinònim per STATS. OPER_HELP_OPER Sintàxi: OPER ADD nick diff --git a/lang/de.l b/lang/de.l index dea7ef4c1..413767d41 100644 --- a/lang/de.l +++ b/lang/de.l @@ -5764,8 +5764,6 @@ OPER_HELP_STATS Durch RESET werden einige Werte der Statistik zurück- gesetzt, unter anderem die max. Anzahl gleichzeitig verbundenen User. - - UPTIME kann als Synonym für STATS verwendet werden. OPER_HELP_OPER Syntax: OPER ADD Nickname diff --git a/lang/en_us.l b/lang/en_us.l index c0c6a28d3..798dcc2b0 100644 --- a/lang/en_us.l +++ b/lang/en_us.l @@ -5466,8 +5466,6 @@ OPER_HELP_STATS The ALL displays the user and uptime statistics, and everything you'd see with MEMORY and UPLINK options. - - UPTIME may be used as a synonym for STATS. OPER_HELP_OPER Syntax: OPER ADD nick diff --git a/lang/es.l b/lang/es.l index d6b526ea2..f057decb2 100644 --- a/lang/es.l +++ b/lang/es.l @@ -5711,8 +5711,6 @@ OPER_HELP_STATS La opcion RESET resetea la cuenta maxima de usuarios al numero de usuarios actualmente presentes en la red. - - UPTIME puede ser usado como sinonimo para STATS. OPER_HELP_OPER Sintaxis: OPER ADD nick diff --git a/lang/fr.l b/lang/fr.l index 527077fe9..51e177d5e 100644 --- a/lang/fr.l +++ b/lang/fr.l @@ -5801,8 +5801,6 @@ OPER_HELP_STATS L'option UPLINK affiche les informations sur le serveur qui est utilisé pour linker Anope au réseau. - - UPTIME est l'équivalent de STATS. OPER_HELP_OPER Syntaxe: OPER ADD pseudo diff --git a/lang/gr.l b/lang/gr.l index 93f549b21..e9d7fab05 100644 --- a/lang/gr.l +++ b/lang/gr.l @@ -5676,8 +5676,6 @@ OPER_HELP_STATS The RESET option currently resets the maximum user count to the number of users currently present on the network. - - UPTIME may be used as a synonym for STATS. OPER_HELP_OPER Óýíôáîç: OPER ADD øåõäþíõìï diff --git a/lang/hun.l b/lang/hun.l index 33ce1da5f..84224f247 100644 --- a/lang/hun.l +++ b/lang/hun.l @@ -5592,8 +5592,6 @@ OPER_HELP_STATS A RESET beállítás nullázza az aktuális felhasználók max. számát átírja a jelenlegi felhasználó számra - UPTIME, a STATS helyett használható. - OPER_HELP_OPER Syntax: OPER ADD nick OPER DEL {nick | sorszám | lista} diff --git a/lang/it.l b/lang/it.l index 974a1da8d..e29c938de 100644 --- a/lang/it.l +++ b/lang/it.l @@ -5624,8 +5624,6 @@ OPER_HELP_STATS L'opzione RESET imposta il numero massimo di utenti registrato al numero degli utenti connessi attualmente alla rete. - - UPTIME può essere usato come sinonimo di STATS. OPER_HELP_OPER Sintassi: OPER ADD nick diff --git a/lang/nl.l b/lang/nl.l index a57bb0d70..3720bea01 100644 --- a/lang/nl.l +++ b/lang/nl.l @@ -5634,8 +5634,6 @@ OPER_HELP_STATS De ALL optie stelt momenteel het maximum aantal gebruikers in op het aantal gebruikers dat momenteel aanwezig is op het netwerk. - - UPTIME kan als een synoniem voor STATS gebruikt worden. OPER_HELP_OPER Gebruik: OPER ADD nick diff --git a/lang/pl.l b/lang/pl.l index 93347ea24..f1a8dbe15 100644 --- a/lang/pl.l +++ b/lang/pl.l @@ -6746,8 +6746,6 @@ OPER_HELP_STATS którego serwisy s± bezpo¶rednio pod³±czone. Parametr ALL wy¶wietla wszystkie dostêpne informacje. - - UPTIME mo¿e byæ u¿ywane jako synonim STATS. OPER_HELP_OPER Sk³adnia: OPER ADD nick diff --git a/lang/pt.l b/lang/pt.l index 4092de4aa..d79758483 100644 --- a/lang/pt.l +++ b/lang/pt.l @@ -5564,8 +5564,6 @@ OPER_HELP_STATS A opção RESET reinicia a contagem do máximo de usuários para o número de usuários atualmente conectados na rede. - - UPTIME pode ser usado como um sinônimo para STATS. OPER_HELP_OPER Sintaxe: OPER ADD nick diff --git a/lang/ru.l b/lang/ru.l index b3c1a3505..fca82d3bd 100644 --- a/lang/ru.l +++ b/lang/ru.l @@ -5630,8 +5630,6 @@ OPER_HELP_STATS Ïàðàìåòð ALL âûâåäåò îáùóþ ñòàòèñòèêó â êîìáèíàöèè ñ äàííûìè èç MEMORY è UPLINK. - - Êîìàíäà UPTIME ÿâëÿåòñÿ àëèàñîì êîìàíäû STATS. OPER_HELP_OPER Ñèíòàêñèñ: OPER ADD íèê diff --git a/lang/tr.l b/lang/tr.l index 8fb1abf3d..06980c5b9 100644 --- a/lang/tr.l +++ b/lang/tr.l @@ -5635,8 +5635,6 @@ OPER_HELP_STATS RESET parametresi önceki maksimum kullanýcý sayýsýný o anda networkte bulunan kullanýcý sayýsýyla deðiþtirir. - - UPTIME komutu STATS komutunun alternatifi olarak kullanýlabilir. OPER_HELP_OPER Kullanýmý: OPER ADD nick diff --git a/src/actions.c b/src/actions.c index 25bea0091..6b96c66fa 100644 --- a/src/actions.c +++ b/src/actions.c @@ -180,8 +180,8 @@ void common_unban(ChannelInfo * ci, char *nick) for (ban = ci->c->bans->entries; ban; ban = next) { next = ban->next; - if (entry_match(ban, u->nick, u->username, u->host, ip) || - entry_match(ban, u->nick, u->username, u->vhost, ip)) { + if (entry_match(ban, u->nick, u->GetIdent().c_str(), u->host, ip) || + entry_match(ban, u->nick, u->GetIdent().c_str(), u->vhost, ip)) { ircdproto->SendMode(whosends(ci), ci->name, "-b %s", ban->mask); if (ircdcap->tsmode) av[3] = ban->mask; @@ -224,42 +224,3 @@ void common_svsmode(User * u, const char *modes, const char *arg) /*************************************************************************/ -/** - * Get the vhost for the user, if set else return the host, on ircds without - * vhost this returns the host - * @param u user to get the vhost for - * @return vhost - */ -char *common_get_vhost(User * u) -{ - if (!u) - return NULL; - - if (ircd->vhostmode && (u->mode & ircd->vhostmode)) - return u->vhost; - else if (ircd->vhost && u->vhost) - return u->vhost; - else - return u->host; -} - -/*************************************************************************/ - -/** - * Get the vident for the user, if set else return the ident, on ircds without - * vident this returns the ident - * @param u user to get info the vident for - * @return vident - */ -char *common_get_vident(User * u) -{ - if (!u) - return NULL; - - if (ircd->vhostmode && (u->mode & ircd->vhostmode)) - return u->vident; - else if (ircd->vident && u->vident) - return u->vident; - else - return u->username; -} diff --git a/src/botserv.c b/src/botserv.c index e671006e2..96b017bcd 100644 --- a/src/botserv.c +++ b/src/botserv.c @@ -421,14 +421,22 @@ void botchanmsgs(User * u, ChannelInfo * ci, char *buf) /* Strip off the fantasy character */ cmd++; - if (check_access(u, ci, CA_FANTASIA)) + if (check_access(u, ci, CA_FANTASIA)) + { + std::string bbuf = std::string(cmd) + " " + ci->name; + if (params) + { + bbuf += " "; + bbuf += params; + } + chanserv(u, const_cast(bbuf.c_str())); // XXX Unsafe cast, this needs reviewing -- CyberBotX event_name = EVENT_BOT_FANTASY; + } if (params) send_event(event_name, 4, cmd, u->nick, ci->name, params); else - send_event(event_name, 3, cmd, u->nick, ci->name); - } + send_event(event_name, 3, cmd, u->nick, ci->name);} } } @@ -596,8 +604,8 @@ static BanData *get_ban_data(Channel * c, User * u) if (!c || !u) return NULL; - snprintf(mask, sizeof(mask), "%s@%s", u->username, - common_get_vhost(u)); + snprintf(mask, sizeof(mask), "%s@%s", u->GetIdent().c_str(), + u->GetDisplayedHost().c_str()); for (bd = c->bd; bd; bd = next) { if (now - bd->last_use > BSKeepData) { diff --git a/src/channels.c b/src/channels.c index 4d5c08b5a..ab5e0b3a8 100644 --- a/src/channels.c +++ b/src/channels.c @@ -174,27 +174,6 @@ void chan_set_modes(const char *source, Channel * chan, int ac, const char **av, alog("debug: Changing modes for %s to %s", chan->name, merge_args(ac, av)); - u = finduser(source); - if (u && (chan_get_user_status(chan, u) & CUS_DEOPPED)) { - char *s; - - if (debug) - alog("debug: Removing instead of setting due to DEOPPED flag"); - - /* Swap adding and removing of the modes */ - for (s = const_cast(av[0]); *s; s++) { // XXX Unsafe cast, this needs reviewing -- CyberBotX - if (*s == '+') - *s = '-'; - else if (*s == '-') - *s = '+'; - } - - /* Set the resulting mode buffer */ - ircdproto->SendMode(whosends(chan->ci), chan->name, merge_args(ac, av)); - - return; - } - ac--; while ((mode = *modes++)) { @@ -256,8 +235,6 @@ void chan_set_modes(const char *source, Channel * chan, int ac, const char **av, if (add) { chan_set_user_status(chan, user, cum->status); /* If this does +o, remove any DEOPPED flag */ - if (cum->status & CUS_OP) - chan_remove_user_status(chan, user, CUS_DEOPPED); } else { chan_remove_user_status(chan, user, cum->status); } @@ -1471,7 +1448,6 @@ void chan_set_correct_modes(User * user, Channel * c, int give_modes) strcat(modebuf, "o"); strcat(userbuf, " "); strcat(userbuf, user->nick); - rem_modes |= CUS_DEOPPED; } else { add_modes &= ~CUS_OP; } @@ -1510,7 +1486,6 @@ void chan_set_correct_modes(User * user, Channel * c, int give_modes) strcat(modebuf, "o"); strcat(userbuf, " "); strcat(userbuf, user->nick); - add_modes |= CUS_DEOPPED; } if (rem_modes & CUS_HALFOP) { strcat(modebuf, "h"); @@ -2122,7 +2097,7 @@ EList *list_create() * @param ip IP to match against, set to 0 to not match this * @return 1 for a match, 0 for no match */ -int entry_match(Entry * e, char *nick, char *user, char *host, uint32 ip) +int entry_match(Entry * e, const char *nick, const char *user, const char *host, uint32 ip) { /* If we don't get an entry, or it s an invalid one, no match ~ Viper */ if (!e || e->type == ENTRYTYPE_NONE) @@ -2160,7 +2135,7 @@ int entry_match(Entry * e, char *nick, char *user, char *host, uint32 ip) * @param ip IP to match against, set to 0 to not match this * @return 1 for a match, 0 for no match */ -int entry_match_mask(Entry * e, char *mask, uint32 ip) +int entry_match_mask(Entry * e, const char *mask, uint32 ip) { char *hostmask, *nick, *user, *host; int res; @@ -2201,7 +2176,7 @@ int entry_match_mask(Entry * e, char *mask, uint32 ip) * @param ip The ip to match * @return Returns the first matching entry, if none, NULL is returned. */ -Entry *elist_match(EList * list, char *nick, char *user, char *host, +Entry *elist_match(EList * list, const char *nick, const char *user, const char *host, uint32 ip) { Entry *e; @@ -2225,7 +2200,7 @@ Entry *elist_match(EList * list, char *nick, char *user, char *host, * @param ip The ip to match * @return Returns the first matching entry, if none, NULL is returned. */ -Entry *elist_match_mask(EList * list, char *mask, uint32 ip) +Entry *elist_match_mask(EList * list, const char *mask, uint32 ip) { char *hostmask, *nick, *user, *host; Entry *res; @@ -2291,9 +2266,9 @@ Entry *elist_match_user(EList * list, User * u) ip = str_is_ip(host); /* Match what we ve got against the lists.. */ - res = elist_match(list, u->nick, u->username, u->host, ip); + res = elist_match(list, u->nick, u->GetIdent().c_str(), u->host, ip); if (!res) - elist_match(list, u->nick, u->username, u->vhost, ip); + elist_match(list, u->nick, u->GetIdent().c_str(), u->vhost, ip); if (host) delete [] host; diff --git a/src/chanserv.c b/src/chanserv.c index eff790d49..ee3b96e97 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -1197,7 +1197,7 @@ int check_kick(User * user, const char *chan, time_t chants) kick: if (debug) alog("debug: channel: AutoKicking %s!%s@%s from %s", user->nick, - user->username, user->host, chan); + user->GetIdent().c_str(), user->host, chan); /* Remember that the user has not been added to our channel user list * yet, so we check whether the channel does not exist OR has no user @@ -1968,22 +1968,24 @@ int get_idealban(ChannelInfo * ci, User * u, char *ret, int retlen) if (!ci || !u || !ret || retlen == 0) return 0; + std::string vident = u->GetIdent(); + switch (ci->bantype) { case 0: - snprintf(ret, retlen, "*!%s@%s", common_get_vident(u), - common_get_vhost(u)); + snprintf(ret, retlen, "*!%s@%s", vident.c_str(), + u->GetDisplayedHost().c_str()); return 1; case 1: - snprintf(ret, retlen, "*!%s%s@%s", - (strlen(common_get_vident(u)) < - (*(common_get_vident(u)) == - '~' ? USERMAX + 1 : USERMAX) ? "*" : ""), - (*(common_get_vident(u)) == - '~' ? common_get_vident(u) + 1 : common_get_vident(u)), - common_get_vhost(u)); + if (vident[0] == '~') + snprintf(ret, retlen, "*!*%s@%s", + vident.c_str(), u->GetDisplayedHost().c_str()); + else + snprintf(ret, retlen, "*!%s@%s", + vident.c_str(), u->GetDisplayedHost().c_str()); + return 1; case 2: - snprintf(ret, retlen, "*!*@%s", common_get_vhost(u)); + snprintf(ret, retlen, "*!*@%s", u->GetDisplayedHost().c_str()); return 1; case 3: mask = create_mask(u); diff --git a/src/commands.c b/src/commands.c index 52b74b488..17b6629b3 100644 --- a/src/commands.c +++ b/src/commands.c @@ -29,8 +29,8 @@ Command *lookup_cmd(Command * list, char *cmd) { Command *c; - for (c = list; c->name; c++) { - if (stricmp(c->name, cmd) == 0) { + for (c = list; ; c++) { + if (stricmp(c->name.c_str(), cmd) == 0) { return c; } } @@ -48,39 +48,66 @@ Command *lookup_cmd(Command * list, char *cmd) * @param cmd Command * @return void */ -void mod_run_cmd(char *service, User * u, CommandHash * cmdTable[], - const char *cmd) +void mod_run_cmd(char *service, User * u, CommandHash * cmdTable[], const char *cmd) { Command *c = findCommand(cmdTable, cmd); int retVal = 0; Command *current; - if (c && c->routine) { - if ((checkDefCon(DEFCON_OPER_ONLY) - || checkDefCon(DEFCON_SILENT_OPER_ONLY)) && !is_oper(u)) { - if (!checkDefCon(DEFCON_SILENT_OPER_ONLY)) { - notice_lang(service, u, OPER_DEFCON_DENIED); - } - } else { - if ((c->has_priv == NULL) || c->has_priv(u)) { - retVal = c->routine(u); - if (retVal == MOD_CONT) { - current = c->next; - while (current && retVal == MOD_CONT) { - retVal = current->routine(u); - current = current->next; - } - } - } else { - notice_lang(service, u, ACCESS_DENIED); - alog("Access denied for %s with service %s and command %s", - u->nick, service, cmd); - } - } - } else { - if ((!checkDefCon(DEFCON_SILENT_OPER_ONLY)) || is_oper(u)) { + if (!c) + { + if ((!checkDefCon(DEFCON_SILENT_OPER_ONLY)) || is_oper(u)) + { notice_lang(service, u, UNKNOWN_COMMAND_HELP, cmd, service); } + return; + } + + if ((checkDefCon(DEFCON_OPER_ONLY) || checkDefCon(DEFCON_SILENT_OPER_ONLY)) && !is_oper(u)) + { + if (!checkDefCon(DEFCON_SILENT_OPER_ONLY)) + { + notice_lang(service, u, OPER_DEFCON_DENIED); + return; + } + } + + if (c->has_priv != NULL && !c->has_priv(u)) + { + notice_lang(service, u, ACCESS_DENIED); + alog("Access denied for %s with service %s and command %s", u->nick, service, cmd); + return; + } + + std::vector params; + std::string curparam; + char *s = NULL; + while ((s = strtok(NULL, " "))) + { + if (params.size() < c->MaxParams) + params.push_back(s); + else + curparam += s; + } + + if (!curparam.empty()) + params.push_back(curparam); + + if (params.size() < c->MinParams) + { + c->OnBadSyntax(u); + return; + } + + retVal = c->Execute(u, params); + if (retVal == MOD_CONT) + { + current = c->next; + while (current && retVal == MOD_CONT) + { + retVal = current->Execute(u, params); + current = current->next; + } } } @@ -124,7 +151,7 @@ void mod_help_cmd(char *service, User * u, CommandHash * cmdTable[], { Command *c = findCommand(cmdTable, cmd); Command *current; - int has_had_help = 0; + bool has_had_help = false; int cont = MOD_CONT; const char *p1 = NULL, *p2 = NULL, *p3 = NULL, *p4 = NULL; @@ -134,52 +161,9 @@ void mod_help_cmd(char *service, User * u, CommandHash * cmdTable[], p2 = current->help_param2; p3 = current->help_param3; p4 = current->help_param4; - if (current->helpmsg_all >= 0) { - notice_help(service, u, current->helpmsg_all, p1, p2, p3, p4); - has_had_help = 1; - } else if (current->all_help) { - cont = current->all_help(u); - has_had_help = 1; - } - if (is_services_root(u)) { - if (current->helpmsg_root >= 0) { - notice_help(service, u, current->helpmsg_root, p1, p2, p3, - p4); - has_had_help = 1; - } else if (current->root_help) { - cont = current->root_help(u); - has_had_help = 1; - } - } else if (is_services_admin(u)) { - if (current->helpmsg_admin >= 0) { - notice_help(service, u, current->helpmsg_admin, p1, p2, p3, - p4); - has_had_help = 1; - } else if (current->admin_help) { - cont = current->admin_help(u); - has_had_help = 1; - } - } else if (is_services_oper(u)) { - if (current->helpmsg_oper >= 0) { - notice_help(service, u, current->helpmsg_oper, p1, p2, p3, - p4); - has_had_help = 1; - } else if (current->oper_help) { - cont = current->oper_help(u); - has_had_help = 1; - } - } else { - if (current->helpmsg_reg >= 0) { - notice_help(service, u, current->helpmsg_reg, p1, p2, p3, - p4); - has_had_help = 1; - } else if (current->regular_help) { - cont = current->regular_help(u); - has_had_help = 1; - } - } + has_had_help = current->OnHelp(u, ""); // XXX: this needs finishing to actually pass a subcommand } - if (has_had_help == 0) { + if (has_had_help == false) { notice_lang(service, u, NO_HELP_AVAILABLE, cmd); } else { do_help_limited(service, u, c); diff --git a/src/core/bs_act.c b/src/core/bs_act.c index 0f2e34af2..f37f2d942 100644 --- a/src/core/bs_act.c +++ b/src/core/bs_act.c @@ -15,21 +15,78 @@ #include "module.h" -int do_act(User * u); void myBotServHelp(User * u); +class CommandBSAct : public Command +{ + public: + CommandBSAct() : Command("ACT", 2, 2) + { + + } + + CommandReturn Execute(User *u, std::vector ¶ms) + { + ChannelInfo *ci; + + if (!(ci = cs_findchan(params[0].c_str()))) + { + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, params[0].c_str()); + return MOD_CONT; + } + + if (ci->flags & CI_VERBOTEN) + { + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, ci->name); + return MOD_CONT; + } + + if (!ci->bi) + { + notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); + return MOD_CONT; + } + + if (!ci->c || ci->c->usercount < BSMinUsers) + { + notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); + return MOD_CONT; + } + + if (!check_access(u, ci, CA_SAY)) + { + notice_lang(s_BotServ, u, ACCESS_DENIED); + return MOD_CONT; + } + + size_t i = 0; + while ((i = params[1].find_first_of("\001"), i) && i != std::string::npos) + { + params[1].erase(i, 1); + } + + ircdproto->SendAction(ci->bi, ci->name, "%s", params[1].c_str()); + ci->bi->lastmsg = time(NULL); + if (LogBot && LogChannel && logchan && !debug && findchan(LogChannel)) + ircdproto->SendPrivmsg(ci->bi, LogChannel, "ACT %s %s %s", u->nick, ci->name, params[1].c_str()); + return MOD_CONT; + } + + void OnBadSyntax(User *u) + { + syntax_error(s_BotServ, u, "ACT", BOT_ACT_SYNTAX); + } +}; + class BSAct : public Module { public: BSAct(const std::string &modname, const std::string &creator) : Module(modname, creator) { - Command *c; - this->SetAuthor("Anope"); this->SetVersion("$Id$"); this->SetType(CORE); - c = createCommand("ACT", do_act, NULL, BOT_HELP_ACT, -1, -1, -1, -1); - this->AddCommand(BOTSERV, c, MOD_UNIQUE); + this->AddCommand(BOTSERV, new CommandBSAct(), MOD_UNIQUE); this->SetBotHelp(myBotServHelp); } @@ -45,39 +102,4 @@ void myBotServHelp(User * u) notice_lang(s_BotServ, u, BOT_HELP_CMD_ACT); } -/** - * The /bs act command. - * @param u The user who issued the command - * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. - **/ -int do_act(User * u) -{ - ChannelInfo *ci; - - char *chan = strtok(NULL, " "); - char *text = strtok(NULL, ""); - - if (!chan || !text) - syntax_error(s_BotServ, u, "ACT", BOT_ACT_SYNTAX); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); - else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if (!ci->bi) - notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); - else if (!ci->c || ci->c->usercount < BSMinUsers) - notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); - else if (!check_access(u, ci, CA_SAY)) - notice_lang(s_BotServ, u, ACCESS_DENIED); - else { - strnrepl(text, BUFSIZE, "\001", ""); - ircdproto->SendAction(ci->bi, ci->name, "%s", text); - ci->bi->lastmsg = time(NULL); - if (LogBot && LogChannel && logchan && !debug && findchan(LogChannel)) - ircdproto->SendPrivmsg(ci->bi, LogChannel, "ACT %s %s %s", - u->nick, ci->name, text); - } - return MOD_CONT; -} - MODULE_INIT("bs_act", BSAct) diff --git a/src/core/bs_assign.c b/src/core/bs_assign.c index 396031662..f9927e25d 100644 --- a/src/core/bs_assign.c +++ b/src/core/bs_assign.c @@ -15,21 +15,90 @@ #include "module.h" -int do_assign(User * u); void myBotServHelp(User * u); +class CommandBSAssign : public Command +{ + public: + CommandBSAssign() : Command("ASSIGN", 1, 1) + { + } + + CommandReturn Execute(User *u, std::vector ¶ms) + { + char *chan = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + BotInfo *bi; + ChannelInfo *ci; + + if (readonly) + { + notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); + return MOD_CONT; + } + + if (!(bi = findbot(nick))) + { + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + return MOD_CONT; + } + + if (bi->flags & BI_PRIVATE && !is_oper(u)) + { + notice_lang(s_BotServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (!(ci = cs_findchan(chan))) + { + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; + } + + if (ci->flags & CI_VERBOTEN) + { + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + return MOD_CONT; + } + + if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) + { + notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); + return MOD_CONT; + } + + if ((ci->botflags & BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) + { + notice_lang(s_BotServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + bi->Assign(u, ci); + notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); + return MOD_CONT; + } + + bool OnHelp(User *u, const std::string &subcommand) + { + notice_lang(s_BotServ, u, BOT_HELP_ASSIGN); + return true; + } + + void OnSyntaxError(User *u) + { + syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); + } +}; + class BSAssign : public Module { public: BSAssign(const std::string &modname, const std::string &creator) : Module(modname, creator) { - Command *c; - this->SetAuthor("Anope"); this->SetVersion("$Id$"); this->SetType(CORE); - c = createCommand("ASSIGN", do_assign, NULL, BOT_HELP_ASSIGN, -1, -1, -1, -1); - this->AddCommand(BOTSERV, c, MOD_UNIQUE); + this->AddCommand(BOTSERV, new CommandBSAssign, MOD_UNIQUE); this->SetBotHelp(myBotServHelp); } @@ -44,40 +113,4 @@ void myBotServHelp(User * u) notice_lang(s_BotServ, u, BOT_HELP_CMD_ASSIGN); } -/** - * The /bs assign command. - * @param u The user who issued the command - * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. - **/ -int do_assign(User * u) -{ - char *chan = strtok(NULL, " "); - char *nick = strtok(NULL, " "); - BotInfo *bi; - ChannelInfo *ci; - - if (readonly) - notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); - else if (!chan || !nick) - syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); - else if (!(bi = findbot(nick))) - notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); - else if (bi->flags & BI_PRIVATE && !is_oper(u)) - notice_lang(s_BotServ, u, PERMISSION_DENIED); - else if (!(ci = cs_findchan(chan))) - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); - else if (ci->flags & CI_VERBOTEN) - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) - notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); - else if ((ci->botflags & BS_NOBOT) - || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) - notice_lang(s_BotServ, u, PERMISSION_DENIED); - else { - bi->Assign(u, ci); - notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); - } - return MOD_CONT; -} - MODULE_INIT("bs_assign", BSAssign) diff --git a/src/core/bs_badwords.c b/src/core/bs_badwords.c index 8a37e9816..41050dc93 100644 --- a/src/core/bs_badwords.c +++ b/src/core/bs_badwords.c @@ -15,80 +15,65 @@ #include "module.h" -int do_badwords(User * u); void myBotServHelp(User * u); int badwords_del_callback(User * u, int num, va_list args); int badwords_list(User * u, int index, ChannelInfo * ci, int *sent_header); int badwords_list_callback(User * u, int num, va_list args); -class BSBadwords : public Module +class CommandBSBadwords : public Command { - public: - BSBadwords(const std::string &modname, const std::string &creator) : Module(modname, creator) + private: + CommandReturn DoList(User *u, ChannelInfo *ci, const char *word) { - Command *c; - - this->SetAuthor("Anope"); - this->SetVersion("$Id$"); - this->SetType(CORE); + int sent_header = 0; + int i = 0; - c = createCommand("BADWORDS", do_badwords, NULL, BOT_HELP_BADWORDS, -1, -1, -1, -1); - this->AddCommand(BOTSERV, c, MOD_UNIQUE); + if (ci->bwcount == 0) + { + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_EMPTY, ci->name); + return MOD_CONT; + } + if (word && strspn(word, "1234567890,-") == strlen(word)) + { + process_numlist(word, NULL, badwords_list_callback, u, ci, &sent_header); + } + else + { + for (i = 0; i < ci->bwcount; i++) + { + if (!(ci->badwords[i].in_use)) + continue; + if (word && ci->badwords[i].word + && !match_wild_nocase(word, ci->badwords[i].word)) + continue; + badwords_list(u, i, ci, &sent_header); + } + } + if (!sent_header) + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name); - this->SetBotHelp(myBotServHelp); + return MOD_CONT; } -}; - - -/** - * Add the help response to Anopes /bs help output. - * @param u The user who is requesting help - **/ -void myBotServHelp(User * u) -{ - notice_lang(s_BotServ, u, BOT_HELP_CMD_BADWORDS); -} - -/** - * The /bs badwords command. - * @param u The user who issued the command - * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. - **/ -int do_badwords(User * u) -{ - char *chan = strtok(NULL, " "); - char *cmd = strtok(NULL, " "); - char *word = strtok(NULL, ""); - ChannelInfo *ci; - BadWord *bw; - - unsigned i; - int need_args = (cmd - && (!stricmp(cmd, "LIST") || !stricmp(cmd, "CLEAR"))); - - if (!cmd || (need_args ? 0 : !word)) { - syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); - } else if (!(ci = cs_findchan(chan))) { - notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); - } else if (ci->flags & CI_VERBOTEN) { - notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); - } else if (!check_access(u, ci, CA_BADWORDS) - && (!need_args || !is_services_admin(u))) { - notice_lang(s_BotServ, u, ACCESS_DENIED); - } else if (stricmp(cmd, "ADD") == 0) { - + + CommandReturn DoAdd(User *u, ChannelInfo *ci, const char *word) + { char *opt, *pos; int type = BW_ANY; + unsigned i = 0; + BadWord *bw; - if (readonly) { + if (readonly) + { notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); return MOD_CONT; } pos = strrchr(word, ' '); - if (pos) { + if (pos) + { opt = pos + 1; - if (*opt) { + if (*opt) + { if (!stricmp(opt, "SINGLE")) type = BW_SINGLE; else if (!stricmp(opt, "START")) @@ -100,26 +85,33 @@ int do_badwords(User * u) } } - for (bw = ci->badwords, i = 0; i < ci->bwcount; bw++, i++) { + for (bw = ci->badwords, i = 0; i < ci->bwcount; bw++, i++) + { if (bw->word && ((BSCaseSensitive && (!strcmp(bw->word, word))) || (!BSCaseSensitive - && (!stricmp(bw->word, word))))) { + && (!stricmp(bw->word, word))))) + { notice_lang(s_BotServ, u, BOT_BADWORDS_ALREADY_EXISTS, bw->word, ci->name); return MOD_CONT; } } - for (i = 0; i < ci->bwcount; i++) { + for (i = 0; i < ci->bwcount; i++) + { if (!ci->badwords[i].in_use) break; } - if (i == ci->bwcount) { - if (i < BSBadWordsMax) { + if (i == ci->bwcount) + { + if (i < BSBadWordsMax) + { ci->bwcount++; ci->badwords = static_cast(srealloc(ci->badwords, sizeof(BadWord) * ci->bwcount)); - } else { + } + else + { notice_lang(s_BotServ, u, BOT_BADWORDS_REACHED_LIMIT, BSBadWordsMax); return MOD_CONT; @@ -131,50 +123,57 @@ int do_badwords(User * u) bw->type = type; notice_lang(s_BotServ, u, BOT_BADWORDS_ADDED, bw->word, ci->name); + return MOD_CONT; + } - } else if (stricmp(cmd, "DEL") == 0) { + CommandReturn DoDelete(User *u, ChannelInfo *ci, const char *word) + { int deleted = 0, a, b; - - if (readonly) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); - return MOD_CONT; - } + int i; + BadWord *bw; /* Special case: is it a number/list? Only do search if it isn't. */ - if (isdigit(*word) && strspn(word, "1234567890,-") == strlen(word)) { + if (isdigit(*word) && strspn(word, "1234567890,-") == strlen(word)) + { int count, last = -1; - deleted = - process_numlist(word, &count, badwords_del_callback, u, ci, - &last); - if (!deleted) { - if (count == 1) { - notice_lang(s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, - last, ci->name); - } else { - notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, - ci->name); + deleted = process_numlist(word, &count, badwords_del_callback, u, ci, &last); + if (!deleted) + { + if (count == 1) + { + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, last, ci->name); + } + else + { + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name); } - } else if (deleted == 1) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_ONE, - ci->name); - } else { - notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, - deleted, ci->name); } - } else { - for (i = 0; i < ci->bwcount; i++) { - if (ci->badwords[i].in_use - && !stricmp(ci->badwords[i].word, word)) + else if (deleted == 1) + { + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_ONE, ci->name); + } + else + { + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, deleted, ci->name); + } + } + else + { + + for (i = 0; i < ci->bwcount; i++) + { + if (!ci->badwords[i].in_use) break; } - if (i == ci->bwcount) { - notice_lang(s_BotServ, u, BOT_BADWORDS_NOT_FOUND, word, - chan); + + if (i == ci->bwcount) + { + notice_lang(s_BotServ, u, BOT_BADWORDS_NOT_FOUND, word, ci->name); return MOD_CONT; } + bw = &ci->badwords[i]; - notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED, bw->word, - ci->name); + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED, bw->word, ci->name); if (bw->word) delete [] bw->word; bw->word = NULL; @@ -205,8 +204,8 @@ int do_badwords(User * u) } /* After reordering only the entries at the end could still be empty. * We ll free the places no longer in use... - Viper */ - for (int j = ci->bwcount - 1; j >= 0; j--) { - if (ci->badwords[j].in_use) + for (i = ci->bwcount - 1; i >= 0; i--) { + if (ci->badwords[i].in_use) break; ci->bwcount--; } @@ -214,50 +213,124 @@ int do_badwords(User * u) static_cast(srealloc(ci->badwords,sizeof(BadWord) * ci->bwcount)); } - } else if (stricmp(cmd, "LIST") == 0) { - int sent_header = 0; + return MOD_CONT; + } + + CommandReturn DoClear(User *u, ChannelInfo *ci, const char *word) + { + int i; + for (i = 0; i < ci->bwcount; i++) + if (ci->badwords[i].word) + delete [] ci->badwords[i].word; - if (ci->bwcount == 0) { - notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_EMPTY, chan); + free(ci->badwords); + ci->badwords = NULL; + ci->bwcount = 0; + + notice_lang(s_BotServ, u, BOT_BADWORDS_CLEAR); + return MOD_CONT; + } + public: + CommandBSBadwords() : Command("BADWORDS", 2, 3) + { + } + + CommandReturn Execute(User *u, std::vector ¶ms) + { + const char *chan = params[0].c_str(); + const char *cmd = params[1].c_str(); + const char *word = params[2].c_str(); + ChannelInfo *ci; + int need_args = (cmd + && (!stricmp(cmd, "LIST") || !stricmp(cmd, "CLEAR"))); + + if (!cmd || (need_args ? 0 : !word)) + { + this->OnSyntaxError(u); return MOD_CONT; } - if (word && strspn(word, "1234567890,-") == strlen(word)) { - process_numlist(word, NULL, badwords_list_callback, u, ci, - &sent_header); - } else { - for (i = 0; i < ci->bwcount; i++) { - if (!(ci->badwords[i].in_use)) - continue; - if (word && ci->badwords[i].word - && !match_wild_nocase(word, ci->badwords[i].word)) - continue; - badwords_list(u, i, ci, &sent_header); - } + + if (!(ci = cs_findchan(chan))) + { + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; } - if (!sent_header) - notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, chan); - } else if (stricmp(cmd, "CLEAR") == 0) { + if (ci->flags & CI_VERBOTEN) + { + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + return MOD_CONT; + } - if (readonly) { - notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + if (!check_access(u, ci, CA_BADWORDS) && (!need_args || !is_services_admin(u))) + { + notice_lang(s_BotServ, u, ACCESS_DENIED); return MOD_CONT; } - for (i = 0; i < ci->bwcount; i++) - if (ci->badwords[i].word) - delete [] ci->badwords[i].word; + if (readonly) + { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } - free(ci->badwords); - ci->badwords = NULL; - ci->bwcount = 0; + if (stricmp(cmd, "ADD") == 0) + { + return this->DoAdd(u, ci, word); + } + else if (stricmp(cmd, "DEL") == 0) + { + return this->DoDelete(u, ci, word); + } + else if (stricmp(cmd, "LIST") == 0) + { + return this->DoList(u, ci, word); + } + else if (stricmp(cmd, "CLEAR") == 0) + { + return this->DoClear(u, ci, word); + } + else + { + this->OnSyntaxError(u); + } + return MOD_CONT; + } - notice_lang(s_BotServ, u, BOT_BADWORDS_CLEAR); + bool OnHelp(User *u, const std::string &subcommand) + { + notice_lang(s_BotServ, u, BOT_HELP_BADWORDS); + return true; + } - } else { + void OnSyntaxError(User *u) + { syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); } - return MOD_CONT; +}; + +class BSBadwords : public Module +{ + public: + BSBadwords(const std::string &modname, const std::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetVersion("$Id$"); + this->SetType(COR