keep in sync with OGN upstream (SVN-326)
[ircu2.10.12-pk.git] / ircd / s_user.c
index c10eb72360d8b152f0241489e197f3346f2bbb77..fc502ae568d77cc656ffc547d8f8a65116c8397a 100644 (file)
@@ -485,7 +485,7 @@ int register_user(struct Client *cptr, struct Client *sptr)
    * 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))
@@ -667,7 +667,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
     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);
       }
       /*
@@ -979,35 +979,47 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
   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.
@@ -1018,20 +1030,17 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
 
   /* 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);
   }
 
@@ -1060,6 +1069,25 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
     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;
 }
@@ -1393,7 +1421,7 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc,
 
   if (IsRegistered(sptr)) {
     if(do_host_hiding)
-      hide_hostmask(sptr, 0);
+      hide_hostmask(sptr, HIDE_HOSTMASK_FLAG_HIDDENHOST);
 
     if (!FlagHas(&setflags, FLAG_OPER) && IsOper(sptr)) {
       /* user now oper */