{ "OSMSG_CHANINFO_USER_COUNT", "Users (%d):" },
{ "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." },
{ NULL, NULL }
};
char *issuer;
char *reason;
unsigned long limit;
- time_t issued;
- time_t expires;
+ unsigned long issued;
+ unsigned long expires;
};
struct gag_entry {
char *mask;
char *owner;
char *reason;
- time_t expires;
+ unsigned long expires;
struct gag_entry *next;
};
typedef struct opservDiscrim {
struct chanNode *channels[DISCRIM_MAX_CHANS];
unsigned int channel_count;
- char *mask_nick, *mask_ident, *mask_host, *mask_info, *server, *reason, *accountmask;
+ char *mask_nick, *mask_ident, *mask_host, *mask_info, *server, *reason, *notice_target, *accountmask;
irc_in_addr_t ip_mask;
unsigned long limit;
- time_t min_ts, max_ts;
+ unsigned long min_ts, max_ts;
unsigned int min_level, max_level, domain_depth, duration, min_clones, min_channels, max_channels;
unsigned char ip_mask_bits;
unsigned int match_opers : 1, match_trusted : 1, option_log : 1;
free(alert);
}
-#define opserv_debug(format...) do { if (opserv_conf.debug_channel) send_channel_notice(opserv_conf.debug_channel , opserv , ## format); } while (0)
-#define opserv_alert(format...) do { if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel , opserv , ## format); } while (0)
+#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)
+#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)
+#endif
/* A lot of these commands are very similar to what ChanServ can do,
* but OpServ can do them even on channels that aren't registered.
const char *fmt;
struct banNode *ban;
struct modeNode *moden;
+ time_t feh;
unsigned int n;
reply("OSMSG_CHANINFO_HEADER", channel->name);
fmt = user_find_message(user, "OSMSG_CHANINFO_TIMESTAMP");
- strftime(buffer, sizeof(buffer), fmt, gmtime(&channel->timestamp));
+ feh = channel->timestamp;
+ strftime(buffer, sizeof(buffer), fmt, gmtime(&feh));
send_message_type(4, user, cmd->parent->bot, "%s", buffer);
irc_make_chanmode(channel, buffer);
if (channel->bad_channel)
reply("OSMSG_CHANINFO_MODES", buffer);
if (channel->topic_time) {
fmt = user_find_message(user, "OSMSG_CHANINFO_TOPIC");
- strftime(buffer, sizeof(buffer), fmt, gmtime(&channel->topic_time));
+ feh = channel->topic_time;
+ strftime(buffer, sizeof(buffer), fmt, gmtime(&feh));
send_message_type(4, user, cmd->parent->bot, buffer, channel->topic_nick, channel->topic);
} else {
irc_fetchtopic(cmd->parent->bot, channel->name);
fmt = user_find_message(user, "OSMSG_CHANINFO_BAN");
for (n = 0; n < channel->banlist.used; n++) {
ban = channel->banlist.list[n];
- strftime(buffer, sizeof(buffer), fmt, localtime(&ban->set));
+ feh = ban->set;
+ strftime(buffer, sizeof(buffer), fmt, localtime(&feh));
send_message_type(4, user, cmd->parent->bot, buffer, ban->ban, ban->who);
}
}
offset = 3;
}
if(duration && duration != opserv_conf.block_gline_duration) {
- // We require more access when the duration is not the default block duration.
+ /* We require more access when the duration is not the default block duration. */
gline_cmd = dict_find(cmd->parent->commands, "gline", NULL);
if(!gline_cmd)
{
return 1;
}
+static MODCMD_FUNC(cmd_forcekick)
+{
+ struct userNode *target;
+ char *reason;
+
+ if (argc < 3) {
+ reason = alloca(strlen(OSMSG_KICK_REQUESTED)+strlen(user->nick)+1);
+ sprintf(reason, OSMSG_KICK_REQUESTED, user->nick);
+ } else {
+ reason = unsplit_string(argv+2, argc-2, NULL);
+ }
+ target = GetUserH(argv[1]);
+ if (!target) {
+ reply("MSG_NICK_UNKNOWN", argv[1]);
+ return 0;
+ }
+ if (!GetUserMode(channel, target)) {
+ reply("OSMSG_NOT_ON_CHANNEL", target->nick, channel->name);
+ return 0;
+ }
+ if (IsLocal(target)) {
+ reply("OSMSG_FORCEKICK_LOCAL", target->nick);
+ return 0;
+ }
+ irc_kick(cmd->parent->bot, target, channel, reason);
+ return 1;
+}
+
static MODCMD_FUNC(cmd_kickall)
{
unsigned int limit, n, inchan;
reply("OSMSG_NOT_ON_CHANNEL", cmd->parent->bot->nick, channel->name);
return 0;
}
- reason = (argc < 3) ? "Leaving." : unsplit_string(argv+2, argc-2, NULL);
+ reason = (argc < 2) ? "Leaving." : unsplit_string(argv+1, argc-1, NULL);
reply("OSMSG_LEAVING", channel->name);
DelChannelUser(cmd->parent->bot, channel, reason, 0);
return 1;
static MODCMD_FUNC(cmd_stats_max) {
- reply("OSMSG_MAX_CLIENTS", max_clients, asctime(localtime(&max_clients_time)));
+ time_t feh;
+ feh = max_clients_time;
+ reply("OSMSG_MAX_CLIENTS", max_clients, asctime(localtime(&feh)));
return 1;
}
static MODCMD_FUNC(cmd_stats_uptime) {
extern int lines_processed;
- extern time_t boot_time;
+ extern unsigned long boot_time;
double kernel_time;
double user_time;
char uptime[INTERVALLEN];
dict_foreach(opserv_channel_alerts, alert_check_user, user);
- if (channel->bad_channel) {
+ 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);
if (channel->name[0] != '#')
DelUser(user, opserv, 1, "OSMSG_ILLEGAL_KILL_REASON");
}
static void
-opserv_add_trusted_host(const char *ipaddr, unsigned int limit, const char *issuer, time_t issued, time_t expires, const char *reason)
+opserv_add_trusted_host(const char *ipaddr, unsigned int limit, const char *issuer, unsigned long issued, unsigned long expires, const char *reason)
{
struct trusted_host *th;
th = calloc(1, sizeof(*th));
if (!self->uplink) return 0;
discrim = calloc(1, sizeof(*discrim));
discrim->limit = dict_size(clients);
- discrim->max_level = ~0;
- discrim->max_ts = now;
+ discrim->max_level = UINT_MAX;
+ discrim->max_ts = ULONG_MAX;
discrim->max_channels = INT_MAX;
discrim->authed = -1;
discrim->info_space = -1;
}
unsigned int
-gag_create(const char *mask, const char *owner, const char *reason, time_t expires)
+gag_create(const char *mask, const char *owner, const char *reason, unsigned long expires)
{
struct gag_entry *gag;
{
struct record_data *rd = data;
char *owner, *reason, *expstr;
- time_t expires;
+ unsigned long expires;
owner = database_get_data(rd->d.object, KEY_OWNER, RECDB_QSTRING);
reason = database_get_data(rd->d.object, KEY_REASON, RECDB_QSTRING);
{
struct record_data *rd = data;
const char *limit, *str, *reason, *issuer;
- time_t issued, expires;
+ unsigned long issued, expires;
if (rd->type == RECDB_QSTRING) {
/* old style host by itself */
static MODCMD_FUNC(cmd_settime)
{
const char *srv_name_mask = "*";
- time_t new_time = now;
+ unsigned long new_time = now;
if (argc > 1)
srv_name_mask = argv[1];
discrim = calloc(1, sizeof(*discrim));
discrim->limit = 250;
- discrim->max_level = ~0;
- discrim->max_ts = INT_MAX;
+ discrim->max_level = UINT_MAX;
+ discrim->max_ts = ULONG_MAX;
discrim->domain_depth = 2;
discrim->max_channels = INT_MAX;
discrim->authed = -1;
} else if (irccasecmp(argv[i], "reason") == 0) {
discrim->reason = strdup(unsplit_string(argv+i+1, argc-i-1, NULL));
i = argc;
+ } else if (irccasecmp(argv[i], "notice_target") == 0 || irccasecmp(argv[i], "target") == 0) {
+ if (!IsChannelName(argv[i + 1])) {
+ send_message(user, opserv, "MSG_NOT_CHANNEL_NAME");
+ goto fail;
+ }
+ discrim->notice_target = argv[++i];
} else if (irccasecmp(argv[i], "last") == 0) {
discrim->min_ts = now - ParseInterval(argv[++i]);
} else if ((irccasecmp(argv[i], "linked") == 0)
|| (target->handle_info
&& target->handle_info->opserv_level > user->handle_info->opserv_level));
- // If we don't need an ip check or want to hit opers or the the "cheap" check already disqualified the target, we are done.
+ /* If we don't need an ip check or want to hit opers or the the "cheap" check already disqualified the target, we are done. */
if (!check_ip || match_opers || !is_victim)
return is_victim;
char *name, *topic;
unsigned int min_users, max_users;
- time_t min_ts, max_ts;
+ unsigned long min_ts, max_ts;
unsigned int limit;
} *cdiscrim_t;
static cdiscrim_t opserv_cdiscrim_create(struct userNode *user, unsigned int argc, char *argv[]);
static unsigned int opserv_cdiscrim_search(cdiscrim_t discrim, cdiscrim_search_func dsf, void *data);
-static time_t
+static unsigned long
smart_parse_time(const char *str) {
/* If an interval-style string is given, treat as time before now.
* If it's all digits, treat directly as a Unix timestamp. */
- return str[strspn(str, "0123456789")] ? (time_t)(now - ParseInterval(str)) : (time_t)atoi(str);
+ return str[strspn(str, "0123456789")] ? (now - ParseInterval(str)) : strtoul(str, NULL, 0);
}
static cdiscrim_t
discrim = calloc(1, sizeof(*discrim));
discrim->limit = 25;
- discrim->max_users = ~0;
- /* So, time_t is frequently signed. Fun. */
- discrim->max_ts = (1ul << (CHAR_BIT * sizeof(time_t) - 1)) - 1;
+ discrim->max_users = UINT_MAX;
+ discrim->max_ts = ULONG_MAX;
for (i = 0; i < argc; i++) {
/* Assume all criteria require arguments. */
log_module(OS_LOG, LOG_ERROR, "Invalid reaction type %d for alert %s.", alert->reaction, key);
/* fall through to REACT_NOTICE case */
case REACT_NOTICE:
- opserv_alert("Alert $b%s$b triggered by user $b%s$b!%s@%s (%s).", key, user->nick, user->ident, user->hostname, alert->discrim->reason);
+ opserv_custom_alert(alert->discrim->notice_target, "Alert $b%s$b triggered by user $b%s$b!%s@%s (%s).", key, user->nick, user->ident, user->hostname, alert->discrim->reason);
break;
}
return 0;
opserv_define_func("JUMP", cmd_jump, 900, 0, 2);
opserv_define_func("JUPE", cmd_jupe, 900, 0, 4);
opserv_define_func("KICK", cmd_kick, 100, 2, 2);
+ opserv_define_func("FORCEKICK", cmd_forcekick, 800, 2, 2);
opserv_define_func("KICKALL", cmd_kickall, 400, 2, 0);
opserv_define_func("KICKBAN", cmd_kickban, 100, 2, 2);
opserv_define_func("KICKBANALL", cmd_kickbanall, 450, 2, 0);