]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/parse.c
Allow pre-defined server local channels ("&").
[ngircd-alex.git] / src / ngircd / parse.c
index d3065bf43c62627897056622a44e101728237f84..ec856a0c28fc05ff33b5d1930c79ee4bdb3f75b1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
  *
  * 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
@@ -9,11 +9,8 @@
  * Please read the file COPYING, README and AUTHORS for more information.
  */
 
-
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: parse.c,v 1.70 2008/01/13 16:12:49 fw Exp $";
-
 /**
  * @file
  * IRC command parser and validator.
@@ -67,6 +64,7 @@ static COMMAND My_Commands[] =
        { "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
        { "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
        { "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
+       { "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 },
        { "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
@@ -91,13 +89,18 @@ static COMMAND My_Commands[] =
        { "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
        { "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0 },
        { "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 },
+       { "SERVICE", IRC_SERVICE, 0xFFFF, 0, 0, 0 },
+       { "SERVLIST", IRC_SERVLIST, CLIENT_USER, 0, 0, 0 },
+       { "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 },
        { "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+       { "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "USER", IRC_USER, 0xFFFF, 0, 0, 0 },
        { "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 },
+       { "USERS", IRC_USERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "WALLOPS", IRC_WALLOPS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
        { "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 },
@@ -335,11 +338,39 @@ Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
 
 
 static bool
-Validate_Args( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
+#ifdef STRICT_RFC
+Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
+#else
+Validate_Args(UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed)
+#endif
 {
+#ifdef STRICT_RFC
+       int i;
+#endif
+
+       *Closed = false;
+
+#ifdef STRICT_RFC
        assert( Idx >= 0 );
        assert( Req != NULL );
-       *Closed = false;
+
+       /* CR and LF are never allowed in command parameters.
+        * But since we do accept lines terminated only with CR or LF in
+        * "non-RFC-compliant mode" (besides the correct CR+LF combination),
+        * this check can only trigger in "strict RFC" mode; therefore we
+        * optimize it away otherwise ... */
+       for (i = 0; i < Req->argc; i++) {
+               if (strchr(Req->argv[i], '\r') || strchr(Req->argv[i], '\n')) {
+                       Log(LOG_ERR,
+                           "Invalid character(s) in parameter (connection %d, command %s)!?",
+                           Idx, Req->command);
+                       if (!Conn_WriteStr(Idx,
+                                          "ERROR :Invalid character(s) in parameter!"))
+                               *Closed = true;
+                       return false;
+               }
+       }
+#endif
 
        return true;
 } /* Validate_Args */
@@ -350,7 +381,8 @@ static bool
 Handle_Numeric(CLIENT *client, REQUEST *Req)
 {
        static const struct _NUMERIC Numerics[] = {
-               { 005, IRC_Num_ISUPPORT },
+               {   5, IRC_Num_ISUPPORT },
+               {  20, NULL },
                { 376, IRC_Num_ENDOFMOTD }
        };
        int i, num;
@@ -358,8 +390,12 @@ Handle_Numeric(CLIENT *client, REQUEST *Req)
        CLIENT *prefix, *target = NULL;
 
        /* Determine target */
-       if (Req->argc > 0)
-               target = Client_Search(Req->argv[0]);
+       if (Req->argc > 0) {
+               if (strcmp(Req->argv[0], "*") != 0)
+                       target = Client_Search(Req->argv[0]);
+               else
+                       target = Client_ThisServer();
+       }
 
        if (!target) {
                /* Status code without target!? */
@@ -378,8 +414,11 @@ Handle_Numeric(CLIENT *client, REQUEST *Req)
                num = atoi(Req->command);
 
                for (i = 0; i < (int) ARRAY_SIZE(Numerics); i++) {
-                       if (num == Numerics[i].numeric)
+                       if (num == Numerics[i].numeric) {
+                               if (!Numerics[i].function)
+                                       return CONNECTED;
                                return Numerics[i].function(client, Req);
+                       }
                }
 
                LogDebug("Ignored status code %s from \"%s\".",
@@ -421,6 +460,7 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
         * wird die Verbindung geschlossen und false geliefert. */
        CLIENT *client;
        bool result = true;
+       int client_type;
        COMMAND *cmd;
 
        assert( Idx >= 0 );
@@ -431,8 +471,9 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
        assert( client != NULL );
 
        /* Numeric? */
-       if ((Client_Type(client) == CLIENT_SERVER ||
-            Client_Type(client) == CLIENT_UNKNOWNSERVER)
+       client_type = Client_Type(client);
+       if ((client_type == CLIENT_SERVER ||
+            client_type == CLIENT_UNKNOWNSERVER)
            && strlen(Req->command) == 3 && atoi(Req->command) > 1)
                return Handle_Numeric(client, Req);
 
@@ -444,7 +485,7 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
                        continue;
                }
 
-               if (!(Client_Type(client) & cmd->type))
+               if (!(client_type & cmd->type))
                        return IRC_WriteStrClient(client, ERR_NOTREGISTERED_MSG, Client_ID(client));
 
                /* Command is allowed for this client: call it and count produced bytes */
@@ -453,16 +494,16 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
                cmd->bytes += Conn_WCounter();
 
                /* Adjust counters */
-               if (Client_Type(client) != CLIENT_SERVER)
+               if (client_type != CLIENT_SERVER)
                        cmd->lcount++;
                else
                        cmd->rcount++;
                return result;
        }
 
-       if (Client_Type( client ) != CLIENT_USER &&
-           Client_Type( client ) != CLIENT_SERVER &&
-           Client_Type( client ) != CLIENT_SERVICE )
+       if (client_type != CLIENT_USER &&
+           client_type != CLIENT_SERVER &&
+           client_type != CLIENT_SERVICE )
                return true;
 
        /* Unknown command and registered connection: generate error: */