modified code to use IOHandler functions instead of own ones
[NeonServV5.git] / src / IRCParser.c
1 /* IRCParser.c - NeonServ v5.5
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "IRCParser.h"
19 #include "UserNode.h"
20 #include "ChanNode.h"
21 #include "ChanUser.h"
22 #include "IRCEvents.h"
23 #include "ClientSocket.h"
24 #include "WHOHandler.h"
25 #include "lang.h"
26 #include "DBHelper.h"
27 #include "BanNode.h"
28 #include "ModeNode.h"
29 #include "tools.h"
30 #include "bots.h"
31
32 struct irc_cmd *irc_commands = NULL;
33 //static struct UserNode *registering_users = NULL;
34 int statistics_privmsg = 0;
35 int statistics_network_users = 0;
36 int statistics_network_channels = 0;
37
38 static void register_irc_function(char *command, irc_cmd_t *func);
39 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
40
41 void parse_line(struct ClientSocket *client, char *line) {
42     int argc = 0;
43     char *argv[MAXNUMPARAMS];
44     #ifdef HAVE_THREADS
45     putlog(LOGLEVEL_RAW, "[%d recv %lu] %s\n", getCurrentThreadID(), (unsigned long) strlen(line), line);
46     #else
47     putlog(LOGLEVEL_RAW, "[recv %lu] %s\n", (unsigned long) strlen(line), line);
48     #endif
49     if(line[0] == ':')
50         line++;
51     else
52         argv[argc++] = NULL;
53     while(*line) {
54         //skip leading spaces
55         while (*line == ' ')
56             *line++ = 0;
57         if (*line == ':') {
58            //the rest is a single parameter
59            argv[argc++] = line + 1;
60            break;
61         }
62         argv[argc++] = line;
63         if (argc >= MAXNUMPARAMS)
64             break;
65         while (*line != ' ' && *line)
66             line++;
67     }
68     if(argc >= 2) {
69         parse_raw(client, argv[0], argv[1], argv+2, argc-2);
70     }
71 }
72
73 static void register_irc_function(char *command, irc_cmd_t *func) {
74     struct irc_cmd *irc_cmd = malloc(sizeof(*irc_cmd));
75     if (!irc_cmd)
76     {
77         perror("malloc() failed");
78         return;
79     }
80     irc_cmd->cmd = command;
81     irc_cmd->func = func;
82     irc_cmd->next = irc_commands;
83     irc_commands = irc_cmd;
84 }
85
86 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) {
87     struct irc_cmd *irc_cmd;
88     int ret = 0;
89     for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) {
90         if(!stricmp(irc_cmd->cmd, cmd)) {
91             ret = irc_cmd->func(client, from, argv, argc);
92             break;
93         }
94     }
95     if(!irc_cmd) {
96         event_raw(client, from, cmd, argv, argc);
97     } else if(!ret) {
98         fprintf(stderr,"PARSE ERROR: %s\n", cmd);
99     }
100 }
101
102 static USERLIST_CALLBACK(got_channel_userlist) {
103     struct ChanUser *chanuser = data;
104     event_join(chanuser);
105 }
106
107 static IRC_CMD(raw_002) { //fixed: ZNC fakes a 001 raw even if we're not connected!
108     struct UserNode *user = getUserByNick(argv[0]);
109     if(!user)
110         user = addUser(argv[0]);
111     client->user = user;
112     client->user->flags |= USERFLAG_ISBOT;
113     client->flags |= SOCKET_FLAG_READY;
114     event_bot_ready(client);
115     return 1;
116 }
117
118 static IRC_CMD(raw_join) {
119     if(from == NULL || argc < 1) return 0;
120     SYNCHRONIZE(cache_sync);
121     struct UserNode *user = getUserByMask(from);
122     struct ChanNode *chan = getChanByName(argv[0]);
123     struct ChanUser *chanuser;
124     if(!chan && (!user || !(user->flags & USERFLAG_ISBOT))) {
125         //parse error if the channel is not known, yet and it's not a bot joining
126         DESYNCHRONIZE(cache_sync);
127         return 0;
128     }
129     if(user == NULL)
130         user = addUserMask(from);
131     if(chan == NULL) {
132         //new channel
133         chan = addChannel(argv[0]);
134         chanuser = addChanUser(chan, user);
135         chanuser->visCount = 1;
136         get_userlist_with_invisible(chan, 0, got_channel_userlist, chanuser);
137         putsock(client, "MODE %s", chan->name);
138         putsock(client, "MODE %s +b", chan->name);
139     } else if((user->flags & USERFLAG_WAS_REGISTERING)) {
140         //user rejoined after registering (should still be present in the channel)
141         if(!(chanuser = getChanUser(user, chan)))
142             chanuser = addChanUser(chan, user);
143         chanuser->visCount++;
144         
145         event_registered(user, from);
146         user->flags &= ~USERFLAG_WAS_REGISTERING;
147     } else if(!isUserOnChan(user, chan)) {
148         //join user to an existing channel
149         chanuser = addChanUser(chan, user);
150         chanuser->visCount = 1;
151         if(isBot(user) && isModeSet(chan->modes, 'D')) //if the bot joins a channel it could also be invisible
152             chanuser->flags |= CHANUSERFLAG_INVISIBLE;
153         
154         event_join(chanuser);
155         
156         if(!(user->flags & USERFLAG_ISBOT) && (chan->flags & CHANFLAG_REJOINING)) {
157             //ABORT AUTOMATIC REJOIN (security break)
158             struct ClientSocket **clients = chan->rejoin_array;
159             while(*clients) {
160                 putsock(*clients, "JOIN %s", chan->name);
161                 clients++;
162             }
163             free(chan->rejoin_array);
164             chan->flags &= ~CHANFLAG_REJOINING;
165         }
166     } else { 
167         //user is already in the channel
168         chanuser = getChanUser(user, chan);
169         chanuser->visCount++;
170         //if multiple bots see the user, it can't be invisible
171         chanuser->flags &= ~CHANUSERFLAG_INVISIBLE;
172     }
173     DESYNCHRONIZE(cache_sync);
174     return 1;
175 }
176
177 static void check_full_rejoin(struct ChanNode *chan) {
178     struct ChanUser *chanuser;
179     char do_rejoin = 1;
180     int botcount = 0;
181     for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
182         if((chanuser->flags & CHANUSERFLAG_OPPED) || !(chanuser->user->flags & USERFLAG_ISBOT)) {
183             do_rejoin = 0;
184             break;
185         }
186         if((chanuser->user->flags & USERFLAG_ISBOT))
187             botcount++;
188     }
189     if(do_rejoin) {
190         struct ClientSocket **clients = calloc(botcount, sizeof(*clients));
191         struct ClientSocket *bot, *chanbot = NULL;
192         int i = 0;
193         for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
194             if(!isUserOnChan(bot->user, chan))
195                 continue;
196             if(!chanbot && ((bot->flags & SOCKET_FLAG_PREFERRED) || !getBots(SOCKET_FLAG_READY, bot)))
197                 chanbot = bot;
198             else {
199                 clients[i++] = bot;
200                 putsock(bot, "PART %s :rejoining", chan->name);
201             }
202         }
203         if(botcount == 1) {
204             //we're alone
205             free(clients);
206             putsock(chanbot, "PART %s :magic hop", chan->name);
207             putsock(chanbot, "JOIN %s", chan->name);
208         } else {
209             chan->flags |= CHANFLAG_REJOINING;
210             chan->rejoin_array = clients;
211         }
212     }
213 }
214
215 static IRC_CMD(raw_part) {
216     if(from == NULL || argc < 1) return 0;
217     SYNCHRONIZE(cache_sync);
218     struct UserNode *user = getUserByMask(from);
219     struct ChanNode *chan = getChanByName(argv[0]);
220     struct ChanUser *chanuser;
221     if(user == NULL || chan == NULL || !(chanuser = getChanUser(user, chan))) {
222         DESYNCHRONIZE(cache_sync);
223         return 0;
224     }
225     chanuser->visCount--;
226     if(chanuser->visCount == 0) {
227         delChanUser(chanuser, 0); //not free, yet!
228         event_part(chanuser, 0, (argc > 1 ? argv[1] : NULL));
229         freeChanUser(chanuser);
230     }
231     
232     //check if channel is still present
233     int keep_channel = 1;
234     if(chan->usercount == 0) {
235         if((chan->flags & CHANFLAG_REJOINING)) {
236             struct ClientSocket **clients = chan->rejoin_array;
237             while(*clients) {
238                 putsock(*clients, "JOIN %s", chan->name);
239                 clients++;
240             }
241             free(chan->rejoin_array);
242             chan->flags &= ~CHANFLAG_REJOINING;
243         }
244         delChannel(chan, 1);
245         keep_channel = 0;
246     } else if(isBot(user)) //bot parted - check if theres another bot in the channel
247         keep_channel = checkChannelVisibility(chan);
248     
249     // free user if he/she is in no other channel
250     if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT))
251         delUser(user, 1);
252
253     if(keep_channel && (chan->flags & CHANFLAG_RECEIVED_USERLIST) && !(chan->flags & CHANFLAG_REJOINING))
254         check_full_rejoin(chan);
255     else if(keep_channel && (chan->flags & CHANFLAG_REJOINING) && chan->usercount == 1) {
256         //bot is alone... rejoin!
257         struct ClientSocket *bot;
258         //find the last bot in the channel
259         for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
260             if(isUserOnChan(bot->user, chan)) {
261                 putsock(bot, "PART %s :magic hop", chan->name);
262                 putsock(bot, "JOIN %s", chan->name);
263             }
264         }
265     }
266     DESYNCHRONIZE(cache_sync);
267     return 1;
268 }
269
270 static IRC_CMD(raw_kick) {
271     if(from == NULL || argc < 3) return 0;
272     SYNCHRONIZE(cache_sync);
273     struct UserNode *user = getUserByMask(from);
274     struct UserNode *target = getUserByNick(argv[1]);
275     struct ChanNode *chan = getChanByName(argv[0]);
276     struct ChanUser *chanuser;
277     if(chan == NULL || target == NULL || !(chanuser = getChanUser(target, chan))) {
278         DESYNCHRONIZE(cache_sync);
279         return 0;
280     }
281     chanuser->visCount--;
282     if(chanuser->visCount == 0) {
283         delChanUser(chanuser, 0); //not free, yet!
284         event_kick(user, chanuser, argv[2]);
285         freeChanUser(chanuser);
286     }
287     
288     //check if channel is still present
289     int keep_channel = 1;
290     if(chan->usercount == 0) {
291         if((chan->flags & CHANFLAG_REJOINING)) {
292             struct ClientSocket **clients = chan->rejoin_array;
293             while(*clients) {
294                 putsock(*clients, "JOIN %s", chan->name);
295                 clients++;
296             }
297             free(chan->rejoin_array);
298             chan->flags &= ~CHANFLAG_REJOINING;
299         }
300         delChannel(chan, 1);
301         keep_channel = 0;
302     } else if(isBot(target)) //bot parted - check if theres another bot in the channel
303         keep_channel = checkChannelVisibility(chan);
304     
305     // free user if he/she is in no other channel
306     if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT))
307         delUser(target, 1);
308
309     if(keep_channel && (chan->flags & CHANFLAG_RECEIVED_USERLIST) && !(chan->flags & CHANFLAG_REJOINING))
310         check_full_rejoin(chan);
311     else if(keep_channel && (chan->flags & CHANFLAG_REJOINING) && chan->usercount == 1) {
312         //bot is alone... rejoin!
313         struct ClientSocket *bot;
314         //find the last bot in the channel
315         for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
316             if(isUserOnChan(bot->user, chan)) {
317                 putsock(bot, "PART %s :magic hop", chan->name);
318                 putsock(bot, "JOIN %s", chan->name);
319             }
320         }
321     }
322     DESYNCHRONIZE(cache_sync);
323     return 1;
324 }
325
326 static IRC_CMD(raw_quit) {
327     if(from == NULL || argc < 1) return 0;
328     SYNCHRONIZE(cache_sync);
329     struct UserNode *user = getUserByMask(from);
330     if(user == NULL) {
331         DESYNCHRONIZE(cache_sync);
332         return 0;
333     }
334     
335     if(client->user == user) {
336         DESYNCHRONIZE(cache_sync);
337         return 0;
338     }
339     
340     //check if user is just registering
341     if(!stricmp(argv[0], "Registered"))
342         user->flags |= USERFLAG_WAS_REGISTERING;
343     
344     //decrease visCount counter
345     struct ChanUser *chanuser, *next_chanuser;
346     for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next_chanuser) {
347         next_chanuser = getUserChannels(user, chanuser);
348         chanuser->visCount--;
349         if(chanuser->visCount == 0) {
350             delChanUser(chanuser, 0); //not free, yet!
351             event_part(chanuser, 1, argv[0]);
352             if((chanuser->chan->flags & CHANFLAG_RECEIVED_USERLIST) && !(chanuser->chan->flags & CHANFLAG_REJOINING))
353                 check_full_rejoin(chanuser->chan);
354             freeChanUser(chanuser);
355         }
356     }
357     
358     if(user->channel == NULL) {
359         if(isBot(user)) {
360             //ASSERT
361             return 0;
362         }
363         if((user->flags & USERFLAG_WAS_REGISTERING)) {
364             //TODO: set a timeout or sth like that?
365         } else
366             delUser(user, 1);
367     }
368     
369     DESYNCHRONIZE(cache_sync);
370     return 1;
371 }
372
373 void bot_disconnect(struct ClientSocket *client) {
374     struct UserNode *user = client->user;
375     if(user) {
376         //just remove the bot mark from the user and handle a normal quit :)
377         user->flags &= ~USERFLAG_ISBOT;
378         client->user = NULL;
379         client->flags &= ~SOCKET_FLAG_READY;
380         
381         //decrease visCount counter
382         struct ChanUser *chanuser, *next_chanuser;
383         for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next_chanuser) {
384             next_chanuser = getUserChannels(user, chanuser);
385             chanuser->visCount--;
386             if(chanuser->visCount == 0) {
387                 delChanUser(chanuser, 0); //not free, yet!
388                 event_part(chanuser, 1, "QUIT");
389                 if((chanuser->chan->flags & CHANFLAG_RECEIVED_USERLIST) && !(chanuser->chan->flags & CHANFLAG_REJOINING))
390                     check_full_rejoin(chanuser->chan);
391                 freeChanUser(chanuser);
392             }
393         }
394         
395         if(user->channel == NULL)
396             delUser(user, 1);
397     }
398 }
399
400 static struct ClientSocket *get_first_prefered_bot_in_channel(struct ChanNode *chan) {
401     struct ClientSocket *bot, *chanbot = NULL;
402     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
403         if(!isUserOnChan(bot->user, chan))
404             continue;
405         if(bot->flags & SOCKET_FLAG_PREFERRED)
406             return bot;
407         chanbot = bot;
408     }
409     return chanbot;
410 }
411
412 static IRC_CMD(raw_topic) {
413     if(from == NULL || argc < 2) return 0;
414     SYNCHRONIZE(cache_sync);
415     struct UserNode *user = getUserByMask(from);
416     struct ChanNode *chan = getChanByName(argv[0]);
417     if(chan == NULL) {
418         DESYNCHRONIZE(cache_sync);
419         return 0;
420     }
421     if(client != get_first_prefered_bot_in_channel(chan)) {
422         DESYNCHRONIZE(cache_sync);
423         return 1; //just ignore it to prevent event duplicates
424     }
425     if(user == NULL) {
426         user = createTempUserMask(from);
427                 if(!user) {
428             DESYNCHRONIZE(cache_sync);
429             return 0;
430         }
431         user->flags |= USERFLAG_ISTMPUSER;
432     }
433     event_topic(user, chan, argv[1]);
434     strcpy(chan->topic, argv[1]);
435     DESYNCHRONIZE(cache_sync);
436     return 1;
437 }
438
439 static IRC_CMD(raw_privmsg) {
440     if(from == NULL || argc < 2) return 0;
441     struct UserNode *user = getUserByMask(from);
442     if(user == NULL) {
443         user = createTempUserMask(from);
444                 if(!user) return 0;
445         user->flags |= USERFLAG_ISTMPUSER;
446     }
447     if(argv[0][0] == '#') { //Channel message
448         struct ChanNode *chan = getChanByName(argv[0]);
449         if(chan && client == get_first_prefered_bot_in_channel(chan)) {
450             if(statistics_enabled)
451                 statistics_privmsg++;
452             if(argv[1][0] == '\001') {
453                 char *cmd = &argv[1][1];
454                 char *text = strstr(cmd, " ");
455                 if(text) {
456                     *text = '\0';
457                     text++;
458                     if(strlen(text) && text[strlen(text)-1] == '\001')
459                         text[strlen(text)-1] = '\0';
460                 } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
461                     cmd[strlen(cmd)-1] = '\0';
462                 event_chanctcp(user, chan, cmd, text);
463             } else
464                 event_chanmsg(user, chan, argv[1]);
465         }
466     } else {
467         struct UserNode *target = getUserByNick(argv[0]);
468         if(target) {
469             if(argv[1][0] == '\001') {
470                 char *cmd = &argv[1][1];
471                 char *text = strstr(cmd, " ");
472                 if(text) {
473                     *text = '\0';
474                     text++;
475                     if(strlen(text) && text[strlen(text)-1] == '\001')
476                         text[strlen(text)-1] = '\0';
477                 } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
478                     cmd[strlen(cmd)-1] = '\0';
479                 event_privctcp(user, target, cmd, text);
480             } else
481                 event_privmsg(user, target, argv[1]);
482         }
483     }
484     return 1;
485 }
486
487 static IRC_CMD(raw_notice) {
488     if(from == NULL || argc < 2) return 0;
489     struct UserNode *user = getUserByMask(from);
490     if(user == NULL) {
491         user = createTempUserMask(from);
492                 if(!user) return 0;
493         user->flags |= USERFLAG_ISTMPUSER;
494     }
495     if(argv[0][0] == '#') { //Channel notice
496         struct ChanNode *chan = getChanByName(argv[0]);
497         if(chan && client == get_first_prefered_bot_in_channel(chan))
498             event_channotice(user, chan, argv[1]);
499     } else {
500         struct UserNode *target = getUserByNick(argv[0]);
501         if(target)
502             event_privnotice(user, target, argv[1]);
503     }
504     return 1;
505 }
506
507 static void client_renamed(struct ClientSocket *client);
508
509 static IRC_CMD(raw_nick) {
510     if(from == NULL || argc == 0) return 0;
511     SYNCHRONIZE(cache_sync);
512     struct UserNode *user = getUserByMask(from);
513     if(user == NULL) {
514         DESYNCHRONIZE(cache_sync);
515         return 1; //maybe already renamed - no parse error
516     }
517     if(isBot(user)) {
518         if(client->user != user) {
519             DESYNCHRONIZE(cache_sync);
520             return 1;
521         }
522         client_renamed(client);
523     }
524     else if(!strcmp(user->nick, argv[0])) {
525         DESYNCHRONIZE(cache_sync);
526         return 1; //user has already this nick (case sensitive)
527     }
528     event_nick(user, argv[0]);
529     renameUser(user, argv[0]);
530     DESYNCHRONIZE(cache_sync);
531     return 1;
532 }
533
534 static IRC_CMD(raw_ping) {
535     if(argc == 0) return 0;
536     putsock(client, "PONG :%s", argv[0]);
537     return 1;
538 }
539
540 static IRC_CMD(raw_354) {
541     recv_whohandler_354(client, argv, argc);
542     return 1;
543 }
544
545 static IRC_CMD(raw_315) {
546     recv_whohandler_315(client, argv, argc);
547     return 1;
548 }
549
550 static IRC_CMD(raw_324) { //MODE LIST
551     //Watchcat #pktest +stnzN
552     if(from == NULL || argc < 3) return 0;
553     struct ChanNode *chan = getChanByName(argv[1]);
554     if(chan == NULL) return 0;
555     parseModes(chan->modes, argv[2], argv+3, argc-3);
556     return 1;
557 }
558
559 static IRC_CMD(raw_invite) {
560     if(from == NULL || argc < 2) return 0;
561     struct UserNode *user = getUserByMask(from);
562     if(user == NULL) {
563         user = createTempUserMask(from);
564                 if(!user) return 0;
565         user->flags |= USERFLAG_ISTMPUSER;
566     }
567     event_invite(client, user, argv[1]);
568     return 1;
569 }
570
571 static IRC_CMD(raw_mode) {
572     if(from == NULL || argc < 2) return 0;
573     SYNCHRONIZE(cache_sync);
574     struct UserNode *user = getUserByMask(from);
575     if(user == NULL) {
576         user = createTempUserMask(from);
577                 if(!user) {
578             DESYNCHRONIZE(cache_sync);
579             return 0;
580         }
581         user->flags |= USERFLAG_ISTMPUSER;
582     }
583     if(argv[0][0] == '#') {
584         //ChannelMode
585         struct ChanNode *chan = getChanByName(argv[0]);
586         if(!chan) {
587             DESYNCHRONIZE(cache_sync);
588             return 0;
589         }
590         if(client != get_first_prefered_bot_in_channel(chan)) {
591             DESYNCHRONIZE(cache_sync);
592             return 1;
593         }
594         parseModes(chan->modes, argv[1], argv+2, argc-2);
595         event_mode(user, chan, argv[1], argv+2, argc-2);
596     } else {
597         //UserMode
598         if(stricmp(client->user->nick, argv[0])) {
599             DESYNCHRONIZE(cache_sync);
600             return 0;
601         }
602         parseUserModes(client->user, argv[1]);
603     }
604     DESYNCHRONIZE(cache_sync);
605     return 1;
606 }
607
608 static IRC_CMD(raw_367) {
609     //Watchcat #pktest pk911!*@* TestBot!~bot@pktest.user.WebGamesNet 1315863279
610     struct ChanNode *chan = getChanByName(argv[1]);
611     if(!chan) return 0;
612     struct BanNode *ban;
613     while((ban = getMatchingChannelBan(chan, argv[2]))) {
614         removeChannelBan(ban);
615     }
616     addChannelBan(chan, argv[2]);
617     return 1;
618 }
619
620 static IRC_CMD(raw_251) {
621     if(argc < 2) return 0;
622     char *total_user_str = argv[1];
623     char total_visible[20], total_invisible[20];
624     int i = 0, total_visible_pos = 0, total_invisible_pos = 0;
625     while(*total_user_str) {
626         if(*total_user_str == ' ') {
627             i++;
628         } else if(i == 2) {
629             if(total_visible_pos < 20)
630                 total_visible[total_visible_pos++] = *total_user_str;
631         } else if(i == 5) {
632             if(total_invisible_pos < 20)
633                 total_invisible[total_invisible_pos++] = *total_user_str;
634         }
635         total_user_str++;
636     }
637     total_visible[total_visible_pos] = '\0';
638     total_invisible[total_invisible_pos] = '\0';
639     statistics_network_users = atoi(total_visible) + atoi(total_invisible);
640     return 1;
641 }
642
643 static IRC_CMD(raw_254) {
644     if(argc < 3) return 0;
645     statistics_network_channels = atoi(argv[1]);
646     statistics_update();
647     return 1;
648 }
649
650 static IRC_CMD(raw_332) {
651     //Skynet #neonserv :topic
652     struct ChanNode *chan = getChanByName(argv[1]);
653     if(!chan) return 0;
654     strcpy(chan->topic, argv[2]);
655     return 1;
656 }
657
658 struct ClientRenamePartedChannel {
659     char channel[CHANNELLEN+1];
660     struct ClientRenamePartedChannel *next;
661 };
662
663 static IRC_CMD(raw_437) { //can NOT change nick
664     struct ClientRenamePartedChannel *partedchan = malloc(sizeof(*partedchan));
665     strcpy(partedchan->channel, argv[1]);
666     if((client->flags & SOCKET_FLAG_CHANGENICK))
667         partedchan->next = client->changenick_channels;
668     else
669         partedchan->next = NULL;
670     client->changenick_channels = partedchan;
671     client->flags |= SOCKET_FLAG_CHANGENICK;
672     putsock(client, "PART %s", argv[1]);
673     putsock(client, "NICK %s", client->nick);
674     return 1;
675 }
676
677 static void client_renamed(struct ClientSocket *client) {
678     if((client->flags & SOCKET_FLAG_CHANGENICK)) {
679         struct ClientRenamePartedChannel *partedchan, *nextchan;
680         for(partedchan = client->changenick_channels; partedchan; partedchan = nextchan) {
681             nextchan = partedchan->next;
682             putsock(client, "JOIN %s", partedchan->channel);
683             free(partedchan);
684         }
685         client->flags &= ~SOCKET_FLAG_CHANGENICK;
686     }
687 }
688
689 static void raw_005_network(struct ClientSocket *client, char *value) {
690     if(!value) return;
691     //check all other networknames
692     //if they are NOT simular to value throw a warning
693     SYNCHRONIZE(cache_sync); //all bots connect to the same time so there is a higher chance that this code is running on multiple threads at the same time
694     if(client->network_name)
695         free(client->network_name);
696     client->network_name = strdup(value);
697     struct ClientSocket *bot;
698     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
699         if(bot == client) continue;
700         if(!bot->network_name) continue;
701         if(stricmp(bot->network_name, value)) {
702             putlog(LOGLEVEL_ERROR, "WARNING: Network name '%s' (%s) differs from '%s' (%s)! Connecting to multiple IRC-Networks with one instance is NOT supported!\n", client->network_name, client->nick, bot->network_name, bot->nick);
703             break;
704         }
705     }
706     DESYNCHRONIZE(cache_sync);
707 }
708
709 static IRC_CMD(raw_005) {
710     char *ptr1 = merge_argv(argv, 1, argc);
711     char *ptr2, *name, *value;
712     do {
713         ptr2 = strchr(ptr1, ' ');
714         if(ptr2)
715             *ptr2 = '\0';
716         name = ptr1;
717         if((value = strchr(ptr1, '='))) {
718             *value = '\0';
719             value++;
720         }
721         if(!stricmp(name, "NETWORK")) raw_005_network(client, value);
722         if(ptr2)
723             ptr1 = ptr2 + 1;
724     } while(ptr2);
725     return 1;
726 }
727
728 static IRC_CMD(raw_nojoin) {
729     if(from == NULL || argc < 3) return 0;
730     struct ChanNode *chan = getChanByName(argv[1]);
731     if(chan == NULL) return 0;
732     if(client->flags & SOCKET_FLAG_REQUEST_INVITE)
733         requestInvite(client->user, chan);
734     return 1;
735 }
736
737 void init_parser() {
738     //all the raws we receive...
739     register_irc_function("437", raw_437);
740     register_irc_function("002", raw_002);
741     register_irc_function("005", raw_005);
742     register_irc_function("251", raw_251);
743     register_irc_function("254", raw_254);
744     register_irc_function("324", raw_324);
745     register_irc_function("332", raw_332);
746     register_irc_function("367", raw_367);
747     register_irc_function("471", raw_nojoin);
748     register_irc_function("473", raw_nojoin);
749     register_irc_function("474", raw_nojoin);
750     register_irc_function("475", raw_nojoin);
751     register_irc_function("INVITE", raw_invite);
752     register_irc_function("NOTICE", raw_notice);
753     register_irc_function("TOPIC", raw_topic);
754     register_irc_function("KICK", raw_kick);
755     register_irc_function("PART", raw_part);
756     register_irc_function("QUIT", raw_quit);
757     register_irc_function("JOIN", raw_join);
758     register_irc_function("MODE", raw_mode);
759     register_irc_function("NICK", raw_nick);
760     register_irc_function("354", raw_354);
761     register_irc_function("315", raw_315);
762     register_irc_function("PING", raw_ping);
763     register_irc_function("PRIVMSG", raw_privmsg);
764 }
765
766 void free_parser() {
767     struct irc_cmd *cmd, *next;
768     for(cmd = irc_commands; cmd; cmd = next) {
769         next = cmd->next;
770         free(cmd);
771     }
772 }
773
774 void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...) {
775     const char *reply_format = get_language_string(user, text);
776     if(reply_format == NULL)
777         reply_format = text;
778     loadUserSettings(user);
779     char formatBuf[MAXLEN];
780     sprintf(formatBuf, "%s %s :%s", ((user->flags & USERFLAG_REPLY_PRIVMSG) ? "PRIVMSG" : "NOTICE"), user->nick, reply_format);
781     va_list arg_list;
782     char sendBuf[MAXLEN];
783     int pos;
784     if (!(client->flags & SOCKET_FLAG_CONNECTED)) return;
785     sendBuf[0] = '\0';
786     va_start(arg_list, text);
787     pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list);
788     va_end(arg_list);
789     if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
790     sendBuf[pos] = '\n';
791     sendBuf[pos+1] = '\0';
792     write_socket(client, sendBuf, pos+1);
793 }
794
795 char* merge_argv(char **argv, int start, int end) {
796     return merge_argv_char(argv, start, end, ' ');
797 }
798
799 char* merge_argv_char(char **argv, int start, int end, char seperator) {
800     int i;
801     char *p = NULL;
802     for(i = start; i < end; i++) {
803         p = argv[i];
804         while(*p) p++;
805         if(i < end-1) {
806             while(p != argv[i+1]) {
807                 *p++ = seperator;
808             }
809         } else
810             *p = seperator;
811     }
812     if(p) *p = '\0';
813     return argv[start];
814 }