X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fopserv.c;h=ccede743d5fb9f1ff7b6677cfd83333ee3a48ba4;hb=91aeb5684130fc8d5322af1eca7be2e2f3d1e928;hp=f9af6bb80ad8e61098e66f4fe1ddd0460217314d;hpb=f09747bbc14a8f086ea137f4d71c77a84465bf27;p=srvx.git diff --git a/src/opserv.c b/src/opserv.c index f9af6bb..ccede74 100644 --- a/src/opserv.c +++ b/src/opserv.c @@ -22,6 +22,7 @@ #include "gline.h" #include "global.h" #include "nickserv.h" +#include "chanserv.h" #include "modcmd.h" #include "opserv.h" #include "timeq.h" @@ -72,10 +73,18 @@ #define KEY_EXPIRES "expires" #define KEY_STAFF_AUTH_CHANNEL "staff_auth_channel" #define KEY_STAFF_AUTH_CHANNEL_MODES "staff_auth_channel_modes" +#define KEY_STAFF_AUTH_FORCE_OPS "staff_auth_force_opers" #define KEY_CLONE_GLINE_DURATION "clone_gline_duration" #define KEY_BLOCK_GLINE_DURATION "block_gline_duration" #define KEY_ISSUER "issuer" #define KEY_ISSUED "issued" +#define KEY_DEVNULL_CLASSES "classes" +#define KEY_DEVNULL_LASTID "devnull_id" +#define KEY_DEVNULL_ID "id" +#define KEY_DEVNULL_NAME "class" +#define KEY_DEVNULL_MODE "modes" +#define KEY_DEVNULL_MAXCHAN "chanlimit" +#define KEY_DEVNULL_MAXSENDQ "sendq" #define IDENT_FORMAT "%s [%s@%s/%s]" #define IDENT_DATA(user) user->nick, user->ident, user->hostname, irc_ntoa(&user->ip) @@ -201,7 +210,9 @@ static const struct message_entry msgtab[] = { { "OSMSG_GLINE_SEARCH_RESULTS", "The following glines were found:" }, { "OSMSG_LOG_SEARCH_RESULTS", "The following log entries were found:" }, { "OSMSG_GSYNC_RUNNING", "Synchronizing glines from %s." }, - { "OSMSG_GTRACE_FORMAT", "%s (issued %s by %s, lastmod %s, expires %s): %s" }, + { "OSMSG_GTRACE_FORMAT", "%1$s (issued %2$s ago by %3$s, lastmod %4$s ago, expires %5$s, lifetime %7$s): %6$s" }, + { "OSMSG_GTRACE_FOREVER", "%1$s (issued %2$s ago by %3$s, lastmod %4$s ago, never expires, lifetime %7$s): %6$s" }, + { "OSMSG_GTRACE_EXPIRED", "%1$s (issued %2$s ago by %3$s, lastmod %4$s ago, expired %5$s ago, lifetime %7$s): %6$s" }, { "OSMSG_GAG_APPLIED", "Gagged $b%s$b, affecting %d users." }, { "OSMSG_GAG_ADDED", "Gagged $b%s$b." }, { "OSMSG_REDUNDANT_GAG", "Gag $b%s$b is redundant." }, @@ -255,6 +266,45 @@ static const struct message_entry msgtab[] = { { "OSMSG_CSEARCH_CHANNEL_INFO", "%s [%d users] %s %s" }, { "OSMSG_TRACE_MAX_CHANNELS", "You may not use the 'channel' criterion more than %d times." }, { "OSMSG_FORCEKICK_LOCAL", "You cannot kick $b%s$b forcefully." }, + { "OSMSG_SVSNONICK", "$b%s$b is not a valid nick." }, + { "OSMSG_SVSNICKUSED", "$b%s$b is an already used nickname." }, + { "OSMSG_SVSNICK", "You have renamed $b%s$b to $b%s$b." }, + { "OSMSG_SVSJOIN", "$b%s$b joined $b%s$b." }, + { "OSMSG_SVSPART", "$b%s$b parted $b%s$b." }, + { "OSMSG_SVSKILL", "$b%s$b killed: $b%s$b." }, + { "OSMSG_SVSMODE", "You have set mode $b%s$b for $b%s$b." }, + { "OSMSG_SIMUL", "You have simuled $b%s$b: %s" }, + { "OSMSG_DEVNULL_USER" , "[%s] %s %s" }, + { "OSMSG_DEVNULL_MATCH" , "%d Users found." }, + { "OSMSG_DEVNULL_CLASS" , "%s is not a valid DevNull class." }, + { "OSMSG_DEVNULL_ADDED", "Added %s to DevNull list (class: %s)" }, + { "OSMSG_DEVNULL_DELETED", "Deleted %s from DevNull list (class: %s)" }, + { "OSMSG_DEVNULL_NOTADDED", "User %s is not listed on DevNull list." }, + { "OSMSG_DEVNULL_ACTION", "Unrecognized trace action $b%s$b" }, + { "OSMSG_DEVNULL_FOUND", "DevNull Class %s is already existing." }, + { "OSMSG_DEVNULL_NOTFOUND", "can't find DevNull class %s." }, + { "OSMSG_DEVNULL_ADDED", "DevNull Class %s added." }, + { "OSMSG_DEVNULL_REMOVED", "DevNull Class %s removed." }, + { "OSMSG_DEVNULL_SET", "Settings for DevNull Class %s" }, + { "OSMSG_DEVNULL_SET_A", "ChanLimit: %s" }, + { "OSMSG_DEVNULL_SET_A_i", "ChanLimit: %i" }, + { "OSMSG_DEVNULL_SET_B", "UnlimitTarget: %s" }, + { "OSMSG_DEVNULL_SET_C", "Flood: %s" }, + { "OSMSG_DEVNULL_SET_E", "ChanHide: %s" }, + { "OSMSG_DEVNULL_SET_F", "IdleHide: %s" }, + { "OSMSG_DEVNULL_SET_G", "ChServMode: %s" }, + { "OSMSG_DEVNULL_SET_H", "XtraOpMode: %s" }, + { "OSMSG_DEVNULL_SET_I", "NetServMode: %s" }, + { "OSMSG_DEVNULL_SET_J", "SeeIdle: %s" }, + { "OSMSG_DEVNULL_SET_K", "ForceIdleHide: %s" }, + { "OSMSG_DEVNULL_SET_L", "OverrideCC: %s" }, + { "OSMSG_DEVNULL_SET_M", "OverrideNoAmsg: %s" }, + { "OSMSG_DEVNULL_SET_N", "MaxSendQ: %s" }, + { "OSMSG_DEVNULL_SET_N_i", "MaxSendQ: %i" }, + { "OSMSG_DEVNULL_SET_OPME", "OpMe: %s" }, + { "OSMSG_DEVNULL_SET_DONE", "Done." }, + { "OSMSG_DEVNULL_RENAMED", "Devnull class %s renamed to %s" }, + { "OSMSG_DEVNULL_SET_INVALID", "Invalid Option for setting %s" }, { NULL, NULL } }; @@ -269,6 +319,7 @@ static dict_t opserv_reserved_nick_dict; /* data is struct userNode* */ static struct string_list *opserv_bad_words; static dict_t opserv_exempt_channels; /* data is not used */ static dict_t opserv_trusted_hosts; /* data is struct trusted_host* */ +static dict_t opserv_devnull_classes; /* data is struct devnull_class* */ static dict_t opserv_hostinfo_dict; /* data is struct opserv_hostinfo* */ static dict_t opserv_user_alerts; /* data is struct opserv_user_alert* */ static dict_t opserv_nick_based_alerts; /* data is struct opserv_user_alert* */ @@ -277,12 +328,18 @@ static dict_t opserv_account_alerts; /* data is struct opserv_user_alert* */ static struct module *opserv_module; static struct log_type *OS_LOG; static unsigned int new_user_flood; +const char *devnull_modes = DEVNULL_MODES; static char *level_strings[1001]; +static char devnull_inverse_modes[256]; +unsigned int devnull_last_id = 1; + +void *devnull_check_priv_func = NULL; static struct { struct chanNode *debug_channel; struct chanNode *alert_channel; struct chanNode *staff_auth_channel; + int staff_auth_force; struct policer_params *join_policer_params; struct policer new_user_policer; unsigned long untrusted_max; @@ -383,13 +440,13 @@ opserv_free_user_alert(void *data) } #if defined(GCC_VARMACROS) -# define opserv_debug(ARGS...) do { if (opserv_conf.debug_channel) send_channel_notice(opserv_conf.debug_channel, opserv, ARGS); } while (0) -# define opserv_alert(ARGS...) do { if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel, opserv, ARGS); } while (0) -# define opserv_custom_alert(CHAN, ARGS...) do { if (CHAN) send_target_message(4, (CHAN), opserv, ARGS); else if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel, opserv, ARGS); } while (0) +# define opserv_debug(ARGS...) do { if (opserv_conf.debug_channel) send_channel_message(opserv_conf.debug_channel, opserv, ARGS); } while (0) +# define opserv_alert(ARGS...) do { if (opserv_conf.alert_channel) send_channel_message(opserv_conf.alert_channel, opserv, ARGS); } while (0) +# define opserv_custom_alert(CHAN, ARGS...) do { if (CHAN) send_target_message(5, (CHAN), opserv, ARGS); else if (opserv_conf.alert_channel) send_channel_message(opserv_conf.alert_channel, opserv, ARGS); } while (0) #elif defined(C99_VARMACROS) -# define opserv_debug(...) do { if (opserv_conf.debug_channel) send_channel_notice(opserv_conf.debug_channel, opserv, __VA_ARGS__); } while (0) -# define opserv_alert(...) do { if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel, opserv, __VA_ARGS__); } while (0) -# define opserv_custom_alert(chan, ...) do { if (chan) send_target_message(4, chan, opserv, __VA_ARGS__); else if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel, opserv, __VA_ARGS__); } while (0) +# define opserv_debug(...) do { if (opserv_conf.debug_channel) send_channel_message(opserv_conf.debug_channel, opserv, __VA_ARGS__); } while (0) +# define opserv_alert(...) do { if (opserv_conf.alert_channel) send_channel_message(opserv_conf.alert_channel, opserv, __VA_ARGS__); } while (0) +# define opserv_custom_alert(chan, ...) do { if (chan) send_target_message(5, chan, opserv, __VA_ARGS__); else if (opserv_conf.alert_channel) send_channel_message(opserv_conf.alert_channel, opserv, __VA_ARGS__); } while (0) #endif /* A lot of these commands are very similar to what ChanServ can do, @@ -577,7 +634,7 @@ static MODCMD_FUNC(cmd_clearmodes) return 0; } mod_chanmode_init(&change); - change.modes_clear = channel->modes; + change.modes_clear = channel->modes & ~MODE_REGISTERED; modcmd_chanmode_announce(&change); reply("OSMSG_CLEARMODES_DONE", channel->name); return 1; @@ -789,7 +846,7 @@ opserv_block(struct userNode *target, char *src_handle, char *reason, unsigned l "G-line requested by %s.", src_handle); if (!duration) duration = opserv_conf.block_gline_duration; - return gline_add(src_handle, mask, duration, reason, now, now, 1); + return gline_add(src_handle, mask, duration, reason, now, now, 0, 1); } static MODCMD_FUNC(cmd_block) @@ -863,7 +920,7 @@ static MODCMD_FUNC(cmd_gline) reply("MSG_INVALID_DURATION", argv[2]); return 0; } - gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, now, 1); + gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, now, 0, 1); reply("OSMSG_GLINE_ISSUED", gline->target); return 1; } @@ -1022,6 +1079,10 @@ static MODCMD_FUNC(cmd_kick) reply("OSMSG_NOT_ON_CHANNEL", target->nick, channel->name); return 0; } + if (IsService(target)) { + reply("MSG_SERVICE_IMMUNE", target->nick); + return 0; + } KickChannelUser(target, channel, cmd->parent->bot, reason); return 1; } @@ -1186,7 +1247,7 @@ static MODCMD_FUNC(cmd_part) static MODCMD_FUNC(cmd_mode) { - if (!modcmd_chanmode(argv+1, argc-1, MCP_ALLOW_OVB|MCP_KEY_FREE|MC_ANNOUNCE)) { + if (!modcmd_chanmode(argv+1, argc-1, MCP_ALLOW_OVB|MCP_KEY_FREE|MC_ANNOUNCE|MCP_OPERMODE)) { reply("MSG_INVALID_MODES", unsplit_string(argv+1, argc-1, NULL)); return 0; } @@ -1285,7 +1346,7 @@ static MODCMD_FUNC(cmd_whois) reply("OSMSG_WHOIS_ACCOUNT", (target->handle_info ? target->handle_info->handle : "Not authenticated")); intervalString(buffer, now - target->timestamp, user->handle_info); reply("OSMSG_WHOIS_NICK_AGE", buffer); - if (target->channels.used <= MAX_CHANNELS_WHOIS) + if (target->channels.used <= MAX_CHANNELS_WHOIS || HANDLE_FLAGGED(user->handle_info, BOT)) opserv_ison(user, target, "OSMSG_WHOIS_CHANNELS"); else reply("OSMSG_WHOIS_HIDECHANS"); @@ -1878,7 +1939,7 @@ opserv_new_user_check(struct userNode *user) } else if (ohi->clients.used > limit) { char target[IRC_NTOP_MAX_SIZE + 3] = { '*', '@', '\0' }; strcpy(target + 2, addr); - gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "AUTO Excessive connections from a single host.", now, now, 1); + gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "AUTO Excessive connections from a single host.", now, now, 0, 1); } } } @@ -2757,6 +2818,65 @@ trusted_host_read(const char *host, void *data, UNUSED_ARG(void *extra)) return 0; } +static void +opserv_add_devnull_class(const char *name, unsigned int id, unsigned long modes, unsigned long maxchan, unsigned long maxsendq) +{ + struct devnull_class *th; + th = calloc(1, sizeof(*th)); + if (!th) + return; + if(id) + th->id = id; + else + th->id = (++devnull_last_id); + th->name = strdup(name); + th->modes = modes; + th->maxchan = maxchan; + th->maxsendq = maxsendq; + dict_insert(opserv_devnull_classes, th->name, th); +} + +static void +free_devnull_class(void *data) +{ + struct devnull_class *th = data; + free(th->name); + free(th); +} + +static int +devnull_class_read(const char *name, void *data, UNUSED_ARG(void *extra)) +{ + struct record_data *rd = data; + const char *str; + unsigned long modes, maxchan, maxsendq; + unsigned int id, ii; + + if (rd->type == RECDB_OBJECT) { + dict_t obj = GET_RECORD_OBJECT(rd); + /* new style structure */ + str = database_get_data(obj, KEY_DEVNULL_ID, RECDB_QSTRING); + if(str) + id = atoi(str); + else + id = 0; + str = database_get_data(obj, KEY_DEVNULL_MODE, RECDB_QSTRING); + modes = 0; + if (str) { + for (ii=0; str[ii]; ii++) + modes |= 1 << (devnull_inverse_modes[(unsigned char)str[ii]] - 1); + } + str = database_get_data(obj, KEY_DEVNULL_MAXCHAN, RECDB_QSTRING); + maxchan = str ? ParseInterval(str) : 0; + str = database_get_data(obj, KEY_DEVNULL_MAXSENDQ, RECDB_QSTRING); + maxsendq = str ? ParseInterval(str) : 0; + } else + return 0; + + opserv_add_devnull_class(name, id, modes, maxchan, maxsendq); + return 0; +} + static int opserv_saxdb_read(struct dict *conf_db) { @@ -2764,6 +2884,7 @@ opserv_saxdb_read(struct dict *conf_db) struct record_data *rd; dict_iterator_t it; unsigned int nn; + char *str; if ((object = database_get_data(conf_db, KEY_RESERVES, RECDB_OBJECT))) dict_foreach(object, add_reserved, opserv_reserved_nick_dict); @@ -2793,14 +2914,17 @@ opserv_saxdb_read(struct dict *conf_db) dict_insert(opserv_exempt_channels, strdup(rd->d.slist->list[nn]), NULL); } if ((object = database_get_data(conf_db, KEY_MAX_CLIENTS, RECDB_OBJECT))) { - char *str; if ((str = database_get_data(object, KEY_MAX, RECDB_QSTRING))) max_clients = atoi(str); if ((str = database_get_data(object, KEY_TIME, RECDB_QSTRING))) max_clients_time = atoi(str); } + if ((str = database_get_data(object, KEY_DEVNULL_LASTID, RECDB_QSTRING))) + devnull_last_id = atoi(str); if ((object = database_get_data(conf_db, KEY_TRUSTED_HOSTS, RECDB_OBJECT))) dict_foreach(object, trusted_host_read, opserv_trusted_hosts); + if ((object = database_get_data(conf_db, KEY_DEVNULL_CLASSES, RECDB_OBJECT))) + dict_foreach(object, devnull_class_read, opserv_devnull_classes); if ((object = database_get_data(conf_db, KEY_GAGS, RECDB_OBJECT))) dict_foreach(object, add_gag_helper, NULL); if ((object = database_get_data(conf_db, KEY_ALERTS, RECDB_OBJECT))) @@ -2858,6 +2982,29 @@ opserv_saxdb_write(struct saxdb_context *ctx) } saxdb_end_record(ctx); } + /* devnull_classes */ + if (dict_size(opserv_devnull_classes)) { + saxdb_start_record(ctx, KEY_DEVNULL_CLASSES, 1); + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + struct devnull_class *th = iter_data(it); + saxdb_start_record(ctx, th->name, 0); + saxdb_write_int(ctx, KEY_DEVNULL_ID, th->id); + if (th->modes) { + int ii, flen; + char flags[50]; + for (ii=flen=0; devnull_modes[ii]; ++ii) + if (th->modes & (1 << ii)) + flags[flen++] = devnull_modes[ii]; + flags[flen] = 0; + saxdb_write_string(ctx, KEY_DEVNULL_MODE, flags); + } + if (th->maxchan) saxdb_write_int(ctx, KEY_DEVNULL_MAXCHAN, th->maxchan); + if (th->maxsendq) saxdb_write_int(ctx, KEY_DEVNULL_MAXSENDQ, th->maxsendq); + saxdb_end_record(ctx); + } + saxdb_end_record(ctx); + } + saxdb_write_int(ctx, KEY_DEVNULL_LASTID, devnull_last_id); /* gags */ if (gagList) { struct gag_entry *gag; @@ -3797,17 +3944,23 @@ gtrace_print_func(struct gline *gline, void *extra) char issued[INTERVALLEN]; char lastmod[INTERVALLEN]; char expires[INTERVALLEN]; + char lifetime[INTERVALLEN]; intervalString(issued, now - gline->issued, xtra->user->handle_info); if (gline->lastmod) intervalString(lastmod, now - gline->lastmod, xtra->user->handle_info); else strcpy(lastmod, ""); - if (gline->expires) + intervalString(lifetime, gline->lifetime - now, xtra->user->handle_info); + if (!gline->expires) { + send_message(xtra->user, opserv, "OSMSG_GTRACE_FOREVER", gline->target, issued, gline->issuer, lastmod, NULL, gline->reason, lifetime); + } else if (gline->expires < now) { + intervalString(expires, now - gline->expires, xtra->user->handle_info); + send_message(xtra->user, opserv, "OSMSG_GTRACE_EXPIRED", gline->target, issued, gline->issuer, lastmod, expires, gline->reason, lifetime); + } else { /* must be in the future */ intervalString(expires, gline->expires - now, xtra->user->handle_info); - else - strcpy(expires, "never"); - send_message(xtra->user, opserv, "OSMSG_GTRACE_FORMAT", gline->target, issued, gline->issuer, lastmod, expires, gline->reason); + send_message(xtra->user, opserv, "OSMSG_GTRACE_FORMAT", gline->target, issued, gline->issuer, lastmod, expires, gline->reason, lifetime); + } } static MODCMD_FUNC(cmd_stats_glines) { @@ -3959,6 +4112,8 @@ opserv_staff_alert(struct userNode *user, UNUSED_ARG(struct handle_info *old_han || user->uplink->burst || !user->handle_info) return; + else if (IsBot(user)) + return; else if (user->handle_info->opserv_level) type = "OPER"; else if (IsNetworkHelper(user)) @@ -3969,9 +4124,9 @@ opserv_staff_alert(struct userNode *user, UNUSED_ARG(struct handle_info *old_han return; if (irc_in_addr_is_valid(user->ip)) - send_channel_notice(opserv_conf.staff_auth_channel, opserv, IDENT_FORMAT" authed to %s account %s", IDENT_DATA(user), type, user->handle_info->handle); + send_channel_message(opserv_conf.staff_auth_channel, opserv, IDENT_FORMAT" authed to %s account %s", IDENT_DATA(user), type, user->handle_info->handle); else - send_channel_notice(opserv_conf.staff_auth_channel, opserv, "%s [%s@%s] authed to %s account %s", user->nick, user->ident, user->hostname, type, user->handle_info->handle); + send_channel_message(opserv_conf.staff_auth_channel, opserv, "%s [%s@%s] authed to %s account %s", user->nick, user->ident, user->hostname, type, user->handle_info->handle); } static void @@ -4123,6 +4278,650 @@ static MODCMD_FUNC(cmd_delalert) return 1; } +static MODCMD_FUNC(cmd_listdevnull) +{ + struct helpfile_table tbl; + unsigned int count = 0, ii = 0; + char *on,*off,*half; + on = "X"; + off = "-"; + half = "1/2"; + + dict_iterator_t it; + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + count++; + } + tbl.length = count+1; + tbl.width = 15; + tbl.flags = 0; + tbl.flags = TABLE_NO_FREE; + tbl.contents = malloc(tbl.length * sizeof(tbl.contents[0])); + tbl.contents[0] = malloc(tbl.width * sizeof(tbl.contents[0][0])); + tbl.contents[0][0] = "Name"; + tbl.contents[0][1] = "MC"; + tbl.contents[0][2] = "UT"; + tbl.contents[0][3] = "FL"; + tbl.contents[0][4] = "CH"; + tbl.contents[0][5] = "IH"; + tbl.contents[0][6] = "SI"; + tbl.contents[0][7] = "IH²"; + tbl.contents[0][8] = "oC"; + tbl.contents[0][9] = "oM"; + tbl.contents[0][10] = "+k"; + tbl.contents[0][11] = "+S"; + tbl.contents[0][12] = "+X"; + tbl.contents[0][13] = "MaxQ"; + tbl.contents[0][14] = "OpMe"; + if(!count) + { + table_send(cmd->parent->bot, user->nick, 0, NULL, tbl); + reply("MSG_NONE"); + free(tbl.contents[0]); + free(tbl.contents); + return 0; + } + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + struct devnull_class *th = iter_data(it); + tbl.contents[++ii] = malloc(tbl.width * sizeof(tbl.contents[0][0])); + tbl.contents[ii][0] = th->name; + if(DEVNULL_HAS_PRIV(th, CHANLIMIT)) { + tbl.contents[ii][1] = strtab(th->maxchan); + } else { + tbl.contents[ii][1] = off; + } + if(DEVNULL_HAS_PRIV(th, UNLIMITTARGET)) { + tbl.contents[ii][2] = on; + } else { + tbl.contents[ii][2] = off; + } + if(DEVNULL_HAS_PRIV(th, NOFLOOD)) { + tbl.contents[ii][3] = on; + } else if(DEVNULL_HAS_PRIV(th, HALFFLOOD)) { + tbl.contents[ii][3] = half; + } else { + tbl.contents[ii][3] = off; + } + if(DEVNULL_HAS_PRIV(th, CHANHIDE)) { + tbl.contents[ii][4] = on; + } else { + tbl.contents[ii][4] = off; + } + if(DEVNULL_HAS_PRIV(th, IDLEHIDE)) { + tbl.contents[ii][5] = on; + } else { + tbl.contents[ii][5] = off; + } + if(DEVNULL_HAS_PRIV(th, CHSERVMODE)) { + tbl.contents[ii][6] = on; + } else { + tbl.contents[ii][6] = off; + } + if(DEVNULL_HAS_PRIV(th, XTRAOPMODE)) { + tbl.contents[ii][7] = on; + } else { + tbl.contents[ii][7] = off; + } + if(DEVNULL_HAS_PRIV(th, NETSERVMODE)) { + tbl.contents[ii][8] = on; + } else { + tbl.contents[ii][8] = off; + } + if(DEVNULL_HAS_PRIV(th, SEEIDLE)) { + tbl.contents[ii][9] = on; + } else { + tbl.contents[ii][9] = off; + } + if(DEVNULL_HAS_PRIV(th, FORCEIDLEHIDE)) { + tbl.contents[ii][10] = on; + } else { + tbl.contents[ii][10] = off; + } + if(DEVNULL_HAS_PRIV(th, OVERRIDECC)) { + tbl.contents[ii][11] = on; + } else { + tbl.contents[ii][11] = off; + } + if(DEVNULL_HAS_PRIV(th, OVERRIDENOAMSG)) { + tbl.contents[ii][12] = on; + } else { + tbl.contents[ii][12] = off; + } + if(DEVNULL_HAS_PRIV(th, MAXSENDQ)) { + tbl.contents[ii][13] = on; + } else { + tbl.contents[ii][13] = off; + } + if(DEVNULL_HAS_PRIV(th, OPME)) { + tbl.contents[ii][14] = on; + } else { + tbl.contents[ii][14] = off; + } + } + table_send(cmd->parent->bot, user->nick, 0, NULL, tbl); + for(ii = 1; ii < tbl.length; ++ii) + { + free(tbl.contents[ii]); + } + free(tbl.contents[0]); + free(tbl.contents); + send_message_type(4, user, opserv,"-"); + /* + tbl.contents[0][1] = "MC"; + tbl.contents[0][2] = "UT"; + tbl.contents[0][3] = "FL"; + tbl.contents[0][4] = "CH"; + tbl.contents[0][5] = "IH"; + tbl.contents[0][6] = "SI"; + tbl.contents[0][7] = "IH²"; + tbl.contents[0][8] = "oC"; + tbl.contents[0][9] = "oM"; + tbl.contents[0][10] = "+k"; + tbl.contents[0][11] = "+S"; + tbl.contents[0][12] = "+X"; + tbl.contents[0][13] = "MaxQ"; + */ + send_message_type(4, user, opserv,"MC = MaxChan"); + send_message_type(4, user, opserv,"UT = UnlimitTargets"); + send_message_type(4, user, opserv,"FL = Flood (1 = 1/2 flood, X = unlimited)"); + send_message_type(4, user, opserv,"CH = Channel Hide (mode +n)"); + send_message_type(4, user, opserv,"IH = Idle Hide (mode +I)"); + send_message_type(4, user, opserv,"SI = See Idle"); + send_message_type(4, user, opserv,"IH² = Idle Hide (override SI)"); + send_message_type(4, user, opserv,"oC = Color override (mode +c)"); + send_message_type(4, user, opserv,"oM = AMsg override"); + send_message_type(4, user, opserv,"+k = ChanServ Mode (mode +k)"); + send_message_type(4, user, opserv,"+S = NetServ Mode (mode +S)"); + send_message_type(4, user, opserv,"+X = XtraOp Mode (mode +X)"); + send_message_type(4, user, opserv,"OpMe = ChanServ opme command"); + return 1; +} + +static MODCMD_FUNC(cmd_adddevnull) +{ + + if (dict_find(opserv_devnull_classes, argv[1], NULL)) { + reply("OSMSG_DEVNULL_FOUND", argv[1]); + return 0; + } + + opserv_add_devnull_class(argv[1], (++devnull_last_id), 0, 0, 0); + reply("OSMSG_DEVNULL_ADDED",argv[1]); + return 1; +} + + +static MODCMD_FUNC(cmd_deldevnull) +{ + unsigned int n; + + for (n=1; nid); + dict_remove(opserv_devnull_classes, argv[n]); + reply("OSMSG_DEVNULL_REMOVED",argv[n]); + } + return 1; +} + +static MODCMD_FUNC(cmd_renamedevnull) +{ + struct devnull_class *th; + if (dict_find(opserv_devnull_classes, argv[2], NULL)) { + reply("OSMSG_DEVNULL_FOUND", argv[2]); + return 0; + } + if ((th = dict_find(opserv_devnull_classes, argv[1], NULL))) { + opserv_add_devnull_class(argv[2], th->id, th->modes, th->maxchan, th->maxsendq); + dict_remove(opserv_devnull_classes, argv[1]); + reply("OSMSG_DEVNULL_RENAMED",argv[1],argv[2]); + } else { + reply("OSMSG_DEVNULL_NOTFOUND", argv[1]); + return 0; + } + return 1; +} + +static MODCMD_FUNC(cmd_setdevnull) +{ + struct devnull_class *th; + unsigned int offset=0; + if ((th = dict_find(opserv_devnull_classes, argv[offset+1], NULL))) { + if (argc > 3) { + unsigned int ii; + for( ii = 0; argv[offset+2][ ii ]; ii++) + argv[offset+2][ ii ] = toupper( argv[offset+2][ ii ] ); + for( ii = 0; argv[offset+3][ ii ]; ii++) + argv[offset+3][ ii ] = toupper( argv[offset+3][ ii ] ); + + if(!strcmp("CHANLIMIT",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, CHANLIMIT); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + DEVNULL_SET_PRIV(th, CHANLIMIT); + th->maxchan = strtoul(argv[offset+3], NULL, 0); + reply("OSMSG_DEVNULL_SET_DONE"); + } + } else if(!strcmp("UNLIMITTARGET",argv[offset+2]) || !strcmp("UNLIMITEDTARGET",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, UNLIMITTARGET); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, UNLIMITTARGET); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("FLOOD",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, HALFFLOOD); + DEVNULL_CLEAR_PRIV(th, NOFLOOD); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, NOFLOOD); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("HALF",argv[offset+3]) || !strcmp("2",argv[offset+3]) || !strcmp("1/2",argv[offset+3])) { + DEVNULL_SET_PRIV(th, HALFFLOOD); + DEVNULL_CLEAR_PRIV(th, NOFLOOD); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("CHANHIDE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, CHANHIDE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, CHANHIDE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("IDLEHIDE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, IDLEHIDE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, IDLEHIDE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("CHSERVMODE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, CHSERVMODE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, CHSERVMODE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("XTRAOPMODE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, XTRAOPMODE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, XTRAOPMODE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("NETSERVMODE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, NETSERVMODE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, NETSERVMODE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("SEEIDLE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, SEEIDLE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, SEEIDLE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("FORCEIDLEHIDE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, FORCEIDLEHIDE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, FORCEIDLEHIDE); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("OVERRIDECC",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, OVERRIDECC); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, OVERRIDECC); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("OVERRIDENOAMSG",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, OVERRIDENOAMSG); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, OVERRIDENOAMSG); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else if(!strcmp("MAXSENDQ",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, MAXSENDQ); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + DEVNULL_SET_PRIV(th, MAXSENDQ); + th->maxsendq = strtoul(argv[offset+3], NULL, 0); + reply("OSMSG_DEVNULL_SET_DONE"); + } + } + else if(!strcmp("OPME",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_PRIV(th, OPME); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_PRIV(th, OPME); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+2]); + } + + } else { + reply("OSMSG_DEVNULL_SET", th->name); + if(DEVNULL_HAS_PRIV(th, CHANLIMIT)) { + reply("OSMSG_DEVNULL_SET_A_i", th->maxchan); + } else { + reply("OSMSG_DEVNULL_SET_A", "off"); + } + if(DEVNULL_HAS_PRIV(th, UNLIMITTARGET)) { + reply("OSMSG_DEVNULL_SET_B", "on"); + } else { + reply("OSMSG_DEVNULL_SET_B", "off"); + } + if(DEVNULL_HAS_PRIV(th, NOFLOOD)) { + reply("OSMSG_DEVNULL_SET_C", "on"); + } else if(DEVNULL_HAS_PRIV(th, HALFFLOOD)) { + reply("OSMSG_DEVNULL_SET_C", "half"); + } else { + reply("OSMSG_DEVNULL_SET_C", "off"); + } + if(DEVNULL_HAS_PRIV(th, CHANHIDE)) { + reply("OSMSG_DEVNULL_SET_E", "on"); + } else { + reply("OSMSG_DEVNULL_SET_E", "off"); + } + if(DEVNULL_HAS_PRIV(th, IDLEHIDE)) { + reply("OSMSG_DEVNULL_SET_F", "on"); + } else { + reply("OSMSG_DEVNULL_SET_F", "off"); + } + if(DEVNULL_HAS_PRIV(th, CHSERVMODE)) { + reply("OSMSG_DEVNULL_SET_G", "on"); + } else { + reply("OSMSG_DEVNULL_SET_G", "off"); + } + if(DEVNULL_HAS_PRIV(th, XTRAOPMODE)) { + reply("OSMSG_DEVNULL_SET_H", "on"); + } else { + reply("OSMSG_DEVNULL_SET_H", "off"); + } + if(DEVNULL_HAS_PRIV(th, NETSERVMODE)) { + reply("OSMSG_DEVNULL_SET_I", "on"); + } else { + reply("OSMSG_DEVNULL_SET_I", "off"); + } + if(DEVNULL_HAS_PRIV(th, SEEIDLE)) { + reply("OSMSG_DEVNULL_SET_J", "on"); + } else { + reply("OSMSG_DEVNULL_SET_J", "off"); + } + if(DEVNULL_HAS_PRIV(th, FORCEIDLEHIDE)) { + reply("OSMSG_DEVNULL_SET_K", "on"); + } else { + reply("OSMSG_DEVNULL_SET_K", "off"); + } + if(DEVNULL_HAS_PRIV(th, OVERRIDECC)) { + reply("OSMSG_DEVNULL_SET_L", "on"); + } else { + reply("OSMSG_DEVNULL_SET_L", "off"); + } + if(DEVNULL_HAS_PRIV(th, OVERRIDENOAMSG)) { + reply("OSMSG_DEVNULL_SET_M", "on"); + } else { + reply("OSMSG_DEVNULL_SET_M", "off"); + } + if(DEVNULL_HAS_PRIV(th, MAXSENDQ)) { + reply("OSMSG_DEVNULL_SET_N_i", th->maxsendq); + } else { + reply("OSMSG_DEVNULL_SET_N", "off"); + } + if(DEVNULL_HAS_PRIV(th, OPME)) { + reply("OSMSG_DEVNULL_SET_OPME", "on"); + } else { + reply("OSMSG_DEVNULL_SET_OPME", "off"); + } + } + } else { + reply("OSMSG_DEVNULL_NOTFOUND", argv[offset+1]); + return 0; + } + return 1; +} + +struct devnull_class *devnull_find_id(unsigned int id) { + dict_iterator_t it; + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + struct devnull_class *th = iter_data(it); + if(th->id == id) + return th; + } + return NULL; +} + +struct devnull_class *devnull_find_name(const char *name) { + struct devnull_class *th; + if ((th = dict_find(opserv_devnull_classes, name, NULL))) { + return th; + } + return NULL; +} + +int devnull_user_has_priv(struct handle_info *hi, int devnull_priv) { + if(devnull_check_priv_func) { + struct devnull_class ext_class = ((struct devnull_class (*)(struct handle_info *))devnull_check_priv_func)(hi); + if((ext_class.modes & devnull_priv)) + return (ext_class.modes & devnull_priv); + } + + if(!hi->devnull_id) + return 0; + struct devnull_class *th = devnull_find_id(hi->devnull_id); + if(!th) + return 0; + return (th->modes & devnull_priv); +} + +struct devnull_class devnull_user_get_class(struct handle_info *hi) { + struct devnull_class th; + memset(&th, 0, sizeof(th)); + + if(devnull_check_priv_func) { + struct devnull_class ext_class = ((struct devnull_class (*)(struct handle_info *))devnull_check_priv_func)(hi); + th.modes |= ext_class.modes; + if(ext_class.name) + th.name = ext_class.name; + if(DEVNULL_HAS_PRIV(&th, CHANLIMIT)) + th.maxchan = ext_class.maxchan; + if(DEVNULL_HAS_PRIV(&th, MAXSENDQ)) + th.maxsendq = ext_class.maxsendq; + } + + if(hi->devnull_id) { + struct devnull_class *thp; + if((thp = devnull_find_id(hi->devnull_id))) { + if(DEVNULL_HAS_PRIV(thp, CHANLIMIT) && (!DEVNULL_HAS_PRIV(&th, CHANLIMIT) || th.maxchan < thp->maxchan)) + th.maxchan = thp->maxchan; + if(DEVNULL_HAS_PRIV(thp, MAXSENDQ) && (!DEVNULL_HAS_PRIV(&th, MAXSENDQ) || th.maxsendq < thp->maxsendq)) + th.maxsendq = thp->maxsendq; + th.modes |= thp->maxsendq; + th.name = thp->name; + } + } + return th; +} + +void operpart(struct chanNode *chan, struct userNode *user) +{ + if(opserv_conf.alert_channel && opserv_conf.staff_auth_force > 0 && + !(irccasecmp(chan->name,opserv_conf.alert_channel->name))) { + struct mod_chanmode *change; + change = find_matching_bans(&chan->banlist, user, NULL); //don't join them if they're banned (exceptions from forced join) + if(change) + return; + irc_svsjoin(opserv,user,chan); + } +} + +void operadd(struct userNode *user) +{ + if(opserv_conf.alert_channel && opserv_conf.staff_auth_force > 0) + irc_svsjoin(opserv,user,opserv_conf.alert_channel); +} + +void operdel(struct userNode *user) +{ + if(opserv_conf.alert_channel && opserv_conf.staff_auth_force == 2) + irc_kick(opserv, user, opserv_conf.alert_channel, "mode -o"); +} + +static MODCMD_FUNC(cmd_svsjoin) +{ + struct userNode *target; + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + if(!IsChannelName(argv[2])) + { + reply("MSG_NOT_CHANNEL_NAME"); + return 0; + } + irc_svsjoinchan(opserv,target,argv[2]); + reply("OSMSG_SVSJOIN",target->nick,argv[2]); + return 1; +} + +static MODCMD_FUNC(cmd_svspart) +{ + struct userNode *target; + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + if(!IsChannelName(argv[2])) + { + reply("MSG_NOT_CHANNEL_NAME"); + return 0; + } + irc_svspartchan(opserv,target,argv[2]); + reply("OSMSG_SVSPART",target->nick,argv[2]); + return 1; +} + +static MODCMD_FUNC(cmd_svskill) +{ + struct userNode *target; + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + DelUser(target, opserv, 1, argv[2]); + reply("OSMSG_SVSKILL",target->nick,argv[2]); + return 1; +} +static MODCMD_FUNC(cmd_svsnick) +{ + struct userNode *target; + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + if(GetUserH(argv[2])) + { + reply("OSMSG_SVSNICKUSED",argv[2]); + return 0; + } + irc_svsnick(opserv,target,argv[2]); + reply("OSMSG_SVSNICK",target->nick,argv[2]); + return 1; +} + +static MODCMD_FUNC(cmd_svsmode) +{ + struct userNode *target; + char *modestr; + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + modestr = unsplit_string(argv + 2, argc - 2, NULL); + irc_svsmode(opserv,target,modestr); + reply("OSMSG_SVSMODE",modestr,target->nick); + return 1; +} + +static MODCMD_FUNC(cmd_simul) +{ + struct userNode *target; + char *line; + if(argc > 2) { + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + line = unsplit_string(argv + 2, argc - 2, NULL); + irc_simul(target,line); + reply("OSMSG_SIMUL",target->nick,line); + return 1; + } + return 0; +} + +static MODCMD_FUNC(cmd_relay) +{ + struct userNode *target; + char *line; + if(!(target=GetUserH(argv[1]))) { + reply("OSMSG_SVSNONICK", argv[1]); + return 0; + } + line = unsplit_string(argv + 2, argc - 2, NULL); + char sendline[512]; + if(channel) + sprintf(sendline, "relay %s %s :%s",user->nick,channel->name,line); + else + sprintf(sendline, "relay %s query :%s",user->nick,line); + irc_privmsg(opserv,target->numeric,sendline); + return 1; +} + static void opserv_conf_read(void) { @@ -4165,8 +4964,11 @@ opserv_conf_read(void) str2 = "+timns"; opserv_conf.staff_auth_channel = AddChannel(str, now, str2, NULL); AddChannelUser(opserv, opserv_conf.staff_auth_channel)->modes |= MODE_CHANOP; + str2 = database_get_data(conf_node, KEY_STAFF_AUTH_FORCE_OPS, RECDB_QSTRING); + opserv_conf.staff_auth_force = str2 ? atoi(str2) : 0; } else { opserv_conf.staff_auth_channel = NULL; + opserv_conf.staff_auth_force = 0; } str = database_get_data(conf_node, KEY_UNTRUSTED_MAX, RECDB_QSTRING); opserv_conf.untrusted_max = str ? strtoul(str, NULL, 0) : 5; @@ -4212,6 +5014,10 @@ opserv_db_init(void) { dict_delete(opserv_trusted_hosts); opserv_trusted_hosts = dict_new(); dict_set_free_data(opserv_trusted_hosts, free_trusted_host); + /* set up opserv_devnull_classes dict */ + dict_delete(opserv_devnull_classes); + opserv_devnull_classes = dict_new(); + dict_set_free_data(opserv_devnull_classes, free_devnull_class); /* set up opserv_chan_warn dict */ dict_delete(opserv_chan_warn); opserv_chan_warn = dict_new(); @@ -4247,6 +5053,7 @@ opserv_db_cleanup(void) free_string_list(opserv_bad_words); dict_delete(opserv_exempt_channels); dict_delete(opserv_trusted_hosts); + dict_delete(opserv_devnull_classes); unreg_del_user_func(opserv_user_cleanup); dict_delete(opserv_hostinfo_dict); dict_delete(opserv_nick_based_alerts); @@ -4271,6 +5078,13 @@ init_opserv(const char *nick) } conf_register_reload(opserv_conf_read); + unsigned int i; + /* set up handle_inverse_flags */ + memset(devnull_inverse_modes, 0, sizeof(devnull_inverse_modes)); + for (i=0; devnull_modes[i]; i++) { + devnull_inverse_modes[(unsigned char)devnull_modes[i]] = i + 1; + } + memset(level_strings, 0, sizeof(level_strings)); opserv_module = module_register("OpServ", OS_LOG, "opserv.help", opserv_help_expand); opserv_define_func("ACCESS", cmd_access, 0, 0, 0); @@ -4349,6 +5163,18 @@ init_opserv(const char *nick) #if defined(WITH_MALLOC_SRVX) || defined(WITH_MALLOC_SLAB) opserv_define_func("STATS MEMORY", cmd_stats_memory, 0, 0, 0); #endif + opserv_define_func("DEVNULL ADD", cmd_adddevnull, 200, 0, 2); + opserv_define_func("DEVNULL DEL", cmd_deldevnull, 200, 0, 2); + opserv_define_func("DEVNULL RENAME", cmd_renamedevnull, 200, 0, 3); + opserv_define_func("DEVNULL SET", cmd_setdevnull, 200, 0, 2); + opserv_define_func("DEVNULL LIST", cmd_listdevnull, 200, 0, 0); + opserv_define_func("SVSJOIN", cmd_svsjoin, 800, 0, 3); + opserv_define_func("SVSPART", cmd_svspart, 800, 0, 3); + opserv_define_func("SVSKILL", cmd_svskill, 800, 0, 3); + opserv_define_func("SVSMODE", cmd_svsmode, 800, 0, 3); + opserv_define_func("SVSNICK", cmd_svsnick, 800, 0, 3); + opserv_define_func("RELAY", cmd_relay, 800, 0, 0); + opserv_define_func("SIMUL", cmd_simul, 999, 0, 3); opserv_define_func("TRACE", cmd_trace, 100, 0, 3); opserv_define_func("TRACE PRINT", NULL, 0, 0, 0); opserv_define_func("TRACE COUNT", NULL, 0, 0, 0);