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

# Content
1 /*
2 * parse.C: Parsing of IRC messages.
3 * Rights to this code are documented in doc/pod/license.pod.
4 *
5 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6 */
7
8 static char const rcsid[] = "$Id: parse.C,v 1.4 2007-08-28 17:08:12 pippijn Exp $";
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 const *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 return slog (LG_INFO, "irc_parse(): got message from nonexistant user or server: %s", origin);
106 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 return slog (LG_DEBUG, "irc_parse(): command not found: %s", coreLine);
131
132 /* take the command through the hash table */
133 if ((pcmd = pcommand_find (command)))
134 {
135 if (si.su && !(pcmd->sourcetype & MSRC_USER))
136 return slog (LG_INFO, "irc_parse(): user %s sent disallowed command %s", si.su->nick, pcmd->token);
137 else if (si.s && !(pcmd->sourcetype & MSRC_SERVER))
138 return slog (LG_INFO, "irc_parse(): server %s sent disallowed command %s", si.s->name, pcmd->token);
139 else if (!me.recvsvr && !(pcmd->sourcetype & MSRC_UNREG))
140 return slog (LG_INFO, "irc_parse(): unregistered server sent disallowed command %s", pcmd->token);
141 if (parc < pcmd->minparc)
142 return slog (LG_INFO, "irc_parse(): insufficient parameters for command %s", pcmd->token);
143 if (pcmd->handler)
144 pcmd->handler (&si, parc, parv);
145 }
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 pcommand_t const *pcmd;
163
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 return slog (LG_DEBUG, "p10_parse(): got message from nonexistant user or server: %s", origin);
232 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 return slog (LG_DEBUG, "p10_parse(): command not found: %s", coreLine);
257
258 /* take the command through the hash table */
259 if ((pcmd = pcommand_find (command)))
260 {
261 if (si.su && !(pcmd->sourcetype & MSRC_USER))
262 return slog (LG_INFO, "p10_parse(): user %s sent disallowed command %s", si.su->nick, pcmd->token);
263 else if (si.s && !(pcmd->sourcetype & MSRC_SERVER))
264 return slog (LG_INFO, "p10_parse(): server %s sent disallowed command %s", si.s->name, pcmd->token);
265 else if (!me.recvsvr && !(pcmd->sourcetype & MSRC_UNREG))
266 return slog (LG_INFO, "p10_parse(): unregistered server sent disallowed command %s", pcmd->token);
267 if (parc < pcmd->minparc)
268 return slog (LG_INFO, "p10_parse(): insufficient parameters for command %s", pcmd->token);
269 if (pcmd->handler)
270 pcmd->handler (&si, parc, parv);
271 }
272 }
273 }