# arch-tag: automatic-ChangeLog--srvx@srvx.net--2006/srvx--devo--1.3
#
+2006-10-27 00:21:32 GMT Michael Poole <mdpoole@troilus.org> patch-63
+
+ Summary:
+ Pull ThiefMaster's patch-3..5.
+ Revision:
+ srvx--devo--1.3--patch-63
+
+ Patches applied:
+
+ * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--base-0
+ tag of srvx@srvx.net--2006/srvx--devo--1.3--patch-58
+
+ * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-3
+ Implement complete remote whois.
+
+ * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-4
+ Improve override logging and ignore godmode in !trim.
+
+ * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-5
+ Announce ounregisters to staff via Global.
+
+ modified files:
+ ChangeLog src/chanserv.c src/hash.h src/modcmd.c src/modcmd.h
+ src/nickserv.c src/opserv.c src/proto-p10.c src/proto.h
+
+ new patches:
+ thiefmaster@gamesurge.net--2006/srvx--devo--1.3--base-0
+ thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-3
+ thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-4
+ thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-5
+
+
2006-10-26 23:44:10 GMT Michael Poole <mdpoole@troilus.org> patch-62
Summary:
static CHANSERV_FUNC(cmd_adduser)
{
struct userData *actee;
- struct userData *actor;
+ struct userData *actor, *real_actor;
struct handle_info *handle;
- unsigned short access;
+ unsigned short access, override = 0;
REQUIRE_PARAMS(3);
}
actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
+
if(actor->access <= access)
{
reply("CSMSG_NO_BUMP_ACCESS");
return 0;
}
+ // Trying to add someone with equal/more access
+ if (!real_actor || real_actor->access <= access)
+ override = CMD_LOG_OVERRIDE;
+
if(!(handle = modcmd_get_handle_info(user, argv[1])))
return 0;
- if((actee = GetTrueChannelAccess(channel->channel_info, handle)))
+ if((actee = GetChannelAccess(channel->channel_info, handle)))
{
reply("CSMSG_USER_EXISTS", handle->handle, channel->name, actee->access);
return 0;
actee = add_channel_user(channel->channel_info, handle, access, 0, NULL);
scan_user_presence(actee, NULL);
reply("CSMSG_ADDED_USER", handle->handle, channel->name, access);
- return 1;
+ return 1 | override;
}
static CHANSERV_FUNC(cmd_clvl)
{
struct handle_info *handle;
struct userData *victim;
- struct userData *actor;
- unsigned short new_access;
+ struct userData *actor, *real_actor;
+ unsigned short new_access, override = 0;
int privileged = IsHelping(user) && ((user->handle_info->opserv_level >= chanserv_conf.nodelete_level) || !IsProtected(channel->channel_info));
REQUIRE_PARAMS(3);
actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
if(!(handle = modcmd_get_handle_info(user, argv[1])))
return 0;
return 0;
}
+ // Trying to clvl a equal/higher user
+ if(!real_actor || (real_actor->access <= victim->access && handle != user->handle_info))
+ override = CMD_LOG_OVERRIDE;
+ // Trying to clvl someone to equal/higher access
+ if(!real_actor || new_access >= real_actor->access)
+ override = CMD_LOG_OVERRIDE;
+ // Helpers clvling themselves get caught by the "clvl someone to equal/higher access" check.
+ // If they lower their own access it's not a big problem.
+
victim->access = new_access;
reply("CSMSG_CHANGED_ACCESS", handle->handle, new_access, channel->name);
- return 1;
+ return 1 | override;
}
static CHANSERV_FUNC(cmd_deluser)
{
struct handle_info *handle;
struct userData *victim;
- struct userData *actor;
- unsigned short access;
+ struct userData *actor, *real_actor;
+ unsigned short access, override = 0;
char *chan_name;
REQUIRE_PARAMS(2);
actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
if(!(handle = modcmd_get_handle_info(user, argv[argc-1])))
return 0;
return 0;
}
+ // If people delete themselves it is an override, but they could've used deleteme so we don't log it as an override
+ if(!real_actor || (real_actor->access <= victim->access && real_actor != victim))
+ override = CMD_LOG_OVERRIDE;
+
chan_name = strdup(channel->name);
del_channel_user(victim, 1);
reply("CSMSG_DELETED_USER", handle->handle, access, chan_name);
free(chan_name);
- return 1;
+ return 1 | override;
}
static int
cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short min_access, unsigned short max_access, char *mask, struct svccmd *cmd)
{
- struct userData *actor, *uData, *next;
+ struct userData *actor, *real_actor, *uData, *next;
+ unsigned int override = 0;
actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
if(min_access > max_access)
{
return 0;
}
+ if(!real_actor || real_actor->access <= max_access)
+ override = CMD_LOG_OVERRIDE;
+
for(uData = channel->channel_info->users; uData; uData = next)
{
next = uData->next;
}
reply("CSMSG_DELETED_USERS", mask, min_access, max_access, channel->name);
- return 1;
+ return 1 | override;
}
static CHANSERV_FUNC(cmd_mdelowner)
unsigned int count;
time_t limit;
- actor = GetChannelUser(channel->channel_info, user->handle_info);
+ actor = GetChannelAccess(channel->channel_info, user->handle_info);
if(min_access > max_access)
{
send_message(user, chanserv, "CSMSG_BAD_RANGE", min_access, max_access);
return 0;
}
- if((actor->access <= max_access) && !IsHelping(user))
+ if(!actor || actor->access <= max_access)
{
send_message(user, chanserv, "CSMSG_NO_ACCESS");
return 0;
static MODCMD_FUNC(cmd_wipeinfo)
{
struct handle_info *victim;
- struct userData *ud, *actor;
+ struct userData *ud, *actor, *real_actor;
+ unsigned int override = 0;
REQUIRE_PARAMS(2);
actor = GetChannelUser(channel->channel_info, user->handle_info);
+ real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
if(!(victim = modcmd_get_handle_info(user, argv[1])))
return 0;
if(!(ud = GetTrueChannelAccess(channel->channel_info, victim)))
reply("MSG_USER_OUTRANKED", victim->handle);
return 0;
}
+ if((ud->access >= real_actor->access) && (ud != real_actor))
+ override = CMD_LOG_OVERRIDE;
if(ud->info)
free(ud->info);
ud->info = NULL;
reply("CSMSG_WIPED_INFO_LINE", argv[1], channel->name);
- return 1;
+ return 1 | override;
}
static CHANSERV_FUNC(cmd_resync)
static CHANSERV_FUNC(cmd_suspend)
{
struct handle_info *hi;
- struct userData *self, *target;
+ struct userData *self, *real_self, *target;
+ unsigned int override = 0;
REQUIRE_PARAMS(2);
if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
self = GetChannelUser(channel->channel_info, user->handle_info);
+ real_self = GetChannelAccess(channel->channel_info, user->handle_info);
if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
{
reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
target->present = 0;
target->seen = now;
}
+ if(!real_self || target->access >= real_self->access)
+ override = CMD_LOG_OVERRIDE;
target->flags |= USER_SUSPENDED;
reply("CSMSG_USER_SUSPENDED", hi->handle, channel->name);
- return 1;
+ return 1 | override;
}
static CHANSERV_FUNC(cmd_unsuspend)
{
struct handle_info *hi;
- struct userData *self, *target;
+ struct userData *self, *real_self, *target;
+ unsigned int override = 0;
REQUIRE_PARAMS(2);
if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
self = GetChannelUser(channel->channel_info, user->handle_info);
+ real_self = GetChannelAccess(channel->channel_info, user->handle_info);
if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
{
reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
reply("CSMSG_NOT_SUSPENDED", hi->handle);
return 0;
}
+ if(!real_self || target->access >= real_self->access)
+ override = CMD_LOG_OVERRIDE;
target->flags &= ~USER_SUSPENDED;
scan_user_presence(target, NULL);
reply("CSMSG_USER_UNSUSPENDED", hi->handle, channel->name);
- return 1;
+ return 1 | override;
}
static MODCMD_FUNC(cmd_deleteme)
#define FLAGS_DEAF 0x0020 /* deaf +d */
#define FLAGS_SERVICE 0x0040 /* cannot be kicked, killed or deoped +k */
#define FLAGS_GLOBAL 0x0080 /* receives global messages +g */
+#define FLAGS_NOCHAN 0x0100 /* hide channels in whois +n */
#define FLAGS_PERSISTENT 0x0200 /* for reserved nicks, this isn't just one-shot */
#define FLAGS_GAGGED 0x0400 /* for gagged users */
#define FLAGS_AWAY 0x0800 /* for away users */
#define IsDeaf(x) ((x)->modes & FLAGS_DEAF)
#define IsInvisible(x) ((x)->modes & FLAGS_INVISIBLE)
#define IsGlobal(x) ((x)->modes & FLAGS_GLOBAL)
+#define IsNoChan(x) ((x)->modes & FLAGS_NOCHAN)
#define IsWallOp(x) ((x)->modes & FLAGS_WALLOP)
#define IsGagged(x) ((x)->modes & FLAGS_GAGGED)
-#define IsPersistent(x) ((x)->modes & FLAGS_PERSISTENT)
+#define IsPersistent(x) ((x)->modes & FLAGS_PERSISTENT)
#define IsAway(x) ((x)->modes & FLAGS_AWAY)
#define IsStamped(x) ((x)->modes & FLAGS_STAMPED)
#define IsHiddenHost(x) ((x)->modes & FLAGS_HIDDEN_HOST)
svccmd_invoke_argv(struct userNode *user, struct service *service, struct chanNode *channel, unsigned int argc, char *argv[], unsigned int server_qualified) {
extern struct userNode *chanserv;
struct svccmd *cmd;
- unsigned int cmd_arg, perms, flags, options;
+ unsigned int cmd_arg, perms, flags, options, result;
char channel_name[CHANNELLEN+1];
/* First check pubcmd for the channel. */
safestrncpy(channel_name, channel->name, sizeof(channel_name));
else
channel_name[0] = 0;
- if (!cmd->command->func(user, channel, argc, argv, cmd))
+ if (!(result = cmd->command->func(user, channel, argc, argv, cmd)))
return 0;
if (!(flags & MODCMD_NO_LOG)) {
enum log_severity slvl;
- if (perms & ACTION_STAFF)
+ if (result & CMD_LOG_OVERRIDE)
+ slvl = LOG_OVERRIDE;
+ else if ((perms & ACTION_STAFF) || (result & CMD_LOG_STAFF))
slvl = LOG_STAFF;
else if (perms & ACTION_OVERRIDE)
slvl = LOG_OVERRIDE;
#define SVCCMD_DEBIT 0x000002
#define SVCCMD_NOISY 0x000004
+/* We do not use constants for 0 (no logging) and 1 (regular logging) as those
+ * are used very often and are intuitive enough.
+ */
+#define CMD_LOG_STAFF 0x02
+#define CMD_LOG_OVERRIDE 0x04
+
/* Modularized commands work like this:
*
* Modules define commands. Services contain "bindings" of those
nickserv_make_cookie(user, hi, ACTIVATION, hi->passwd);
/* Set registering flag.. */
- user->modes |= FLAGS_REGISTERING;
+ user->modes |= FLAGS_REGISTERING;
return 1;
}
static NICKSERV_FUNC(cmd_ounregister)
{
struct handle_info *hi;
+ char reason[MAXLEN];
NICKSERV_MIN_PARMS(2);
if (!(hi = get_victim_oper(user, argv[1])))
return 0;
+ snprintf(reason, sizeof(reason), "%s unregistered account %s.", user->handle_info->handle, hi->handle);
+ global_message(MESSAGE_RECIPIENT_STAFF, reason);
nickserv_unregister_handle(hi, user);
return 1;
}
if (IsGlobal(target)) buffer[bpos++] = 'g';
if (IsService(target)) buffer[bpos++] = 'k';
if (IsDeaf(target)) buffer[bpos++] = 'd';
+ if (IsNoChan(target)) buffer[bpos++] = 'n';
if (IsHiddenHost(target)) buffer[bpos++] = 'x';
if (IsGagged(target)) buffer_cat(" (gagged)");
if (IsRegistering(target)) buffer_cat(" (registered account)");
modes[modelen++] = 'd';
if (IsGlobal(user))
modes[modelen++] = 'g';
+ if (IsNoChan(user))
+ modes[modelen++] = 'n';
if (IsHiddenHost(user))
modes[modelen++] = 'x';
modes[modelen] = 0;
{
struct userNode *from;
struct userNode *who;
+ char buf[MAXLEN];
+ unsigned int i, mlen, len;
if (argc < 3)
return 0;
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;
+
+ if (IsFakeHost(who) && IsHiddenHost(who))
+ irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->fakehost, who->info);
+ else if (IsHiddenHost(who) && who->handle_info && hidden_host_suffix)
+ irc_numeric(from, RPL_WHOISUSER, "%s %s %s.%s * :%s", who->nick, who->ident, who->handle_info->handle, hidden_host_suffix, who->info);
+ else
+ irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info);
+
+ if ((!IsService(who) && !IsNoChan(who)) || (from == who)) {
+ struct modeNode *mn;
+ mlen = strlen(self->name) + strlen(from->nick) + 12 + strlen(who->nick);
+ len = 0;
+ *buf = '\0';
+ for (i = 0; i < who->channels.used; i++)
+ {
+ mn = who->channels.list[i];
+
+ if (!IsOper(from) && (mn->channel->modes & (MODE_PRIVATE | MODE_SECRET)) && !GetUserMode(mn->channel, from))
+ continue;
+
+ if (len + strlen(mn->channel->name) + mlen > MAXLEN - 5)
+ {
+ irc_numeric(from, RPL_WHOISCHANNELS, "%s :%s", who->nick, buf);
+ *buf = '\0';
+ len = 0;
+ }
+
+ if (IsDeaf(who))
+ *(buf + len++) = '-';
+ if ((mn->channel->modes & (MODE_PRIVATE | MODE_SECRET)) && !GetUserMode(mn->channel, from))
+ *(buf + len++) = '*';
+ if (mn->modes & MODE_CHANOP)
+ *(buf + len++) = '@';
+ else if (mn->modes & MODE_VOICE)
+ *(buf + len++) = '+';
+
+ if (len)
+ *(buf + len) = '\0';
+ strcpy(buf + len, mn->channel->name);
+ len += strlen(mn->channel->name);
+ strcat(buf + len, " ");
+ len++;
+ }
+ if (buf[0] != '\0')
+ irc_numeric(from, RPL_WHOISCHANNELS, "%s :%s", who->nick, buf);
}
- irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info);
- if (his_servername && his_servercomment)
+
+ if (his_servername && his_servercomment && !IsOper(from) && from != who)
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 (IsAway(who))
+ irc_numeric(from, RPL_AWAY, "%s :Away", who->nick);
if (IsOper(who))
- irc_numeric(from, RPL_WHOISOPERATOR, "%s :is a megalomaniacal power hungry tyrant", who->nick);
+ irc_numeric(from, RPL_WHOISOPERATOR, "%s :%s", who->nick, IsLocal(who) ? "is a megalomaniacal power hungry tyrant" : "is an IRC Operator");
+ if (who->handle_info)
+ irc_numeric(from, RPL_WHOISACCOUNT, "%s %s :is logged in as", who->nick, who->handle_info->handle);
+ if (IsHiddenHost(who) && who->handle_info && (IsOper(from) || from == who))
+ irc_numeric(from, RPL_WHOISACTUALLY, "%s %s@%s %s :Actual user@host, Actual IP", who->nick, who->ident, who->hostname, irc_ntoa(&who->ip));
+
irc_numeric(from, RPL_ENDOFWHOIS, "%s :End of /WHOIS list", who->nick);
return 1;
}
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 'n': do_user_mode(FLAGS_NOCHAN); break;
case 'x': do_user_mode(FLAGS_HIDDEN_HOST); break;
case 'r':
if (*word) {
memset(privmsg_funcs+user->num_local, 0, sizeof(privmsg_func_t));
- for (x = user->num_local+1; x < num_privmsg_funcs; x++)
+ for (x = user->num_local+1; x < num_privmsg_funcs; x++)
memmove(privmsg_funcs+x-1, privmsg_funcs+x, sizeof(privmsg_func_t));
-
- privmsg_funcs = realloc(privmsg_funcs, num_privmsg_funcs*sizeof(privmsg_func_t));
+
+ privmsg_funcs = realloc(privmsg_funcs, num_privmsg_funcs*sizeof(privmsg_func_t));
num_privmsg_funcs--;
}
#define RPL_ENDOFSTATS 219
#define RPL_STATSUPTIME 242
#define RPL_MAXCONNECTIONS 250
+#define RPL_AWAY 301
#define RPL_WHOISUSER 311
#define RPL_WHOISSERVER 312
#define RPL_WHOISOPERATOR 313
#define RPL_ENDOFWHOIS 318
+#define RPL_WHOISCHANNELS 319
+#define RPL_WHOISACCOUNT 330
+#define RPL_WHOISACTUALLY 338
#define ERR_NOSUCHNICK 401
/* stuff originally from other headers that is really protocol-specific */