# arch-tag: automatic-ChangeLog--srvx@srvx.net--2004-srvx/srvx--devo--1.3
#
+2004-05-09 03:05:48 GMT Michael Poole <mdpoole@troilus.org> patch-60
+
+ Summary:
+ Fix several bugs; make off-channel a per-channel option
+ Revision:
+ srvx--devo--1.3--patch-60
+
+ * Add per-channel option (!set offchannel) for off-channel services
+ support.
+
+ * Rename REGISTERED_MODE to MODE_REGISTERED and always use it.
+
+ * Delete remaining (registered) channels on exit.
+
+ * Fix tests in proto-p10.c for chanop-ness when using off-channel
+ services support.
+
+ modified files:
+ ChangeLog src/chanserv.c src/chanserv.h src/hash.c src/hash.h
+ src/nickserv.c src/proto-bahamut.c src/proto-common.c
+ src/proto-p10.c src/proto.h srvx.conf.example
+
+
2004-05-07 14:32:06 GMT Michael Poole <mdpoole@troilus.org> patch-59
Summary:
#define KEY_EXPIRES "expires"
#define KEY_TRIGGERED "triggered"
-#define CHANNEL_DEFAULT_FLAGS (0)
+#define CHANNEL_DEFAULT_FLAGS (CHANNEL_OFFCHANNEL)
#define CHANNEL_DEFAULT_OPTIONS "lmoooanpcnat"
/* Administrative messages */
{ "CSMSG_SET_MODES", "$bModes $b %s" },
{ "CSMSG_SET_NODELETE", "$bNoDelete $b %s" },
{ "CSMSG_SET_DYNLIMIT", "$bDynLimit $b %s" },
+ { "CSMSG_SET_OFFCHANNEL", "$bOffChannel $b %s" },
{ "CSMSG_SET_USERINFO", "$bUserInfo $b %d" },
{ "CSMSG_SET_GIVE_VOICE", "$bGiveVoice $b %d" },
{ "CSMSG_SET_TOPICSNARF", "$bTopicSnarf $b %d" },
struct userNode *chanserv;
dict_t note_types;
+int off_channel;
static dict_t plain_dnrs, mask_dnrs, handle_dnrs;
static struct log_type *CS_LOG;
static void
unregister_channel(struct chanData *channel, const char *reason)
{
+ struct mod_chanmode change;
char msgbuf[MAXLEN];
/* After channel unregistration, the following must be cleaned
timeq_del(0, NULL, channel, TIMEQ_IGNORE_FUNC | TIMEQ_IGNORE_WHEN);
+ mod_chanmode_init(&change);
+ change.modes_clear |= MODE_REGISTERED;
+ mod_chanmode_announce(chanserv, channel->channel, &change);
+
while(channel->users)
del_channel_user(channel->users, 0);
while(channel->bans)
del_channel_ban(channel->bans);
- if(channel->topic) free(channel->topic);
- if(channel->registrar) free(channel->registrar);
- if(channel->greeting) free(channel->greeting);
- if(channel->user_greeting) free(channel->user_greeting);
- if(channel->topic_mask) free(channel->topic_mask);
+ free(channel->topic);
+ free(channel->registrar);
+ free(channel->greeting);
+ free(channel->user_greeting);
+ free(channel->topic_mask);
- if(channel->prev) channel->prev->next = channel->next;
- else channelList = channel->next;
+ if(channel->prev)
+ channel->prev->next = channel->next;
+ else
+ channelList = channel->next;
- if(channel->next) channel->next->prev = channel->prev;
+ if(channel->next)
+ channel->next->prev = channel->prev;
if(channel->suspended)
{
}
channel->channel->channel_info = NULL;
- if(channel->notes)
- dict_delete(channel->notes);
+ dict_delete(channel->notes);
sprintf(msgbuf, "%s %s", channel->channel->name, reason);
if(!IsSuspended(channel))
DelChannelUser(chanserv, channel->channel, msgbuf, 0);
CHANNEL_BINARY_OPTION("CSMSG_SET_DYNLIMIT", CHANNEL_DYNAMIC_LIMIT);
}
+static MODCMD_FUNC(chan_opt_offchannel)
+{
+ struct chanData *cData = channel->channel_info;
+ int value;
+
+ if(argc > 1)
+ {
+ /* Set flag according to value. */
+ if(enabled_string(argv[1]))
+ {
+ if(!IsOffChannel(cData))
+ DelChannelUser(chanserv, channel, "Going off-channel.", 0);
+ cData->flags |= CHANNEL_OFFCHANNEL;
+ value = 1;
+ }
+ else if(disabled_string(argv[1]))
+ {
+ if(IsOffChannel(cData))
+ {
+ struct mod_chanmode change;
+ mod_chanmode_init(&change);
+ change.argc = 1;
+ change.args[0].mode = MODE_CHANOP;
+ change.args[0].member = AddChannelUser(chanserv, channel);
+ mod_chanmode_announce(chanserv, channel, &change);
+ }
+ cData->flags &= ~CHANNEL_OFFCHANNEL;
+ value = 0;
+ }
+ else
+ {
+ reply("MSG_INVALID_BINARY", argv[1]);
+ return 0;
+ }
+ }
+ else
+ {
+ /* Find current option value. */
+ value = (cData->flags & CHANNEL_OFFCHANNEL) ? 1 : 0;
+ }
+
+ if(value)
+ reply("CSMSG_SET_OFFCHANNEL", user_find_message(user, "MSG_ON"));
+ else
+ reply("CSMSG_SET_OFFCHANNEL", user_find_message(user, "MSG_OFF"));
+ return 1;
+}
+
static MODCMD_FUNC(chan_opt_defaults)
{
struct userData *uData;
&& IsUserAutoInvite(channel)
&& (channel->access >= channel->channel->lvlOpts[lvlInviteMe])
&& !self->burst
- && !user->uplink->burst)
+ && !user->uplink->burst)
irc_invite(chanserv, user, cn);
continue;
}
struct string_list *strlist;
struct chanNode *chan;
unsigned int ii;
- extern int off_channel;
if(!(conf_node = conf_get_data(CHANSERV_CONF_NAME, RECDB_OBJECT)))
{
char *str, *argv[10];
dict_iterator_t it;
unsigned int argc;
- extern int off_channel;
channel = hir->d.object;
/* We could use suspended->expires and suspended->revoked to
* set the CHANNEL_SUSPENDED flag, but we don't. */
}
- else if(cData->flags & CHANNEL_SUSPENDED)
+ else if(IsSuspended(cData))
{
suspended = calloc(1, sizeof(*suspended));
suspended->issued = 0;
suspended->cData = cData;
}
else
- suspended = NULL;
+ suspended = NULL; /* to squelch a warning */
- if((cData->flags & CHANNEL_SUSPENDED)
- && suspended->expires
- && (suspended->expires <= now))
- {
- cData->flags &= ~CHANNEL_SUSPENDED;
+ if(IsSuspended(cData)) {
+ if(suspended->expires > now)
+ timeq_add(suspended->expires, chanserv_expire_suspension, suspended);
+ else if(suspended->expires)
+ cData->flags &= ~CHANNEL_SUSPENDED;
}
- if (!off_channel) {
- if (!(cData->flags & CHANNEL_SUSPENDED)) {
- struct mod_chanmode change;
- mod_chanmode_init(&change);
- change.argc = 1;
- change.args[0].mode = MODE_CHANOP;
- change.args[0].member = AddChannelUser(chanserv, cNode);
- mod_chanmode_announce(chanserv, cNode, &change);
-
- } else if (suspended->expires > now) {
- timeq_add(suspended->expires, chanserv_expire_suspension, suspended);
- }
+ if((!off_channel || !IsOffChannel(cData)) && !IsSuspended(cData)) {
+ struct mod_chanmode change;
+ mod_chanmode_init(&change);
+ change.argc = 1;
+ change.args[0].mode = MODE_CHANOP;
+ change.args[0].member = AddChannelUser(chanserv, cNode);
+ mod_chanmode_announce(chanserv, cNode, &change);
}
str = database_get_data(channel, KEY_REGISTERED, RECDB_QSTRING);
str = database_get_data(channel, KEY_TOPIC, RECDB_QSTRING);
cData->topic = str ? strdup(str) : NULL;
- if((str = database_get_data(channel, KEY_MODES, RECDB_QSTRING))
+ if(!IsSuspended(cData)
+ && (str = database_get_data(channel, KEY_MODES, RECDB_QSTRING))
&& (argc = split_line(str, 0, ArrayLength(argv), argv))
&& (modes = mod_chanmode_parse(cNode, argv, argc, MCP_KEY_FREE))) {
cData->modes = *modes;
- if(off_channel && !(REGISTERED_MODE == 0))
- cData->modes.modes_set |= REGISTERED_MODE;
+ cData->modes.modes_set |= MODE_REGISTERED;
if(cData->modes.argc > 1)
cData->modes.argc = 1;
- if(!IsSuspended(cData))
- mod_chanmode_announce(chanserv, cNode, &cData->modes);
+ mod_chanmode_announce(chanserv, cNode, &cData->modes);
mod_chanmode_free(modes);
}
DEFINE_CHANNEL_OPTION(ctcpusers);
DEFINE_CHANNEL_OPTION(ctcpreaction);
DEFINE_CHANNEL_OPTION(inviteme);
+ if(off_channel)
+ DEFINE_CHANNEL_OPTION(offchannel);
modcmd_register(chanserv_module, "set defaults", chan_opt_defaults, 1, 0, "access", "owner", NULL);
/* Alias set topic to set defaulttopic for compatibility. */
#define CHANNEL_DYNAMIC_LIMIT 0x00000020 /* (1 << 5) */
#define CHANNEL_TOPIC_SNARF 0x00000040 /* (1 << 6) - DEPRECATED */
#define CHANNEL_PEON_INVITE 0x00000080 /* (1 << 7) - DEPRECATED */
+#define CHANNEL_OFFCHANNEL 0x00000100 /* (1 << 8) */
/* Flags with values over 0x20000000 or (1 << 29) will not work
* because chanData.flags is a 30-bit field.
*/
#define IsProtected(x) ((x)->flags & CHANNEL_NODELETE)
#define IsSuspended(x) ((x)->flags & CHANNEL_SUSPENDED)
+#define IsOffChannel(x) ((x)->flags & CHANNEL_OFFCHANNEL)
struct chanData
{
struct modeNode* mNode;
unsigned int n;
- if (reason) {
+ if (reason)
irc_part(user, channel, reason);
- }
mNode = GetUserMode(channel, user);
modeList_remove(&user->channels, mNode);
free(mNode);
- if (!deleting && !channel->members.used && !channel->locks)
+ if (!deleting && !channel->members.used && !channel->locks && !(channel->modes & MODE_REGISTERED))
DelChannel(channel);
}
static void
hash_cleanup(void)
{
+ dict_iterator_t it, next;
+
DelServer(self, 0, NULL);
+ for (it = dict_first(channels); it; it = next) {
+ next = iter_next(it);
+ DelChannel(iter_data(it));
+ }
dict_delete(channels);
dict_delete(clients);
dict_delete(servers);
#define MODE_BAN 0x0200 /* +b BAN */
#define MODE_LIMIT 0x0400 /* +l LIMIT */
#define MODE_DELAYJOINS 0x0800 /* +D */
-#define MODE_REGONLY 0x1000 /* +r */
+#define MODE_REGONLY 0x1000 /* ircu +r, Bahamut +R */
#define MODE_NOCOLORS 0x2000 /* +c */
#define MODE_NOCTCPS 0x4000 /* +C */
+#define MODE_REGISTERED 0x8000 /* Bahamut +r */
#define MODE_REMOVE 0x80000000
#define FLAGS_OPER 0x0001 /* Operator +O */
#define IsReggedNick(x) ((x)->modes & FLAGS_REGNICK)
#define IsLocal(x) ((x)->uplink == self)
-/* Please set this and define the mode you wish to be set/maintained on registered channels. */
-#define REGISTERED_MODE 0
-
#define NICKLEN 30
#define USERLEN 10
#define HOSTLEN 63
}
if (IsLocal(target)) {
if (IsService(target))
- send_message(user, service, "NSMSG_USER_IS_SERVICE", target->nick);
+ send_message(user, service, "NSMSG_USER_IS_SERVICE", target->nick);
else
- send_message(user, service, "MSG_USER_AUTHENTICATE", target->nick);
+ send_message(user, service, "MSG_USER_AUTHENTICATE", target->nick);
return 0;
}
if (!(hi = target->handle_info)) {
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;
break;
#define do_chan_mode(FLAG) do { if (add) change->modes_set |= FLAG, change->modes_clear &= ~FLAG; else change->modes_clear |= FLAG, change->modes_set &= ~FLAG; } while(0)
case 'R': do_chan_mode(MODE_REGONLY); break;
+ case 'r': do_chan_mode(MODE_REGISTERED); break;
case 'D': do_chan_mode(MODE_DELAYJOINS); break;
case 'c': do_chan_mode(MODE_NOCOLORS); break;
case 'i': do_chan_mode(MODE_INVITEONLY); 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_clear & channel->modes & MODE_KEY)
mod_chanmode_append(&chbuf, 'k', channel->key);
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);
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');
#undef DO_MODE_CHAR
switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) {
case MODE_KEY|MODE_LIMIT:
struct io_fd *socket_io_fd;
int force_n2k;
const char *hidden_host_suffix;
-int off_channel;
static char replay_line[MAXLEN+80];
static int ping_freq;
return 1;
}
-static CMD_FUNC(cmd_whois)
-{
- struct userNode *from;
- struct userNode *who;
-#ifdef WITH_PROTOCOL_P10
- extern char *his_servername;
- extern char *his_servercomment;
-#endif
-
- 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_version)
{
struct userNode *user;
static privmsg_func_t *notice_funcs;
static unsigned int num_notice_funcs;
static struct dict *unbursted_channels;
-
-char *his_servername;
-char *his_servercomment;
+static char *his_servername;
+static 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, time_t timestamp, const char *realip);
+extern int off_channel;
+
/* Numerics can be XYY, XYYY, or XXYYY; with X's identifying the
* server and Y's indentifying the client on that server. */
struct server*
{
const char *numeric;
struct modeNode *mn = GetUserMode(channel, who);
- numeric = ((!mn && off_channel) || (mn->modes & MODE_CHANOP)) ? who->numeric : self->numeric;
+ numeric = ((mn && (mn->modes & MODE_CHANOP)) || off_channel) ? who->numeric : self->numeric;
putsock("%s " P10_KICK " %s %s :%s",
numeric, channel->name, target->numeric, msg);
}
}
}
+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);
+ if (his_servername && his_servercomment)
+ irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, his_servername, his_servercomment);
+ else
+ 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_server)
{
struct server *srv;
const char *str, *desc;
int numnick, usermask, max_users;
char numer[COMBO_NUMERIC_LEN+1];
- extern char *his_servername;
- extern char *his_servercomment;
/* read config items */
str = conf_get_data("server/ping_freq", RECDB_QSTRING);
chbuf.chname_len = strlen(channel->name);
mn = GetUserMode(channel, who);
- if ((!mn && off_channel) || (mn->modes & MODE_CHANOP))
+ if ((mn && (mn->modes & MODE_CHANOP)) || off_channel)
chbuf.is_chanop = 1;
/* First remove modes */
#ifdef WITH_PROTOCOL_P10
struct server* GetServerN(const char *numeric);
struct userNode* GetUserN(const char *numeric);
-extern char *his_servername;
-extern char *his_servercomment;
#endif
/* Basic protocol parsing support. */
// (This is changed relative srvx-1.0.x, which would use default
// unless you specified ".disabled".)
"nick" "ChanServ";
- // Should ChanServ join the channel? Please do not ask the srvx dev
- // team for help configuring your ircd or a patch if you attempt to
- // use this option on ircds that do not support having services off
- // of the channel. Most people will leave this off; we cannot assist
- // you in designing your network to make this option usefull to you.
- "off_channel" "no";
+ // Does your ircd have off-channel services support?
+ // Bahamut does; ircu2.10.11 does not.
+ "off_channel" "no";
// how long should a person be unseen before resending infoline?
"info_delay" "120";
// maximum greeting length