- bessere Debug-Ausgaben,
[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.2 2001/12/23 21:56:47 alex Exp $
13  *
14  * parse.c: Parsen der Client-Anfragen
15  *
16  * $Log: parse.c,v $
17  * Revision 1.2  2001/12/23 21:56:47  alex
18  * - bessere Debug-Ausgaben,
19  * - Bug im Parameter-Parser behoben (bei "langem" Parameter)
20  * - erste IRC-Befehle werden erkannt :-)
21  *
22  * Revision 1.1  2001/12/21 23:53:16  alex
23  * - Modul zum Parsen von Client-Requests begonnen.
24  */
25
26
27 #include <portab.h>
28 #include "global.h"
29
30 #include <imp.h>
31 #include <assert.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "client.h"
36 #include "conn.h"
37 #include "irc.h"
38 #include "log.h"
39 #include "messages.h"
40
41 #include <exp.h>
42 #include "parse.h"
43
44
45 LOCAL VOID Init_Request( REQUEST *Req );
46
47 LOCAL BOOLEAN Parse_Error( CONN_ID Idx, CHAR *Error );
48
49 LOCAL BOOLEAN Validate_Prefix( REQUEST *Req );
50 LOCAL BOOLEAN Validate_Command( REQUEST *Req );
51 LOCAL BOOLEAN Validate_Args( REQUEST *Req );
52
53 LOCAL BOOLEAN Handle_Request( CONN_ID Idx, REQUEST *Req );
54
55
56 GLOBAL VOID Parse_Init( VOID )
57 {
58 } /* Parse_Init */
59
60
61 GLOBAL VOID Parse_Exit( VOID )
62 {
63 } /* Parse_Exit */
64
65
66 GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request )
67 {
68         /* Client-Request parsen. Bei einem schwerwiegenden Fehler wird
69          * die Verbindung geschlossen und FALSE geliefert.
70          * Der Aufbau gueltiger Requests ist in RFC 2812, 2.3 definiert. */
71
72         REQUEST req;
73         CHAR *start, *ptr;
74
75         assert( Idx >= 0 );
76         assert( Request != NULL );
77
78 #ifdef DEBUG
79         Log( LOG_DEBUG, " <- connection %d: '%s'.", Idx, Request );
80 #endif
81         
82         Init_Request( &req );
83
84         /* gibt es ein Prefix? */
85         if( Request[0] == ':' )
86         {
87                 /* Prefix vorhanden */
88                 req.prefix = Request + 1;
89                 ptr = strchr( Request, ' ' );
90                 if( ! ptr ) return Parse_Error( Idx, "Invalid prefix (command missing!?)" );
91                 *ptr = '\0';
92                 start = ptr + 1;
93         }
94         else start = Request;
95
96         if( ! Validate_Prefix( &req )) return Parse_Error( Idx, "Invalid prefix");
97
98         /* Befehl */
99         ptr = strchr( start, ' ' );
100         if( ptr ) *ptr = '\0';
101         req.command = start;
102
103         if( ! Validate_Command( &req )) return Parse_Error( Idx, "Invalid command" );
104
105         /* Argumente, Parameter */
106         if( ptr )
107         {
108                 /* Prinzipiell gibt es welche :-) */
109                 start = ptr + 1;
110                 while( start )
111                 {
112                         /* Parameter-String "zerlegen" */
113                         if( start[0] == ':' )
114                         {
115                                 req.argv[req.argc] = start + 1;
116                                 ptr = NULL;
117                         }
118                         else
119                         {
120                                 req.argv[req.argc] = start;
121                                 ptr = strchr( start, ' ' );
122                                 if( ptr ) *ptr = '\0';
123                         }
124                         
125                         req.argc++;
126
127                         if( start[0] == ':' ) break;
128                         if( req.argc > 14 ) break;
129                         
130                         if( ptr ) start = ptr + 1;
131                         else start = NULL;
132                 }
133         }
134         
135         if( ! Validate_Args( &req )) return Parse_Error( Idx, "Invalid argument(s)" );
136         
137         return Handle_Request( Idx, &req );
138 } /* Parse_Request */
139
140
141 LOCAL VOID Init_Request( REQUEST *Req )
142 {
143         /* Neue Request-Struktur initialisieren */
144
145         INT i;
146         
147         assert( Req != NULL );
148
149         Req->prefix = NULL;
150         Req->command = NULL;
151         for( i = 0; i < 15; Req->argv[i++] = NULL );
152         Req->argc = 0;
153 } /* Init_Request */
154
155
156 LOCAL BOOLEAN Parse_Error( CONN_ID Idx, CHAR *Error )
157 {
158         /* Fehler beim Parsen. Fehlermeldung an den Client schicken.
159          * TRUE: Connection wurde durch diese Funktion nicht geschlossen,
160          * FALSE: Connection wurde terminiert. */
161         
162         CHAR msg[256];
163         
164         assert( Idx >= 0 );
165         assert( Error != NULL );
166
167         sprintf( msg, "Parse error: %s!", Error );
168         return Conn_WriteStr( Idx, msg );
169 } /* Parse_Error */
170
171
172 LOCAL BOOLEAN Validate_Prefix( REQUEST *Req )
173 {
174         assert( Req != NULL );
175         return TRUE;
176 } /* Validate_Prefix */
177
178
179 LOCAL BOOLEAN Validate_Command( REQUEST *Req )
180 {
181         assert( Req != NULL );
182         return TRUE;
183 } /* Validate_Comman */
184
185
186 LOCAL BOOLEAN Validate_Args( REQUEST *Req )
187 {
188         assert( Req != NULL );
189         return TRUE;
190 } /* Validate_Args */
191
192
193 LOCAL BOOLEAN Handle_Request( CONN_ID Idx, REQUEST *Req )
194 {
195         /* Client-Request verarbeiten. Bei einem schwerwiegenden Fehler
196          * wird die Verbindung geschlossen und FALSE geliefert. */
197
198         CLIENT *client;
199
200         assert( Idx >= 0 );
201         assert( Req != NULL );
202         assert( Req->command != NULL );
203
204 #ifdef DEBUG
205         Log( LOG_DEBUG, "    connection %d: '%s', %d %s,%s prefix.", Idx, Req->command, Req->argc, Req->argc == 1 ? "parameter" : "parameters", Req->prefix ? "" : " no" );
206 #endif
207
208         client = Client_GetFromConn( Idx );
209         assert( client != NULL );
210
211         if( strcmp( Req->command, "PASS" ) == 0 ) return IRC_PASS( client, Req );
212         else if( strcmp( Req->command, "NICK" ) == 0 ) return IRC_NICK( client, Req );
213         else if( strcmp( Req->command, "USER" ) == 0 ) return IRC_USER( client, Req );
214
215         /* Unbekannter Befehl */
216         Conn_WriteStr( Idx, ERR_UNKNOWNCOMMAND_MSG, Req->command );
217
218         return TRUE;
219 } /* Handle_Request */
220
221
222 /* -eof- */