fixed last commit
[NeonServV5.git] / IRCParser.c
1
2 #include "IRCParser.h"
3 #include "UserNode.h"
4 #include "ChanNode.h"
5 #include "ChanUser.h"
6 #include "IRCEvents.h"
7 #include "ClientSocket.h"
8 #include "WHOHandler.h"
9 #include "lang.h"
10 #include "DBHelper.h"
11 #include "BanNode.h"
12
13 struct irc_cmd *irc_commands = NULL;
14
15 static void parse_line(struct ClientSocket *client, char *line);
16 static void register_irc_function(char *command, irc_cmd_t *func);
17 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
18
19 int parse_lines(struct ClientSocket *client, char *lines, int len) {
20     int i, used = 0;
21     char *line = lines;
22     for(i = 0; i < len; i++) {
23         if(lines[i] == '\r') //just zero it out :D
24             lines[i] = 0;
25         if(lines[i] == '\n') {
26             lines[i] = 0;
27             parse_line(client, line);
28             line = lines+(i+1);
29             used = i+1;
30         }
31     }
32     return used;
33 }
34
35 static void parse_line(struct ClientSocket *client, char *line) {
36     int argc = 0;
37     char *argv[MAXNUMPARAMS];
38     printf("[recv %lu] %s\n", (unsigned long) strlen(line), line);
39     if(line[0] == ':')
40         line++;
41     else
42         argv[argc++] = NULL;
43     while(*line) {
44         //skip leading spaces
45         while (*line == ' ')
46             *line++ = 0;
47         if (*line == ':') {
48            //the rest is a single parameter
49            argv[argc++] = line + 1;
50            break;
51         }
52         argv[argc++] = line;
53         if (argc >= MAXNUMPARAMS)
54             break;
55         while (*line != ' ' && *line)
56             line++;
57     }
58     if(argc >= 2) {
59         parse_raw(client, argv[0], argv[1], argv+2, argc-2);
60     }
61 }
62
63 static void register_irc_function(char *command, irc_cmd_t *func) {
64     struct irc_cmd *irc_cmd = malloc(sizeof(*irc_cmd));
65     if (!irc_cmd)
66     {
67         perror("malloc() failed");
68         return;
69     }
70     irc_cmd->cmd = command;
71     irc_cmd->func = func;
72     irc_cmd->next = irc_commands;
73     irc_commands = irc_cmd;
74 }
75
76 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) {
77     struct irc_cmd *irc_cmd;
78     int ret = 0;
79     for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) {
80         if(!stricmp(irc_cmd->cmd, cmd)) {
81             ret = irc_cmd->func(client, from, argv, argc);
82             break;
83         }
84     }
85     if(!irc_cmd) {
86         event_raw(client, from, cmd, argv, argc);
87     } else if(!ret) {
88         fprintf(stderr,"PARSE ERROR: %s", cmd);
89     }
90 }
91
92 static USERLIST_CALLBACK(got_channel_userlist) {
93     struct ChanUser *chanuser = data;
94     event_join(chanuser);
95 }
96
97 static IRC_CMD(raw_001) {
98     client->flags |= SOCKET_FLAG_READY;
99     event_bot_ready(client);
100     return 1;
101 }
102
103 static IRC_CMD(raw_join) {
104     if(from == NULL || argc < 1) return 0;
105     struct UserNode *user = getUserByMask(from);
106     struct ChanNode *chan = getChanByName(argv[0]);
107     if(!chan && !(user->flags & USERFLAG_ISBOT)) return 0;
108     if(user == NULL) {
109         user = addUserMask(from);
110     }
111     if(chan == NULL) {
112         chan = addChannel(argv[0]);
113         //request member list
114         chan->chanbot = user;
115         struct ChanUser *chanuser = addChanUser(chan, user); //it must be a bot
116         get_userlist(chan, got_channel_userlist, chanuser);
117         putsock(client, "MODE %s", chan->name);
118         putsock(client, "MODE +b %s", chan->name);
119     } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
120         struct ChanUser *chanuser = addChanUser(chan, user);
121         event_join(chanuser);
122     }
123     return 1;
124 }
125
126 static IRC_CMD(raw_part) {
127     if(from == NULL || argc < 2) return 0;
128     struct UserNode *user = getUserByMask(from);
129     if(user == NULL) return 0;
130     struct ChanNode *chan = getChanByName(argv[0]);
131     if(chan == NULL) return 0;
132     if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
133         struct ChanUser *chanuser = getChanUser(user, chan);
134         delChanUser(chanuser, 0); //we need to free the chanuser manually!
135         event_part(chanuser, argv[1]);
136         free(chanuser);
137         if(chan->chanbot == user) {
138             //check if theres another bot in the channel - otherwise free it
139             checkChannelVisibility(chan);
140         }
141     }
142     if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) {
143         //remove the user
144         delUser(user, 1);
145     }
146     return 1;
147 }
148
149 static IRC_CMD(raw_quit) {
150     if(from == NULL || argc < 2) return 0;
151     struct UserNode *user = getUserByMask(from);
152     if(user == NULL) return 0;
153     delUser(user, 0); //a little bit crazy, but we want to delete the user on the channel's userlists - but not the users channel list
154     event_quit(user, argv[1]);
155     if(user->flags & USERFLAG_ISBOT) {
156         //check if there are other bots in the users channel - otherwise free them
157         struct ChanUser *chanuser, *next;
158         for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
159             next = getUserChannels(user, chanuser);
160             checkChannelVisibility(chanuser->chan);
161         }
162     }
163     delUser(user, 1); //now we fully free the user
164     return 1;
165 }
166
167 void bot_disconnect(struct ClientSocket *client) {
168     struct UserNode *user = client->user;
169     struct ChanUser *chanuser, *next;
170     delUser(user, 0);
171     event_quit(user, "disconnected");
172     for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
173         next = getUserChannels(user, chanuser);
174         checkChannelVisibility(chanuser->chan);
175         free(chanuser);
176     }
177     user->channel = NULL;
178 }
179
180 static IRC_CMD(raw_kick) {
181     if(from == NULL || argc < 3) return 0;
182     struct UserNode *user = getUserByMask(from);
183     struct UserNode *target = getUserByNick(argv[1]);
184     struct ChanNode *chan = getChanByName(argv[0]);
185     if(chan == NULL || target == NULL) return 0;
186     if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
187         if(user == NULL) {
188             user = createTempUser(from);
189             user->flags |= USERFLAG_ISTMPUSER;
190         }
191         struct ChanUser *chanuser = getChanUser(target, chan);
192         delChanUser(chanuser, 0); //we need to free the chanuser manually!
193         event_kick(user, chanuser, argv[1]);
194         free(chanuser);
195         if(target->flags & USERFLAG_ISBOT) {
196             //check if theres another bot in the channel - otherwise free it
197             checkChannelVisibility(chan);
198         }
199     }
200     if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) {
201         //remove the user
202         delUser(target, 1);
203     }
204     return 1;
205 }
206
207 static IRC_CMD(raw_topic) {
208     if(from == NULL || argc < 2) return 0;
209     struct UserNode *user = getUserByMask(from);
210     struct ChanNode *chan = getChanByName(argv[0]);
211     if(chan == NULL) return 0;
212     if(chan->chanbot != client->user) return 1; //just ignore it to prevent event duplicates
213     if(user == NULL) {
214         user = createTempUser(from);
215         user->flags |= USERFLAG_ISTMPUSER;
216     }
217     event_topic(user, chan, argv[1]);
218     strcpy(chan->topic, argv[1]);
219     return 1;
220 }
221
222 static IRC_CMD(raw_privmsg) {
223     if(from == NULL || argc < 2) return 0;
224     struct UserNode *user = getUserByMask(from);
225     if(user == NULL) {
226         user = createTempUser(from);
227         user->flags |= USERFLAG_ISTMPUSER;
228     }
229     if(argv[0][0] == '#') { //Channel message
230         struct ChanNode *chan = getChanByName(argv[0]);
231         if(chan && chan->chanbot == client->user) {
232             if(argv[1][0] == '\001') {
233                 char *cmd = &argv[1][1];
234                 char *text = strstr(cmd, " ");
235                 if(text) {
236                     *text = '\0';
237                     text++;
238                     if(strlen(text) && text[strlen(text)-1] == '\001')
239                         text[strlen(text)-1] = '\0';
240                 } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
241                     cmd[strlen(cmd)-1] = '\0';
242                 event_chanctcp(user, chan, cmd, text);
243             } else
244                 event_chanmsg(user, chan, argv[1]);
245         }
246     } else {
247         struct UserNode *target = getUserByNick(argv[0]);
248         if(target) {
249             if(argv[1][0] == '\001') {
250                 char *cmd = &argv[1][1];
251                 char *text = strstr(cmd, " ");
252                 if(text) {
253                     *text = '\0';
254                     text++;
255                     if(strlen(text) && text[strlen(text)-1] == '\001')
256                         text[strlen(text)-1] = '\0';
257                 } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
258                     cmd[strlen(cmd)-1] = '\0';
259                 event_privctcp(user, target, cmd, text);
260             } else
261                 event_privmsg(user, target, argv[1]);
262         }
263     }
264     return 1;
265 }
266
267 static IRC_CMD(raw_notice) {
268     if(from == NULL || argc < 2) return 0;
269     struct UserNode *user = getUserByMask(from);
270     if(user == NULL) {
271         user = createTempUser(from);
272         user->flags |= USERFLAG_ISTMPUSER;
273     }
274     if(argv[0][0] == '#') { //Channel notice
275         struct ChanNode *chan = getChanByName(argv[0]);
276         if(chan && chan->chanbot == client->user)
277             event_channotice(user, chan, argv[1]);
278     } else {
279         struct UserNode *target = getUserByNick(argv[0]);
280         if(target)
281             event_privnotice(user, target, argv[1]);
282     }
283     return 1;
284 }
285
286 static IRC_CMD(raw_nick) {
287     if(from == NULL || argc == 0) return 0;
288     struct UserNode *user = getUserByMask(from);
289     if(user == NULL) return 0;
290     event_nick(user, argv[0]);
291     renameUser(user, argv[0]);
292     return 1;
293 }
294
295 static IRC_CMD(raw_ping) {
296     if(argc == 0) return 0;
297     putsock(client, "PONG :%s", argv[0]);
298     return 1;
299 }
300
301 static IRC_CMD(raw_354) {
302     recv_whohandler_354(client, argv, argc);
303     return 1;
304 }
305
306 static IRC_CMD(raw_315) {
307     recv_whohandler_315(client, argv, argc);
308     return 1;
309 }
310
311 static IRC_CMD(raw_324) { //MODE LIST
312     //Watchcat #pktest +stnzN
313     if(from == NULL || argc < 3) return 0;
314     struct ChanNode *chan = getChanByName(argv[1]);
315     if(chan == NULL) return 0;
316     parseModes(chan, argv[2], argv+3, argc-3);
317     return 1;
318 }
319
320 static IRC_CMD(raw_invite) {
321     if(from == NULL || argc < 2) return 0;
322     struct UserNode *user = getUserByMask(from);
323     event_invite(user, argv[1]);
324     return 1;
325 }
326
327 static IRC_CMD(raw_mode) {
328     if(from == NULL || argc < 2) return 0;
329     struct UserNode *user = getUserByMask(from);
330     if(user == NULL) {
331         user = createTempUser(from);
332         user->flags |= USERFLAG_ISTMPUSER;
333     }
334     if(argv[0][0] == '#') {
335         //ChannelMode
336         struct ChanNode *chan = getChanByName(argv[0]);
337         if(!chan) return 0;
338         if(chan->chanbot != client->user) return 1;
339         event_mode(user, chan, argv[1], argv+2, argc-2);
340         parseModes(chan, argv[1], argv+2, argc-2);
341     } else {
342         //UserMode
343     }
344     return 1;
345 }
346
347 static IRC_CMD(raw_367) {
348     //Watchcat #pktest pk911!*@* TestBot!~bot@pktest.user.WebGamesNet 1315863279
349     struct ChanNode *chan = getChanByName(argv[1]);
350     if(!chan) return 0;
351     struct BanNode *ban;
352     while((ban = getMatchingChannelBan(chan, argv[2]))) {
353         removeChannelBan(ban);
354     }
355     addChannelBan(chan, argv[2]);
356     return 1;
357 }
358
359 void init_parser() {
360     //all the raws we receive...
361     register_irc_function("001", raw_001);
362     register_irc_function("324", raw_324);
363     register_irc_function("367", raw_367);
364     register_irc_function("INVITE", raw_invite);
365     register_irc_function("NOTICE", raw_notice);
366     register_irc_function("TOPIC", raw_topic);
367     register_irc_function("KICK", raw_kick);
368     register_irc_function("PART", raw_part);
369     register_irc_function("QUIT", raw_quit);
370     register_irc_function("JOIN", raw_join);
371     register_irc_function("MODE", raw_mode);
372     register_irc_function("NICK", raw_nick);
373     register_irc_function("354", raw_354);
374     register_irc_function("315", raw_315);
375     register_irc_function("PING", raw_ping);
376     register_irc_function("PRIVMSG", raw_privmsg);
377 }
378
379 void free_parser() {
380     struct irc_cmd *cmd, *next;
381     for(cmd = irc_commands; cmd; cmd = next) {
382         next = cmd->next;
383         free(cmd);
384     }
385 }
386
387 void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...) {
388     const char *reply_format = get_language_string(user, text);
389     if(reply_format == NULL)
390         reply_format = text;
391     loadUserSettings(user);
392     char formatBuf[MAXLEN];
393     sprintf(formatBuf, "%s %s :%s", ((user->flags & USERFLAG_REPLY_PRIVMSG) ? "PRIVMSG" : "NOTICE"), user->nick, reply_format);
394     va_list arg_list;
395     char sendBuf[MAXLEN];
396     int pos;
397     if (!(client->flags & SOCKET_FLAG_CONNECTED)) return;
398     sendBuf[0] = '\0';
399     va_start(arg_list, text);
400     pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list);
401     va_end(arg_list);
402     if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
403     sendBuf[pos] = '\n';
404     sendBuf[pos+1] = '\0';
405     write_socket(client, sendBuf, pos+1);
406 }
407
408 char* merge_argv(char **argv, int start, int end) {
409     return merge_argv_char(argv, start, end, ' ');
410 }
411
412 char* merge_argv_char(char **argv, int start, int end, char seperator) {
413     int i;
414     char *p = NULL;
415     for(i = start; i < end; i++) {
416         p = argv[i];
417         while(*p) p++;
418         *p = seperator;
419     }
420     if(p) *p = '\0';
421     return argv[start];
422 }