]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/parse.c
98d5094e76e2b43e0e7591258213d230f3aecb9f
[ngircd-alex.git] / src / ngircd / parse.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001 by Alexander Barton (alex@barton.de)
4  *
5  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6  * der GNU General Public License (GPL), wie von der Free Software Foundation
7  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10  * der an comBase beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: parse.c,v 1.6 2001/12/26 14:45:37 alex Exp $
13  *
14  * parse.c: Parsen der Client-Anfragen
15  *
16  * $Log: parse.c,v $
17  * Revision 1.6  2001/12/26 14:45:37  alex
18  * - "Code Cleanups".
19  *
20  * Revision 1.5  2001/12/26 03:23:03  alex
21  * - PING/PONG-Befehle implementiert.
22  *
23  * Revision 1.4  2001/12/25 22:04:26  alex
24  * - Aenderungen an den Debug- und Logging-Funktionen.
25  *
26  * Revision 1.3  2001/12/25 19:18:36  alex
27  * - Gross- und Kleinschreibung der IRC-Befehle wird ignoriert.
28  * - bessere Debug-Ausgaben.
29  *
30  * Revision 1.2  2001/12/23 21:56:47  alex
31  * - bessere Debug-Ausgaben,
32  * - Bug im Parameter-Parser behoben (bei "langem" Parameter)
33  * - erste IRC-Befehle werden erkannt :-)
34  *
35  * Revision 1.1  2001/12/21 23:53:16  alex
36  * - Modul zum Parsen von Client-Requests begonnen.
37  */
38
39
40 #include <portab.h>
41 #include "global.h"
42
43 #include <imp.h>
44 #include <assert.h>
45 #include <stdio.h>
46 #include <string.h>
47
48 #include "client.h"
49 #include "conn.h"
50 #include "irc.h"
51 #include "log.h"
52 #include "messages.h"
53
54 #include <exp.h>
55 #include "parse.h"
56
57
58 LOCAL VOID Init_Request( REQUEST *Req );
59
60 LOCAL BOOLEAN Parse_Error( CONN_ID Idx, CHAR *Error );
61
62 LOCAL BOOLEAN Validate_Prefix( REQUEST *Req );
63 LOCAL BOOLEAN Validate_Command( REQUEST *Req );
64 LOCAL BOOLEAN Validate_Args( REQUEST *Req );
65
66 LOCAL BOOLEAN Handle_Request( CONN_ID Idx, REQUEST *Req );
67
68
69 GLOBAL VOID Parse_Init( VOID )
70 {
71 } /* Parse_Init */
72
73
74 GLOBAL VOID Parse_Exit( VOID )
75 {
76 } /* Parse_Exit */
77
78
79 GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request )
80 {
81         /* Client-Request parsen. Bei einem schwerwiegenden Fehler wird
82          * die Verbindung geschlossen und FALSE geliefert.
83          * Der Aufbau gueltiger Requests ist in RFC 2812, 2.3 definiert. */
84
85         REQUEST req;
86         CHAR *start, *ptr;
87
88         assert( Idx >= 0 );
89         assert( Request != NULL );
90
91 #ifdef SNIFFER
92         Log( LOG_DEBUG, " <- connection %d: '%s'.", Idx, Request );
93 #endif
94         
95         Init_Request( &req );
96
97         /* gibt es ein Prefix? */
98         if( Request[0] == ':' )
99         {
100                 /* Prefix vorhanden */
101                 req.prefix = Request + 1;
102                 ptr = strchr( Request, ' ' );
103                 if( ! ptr ) return Parse_Error( Idx, "Invalid prefix (command missing!?)" );
104                 *ptr = '\0';
105                 start = ptr + 1;
106         }
107         else start = Request;
108
109         if( ! Validate_Prefix( &req )) return Parse_Error( Idx, "Invalid prefix");
110
111         /* Befehl */
112         ptr = strchr( start, ' ' );
113         if( ptr ) *ptr = '\0';
114         req.command = start;
115
116         if( ! Validate_Command( &req )) return Parse_Error( Idx, "Invalid command" );
117
118         /* Argumente, Parameter */
119         if( ptr )
120         {
121                 /* Prinzipiell gibt es welche :-) */
122                 start = ptr + 1;
123                 while( start )
124                 {
125                         /* Parameter-String "zerlegen" */
126                         if( start[0] == ':' )
127                         {
128                                 req.argv[req.argc] = start + 1;
129                                 ptr = NULL;
130                         }
131                         else
132                         {
133                                 req.argv[req.argc] = start;
134                                 ptr = strchr( start, ' ' );
135                                 if( ptr ) *ptr = '\0';
136                         }
137                         
138                         req.argc++;
139
140                         if( start[0] == ':' ) break;
141                         if( req.argc > 14 ) break;
142                         
143                         if( ptr ) start = ptr + 1;
144                         else start = NULL;
145                 }
146         }
147         
148         if( ! Validate_Args( &req )) return Parse_Error( Idx, "Invalid argument(s)" );
149         
150         return Handle_Request( Idx, &req );
151 } /* Parse_Request */
152
153
154 LOCAL VOID Init_Request( REQUEST *Req )
155 {
156         /* Neue Request-Struktur initialisieren */
157
158         INT i;
159         
160         assert( Req != NULL );
161
162         Req->prefix = NULL;
163         Req->command = NULL;
164         for( i = 0; i < 15; Req->argv[i++] = NULL );
165         Req->argc = 0;
166 } /* Init_Request */
167
168
169 LOCAL BOOLEAN Parse_Error( CONN_ID Idx, CHAR *Error )
170 {
171         /* Fehler beim Parsen. Fehlermeldung an den Client schicken.
172          * TRUE: Connection wurde durch diese Funktion nicht geschlossen,
173          * FALSE: Connection wurde terminiert. */
174         
175         CHAR msg[256];
176         
177         assert( Idx >= 0 );
178         assert( Error != NULL );
179
180         sprintf( msg, "Parse error: %s!", Error );
181         return Conn_WriteStr( Idx, msg );
182 } /* Parse_Error */
183
184
185 LOCAL BOOLEAN Validate_Prefix( REQUEST *Req )
186 {
187         assert( Req != NULL );
188         return TRUE;
189 } /* Validate_Prefix */
190
191
192 LOCAL BOOLEAN Validate_Command( REQUEST *Req )
193 {
194         assert( Req != NULL );
195         return TRUE;
196 } /* Validate_Comman */
197
198
199 LOCAL BOOLEAN Validate_Args( REQUEST *Req )
200 {
201         assert( Req != NULL );
202         return TRUE;
203 } /* Validate_Args */
204
205
206 LOCAL BOOLEAN Handle_Request( CONN_ID Idx, REQUEST *Req )
207 {
208         /* Client-Request verarbeiten. Bei einem schwerwiegenden Fehler
209          * wird die Verbindung geschlossen und FALSE geliefert. */
210
211         CLIENT *client;
212
213         assert( Idx >= 0 );
214         assert( Req != NULL );
215         assert( Req->command != NULL );
216
217 #ifdef SNIFFER
218         Log( LOG_DEBUG, "    connection %d: '%s', %d %s,%s prefix.", Idx, Req->command, Req->argc, Req->argc == 1 ? "parameter" : "parameters", Req->prefix ? "" : " no" );
219 #endif
220         
221         client = Client_GetFromConn( Idx );
222         assert( client != NULL );
223
224         if( strcasecmp( Req->command, "PASS" ) == 0 ) return IRC_PASS( client, Req );
225         else if( strcasecmp( Req->command, "NICK" ) == 0 ) return IRC_NICK( client, Req );
226         else if( strcasecmp( Req->command, "USER" ) == 0 ) return IRC_USER( client, Req );
227         else if( strcasecmp( Req->command, "QUIT" ) == 0 ) return IRC_QUIT( client, Req );
228         else if( strcasecmp( Req->command, "PING" ) == 0 ) return IRC_PING( client, Req );
229         else if( strcasecmp( Req->command, "PONG" ) == 0 ) return IRC_PONG( client, Req );
230         else if( strcasecmp( Req->command, "MOTD" ) == 0 ) return IRC_MOTD( client, Req );
231
232         /* Unbekannter Befehl */
233         IRC_WriteStrClient( client, This_Server, ERR_UNKNOWNCOMMAND_MSG, Client_Name( client ), Req->command );
234
235         Log( LOG_DEBUG, "Connection %d: Unknown command '%s', %d %s,%s prefix.", Idx, Req->command, Req->argc, Req->argc == 1 ? "parameter" : "parameters", Req->prefix ? "" : " no" );
236         
237         return TRUE;
238 } /* Handle_Request */
239
240
241 /* -eof- */