/* proto-p10.c - IRC protocol output
- * Copyright 2000-2006 srvx Development Team
+ * Copyright 2000-2008 srvx Development Team
*
* This file is part of srvx.
*
static privmsg_func_t *notice_funcs;
static unsigned int num_notice_funcs;
static struct dict *unbursted_channels;
-static char *his_servername;
-static char *his_servercomment;
+static const char *his_servername;
+static const char *his_servercomment;
static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, unsigned long timestamp, const char *realip);
}
void
-irc_account(struct userNode *user, const char *stamp)
+irc_account(struct userNode *user, const char *stamp, unsigned long timestamp, unsigned long serial)
{
- putsock("%s " P10_ACCOUNT " %s %s", self->numeric, user->numeric, stamp);
+ putsock("%s " P10_ACCOUNT " %s %s %lu %lu", self->numeric, user->numeric, stamp, timestamp, serial);
}
void
log_module(MAIN_LOG, LOG_ERROR, "Could not find WHOIS origin user %s", origin);
return 0;
}
- if(!(who = GetUserH(argv[2]))) {
+ if (!(who = GetUserH(argv[2]))) {
irc_numeric(from, ERR_NOSUCHNICK, "%s@%s :No such nick", argv[2], self->name);
return 1;
}
static CMD_FUNC(cmd_account)
{
struct userNode *user;
+ unsigned long timestamp = 0;
+ unsigned long serial = 0;
if ((argc < 3) || !origin || !GetServerH(origin))
return 0; /* Origin must be server. */
user = GetUserN(argv[1]);
if (!user)
return 1; /* A QUIT probably passed the ACCOUNT. */
- call_account_func(user, argv[2]);
+ if (argc > 3)
+ timestamp = strtoul(argv[3], NULL, 10);
+ if (argc > 4)
+ serial = strtoul(argv[4], NULL, 10);
+ call_account_func(user, argv[2], timestamp, serial);
return 1;
}
return 1;
}
-static oper_func_t *of_list;
-static unsigned int of_size = 0, of_used = 0;
-
void
free_user(struct userNode *user)
{
for (nn=0; nn<dead_users.used; nn++)
free_user(dead_users.list[nn]);
userList_clean(&dead_users);
- free(his_servername);
- free(his_servercomment);
}
static void
p10_conf_reload(void) {
hidden_host_suffix = conf_get_data("server/hidden_host", RECDB_QSTRING);
+ his_servername = conf_get_data("server/his_servername", RECDB_QSTRING);
+ his_servercomment = conf_get_data("server/his_servercomment", RECDB_QSTRING);
}
static void
else
inttobase64(numer, (numnick << 18) + (usermask & 0x3ffff), 5);
- str = conf_get_data("server/his_servername", RECDB_QSTRING);
- his_servername = str ? strdup(str) : NULL;
- str = conf_get_data("server/his_servercomment", RECDB_QSTRING);
- his_servercomment = str ? strdup(str) : NULL;
-
str = conf_get_data("server/hostname", RECDB_QSTRING);
desc = conf_get_data("server/description", RECDB_QSTRING);
if (!str || !desc) {
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);
+ log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): numeric %s wrong length!", (void*)uplink, nick, numeric);
return NULL;
}
if (!uplink) {
- log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server for numeric %s doesn't exist!", uplink, nick, numeric);
+ log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server for numeric %s doesn't exist!", (void*)uplink, nick, numeric);
return NULL;
}
if (uplink != GetServerN(numeric)) {
- log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server for numeric %s differs from nominal uplink %s.", uplink, nick, numeric, uplink->name);
+ log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server for numeric %s differs from nominal uplink %s.", (void*)uplink, nick, numeric, uplink->name);
return NULL;
}
if (dummy) {
++modes;
} else if (!is_valid_nick(nick)) {
- log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): invalid nickname detected.", uplink, nick);
+ log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): invalid nickname detected.", (void*)uplink, nick);
return NULL;
}
ignore_user = 0;
if ((oldUser = GetUserH(nick))) {
- if (IsLocal(oldUser) && (IsService(oldUser) || IsPersistent(oldUser))) {
- /* The service should collide the new user off. */
+ if (IsLocal(oldUser)
+ && (IsService(oldUser) || IsPersistent(oldUser))) {
+ /* The service should collide the new user off - but not
+ * if the new user is coming in during a burst. (During a
+ * burst, the bursting server will kill either our user --
+ * triggering a ReintroduceUser() -- or its own.)
+ */
oldUser->timestamp = timestamp - 1;
- irc_user(oldUser);
- }
- if (oldUser->timestamp > timestamp) {
- /* "Old" user is really newer; remove them */
+ ignore_user = 1;
+ if (!uplink->burst)
+ irc_user(oldUser);
+ } else if (oldUser->timestamp > timestamp) {
+ /* "Old" user is really newer; remove them. */
DelUser(oldUser, 0, 1, "Overruled by older nick");
} else {
/* User being added is too new; do not add them to
}
if (IsLocal(uNode))
irc_user(uNode);
- for (n=0; n<nuf_used; n++)
- if (nuf_list[n](uNode))
- break;
+ for (n=0; (n<nuf_used) && !uNode->dead; n++)
+ nuf_list[n](uNode);
return uNode;
}
case 'r':
if (*word) {
char tag[MAXLEN];
+ char *sep;
unsigned int ii;
- for (ii=0; (*word != ' ') && (*word != '\0'); )
+ unsigned long ts = 0;
+ unsigned long id = 0;
+
+ for (ii=0; (*word != ' ') && (*word != '\0') && (*word != ':'); )
tag[ii++] = *word++;
- tag[ii] = 0;
+ if (*word == ':') {
+ ts = strtoul(word + 1, &sep, 10);
+ if (*sep == ':') {
+ id = strtoul(word + 1, &sep, 10);
+ } else if (*sep != ' ' && *sep != '\0') {
+ ts = 0;
+ }
+ }
+ tag[ii] = '\0';
while (*word == ' ')
word++;
- call_account_func(user, tag);
+ call_account_func(user, tag, ts, id);
}
break;
case 'f':
}
}
+static int
+keyncpy(char output[], char input[], size_t output_size)
+{
+ size_t ii;
+
+ if (input[0] == ':')
+ {
+ output[0] = '\0';
+ return 1;
+ }
+
+ for (ii = 0; (ii + 1 < output_size) && (input[ii] != '\0'); ++ii)
+ {
+ output[ii] = input[ii];
+ }
+
+ output[ii] = '\0';
+ return 0;
+}
+
struct mod_chanmode *
mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
{
case 't': do_chan_mode(MODE_TOPICLIMIT); break;
case 'z':
if (!(flags & MCP_REGISTERED)) {
- do_chan_mode(MODE_REGISTERED);
+ do_chan_mode(MODE_REGISTERED);
} else {
- mod_chanmode_free(change);
- return NULL;
+ mod_chanmode_free(change);
+ return NULL;
}
break;
#undef do_chan_mode
break;
case 'k':
if (add) {
- if (in_arg >= argc)
+ if ((in_arg >= argc)
+ || keyncpy(change->new_key, modes[in_arg++], sizeof(change->new_key)))
goto error;
change->modes_set |= MODE_KEY;
- safestrncpy(change->new_key, modes[in_arg++], sizeof(change->new_key));
} else {
change->modes_clear |= MODE_KEY;
if (!(flags & MCP_KEY_FREE)) {
case 'U':
if (add)
{
- if (in_arg >= argc)
- goto error;
- change->modes_set |= MODE_UPASS;
- safestrncpy(change->new_upass, modes[in_arg++], sizeof(change->new_upass));
+ if ((in_arg >= argc)
+ || keyncpy(change->new_upass, modes[in_arg++], sizeof(change->new_upass)))
+ goto error;
+ change->modes_set |= MODE_UPASS;
} else {
change->modes_clear |= MODE_UPASS;
if (!(flags & MCP_UPASS_FREE)) {
break;
case 'A':
if (add) {
- if (in_arg >= argc)
+ if ((in_arg >= argc)
+ || keyncpy(change->new_upass, modes[in_arg++], sizeof(change->new_upass)))
goto error;
change->modes_set |= MODE_APASS;
- safestrncpy(change->new_apass, modes[in_arg++], sizeof(change->new_apass));
} else {
change->modes_clear |= MODE_APASS;
if (!(flags & MCP_APASS_FREE)) {
notice_funcs[user->num_local] = NULL;
}
-void
-reg_oper_func(oper_func_t handler)
-{
- if (of_used == of_size) {
- if (of_size) {
- of_size <<= 1;
- of_list = realloc(of_list, of_size*sizeof(oper_func_t));
- } else {
- of_size = 8;
- of_list = malloc(of_size*sizeof(oper_func_t));
- }
- }
- of_list[of_used++] = handler;
-}
-
-static void
-call_oper_funcs(struct userNode *user)
-{
- unsigned int n;
- if (IsLocal(user))
- return;
- for (n=0; n<of_used; n++)
- of_list[n](user);
-}
-
static void
send_burst(void)
{