mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-06-28 20:36:36 +02:00
Add "CAP chghost" support. Internal recode of userhost changes.
Fix force-rejoin not working if doing SVSMODE -x/+x (Koragg, #5015). Note to module coders: Please use the following procedure in case of an user/host change: * userhost_save_current(acptr); * << change username or hostname here (or both) >> * userhost_changed(acptr); This function will take care of notifying other clients about the userhost change, such as doing PART+JOIN+MODE if force-rejoin is enabled, and sending :xx CHGHOST user host messages to "CAP chghost" capable clients. Also, small note to everyone: If force-rejoin is enabled we will not send the PART+JOIN+MODE to "CAP chghost" capable clients. Doing so is just a hack to notify people of a userhost change. "CAP chghost" users can thus benefit from the reduced noise in this respect.
This commit is contained in:
+4
-2
@@ -515,8 +515,6 @@ extern u_char getrandom8();
|
||||
extern u_int16_t getrandom16();
|
||||
extern u_int32_t getrandom32();
|
||||
#define EVENT_DRUGS BASE_VERSION
|
||||
extern void rejoin_leave(aClient *sptr);
|
||||
extern void rejoin_joinandmode(aClient *sptr);
|
||||
extern void ident_failed(aClient *cptr);
|
||||
|
||||
extern MODVAR char extchmstr[4][64];
|
||||
@@ -669,6 +667,8 @@ extern MODVAR int (*check_banned)(aClient *cptr);
|
||||
extern MODVAR void (*introduce_user)(aClient *to, aClient *acptr);
|
||||
extern MODVAR int (*check_deny_version)(aClient *cptr, char *version_string, int protocol, char *flags);
|
||||
extern MODVAR int (*match_user)(char *rmask, aClient *acptr, int options);
|
||||
extern MODVAR void (*userhost_save_current)(aClient *sptr);
|
||||
extern MODVAR void (*userhost_changed)(aClient *sptr);
|
||||
/* /Efuncs */
|
||||
|
||||
extern MODVAR aMotdFile opermotd, svsmotd, motd, botmotd, smotd, rules;
|
||||
@@ -798,3 +798,5 @@ extern int cipher_check(SSL_CTX *ctx, char **errstr);
|
||||
extern void clicap_pre_rehash(void);
|
||||
extern void clicap_post_rehash(void);
|
||||
extern void send_cap_notify(int add, char *token);
|
||||
extern void sendbufto_one(aClient *to, char *msg, unsigned int quick);
|
||||
extern MODVAR int current_serial;
|
||||
|
||||
@@ -1044,6 +1044,8 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
|
||||
#define EFUNC_SEND_MODDATA_MEMBERS 51
|
||||
#define EFUNC_BROADCAST_MODDATA_CLIENT 52
|
||||
#define EFUNC_MATCH_USER 53
|
||||
#define EFUNC_USERHOST_SAVE_CURRENT 54
|
||||
#define EFUNC_USERHOST_CHANGED 55
|
||||
|
||||
/* Module flags */
|
||||
#define MODFLAG_NONE 0x0000
|
||||
|
||||
@@ -357,6 +357,7 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia
|
||||
#define PROTO_ACCOUNT_NOTIFY 0x200000 /* client supports account-notify */
|
||||
#define PROTO_MLOCK 0x400000 /* server supports MLOCK */
|
||||
#define PROTO_EXTSWHOIS 0x800000 /* extended SWHOIS support */
|
||||
#define PROTO_CAP_CHGHOST 0x1000000 /* CAP chghost */
|
||||
|
||||
/*
|
||||
* flags macros.
|
||||
|
||||
@@ -1269,104 +1269,6 @@ void send_user_joins(aClient *cptr, aClient *user)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* rejoin_leave:
|
||||
* sends a PART to all channels (to local users only)
|
||||
* TODO: use QUIT instead of PART if configured to do so
|
||||
*/
|
||||
void rejoin_leave(aClient *sptr)
|
||||
{
|
||||
Membership *tmp;
|
||||
aChannel *chptr;
|
||||
char *comment = "Changing host";
|
||||
int i = 0;
|
||||
|
||||
for (tmp = sptr->user->channel; tmp; tmp = tmp->next)
|
||||
{
|
||||
tmp->flags &= ~CHFL_REJOINING;
|
||||
|
||||
chptr = tmp->chptr;
|
||||
if (!chptr)
|
||||
continue; /* Possible? */
|
||||
|
||||
/* If the user is banned, don't do it */
|
||||
if (is_banned(sptr, chptr, BANCHK_JOIN))
|
||||
continue;
|
||||
|
||||
/* Ok, we will now part/quit/whatever the user, so tag it.. */
|
||||
tmp->flags |= CHFL_REJOINING;
|
||||
|
||||
if (invisible_user_in_channel(sptr, chptr))
|
||||
{
|
||||
sendto_chanops_butone(sptr, chptr, ":%s!%s@%s PART %s :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname, comment);
|
||||
} else
|
||||
sendto_channel_butserv_butone(chptr, sptr, sptr, ":%s PART %s :%s", sptr->name, chptr->chname, comment);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rejoin_joinandmode:
|
||||
* sends a JOIN and a MODE (if needed) to restore qaohv modes (to local users only)
|
||||
*/
|
||||
void rejoin_joinandmode(aClient *sptr)
|
||||
{
|
||||
Membership *tmp;
|
||||
aChannel *chptr;
|
||||
int i, j = 0, n, flags;
|
||||
int k = 0;
|
||||
char flagbuf[8]; /* For holding "qohva" and "*~@%+" */
|
||||
|
||||
for (tmp = sptr->user->channel; tmp; tmp = tmp->next)
|
||||
{
|
||||
flags = tmp->flags;
|
||||
chptr = tmp->chptr;
|
||||
if (!chptr)
|
||||
continue; /* Is it possible? */
|
||||
|
||||
/* If the user is banned, don't do it */
|
||||
if (!(flags & CHFL_REJOINING))
|
||||
continue;
|
||||
|
||||
if (invisible_user_in_channel(sptr, chptr))
|
||||
{
|
||||
sendto_chanops_butone(sptr, chptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname);
|
||||
} else
|
||||
sendto_channel_butserv_butone(chptr, sptr, sptr, ":%s JOIN :%s", sptr->name, chptr->chname);
|
||||
|
||||
/* Set the modes (if any) */
|
||||
if (flags)
|
||||
{
|
||||
char *p = flagbuf;
|
||||
if (flags & MODE_CHANOP)
|
||||
*p++ = 'o';
|
||||
if (flags & MODE_VOICE)
|
||||
*p++ = 'v';
|
||||
if (flags & MODE_HALFOP)
|
||||
*p++ = 'h';
|
||||
if (flags & MODE_CHANOWNER)
|
||||
*p++ = 'q';
|
||||
if (flags & MODE_CHANPROT)
|
||||
*p++ = 'a';
|
||||
*p = '\0';
|
||||
parabuf[0] = '\0';
|
||||
n = strlen(flagbuf);
|
||||
if (n)
|
||||
{
|
||||
for (i=0; i < n; i++)
|
||||
{
|
||||
strcat(parabuf, sptr->name);
|
||||
if (i < n - 1)
|
||||
strcat(parabuf, " ");
|
||||
}
|
||||
sendto_channel_butserv_butone(chptr, &me, sptr, ":%s MODE %s +%s %s",
|
||||
me.name, chptr->chname, flagbuf, parabuf);
|
||||
}
|
||||
}
|
||||
|
||||
tmp->flags &= ~CHFL_REJOINING; /* esthetics.. ;) */
|
||||
}
|
||||
}
|
||||
|
||||
/* set_channel_mlock()
|
||||
*
|
||||
* inputs - client, source, channel, params
|
||||
|
||||
+5
-1
@@ -132,6 +132,8 @@ void (*send_moddata_channel)(aClient *srv, aChannel *chptr);
|
||||
void (*send_moddata_members)(aClient *srv);
|
||||
void (*broadcast_moddata_client)(aClient *acptr);
|
||||
int (*match_user)(char *rmask, aClient *acptr, int options);
|
||||
void (*userhost_changed)(aClient *sptr);
|
||||
void (*userhost_save_current)(aClient *sptr);
|
||||
|
||||
static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
|
||||
/* 00 */ {NULL, NULL},
|
||||
@@ -188,7 +190,9 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
|
||||
/* 51 */ {"send_moddata_members", (void *)&send_moddata_members},
|
||||
/* 52 */ {"broadcast_moddata_client", (void *)&broadcast_moddata_client},
|
||||
/* 53 */ {"match_user", (void *)&match_user},
|
||||
/* 54 */ {NULL, NULL}
|
||||
/* 54 */ {"userhost_save_current", (void *)&userhost_save_current},
|
||||
/* 55 */ {"userhost_changed", (void *)&userhost_changed},
|
||||
/* 56 */ {NULL, NULL}
|
||||
};
|
||||
|
||||
#ifdef UNDERSCORE
|
||||
|
||||
@@ -69,6 +69,11 @@ MOD_INIT(m_cap)
|
||||
c.cap = PROTO_CAP_NOTIFY;
|
||||
ClientCapabilityAdd(modinfo->handle, &c);
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.name = "chghost";
|
||||
c.cap = PROTO_CAP_CHGHOST;
|
||||
ClientCapabilityAdd(modinfo->handle, &c);
|
||||
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,9 @@ CMD_FUNC(m_chghost)
|
||||
sendnotice(sptr, "*** /ChgHost Error: requested host is same as current host.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
userhost_save_current(acptr);
|
||||
|
||||
switch (UHOST_ALLOWED)
|
||||
{
|
||||
case UHALLOW_NEVER:
|
||||
@@ -130,8 +133,7 @@ CMD_FUNC(m_chghost)
|
||||
}
|
||||
break;
|
||||
case UHALLOW_REJOIN:
|
||||
rejoin_leave(acptr);
|
||||
/* join sent later when the host has been changed */
|
||||
/* rejoin sent later when the host has been changed */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -158,9 +160,9 @@ CMD_FUNC(m_chghost)
|
||||
acptr->user->virthost = 0;
|
||||
}
|
||||
acptr->user->virthost = strdup(parv[2]);
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_joinandmode(acptr);
|
||||
|
||||
userhost_changed(acptr);
|
||||
|
||||
if (MyClient(acptr))
|
||||
sendto_one(acptr, err_str(RPL_HOSTHIDDEN), me.name, acptr->name, parv[2]);
|
||||
|
||||
|
||||
@@ -113,6 +113,8 @@ CMD_FUNC(m_chgident)
|
||||
|
||||
if ((acptr = find_person(parv[1], NULL)))
|
||||
{
|
||||
userhost_save_current(acptr);
|
||||
|
||||
switch (UHOST_ALLOWED)
|
||||
{
|
||||
case UHALLOW_NEVER:
|
||||
@@ -133,7 +135,6 @@ CMD_FUNC(m_chgident)
|
||||
}
|
||||
break;
|
||||
case UHALLOW_REJOIN:
|
||||
rejoin_leave(acptr);
|
||||
/* join sent later when the ident has been changed */
|
||||
break;
|
||||
}
|
||||
@@ -150,13 +151,11 @@ CMD_FUNC(m_chgident)
|
||||
GetHost(acptr), parv[2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
sendto_server(cptr, 0, 0, ":%s CHGIDENT %s %s",
|
||||
sptr->name, acptr->name, parv[2]);
|
||||
ircsnprintf(acptr->user->username, sizeof(acptr->user->username), "%s", parv[2]);
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_joinandmode(acptr);
|
||||
|
||||
userhost_changed(acptr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
||||
+199
-1
@@ -27,7 +27,8 @@ CMD_FUNC(m_join);
|
||||
DLLFUNC void _join_channel(aChannel *chptr, aClient *cptr, aClient *sptr, int flags);
|
||||
CMD_FUNC(_do_join);
|
||||
DLLFUNC int _can_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *key, char *parv[]);
|
||||
#define MAXBOUNCE 5 /** Most sensible */
|
||||
void _userhost_save_current(aClient *sptr);
|
||||
void _userhost_changed(aClient *sptr);
|
||||
|
||||
/* Externs */
|
||||
extern MODVAR int spamf_ugly_vchanoverride;
|
||||
@@ -36,6 +37,8 @@ extern int find_invex(aChannel *chptr, aClient *sptr);
|
||||
/* Local vars */
|
||||
static int bouncedtimes = 0;
|
||||
|
||||
/* Macros */
|
||||
#define MAXBOUNCE 5 /** Most sensible */
|
||||
#define MSG_JOIN "JOIN"
|
||||
|
||||
ModuleHeader MOD_HEADER(m_join)
|
||||
@@ -53,6 +56,9 @@ MOD_TEST(m_join)
|
||||
EfunctionAddVoid(modinfo->handle, EFUNC_JOIN_CHANNEL, _join_channel);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_DO_JOIN, _do_join);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_CAN_JOIN, _can_join);
|
||||
EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_SAVE_CURRENT, _userhost_save_current);
|
||||
EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_CHANGED, _userhost_changed);
|
||||
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -526,3 +532,195 @@ CMD_FUNC(_do_join)
|
||||
RET(0)
|
||||
#undef RET
|
||||
}
|
||||
|
||||
/* Additional channel-related functions. I've put it here instead
|
||||
* of the core so it could be upgraded on the fly should it be necessary.
|
||||
*/
|
||||
|
||||
char *get_chmodes_for_user(aClient *sptr, int flags)
|
||||
{
|
||||
static char modebuf[512]; /* returned */
|
||||
char flagbuf[8]; /* For holding "vhoaq" */
|
||||
char *p = flagbuf;
|
||||
char parabuf[512];
|
||||
int n, i;
|
||||
|
||||
if (!flags)
|
||||
return "";
|
||||
|
||||
if (flags & MODE_CHANOWNER)
|
||||
*p++ = 'q';
|
||||
if (flags & MODE_CHANPROT)
|
||||
*p++ = 'a';
|
||||
if (flags & MODE_CHANOP)
|
||||
*p++ = 'o';
|
||||
if (flags & MODE_VOICE)
|
||||
*p++ = 'v';
|
||||
if (flags & MODE_HALFOP)
|
||||
*p++ = 'h';
|
||||
*p = '\0';
|
||||
|
||||
parabuf[0] = '\0';
|
||||
|
||||
n = strlen(flagbuf);
|
||||
if (n)
|
||||
{
|
||||
for (i=0; i < n; i++)
|
||||
{
|
||||
strlcat(parabuf, sptr->name, sizeof(parabuf));
|
||||
if (i < n - 1)
|
||||
strlcat(parabuf, " ", sizeof(parabuf));
|
||||
}
|
||||
/* And we have our mode line! */
|
||||
snprintf(modebuf, sizeof(modebuf), "+%s %s", flagbuf, parabuf);
|
||||
return modebuf;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static char remember_nick[NICKLEN+1];
|
||||
static char remember_user[USERLEN+1];
|
||||
static char remember_host[HOSTLEN+1];
|
||||
|
||||
/** Save current nick/user/host. Used later by userhost_changed(). */
|
||||
void _userhost_save_current(aClient *sptr)
|
||||
{
|
||||
strlcpy(remember_nick, sptr->name, sizeof(remember_nick));
|
||||
strlcpy(remember_user, sptr->user->username, sizeof(remember_user));
|
||||
strlcpy(remember_host, GetHost(sptr), sizeof(remember_host));
|
||||
}
|
||||
|
||||
/** User/Host changed for user.
|
||||
* Note that userhost_save_current() needs to be called before this
|
||||
* to save the old username/hostname.
|
||||
* This userhost_changed() function deals with notifying local clients
|
||||
* about the user/host change by sending PART+JOIN+MODE if
|
||||
* set::allow-userhost-change force-rejoin is in use,
|
||||
* and it wills end "CAP chghost" to such capable clients.
|
||||
* It will also deal with bumping fakelag for the user since a user/host
|
||||
* change is costly, doesn't matter if it was self-induced or not.
|
||||
*
|
||||
* Please call this function for any user/host change by doing:
|
||||
* userhost_save_current(acptr);
|
||||
* << change username or hostname here >>
|
||||
* userhost_changed(acptr);
|
||||
*/
|
||||
void _userhost_changed(aClient *sptr)
|
||||
{
|
||||
Membership *channels;
|
||||
aChannel *chptr;
|
||||
Member *lp;
|
||||
aClient *acptr;
|
||||
int i = 0;
|
||||
int impact = 0;
|
||||
char buf[512];
|
||||
|
||||
if (strcmp(remember_nick, sptr->name))
|
||||
{
|
||||
ircd_log(LOG_ERROR, "[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: %s",
|
||||
sptr->name);
|
||||
ircd_log(LOG_ERROR, "Please report above bug on https://bugs.unrealircd.org/");
|
||||
sendto_realops("[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: %s",
|
||||
sptr->name);
|
||||
sendto_realops("Please report above bug on https://bugs.unrealircd.org/");
|
||||
return; /* We cannot safely process this request anymore */
|
||||
}
|
||||
|
||||
/* It's perfectly acceptable to call us even if the userhost didn't change. */
|
||||
if (!strcmp(remember_user, sptr->user->username) && !strcmp(remember_host, GetHost(sptr)))
|
||||
return; /* Nothing to do */
|
||||
|
||||
/* Most of the work is only necessary for set::allow-userhost-change force-rejoin */
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
{
|
||||
/* Walk through all channels of this user.. */
|
||||
for (channels = sptr->user->channel; channels; channels = channels->next)
|
||||
{
|
||||
aChannel *chptr = channels->chptr;
|
||||
int flags = channels->flags;
|
||||
char *modes;
|
||||
char partbuf[512]; /* PART */
|
||||
char joinbuf[512]; /* JOIN */
|
||||
char modebuf[512]; /* MODE (if any) */
|
||||
int chanops_only = invisible_user_in_channel(sptr, chptr);
|
||||
|
||||
modebuf[0] = '\0';
|
||||
|
||||
/* If the user is banned, don't send any rejoins, it would only be annoying */
|
||||
if (is_banned(sptr, chptr, BANCHK_JOIN))
|
||||
continue;
|
||||
|
||||
/* Prepare buffers for PART, JOIN, MODE */
|
||||
ircsnprintf(partbuf, sizeof(partbuf), ":%s!%s@%s PART %s :%s",
|
||||
remember_nick, remember_user, remember_host,
|
||||
chptr->chname,
|
||||
"Changing host");
|
||||
|
||||
ircsnprintf(joinbuf, sizeof(joinbuf), ":%s!%s@%s JOIN %s",
|
||||
sptr->name, sptr->user->username, GetHost(sptr), chptr->chname);
|
||||
|
||||
modes = get_chmodes_for_user(sptr, flags);
|
||||
if (modes)
|
||||
ircsnprintf(modebuf, sizeof(modebuf), ":%s MODE %s %s", me.name, chptr->chname, modes);
|
||||
|
||||
for (lp = chptr->members; lp; lp = lp->next)
|
||||
{
|
||||
acptr = lp->cptr;
|
||||
|
||||
if (acptr == sptr)
|
||||
continue; /* skip self */
|
||||
|
||||
if (!MyConnect(acptr))
|
||||
continue; /* only locally connected clients */
|
||||
|
||||
if (chanops_only && !(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT)))
|
||||
continue; /* skip non-ops if requested to (used for mode +D) */
|
||||
|
||||
if (acptr->local->proto & PROTO_CAP_CHGHOST)
|
||||
continue; /* we notify 'CAP chghost' users in a different way, so don't send it here. */
|
||||
|
||||
impact++;
|
||||
|
||||
sendbufto_one(acptr, partbuf, 0);
|
||||
sendbufto_one(acptr, joinbuf, 0);
|
||||
if (*modebuf)
|
||||
sendbufto_one(acptr, modebuf, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now deal with "CAP chghost" clients.
|
||||
* This only needs to be sent one per "common channel".
|
||||
* This would normally call sendto_common_channels_local_butone() but the user already
|
||||
* has the new user/host.. so we do it here..
|
||||
*/
|
||||
ircsnprintf(buf, sizeof(buf), ":%s!%s@%s CHGHOST %s %s",
|
||||
remember_nick, remember_user, remember_host,
|
||||
sptr->user->username,
|
||||
GetHost(sptr));
|
||||
current_serial++;
|
||||
for (channels = sptr->user->channel; channels; channels = channels->next)
|
||||
{
|
||||
for (lp = channels->chptr->members; lp; lp = lp->next)
|
||||
{
|
||||
acptr = lp->cptr;
|
||||
if (MyClient(acptr) && (acptr->local->proto & PROTO_CAP_CHGHOST) &&
|
||||
(acptr->local->serial != current_serial) && (sptr != acptr))
|
||||
{
|
||||
sendbufto_one(acptr, buf, 0);
|
||||
acptr->local->serial = current_serial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A userhost change always generates the following network traffic:
|
||||
* server to server traffic, CAP "chghost" notifications, and
|
||||
* possibly PART+JOIN+MODE if force-rejoin had work to do.
|
||||
* We give the user a penalty so they don't flood...
|
||||
*/
|
||||
if (impact)
|
||||
sptr->local->since += 7; /* Resulted in rejoins and such. */
|
||||
else
|
||||
sptr->local->since += 4; /* No rejoins */
|
||||
}
|
||||
|
||||
+8
-29
@@ -1599,6 +1599,8 @@ CMD_FUNC(_m_umode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
userhost_save_current(sptr); /* save host, in case we do any +x/-x or similar */
|
||||
|
||||
/* find flags already set for user */
|
||||
for (i = 0; i <= Usermode_highest; i++)
|
||||
if ((sptr->umodes & Usermode_Table[i].mode))
|
||||
@@ -1769,28 +1771,12 @@ CMD_FUNC(_m_umode)
|
||||
sendto_server(cptr, PROTO_VHP, 0, ":%s SETHOST :%s",
|
||||
sptr->name, sptr->user->virthost);
|
||||
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
{
|
||||
/* Damn, this is ugly: we have to restore umodes to old state,
|
||||
* do the PART and then set umodes to the new modes again.
|
||||
*/
|
||||
long newmodes = sptr->umodes;
|
||||
sptr->umodes = oldumodes;
|
||||
rejoin_leave(sptr);
|
||||
sptr->umodes = newmodes;
|
||||
}
|
||||
|
||||
/* Set the vhost */
|
||||
safefree(sptr->user->virthost);
|
||||
sptr->user->virthost = strdup(sptr->user->cloakedhost);
|
||||
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
{
|
||||
sptr->umodes |= UMODE_HIDE;
|
||||
rejoin_joinandmode(sptr);
|
||||
if (MyClient(sptr))
|
||||
sptr->local->since += 7; /* Add fake lag */
|
||||
}
|
||||
|
||||
/* Notify */
|
||||
userhost_changed(sptr);
|
||||
if (MyClient(sptr))
|
||||
sendto_one(sptr, err_str(RPL_HOSTHIDDEN), me.name, sptr->name, sptr->user->virthost);
|
||||
}
|
||||
@@ -1798,22 +1784,15 @@ CMD_FUNC(_m_umode)
|
||||
/* -x */
|
||||
if (!IsHidden(sptr) && (oldumodes & UMODE_HIDE))
|
||||
{
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
{
|
||||
/* LOL, this is ugly ;) */
|
||||
sptr->umodes |= UMODE_HIDE;
|
||||
rejoin_leave(sptr);
|
||||
sptr->umodes &= ~UMODE_HIDE;
|
||||
rejoin_joinandmode(sptr);
|
||||
if (MyClient(sptr))
|
||||
sptr->local->since += 7; /* Add fake lag */
|
||||
}
|
||||
/* (Re)create the cloaked virthost, because it will be used
|
||||
* for ban-checking... free+recreate here because it could have
|
||||
* been a vhost for example. -- Syzop
|
||||
*/
|
||||
safefree(sptr->user->virthost);
|
||||
sptr->user->virthost = strdup(sptr->user->cloakedhost);
|
||||
|
||||
/* Notify */
|
||||
userhost_changed(sptr);
|
||||
if (MyClient(sptr))
|
||||
sendto_one(sptr, err_str(RPL_HOSTHIDDEN), me.name, sptr->name, sptr->user->realhost);
|
||||
}
|
||||
|
||||
@@ -128,6 +128,8 @@ CMD_FUNC(m_sethost)
|
||||
}
|
||||
|
||||
{
|
||||
userhost_save_current(sptr);
|
||||
|
||||
switch (UHOST_ALLOWED)
|
||||
{
|
||||
case UHALLOW_NEVER:
|
||||
@@ -147,7 +149,6 @@ CMD_FUNC(m_sethost)
|
||||
}
|
||||
break;
|
||||
case UHALLOW_REJOIN:
|
||||
rejoin_leave(sptr);
|
||||
/* join sent later when the host has been changed */
|
||||
break;
|
||||
}
|
||||
@@ -165,8 +166,7 @@ CMD_FUNC(m_sethost)
|
||||
/* spread it out */
|
||||
sendto_server(cptr, 0, 0, ":%s SETHOST %s", sptr->name, parv[1]);
|
||||
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_joinandmode(sptr);
|
||||
userhost_changed(sptr);
|
||||
}
|
||||
|
||||
if (MyConnect(sptr))
|
||||
|
||||
@@ -155,6 +155,8 @@ CMD_FUNC(m_setident)
|
||||
}
|
||||
|
||||
{
|
||||
userhost_save_current(sptr);
|
||||
|
||||
switch (UHOST_ALLOWED)
|
||||
{
|
||||
case UHALLOW_ALWAYS:
|
||||
@@ -174,7 +176,7 @@ CMD_FUNC(m_setident)
|
||||
}
|
||||
break;
|
||||
case UHALLOW_REJOIN:
|
||||
rejoin_leave(sptr);
|
||||
/* dealt with later */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -183,8 +185,7 @@ CMD_FUNC(m_setident)
|
||||
/* spread it out */
|
||||
sendto_server(cptr, 0, 0, ":%s SETIDENT %s", sptr->name, parv[1]);
|
||||
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_joinandmode(sptr);
|
||||
userhost_changed(sptr);
|
||||
}
|
||||
|
||||
if (MyConnect(sptr))
|
||||
|
||||
@@ -387,6 +387,8 @@ int do_svsmode(aClient *cptr, aClient *sptr, int parc, char *parv[], int show_c
|
||||
if (!(acptr = find_person(parv[1], NULL)))
|
||||
return 0;
|
||||
|
||||
userhost_save_current(acptr);
|
||||
|
||||
/* initialize setflag to be the user's pre-SVSMODE flags */
|
||||
for (i = 0; i <= Usermode_highest; i++)
|
||||
if (Usermode_Table[i].flag && (acptr->umodes & Usermode_Table[i].mode))
|
||||
@@ -550,6 +552,8 @@ int do_svsmode(aClient *cptr, aClient *sptr, int parc, char *parv[], int show_c
|
||||
sendto_one(acptr, ":%s MODE %s :%s", sptr->name, acptr->name, buf);
|
||||
}
|
||||
|
||||
userhost_changed(acptr); /* we can safely call this, even if nothing changed */
|
||||
|
||||
VERIFY_OPERCOUNT(acptr, "svsmodeX");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -109,6 +109,8 @@ CMD_FUNC(m_vhost)
|
||||
{
|
||||
char olduser[USERLEN+1];
|
||||
|
||||
userhost_save_current(sptr);
|
||||
|
||||
switch (UHOST_ALLOWED)
|
||||
{
|
||||
case UHALLOW_NEVER:
|
||||
@@ -128,7 +130,6 @@ CMD_FUNC(m_vhost)
|
||||
}
|
||||
break;
|
||||
case UHALLOW_REJOIN:
|
||||
rejoin_leave(sptr);
|
||||
/* join sent later when the host has been changed */
|
||||
break;
|
||||
}
|
||||
@@ -162,8 +163,7 @@ CMD_FUNC(m_vhost)
|
||||
vhost->virtuser ? olduser : sptr->user->username,
|
||||
sptr->user->realhost, vhost->virtuser ? vhost->virtuser : "",
|
||||
vhost->virtuser ? "@" : "", vhost->virthost);
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_joinandmode(sptr);
|
||||
userhost_changed(sptr);
|
||||
return 0;
|
||||
}
|
||||
if (i == -1)
|
||||
|
||||
+3
-4
@@ -65,8 +65,8 @@ void iNAH_host(aClient *sptr, char *host)
|
||||
if (!sptr->user)
|
||||
return;
|
||||
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_leave(sptr);
|
||||
userhost_save_current(sptr);
|
||||
|
||||
if (sptr->user->virthost)
|
||||
{
|
||||
MyFree(sptr->user->virthost);
|
||||
@@ -77,8 +77,7 @@ void iNAH_host(aClient *sptr, char *host)
|
||||
sendto_server(&me, 0, 0, ":%s SETHOST :%s", sptr->name, sptr->user->virthost);
|
||||
sptr->umodes |= UMODE_SETHOST;
|
||||
|
||||
if (UHOST_ALLOWED == UHALLOW_REJOIN)
|
||||
rejoin_joinandmode(sptr);
|
||||
userhost_changed(sptr);
|
||||
|
||||
sendto_one(sptr, err_str(RPL_HOSTHIDDEN), me.name, sptr->name, sptr->user->virthost);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user