X-Git-Url: http://git.pk910.de/?p=srvx.git;a=blobdiff_plain;f=src%2Fopserv.c;h=d358d57637b4c59f10a51e819e99ee32115d2e6c;hp=38ad356ee2d84bbc14fbe97b3156460d054ed2da;hb=52ad451848654edc3f544e7e52eb773b156da9ff;hpb=f6b39d3f8fa704355045ace0df293bc6f04cb36d diff --git a/src/opserv.c b/src/opserv.c index 38ad356..d358d57 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,16 @@ #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_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) @@ -257,6 +264,43 @@ 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_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 } }; @@ -271,6 +315,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* */ @@ -279,12 +324,15 @@ 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]; 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; @@ -1192,7 +1240,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; } @@ -1291,7 +1339,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"); @@ -2763,6 +2811,57 @@ trusted_host_read(const char *host, void *data, UNUSED_ARG(void *extra)) return 0; } +static void +opserv_add_devnull_class(const char *name, unsigned long modes, unsigned long maxchan, unsigned long maxsendq) +{ + struct devnull_class *th; + th = calloc(1, sizeof(*th)); + if (!th) + return; + 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 *nameb = name, *str; + unsigned long modes, maxchan, maxsendq; + unsigned int ii; + + if (rd->type == RECDB_OBJECT) { + dict_t obj = GET_RECORD_OBJECT(rd); + /* new style structure */ + nameb = database_get_data(obj, KEY_DEVNULL_NAME, RECDB_QSTRING); + 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(nameb, modes, maxchan, maxsendq); + return 0; +} + static int opserv_saxdb_read(struct dict *conf_db) { @@ -2807,6 +2906,8 @@ opserv_saxdb_read(struct dict *conf_db) } 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))) @@ -2864,6 +2965,28 @@ 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, iter_key(it), 0); + if (th->name) saxdb_write_string(ctx, KEY_DEVNULL_NAME, th->name); + 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); + } /* gags */ if (gagList) { struct gag_entry *gag; @@ -3971,6 +4094,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)) @@ -3981,9 +4106,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 @@ -4135,6 +4260,584 @@ 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_FLAGGED(th, MODE_A)) { + tbl.contents[ii][1] = strtab(th->maxchan); + } else { + tbl.contents[ii][1] = off; + } + if(DEVNULL_FLAGGED(th, MODE_B)) { + tbl.contents[ii][2] = on; + } else { + tbl.contents[ii][2] = off; + } + if(DEVNULL_FLAGGED(th, MODE_D)) { + tbl.contents[ii][3] = on; + } else if(DEVNULL_FLAGGED(th, MODE_C)) { + tbl.contents[ii][3] = half; + } else { + tbl.contents[ii][3] = off; + } + if(DEVNULL_FLAGGED(th, MODE_E)) { + tbl.contents[ii][4] = on; + } else { + tbl.contents[ii][4] = off; + } + if(DEVNULL_FLAGGED(th, MODE_F)) { + tbl.contents[ii][5] = on; + } else { + tbl.contents[ii][5] = off; + } + if(DEVNULL_FLAGGED(th, MODE_J)) { + tbl.contents[ii][6] = on; + } else { + tbl.contents[ii][6] = off; + } + if(DEVNULL_FLAGGED(th, MODE_K)) { + tbl.contents[ii][7] = on; + } else { + tbl.contents[ii][7] = off; + } + if(DEVNULL_FLAGGED(th, MODE_L)) { + tbl.contents[ii][8] = on; + } else { + tbl.contents[ii][8] = off; + } + if(DEVNULL_FLAGGED(th, MODE_M)) { + tbl.contents[ii][9] = on; + } else { + tbl.contents[ii][9] = off; + } + if(DEVNULL_FLAGGED(th, MODE_G)) { + tbl.contents[ii][10] = on; + } else { + tbl.contents[ii][10] = off; + } + if(DEVNULL_FLAGGED(th, MODE_I)) { + tbl.contents[ii][11] = on; + } else { + tbl.contents[ii][11] = off; + } + if(DEVNULL_FLAGGED(th, MODE_H)) { + tbl.contents[ii][12] = on; + } else { + tbl.contents[ii][12] = off; + } + if(DEVNULL_FLAGGED(th, MODE_N)) { + tbl.contents[ii][13] = on; + } else { + tbl.contents[ii][13] = off; + } + if(DEVNULL_FLAGGED(th, MODE_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], 0, 0, 0); + reply("OSMSG_DEVNULL_ADDED",argv[1]); + return 1; +} + + +static MODCMD_FUNC(cmd_deldevnull) +{ + unsigned int n; + + for (n=1; nname); + 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->modes, th->maxchan, th->maxsendq); + nickserv_devnull_rename(th->name,argv[2]); + 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_FLAG(th, MODE_A); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + DEVNULL_SET_FLAG(th, MODE_A); + 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_FLAG(th, MODE_B); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_B); + 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_FLAG(th, MODE_C); + DEVNULL_CLEAR_FLAG(th, MODE_D); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_D); + 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_FLAG(th, MODE_C); + DEVNULL_CLEAR_FLAG(th, MODE_D); + 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_FLAG(th, MODE_E); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_E); + 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_FLAG(th, MODE_F); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_F); + 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_FLAG(th, MODE_G); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_G); + 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_FLAG(th, MODE_H); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_H); + 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_FLAG(th, MODE_I); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_I); + 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_FLAG(th, MODE_J); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_J); + 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_FLAG(th, MODE_K); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_K); + 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_FLAG(th, MODE_L); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_L); + 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_FLAG(th, MODE_M); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_M); + 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_FLAG(th, MODE_N); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + DEVNULL_SET_FLAG(th, MODE_N); + 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_FLAG(th, MODE_OPME); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_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_FLAGGED(th, MODE_A)) { + reply("OSMSG_DEVNULL_SET_A_i", th->maxchan); + } else { + reply("OSMSG_DEVNULL_SET_A", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_B)) { + reply("OSMSG_DEVNULL_SET_B", "on"); + } else { + reply("OSMSG_DEVNULL_SET_B", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_D)) { + reply("OSMSG_DEVNULL_SET_C", "on"); + } else if(DEVNULL_FLAGGED(th, MODE_C)) { + reply("OSMSG_DEVNULL_SET_C", "half"); + } else { + reply("OSMSG_DEVNULL_SET_C", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_E)) { + reply("OSMSG_DEVNULL_SET_E", "on"); + } else { + reply("OSMSG_DEVNULL_SET_E", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_F)) { + reply("OSMSG_DEVNULL_SET_F", "on"); + } else { + reply("OSMSG_DEVNULL_SET_F", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_G)) { + reply("OSMSG_DEVNULL_SET_G", "on"); + } else { + reply("OSMSG_DEVNULL_SET_G", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_H)) { + reply("OSMSG_DEVNULL_SET_H", "on"); + } else { + reply("OSMSG_DEVNULL_SET_H", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_I)) { + reply("OSMSG_DEVNULL_SET_I", "on"); + } else { + reply("OSMSG_DEVNULL_SET_I", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_J)) { + reply("OSMSG_DEVNULL_SET_J", "on"); + } else { + reply("OSMSG_DEVNULL_SET_J", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_K)) { + reply("OSMSG_DEVNULL_SET_K", "on"); + } else { + reply("OSMSG_DEVNULL_SET_K", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_L)) { + reply("OSMSG_DEVNULL_SET_L", "on"); + } else { + reply("OSMSG_DEVNULL_SET_L", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_M)) { + reply("OSMSG_DEVNULL_SET_M", "on"); + } else { + reply("OSMSG_DEVNULL_SET_M", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_N)) { + reply("OSMSG_DEVNULL_SET_N_i", th->maxsendq); + } else { + reply("OSMSG_DEVNULL_SET_N", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_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; +} + +int devnull_check(const char *name) { + if (dict_find(opserv_devnull_classes, name, NULL)) { + return 1; + } + return 0; +} + +struct devnull_class* + devnull_get(const char *name) { + return dict_find(opserv_devnull_classes, name, NULL); +} + +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_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) { @@ -4177,8 +4880,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; @@ -4224,6 +4930,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(); @@ -4259,6 +4969,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); @@ -4283,6 +4994,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); @@ -4361,6 +5079,16 @@ 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("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, 2); 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);