]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/irc-mode.c
Move "ClientHost" and "ClientUserNick" to end of [Global] section
[ngircd-alex.git] / src / ngircd / irc-mode.c
index 10d4641ea731db8a6a8698cd6dfa4915f5c3f9df..50b0db0476cf4eab116d8192606843ac0c351fe2 100644 (file)
@@ -1,19 +1,21 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
- *
- * IRC commands for mode changes (MODE, AWAY, ...)
  */
 
-
 #include "portab.h"
 
+/**
+ * @file
+ * IRC commands for mode changes (like MODE, AWAY, etc.)
+ */
+
 #include "imp.h"
 #include <assert.h>
 #include <stdio.h>
 
 #include "defines.h"
 #include "conn.h"
-#include "client.h"
 #include "channel.h"
 #include "irc-write.h"
 #include "lists.h"
 #include "log.h"
 #include "parse.h"
 #include "messages.h"
-#include "resolve.h"
 #include "conf.h"
 
 #include "exp.h"
@@ -187,6 +187,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        ERR_NOPRIVILEGES_MSG,
                                                        Client_ID(Origin));
                                break;
+
                        case 'o': /* IRC operator (only unsettable!) */
                                if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER ))
                                {
@@ -201,6 +202,15 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin ));
                                break;
 
+                       case 'x': /* Cloak hostname */
+                               if (Client_HasMode(Client, 'r'))
+                                       ok = IRC_WriteStrClient(Origin,
+                                                          ERR_RESTRICTED_MSG,
+                                                          Client_ID(Origin));
+                               else
+                                       x[0] = 'x';
+                               break;
+
                        default:
                                Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
                                if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
@@ -286,8 +296,17 @@ Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel)
        if (the_args[0])
                strlcat(the_modes, the_args, sizeof(the_modes));
 
-       return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG,
-               Client_ID(Origin), Channel_Name(Channel), the_modes);
+       if (!IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG,
+                               Client_ID(Origin), Channel_Name(Channel),
+                               the_modes))
+               return DISCONNECTED;
+#ifndef STRICT_RFC
+       if (!IRC_WriteStrClient(Origin, RPL_CREATIONTIME_MSG,
+                                 Client_ID(Origin), Channel_Name(Channel),
+                                 Channel_CreationTime(Channel)))
+               return DISCONNECTED;
+#endif
+       return CONNECTED;
 }
 
 
@@ -299,7 +318,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
 {
        char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2],
            argadd[CLIENT_PASS_LEN], *mode_ptr;
-       bool connected, set, modeok = true, skiponce, use_servermode = false, retval;
+       bool connected, set, skiponce, retval, onchannel, modeok, use_servermode;
        int mode_arg, arg_arg;
        CLIENT *client;
        long l;
@@ -313,25 +332,13 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
        if (Req->argc <= 1)
                return Channel_Mode_Answer_Request(Origin, Channel);
 
-       /* Is the user allowed to change modes? */
-       if (Client_Type(Client) == CLIENT_USER) {
-               /* Is the originating user on that channel? */
-               if (!Channel_IsMemberOf(Channel, Origin))
-                       return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG,
-                               Client_ID(Origin), Channel_Name(Channel));
-               modeok = false;
-               /* channel operator? */
-               if (strchr(Channel_UserModes(Channel, Origin), 'o'))
-                       modeok = true;
-               else if (Conf_OperCanMode) {
-                       /* IRC-Operators can use MODE as well */
-                       if (Client_OperByMe(Origin)) {
-                               modeok = true;
-                               if (Conf_OperServerMode)
-                                       use_servermode = true; /* Change Origin to Server */
-                       }
-               }
-       }
+       Channel_CheckAdminRights(Channel, Client, Origin,
+                                &onchannel, &modeok, &use_servermode);
+
+       if (!onchannel && !modeok)
+               return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG,
+                                         Client_ID(Origin),
+                                         Channel_Name(Channel));
 
        mode_arg = 1;
        mode_ptr = Req->argv[mode_arg];
@@ -494,6 +501,23 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                                goto chan_exit;
                        }
                        break;
+               case 'O': /* IRC operators only */
+                       if (modeok) {
+                               /* Only IRC operators are allowed to
+                                * set the 'O' channel mode! */
+                               if (set && !(Client_OperByMe(Client)
+                                   || Client_Type(Client) == CLIENT_SERVER))
+                                       connected = IRC_WriteStrClient(Origin,
+                                               ERR_NOPRIVILEGES_MSG,
+                                               Client_ID(Origin));
+                               else
+                                       x[0] = 'O';
+                       } else
+                               connected = IRC_WriteStrClient(Origin,
+                                               ERR_CHANOPRIVSNEEDED_MSG,
+                                               Client_ID(Origin),
+                                               Channel_Name(Channel));
+                               break;
                case 'P': /* Persistent channel */
                        if (modeok) {
                                /* Only IRC operators are allowed to