ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/parse.C
Revision: 1.7
Committed: Sun Sep 16 18:54:45 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +7 -2 lines
Log Message:
#defines to enum

File Contents

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