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