ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/parse.C
Revision: 1.4
Committed: Tue Aug 28 17:08:12 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.3: +4 -4 lines
Log Message:
- changed name
- updated the example config to the new system
- added more documentation
- enhanced documentation generators
- added a link to the pdf to the website
- added an RSS feed generator
- transitioned hooks to c++ callbacks
- did various merges with upstream along the way
- added const where appropriate
- removed the old block allocator
- fixed most memory leaks
- transitioned some dictionaries to std::map
- transitioned some lists to std::vector
- made some free functions members where appropriate
- renamed string to dynstr and added a static string ststr
- use NOW instead of time (NULL) if possible
- completely reworked database backends, crypto handlers and protocol handlers
  to use an object factory
- removed the old module system. ermyth does not do any dynamic loading anymore
- fixed most of the build system
- reworked how protocol commands work

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.4 static char const rcsid[] = "$Id: parse.C,v 1.3 2007-07-21 13:23:22 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     {
106     slog (LG_INFO, "irc_parse(): got message from nonexistant user or server: %s", origin);
107     return;
108     }
109     si.smu = si.su != NULL ? si.su->myuser : NULL;
110    
111     /* okay, the nasty part is over, now we need to make a
112     * parv out of what's left
113     */
114    
115     if (message)
116     {
117     if (*message == ':')
118     {
119     message++;
120     parv[0] = message;
121     parc = 1;
122     }
123     else
124     parc = tokenize (message, parv);
125     }
126     else
127     parc = 0;
128    
129     /* now we should have origin (or NULL), command, and a parv
130     * with it's accompanying parc... let's make ABSOLUTELY sure
131     */
132     if (!command)
133     {
134     slog (LG_DEBUG, "irc_parse(): command not found: %s", coreLine);
135     return;
136     }
137    
138     /* take the command through the hash table */
139     if ((pcmd = pcommand_find (command)))
140     {
141     if (si.su && !(pcmd->sourcetype & MSRC_USER))
142     {
143     slog (LG_INFO, "irc_parse(): user %s sent disallowed command %s", si.su->nick, pcmd->token);
144     return;
145     }
146     else if (si.s && !(pcmd->sourcetype & MSRC_SERVER))
147     {
148     slog (LG_INFO, "irc_parse(): server %s sent disallowed command %s", si.s->name, pcmd->token);
149     return;
150     }
151     else if (!me.recvsvr && !(pcmd->sourcetype & MSRC_UNREG))
152     {
153     slog (LG_INFO, "irc_parse(): unregistered server sent disallowed command %s", pcmd->token);
154     return;
155     }
156     if (parc < pcmd->minparc)
157     {
158     slog (LG_INFO, "irc_parse(): insufficient parameters for command %s", pcmd->token);
159     return;
160     }
161     if (pcmd->handler)
162     {
163     pcmd->handler (&si, parc, parv);
164     }
165     }
166     }
167     }
168    
169     /* parses a P10 IRC stream */
170     void
171     p10_parse (char *line)
172     {
173     sourceinfo_t si;
174     char *pos;
175     char *origin = NULL;
176     char *command = NULL;
177     char *message = NULL;
178     char *parv[MAXPARC + 1];
179     static char coreLine[BUFSIZE];
180     int parc = 0;
181     unsigned int i;
182 pippijn 1.4 pcommand_t const *pcmd;
183 pippijn 1.1
184     /* clear the parv */
185     for (i = 0; i <= MAXPARC; i++)
186     parv[i] = NULL;
187    
188     memset (&si, '\0', sizeof si);
189     si.connection = curr_uplink->conn;
190    
191     if (line != NULL)
192     {
193     /* sometimes we'll get a blank line with just a \n on it...
194     * catch those here... they'll core us later on if we don't
195     */
196     if (*line == '\n')
197     return;
198     if (*line == '\000')
199     return;
200    
201     /* copy the original line so we know what we crashed on */
202     memset ((char *) &coreLine, '\0', BUFSIZE);
203     strlcpy (coreLine, line, BUFSIZE);
204    
205     slog (LG_RAWDATA, "-> %s", line);
206    
207     /* find the first spcae */
208     if ((pos = strchr (line, ' ')))
209     {
210     *pos = '\0';
211     pos++;
212     /* if it starts with a : we have a prefix/origin
213     * pull the origin off into `origin', and have pos for the
214     * command, message will be the part afterwards
215     */
216     if (*line == ':' || me.recvsvr == true)
217     {
218     origin = line;
219     if (*origin == ':')
220     {
221     origin++;
222     si.s = server_find (origin);
223     si.su = user_find_named (origin);
224     }
225     else
226     {
227     si.s = server_find (origin);
228     si.su = user_find (origin);
229     }
230    
231     if ((message = strchr (pos, ' ')))
232     {
233     *message = '\0';
234     message++;
235     command = pos;
236     }
237     else
238     {
239     command = pos;
240     message = NULL;
241     }
242     }
243     else
244     {
245     message = pos;
246     command = line;
247     }
248     }
249    
250     if (!si.s && !si.su && me.recvsvr)
251     {
252     slog (LG_DEBUG, "irc_parse(): got message from nonexistant user or server: %s", origin);
253     return;
254     }
255     si.smu = si.su != NULL ? si.su->myuser : NULL;
256    
257     /* okay, the nasty part is over, now we need to make a
258     * parv out of what's left
259     */
260    
261     if (message)
262     {
263     if (*message == ':')
264     {
265     message++;
266     parv[0] = message;
267     parc = 1;
268     }
269     else
270     parc = tokenize (message, parv);
271     }
272     else
273     parc = 0;
274    
275     /* now we should have origin (or NULL), command, and a parv
276     * with it's accompanying parc... let's make ABSOLUTELY sure
277     */
278     if (!command)
279     {
280     slog (LG_DEBUG, "irc_parse(): command not found: %s", coreLine);
281     return;
282     }
283    
284     /* take the command through the hash table */
285     if ((pcmd = pcommand_find (command)))
286     {
287     if (si.su && !(pcmd->sourcetype & MSRC_USER))
288     {
289     slog (LG_INFO, "irc_parse(): user %s sent disallowed command %s", si.su->nick, pcmd->token);
290     return;
291     }
292     else if (si.s && !(pcmd->sourcetype & MSRC_SERVER))
293     {
294     slog (LG_INFO, "irc_parse(): server %s sent disallowed command %s", si.s->name, pcmd->token);
295     return;
296     }
297     else if (!me.recvsvr && !(pcmd->sourcetype & MSRC_UNREG))
298     {
299     slog (LG_INFO, "irc_parse(): unregistered server sent disallowed command %s", pcmd->token);
300     return;
301     }
302     if (parc < pcmd->minparc)
303     {
304     slog (LG_INFO, "irc_parse(): insufficient parameters for command %s", pcmd->token);
305     return;
306     }
307     if (pcmd->handler)
308     {
309     pcmd->handler (&si, parc, parv);
310     return;
311     }
312     }
313     }
314     }
315    
316     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
317     * vim:ts=8
318     * vim:sw=8
319     * vim:noexpandtab
320     */