#define KEY_DNR_EXPIRE_FREQ "dnr_expire_freq"
#define KEY_MAX_CHAN_USERS "max_chan_users"
#define KEY_MAX_CHAN_BANS "max_chan_bans"
+#define KEY_MIN_TIME_BANS "min_time_bans"
#define KEY_NICK "nick"
#define KEY_OLD_CHANSERV_NAME "old_chanserv_name"
#define KEY_8BALL_RESPONSES "8ball"
#define KEY_EXPIRES "expires"
#define KEY_TRIGGERED "triggered"
-#define CHANNEL_DEFAULT_FLAGS (CHANNEL_OFFCHANNEL | CHANNEL_UNREVIEWED)
+#define CHANNEL_DEFAULT_FLAGS (CHANNEL_UNREVIEWED)
#define CHANNEL_PRESERVED_FLAGS (CHANNEL_UNREVIEWED)
#define CHANNEL_DEFAULT_OPTIONS "lmoooanpcnat"
{ NULL, NULL }
};
+#define CSMSG_ALERT_REGISTERED "%s registered to %s by %s."
+#define CSMSG_ALERT_UNREGISTERED "%s %s"
+
/* eject_user and unban_user flags */
#define ACTION_KICK 0x0001
#define ACTION_BAN 0x0002
DECLARE_LIST(dnrList, struct do_not_register *);
DEFINE_LIST(dnrList, struct do_not_register *)
+#define chanserv_notice(target, format...) send_message(target , chanserv , ## format)
+#define chanserv_oper_message(format...) do { if(chanserv_conf.oper_channel) send_channel_message(chanserv_conf.oper_channel , chanserv , ## format); } while(0)
+
static int eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, char *argv[], struct svccmd *cmd, int action);
struct userNode *chanserv;
unsigned int max_owned;
unsigned int max_chan_users;
unsigned int max_chan_bans;
+ unsigned int min_time_bans;
unsigned int max_userinfo_length;
unsigned int revoke_mode_a;
const char *new_channel_authed;
const char *new_channel_unauthed;
const char *new_channel_msg;
+
+ struct chanNode *oper_channel;
} chanserv_conf;
struct listData
channel->channel->channel_info = NULL;
dict_delete(channel->notes);
- sprintf(msgbuf, "%s %s", channel->channel->name, reason);
if(!IsSuspended(channel))
DelChannelUser(chanserv, channel->channel, msgbuf, 0);
- global_message(MESSAGE_RECIPIENT_OPERS | MESSAGE_RECIPIENT_HELPERS, msgbuf);
+
+ chanserv_oper_message(CSMSG_ALERT_UNREGISTERED, channel->channel->name, reason);
UnlockChannel(channel->channel);
free(channel);
registered_channels--;
else
reply("CSMSG_REG_SUCCESS", channel->name);
- sprintf(reason, "%s registered to %s by %s.", channel->name, handle->handle, user->handle_info->handle);
- global_message(MESSAGE_RECIPIENT_OPERS | MESSAGE_RECIPIENT_HELPERS, reason);
+ chanserv_oper_message(CSMSG_ALERT_REGISTERED, channel->name, handle->handle, user->handle_info->handle);
return 1;
}
{
duration = ParseInterval(argv[2]);
- if(duration < 15)
+ if(duration < chanserv_conf.min_time_bans)
{
reply("CSMSG_DURATION_TOO_LOW");
free(ban);
ary[1] = uData->handle->handle;
if(uData->present)
ary[2] = "Here";
+ else if(HANDLE_FLAGGED(uData->handle, NETWORK))
+ ary[2] = "Here";
else if(!uData->seen)
ary[2] = "Never";
else
ary[2] = strdup(ary[2]);
if(IsUserSuspended(uData))
ary[3] = "Suspended";
+ else if(HANDLE_FLAGGED(uData->handle, OPER))
+ ary[3] = "Operator";
+ else if(HANDLE_FLAGGED(uData->handle, HELPING))
+ ary[3] = "Staff";
+ else if(HANDLE_FLAGGED(uData->handle, NETWORK))
+ ary[3] = "Network";
else if(HANDLE_FLAGGED(uData->handle, FROZEN))
ary[3] = "Vacation";
else if(HANDLE_FLAGGED(uData->handle, BOT))
if(!isdigit(topic[pos]))
break;
}
- if(advtopic_index < 0 || advtopic_index > MAXADVTOPICENTRIES)
+ if(advtopic_index < 0 || advtopic_index >= MAXADVTOPICENTRIES)
{
//invalid id!
- reply("CSMSG_ADVTOPIC_INVALID_ID", advtopic_index);
+ reply("CSMSG_ADVTOPIC_INVALID_ID", advtopic_index+1);
return 0;
}
if(cData->advtopic[advtopic_index])
new_topic[dpos++] = *ptr; //is % again
break;
}
- ptr--;
advtopic_index--; //no zero base
if(!cData->advtopic[advtopic_index])
break; //just leave it empty
break;
case '\\':
ptr++; /* and fall through */
+ if(!*ptr) break;
default:
new_topic[dpos++] = *ptr;
+ ptr++;
break;
}
- ptr++;
}
} else {
while((tchar = topic_mask[pos++]) && (dpos <= TOPICLEN))
return 1;
}
+static void
+chanserv_expire_user_suspension(void *data)
+{
+ struct userData *target = data;
+
+ target->expires = 0;
+ target->flags &= ~USER_SUSPENDED;
+}
+
static CHANSERV_FUNC(cmd_suspend)
{
struct handle_info *hi;
struct userData *actor, *real_actor, *target;
unsigned int override = 0;
+ time_t expiry;
- REQUIRE_PARAMS(2);
+ REQUIRE_PARAMS(3);
if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
actor = GetChannelUser(channel->channel_info, user->handle_info);
real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
}
if(!real_actor || target->access >= real_actor->access)
override = CMD_LOG_OVERRIDE;
+ if(!strcmp(argv[2], "0"))
+ expiry = 0;
+ else
+ {
+ unsigned int duration;
+ if(!(duration = ParseInterval(argv[2])))
+ {
+ reply("MSG_INVALID_DURATION", argv[2]);
+ return 0;
+ }
+ expiry = now + duration;
+ }
+
+ target->expires = expiry;
+
+ if(target->expires)
+ timeq_add(target->expires, chanserv_expire_user_suspension, target);
+
target->flags |= USER_SUSPENDED;
reply("CSMSG_USER_SUSPENDED", hi->handle, channel->name);
return 1 | override;
}
if(!real_actor || target->access >= real_actor->access)
override = CMD_LOG_OVERRIDE;
+ timeq_del(target->expires, chanserv_expire_user_suspension, target, 0);
target->flags &= ~USER_SUSPENDED;
scan_user_presence(target, NULL);
reply("CSMSG_USER_UNSUSPENDED", hi->handle, channel->name);
chanserv_conf.max_chan_users = str ? atoi(str) : 512;
str = database_get_data(conf_node, KEY_MAX_CHAN_BANS, RECDB_QSTRING);
chanserv_conf.max_chan_bans = str ? atoi(str) : 512;
+ str = database_get_data(conf_node, KEY_MIN_TIME_BANS, RECDB_QSTRING);
+ chanserv_conf.min_time_bans = str ? atoi(str) : 5;
str = database_get_data(conf_node, KEY_MAX_USERINFO_LENGTH, RECDB_QSTRING);
chanserv_conf.max_userinfo_length = str ? atoi(str) : 400;
str = database_get_data(conf_node, KEY_NICK, RECDB_QSTRING);
chanserv_conf.old_ban_names = strlist;
str = database_get_data(conf_node, "off_channel", RECDB_QSTRING);
off_channel = str ? atoi(str) : 0;
+
+ str = database_get_data(conf_node, "oper_chan", RECDB_QSTRING);
+ if(str)
+ {
+ chanserv_conf.oper_channel = AddChannel(str, now, "+tinms", NULL);
+ }
+ else
+ {
+ chanserv_conf.oper_channel = NULL;
+ }
}
static void
{
struct handle_info *handle;
struct userData *uData;
- char *seen, *inf, *flags, *voted, *votefor;
+ char *seen, *inf, *flags, *voted, *votefor, *expires;
unsigned long last_seen;
unsigned short access_level;
seen = database_get_data(rd->d.object, KEY_SEEN, RECDB_QSTRING);
last_seen = seen ? strtoul(seen, NULL, 0) : now;
flags = database_get_data(rd->d.object, KEY_FLAGS, RECDB_QSTRING);
+ expires = database_get_data(rd->d.object, KEY_EXPIRES, RECDB_QSTRING);
voted = database_get_data(rd->d.object, KEY_VOTE_VOTED, RECDB_QSTRING);
votefor = database_get_data(rd->d.object, KEY_VOTE_VOTEDFOR, RECDB_QSTRING);
handle = get_handle_info(key);
uData = add_channel_user(chan, handle, access_level, last_seen, inf);
uData->flags = flags ? strtoul(flags, NULL, 0) : 0;
+ uData->expires = expires ? (signed)strtoul(expires, NULL, 0) : 0;
+
+ if((uData->flags & USER_SUSPENDED) && uData->expires)
+ {
+ if(uData->expires > now)
+ timeq_add(uData->expires, chanserv_expire_user_suspension, uData);
+ else
+ uData->flags &= ~USER_SUSPENDED;
+ }
if(chan->vote) {
uData->voted = voted ? strtoul(voted, NULL, 0) : 0;
uData->votefor = votefor ? strtoul(votefor, NULL, 0) : 0;
saxdb_write_int(ctx, KEY_SEEN, uData->seen);
if(uData->flags)
saxdb_write_int(ctx, KEY_FLAGS, uData->flags);
+ if(uData->expires)
+ saxdb_write_int(ctx, KEY_EXPIRES, uData->expires);
if(uData->channel->vote && uData->voted)
saxdb_write_int(ctx, KEY_VOTE_VOTED, uData->voted);
if(uData->channel->vote && uData->votefor)