X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=IRCParser.c;h=682cdf0fc811e170969388315791f34a5ef689d1;hb=84fb65ee885f3f747b0a07eb07999395c0ae22f9;hp=622cd8a67f1b6c2d2039c6fb027885b40836abd5;hpb=173ee86c2b78acd2ccc57bf0814235e8445123c5;p=NeonServV5.git diff --git a/IRCParser.c b/IRCParser.c index 622cd8a..682cdf0 100644 --- a/IRCParser.c +++ b/IRCParser.c @@ -1,6 +1,11 @@ #include "IRCParser.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "IRCEvents.h" #include "ClientSocket.h" +#include "WHOHandler.h" struct irc_cmd *irc_commands = NULL; @@ -9,26 +14,27 @@ static void register_irc_function(char *command, irc_cmd_t *func); static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc); int parse_lines(struct ClientSocket *client, char *lines, int len) { - int i, startpos = 0; + int i, used = 0; + char *line = lines; for(i = 0; i < len; i++) { if(lines[i] == '\r') //just zero it out :D lines[i] = 0; if(lines[i] == '\n') { lines[i] = 0; - parse_line(client, lines); - lines += i-startpos; - startpos = i+1; + parse_line(client, line); + line = lines+(i+1); + used = i+1; } } - return startpos; + return used; } static void parse_line(struct ClientSocket *client, char *line) { - int i = 0, argc = 0; + int argc = 0; char *argv[MAXNUMPARAMS]; printf("[recv %lu] %s\n", (unsigned long) strlen(line), line); if(line[0] == ':') - i = 1; + line++; else argv[argc++] = NULL; while(*line) { @@ -65,17 +71,219 @@ static void register_irc_function(char *command, irc_cmd_t *func) { static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) { struct irc_cmd *irc_cmd; + int ret = 0; for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) { if(!stricmp(irc_cmd->cmd, cmd)) { - irc_cmd->func(client, from, argv, argc); + ret = irc_cmd->func(client, from, argv, argc); break; } } + if(!irc_cmd) { + event_raw(client, from, cmd, argv, argc); + } else if(!ret) { + fprintf(stderr,"PARSE ERROR: %s", cmd); + } +} + +static USERLIST_CALLBACK(got_channel_userlist) { + struct ChanUser *chanuser = data; + event_join(chanuser); } static IRC_CMD(raw_001) { client->flags |= SOCKET_FLAG_READY; - putsock(client, "PRIVMSG Watchcat :hi"); + event_bot_ready(client); + return 1; +} + +static IRC_CMD(raw_join) { + if(from == NULL || argc < 1) return 0; + struct UserNode *user = getUserByMask(from); + struct ChanNode *chan = getChanByName(argv[0]); + if(!chan && !(user->flags & USERFLAG_ISBOT)) return 0; + if(user == NULL) { + user = addUserMask(from); + } + if(chan == NULL) { + chan = addChannel(argv[0]); + //request member list + chan->chanbot = user; + struct ChanUser *chanuser = addChanUser(chan, user); //it must be a bot + get_userlist(chan, got_channel_userlist, chanuser); + putsock(client, "MODE %s", chan->name); + } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + struct ChanUser *chanuser = addChanUser(chan, user); + event_join(chanuser); + } + return 1; +} + +static IRC_CMD(raw_part) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) return 0; + struct ChanNode *chan = getChanByName(argv[0]); + if(chan == NULL) return 0; + if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + struct ChanUser *chanuser = getChanUser(user, chan); + delChanUser(chanuser, 0); //we need to free the chanuser manually! + event_part(chanuser, argv[1]); + free(chanuser); + if(chan->chanbot == user) { + //check if theres another bot in the channel - otherwise free it + checkChannelVisibility(chan); + } + } + if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) { + //remove the user + delUser(user, 1); + } + return 1; +} + +static IRC_CMD(raw_quit) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) return 0; + 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 + event_quit(user, argv[1]); + if(user->flags & USERFLAG_ISBOT) { + //check if there are other bots in the users channel - otherwise free them + struct ChanUser *chanuser, *next; + for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) { + next = getUserChannels(user, chanuser); + checkChannelVisibility(chanuser->chan); + } + } + delUser(user, 1); //now we fully free the user + return 1; +} + +void bot_disconnect(struct ClientSocket *client) { + struct UserNode *user = client->user; + struct ChanUser *chanuser, *next; + delUser(user, 0); + event_quit(user, "disconnected"); + for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) { + next = getUserChannels(user, chanuser); + checkChannelVisibility(chanuser->chan); + free(chanuser); + } + user->channel = NULL; +} + +static IRC_CMD(raw_kick) { + if(from == NULL || argc < 3) return 0; + struct UserNode *user = getUserByMask(from); + struct UserNode *target = getUserByNick(argv[1]); + struct ChanNode *chan = getChanByName(argv[0]); + if(chan == NULL || target == NULL) return 0; + if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + struct ChanUser *chanuser = getChanUser(target, chan); + delChanUser(chanuser, 0); //we need to free the chanuser manually! + event_kick(user, chanuser, argv[1]); + free(chanuser); + if(target->flags & USERFLAG_ISBOT) { + //check if theres another bot in the channel - otherwise free it + checkChannelVisibility(chan); + } + } + if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) { + //remove the user + delUser(user, 1); + } + return 1; +} + +static IRC_CMD(raw_topic) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + struct ChanNode *chan = getChanByName(argv[0]); + if(chan == NULL) return 0; + if(chan->chanbot != client->user) return 1; //just ignore it to prevent event duplicates + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + event_topic(user, chan, argv[1]); + strcpy(chan->topic, argv[1]); + return 1; +} + +static IRC_CMD(raw_privmsg) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + if(argv[0][0] == '#') { //Channel message + struct ChanNode *chan = getChanByName(argv[0]); + if(chan && chan->chanbot == client->user) { + if(argv[1][0] == '\001') { + char *cmd = &argv[1][1]; + char *text = strstr(cmd, " "); + if(text) { + *text = '\0'; + text++; + if(strlen(text) && text[strlen(text)-1] == '\001') + text[strlen(text)-1] = '\0'; + } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001') + cmd[strlen(cmd)-1] = '\0'; + event_chanctcp(user, chan, cmd, text); + } else + event_chanmsg(user, chan, argv[1]); + } + } else { + struct UserNode *target = getUserByNick(argv[0]); + if(target) { + if(argv[1][0] == '\001') { + char *cmd = &argv[1][1]; + char *text = strstr(cmd, " "); + if(text) { + *text = '\0'; + text++; + if(strlen(text) && text[strlen(text)-1] == '\001') + text[strlen(text)-1] = '\0'; + } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001') + cmd[strlen(cmd)-1] = '\0'; + event_privctcp(user, target, cmd, text); + } else + event_privmsg(user, target, argv[1]); + } + } + return 1; +} + +static IRC_CMD(raw_notice) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + if(argv[0][0] == '#') { //Channel notice + struct ChanNode *chan = getChanByName(argv[0]); + if(chan && chan->chanbot == client->user) + event_channotice(user, chan, argv[1]); + } else { + struct UserNode *target = getUserByNick(argv[0]); + if(target) + event_privnotice(user, target, argv[1]); + } + return 1; +} + +static IRC_CMD(raw_nick) { + if(from == NULL || argc == 0) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) return 0; + event_nick(user, argv[0]); + renameUser(user, argv[0]); return 1; } @@ -85,8 +293,76 @@ static IRC_CMD(raw_ping) { return 1; } -void parser_init() { +static IRC_CMD(raw_354) { + recv_whohandler_354(client, argv, argc); + return 1; +} + +static IRC_CMD(raw_315) { + recv_whohandler_315(client, argv, argc); + return 1; +} + +static IRC_CMD(raw_324) { //MODE LIST + //Watchcat #pktest +stnzN + if(from == NULL || argc < 3) return 0; + struct ChanNode *chan = getChanByName(argv[1]); + if(chan == NULL) return 0; + parseModes(chan, argv[2], argv+3, argc-3); + return 1; +} + +static IRC_CMD(raw_invite) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + event_invite(user, argv[1]); + return 1; +} + +static IRC_CMD(raw_mode) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + if(argv[0][0] == '#') { + //ChannelMode + struct ChanNode *chan = getChanByName(argv[0]); + if(!chan) return 0; + if(chan->chanbot != client->user) return 1; + event_mode(user, chan, argv[1], argv+2, argc-2); + parseModes(chan, argv[1], argv+2, argc-2); + } else { + //UserMode + } + return 1; +} + +void init_parser() { //all the raws we receive... register_irc_function("001", raw_001); + register_irc_function("324", raw_324); + register_irc_function("INVITE", raw_invite); + register_irc_function("NOTICE", raw_notice); + register_irc_function("TOPIC", raw_topic); + register_irc_function("KICK", raw_kick); + register_irc_function("PART", raw_part); + register_irc_function("QUIT", raw_quit); + register_irc_function("JOIN", raw_join); + register_irc_function("MODE", raw_mode); + register_irc_function("NICK", raw_nick); + register_irc_function("354", raw_354); + register_irc_function("315", raw_315); register_irc_function("PING", raw_ping); + register_irc_function("PRIVMSG", raw_privmsg); } + +void free_parser() { + struct irc_cmd *cmd, *next; + for(cmd = irc_commands; cmd; cmd = next) { + next = cmd->next; + free(cmd); + } +} +