/* proto-p10.c - IRC protocol output
- * Copyright 2000-2004 srvx Development Team
+ * Copyright 2000-2006 srvx Development Team
*
* This file is part of srvx.
*
unsigned int value;
memset(ip, 0, 6 * sizeof(ip->in6[0]));
value = base64toint(input, 6);
+ if (value)
+ ip->in6[5] = htons(65535);
ip->in6[6] = htons(value >> 16);
ip->in6[7] = htons(value & 65535);
} else {
static void
irc_p10_ntop(char *output, const irc_in_addr_t *ip)
{
- if (irc_in_addr_is_ipv4(*ip)) {
+ if (!irc_in_addr_is_valid(*ip)) {
+ strcpy(output, "AAAAAA");
+ } else if (irc_in_addr_is_ipv4(*ip)) {
unsigned int in4;
in4 = (ntohs(ip->in6[6]) << 16) | ntohs(ip->in6[7]);
inttobase64(output, in4, 6);
irc_user(struct userNode *user)
{
char b64ip[25];
- if (!user)
+ if (!user || IsDummy(user))
return;
irc_p10_ntop(b64ip, &user->ip);
if (user->modes) {
modes[modelen++] = 'w';
if (IsService(user))
modes[modelen++] = 'k';
- if (IsServNotice(user))
- modes[modelen++] = 's';
if (IsDeaf(user))
modes[modelen++] = 'd';
if (IsGlobal(user))
modes[modelen++] = 'g';
- if (IsHelperIrcu(user))
- modes[modelen++] = 'h';
if (IsHiddenHost(user))
modes[modelen++] = 'x';
modes[modelen] = 0;
putsock("%s " P10_WALLCHOPS " %s :%s", from->numeric, to, message);
}
+static int
+deliver_to_dummy(struct userNode *source, struct userNode *dest, const char *message, int type)
+{
+ unsigned int num;
+
+ if (!dest || !IsDummy(dest) || !IsLocal(dest))
+ return 0;
+ num = dest->num_local;
+ switch (type) {
+ default:
+ if ((num < num_notice_funcs) && notice_funcs[num])
+ notice_funcs[num](source, dest, message, 0);
+ break;
+ case 1:
+ if ((num < num_privmsg_funcs) && privmsg_funcs[num])
+ privmsg_funcs[num](source, dest, message, 0);
+ break;
+ }
+ return 1;
+}
+
void
irc_notice(struct userNode *from, const char *to, const char *message)
{
- putsock("%s " P10_NOTICE " %s :%s", from->numeric, to, message);
+ if (to[0] != '#' && to[0] != '$'
+ && !deliver_to_dummy(from, GetUserN(to), message, 0))
+ putsock("%s " P10_NOTICE " %s :%s", from->numeric, to, message);
}
void
irc_notice_user(struct userNode *from, struct userNode *to, const char *message)
{
- putsock("%s " P10_NOTICE " %s :%s", from->numeric, to->numeric, message);
+ if (!deliver_to_dummy(from, to, message, 0))
+ putsock("%s " P10_NOTICE " %s :%s", from->numeric, to->numeric, message);
}
void
irc_privmsg(struct userNode *from, const char *to, const char *message)
{
- putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to, message);
+ if (to[0] != '#' && to[0] != '$'
+ && !deliver_to_dummy(from, GetUserN(to), message, 1))
+ putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to, message);
}
void
void
irc_gline(struct server *srv, struct gline *gline)
{
- putsock("%s " P10_GLINE " %s +%s %ld :%s",
- self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, gline->reason);
+ if (gline->lastmod)
+ putsock("%s " P10_GLINE " %s +%s %ld %ld :%s",
+ self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, gline->lastmod, gline->reason);
+ else
+ putsock("%s " P10_GLINE " %s +%s %ld :%s",
+ self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, gline->reason);
}
void
static CMD_FUNC(cmd_num_gline)
{
+ time_t lastmod;
if (argc < 6)
return 0;
- gline_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0);
+ lastmod = (argc > 5) ? strtoul(argv[5], NULL, 0) : 0;
+ gline_add(origin, argv[3], atoi(argv[4])-now, argv[argc - 1], now, lastmod, 0);
return 1;
}
return 1;
}
-static CMD_FUNC(cmd_part)
-{
- struct userNode *user;
-
- if (argc < 2)
- return 0;
- user = GetUserH(origin);
- if (!user)
- return 0;
- parse_foreach(argv[1], part_helper, NULL, NULL, NULL, user);
- return 1;
-}
-
static CMD_FUNC(cmd_kick)
{
if (argc < 3)
static CMD_FUNC(cmd_gline)
{
+ time_t lastmod;
+
if (argc < 3)
return 0;
if (argv[2][0] == '+') {
if (argc < 5)
return 0;
- gline_add(origin, argv[2]+1, strtoul(argv[3], NULL, 0), argv[argc-1], now, 0);
+ lastmod = (argc > 5) ? strtoul(argv[5], NULL, 0) : 0;
+ gline_add(origin, argv[2]+1, strtoul(argv[3], NULL, 0), argv[argc-1], now, lastmod, 0);
return 1;
} else if (argv[2][0] == '-') {
gline_remove(argv[2]+1, 0);
}
struct userNode *
-AddService(const char *nick, const char *modes, const char *desc, const char *hostname)
+AddLocalUser(const char *nick, const char *ident, const char *hostname, const char *desc, const char *modes)
{
char numeric[COMBO_NUMERIC_LEN+1];
int local_num = get_local_numeric();
time_t timestamp = now;
struct userNode *old_user = GetUserH(nick);
+ if (!modes)
+ modes = "+oik";
if (old_user) {
if (IsLocal(old_user))
return old_user;
if (!hostname)
hostname = self->name;
make_numeric(self, local_num, numeric);
- return AddUser(self, nick, nick, hostname, modes ? modes : "+oik", numeric, desc, now, "AAAAAA");
+ return AddUser(self, nick, ident, hostname, modes, numeric, desc, now, "AAAAAA");
}
struct userNode *
AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, time_t timestamp, const char *realip)
{
struct userNode *oldUser, *uNode;
- unsigned int n, ignore_user;
+ unsigned int n, ignore_user, dummy;
if ((strlen(numeric) < 3) || (strlen(numeric) > 5)) {
log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): numeric %s wrong length!", uplink, nick, numeric);
return NULL;
}
- if (!is_valid_nick(nick)) {
+ dummy = modes && modes[0] == '*';
+ if (dummy) {
+ ++modes;
+ } else if (!is_valid_nick(nick)) {
log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): invalid nickname detected.", uplink, nick);
return NULL;
}
uNode->num_local = base64toint(numeric+strlen(uNode->uplink->numeric), 3) & uNode->uplink->num_mask;
uNode->uplink->users[uNode->num_local] = uNode;
mod_usermode(uNode, modes);
+ if (dummy)
+ uNode->modes |= FLAGS_DUMMY;
if (ignore_user)
return uNode;
/* remove user from all channels */
while (user->channels.used > 0)
- DelChannelUser(user, user->channels.list[user->channels.used-1]->channel, false, 0);
+ DelChannelUser(user, user->channels.list[user->channels.used-1]->channel, NULL, false);
/* Call these in reverse order so ChanServ can update presence
information before NickServ nukes the handle_info. */
irc_kill(killer, user, why);
}
+ if (IsLocal(user)) {
+ unsigned int num = user->num_local;
+ if (num < num_privmsg_funcs)
+ privmsg_funcs[num] = NULL;
+ if (num < num_notice_funcs)
+ notice_funcs[num] = NULL;
+ }
+
modeList_clean(&user->channels);
/* We don't free them, in case we try to privmsg them or something
* (like when a stupid oper kills themself). We just put them onto
userList_remove(&curr_opers, user);
}
break;
- case 'O': do_user_mode(FLAGS_LOCOP); break;
case 'i': do_user_mode(FLAGS_INVISIBLE);
if (add)
invis_clients++;
invis_clients--;
break;
case 'w': do_user_mode(FLAGS_WALLOP); break;
- case 's': do_user_mode(FLAGS_SERVNOTICE); break;
case 'd': do_user_mode(FLAGS_DEAF); break;
case 'k': do_user_mode(FLAGS_SERVICE); break;
case 'g': do_user_mode(FLAGS_GLOBAL); break;
- case 'h': do_user_mode(FLAGS_HELPER); break;
case 'x': do_user_mode(FLAGS_HIDDEN_HOST); break;
case 'r':
if (*word) {
char *oplevel_str;
int oplevel;
+ if (in_arg >= argc)
+ goto error;
oplevel_str = strchr(modes[in_arg], ':');
if (oplevel_str)
{