X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/d76ed9a966ee3d955c8ef00ecc02e643c2005e2e..e42487a5d0733c361fce6607ed7f01025f650aa1:/src/opserv.c diff --git a/src/opserv.c b/src/opserv.c index a63c0e1..1fb15bd 100644 --- a/src/opserv.c +++ b/src/opserv.c @@ -1,7 +1,7 @@ /* opserv.c - IRC Operator assistance service * Copyright 2000-2004 srvx Development Team * - * This file is part of srvx. + * This file is part of x3. * * srvx is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -86,6 +86,7 @@ #define OSMSG_GAG_REQUESTED "Gag requested by %s." static const struct message_entry msgtab[] = { + { "OSMSG_BAR", "----------------------------------------" }, { "OSMSG_USER_ACCESS_IS", "$b%s$b (account $b%s$b) has %d access." }, { "OSMSG_LEVEL_TOO_LOW", "You lack sufficient access to use this command." }, { "OSMSG_NEED_CHANNEL", "You must specify a channel for $b%s$b." }, @@ -101,6 +102,8 @@ static const struct message_entry msgtab[] = { { "OSMSG_NO_CHANNEL_MODES", "Channel $b%s$b had no modes to clear." }, { "OSMSG_DEOP_DONE", "Deopped the requested lusers." }, { "OSMSG_DEOPALL_DONE", "Deopped everyone on $b%s$b." }, + { "OSMSG_DEHOP_DONE", "Dehalfopped the requested lusers." }, + { "OSMSG_DEHOPALL_DONE", "Dehalfopped everyone on $b%s$b." }, { "OSMSG_NO_DEBUG_CHANNEL", "No debug channel has been configured." }, { "OSMSG_INVITE_DONE", "Invited $b%s$b to $b%s$b." }, { "OSMSG_ALREADY_THERE", "You are already in $b%s$b." }, @@ -112,6 +115,8 @@ static const struct message_entry msgtab[] = { { "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." }, { "OSMSG_WHOIS_IDENT", "%s (%s@%s) from %d.%d.%d.%d" }, { "OSMSG_WHOIS_NICK", "Nick : %s" }, { "OSMSG_WHOIS_HOST", "Host : %s@%s" }, @@ -155,8 +160,12 @@ static const struct message_entry msgtab[] = { { "OSMSG_MAX_CLIENTS", "Max clients: %d at %s" }, { "OSMSG_NETWORK_INFO", "Total users: %d (%d invisible, %d opers)" }, { "OSMSG_RESERVED_LIST", "List of reserved nicks:" }, - { "OSMSG_TRUSTED_LIST", "List of trusted hosts:" }, - { "OSMSG_HOST_IS_TRUSTED", "%s (%s; set %s ago by %s; expires %s: %s)" }, + { "OSMSG_TRUSTED_LIST", "$bTrusted Hosts$b" }, + { "OSMSG_TRUSTED_LIST_HEADER", "IP Address Limit By Time" }, + { "OSMSG_HOST_IS_TRUSTED", "%-15s %-5s %-10s set %s ago, expires %s" }, + { "OSMSG_HOST_IS_TRUSTED_DESC", " Reason: %s" }, + { "OSMSG_TRUSTED_LIST_BAR", "----------------------------------------" }, + { "OSMSG_TRUSTED_LIST_END", "----------End of Trusted Hosts----------" }, { "OSMSG_HOST_NOT_TRUSTED", "%s does not have a special trust." }, { "OSMSG_UPTIME_STATS", "Uptime: %s (%u lines processed, CPU time %.2fu/%.2fs)" }, { "OSMSG_LINE_DUMPED", "Raw line sent." }, @@ -177,6 +186,7 @@ static const struct message_entry msgtab[] = { { "OSMSG_CLONE_JOINED", "$b%s$b has joined $b%s$b." }, { "OSMSG_CLONE_PARTED", "$b%s$b has left $b%s$b." }, { "OSMSG_OPS_GIVEN", "I have given ops in $b%s$b to $b%s$b." }, + { "OSMSG_HOPS_GIVEN", "I have given halfops in $b%s$b to $b%s$b." }, { "OSMSG_CLONE_SAID", "$b%s$b has spoken to $b%s$b." }, { "OSMSG_UNKNOWN_SUBCOMMAND", "$b%s$b is not a valid subcommand of $b%s$b." }, { "OSMSG_UNKNOWN_OPTION", "$b%s$b has not been set." }, @@ -191,6 +201,10 @@ static const struct message_entry msgtab[] = { { "OSMSG_SETTIME_SUCCESS", "Set time for servers named like $b%s$b." }, { "OSMSG_BAD_ACTION", "Unrecognized trace action $b%s$b." }, { "OSMSG_USER_SEARCH_RESULTS", "The following users were found:" }, + { "OSMSG_USER_SEARCH_HEADER", "Nick User@Host (Account)" }, + { "OSMSG_USER_SEARCH_BAR", "-------------------------------------------" }, + { "OSMSG_USER_SEARCH_COUNT", "There were %4u matches" }, + { "OSMSG_USER_SEARCH_COUNT_BAR", "------------ Found %4u matches -----------" }, { "OSMSG_CHANNEL_SEARCH_RESULTS", "The following channels were found:" }, { "OSMSG_GLINE_SEARCH_RESULTS", "The following glines were found:" }, { "OSMSG_LOG_SEARCH_RESULTS", "The following log entries were found:" }, @@ -209,8 +223,12 @@ static const struct message_entry msgtab[] = { { "OSMSG_ADDED_ALERT", "Added alert named $b%s$b." }, { "OSMSG_REMOVED_ALERT", "Removed alert named $b%s$b." }, { "OSMSG_NO_SUCH_ALERT", "No alert named $b%s$b could be found." }, - { "OSMSG_ALERT_IS", "%s (by %s, reaction %s): %s" }, - { "OSMSG_ALERTS_LIST", "Current $O alerts:" }, + { "OSMSG_ALERTS_LIST", "$bCurrent $O alerts$b" }, + { "OSMSG_ALERTS_BAR", "----------------------------------------------" }, + { "OSMSG_ALERTS_HEADER", "Name Action (by Oper)" }, + { "OSMSG_ALERTS_DESC", " Criteria: %s" }, + { "OSMSG_ALERT_IS", "$b%-20s$b %-6s (by %s)" }, + { "OSMSG_ALERT_END", "----------------End of Alerts-----------------" }, { "OSMSG_REHASH_COMPLETE", "Completed rehash of configuration database." }, { "OSMSG_REHASH_FAILED", "Rehash of configuration database failed, previous configuration is intact." }, { "OSMSG_REOPEN_COMPLETE", "Closed and reopened all log files." }, @@ -221,6 +239,7 @@ static const struct message_entry msgtab[] = { { "OSMSG_SERVER_JUPED", "Added new jupe server %s." }, { "OSMSG_SERVER_NOT_JUPE", "That server is not a juped server." }, { "OSMSG_SERVER_UNJUPED", "Server jupe removed." }, + /* { "OSMSG_WARN_ADDED", "Added channel activity warning for $b%s$b (%s)" }, { "OSMSG_WARN_EXISTS", "Channel activity warning for $b%s$b already exists." }, { "OSMSG_WARN_DELETED", "Removed channel activity warning for $b%s$b" }, @@ -228,6 +247,7 @@ static const struct message_entry msgtab[] = { { "OSMSG_WARN_LISTSTART", "Channel activity warnings:" }, { "OSMSG_WARN_LISTENTRY", "%s (%s)" }, { "OSMSG_WARN_LISTEND", "End of activity warning list." }, + */ { "OSMSG_UPLINK_CONNECTING", "Establishing connection with %s (%s:%d)." }, { "OSMSG_CURRENT_UPLINK", "$b%s$b is already the current uplink." }, { "OSMSG_INVALID_UPLINK", "$b%s$b is not a valid uplink name." }, @@ -244,19 +264,21 @@ static const struct message_entry msgtab[] = { { "OSMSG_CHANINFO_TOPIC_UNKNOWN", "Topic: (none / not gathered)" }, { "OSMSG_CHANINFO_BAN_COUNT", "Bans (%d):" }, { "OSMSG_CHANINFO_BAN", "%%s by %%s (%a %b %d %H:%M:%S %Y)" }, + { "OSMSG_CHANINFO_EXEMPT_COUNT", "Exempts (%d):" }, + { "OSMSG_CHANINFO_EXEMPT", "%%s by %%s (%a %b %d %H:%M:%S %Y)" }, { "OSMSG_CHANINFO_MANY_USERS", "%d users (\"/msg $S %s %s users\" for the list)" }, { "OSMSG_CHANINFO_USER_COUNT", "Users (%d):" }, { "OSMSG_CSEARCH_CHANNEL_INFO", "%s [%d users] %s %s" }, { NULL, NULL } }; -#define OPSERV_SYNTAX() svccmd_send_help(user, opserv, cmd) +#define OPSERV_SYNTAX() svccmd_send_help_brief(user, opserv, cmd) typedef int (*discrim_search_func)(struct userNode *match, void *extra); struct userNode *opserv; -static dict_t opserv_chan_warn; /* data is char* */ +/*static dict_t opserv_chan_warn; */ /* data is char* */ 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 */ @@ -402,16 +424,16 @@ static MODCMD_FUNC(cmd_ban) change.argc = 1; change.args[0].mode = MODE_BAN; if (is_ircmask(argv[1])) - change.args[0].hostmask = strdup(argv[1]); + change.args[0].u.hostmask = strdup(argv[1]); else if ((victim = GetUserH(argv[1]))) - change.args[0].hostmask = generate_hostmask(victim, 0); + change.args[0].u.hostmask = generate_hostmask(victim, 0); else { reply("OSMSG_INVALID_IRCMASK", argv[1]); return 0; } modcmd_chanmode_announce(&change); - reply("OSMSG_ADDED_BAN", change.args[0].hostmask, channel->name); - free((char*)change.args[0].hostmask); + reply("OSMSG_ADDED_BAN", change.args[0].u.hostmask, channel->name); + free((char*)change.args[0].u.hostmask); return 1; } @@ -420,6 +442,7 @@ static MODCMD_FUNC(cmd_chaninfo) char buffer[MAXLEN]; const char *fmt; struct banNode *ban; + struct exemptNode *exempt; struct modeNode *moden; unsigned int n; @@ -449,6 +472,15 @@ static MODCMD_FUNC(cmd_chaninfo) send_message_type(4, user, cmd->parent->bot, buffer, ban->ban, ban->who); } } + if (channel->exemptlist.used) { + reply("OSMSG_CHANINFO_EXEMPT_COUNT", channel->exemptlist.used); + fmt = user_find_message(user, "OSMSG_CHANINFO_EXEMPT"); + for (n = 0; n < channel->exemptlist.used; n++) { + exempt = channel->exemptlist.list[n]; + strftime(buffer, sizeof(buffer), fmt, localtime(&exempt->set)); + send_message_type(4, user, cmd->parent->bot, buffer, exempt->exempt, exempt->who); + } + } if ((argc < 2) && (channel->members.used >= 50)) { /* early out unless they ask for users */ reply("OSMSG_CHANINFO_MANY_USERS", channel->members.used, argv[0], channel->name); @@ -460,19 +492,26 @@ static MODCMD_FUNC(cmd_chaninfo) if (moden->modes & MODE_CHANOP) send_message_type(4, user, cmd->parent->bot, " @%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname); } + for (n=0; nmembers.used; n++) { + moden = channel->members.list[n]; + if ((moden->modes & (MODE_CHANOP|MODE_HALFOP|MODE_VOICE)) == MODE_HALFOP) + send_message_type(4, user, cmd->parent->bot, " %s%s (%s@%s)", "%", moden->user->nick, moden->user->ident, moden->user->hostname); + } for (n=0; nmembers.used; n++) { moden = channel->members.list[n]; - if ((moden->modes & (MODE_CHANOP|MODE_VOICE)) == MODE_VOICE) + if ((moden->modes & (MODE_CHANOP|MODE_HALFOP|MODE_VOICE)) == MODE_VOICE) send_message_type(4, user, cmd->parent->bot, " +%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname); } for (n=0; nmembers.used; n++) { moden = channel->members.list[n]; - if ((moden->modes & (MODE_CHANOP|MODE_VOICE)) == 0) + if ((moden->modes & (MODE_CHANOP|MODE_HALFOP|MODE_VOICE)) == 0) send_message_type(4, user, cmd->parent->bot, " %s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname); } return 1; } +/* This command has been replaced by 'alert notice channel #foo' */ +/* static MODCMD_FUNC(cmd_warn) { char *reason, *message; @@ -513,6 +552,7 @@ static MODCMD_FUNC(cmd_unwarn) reply("OSMSG_WARN_DELETED", argv[1]); return 1; } +*/ static MODCMD_FUNC(cmd_clearbans) { @@ -522,9 +562,11 @@ static MODCMD_FUNC(cmd_clearbans) change = mod_chanmode_alloc(channel->banlist.used); for (ii=0; iibanlist.used; ii++) { change->args[ii].mode = MODE_REMOVE | MODE_BAN; - change->args[ii].hostmask = channel->banlist.list[ii]->ban; + change->args[ii].u.hostmask = strdup(channel->banlist.list[ii]->ban); } modcmd_chanmode_announce(change); + for (ii=0; iiargc; ++ii) + free((char*)change->args[ii].u.hostmask); mod_chanmode_free(change); reply("OSMSG_CLEARBANS_DONE", channel->name); return 1; @@ -559,7 +601,7 @@ static MODCMD_FUNC(cmd_deop) || !(mn->modes & MODE_CHANOP)) continue; change->args[count].mode = MODE_REMOVE | MODE_CHANOP; - change->args[count++].member = mn; + change->args[count++].u.member = mn; } if (count) { change->argc = count; @@ -570,6 +612,31 @@ static MODCMD_FUNC(cmd_deop) return 1; } +static MODCMD_FUNC(cmd_dehop) +{ + struct mod_chanmode *change; + unsigned int arg, count; + + change = mod_chanmode_alloc(argc-1); + for (arg = 1, count = 0; arg < argc; ++arg) { + struct userNode *victim = GetUserH(argv[arg]); + struct modeNode *mn; + if (!victim || IsService(victim) + || !(mn = GetUserMode(channel, victim)) + || !(mn->modes & MODE_HALFOP)) + continue; + change->args[count].mode = MODE_REMOVE | MODE_HALFOP; + change->args[count++].u.member = mn; + } + if (count) { + change->argc = count; + modcmd_chanmode_announce(change); + } + mod_chanmode_free(change); + reply("OSMSG_DEHOP_DONE"); + return 1; +} + static MODCMD_FUNC(cmd_deopall) { struct mod_chanmode *change; @@ -581,7 +648,7 @@ static MODCMD_FUNC(cmd_deopall) if (IsService(mn->user) || !(mn->modes & MODE_CHANOP)) continue; change->args[count].mode = MODE_REMOVE | MODE_CHANOP; - change->args[count++].member = mn; + change->args[count++].u.member = mn; } if (count) { change->argc = count; @@ -592,6 +659,28 @@ static MODCMD_FUNC(cmd_deopall) return 1; } +static MODCMD_FUNC(cmd_dehopall) +{ + struct mod_chanmode *change; + unsigned int ii, count; + + change = mod_chanmode_alloc(channel->members.used); + for (ii = count = 0; ii < channel->members.used; ++ii) { + struct modeNode *mn = channel->members.list[ii]; + if (IsService(mn->user) || !(mn->modes & MODE_HALFOP)) + continue; + change->args[count].mode = MODE_REMOVE | MODE_HALFOP; + change->args[count++].u.member = mn; + } + if (count) { + change->argc = count; + modcmd_chanmode_announce(change); + } + mod_chanmode_free(change); + reply("OSMSG_DEHOPALL_DONE", channel->name); + return 1; +} + static MODCMD_FUNC(cmd_rehash) { extern char *services_config; @@ -856,6 +945,8 @@ opserv_ison(struct userNode *tell, struct userNode *target, const char *message) } if (mn->modes & MODE_CHANOP) buff[count++] = '@'; + if (mn->modes & MODE_HALFOP) + buff[count++] = '%'; if (mn->modes & MODE_VOICE) buff[count++] = '+'; memcpy(buff+count, mn->channel->name, here_len); @@ -886,7 +977,7 @@ static MODCMD_FUNC(cmd_inviteme) return 0; } if (GetUserMode(opserv_conf.debug_channel, user)) { - reply("OSMSG_ALREADY_THERE", channel->name); + reply("OSMSG_ALREADY_THERE", opserv_conf.debug_channel->name); return 0; } irc_invite(cmd->parent->bot, target, opserv_conf.debug_channel); @@ -913,7 +1004,7 @@ static MODCMD_FUNC(cmd_join) reply("MSG_NOT_CHANNEL_NAME"); return 0; } else if (!(channel = GetChannel(argv[1]))) { - channel = AddChannel(argv[1], now, NULL, NULL); + channel = AddChannel(argv[1], now, NULL, NULL, NULL); AddChannelUser(bot, channel)->modes |= MODE_CHANOP; } else if (GetUserMode(channel, bot)) { reply("OSMSG_ALREADY_JOINED", channel->name); @@ -923,7 +1014,7 @@ static MODCMD_FUNC(cmd_join) mod_chanmode_init(&change); change.argc = 1; change.args[0].mode = MODE_CHANOP; - change.args[0].member = AddChannelUser(bot, channel); + change.args[0].u.member = AddChannelUser(bot, channel); modcmd_chanmode_announce(&change); } irc_fetchtopic(bot, channel->name); @@ -968,7 +1059,7 @@ static MODCMD_FUNC(cmd_kickall) struct mod_chanmode change; mod_chanmode_init(&change); change.args[0].mode = MODE_CHANOP; - change.args[0].member = AddChannelUser(bot, channel); + change.args[0].u.member = AddChannelUser(bot, channel); modcmd_chanmode_announce(&change); } if (argc < 2) { @@ -1018,7 +1109,7 @@ static MODCMD_FUNC(cmd_kickban) mod_chanmode_init(&change); change.argc = 1; change.args[0].mode = MODE_BAN; - change.args[0].hostmask = mask = generate_hostmask(target, 0); + change.args[0].u.hostmask = mask = generate_hostmask(target, 0); modcmd_chanmode_announce(&change); KickChannelUser(target, channel, cmd->parent->bot, reason); free(mask); @@ -1038,15 +1129,16 @@ static MODCMD_FUNC(cmd_kickbanall) if (!(inchan = GetUserMode(channel, bot) ? 1 : 0)) { change = mod_chanmode_alloc(2); change->args[0].mode = MODE_CHANOP; - change->args[0].member = AddChannelUser(bot, channel); + change->args[0].u.member = AddChannelUser(bot, channel); change->args[1].mode = MODE_BAN; - change->args[1].hostmask = "*!*@*"; + change->args[1].u.hostmask = "*!*@*"; } else { change = mod_chanmode_alloc(1); change->args[0].mode = MODE_BAN; - change->args[0].hostmask = "*!*@*"; + change->args[0].u.hostmask = "*!*@*"; } modcmd_chanmode_announce(change); + mod_chanmode_free(change); if (argc < 2) { reason = alloca(strlen(OSMSG_KICK_REQUESTED)+strlen(user->nick)+1); sprintf(reason, OSMSG_KICK_REQUESTED, user->nick); @@ -1116,7 +1208,7 @@ static MODCMD_FUNC(cmd_op) if (mn->modes & MODE_CHANOP) continue; change->args[count].mode = MODE_CHANOP; - change->args[count++].member = mn; + change->args[count++].u.member = mn; } if (count) { change->argc = count; @@ -1127,6 +1219,33 @@ static MODCMD_FUNC(cmd_op) return 1; } +static MODCMD_FUNC(cmd_hop) +{ + struct mod_chanmode *change; + unsigned int arg, count; + + change = mod_chanmode_alloc(argc-1); + for (arg = 1, count = 0; arg < argc; ++arg) { + struct userNode *victim; + struct modeNode *mn; + if (!(victim = GetUserH(argv[arg]))) + continue; + if (!(mn = GetUserMode(channel, victim))) + continue; + if (mn->modes & MODE_HALFOP) + continue; + change->args[count].mode = MODE_HALFOP; + change->args[count++].u.member = mn; + } + if (count) { + change->argc = count; + modcmd_chanmode_announce(change); + } + mod_chanmode_free(change); + reply("OSMSG_HOP_DONE"); + return 1; +} + static MODCMD_FUNC(cmd_opall) { struct mod_chanmode *change; @@ -1138,7 +1257,7 @@ static MODCMD_FUNC(cmd_opall) if (mn->modes & MODE_CHANOP) continue; change->args[count].mode = MODE_CHANOP; - change->args[count++].member = mn; + change->args[count++].u.member = mn; } if (count) { change->argc = count; @@ -1149,6 +1268,28 @@ static MODCMD_FUNC(cmd_opall) return 1; } +static MODCMD_FUNC(cmd_hopall) +{ + struct mod_chanmode *change; + unsigned int ii, count; + + change = mod_chanmode_alloc(channel->members.used); + for (ii = count = 0; ii < channel->members.used; ++ii) { + struct modeNode *mn = channel->members.list[ii]; + if (mn->modes & MODE_HALFOP) + continue; + change->args[count].mode = MODE_HALFOP; + change->args[count++].u.member = mn; + } + if (count) { + change->argc = count; + modcmd_chanmode_announce(change); + } + mod_chanmode_free(change); + reply("OSMSG_HOPALL_DONE", channel->name); + return 1; +} + static MODCMD_FUNC(cmd_whois) { struct userNode *target; @@ -1159,10 +1300,8 @@ static MODCMD_FUNC(cmd_whois) if (argv[1][0] == '*') target = GetUserN(argv[1]+1); else - target = GetUserH(argv[1]); -#else - target = GetUserH(argv[1]); #endif + target = GetUserH(argv[1]); if (!target) { reply("MSG_NICK_UNKNOWN", argv[1]); return 0; @@ -1180,9 +1319,14 @@ static MODCMD_FUNC(cmd_whois) if (IsOper(target)) buffer[bpos++] = 'o'; if (IsGlobal(target)) buffer[bpos++] = 'g'; if (IsServNotice(target)) buffer[bpos++] = 's'; - if (IsHelperIrcu(target)) buffer[bpos++] = 'h'; + + // 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 (IsGagged(target)) buffer_cat(" (gagged)"); if (IsRegistering(target)) buffer_cat(" (registered account)"); @@ -1211,7 +1355,7 @@ static MODCMD_FUNC(cmd_unban) mod_chanmode_init(&change); change.argc = 1; change.args[0].mode = MODE_REMOVE | MODE_BAN; - change.args[0].hostmask = argv[1]; + change.args[0].u.hostmask = argv[1]; modcmd_chanmode_announce(&change); reply("OSMSG_UNBAN_DONE", channel->name); return 1; @@ -1225,10 +1369,10 @@ static MODCMD_FUNC(cmd_voiceall) change = mod_chanmode_alloc(channel->members.used); for (ii = count = 0; ii < channel->members.used; ++ii) { struct modeNode *mn = channel->members.list[ii]; - if (mn->modes & (MODE_CHANOP|MODE_VOICE)) + if (mn->modes & (MODE_CHANOP|MODE_HALFOP|MODE_VOICE)) continue; change->args[count].mode = MODE_VOICE; - change->args[count++].member = mn; + change->args[count++].u.member = mn; } if (count) { change->argc = count; @@ -1250,7 +1394,7 @@ static MODCMD_FUNC(cmd_devoiceall) if (!(mn->modes & MODE_VOICE)) continue; change->args[count].mode = MODE_REMOVE | MODE_VOICE; - change->args[count++].member = mn; + change->args[count++].u.member = mn; } if (count) { change->argc = count; @@ -1267,8 +1411,10 @@ static MODCMD_FUNC(cmd_stats_bad) { char buffer[400]; /* Show the bad word list.. */ + /* TODO: convert nonprinting chars like bold to $b etc in a usable way */ for (ii=end=0; iiused; ii++) { here_len = strlen(opserv_bad_words->list[ii]); + /* If the line is full output it & start again */ if ((end + here_len + 2) > sizeof(buffer)) { buffer[end] = 0; reply("OSMSG_BADWORD_LIST", buffer); @@ -1428,6 +1574,10 @@ static MODCMD_FUNC(cmd_stats_trusted) { struct trusted_host *th; char length[INTERVALLEN], issued[INTERVALLEN], limit[32]; + reply("OSMSG_TRUSTED_LIST"); + reply("OSMSG_TRUSTED_LIST_BAR"); + reply("OSMSG_TRUSTED_LIST_HEADER"); + reply("OSMSG_TRUSTED_LIST_BAR"); if (argc > 1) { th = dict_find(opserv_trusted_hosts, argv[1], NULL); if (th) { @@ -1436,19 +1586,18 @@ static MODCMD_FUNC(cmd_stats_trusted) { if (th->expires) intervalString(length, th->expires - now, user->handle_info); if (th->limit) - sprintf(limit, "limit %lu", th->limit); + sprintf(limit, "%lu", th->limit); reply("OSMSG_HOST_IS_TRUSTED", th->ipaddr, - (th->limit ? limit : "no limit"), - (th->issued ? issued : "some time"), + (th->limit ? limit : "none"), (th->issuer ? th->issuer : ""), - (th->expires ? length : "never"), - (th->reason ? th->reason : "")); + (th->issued ? issued : "some time"), + (th->expires ? length : "never")); + reply("OSMSG_HOST_IS_TRUSTED_DESC", (th->reason ? th->reason : "")); } else { reply("OSMSG_HOST_NOT_TRUSTED", argv[1]); } } else { - reply("OSMSG_TRUSTED_LIST"); for (it = dict_first(opserv_trusted_hosts); it; it = iter_next(it)) { th = iter_data(it); if (th->issued) @@ -1456,15 +1605,16 @@ static MODCMD_FUNC(cmd_stats_trusted) { if (th->expires) intervalString(length, th->expires - now, user->handle_info); if (th->limit) - sprintf(limit, "limit %lu", th->limit); + sprintf(limit, "%lu", th->limit); reply("OSMSG_HOST_IS_TRUSTED", iter_key(it), - (th->limit ? limit : "no limit"), - (th->issued ? issued : "some time"), + (th->limit ? limit : "none"), (th->issuer ? th->issuer : ""), - (th->expires ? length : "never"), - (th->reason ? th->reason : "")); + (th->issued ? issued : "some time"), + (th->expires ? length : "never")); + reply("OSMSG_HOST_IS_TRUSTED_DESC", (th->reason ? th->reason : "")); } } + reply("OSMSG_TRUSTED_LIST_END"); return 1; } @@ -1510,6 +1660,9 @@ static MODCMD_FUNC(cmd_stats_alerts) { const char *reaction; reply("OSMSG_ALERTS_LIST"); + reply("OSMSG_ALERTS_BAR"); + reply("OSMSG_ALERTS_HEADER"); + reply("OSMSG_ALERTS_BAR"); for (it = dict_first(opserv_user_alerts); it; it = iter_next(it)) { alert = iter_data(it); switch (alert->reaction) { @@ -1518,8 +1671,10 @@ static MODCMD_FUNC(cmd_stats_alerts) { case REACT_GLINE: reaction = "gline"; break; default: reaction = ""; break; } - reply("OSMSG_ALERT_IS", iter_key(it), alert->owner, reaction, alert->text_discrim); + reply("OSMSG_ALERT_IS", iter_key(it), reaction, alert->owner); + reply("OSMSG_ALERTS_DESC", alert->text_discrim); } + reply("OSMSG_ALERT_END"); return 1; } @@ -1569,6 +1724,7 @@ static MODCMD_FUNC(cmd_stats_timeq) { return 1; } +/* static MODCMD_FUNC(cmd_stats_warn) { dict_iterator_t it; @@ -1578,12 +1734,35 @@ static MODCMD_FUNC(cmd_stats_warn) { reply("OSMSG_WARN_LISTEND"); return 1; } +*/ + +#if defined(WITH_MALLOC_X3) +static MODCMD_FUNC(cmd_stats_memory) { + extern unsigned long alloc_count, alloc_size; + send_message_type(MSG_TYPE_NOXLATE, user, cmd->parent->bot, + "%u allocations totalling %u bytes.", + alloc_count, alloc_size); + return 1; +} +#elif defined(WITH_MALLOC_SLAB) +static MODCMD_FUNC(cmd_stats_memory) { + extern unsigned long slab_alloc_count, slab_count, slab_alloc_size; + extern unsigned long big_alloc_count, big_alloc_size; + send_message_type(MSG_TYPE_NOXLATE, user, cmd->parent->bot, + "%u allocations in %u slabs totalling %u bytes.", + slab_alloc_count, slab_count, slab_alloc_size); +/* send_message_type(MSG_TYPE_NOXLATE, user, cmd->parent->bot, + "%u big allocations totalling %u bytes.", + */ + return 1; +} +#endif static MODCMD_FUNC(cmd_dump) { - char linedup[MAXLEN], *original; + char linedup[MAXLEN], original[MAXLEN]; - original = unsplit_string(argv+1, argc-1, NULL); + unsplit_string(argv+1, argc-1, original); safestrncpy(linedup, original, sizeof(linedup)); /* assume it's only valid IRC if we can parse it */ if (parse_line(linedup, 1)) { @@ -1596,9 +1775,9 @@ static MODCMD_FUNC(cmd_dump) static MODCMD_FUNC(cmd_raw) { - char linedup[MAXLEN], *original; + char linedup[MAXLEN], original[MAXLEN]; - original = unsplit_string(argv+1, argc-1, NULL); + unsplit_string(argv+1, argc-1, original); safestrncpy(linedup, original, sizeof(linedup)); /* Try to parse the line before sending it; if it's too wrong, * maybe it will core us instead of our uplink. */ @@ -1802,9 +1981,9 @@ opserv_shutdown_channel(struct chanNode *channel, const char *reason) change = mod_chanmode_alloc(2); change->modes_set = MODE_SECRET | MODE_INVITEONLY; change->args[0].mode = MODE_CHANOP; - change->args[0].member = AddChannelUser(opserv, channel); + change->args[0].u.member = AddChannelUser(opserv, channel); change->args[1].mode = MODE_BAN; - change->args[1].hostmask = "*!*@*"; + change->args[1].u.hostmask = "*!*@*"; mod_chanmode_announce(opserv, channel, change); mod_chanmode_free(change); for (nn=channel->members.used; nn>0; ) { @@ -1819,17 +1998,19 @@ opserv_shutdown_channel(struct chanNode *channel, const char *reason) static void opserv_channel_check(struct chanNode *newchan) { - char *warning; + /*char *warning; */ if (!newchan->join_policer.params) { newchan->join_policer.last_req = now; newchan->join_policer.params = opserv_conf.join_policer_params; } + /* if ((warning = dict_find(opserv_chan_warn, newchan->name, NULL))) { char message[MAXLEN]; snprintf(message, sizeof(message), "Channel activity warning for channel %s: %s", newchan->name, warning); global_message(MESSAGE_RECIPIENT_OPERS, message); } + */ /* Wait until the join check to shut channels down. */ newchan->bad_channel = opserv_bad_channel(newchan->name); @@ -1883,7 +2064,7 @@ opserv_join_check(struct modeNode *mNode) if (!GetUserMode(channel, opserv)) { /* If we aren't in the channel, join it. */ change.args[0].mode = MODE_CHANOP; - change.args[0].member = AddChannelUser(opserv, channel); + change.args[0].u.member = AddChannelUser(opserv, channel); change.argc++; } if (!(channel->modes & MODE_MODERATED)) @@ -2255,7 +2436,7 @@ static MODCMD_FUNC(cmd_clone) channel = GetChannel(argv[3]); if (!irccasecmp(argv[1], "JOIN")) { if (!channel - && !(channel = AddChannel(argv[3], now, NULL, NULL))) { + && !(channel = AddChannel(argv[3], now, NULL, NULL, NULL))) { reply("MSG_CHANNEL_UNKNOWN", argv[3]); return 0; } @@ -2285,8 +2466,8 @@ static MODCMD_FUNC(cmd_clone) mod_chanmode_init(&change); change.argc = 1; change.args[0].mode = MODE_CHANOP; - change.args[0].member = GetUserMode(channel, clone); - if (!change.args[0].member) { + change.args[0].u.member = GetUserMode(channel, clone); + if (!change.args[0].u.member) { reply("OSMSG_NOT_ON_CHANNEL", clone->nick, channel->name); return 0; } @@ -2294,6 +2475,24 @@ static MODCMD_FUNC(cmd_clone) reply("OSMSG_OPS_GIVEN", channel->name, clone->nick); return 1; } + if (!irccasecmp(argv[1], "HOP")) { + struct mod_chanmode change; + if (!channel) { + reply("MSG_CHANNEL_UNKNOWN", argv[3]); + return 0; + } + mod_chanmode_init(&change); + change.argc = 1; + change.args[0].mode = MODE_HALFOP; + change.args[0].u.member = GetUserMode(channel, clone); + if (!change.args[0].u.member) { + reply("OSMSG_NOT_ON_CHANNEL", clone->nick, channel->name); + return 0; + } + modcmd_chanmode_announce(&change); + reply("OSMSG_HOPS_GIVEN", channel->name, clone->nick); + return 1; + } if (argc < 5) { reply("MSG_MISSING_PARAMS", argv[1]); OPSERV_SYNTAX(); @@ -2546,19 +2745,21 @@ opserv_add_user_alert(struct userNode *req, const char *name, opserv_alert_react return alert; } +/* static int add_chan_warn(const char *key, void *data, UNUSED_ARG(void *extra)) { struct record_data *rd = data; char *reason = GET_RECORD_QSTRING(rd); - /* i hope this can't happen */ + * i hope this can't happen * if (!reason) reason = "No Reason"; dict_insert(opserv_chan_warn, strdup(key), strdup(reason)); return 0; } +*/ static int add_user_alert(const char *key, void *data, UNUSED_ARG(void *extra)) @@ -2676,8 +2877,10 @@ opserv_saxdb_read(struct dict *conf_db) dict_foreach(object, add_gag_helper, NULL); if ((object = database_get_data(conf_db, KEY_ALERTS, RECDB_OBJECT))) dict_foreach(object, add_user_alert, NULL); +/* if ((object = database_get_data(conf_db, KEY_WARN, RECDB_OBJECT))) dict_foreach(object, add_chan_warn, NULL); +*/ return 0; } @@ -2743,6 +2946,7 @@ opserv_saxdb_write(struct saxdb_context *ctx) saxdb_end_record(ctx); } /* channel warnings */ + /* if (dict_size(opserv_chan_warn)) { saxdb_start_record(ctx, KEY_WARN, 0); for (it = dict_first(opserv_chan_warn); it; it = iter_next(it)) { @@ -2750,6 +2954,7 @@ opserv_saxdb_write(struct saxdb_context *ctx) } saxdb_end_record(ctx); } + */ /* alerts */ if (dict_size(opserv_user_alerts)) { saxdb_start_record(ctx, KEY_ALERTS, 1); @@ -2954,11 +3159,17 @@ opserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[], in case '#': goto find_channel; case '-': - discrim->chan_no_modes |= MODE_CHANOP | MODE_VOICE; + discrim->chan_no_modes |= MODE_CHANOP | MODE_HALFOP | MODE_VOICE; break; case '+': discrim->chan_req_modes |= MODE_VOICE; discrim->chan_no_modes |= MODE_CHANOP; + discrim->chan_no_modes |= MODE_HALFOP; + break; + case '%': + discrim->chan_req_modes |= MODE_HALFOP; + discrim->chan_no_modes |= MODE_CHANOP; + discrim->chan_no_modes |= MODE_VOICE; break; case '@': discrim->chan_req_modes |= MODE_CHANOP; @@ -2977,7 +3188,7 @@ opserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[], in send_message(user, opserv, "MSG_CHANNEL_UNKNOWN", argv[i]); goto fail; } else { - discrim->channel = AddChannel(argv[i]+j, now, NULL, NULL); + discrim->channel = AddChannel(argv[i]+j, now, NULL, NULL, NULL); } } LockChannel(discrim->channel); @@ -3171,9 +3382,9 @@ trace_print_func(struct userNode *match, void *extra) { struct discrim_and_source *das = extra; if (match->handle_info) { - send_message_type(4, das->source, opserv, "%s!%s@%s %s", match->nick, match->ident, match->hostname, match->handle_info->handle); + send_message_type(4, das->source, opserv, "%-15s\002 \002%10s\002@\002%s (%s)", match->nick, match->ident, match->hostname, match->handle_info->handle); } else { - send_message_type(4, das->source, opserv, "%s!%s@%s", match->nick, match->ident, match->hostname); + send_message_type(4, das->source, opserv, "%-15s\002 \002%10s\002@\002%s", match->nick, match->ident, match->hostname); } return 0; } @@ -3357,7 +3568,12 @@ static MODCMD_FUNC(cmd_trace) return 0; if (action == trace_print_func) - reply("OSMSG_USER_SEARCH_RESULTS"); + { + reply("OSMSG_USER_SEARCH_RESULTS"); + reply("OSMSG_USER_SEARCH_BAR"); + reply("OSMSG_USER_SEARCH_HEADER"); + reply("OSMSG_USER_SEARCH_BAR"); + } else if (action == trace_count_func) das.discrim->limit = INT_MAX; else if ((action == trace_gline_func) && !das.discrim->duration) @@ -3375,9 +3591,14 @@ static MODCMD_FUNC(cmd_trace) dict_foreach(das.dict, opserv_show_hostinfo, &das); if (matches) - reply("MSG_MATCH_COUNT", matches); + { + if(action == trace_print_func) + reply("OSMSG_USER_SEARCH_COUNT_BAR", matches); + else + reply("OSMSG_USER_SEARCH_COUNT", matches); + } else - reply("MSG_NO_MATCHES"); + reply("MSG_NO_MATCHES"); if (das.discrim->channel) UnlockChannel(das.discrim->channel); @@ -3903,7 +4124,7 @@ opserv_conf_read(void) str2 = database_get_data(conf_node, KEY_DEBUG_CHANNEL_MODES, RECDB_QSTRING); if (!str2) str2 = "+tinms"; - opserv_conf.debug_channel = AddChannel(str, now, str2, NULL); + opserv_conf.debug_channel = AddChannel(str, now, str2, NULL, NULL); AddChannelUser(opserv, opserv_conf.debug_channel)->modes |= MODE_CHANOP; } else { opserv_conf.debug_channel = NULL; @@ -3913,7 +4134,7 @@ opserv_conf_read(void) str2 = database_get_data(conf_node, KEY_ALERT_CHANNEL_MODES, RECDB_QSTRING); if (!str2) str2 = "+tns"; - opserv_conf.alert_channel = AddChannel(str, now, str2, NULL); + opserv_conf.alert_channel = AddChannel(str, now, str2, NULL, NULL); AddChannelUser(opserv, opserv_conf.alert_channel)->modes |= MODE_CHANOP; } else { opserv_conf.alert_channel = NULL; @@ -3923,7 +4144,7 @@ opserv_conf_read(void) str2 = database_get_data(conf_node, KEY_STAFF_AUTH_CHANNEL_MODES, RECDB_QSTRING); if (!str2) str2 = "+timns"; - opserv_conf.staff_auth_channel = AddChannel(str, now, str2, NULL); + opserv_conf.staff_auth_channel = AddChannel(str, now, str2, NULL, NULL); AddChannelUser(opserv, opserv_conf.staff_auth_channel)->modes |= MODE_CHANOP; } else { opserv_conf.staff_auth_channel = NULL; @@ -3973,10 +4194,13 @@ opserv_db_init(void) { opserv_trusted_hosts = dict_new(); dict_set_free_data(opserv_trusted_hosts, free_trusted_host); /* set up opserv_chan_warn dict */ + +/* alert trace notice channel #x replaces warnings dict_delete(opserv_chan_warn); opserv_chan_warn = dict_new(); dict_set_free_keys(opserv_chan_warn, free); dict_set_free_data(opserv_chan_warn, free); +*/ /* set up opserv_user_alerts */ dict_delete(opserv_channel_alerts); opserv_channel_alerts = dict_new(); @@ -4000,7 +4224,7 @@ opserv_db_cleanup(void) { unsigned int nn; - dict_delete(opserv_chan_warn); +/* dict_delete(opserv_chan_warn); */ dict_delete(opserv_reserved_nick_dict); free_string_list(opserv_bad_words); dict_delete(opserv_exempt_channels); @@ -4022,8 +4246,10 @@ void init_opserv(const char *nick) { OS_LOG = log_register_type("OpServ", "file:opserv.log"); - if (nick) - opserv = AddService(nick, "Oper Services", NULL); + if (nick) { + const char *modes = conf_get_data("services/opserv/modes", RECDB_QSTRING); + opserv = AddService(nick, modes ? modes : NULL, "Oper Services", NULL); + } conf_register_reload(opserv_conf_read); memset(level_strings, 0, sizeof(level_strings)); @@ -4052,6 +4278,8 @@ init_opserv(const char *nick) opserv_define_func("DELTRUST", cmd_deltrust, 800, 0, 2); opserv_define_func("DEOP", cmd_deop, 100, 2, 2); opserv_define_func("DEOPALL", cmd_deopall, 400, 2, 0); + opserv_define_func("DEHOP", cmd_dehop, 100, 2, 2); + opserv_define_func("DEHOPALL", cmd_dehopall, 400, 2, 0); opserv_define_func("DEVOICEALL", cmd_devoiceall, 300, 2, 0); opserv_define_func("DIE", cmd_die, 900, 0, 2); opserv_define_func("DUMP", cmd_dump, 999, 0, 2); @@ -4075,6 +4303,8 @@ init_opserv(const char *nick) opserv_define_func("MODE", cmd_mode, 100, 2, 2); opserv_define_func("OP", cmd_op, 100, 2, 2); opserv_define_func("OPALL", cmd_opall, 400, 2, 0); + opserv_define_func("HOP", cmd_hop, 100, 2, 2); + opserv_define_func("HOPALL", cmd_hopall, 400, 2, 0); opserv_define_func("PART", cmd_part, 601, 0, 2); opserv_define_func("QUERY", cmd_query, 0, 0, 0); opserv_define_func("RAW", cmd_raw, 999, 0, 2); @@ -4099,7 +4329,10 @@ init_opserv(const char *nick) opserv_define_func("STATS TRUSTED", cmd_stats_trusted, 0, 0, 0); opserv_define_func("STATS UPLINK", cmd_stats_uplink, 0, 0, 0); opserv_define_func("STATS UPTIME", cmd_stats_uptime, 0, 0, 0); - opserv_define_func("STATS WARN", cmd_stats_warn, 0, 0, 0); +/* opserv_define_func("STATS WARN", cmd_stats_warn, 0, 0, 0); */ +#if defined(WITH_MALLOC_X3) || defined(WITH_MALLOC_SLAB) + opserv_define_func("STATS MEMORY", cmd_stats_memory, 0, 0, 0); +#endif 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); @@ -4113,9 +4346,9 @@ init_opserv(const char *nick) modcmd_register(opserv_module, "GTRACE UNGLINE", NULL, 0, 0, "template", "ungline", NULL); opserv_define_func("UNJUPE", cmd_unjupe, 900, 0, 2); opserv_define_func("UNRESERVE", cmd_unreserve, 800, 0, 2); - opserv_define_func("UNWARN", cmd_unwarn, 800, 0, 0); +/* opserv_define_func("UNWARN", cmd_unwarn, 800, 0, 0); */ opserv_define_func("VOICEALL", cmd_voiceall, 300, 2, 0); - opserv_define_func("WARN", cmd_warn, 800, 0, 2); +/* opserv_define_func("WARN", cmd_warn, 800, 0, 2); */ opserv_define_func("WHOIS", cmd_whois, 0, 0, 2); opserv_reserved_nick_dict = dict_new(); @@ -4126,7 +4359,7 @@ init_opserv(const char *nick) 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_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);