X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/1136f709ef8add5fa9ba8663db910003362e1bd2..26b2c254c534b044c4a6357a7b9830d6db7d4618:/src/opserv.c diff --git a/src/opserv.c b/src/opserv.c index e3aacab..012d0da 100644 --- a/src/opserv.c +++ b/src/opserv.c @@ -182,12 +182,14 @@ static const struct message_entry msgtab[] = { { "OSMSG_KICKALL_DONE", "I have cleared out %s." }, { "OSMSG_LEAVING", "Leaving $b%s$b." }, { "OSMSG_MARK_INVALID", "Sorry, marks must contain only letters, numbers, and dashes ('-')." }, + { "OSMSG_MARK_NOTMARKED", "Action not mark but mark supplied. (Did you mean marked?)" }, { "OSMSG_MODE_SET", "I have set the modes for $b%s$b." }, { "OSMSG_OP_DONE", "Opped the requested lusers." }, { "OSMSG_OPALL_DONE", "Opped everyone on $b%s$b." }, { "OSMSG_HOP_DONE", "Halfopped the requested lusers." }, { "OSMSG_HOPALL_DONE", "Halfopped everyone on $b%s$b." }, { "OMSG_BAD_SVSNICK", "$b%s$b is an invalid nickname." }, + { "OSMSG_BAD_SVSCMDTARGET", "$b%s$b is an invalid target for %s." }, { "OSMSG_WHOIS_IDENT", "%s (%s@%s) from %d.%d.%d.%d" }, { "OSMSG_WHOIS_NICK", "Nick : %s" }, @@ -216,7 +218,9 @@ static const struct message_entry msgtab[] = { { "OSMSG_WHOIS_CHANNELS", "Channels : %s" }, { "OSMSG_WHOIS_HIDECHANS", "Channel list omitted for your sanity." }, { "OSMSG_WHOIS_VERSION", "Version : %s" }, - { "OSMSG_WHOIS_MARK", "Mark : %s" }, + { "OSMSG_WHOIS_SSLFP", "SSL f/print : %s" }, + { "OSMSG_WHOIS_MARK", "Mark : %s" }, + { "OSMSG_WHOIS_MARKS", "Marks : %s" }, { "OSMSG_WHOIS_NO_NOTICE", "No_notices : %s" }, { "OSMSG_UNBAN_DONE", "Ban(s) removed from channel %s." }, { "OSMSG_CHANNEL_VOICED", "All users on %s voiced." }, @@ -305,8 +309,8 @@ static const struct message_entry msgtab[] = { { "OSMSG_LOG_SEARCH_RESULTS", "The following log entries were found:" }, { "OSMSG_GSYNC_RUNNING", "Synchronizing glines from %s." }, { "OSMSG_SSYNC_RUNNING", "Synchronizing shuns from %s." }, - { "OSMSG_GTRACE_FORMAT", "%s (issued %s by %s, lastmod %s, expires %s): %s" }, - { "OSMSG_STRACE_FORMAT", "%s (issued %s by %s, lastmod %s, expires %s): %s" }, + { "OSMSG_GTRACE_FORMAT", "%s (issued %s by %s, expires %s): %s" }, + { "OSMSG_STRACE_FORMAT", "%s (issued %s by %s, expires %s): %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." }, @@ -570,7 +574,7 @@ struct discrim_and_source { unsigned int disp_limit; }; -static discrim_t opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int argc, char *argv[], int allow_channel); +static discrim_t opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int argc, char *argv[], int allow_channel, const char *action); static unsigned int opserv_discrim_search(discrim_t discrim, discrim_search_func dsf, void *data); static int gag_helper_func(struct userNode *match, void *extra); static int ungag_helper_func(struct userNode *match, void *extra); @@ -585,7 +589,9 @@ typedef enum { REACT_SVSJOIN, REACT_SVSPART, REACT_VERSION, - REACT_MARK + REACT_MARK, + REACT_NOTICEUSER, + REACT_MSGUSER } opserv_alert_reaction; struct opserv_user_alert { @@ -1304,7 +1310,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, silent ? 1 : 0); + return gline_add(src_handle, mask, duration, reason, now, 1, silent ? 1 : 0); } static MODCMD_FUNC(cmd_block) @@ -1376,7 +1382,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, 0); + gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, 1, 0); reply("OSMSG_GLINE_ISSUED", gline->target); return 1; } @@ -1457,6 +1463,22 @@ opserv_svsjoin(struct userNode *target, UNUSED_ARG(char *src_handle), UNUSED_ARG return; /* channel is invite only */ } + if (!IsOper(target) && (channel->modes & MODE_OPERSONLY)) { + return; /* user is not oper and channel is opers only */ + } + + if (!IsAdmin(target) && (channel->modes & MODE_ADMINSONLY)) { + return; /* user is not admin and channel is admin only */ + } + + if (target->handle_info && (channel->modes & MODE_REGONLY)) { + return; /* user is not authed and channel is authed only users */ + } + + if (!IsSSL(target) && (channel->modes & MODE_SSLONLY)) { + return; /* user is not SSL and channel is SSL only */ + } + if (channel->limit > 0) { if (channel->members.used >= channel->limit) { return; /* channel is invite on */ @@ -1506,7 +1528,7 @@ opserv_shun(struct userNode *target, char *src_handle, char *reason, unsigned lo snprintf(reason, MAXLEN, "Shun requested by %s.", src_handle); } if (!duration) duration = opserv_conf.block_shun_duration; - return shun_add(src_handle, mask, duration, reason, now, now, 1); + return shun_add(src_handle, mask, duration, reason, now, 1); } static MODCMD_FUNC(cmd_sblock) @@ -1565,7 +1587,7 @@ static MODCMD_FUNC(cmd_shun) struct shun *shun; reason = unsplit_string(argv+3, argc-3, NULL); - if (!is_shun(argv[1]) && !IsChannelName(argv[1]) && (argv[1][0] != '&')) { + if (!is_shun(argv[1])) { reply("MSG_INVALID_SHUN", argv[1]); return 0; } @@ -1578,7 +1600,7 @@ static MODCMD_FUNC(cmd_shun) reply("MSG_INVALID_DURATION", argv[2]); return 0; } - shun = shun_add(user->handle_info->handle, argv[1], duration, reason, now, now, 1); + shun = shun_add(user->handle_info->handle, argv[1], duration, reason, now, 1); reply("OSMSG_SHUN_ISSUED", shun->target); return 1; } @@ -1704,6 +1726,11 @@ static MODCMD_FUNC(cmd_svsjoin) return 0; } + if (IsLocal(target)) { + reply("OSMSG_BAD_SVSCMDTARGET", argv[1], "SVSJOIN"); + return 0; + } + if (!(channel = GetChannel(argv[2]))) { channel = AddChannel(argv[2], now, NULL, NULL, NULL); } @@ -1725,6 +1752,12 @@ static MODCMD_FUNC(cmd_svsnick) reply("MSG_NICK_UNKNOWN", argv[1]); return 0; } + + if (IsLocal(target)) { + reply("OSMSG_BAD_SVSCMDTARGET", argv[1], "SVSNICK"); + return 0; + } + if(!is_valid_nick(argv[2])) { reply("OMSG_BAD_SVSNICK", argv[2]); return 0; @@ -1950,6 +1983,11 @@ static MODCMD_FUNC(cmd_svspart) return 0; } + if (IsLocal(target)) { + reply("OSMSG_BAD_SVSCMDTARGET", argv[1], "SVSPART"); + return 0; + } + if (!GetUserMode(target_channel, target)) { reply("OSMSG_NOT_ON_CHANNEL", cmd->parent->bot->nick, target_channel->name); return 0; @@ -2167,31 +2205,39 @@ static MODCMD_FUNC(cmd_whois) if(target->version_reply) { reply("OSMSG_WHOIS_VERSION", target->version_reply); } + if(target->sslfp) { + reply("OSMSG_WHOIS_SSLFP", target->sslfp); + } if(target->mark) { reply("OSMSG_WHOIS_MARK", target->mark); } + if(target->marks) { + char markbuf[MAXLEN] = ""; + unsigned int ii = 0; + + string_list_sort(user->marks); + + for (ii=0; iimarks->used; ii++) + { + if (markbuf[0] && strlen(markbuf) + strlen(user->marks->list[ii]) + 4 > 70) { + reply("OSMSG_WHOIS_MARKS", markbuf); + memset(&markbuf, 0, MAXLEN); + } + + if (markbuf[0]) + strcat(markbuf, ", "); + strcat(markbuf, user->marks->list[ii]); + } + + if (markbuf[0]) + reply("OSMSG_WHOIS_MARKS", markbuf); + } + reply("OSMSG_WHOIS_NO_NOTICE", target->no_notice ? "YES":"NO"); if (target->modes) { - bpos = 0; + bpos = irc_user_modes(target, buffer, sizeof(buffer)); #define buffer_cat(str) (herelen = strlen(str), memcpy(buffer+bpos, str, herelen), bpos += herelen) - if (IsInvisible(target)) buffer[bpos++] = 'i'; - if (IsWallOp(target)) buffer[bpos++] = 'w'; - if (IsOper(target)) buffer[bpos++] = 'o'; - if (IsGlobal(target)) buffer[bpos++] = 'g'; - - // sethost - reed/apples - // if (IsHelperIrcu(target)) buffer[bpos++] = 'h'; - if (IsSetHost(target)) buffer[bpos++] = 'h'; - - if (IsService(target)) buffer[bpos++] = 'k'; - if (IsDeaf(target)) buffer[bpos++] = 'd'; - if (target->handle_info) buffer[bpos++] = 'r'; - if (IsHiddenHost(target)) buffer[bpos++] = 'x'; - if (IsBotM(target)) buffer[bpos++] = 'B'; - if (IsHideChans(target)) buffer[bpos++] = 'n'; - if (IsHideIdle(target)) buffer[bpos++] = 'I'; - if (IsXtraOp(target)) buffer[bpos++] = 'X'; if (IsGagged(target)) buffer_cat(" (gagged)"); if (IsRegistering(target)) buffer_cat(" (registered account)"); buffer[bpos] = 0; @@ -2545,6 +2591,8 @@ static MODCMD_FUNC(cmd_stats_alerts) { case REACT_SVSPART: reaction = "svspart"; break; case REACT_VERSION: reaction = "version"; break; case REACT_MARK: reaction = "mark"; break; + case REACT_NOTICEUSER: reaction = "noticeuser"; break; + case REACT_MSGUSER: reaction = "msguser"; break; default: reaction = ""; break; } reply("OSMSG_ALERT_IS", iter_key(it), reaction, alert->owner); @@ -2758,7 +2806,7 @@ opserv_part_channel(void *data) static int alert_check_user(const char *key, void *data, void *extra); static int -opserv_new_user_check(struct userNode *user) +opserv_new_user_check(struct userNode *user, UNUSED_ARG(void *extra)) { struct opserv_hostinfo *ohi; struct gag_entry *gag; @@ -2774,7 +2822,7 @@ opserv_new_user_check(struct userNode *user) /* Gag them if appropriate. */ for (gag = gagList; gag; gag = gag->next) { - if (user_matches_glob(user, gag->mask, MATCH_USENICK)) { + if (user_matches_glob(user, gag->mask, MATCH_USENICK, 0)) { gag_helper_func(user, NULL); break; } @@ -2811,9 +2859,9 @@ opserv_new_user_check(struct userNode *user) strcpy(target + 2, user->hostname); if (checkDefCon(DEFCON_GLINE_NEW_CLIENTS)) - gline_add(opserv->nick, target, DefConGlineExpire, DefConGlineReason, now, now, 1, 0); + gline_add(opserv->nick, target, DefConGlineExpire, DefConGlineReason, now, 1, 0); else if (checkDefCon(DEFCON_SHUN_NEW_CLIENTS)) - shun_add(opserv->nick, target, DefConGlineExpire, DefConGlineReason, now, now, 1); + shun_add(opserv->nick, target, DefConGlineExpire, DefConGlineReason, now, 1); return 0; } @@ -2837,7 +2885,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, "Excessive connections from a single host.", now, now, 1, 1); + gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "Excessive connections from a single host.", now, 1, 1); } } @@ -2845,7 +2893,7 @@ opserv_new_user_check(struct userNode *user) } static void -opserv_user_cleanup(struct userNode *user, UNUSED_ARG(struct userNode *killer), UNUSED_ARG(const char *why)) +opserv_user_cleanup(struct userNode *user, UNUSED_ARG(struct userNode *killer), UNUSED_ARG(const char *why), UNUSED_ARG(void *extra)) { struct opserv_hostinfo *ohi; char addr[IRC_NTOP_MAX_SIZE]; @@ -2909,7 +2957,7 @@ opserv_shutdown_channel(struct chanNode *channel, const char *reason) } static void -opserv_channel_check(struct chanNode *newchan) +opserv_channel_check(struct chanNode *newchan, UNUSED_ARG(void *extra)) { /*char *warning; */ @@ -2928,7 +2976,7 @@ opserv_channel_check(struct chanNode *newchan) } static void -opserv_channel_delete(struct chanNode *chan) +opserv_channel_delete(struct chanNode *chan, UNUSED_ARG(void *extra)) { timeq_del(0, opserv_part_channel, chan, TIMEQ_IGNORE_WHEN); } @@ -2959,7 +3007,7 @@ opserv_notice_handler(struct userNode *user, struct userNode *bot, const char *t } static int -opserv_join_check(struct modeNode *mNode) +opserv_join_check(struct modeNode *mNode, UNUSED_ARG(void *extra)) { struct userNode *user = mNode->user; struct chanNode *channel = mNode->channel; @@ -2968,7 +3016,9 @@ opserv_join_check(struct modeNode *mNode) if (IsService(user)) return 0; - dict_foreach(opserv_channel_alerts, alert_check_user, user); + /* Check for alerts, and stop if we find one that kills them. */ + if (dict_foreach(opserv_user_alerts, alert_check_user, user)) + return 1; if (opserv && channel->bad_channel) { opserv_debug("Found $b%s$b in bad-word channel $b%s$b; removing the user.", user->nick, channel->name); @@ -4764,7 +4814,7 @@ add_gag_helper(const char *key, void *data, UNUSED_ARG(void *extra)) } static struct opserv_user_alert * -opserv_add_user_alert(struct userNode *req, const char *name, opserv_alert_reaction reaction, const char *text_discrim, int last, int expire) +opserv_add_user_alert(struct userNode *req, const char *name, opserv_alert_reaction reaction, const char *text_discrim, int last, int expire, const char *action) { unsigned int wordc; char *wordv[MAXNUMPARAMS], *discrim_copy; @@ -4781,7 +4831,7 @@ opserv_add_user_alert(struct userNode *req, const char *name, opserv_alert_react alert->last = last; discrim_copy = strdup(text_discrim); /* save a copy of the discrim */ wordc = split_line(discrim_copy, false, ArrayLength(wordv), wordv); - alert->discrim = opserv_discrim_create(req, opserv, wordc, wordv, 0); + alert->discrim = opserv_discrim_create(req, opserv, wordc, wordv, 0, action); alert->expire = expire; /* Check for missing required criteria or broken records */ if (!alert->discrim || (reaction==REACT_SVSJOIN && !alert->discrim->chantarget) || @@ -4877,11 +4927,15 @@ add_user_alert(const char *key, void *data, UNUSED_ARG(void *extra)) reaction = REACT_VERSION; else if (!irccasecmp(react, "mark")) reaction = REACT_MARK; + else if (!irccasecmp(react, "noticeuser")) + reaction = REACT_NOTICEUSER; + else if (!irccasecmp(react, "msguser")) + reaction = REACT_MSGUSER; else { log_module(OS_LOG, LOG_ERROR, "Invalid reaction %s for alert %s.", react, key); return 0; } - alert = opserv_add_user_alert(opserv, key, reaction, discrim, last, expire); + alert = opserv_add_user_alert(opserv, key, reaction, discrim, last, expire, react); if (!alert) { log_module(OS_LOG, LOG_ERROR, "Unable to create alert %s from database.", key); return 0; @@ -5164,6 +5218,8 @@ opserv_saxdb_write(struct saxdb_context *ctx) case REACT_SVSPART: reaction = "svspart"; break; case REACT_VERSION: reaction = "version"; break; case REACT_MARK: reaction = "mark"; break; + case REACT_NOTICEUSER: reaction = "noticeuser"; break; + case REACT_MSGUSER: reaction = "msguser"; break; default: reaction = NULL; log_module(OS_LOG, LOG_ERROR, "Invalid reaction type %d for alert %s (while writing database).", alert->reaction, iter_key(it)); @@ -5265,7 +5321,7 @@ static MODCMD_FUNC(cmd_settime) } static discrim_t -opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int argc, char *argv[], int allow_channel) +opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int argc, char *argv[], int allow_channel, const char *action) { unsigned int i, j; discrim_t discrim; @@ -5373,6 +5429,10 @@ opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int goto fail; } } else if (irccasecmp(argv[i], "mark") == 0) { + if (irccasecmp(action, "mark")) { + send_message(user, bot, "OSMSG_MARK_NOTMARKED"); + goto fail; + } if(!is_valid_mark(argv[i+1])) { send_message(user, bot, "OSMSG_MARK_INVALID"); goto fail; @@ -5660,6 +5720,20 @@ discrim_match(discrim_t discrim, struct userNode *user) { unsigned int level, i; char *scmp=NULL, *dcmp=NULL; + int markmatched = 0; + + if (discrim->mask_mark) + { + unsigned int ii = 0; + + if (user->mark && match_ircglob(user->mark, discrim->mask_mark)) + markmatched = 1; + + if (user->marks) + for (ii=0; iimarks->used; ii++) + if (match_ircglob(user->marks->list[ii], discrim->mask_mark)) + markmatched = 1; + } if ((user->timestamp < discrim->min_ts) || (user->timestamp > discrim->max_ts) @@ -5670,7 +5744,7 @@ discrim_match(discrim_t discrim, struct userNode *user) || (discrim->info_space == 0 && user->info[0] == ' ') || (discrim->info_space == 1 && user->info[0] != ' ') || (discrim->server && !match_ircglob(user->uplink->name, discrim->server)) - || (discrim->mask_mark && (!user->mark || !match_ircglob(user->mark, discrim->mask_mark))) + || (discrim->mask_mark && !markmatched) || (discrim->accountmask && (!user->handle_info || !match_ircglob(user->handle_info->handle, discrim->accountmask))) || (discrim->ip_mask_bits && !irc_check_mask(&user->ip, &discrim->ip_mask, discrim->ip_mask_bits)) ) @@ -5728,46 +5802,80 @@ discrim_match(discrim_t discrim, struct userNode *user) if (discrim->modes) { unsigned int ii, matches = 0; + unsigned int negate = 0; for (ii = 0; ii < strlen(discrim->modes); ii++) { switch(discrim->modes[ii]) { + case '+': + negate = 0; + matches++; + break; + case '-': + negate = 1; + matches++; + break; case 'O': - if(IsOper(user)) matches++; + if(IsOper(user) != 0 != negate) matches++; break; case 'o': - if(IsOper(user)) matches++; + if(IsOper(user) != 0 != negate) matches++; break; case 'i': - if(IsInvisible(user)) matches++; + if(IsInvisible(user) != 0 != negate) matches++; break; case 'w': - if(IsWallOp(user)) matches++; + if(IsWallOp(user) != 0 != negate) matches++; break; case 'd': - if(IsDeaf(user)) matches++; + if(IsDeaf(user) != 0 != negate) matches++; break; case 'k': - if(IsService(user)) matches++; + if(IsService(user) != 0 != negate) matches++; break; case 'g': - if(IsGlobal(user)) matches++; + if(IsGlobal(user) != 0 != negate) matches++; break; case 'h': - if(IsSetHost(user)) matches++; + if(IsSetHost(user) != 0 != negate) matches++; break; case 'B': - if(IsBotM(user)) matches++; + if(IsBotM(user) != 0 != negate) matches++; break; + case 'p': case 'n': - if(IsHideChans(user)) matches++; + if(IsHideChans(user) != 0 != negate) matches++; break; case 'I': - if(IsHideIdle(user)) matches++; + if(IsHideIdle(user) != 0 != negate) matches++; break; case 'X': - if(IsXtraOp(user)) matches++; + if(IsXtraOp(user) != 0 != negate) matches++; break; case 'x': - if(IsHiddenHost(user)) matches++; + if(IsHiddenHost(user) != 0 != negate) matches++; + break; + case 'a': + if(IsAdmin(user) != 0 != negate) matches++; + break; + case 'z': + if(IsSSL(user) != 0 != negate) matches++; + break; + case 'D': + if(IsPrivDeaf(user) != 0 != negate) matches++; + break; + case 'R': + if(IsAccountOnly(user) != 0 != negate) matches++; + break; + case 'W': + if(IsWhoisNotice(user) != 0 != negate) matches++; + break; + case 'H': + if(IsHideOper(user) != 0 != negate) matches++; + break; + case 'L': + if(IsHideOper(user) != 0 != negate) matches++; + break; + case 'q': + if(IsCommonChansOnly(user) != 0 != negate) matches++; break; } } @@ -5883,6 +5991,30 @@ trace_print_func(struct userNode *match, void *extra) return 0; } +static int +trace_privmsg_func(struct userNode *match, void *extra) +{ + struct discrim_and_source *das = extra; + char *reason; + if (das->discrim->reason) { + reason = das->discrim->reason; + irc_privmsg_user(opserv, match, reason); + } + return 0; +} + +static int +trace_notice_func(struct userNode *match, void *extra) +{ + struct discrim_and_source *das = extra; + char *reason; + if (das->discrim->reason) { + reason = das->discrim->reason; + irc_notice_user(opserv, match, reason); + } + return 0; +} + static int trace_count_func(UNUSED_ARG(struct userNode *match), UNUSED_ARG(void *extra)) { @@ -6170,6 +6302,10 @@ static MODCMD_FUNC(cmd_trace) action = trace_print_func; else if (!irccasecmp(argv[1], "count")) action = trace_count_func; + else if (!irccasecmp(argv[1], "privmsg")) + action = trace_privmsg_func; + else if (!irccasecmp(argv[1], "notice")) + action = trace_notice_func; else if (!irccasecmp(argv[1], "domains")) action = trace_domains_func; else if (!irccasecmp(argv[1], "gline")) @@ -6201,7 +6337,7 @@ static MODCMD_FUNC(cmd_trace) das.dict = NULL; das.source = user; das.destination = cmd->parent->bot; - das.discrim = opserv_discrim_create(user, cmd->parent->bot, argc-2, argv+2, 1); + das.discrim = opserv_discrim_create(user, cmd->parent->bot, argc-2, argv+2, 1, argv[1]); if (!das.discrim) return 0; @@ -6504,19 +6640,14 @@ gtrace_print_func(struct gline *gline, void *extra) { struct gline_extra *xtra = extra; char issued[INTERVALLEN]; - char lastmod[INTERVALLEN]; char expires[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(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, expires, gline->reason); } static MODCMD_FUNC(cmd_stats_glines) { @@ -6613,19 +6744,14 @@ strace_print_func(struct shun *shun, void *extra) { struct shun_extra *xtra = extra; char issued[INTERVALLEN]; - char lastmod[INTERVALLEN]; char expires[INTERVALLEN]; intervalString(issued, now - shun->issued, xtra->user->handle_info); - if (shun->lastmod) - intervalString(lastmod, now - shun->lastmod, xtra->user->handle_info); - else - strcpy(lastmod, ""); if (shun->expires) intervalString(expires, shun->expires - now, xtra->user->handle_info); else strcpy(expires, "never"); - send_message(xtra->user, opserv, "OSMSG_STRACE_FORMAT", shun->target, issued, shun->issuer, lastmod, expires, shun->reason); + send_message(xtra->user, opserv, "OSMSG_STRACE_FORMAT", shun->target, issued, shun->issuer, expires, shun->reason); } static MODCMD_FUNC(cmd_stats_shuns) { @@ -6779,18 +6905,24 @@ alert_check_user(const char *key, void *data, void *extra) add_track_user(user); #endif break; + case REACT_NOTICEUSER: + irc_notice_user(opserv, user, alert->discrim->reason); + break; + case REACT_MSGUSER: + irc_privmsg_user(opserv, user, alert->discrim->reason); + break; } return 0; } static void -opserv_alert_check_account(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle)) +opserv_alert_check_account(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle), UNUSED_ARG(void *extra)) { dict_foreach(opserv_account_based_alerts, alert_check_user, user); } static void -opserv_alert_check_nick(struct userNode *user, UNUSED_ARG(const char *old_nick)) +opserv_alert_check_nick(struct userNode *user, UNUSED_ARG(const char *old_nick), UNUSED_ARG(void *extra)) { struct gag_entry *gag; @@ -6799,7 +6931,7 @@ opserv_alert_check_nick(struct userNode *user, UNUSED_ARG(const char *old_nick)) /* Gag them if appropriate (and only if). */ user->modes &= ~FLAGS_GAGGED; for (gag = gagList; gag; gag = gag->next) { - if (user_matches_glob(user, gag->mask, MATCH_USENICK)) { + if (user_matches_glob(user, gag->mask, MATCH_USENICK, 0)) { gag_helper_func(user, NULL); break; } @@ -6807,7 +6939,7 @@ opserv_alert_check_nick(struct userNode *user, UNUSED_ARG(const char *old_nick)) } static void -opserv_staff_alert(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle)) +opserv_staff_alert(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle), UNUSED_ARG(void *extra)) { const char *type; @@ -6964,6 +7096,10 @@ static MODCMD_FUNC(cmd_addalert) reaction = REACT_VERSION; else if(!irccasecmp(argv[2], "mark")) reaction = REACT_MARK; + else if(!irccasecmp(argv[2], "noticeuser")) + reaction = REACT_NOTICEUSER; + else if(!irccasecmp(argv[2], "msguser")) + reaction = REACT_MSGUSER; else { reply("OSMSG_UNKNOWN_REACTION", argv[2]); return 0; @@ -6973,7 +7109,7 @@ static MODCMD_FUNC(cmd_addalert) expire = now + ParseInterval(argv[4]); if (!svccmd_can_invoke(user, opserv_service->bot, subcmd, channel, SVCCMD_NOISY) - || !opserv_add_user_alert(user, name, reaction, unsplit_string(argv + (expire ? 5 : 3), argc - (expire ? 5 : 3), NULL), 0, expire)) { + || !opserv_add_user_alert(user, name, reaction, unsplit_string(argv + (expire ? 5 : 3), argc - (expire ? 5 : 3), NULL), 0, expire, argv[2])) { reply("OSMSG_ALERT_ADD_FAILED"); return 0; } @@ -7210,7 +7346,7 @@ opserv_db_init(void) { } static void -opserv_db_cleanup(void) +opserv_db_cleanup(UNUSED_ARG(void* extra)) { unsigned int nn; @@ -7219,7 +7355,7 @@ opserv_db_cleanup(void) free_string_list(opserv_bad_words); dict_delete(opserv_exempt_channels); dict_delete(opserv_trusted_hosts); - unreg_del_user_func(opserv_user_cleanup); + unreg_del_user_func(opserv_user_cleanup, NULL); dict_delete(opserv_hostinfo_dict); dict_delete(opserv_nick_based_alerts); dict_delete(opserv_account_based_alerts); @@ -7248,6 +7384,8 @@ init_opserv(const char *nick) opserv_define_func("ACCESS", cmd_access, 0, 0, 0); opserv_define_func("ADDALERT", cmd_addalert, 800, 0, 4); opserv_define_func("ADDALERT NOTICE", NULL, 0, 0, 0); + opserv_define_func("ADDALERT NOTICEUSER", NULL, 0, 0, 0); + opserv_define_func("ADDALERT MSGUSER", NULL, 0, 0, 0); opserv_define_func("ADDALERT SILENT", NULL, 900, 0, 0); opserv_define_func("ADDALERT GLINE", NULL, 900, 0, 0); opserv_define_func("ADDALERT SHUN", NULL, 900, 0, 0); @@ -7359,6 +7497,8 @@ init_opserv(const char *nick) 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); + opserv_define_func("TRACE PRIVMSG", NULL, 0, 0, 0); + opserv_define_func("TRACE NOTICE", NULL, 0, 0, 0); opserv_define_func("TRACE DOMAINS", NULL, 0, 0, 0); opserv_define_func("TRACE GLINE", NULL, 600, 0, 0); opserv_define_func("TRACE SHUN", NULL, 600, 0, 0); @@ -7390,14 +7530,14 @@ init_opserv(const char *nick) opserv_waiting_connections = dict_new(); dict_set_free_data(opserv_waiting_connections, opserv_free_waiting_connection); - reg_new_user_func(opserv_new_user_check); - reg_nick_change_func(opserv_alert_check_nick); - reg_del_user_func(opserv_user_cleanup); - reg_new_channel_func(opserv_channel_check); - reg_del_channel_func(opserv_channel_delete); - reg_join_func(opserv_join_check); - reg_auth_func(opserv_staff_alert); - reg_auth_func(opserv_alert_check_account); + reg_new_user_func(opserv_new_user_check, NULL); + reg_nick_change_func(opserv_alert_check_nick, NULL); + reg_del_user_func(opserv_user_cleanup, NULL); + reg_new_channel_func(opserv_channel_check, NULL); + reg_del_channel_func(opserv_channel_delete, NULL); + reg_join_func(opserv_join_check, NULL); + reg_auth_func(opserv_staff_alert, NULL); + reg_auth_func(opserv_alert_check_account, NULL); reg_notice_func(opserv, opserv_notice_handler); opserv_db_init(); @@ -7415,6 +7555,6 @@ init_opserv(const char *nick) /* start the karma timer, using the saved one if available */ routing_karma_timer(dict_find(opserv_routing_plan_options, "KARMA_TIMER", NULL)); - reg_exit_func(opserv_db_cleanup); + reg_exit_func(opserv_db_cleanup, NULL); message_register_table(msgtab); }