/* proto-bahamut.c - IRC protocol output
- * Copyright 2000-2004 srvx Development Team
+ * Copyright 2000-2006 srvx Development Team
*
* This file is part of srvx.
*
static int uplink_capab;
static void privmsg_user_helper(struct userNode *un, void *data);
+/* These correspond to 1 << X: 012345678901234567 */
+const char irc_user_mode_chars[] = "o iw dkg r ";
+
void irc_svsmode(struct userNode *target, char *modes, unsigned long stamp);
struct server *
-AddServer(struct server *uplink, const char *name, int hops, time_t boot, time_t link, UNUSED_ARG(const char *numeric), const char *description) {
+AddServer(struct server *uplink, const char *name, int hops, unsigned long boot, unsigned long link_time, UNUSED_ARG(const char *numeric), const char *description) {
struct server* sNode;
sNode = calloc(1, sizeof(*sNode));
safestrncpy(sNode->name, name, sizeof(sNode->name));
sNode->hops = hops;
sNode->boot = boot;
- sNode->link = link;
+ sNode->link_time = link_time;
sNode->users = dict_new();
safestrncpy(sNode->description, description, sizeof(sNode->description));
serverList_init(&sNode->children);
}
struct userNode *
-AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *userinfo, time_t timestamp, struct in_addr realip, const char *stamp) {
+AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *userinfo, unsigned long timestamp, irc_in_addr_t realip, unsigned long stamp) {
struct userNode *uNode, *oldUser;
- unsigned int nn;
+ unsigned int nn, dummy;
if (!uplink) {
log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server does not exist!", uplink, nick);
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;
}
}
mod_usermode(uNode, modes);
- if (stamp) call_account_func(uNode, stamp);
+ if (dummy) uNode->modes |= FLAGS_DUMMY;
+ if (stamp) call_account_func(uNode, NULL, 0, stamp);
if (IsLocal(uNode)) irc_user(uNode);
- for (nn=0; nn<nuf_used; nn++) {
- if (nuf_list[nn](uNode)) break;
- }
+ for (nn=0; (nn<nuf_used) && !uNode->dead; nn++)
+ nuf_list[nn](uNode);
return uNode;
}
struct userNode *
-AddService(const char *nick, const char *desc) {
- time_t timestamp = now;
+AddLocalUser(const char *nick, const char *ident, const char *hostname, const char *desc, const char *modes)
+{
+ unsigned long timestamp = now;
struct userNode *old_user = GetUserH(nick);
- struct in_addr ipaddr = { INADDR_LOOPBACK };
- if (old_user) {
- if (IsLocal(old_user))
- return old_user;
- timestamp = old_user->timestamp - 1;
- }
- return AddUser(self, nick, nick, self->name, "+oikr", desc, timestamp, ipaddr, 0);
-}
+ static const irc_in_addr_t ipaddr;
-struct userNode *
-AddClone(const char *nick, const char *ident, const char *hostname, const char *desc) {
- time_t timestamp = now;
- struct userNode *old_user = GetUserH(nick);
- struct in_addr ipaddr = { INADDR_LOOPBACK };
+ if (!modes)
+ modes = "+oikr";
if (old_user) {
if (IsLocal(old_user))
return old_user;
timestamp = old_user->timestamp - 1;
}
- return AddUser(self, nick, ident, hostname, "+ir", desc, timestamp, ipaddr, 0);
+ if (!hostname)
+ hostname = self->name;
+ return AddUser(self, nick, ident, hostname, modes, desc, timestamp, ipaddr, 0);
}
void
unsigned int nn;
for (nn=user->channels.used; nn>0;) {
- DelChannelUser(user, user->channels.list[--nn]->channel, false, 0);
+ DelChannelUser(user, user->channels.list[--nn]->channel, NULL, false);
}
for (nn=duf_used; nn>0; ) duf_list[--nn](user, killer, why);
user->uplink->clients--;
irc_kill(killer, user, why);
}
}
+ dict_remove(service_msginfo_dict, user->nick);
modeList_clean(&user->channels);
user->dead = 1;
if (dead_users.size) {
void
irc_user(struct userNode *user) {
char modes[32];
- int modelen = 0;
- if (IsOper(user)) modes[modelen++] = 'o';
- if (IsInvisible(user)) modes[modelen++] = 'i';
- if (IsWallOp(user)) modes[modelen++] = 'w';
- if (IsService(user)) modes[modelen++] = 'k';
- if (IsServNotice(user)) modes[modelen++] = 's';
- if (IsDeaf(user)) modes[modelen++] = 'd';
- if (IsReggedNick(user)) modes[modelen++] = 'r';
- if (IsGlobal(user)) modes[modelen++] = 'g';
- modes[modelen] = 0;
- putsock("NICK %s %d "FMT_TIME_T" +%s %s %s %s %d %u :%s",
- user->nick, user->uplink->hops+2, user->timestamp, modes,
- user->ident, user->hostname, user->uplink->name, 0, ntohl(user->ip.s_addr), user->info);
+ if (!user || user->nick[0] != ' ') return;
+ irc_user_modes(user, modes, sizeof(modes));
+ putsock("NICK %s %d %lu +%s %s %s %s %d %u :%s",
+ user->nick, user->uplink->hops+2, (unsigned long)user->timestamp,
+ modes, user->ident, user->hostname, user->uplink->name, 0,
+ ntohl(user->ip.in6_32[3]), user->info);
}
void
-irc_account(struct userNode *user, const char *stamp)
+irc_account(struct userNode *user, UNUSED_ARG(const char *stamp), UNUSED_ARG(unsigned long timestamp), unsigned long serial)
{
if (IsReggedNick(user)) {
- irc_svsmode(user, "+rd", base64toint(stamp, IDLEN));
+ irc_svsmode(user, "+rd", serial);
} else {
- irc_svsmode(user, "+d", base64toint(stamp, IDLEN));
+ irc_svsmode(user, "+d", serial);
}
}
+void
+irc_fakehost(UNUSED_ARG(struct userNode *user), UNUSED_ARG(const char *host), UNUSED_ARG(const char *ident), UNUSED_ARG(int force))
+{
+ /* not supported in bahamut */
+}
+
void
irc_regnick(struct userNode *user)
{
dict_insert(service_msginfo_dict, user->nick, smi);
}
}
- putsock(":%s NICK %s :"FMT_TIME_T, old_nick, user->nick, user->timestamp);
+ putsock(":%s NICK %s :%lu", old_nick, user->nick, (unsigned long)user->timestamp);
}
void
void
irc_svinfo() {
- putsock("SVINFO 3 3 0 :"FMT_TIME_T, now);
-}
-
-void
-irc_burst() {
- putsock("BURST");
+ putsock("SVINFO 3 3 0 :%lu", (unsigned long)now);
}
void
irc_introduce(const char *passwd) {
- extern time_t burst_begin;
+ extern unsigned long burst_begin;
irc_pass(passwd);
irc_capab();
}
}
+static int
+deliver_to_dummy(struct userNode *source, struct userNode *dest, const char *message, int type)
+{
+ struct service_message_info *smi;
+
+ if (!dest || !IsDummy(dest) || !IsLocal(dest))
+ return 0;
+ smi = dict_find(service_msginfo_dict, dest->nick, NULL);
+ switch (type) {
+ default:
+ if (smi && smi->on_privmsg)
+ {
+ smi->on_privmsg(source, dest, message, 0);
+ return 1;
+ }
+ break;
+ case 1:
+ if (smi && smi->on_notice)
+ {
+ smi->on_notice(source, dest, message, 0);
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
void
irc_privmsg(struct userNode *from, const char *to, const char *message) {
- putsock(":%s PRIVMSG %s :%s", from->nick, to, message);
+ if (!deliver_to_dummy(from, GetUserH(to), message, 1))
+ putsock(":%s PRIVMSG %s :%s", from->nick, to, message);
}
void
irc_notice(struct userNode *from, const char *to, const char *message) {
- putsock(":%s NOTICE %s :%s", from->nick, to, message);
+ if (!deliver_to_dummy(from, GetUserH(to), message, 0))
+ putsock(":%s NOTICE %s :%s", from->nick, to, message);
}
void
irc_notice_user(struct userNode *from, struct userNode *to, const char *message) {
- putsock(":%s NOTICE %s :%s", from->nick, to->nick, message);
+ if (!deliver_to_dummy(from, to, message, 0))
+ putsock(":%s NOTICE %s :%s", from->nick, to->nick, message);
}
void
void
irc_join(struct userNode *who, struct chanNode *what) {
if (what->members.used == 1) {
- putsock(":%s SJOIN "FMT_TIME_T" %s + :@%s", self->name, what->timestamp, what->name, who->nick);
+ putsock(":%s SJOIN %lu %s + :@%s", self->name, (unsigned long)what->timestamp, what->name, who->nick);
} else {
- putsock(":%s SJOIN "FMT_TIME_T" %s", who->nick, what->timestamp, what->name);
+ putsock(":%s SJOIN %lu %s", who->nick, (unsigned long)what->timestamp, what->name);
}
}
void
irc_mode(struct userNode *who, struct chanNode *target, const char *modes) {
- putsock(":%s MODE %s "FMT_TIME_T" %s", who->nick, target->name, target->timestamp, modes);
+ putsock(":%s MODE %s %lu %s", who->nick, target->name, (unsigned long)target->timestamp, modes);
}
void
irc_svsmode(struct userNode *target, char *modes, unsigned long stamp) {
extern struct userNode *nickserv;
if (stamp) {
- putsock(":%s SVSMODE %s "FMT_TIME_T" %s %lu", nickserv->nick, target->nick, target->timestamp, modes, stamp);
+ putsock(":%s SVSMODE %s %lu %s %lu", nickserv->nick, target->nick, (unsigned long)target->timestamp, modes, stamp);
} else {
- putsock(":%s SVSMODE %s "FMT_TIME_T" %s", nickserv->nick, target->nick, target->timestamp, modes);
+ putsock(":%s SVSMODE %s %lu %s", nickserv->nick, target->nick, (unsigned long)target->timestamp, modes);
}
}
if (len > ArrayLength(ident)) len = ArrayLength(ident);
safestrncpy(ident, gline->target, len);
safestrncpy(host, sep+1, ArrayLength(host));
- putsock(":%s AKILL %s %s "FMT_TIME_T" %s "FMT_TIME_T" :%s", self->name, host, ident, gline->expires-gline->issued, gline->issuer, gline->issued, gline->reason);
+ putsock(":%s AKILL %s %s %lu %s %lu :%s", self->name, host, ident, (unsigned long)(gline->expires-gline->issued), gline->issuer, (unsigned long)gline->issued, gline->reason);
}
void
-irc_settime(UNUSED_ARG(const char *srv_name_mask), UNUSED_ARG(time_t new_time))
+irc_settime(UNUSED_ARG(const char *srv_name_mask), UNUSED_ARG(unsigned long new_time))
{
/* Bahamut has nothing like this, so ignore it. */
}
void
irc_svsnick(struct userNode *from, struct userNode *target, const char *newnick)
{
- putsock(":%s SVSNICK %s %s :"FMT_TIME_T, from->nick, target->nick, newnick, now);
+ putsock(":%s SVSNICK %s %s :%lu", from->nick, target->nick, newnick, (unsigned long)now);
}
void
parse_foreach(char *target_list, foreach_chanfunc cf, foreach_nonchan nc, foreach_userfunc uf, foreach_nonuser nu, void *data) {
char *j, old;
do {
- j = target_list;
- while (*j != 0 && *j != ',') j++;
- old = *j;
+ j = target_list;
+ while (*j != 0 && *j != ',') j++;
+ old = *j;
*j = 0;
- if (IsChannelName(target_list)) {
- struct chanNode *chan = GetChannel(target_list);
+ if (IsChannelName(target_list)) {
+ struct chanNode *chan = GetChannel(target_list);
if (chan) {
if (cf) cf(chan, data);
} else {
if (nc) nc(target_list, data);
}
- } else {
- struct userNode *user;
+ } else {
+ struct userNode *user;
struct privmsg_desc *pd = data;
pd->is_qualified = 0;
if (*target_list == '@') {
user = NULL;
} else if (strchr(target_list, '@')) {
- struct server *server;
+ struct server *server;
pd->is_qualified = 1;
- user = GetUserH(strtok(target_list, "@"));
- server = GetServerH(strtok(NULL, "@"));
-
- if (user && (user->uplink != server)) {
- /* Don't attempt to index into any arrays
- using a user's numeric on another server. */
- user = NULL;
- }
- } else {
- user = GetUserH(target_list);
- }
+ user = GetUserH(strtok(target_list, "@"));
+ server = GetServerH(strtok(NULL, "@"));
+
+ if (user && (user->uplink != server)) {
+ /* Don't attempt to index into any arrays
+ using a user's numeric on another server. */
+ user = NULL;
+ }
+ } else {
+ user = GetUserH(target_list);
+ }
if (user) {
if (uf) uf(user, data);
} else {
if (nu) nu(target_list, data);
}
- }
- target_list = j+1;
+ }
+ target_list = j+1;
} while (old == ',');
}
return 1;
}
+static CMD_FUNC(cmd_whois) {
+ struct userNode *from;
+ struct userNode *who;
+
+ if (argc < 3)
+ return 0;
+ if (!(from = GetUserH(origin))) {
+ log_module(MAIN_LOG, LOG_ERROR, "Could not find WHOIS origin user %s", origin);
+ return 0;
+ }
+ if(!(who = GetUserH(argv[2]))) {
+ irc_numeric(from, ERR_NOSUCHNICK, "%s@%s :No such nick", argv[2], self->name);
+ return 1;
+ }
+ if (IsHiddenHost(who) && !IsOper(from)) {
+ /* Just stay quiet. */
+ return 1;
+ }
+ irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info);
+#ifdef WITH_PROTOCOL_P10
+ if (his_servername && his_servercomment)
+ irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, his_servername, his_servercomment);
+ else
+#endif
+ irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, who->uplink->name, who->uplink->description);
+
+ if (IsOper(who)) {
+ irc_numeric(from, RPL_WHOISOPERATOR, "%s :is a megalomaniacal power hungry tyrant", who->nick);
+ }
+ irc_numeric(from, RPL_ENDOFWHOIS, "%s :End of /WHOIS list", who->nick);
+ return 1;
+}
+
static CMD_FUNC(cmd_capab) {
static const struct {
const char *name;
if (!chan->members.used) return;
/* send list of users in the channel.. */
- base_len = sprintf(line, ":%s SJOIN "FMT_TIME_T" %s ", self->name, chan->timestamp, chan->name);
+ base_len = sprintf(line, ":%s SJOIN %lu %s ", self->name, (unsigned long)chan->timestamp, chan->name);
len = irc_make_chanmode(chan, line+base_len);
pos = base_len + len;
line[pos++] = ' ';
line[pos] = 0;
putsock("%s", line);
/* now send the bans.. */
- base_len = sprintf(line, ":%s MODE "FMT_TIME_T" %s +", self->name, chan->timestamp, chan->name);
+ base_len = sprintf(line, ":%s MODE %lu %s +", self->name, (unsigned long)chan->timestamp, chan->name);
pos = sizeof(line)-1;
line[pos] = 0;
for (nn=queued=0; nn<chan->banlist.used; nn++) {
AddServer(GetServerH(origin), argv[1], atoi(argv[2]), 0, now, 0, argv[3]);
} else {
self->uplink = AddServer(self, argv[1], atoi(argv[2]), 0, now, 0, argv[3]);
- send_burst();
}
return 1;
}
if (argc < 5) return 0;
if ((atoi(argv[1]) < 3) || (atoi(argv[2]) > 3)) return 0;
/* TODO: something with the timestamp we get from the other guy */
+ send_burst();
return 1;
}
NickChange(un, argv[1], 1);
} else {
/* new nick from a server */
- char id[8];
unsigned long stamp;
- struct in_addr ip;
+ irc_in_addr_t ip;
if (argc < 10) return 0;
stamp = strtoul(argv[8], NULL, 0);
- if (stamp) inttobase64(id, stamp, IDLEN);
- ip.s_addr = (argc > 10) ? atoi(argv[9]) : 0;
- un = AddUser(GetServerH(argv[7]), argv[1], argv[5], argv[6], argv[4], argv[argc-1], atoi(argv[3]), ip, (stamp ? id : 0));
+ if (argc > 10)
+ ip.in6_32[3] = htonl(atoi(argv[9]));
+ un = AddUser(GetServerH(argv[7]), argv[1], argv[5], argv[6], argv[4], argv[argc-1], atoi(argv[3]), ip, stamp);
}
return 1;
}
return 1;
}
-static CMD_FUNC(cmd_part) {
- if (argc < 2) return 0;
- parse_foreach(argv[1], part_helper, NULL, NULL, NULL, GetUserH(origin));
- return 1;
-}
-
static CMD_FUNC(cmd_away) {
struct userNode *un;
{
if (argc < 3) return 0;
if (!strcmp(argv[2], self->name)) {
- timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
- timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
- timeq_add(now + ping_freq, timed_send_ping, 0);
- received_ping();
+ timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
+ timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
+ timeq_add(now + ping_freq, timed_send_ping, 0);
+ received_ping();
}
return 1;
}
return 1;
}
-static oper_func_t *of_list;
-static unsigned int of_size = 0, of_used = 0;
-
void parse_cleanup(void) {
unsigned int nn;
- if (of_list) free(of_list);
+ free(of_list);
dict_delete(irc_func_dict);
dict_delete(service_msginfo_dict);
free(mcf_list);
userList_init(&dead_users);
reg_exit_func(parse_cleanup);
+ (void)call_xquery_funcs;
}
int parse_line(char *line, int recursive) {
res = 0;
}
if (!res) {
- log_module(MAIN_LOG, LOG_ERROR, "PARSE ERROR on line: %s", unsplit_string(argv, argc, NULL));
+ log_module(MAIN_LOG, LOG_ERROR, "PARSE ERROR on line: %s", unsplit_string(argv, argc, NULL));
} else if (!recursive) {
unsigned int i;
for (i=0; i<dead_users.used; i++) {
info->on_privmsg = handler;
}
+void
+unreg_privmsg_func(struct userNode *user) {
+ struct service_message_info *info;
+ info = dict_find(service_msginfo_dict, user->nick, NULL);
+ if (info) {
+ info->on_privmsg = NULL;
+ if (info->on_notice == NULL) {
+ dict_remove(service_msginfo_dict, user->nick);
+ }
+ }
+}
+
void
reg_notice_func(struct userNode *user, privmsg_func_t handler) {
struct service_message_info *info = dict_find(service_msginfo_dict, user->nick, 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);
+unreg_notice_func(struct userNode *user) {
+ struct service_message_info *info;
+ info = dict_find(service_msginfo_dict, user->nick, NULL);
+ if (info) {
+ info->on_notice = NULL;
+ if (info->on_privmsg == NULL) {
+ dict_remove(service_msginfo_dict, user->nick);
+ }
}
}
if (!user || !mode_change) return;
while (1) {
#define do_user_mode(FLAG) do { if (add) user->modes |= FLAG; else user->modes &= ~FLAG; } while (0)
- switch (*mode_change++) {
- case 0: return;
- case '+': add = 1; break;
- case '-': add = 0; break;
- case 'o':
- do_user_mode(FLAGS_OPER);
- if (add) {
- userList_append(&curr_opers, user);
- call_oper_funcs(user);
- } else {
- 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++; else 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 'r': do_user_mode(FLAGS_REGNICK); 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;
- }
+ switch (*mode_change++) {
+ case 0: return;
+ case '+': add = 1; break;
+ case '-': add = 0; break;
+ case 'o':
+ do_user_mode(FLAGS_OPER);
+ if (add) {
+ userList_append(&curr_opers, user);
+ call_oper_funcs(user);
+ } else {
+ userList_remove(&curr_opers, user);
+ }
+ break;
+ case 'i': do_user_mode(FLAGS_INVISIBLE);
+ if (add) invis_clients++; else invis_clients--;
+ break;
+ case 'w': do_user_mode(FLAGS_WALLOP); break;
+ case 'd': do_user_mode(FLAGS_DEAF); break;
+ case 'r': do_user_mode(FLAGS_REGNICK); break;
+ case 'k': do_user_mode(FLAGS_SERVICE); break;
+ case 'g': do_user_mode(FLAGS_GLOBAL); break;
+ }
#undef do_user_mode
}
}
struct mod_chanmode *
-mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags)
+mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
{
struct mod_chanmode *change;
unsigned int ii, in_arg, ch_arg, add;
case 'p': do_chan_mode(MODE_PRIVATE); break;
case 's': do_chan_mode(MODE_SECRET); break;
case 't': do_chan_mode(MODE_TOPICLIMIT); break;
+ case 'r':
+ if (!(flags & MCP_REGISTERED)) {
+ do_chan_mode(MODE_REGISTERED);
+ } else {
+ mod_chanmode_free(change);
+ return NULL;
+ }
+ break;
#undef do_chan_mode
case 'l':
if (add) {
change->args[ch_arg].mode = MODE_BAN;
if (!add)
change->args[ch_arg].mode |= MODE_REMOVE;
- change->args[ch_arg++].hostmask = modes[in_arg++];
+ change->args[ch_arg++].u.hostmask = modes[in_arg++];
break;
case 'o': case 'v':
{
victim = GetUserH(modes[in_arg++]);
if (!victim)
continue;
- if ((change->args[ch_arg].member = GetUserMode(channel, victim)))
+ if ((change->args[ch_arg].u.member = GetUserMode(channel, victim)))
ch_arg++;
break;
}
break;
}
}
- change->argc = argc; /* in case any turned out to be ignored */
+ change->argc = ch_arg; /* in case any turned out to be ignored */
if (change->modes_set & MODE_SECRET) {
change->modes_set &= ~(MODE_PRIVATE);
change->modes_clear |= MODE_PRIVATE;
error:
mod_chanmode_free(change);
return NULL;
+ (void)base_oplevel;
}
struct chanmode_buffer {
DO_MODE_CHAR(DELAYJOINS, 'D');
DO_MODE_CHAR(REGONLY, 'R');
DO_MODE_CHAR(NOCOLORS, 'c');
+ DO_MODE_CHAR(REGISTERED, 'r');
#undef DO_MODE_CHAR
if (change->modes_clear & channel->modes & MODE_KEY)
mod_chanmode_append(&chbuf, 'k', channel->key);
continue;
switch (change->args[arg].mode & ~MODE_REMOVE) {
case MODE_BAN:
- mod_chanmode_append(&chbuf, 'b', change->args[arg].hostmask);
+ mod_chanmode_append(&chbuf, 'b', change->args[arg].u.hostmask);
break;
default:
if (change->args[arg].mode & MODE_CHANOP)
- mod_chanmode_append(&chbuf, 'o', change->args[arg].member->user->nick);
+ mod_chanmode_append(&chbuf, 'o', change->args[arg].u.member->user->nick);
if (change->args[arg].mode & MODE_VOICE)
- mod_chanmode_append(&chbuf, 'v', change->args[arg].member->user->nick);
+ mod_chanmode_append(&chbuf, 'v', change->args[arg].u.member->user->nick);
break;
}
}
DO_MODE_CHAR(DELAYJOINS, 'D');
DO_MODE_CHAR(REGONLY, 'R');
DO_MODE_CHAR(NOCOLORS, 'c');
+ DO_MODE_CHAR(REGISTERED, 'r');
#undef DO_MODE_CHAR
if (change->modes_set & MODE_KEY)
mod_chanmode_append(&chbuf, 'k', change->new_key);
continue;
switch (change->args[arg].mode) {
case MODE_BAN:
- mod_chanmode_append(&chbuf, 'b', change->args[arg].hostmask);
+ mod_chanmode_append(&chbuf, 'b', change->args[arg].u.hostmask);
break;
default:
if (change->args[arg].mode & MODE_CHANOP)
- mod_chanmode_append(&chbuf, 'o', change->args[arg].member->user->nick);
+ mod_chanmode_append(&chbuf, 'o', change->args[arg].u.member->user->nick);
if (change->args[arg].mode & MODE_VOICE)
- mod_chanmode_append(&chbuf, 'v', change->args[arg].member->user->nick);
+ mod_chanmode_append(&chbuf, 'v', change->args[arg].u.member->user->nick);
break;
}
}
mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
{
unsigned int used = 0;
+ unsigned int args_used = 0;
+ char args[MAXLEN];
+
assert(change->argc <= change->alloc_argc);
if (change->modes_clear) {
outbuff[used++] = '-';
DO_MODE_CHAR(LIMIT, 'l');
DO_MODE_CHAR(KEY, 'k');
DO_MODE_CHAR(DELAYJOINS, 'D');
- DO_MODE_CHAR(REGONLY, '$');
+ DO_MODE_CHAR(REGONLY, 'R');
DO_MODE_CHAR(NOCOLORS, 'c');
+ DO_MODE_CHAR(REGISTERED, 'r');
#undef DO_MODE_CHAR
}
if (change->modes_set) {
DO_MODE_CHAR(DELAYJOINS, 'D');
DO_MODE_CHAR(REGONLY, 'R');
DO_MODE_CHAR(NOCOLORS, 'c');
+ DO_MODE_CHAR(REGISTERED, 'r');
+ DO_MODE_CHAR(LIMIT, 'l'), args_used += sprintf(args + args_used, " %d", change->new_limit);
+ DO_MODE_CHAR(KEY, 'k'), args_used += sprintf(args + args_used, " %s", change->new_key);
#undef DO_MODE_CHAR
- switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) {
- case MODE_KEY|MODE_LIMIT:
- used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key);
- break;
- case MODE_KEY:
- used += sprintf(outbuff+used, "k %s", change->new_key);
- break;
- case MODE_LIMIT:
- used += sprintf(outbuff+used, "l %d", change->new_limit);
- break;
- }
}
- outbuff[used] = 0;
+ args[args_used] = '\0';
+ strcpy(outbuff + used, args);
return outbuff;
}