ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/parse.C
Revision: 1.5
Committed: Wed Aug 29 21:01:18 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.4: +15 -62 lines
Log Message:
- reduced ifdefs by moving __GNUC__ and friends to svsconfig.h
- #define to enum { } in tools.h
- corrected log levels a bit
- made timersub an inline function instead of a macro
- added a simple garbage collection mechanism for postponed freeing of lost
  memory chunks
- enhanced type_traits
- merged inspircd1.2 support with upstream
- reformatting
- renamed TTP to a more "standard" PRItime and STP to PRIsize

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * parse.C: Parsing of IRC messages.
3 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
4 pippijn 1.1 *
5 pippijn 1.4 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6 pippijn 1.1 */
7    
8 pippijn 1.5 static char const rcsid[] = "$Id: parse.C,v 1.4 2007-08-28 17:08:12 pippijn Exp $";
9 pippijn 1.1
10     #include "atheme.h"
11     #include "uplink.h"
12     #include "pmodule.h"
13    
14     /* by default, we want the 2.8.21 parser */
15     void (*parse) (char *line) = &irc_parse;
16    
17     /* parses a standard 2.8.21 style IRC stream */
18     void
19     irc_parse (char *line)
20     {
21     sourceinfo_t si;
22     char *pos;
23     char *origin = NULL;
24     char *command = NULL;
25     char *message = NULL;
26     char *parv[MAXPARC + 1];
27     static char coreLine[BUFSIZE];
28     int parc = 0;
29     unsigned int i;
30 pippijn 1.4 pcommand_t const *pcmd;
31 pippijn 1.1
32     /* clear the parv */
33     for (i = 0; i <= MAXPARC; i++)
34     parv[i] = NULL;
35    
36     memset (&si, '\0', sizeof si);
37     si.connection = curr_uplink->conn;
38    
39     if (line != NULL)
40     {
41     /* sometimes we'll get a blank line with just a \n on it...
42     * catch those here... they'll core us later on if we don't
43     */
44     if (*line == '\n')
45     return;
46     if (*line == '\000')
47     return;
48    
49     /* copy the original line so we know what we crashed on */
50     memset ((char *) &coreLine, '\0', BUFSIZE);
51     strlcpy (coreLine, line, BUFSIZE);
52    
53     slog (LG_RAWDATA, "-> %s", line);
54    
55     /* find the first space */
56     if ((pos = strchr (line, ' ')))
57     {
58     *pos = '\0';
59     pos++;
60     /* if it starts with a : we have a prefix/origin
61     * pull the origin off into `origin', and have pos for the
62     * command, message will be the part afterwards
63     */
64     if (*line == ':')
65     {
66     origin = line + 1;
67    
68     si.s = server_find (origin);
69     si.su = user_find (origin);
70    
71     if ((message = strchr (pos, ' ')))
72     {
73     *message = '\0';
74     message++;
75     command = pos;
76     }
77     else
78     {
79     command = pos;
80     message = NULL;
81     }
82     }
83     else
84     {
85     if (me.recvsvr)
86     {
87     origin = me.actual;
88     si.s = server_find (origin);
89     }
90     message = pos;
91     command = line;
92     }
93     }
94     else
95     {
96     if (me.recvsvr)
97     {
98     origin = me.actual;
99     si.s = server_find (origin);
100     }
101     command = line;
102     message = NULL;
103     }
104     if (!si.s && !si.su && me.recvsvr)
105 pippijn 1.5 return slog (LG_INFO, "irc_parse(): got message from nonexistant user or server: %s", origin);
106 pippijn 1.1 si.smu = si.su != NULL ? si.su->myuser : NULL;
107    
108     /* okay, the nasty part is over, now we need to make a
109     * parv out of what's left
110     */
111    
112     if (message)
113     {
114     if (*message == ':')
115     {
116     message++;
117     parv[0] = message;
118     parc = 1;
119     }
120     else
121     parc = tokenize (message, parv);
122     }
123     else
124     parc = 0;
125    
126     /* now we should have origin (or NULL), command, and a parv
127     * with it's accompanying parc... let's make ABSOLUTELY sure
128     */
129     if (!command)
130 pippijn 1.5 return slog (LG_DEBUG, "irc_parse(): command not found: %s", coreLine);
131 pippijn 1.1
132     /* take the command through the hash table */
133     if ((pcmd = pcommand_find (command)))
134     {
135     if (si.su && !(pcmd->sourcetype & MSRC_USER))
136 pippijn 1.5 return slog (LG_INFO, "irc_parse(): user %s sent disallowed command %s", si.su->nick, pcmd->token);
137 pippijn 1.1 else if (si.s && !(pcmd->sourcetype & MSRC_SERVER))
138 pippijn 1.5 return slog (LG_INFO, "irc_parse(): server %s sent disallowed command %s", si.s->name, pcmd->token);
139 pippijn 1.1 else if (!me.recvsvr && !(pcmd->sourcetype & MSRC_UNREG))
140 pippijn 1.5 return slog (LG_INFO, "irc_parse(): unregistered server sent disallowed command %s", pcmd->token);
141 pippijn 1.1 if (parc < pcmd->minparc)
142 pippijn 1.5 return slog (LG_INFO, "irc_parse(): insufficient parameters for command %s", pcmd->token);
143 pippijn 1.1 if (pcmd->handler)
144 pippijn 1.5 pcmd->handler (&si, parc, parv);
145 pippijn 1.1 }
146     }
147     }
148    
149     /* parses a P10 IRC stream */
150     void
151     p10_parse (char *line)
152     {
153     sourceinfo_t si;
154     char *pos;
155     char *origin = NULL;
156     char *command = NULL;
157     char *message = NULL;
158     char *parv[MAXPARC + 1];
159     static char coreLine[BUFSIZE];
160     int parc = 0;
161     unsigned int i;
162 pippijn 1.4 pcommand_t const *pcmd;
163 pippijn 1.1
164     /* clear the parv */
165     for (i = 0; i <= MAXPARC; i++)
166     parv[i] = NULL;
167    
168     memset (&si, '\0', sizeof si);
169     si.connection = curr_uplink->conn;
170    
171     if (line != NULL)
172     {
173     /* sometimes we'll get a blank line with just a \n on it...
174     * catch those here... they'll core us later on if we don't
175     */
176     if (*line == '\n')
177     return;
178     if (*line == '\000')
179     return;
180    
181     /* copy the original line so we know what we crashed on */
182     memset ((char *) &coreLine, '\0', BUFSIZE);
183     strlcpy (coreLine, line, BUFSIZE);
184    
185     slog (LG_RAWDATA, "-> %s", line);
186    
187     /* find the first spcae */
188     if ((pos = strchr (line, ' ')))
189     {
190     *pos = '\0';
191     pos++;
192     /* if it starts with a : we have a prefix/origin
193     * pull the origin off into `origin', and have pos for the
194     * command, message will be the part afterwards
195     */
196     if (*line == ':' || me.recvsvr == true)
197     {
198     origin = line;
199     if (*origin == ':')
200     {
201     origin++;
202     si.s = server_find (origin);
203     si.su = user_find_named (origin);
204     }
205     else
206     {
207     si.s = server_find (origin);
208     si.su = user_find (origin);
209     }
210    
211     if ((message = strchr (pos, ' ')))
212     {
213     *message = '\0';
214     message++;
215     command = pos;
216     }
217     else
218     {
219     command = pos;
220     message = NULL;
221     }
222     }
223     else
224     {
225     message = pos;
226     command = line;
227     }
228     }
229    
230     if (!si.s && !si.su && me.recvsvr)
231 pippijn 1.5 return slog (LG_DEBUG, "p10_parse(): got message from nonexistant user or server: %s", origin);
232 pippijn 1.1 si.smu = si.su != NULL ? si.su->myuser : NULL;
233    
234     /* okay, the nasty part is over, now we need to make a
235     * parv out of what's left
236     */
237    
238     if (message)
239     {
240     if (*message == ':')
241     {
242     message++;
243     parv[0] = message;
244     parc = 1;
245     }
246     else
247     parc = tokenize (message, parv);
248     }
249     else
250     parc = 0;
251    
252     /* now we should have origin (or NULL), command, and a parv
253     * with it's accompanying parc... let's make ABSOLUTELY sure
254     */
255     if (!command)
256 pippijn 1.5 return slog (LG_DEBUG, "p10_parse(): command not found: %s", coreLine);
257 pippijn 1.1
258     /* take the command through the hash table */
259     if ((pcmd = pcommand_find (command)))
260     {
261     if (si.su && !(pcmd->sourcetype & MSRC_USER))
262 pippijn 1.5 return slog (LG_INFO, "p10_parse(): user %s sent disallowed command %s", si.su->nick, pcmd->token);
263 pippijn 1.1 else if (si.s && !(pcmd->sourcetype & MSRC_SERVER))
264 pippijn 1.5 return slog (LG_INFO, "p10_parse(): server %s sent disallowed command %s", si.s->name, pcmd->token);
265 pippijn 1.1 else if (!me.recvsvr && !(pcmd->sourcetype & MSRC_UNREG))
266 pippijn 1.5 return slog (LG_INFO, "p10_parse(): unregistered server sent disallowed command %s", pcmd->token);
267 pippijn 1.1 if (parc < pcmd->minparc)
268 pippijn 1.5 return slog (LG_INFO, "p10_parse(): insufficient parameters for command %s", pcmd->token);
269 pippijn 1.1 if (pcmd->handler)
270 pippijn 1.5 pcmd->handler (&si, parc, parv);
271 pippijn 1.1 }
272     }
273     }