]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/irc-mode.c
Introduce numeric RPL_HOSTHIDDEN_MSG(396)
[ngircd-alex.git] / src / ngircd / irc-mode.c
index 71c9f796e952d592b28603c354012826b9dceeff..71557201d8d938f4a5ff65416f50eb487f78333d 100644 (file)
@@ -138,6 +138,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
 {
        char the_modes[COMMAND_LEN], x[2], *mode_ptr;
        bool ok, set;
+       bool send_RPL_HOSTHIDDEN_MSG = false;
        int mode_arg;
        size_t len;
 
@@ -229,6 +230,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        ERR_NOPRIVILEGES_MSG,
                                                        Client_ID(Origin));
                        break;
+               case 'B': /* Bot */
+                       if (Client_HasMode(Client, 'r'))
+                               ok = IRC_WriteStrClient(Origin,
+                                                       ERR_RESTRICTED_MSG,
+                                                       Client_ID(Origin));
+                       else
+                               x[0] = 'B';
+                       break;
                case 'c': /* Receive connect notices
                           * (only settable by IRC operators!) */
                        if (!set || Client_Type(Client) == CLIENT_SERVER
@@ -256,6 +265,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        ERR_RESTRICTED_MSG,
                                                        Client_ID(Origin));
                        break;
+               case 'R': /* Registered (not [un]settable by clients) */
+                       if (Client_Type(Client) == CLIENT_SERVER)
+                               x[0] = 'R';
+                       else
+                               ok = IRC_WriteStrClient(Origin,
+                                                       ERR_NICKREGISTER_MSG,
+                                                       Client_ID(Origin));
+                       break;
                case 'x': /* Cloak hostname */
                        if (Client_HasMode(Client, 'r'))
                                ok = IRC_WriteStrClient(Origin,
@@ -263,6 +280,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        Client_ID(Origin));
                        else
                                x[0] = 'x';
+                               send_RPL_HOSTHIDDEN_MSG = true;
                        break;
                default:
                        if (Client_Type(Client) != CLIENT_SERVER) {
@@ -332,6 +350,10 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                  "MODE %s :%s",
                                                  Client_ID(Target),
                                                  the_modes);
+                       if (send_RPL_HOSTHIDDEN_MSG)
+                               IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+                                                  Client_ID(Client),
+                                                  Client_HostnameCloaked(Client));
                }
                LogDebug("%s \"%s\": Mode change, now \"%s\".",
                         Client_TypeText(Target), Client_Mask(Target),
@@ -500,6 +522,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                switch (*mode_ptr) {
                /* --- Channel modes --- */
                case 'i': /* Invite only */
+               case 'M': /* Only identified nicks can write */
                case 'm': /* Moderated */
                case 'n': /* Only members can write */
                case 'R': /* Registered users only */
@@ -662,6 +685,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                /* --- Channel lists --- */
                case 'I': /* Invite lists */
                case 'b': /* Ban lists */
+               case 'e': /* Channel exception lists */
                        if (Mode_Limit_Reached(Client, mode_arg_count++))
                                goto chan_exit;
                        if (arg_arg > mode_arg) {
@@ -683,10 +707,17 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                                Req->argv[arg_arg][0] = '\0';
                                arg_arg++;
                        } else {
-                               if (*mode_ptr == 'I')
+                               switch (*mode_ptr) {
+                               case 'I':
                                        Channel_ShowInvites(Origin, Channel);
-                               else
+                                       break;
+                               case 'b':
                                        Channel_ShowBans(Origin, Channel);
+                                       break;
+                               case 'e':
+                                       Channel_ShowExcepts(Origin, Channel);
+                                       break;
+                               }
                        }
                        break;
                default:
@@ -836,7 +867,7 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req )
 /**
  * Add entries to channel invite, ban and exception lists.
  *
- * @param what Can be 'I' for invite or 'b' for ban list.
+ * @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
  * @param Prefix The originator of the command.
  * @param Client The sender of the command.
  * @param Channel The channel of which the list should be modified.
@@ -848,14 +879,18 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
            const char *Pattern)
 {
        const char *mask;
-       struct list_head *list;
+       struct list_head *list = NULL;
+       long int current_count;
 
        assert(Client != NULL);
        assert(Channel != NULL);
        assert(Pattern != NULL);
-       assert(what == 'I' || what == 'b');
+       assert(what == 'I' || what == 'b' || what == 'e');
 
        mask = Lists_MakeMask(Pattern);
+       current_count = Lists_Count(Channel_GetListInvites(Channel))
+                       + Lists_Count(Channel_GetListExcepts(Channel))
+                       + Lists_Count(Channel_GetListBans(Channel));
 
        switch(what) {
                case 'I':
@@ -864,12 +899,15 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
                case 'b':
                        list = Channel_GetListBans(Channel);
                        break;
+               case 'e':
+                       list = Channel_GetListExcepts(Channel);
+                       break;
        }
 
        if (Lists_CheckDupeMask(list, mask))
                return CONNECTED;
        if (Client_Type(Client) == CLIENT_USER &&
-           Lists_Count(list) >= MAX_HNDL_CHANNEL_LISTS)
+           current_count >= MAX_HNDL_CHANNEL_LISTS)
                return IRC_WriteStrClient(Client, ERR_LISTFULL_MSG,
                                          Client_ID(Client),
                                          Channel_Name(Channel), mask,
@@ -884,6 +922,10 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
                        if (!Channel_AddBan(Channel, mask))
                                return CONNECTED;
                        break;
+               case 'e':
+                       if (!Channel_AddExcept(Channel, mask))
+                               return CONNECTED;
+                       break;
        }
        return Send_ListChange(true, what, Prefix, Client, Channel, mask);
 }
@@ -892,7 +934,7 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
 /**
  * Delete entries from channel invite, ban and exeption lists.
  *
- * @param what Can be 'I' for invite or 'b' for ban list.
+ * @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
  * @param Prefix The originator of the command.
  * @param Client The sender of the command.
  * @param Channel The channel of which the list should be modified.
@@ -904,12 +946,12 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
              const char *Pattern)
 {
        const char *mask;
-       struct list_head *list;
+       struct list_head *list = NULL;
 
        assert(Client != NULL);
        assert(Channel != NULL);
        assert(Pattern != NULL);
-       assert(what == 'I' || what == 'b');
+       assert(what == 'I' || what == 'b' || what == 'e');
 
        mask = Lists_MakeMask(Pattern);
 
@@ -920,6 +962,9 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
                case 'b':
                        list = Channel_GetListBans(Channel);
                        break;
+               case 'e':
+                       list = Channel_GetListExcepts(Channel);
+                       break;
        }
 
        if (!Lists_CheckDupeMask(list, mask))
@@ -931,7 +976,7 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
 
 
 /**
- * Send information about changed channel ban/invite lists to clients.
+ * Send information about changed channel invite/ban/exception lists to clients.
  *
  * @param IsAdd true if the list item has been added, false otherwise.
  * @param ModeChar The mode to use (e. g. 'b' or 'I')