ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/parse.C
Revision: 1.1
Committed: Thu Jul 19 08:24:59 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

# Content
1 /*
2 * parse.C: Parsing of IRC messages.
3 * Rights to this code are documented in doc/LICENSE.
4 *
5 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6 */
7
8 static char const rcsid[] = "$Id";
9
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 pcommand_t *pcmd;
31
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 pcommand_t *pcmd;
183
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 */