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