/* proto-common.c - common IRC protocol parsing/sending support
* Copyright 2000-2004 srvx Development Team
*
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version. Important limitations are
- * listed in the COPYING file that accompanies this software.
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, email srvx-maintainers@srvx.net.
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "conf.h"
close_socket();
return;
}
- if ((eol = strpbrk(buffer, "\r\n"))) *eol = 0;
+ if ((eol = strpbrk(buffer, "\r\n")))
+ *eol = 0;
log_replay(MAIN_LOG, false, buffer);
if (cManager.uplink->state != DISCONNECTED)
parse_line(buffer, 0);
log_module(MAIN_LOG, LOG_ERROR, "Connection to server lost.");
socket_io_fd = NULL;
cManager.uplink->state = DISCONNECTED;
- if (self->uplink) DelServer(self->uplink, 0, NULL);
+ if (self->uplink)
+ DelServer(self->uplink, 0, NULL);
}
void replay_event_loop(void)
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);
- 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_version)
{
struct userNode *user;
struct userNode *service;
} chanmsg_funcs[256]; /* indexed by trigger character */
+static struct allchanmsg_func {
+ chanmsg_func_t func;
+ struct userNode *service;
+} allchanmsg_funcs[ALLCHANMSG_FUNCS_MAX];
+
struct privmsg_desc {
struct userNode *user;
char *text;
struct privmsg_desc *pd = data;
struct modeNode *mn;
struct chanmsg_func *cf = &chanmsg_funcs[(unsigned char)pd->text[0]];
+ int x;
/* Don't complain if it can't find the modeNode because the channel might
* be -n */
/* Never send a NOTICE to a channel to one of the services */
if (!pd->is_notice && cf->func && GetUserMode(cn, cf->service))
cf->func(pd->user, cn, pd->text+1, cf->service);
+
+ /* This catches *all* text sent to the channel that the services server sees */
+ for (x = 0; x < ALLCHANMSG_FUNCS_MAX; x++) {
+ cf = (struct chanmsg_func *)&allchanmsg_funcs[x];
+ if (!cf->func)
+ break; /* end of list */
+ else
+ cf->func(pd->user, cn, pd->text, cf->service);
+ }
}
static void
chanmsg_funcs[prefix].service = service;
}
+void
+reg_allchanmsg_func(struct userNode *service, chanmsg_func_t handler)
+{
+ int x;
+ for (x = 0; x < ALLCHANMSG_FUNCS_MAX; x++) {
+ if (allchanmsg_funcs[x].func)
+ continue;
+ allchanmsg_funcs[x].func = handler;
+ allchanmsg_funcs[x].service = service;
+ break;
+ }
+}
+
struct userNode *
get_chanmsg_bot(unsigned char prefix)
{
res = calloc(1, sizeof(*res) + (argc-1)*sizeof(res->args[0]));
else
res = calloc(1, sizeof(*res));
- if (res)
+ if (res) {
+#if !defined(NDEBUG)
+ res->alloc_argc = argc;
+#endif
res->argc = argc;
+ }
return res;
}
if (res) {
res->modes_set = orig->modes_set;
res->modes_clear = orig->modes_clear;
+ res->new_limit = orig->new_limit;
+ memcpy(res->new_key, orig->new_key, sizeof(res->new_key));
res->argc = orig->argc;
memcpy(res->args, orig->args, orig->argc*sizeof(orig->args[0]));
}
struct banNode *bn;
unsigned int ii, jj;
+ assert(change->argc <= change->alloc_argc);
channel->modes = (channel->modes & ~change->modes_clear) | change->modes_set;
if (change->modes_set & MODE_LIMIT)
channel->limit = change->new_limit;
* to be more specific than an existing ban.
*/
for (jj=0; jj<channel->banlist.used; ++jj) {
- if (match_ircglobs(change->args[ii].hostmask, channel->banlist.list[jj]->ban)) {
+ if (match_ircglobs(change->args[ii].u.hostmask, channel->banlist.list[jj]->ban)) {
banList_remove(&channel->banlist, channel->banlist.list[jj]);
free(channel->banlist.list[jj]);
jj--;
}
}
bn = calloc(1, sizeof(*bn));
- safestrncpy(bn->ban, change->args[ii].hostmask, sizeof(bn->ban));
- safestrncpy(bn->who, who->nick, sizeof(bn->who));
+ safestrncpy(bn->ban, change->args[ii].u.hostmask, sizeof(bn->ban));
+ if (who)
+ safestrncpy(bn->who, who->nick, sizeof(bn->who));
+ else
+ safestrncpy(bn->who, "<unknown>", sizeof(bn->who));
bn->set = now;
banList_append(&channel->banlist, bn);
break;
case MODE_REMOVE|MODE_BAN:
for (jj=0; jj<channel->banlist.used; ++jj) {
- if (strcmp(channel->banlist.list[jj]->ban, change->args[ii].hostmask))
+ if (strcmp(channel->banlist.list[jj]->ban, change->args[ii].u.hostmask))
continue;
free(channel->banlist.list[jj]);
banList_remove(&channel->banlist, channel->banlist.list[jj]);
break;
}
break;
- default:
- assert((change->args[ii].mode & (MODE_REMOVE|MODE_CHANOP|MODE_VOICE)) != 0);
+ case MODE_CHANOP:
+ case MODE_VOICE:
+ case MODE_VOICE|MODE_CHANOP:
+ case MODE_REMOVE|MODE_CHANOP:
+ case MODE_REMOVE|MODE_VOICE:
+ case MODE_REMOVE|MODE_VOICE|MODE_CHANOP:
if (change->args[ii].mode & MODE_REMOVE)
- change->args[ii].member->modes &= ~change->args[ii].mode;
+ change->args[ii].u.member->modes &= ~change->args[ii].mode;
else
- change->args[ii].member->modes |= change->args[ii].mode;
+ change->args[ii].u.member->modes |= change->args[ii].mode;
break;
+ default:
+ assert(0 && "Invalid mode argument");
+ continue;
}
}
}
}
int
-irc_make_chanmode(struct chanNode *chan, char *out) {
+irc_make_chanmode(struct chanNode *chan, char *out)
+{
struct mod_chanmode change;
+ mod_chanmode_init(&change);
change.modes_set = chan->modes;
- change.modes_clear = change.argc = 0;
change.new_limit = chan->limit;
safestrncpy(change.new_key, chan->key, sizeof(change.new_key));
return strlen(mod_chanmode_format(&change, out));
strcpy(ident+1, user->ident + ((*user->ident == '~')?1:0));
}
hostname = user->hostname;
- if (IsHiddenHost(user) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) {
+ if (IsFakeHost(user) && IsHiddenHost(user) && !(options & GENMASK_NO_HIDING)) {
+ hostname = user->fakehost;
+ } else if (IsHiddenHost(user) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) {
hostname = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2);
sprintf(hostname, "%s.%s", user->handle_info->handle, hidden_host_suffix);
} else if (options & GENMASK_STRICT_HOST) {