]>
jfr.im git - irc/quakenet/lightweight.git/blob - parseline.c
1 /*******************************************************************************
3 * lightweight - a minimalistic chanserv for ircu's p10-protocol
5 * copyright 2002 by Rasmus Have & David Mansell
7 * $Id: parseline.c,v 1.23 2003/09/08 01:19:25 zarjazz Exp $
9 *******************************************************************************/
12 This file is part of lightweight.
14 lightweight is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 lightweight is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with lightweight; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <lightweight.h>
30 #include <globalexterns.h>
32 #include <channelsdb.h>
42 /* Make sure we dont have any spaces in front. */
43 sender
= StripBlanks(currentline
);
45 /* Given that every single line is passed through here
46 * I don't see that null lines are a problem. I'm
47 * 99% sure they are simply caused by a chunk ending
48 * between the \r and \n from the server.
50 * The easiest way to deal with this is simply to bounce
51 * them back here silently. - splidge
56 /* fprintf(stderr,"<< %s\n",sender); */
58 /* Get the pointer to the next word (the command) and make the sender token zero terminated. */
59 command
= SeperateWord(sender
);
61 /* Get a pointer to the tail and zero terminate the command. */
62 tail
= SeperateWord(command
);
64 /* Switch over the commands we give a fuck about and fuck the rest. */
66 if (command
[0] == 'B' && command
[1] == '\0') {
67 /* Grab the timestamp from the burst */
68 /* a9 B #bar 1016451591 a9AAD:ov,a8AAE:o,a9AAK */
69 char *channel
, *timestr
, *modestr
;
70 struct reggedchannel
*chn_ptr
;
75 timestr
= SeperateWord(channel
);
76 modestr
= SeperateWord(timestr
);
77 SeperateWord(modestr
);
79 chn_ptr
= GetChannelPointer(channel
);
81 if (chn_ptr
!= NULL
) {
82 newtimestamp
= strtol(timestr
, NULL
, 10);
84 SyncTimestamp(chn_ptr
, newtimestamp
);
86 if (IsInviteOnly(chn_ptr
) && (!modestr
|| !strchr(modestr
, 'i'))) {
87 /* Channel is bursted without +i but is invite only. Send +i mode. */
88 sprintf(buf
, "%sAAA M %s +i\r\n", my_numeric
, chn_ptr
->channelname
);
92 } else if (command
[0] == 'N' && command
[1] == '\0') {
93 /* Nick command recieved. */
94 /* Branch on Nick introduction and Nick change. */
95 /* Introdution: Create a new user in the userdb. */
96 /* Change: Update the userdb. */
98 if (sender
[2] == '\0') {
99 /* Came from server: it's a new user */
100 /* AD N Q 3 000000100 TheQBot CServe.quakenet.org +oiwdk B]AAAB ADAAA :The Q Bot */
106 char *account
= NULL
;
109 for (i
= 0; i
< 5; i
++)
110 tail
= SeperateWord(tail
);
113 /* There are usermodes for this user.
114 * We are interested in three things:
115 * - We now need to advance an extra word down the sentence
116 * - Check if the usermodes include +o (oper)
117 * - Check if the usermodes include +r (registered nick)
118 * (and do appropriate things with this information
119 * After this block executes, "tail" will point at the IP address field
120 * (if there were no modes this was true already) */
122 tempstr
= tail
; /* tempstr = list of user modes */
123 tail
= SeperateWord(tail
);
124 if (IsCharInString('r', tempstr
)) {
125 /* Found +r usermode -- that means the user is already authed */
126 /* tail is now pointing at the auth name, so grab that and advance another word */
128 tail
= SeperateWord(tail
);
130 if (IsCharInString('h', tempstr
)) {
131 /* Found +h usermode - just skip the parameter */
132 tail
= SeperateWord(tail
);
134 isoper
= IsCharInString('o', tempstr
);
137 tail
= SeperateWord(tail
);
141 UserNickCreation(numeric
, nick
, isoper
);
143 if (account
!= NULL
) {
144 /* Account was authed: so call the auth routine now... */
145 AuthUser(numeric
, account
);
149 /* [hAAA N splidge_ 1013972401 */
150 char *newnick
= tail
;
152 tail
= SeperateWord(tail
);
153 UserNickChange(sender
, newnick
);
156 } else if (command
[0] == 'A' && command
[1] == 'C' && command
[2] == '\0') {
157 /* ACCOUNT command received. */
159 /* AD AC [hAAA splidge */
161 char *numeric
, *account
;
164 account
= SeperateWord(tail
);
165 tail
= SeperateWord(tail
);
167 AuthUser(numeric
, account
);
168 } else if (command
[0] == 'Q' && command
[1] == '\0') {
169 /* Quit command recieved. */
170 /* Remove user from userdb. */
171 /* Thank you for flying QuakeNet. */
175 } else if (command
[0] == 'D' && command
[1] == '\0') {
176 /* Kill command received. */
177 /* Much like Quit, this one */
178 /* a9AAD D bcAAQ :frogsquad.netsplit.net!splidge (m00) */
182 tail
= SeperateWord(tail
);
185 } else if (command
[0] == 'J' && command
[1] == '\0') {
186 /* Join command recieved. */
187 /* Check if user is authed or if channel is known, whichever is fastest. */
188 /* If authed or if channel is known, check if user has flags on channel, and op/voice the person in that case. */
190 /* The only stuff in the tail is the list of channels to join, or 0 */
191 /* Luckily, ircu seems to deal with most of the "JOIN 0" nastiness for us */
193 /* a9AAD J #foo,#bar */
196 /* Seperate off the second parameter (if any) */
199 DoJoins(sender
, tail
, 0); /* Last parameter = 0 => this is NOT a CREATE */
200 } else if (command
[0] == 'C' && command
[1] == '\0') {
201 /* Create command recieved. */
202 /* Check if user is authed or if channel is known, whichever is fastest. */
203 /* If authed or if channel is known, check if user has flags on channel, and op/voice the person in that case. Deop in the opposite case. */
205 char *chanlist
= tail
;
208 timestr
= SeperateWord(tail
);
209 SeperateWord(timestr
);
211 DoJoins(sender
, chanlist
, strtol(timestr
, NULL
, 10)); /* Last parameter = timestamp */
212 } else if (command
[0] == 'M' && command
[1] == '\0') {
214 /* [hAAA M splidge[wind] :+k */
215 /* [hAAA M #twilightzone -o [hAAA */
224 modes
= SeperateWord(target
);
226 if (target
[0] != '#') { /* Not a channel (you don't get mode changes on + channels... */
227 /* This must be a user mode change. Make sure it all checks out */
228 /* Assuming it does, we're only interested in users who are opering or deopering */
230 if ((usrptr
= FindUserByNumeric(sender
)) == NULL
) {
231 Error(ERR_PROTOCOL
| ERR_WARNING
, "Mode change from non-existent user %s", sender
);
235 if (Strcmp(usrptr
->nick
, target
)) {
236 Error(ERR_PROTOCOL
| ERR_WARNING
, "Mode change for other user (%s) from %s", target
, usrptr
->nick
);
242 Error(ERR_PROTOCOL
| ERR_WARNING
, "Mode change with no parameters from %s", sender
);
246 for (cp
= modes
; *cp
!= '\0'; cp
++) { /* Step over each character in the mode string */
261 /* Channel mode change -- which we healthily ignore for now */
262 /* Eeep! Need to examine -i channelmodes, since we introduced invite only channels. */
263 DoChanMode(sender
, target
, modes
);
265 } else if (command
[0] == 'P' && command
[1] == '\0') {
266 /* Privmsg command recieved. */
267 /* Usersupport... ugh. */
268 /* a9AAD P #twilightzone :ooops */
269 /* a9AAD P #twilightzone :I missed a field out :) */
270 /* a9AAD P ppAAA :YOU SUCK */
274 content
= SeperateWord(tail
);
276 /* Ignore the target (assume it was us..) */
277 /* Note that since we're not doing AUTH we don't need "secure" messages */
279 /* Check that the user is authed -- we don't talk to unauthed masses */
281 ProcessMessage(sender
, content
+ 1);
282 } else if (command
[0] == 'G' && command
[1] == '\0') {
283 /* Ping command recieved. */
284 /* Send "Im fine. Weather is good. Send more money.". */
287 sprintf(buf
, "%s Z %s\r\n", my_numeric
, tail
);
289 } else if (command
[0] == 'S' && command
[1] == '\0') {
290 /* Server command recieved. */
291 /* Create server in the servertree. */
292 /* AH S hub.uk.quakenet.org 2 0 1013950331 P10 AKAD] 0 :BarrysWorld QuakeNet IRC Server */
298 int imaxusersnumeric
;
301 for (count
= 0; count
< 5; count
++)
302 tail
= SeperateWord(tail
);
304 iparentnumeric
= NumericToLong(sender
, 2);
305 iservernumeric
= NumericToLong(tail
, 2);
306 imaxusersnumeric
= NumericToLong(tail
+ 2, 3) + 1;
308 AddServer(iservernumeric
, servername
, imaxusersnumeric
, iparentnumeric
);
309 } else if (command
[0] == 'S' && command
[1] == 'Q' && command
[2] == '\0') {
310 /* Server Quit command recieved. */
311 /* Delete server in the servertree and remove all corresponding clients. */
312 /* [h SQ wind.splidge.netsplit.net 0 :Ping timeout */
317 tail
= SeperateWord(tail
);
318 HandleSquit(servername
);
319 } else if (command
[0] == 'E' && command
[1] == 'B' && command
[2] == '\0') {
320 /* End of burst command. */
321 /* If it's OUR server we need to ack */
324 /* Quick hack to get some stats whenever a EB is recieved. */
327 if (!strncmp(sender
, MyServer
, 2)) {
328 /* It was my server which said EB so throw back a EA. */
329 /* We end our own burst here too */
331 #ifndef HORRIBLE_DEOPALL_HACK
332 sprintf(buf
, "%s EB\r\n", my_numeric
);
334 sprintf(buf
, "%s EA\r\n", my_numeric
);
339 /* Crap command recieved. */
340 /* Well, is there anything else we care about? */