* account assignment causes a numeric reply during registration.
*/
if (HasHiddenHost(sptr))
- hide_hostmask(sptr, FLAG_HIDDENHOST);
+ hide_hostmask(sptr, HIDE_HOSTMASK_FLAG_HIDDENHOST);
if (IsInvisible(sptr))
++UserStats.inv_clients;
if (IsOper(sptr))
{ FLAG_WEBIRC, 'W' },
{ FLAG_SEE_IDLETIME,'t' },
{ FLAG_SECURITY_SERV,'D' },
- { FLAG_HIDDENHOST, 'x' }
+ { FLAG_KEEPCONN_ENABLED, 'K' },
+ { FLAG_HIDDENHOST, 'x' },
+ { FLAG_NOTCONN, 'Z' }
};
/** Length of #userModeList. */
if (MyUser(sptr)) {
const char* channel_name;
struct Membership *member;
- if (!force && !IsXtraOp(sptr) && (channel_name = find_no_nickchange_channel(sptr))) {
+ if (!force && !IsXtraOp(sptr) && (channel_name = find_no_nickchange_channel(sptr, nick))) {
return send_reply(cptr, ERR_BANNICKCHANGE, channel_name);
}
/*
}
else {
/* Local client setting NICK the first time */
- strcpy(cli_name(sptr), nick);
+ if(!force)
+ strcpy(cli_name(sptr), nick);
+ else {
+ /* use a "temponary" nick here (we'll switch later) */
+ char tmpnick[NICKLEN + 2];
+ int tmpnickend;
+ strcpy(tmpnick, nick);
+ /* we need at least 10 characters */
+ if (strlen(tmpnick) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN)) - 10)
+ tmpnick[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))-10] = '\0';
+ tmpnickend = strlen(tmpnick);
+
+ do { /* get a non-used nick... */
+ sprintf(tmpnick + tmpnickend, "[rz%d]", ircrandom() % 10000);
+ } while(FindClient(tmpnick));
+ strcpy(cli_name(sptr), tmpnick);
+ }
hAddClient(sptr);
return auth_set_nick(cli_auth(sptr), nick);
}
}
if (cptr && MyUser(cptr))
send_umode(cptr, sptr, old, ALL_UMODES, 0);
+ if (sptr && sptr != cptr && MyUser(sptr))
+ send_umode(sptr, sptr, old, ALL_UMODES, 0);
}
struct Membership *chan;
char buf[HOSTLEN];
- switch (flag) {
- case FLAG_HIDDENHOST:
+ if (flag & HIDE_HOSTMASK_FLAG_HIDDENHOST) {
/* Local users cannot set +x unless FEAT_HOST_HIDING is true. */
if (MyConnect(cptr) && !feature_bool(FEAT_HOST_HIDING))
return 0;
- break;
- case FLAG_ACCOUNT:
- case FLAG_FAKEHOST:
- case FLAG_FAKEIDENT:
+ }
+ if (flag & (HIDE_HOSTMASK_FLAG_ACCOUNT | HIDE_HOSTMASK_FLAG_FAKEHOST | HIDE_HOSTMASK_FLAG_FAKEIDENT)) {
/* Invalidate all bans against the user so we check them again */
for (chan = (cli_user(cptr))->channel; chan;
chan = chan->next_channel)
ClearBanValid(chan);
- break;
- default:
- /* default: no special handling */
- break;
}
/* Set flags and stop if no fakehost has to be applied. */
- SetFlag(cptr, flag);
+ if(flag & HIDE_HOSTMASK_FLAG_HIDDENHOST)
+ SetFlag(cptr, FLAG_HIDDENHOST);
+ if(flag & HIDE_HOSTMASK_FLAG_ACCOUNT)
+ SetFlag(cptr, FLAG_ACCOUNT);
+ if(flag & HIDE_HOSTMASK_FLAG_FAKEHOST)
+ SetFlag(cptr, FLAG_FAKEHOST);
+ if(flag & HIDE_HOSTMASK_FLAG_FAKEIDENT)
+ SetFlag(cptr, FLAG_FAKEIDENT);
+
if(!HasHiddenHost(cptr))
return 0;
/* Generate new fakehost. */
- if(IsFakeHost(cptr)) ircd_strncpy(buf, cli_user(cptr)->fakehost, HOSTLEN);
- else if (IsAccount(cptr)) ircd_snprintf(0, buf, HOSTLEN, "%s.%s", cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
- else return 0;
- if(strncmp(buf, cli_user(cptr)->host, HOSTLEN) == 0 && (!IsFakeIdent(cptr) || strncmp(cli_user(cptr)->fakeuser, cli_user(cptr)->username, USERLEN) == 0)) return 0;
+ unsigned int reregister = 0;
+ if(IsFakeHost(cptr) || IsAccount(cptr)) {
+ if(IsFakeHost(cptr))
+ ircd_strncpy(buf, cli_user(cptr)->fakehost, HOSTLEN);
+ else
+ ircd_snprintf(0, buf, HOSTLEN, "%s.%s", cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
+ if(strncmp(buf, cli_user(cptr)->host, HOSTLEN))
+ reregister |= HIDE_HOSTMASK_FLAG_FAKEHOST;
+ }
+ if(IsFakeIdent(cptr)) {
+ if(strncmp(cli_user(cptr)->fakeuser, cli_user(cptr)->username, USERLEN))
+ reregister |= HIDE_HOSTMASK_FLAG_FAKEIDENT;
+ }
+
+ if (!reregister) return 0;
/* Remove all "valid" marks on the bans. This forces them to be
* rechecked if the ban is accessed again.
/* Quit user and set the previously generated fakehost. */
sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Registered");
- ircd_strncpy(cli_user(cptr)->host, buf, HOSTLEN);
-
- /* spoof also the username if username is passed */
- if(IsFakeIdent(cptr)) {
- if(strncmp(cli_user(cptr)->username, cli_user(cptr)->fakeuser, USERLEN) != 0) {
- ircd_strncpy(cli_username(cptr), cli_user(cptr)->fakeuser, USERLEN);
- ircd_strncpy(cli_user(cptr)->username, cli_user(cptr)->fakeuser, USERLEN);
- }
- /* ok, the client is now fully hidden, so let them know -- hikari */
- if (MyConnect(cptr))
+ if(reregister & HIDE_HOSTMASK_FLAG_FAKEHOST)
+ ircd_strncpy(cli_user(cptr)->host, buf, HOSTLEN);
+ if(reregister & HIDE_HOSTMASK_FLAG_FAKEIDENT)
+ ircd_strncpy(cli_user(cptr)->username, cli_user(cptr)->fakeuser, USERLEN);
+
+
+ /* ok, the client is now fully hidden, so let them know -- hikari */
+ if(MyConnect(cptr)) {
+ if (IsFakeIdent(cptr))
send_reply(cptr, RPL_HOSTUSERHIDDEN, cli_user(cptr)->username, cli_user(cptr)->host);
- } else {
- /* ok, the client is now fully hidden, so let them know -- hikari */
- if (MyConnect(cptr))
+ else
send_reply(cptr, RPL_HOSTHIDDEN, cli_user(cptr)->host);
}
else {
SetDelayedJoin(chan);
}
+
+ /*
+ * Check if the client is actually overriding a ban with the
+ * mask change, if so, kick him out of the channel.
+ * We have to proceed that way to ensure data consistency (join + kick)
+ */
+ if (find_ban(cptr, chan->channel->banlist)) {
+ /* Silentely kick in case of delayed join */
+ if (chan->channel->mode.mode & MODE_DELJOINS) {
+ sendcmdto_one(&his, CMD_KICK, cptr, "%H %C :Ban override", chan->channel, cptr);
+ CheckDelayedJoins(chan->channel);
+
+ } else {
+ /* Otherwise publicly kick */
+ sendcmdto_serv_butone(&me, CMD_KICK, NULL, "%H %C :Ban override", chan->channel, cptr);
+ sendcmdto_channel_butserv_butone(&his, CMD_KICK, chan->channel, NULL, 0, "%H %C :Ban override", chan->channel, cptr);
+ make_zombie(chan, cptr, &me, &me, chan->channel);
+ }
+ }
}
return 0;
}
char buf[BUFSIZE];
int prop = 0;
int do_host_hiding = 0;
- char* account = NULL, *fakehost = NULL;
+ char* account = NULL, *fakehost = NULL, *keepconn = NULL;
struct Membership *chan;
what = MODE_ADD;
else
ClearWebIRC(sptr);
break;
+ case 'K':
+ if (what == MODE_ADD) {
+ if(*(p + 1) == 0)
+ break;
+ keepconn = *(++p);
+ SetKeepConnEnabled(sptr);
+ } else {
+ ClearKeepConnEnabled(sptr);
+ }
+ break;
case 'r':
if (*(p + 1) && (what == MODE_ADD)) {
account = *(++p);
case 'z': /* Formerly SSL mode; we ignore it. */
break;
#endif
+ case 'Z':
+ if (what == MODE_ADD)
+ SetNotConn(sptr);
+ else
+ ClearNotConn(sptr);
+ break;
default:
send_reply(sptr, ERR_UMODEUNKNOWNFLAG, *m);
break;
ClrFlag(sptr, FLAG_FAKEHOST);
if (!FlagHas(&setflags, FLAG_SEE_IDLETIME) && IsSeeIdletime(sptr))
ClrFlag(sptr, FLAG_SEE_IDLETIME);
+ if (!FlagHas(&setflags, FLAG_NOTCONN) && IsNotConn(sptr))
+ ClrFlag(sptr, FLAG_NOTCONN);
/*
* new umode; servers and privileged opers can set it, local users cannot;
* prevents users from /kick'ing or /mode -o'ing
ClearHiddenOper(sptr);
if (!FlagHas(&setflags, FLAG_OVERRIDECC) && IsOverrideCC(sptr) && !HasPriv(sptr, PRIV_UMODE_OVERRIDECC))
ClearOverrideCC(sptr);
+ if (!FlagHas(&setflags, FLAG_KEEPCONN_ENABLED) && IsKeepConnEnabled(sptr) && !HasPriv(sptr, PRIV_SET_KEEPCONN))
+ ClearKeepConnEnabled(sptr);
+ if(keepconn && !HasPriv(sptr, PRIV_SET_KEEPCONN))
+ keepconn = NULL;
/* Opers are able to fake the webirc usermode only if FEAT_FAKE_WEBIRC is true. */
if (!FlagHas(&setflags, FLAG_WEBIRC) && IsWebIRC(sptr) && !(feature_bool(FEAT_FAKE_WEBIRC) && IsOper(sptr)))
ClearWebIRC(sptr);
if (!FlagHas(&setflags, FLAG_FAKEHOST) && IsFakeHost(sptr)) {
ircd_strncpy(cli_user(sptr)->fakehost, fakehost, HOSTLEN);
}
+ if (!FlagHas(&setflags, FLAG_KEEPCONN_ENABLED) && IsKeepConnEnabled(sptr)) {
+ sptr->keepconn = atoi(keepconn);
+ } else if(keepconn && sptr->keepconn != atoi(keepconn)) {
+ FlagClr(&setflags, FLAG_KEEPCONN_ENABLED);
+ sptr->keepconn = atoi(keepconn);
+ }
if (IsRegistered(sptr)) {
if(do_host_hiding)
int flag;
char *m;
int what = MODE_NULL;
- int add_fakehost = 0, add_account = 0;
+ int add_fakehost = 0, add_account = 0, add_keepconn = 0;
/*
* Build a string in umodeBuf to represent the change in the user's
if(!serv_modes || FlagHas(old, flag)) continue;
add_fakehost = 1;
}
+
+ if(flag == FLAG_KEEPCONN_ENABLED) {
+ add_keepconn = 1;
+ }
switch (sendset)
{
while((*m++ = *t++)) ; /* Empty loop */
--m; /* back up over previous nul-termination */
}
+
+ if(add_keepconn) {
+ *m++ = ' ';
+ m += sprintf(m, "%u", sptr->keepconn);
+ }
*m = '\0';
if (*umodeBuf && cptr)