X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=blobdiff_plain;f=src%2FUserNode.c;h=cd8735e8f5ba7716b4cb5c3996d04b1353d53c7f;hp=f23548b57e22a485f62e7dd9396530e4478b7004;hb=HEAD;hpb=95fed4deda0319bee515e44ceec0c77061a2c04e diff --git a/src/UserNode.c b/src/UserNode.c index f23548b..cd8735e 100644 --- a/src/UserNode.c +++ b/src/UserNode.c @@ -1,5 +1,5 @@ -/* UserNode.c - NeonServ v5.0 - * Copyright (C) 2011 Philipp Kreil (pk910) +/* UserNode.c - NeonServ v5.6 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,13 +15,45 @@ * along with this program. If not, see . */ #include "UserNode.h" +#include "ChanNode.h" #include "ChanUser.h" #include "tools.h" +#include "IRCEvents.h" +#include "IPNode.h" +#include "log.h" static struct UserNode **userList; +unsigned int valid_user_modes[] = { + 1, 'o', + 2, 'O', + 3, 'i', + 4, 'w', + 5, 's', + 6, 'd', + 7, 'k', + 8, 'g', + 9, 'n', + 10, 'I', + 11, 'X', + 12, 'S', + 13, 'H', + 14, 'c', + 15, 'W', + 16, 't', + 17, 'D', + 18, 'x', +// ^ maximum is 32!!! + 0x00, 0x00 +}; + void init_UserNode() { + unsigned int *mode, flag = 1; userList = calloc(VALID_NICK_CHARS_FIRST_LEN+1, sizeof(*userList)); + for (mode = valid_user_modes; mode[1]; mode += 2) { + mode[0] = flag; + flag = flag << 1; + } } void free_UserNode() { @@ -62,19 +94,61 @@ static int get_nicklist_entry(int nick) { return -1; //ERROR! } +static unsigned int* getUserModeOptions(char mode) { + unsigned int *cmode; + for (cmode = valid_user_modes; cmode[1]; cmode += 2) { + if(cmode[1] == mode) + return cmode; + } + return NULL; +} + +int isUserModeSet(struct UserNode *user, char modeChar) { + unsigned int *modeOpt = getUserModeOptions(modeChar); + return (user->usermode & modeOpt[0]); +} + +void parseUserModes(struct UserNode* user, char *modeStr) { + int i, add = 1; + unsigned int *modeOpt; + for(i = 0; i < strlen(modeStr); i++) { + if(modeStr[i] == '+') { + add = 1; + continue; + } + if(modeStr[i] == '-') { + add = 0; + continue; + } + modeOpt = getUserModeOptions(modeStr[i]); + if(!modeOpt) continue; // unknown mode? + if(add) { + user->usermode |= modeOpt[0]; + } else { + user->usermode &= ~modeOpt[0]; + } + } +} + + struct UserNode* getUserByNick(const char *nick) { //case sensitive int userListIndex = get_nicklist_entry(*nick); if(userListIndex == -1 || userList[userListIndex] == NULL) return NULL; + SYNCHRONIZE(cache_sync); struct UserNode *user; for(user = userList[userListIndex]; user; user = user->next) { - if(!stricmp(nick, user->nick)) + if(!stricmp(nick, user->nick)) { + DESYNCHRONIZE(cache_sync); return user; + } } + DESYNCHRONIZE(cache_sync); return NULL; } struct UserNode* getUserByMask(const char *mask) { //case sensitive + SYNCHRONIZE(cache_sync); char cmask[strlen(mask)+1]; strcpy(cmask, mask); int i; @@ -83,12 +157,15 @@ struct UserNode* getUserByMask(const char *mask) { //case sensitive if(cmask[i] == '!') { cmask[i] = 0; user = getUserByNick(&cmask[0]); + DESYNCHRONIZE(cache_sync); return user; } else if(cmask[i] == '.') { //it's a server + DESYNCHRONIZE(cache_sync); return NULL; } } + DESYNCHRONIZE(cache_sync); return NULL; } @@ -96,6 +173,7 @@ struct UserNode* searchUserByNick(const char *nick) { //case insensitive if(!isalpha(*nick)) return getUserByNick(nick); + SYNCHRONIZE(cache_sync); int userListIndex; struct UserNode *user; @@ -103,70 +181,104 @@ struct UserNode* searchUserByNick(const char *nick) { //case insensitive userListIndex = get_nicklist_entry(tolower(*nick)); if(userListIndex != -1 && userList[userListIndex] != NULL) { for(user = userList[userListIndex]; user; user = user->next) { - if(!stricmp(nick, user->nick)) + if(!stricmp(nick, user->nick)) { + DESYNCHRONIZE(cache_sync); return user; + } } } //search in the upper case "section" userListIndex = get_nicklist_entry(toupper(*nick)); if(userListIndex != -1 && userList[userListIndex] != NULL) { for(user = userList[userListIndex]; user; user = user->next) { - if(!stricmp(nick, user->nick)) + if(!stricmp(nick, user->nick)) { + DESYNCHRONIZE(cache_sync); return user; + } } } + DESYNCHRONIZE(cache_sync); return NULL; } int countUsersWithHost(char *host) { + SYNCHRONIZE(cache_sync); int i, count = 0; struct UserNode *user; - for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) { + for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) { for(user = userList[i]; user; user = user->next) { if(!strcmp(user->host, host)) { count++; } } } + DESYNCHRONIZE(cache_sync); return count; } char *getAuthFakehost(char *auth) { + SYNCHRONIZE(cache_sync); int i; struct UserNode *user; - for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) { + for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) { for(user = userList[i]; user; user = user->next) { if((user->flags & USERFLAG_ISAUTHED) && !strcmp(user->auth, auth) && isFakeHost(user->host)) { + DESYNCHRONIZE(cache_sync); return user->host; } } } + DESYNCHRONIZE(cache_sync); return NULL; } struct UserNode* getAllUsers(struct UserNode *last) { + SYNCHRONIZE(cache_sync); if(last == NULL || last->next == NULL) { int cindex; if(last == NULL) cindex = 0; else cindex = get_nicklist_entry(last->nick[0]) + 1; - while(userList[cindex] == NULL && cindex <= VALID_NICK_CHARS_FIRST_LEN) + while(userList[cindex] == NULL && cindex < VALID_NICK_CHARS_FIRST_LEN) cindex++; - if(cindex > VALID_NICK_CHARS_FIRST_LEN) return NULL; + DESYNCHRONIZE(cache_sync); + if(cindex >= VALID_NICK_CHARS_FIRST_LEN) return NULL; return userList[cindex]; - } else + } else { + DESYNCHRONIZE(cache_sync); return last->next; + } +} + +struct UserNode* getUsersWithAuth(const char *auth, struct UserNode *last) { + SYNCHRONIZE(cache_sync); + int cindex = (last ? get_nicklist_entry(last->nick[0]) : 0); + struct UserNode *cuser = last; + while(cindex <= VALID_NICK_CHARS_FIRST_LEN) { + for(cuser = (cuser ? cuser->next : userList[cindex]); cuser; cuser = cuser->next) { + if((cuser->flags & USERFLAG_ISAUTHED) && !strcmp(cuser->auth, auth)) { + DESYNCHRONIZE(cache_sync); + return cuser; + } + } + cindex++; + cuser = NULL; + } + DESYNCHRONIZE(cache_sync); + return NULL; } int getUserCount() { + SYNCHRONIZE(cache_sync); int i, count = 0; struct UserNode *user; - for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) { + for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) { for(user = userList[i]; user; user = user->next) { count++; } } + DESYNCHRONIZE(cache_sync); return count; } @@ -177,18 +289,23 @@ struct UserNode* addUser(const char *nick) { struct UserNode *user = malloc(sizeof(*user)); if (!user) { - perror("malloc() failed"); + printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__); return NULL; } strcpy(user->nick, nick); user->created = time(0); user->ident[0] = 0; user->host[0] = 0; + user->ip = NULL; user->realname[0] = 0; user->flags = 0; user->channel = NULL; + user->last_who = 0; + user->usermode = 0; + SYNCHRONIZE(cache_sync); user->next = userList[userListIndex]; userList[userListIndex] = user; + DESYNCHRONIZE(cache_sync); return user; } @@ -219,45 +336,108 @@ struct UserNode* addUserMask(const char *mask) { return user; } -struct UserNode* createTempUser(const char *mask) { +struct UserNode* createTempUser(const char *nick) { + int already_on_list = 0; + struct UserNode *user = NULL; + if(!is_valid_nick(nick)) { + return NULL; + } + for(user = userList[TEMPUSER_LIST_INDEX]; user; user = user->next) { + if(!stricmp(user->nick, nick)) { + already_on_list = 1; + break; + } + } + if(!user) { + user = malloc(sizeof(*user)); + if (!user) { + printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__); + return NULL; + } + user->ident[0] = 0; + user->host[0] = 0; + user->ip = NULL; + user->realname[0] = 0; + user->flags = 0; + user->channel = NULL; + user->usermode = 0; + user->last_who = 0; + } else + user->flags &= ~USERFLAG_FREETMPUSER; + user->created = time(0); + if(user->created - user->last_who > REWHO_TIMEOUT) + user->flags &= ~USERFLAG_ISAUTHED; //remove authed flag (security reasons) + strcpy(user->nick, nick); + if(!already_on_list) { + SYNCHRONIZE(cache_sync); + user->next = userList[TEMPUSER_LIST_INDEX]; + userList[TEMPUSER_LIST_INDEX] = user; + DESYNCHRONIZE(cache_sync); + } + return user; +} + +struct UserNode* createTempUserMask(const char *mask) { //note: it could also be a server we have to create a temponary user for... char cmask[strlen(mask)+1]; strcpy(cmask, mask); int i, ii = 0; + int already_on_list = 0; struct UserNode *user = NULL; for(i = 0; i < strlen(mask)+1; i++) { if(cmask[i] == '!') { cmask[i] = 0; - user = malloc(sizeof(*user)); - if (!user) - { - perror("malloc() failed"); + if(!is_valid_nick(cmask)) { return NULL; } - strcpy(user->nick, cmask); + for(user = userList[TEMPUSER_LIST_INDEX]; user; user = user->next) { + if(!stricmp(user->nick, cmask)) { + already_on_list = 1; + break; + } + } + if(!user) { + user = malloc(sizeof(*user)); + if (!user) { + printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__); + return NULL; + } + user->ident[0] = 0; + user->host[0] = 0; + user->ip = NULL; + user->realname[0] = 0; + user->flags = 0; + user->channel = NULL; + user->usermode = 0; + user->last_who = 0; + } else + user->flags &= ~USERFLAG_FREETMPUSER; user->created = time(0); - user->ident[0] = 0; - user->host[0] = 0; - user->realname[0] = 0; - user->flags = 0; - user->channel = NULL; + if(user->created - user->last_who > REWHO_TIMEOUT) + user->flags &= ~USERFLAG_ISAUTHED; //remove authed flag (security reasons) + strcpy(user->nick, cmask); ii = i+1; } else if(cmask[i] == '.' && !user) { //it's a server user = malloc(sizeof(*user)); if (!user) { - perror("malloc() failed"); + printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__); return NULL; } strcpy(user->host, cmask); + strncpy(user->nick, cmask, NICKLEN); + user->nick[NICKLEN] = 0; user->created = time(0); user->ident[0] = 0; user->host[0] = 0; + user->ip = NULL; user->realname[0] = 0; user->flags = USERFLAG_ISSERVER; user->channel = NULL; - return user; + user->usermode = 0; + user->last_who = 0; + break; } else if(cmask[i] == '@') { if(user == NULL) return NULL; cmask[i] = 0; @@ -269,21 +449,30 @@ struct UserNode* createTempUser(const char *mask) { user = malloc(sizeof(*user)); if (!user) { - perror("malloc() failed"); + printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__); return NULL; } strcpy(user->nick, cmask); user->created = time(0); user->ident[0] = 0; user->host[0] = 0; + user->ip = NULL; user->realname[0] = 0; user->flags = 0; user->channel = NULL; - return user; + user->usermode = 0; + user->last_who = 0; + break; } strcpy(user->host, &cmask[ii]); } } + if(!already_on_list) { + SYNCHRONIZE(cache_sync); + user->next = userList[TEMPUSER_LIST_INDEX]; + userList[TEMPUSER_LIST_INDEX] = user; + DESYNCHRONIZE(cache_sync); + } return user; } @@ -294,17 +483,36 @@ int renameUser(struct UserNode* user, const char *new_nick) { strcpy(user->nick, new_nick); return 1; } - int userListIndex = get_nicklist_entry(*new_nick); - delUser(user, 0); + //delUser(user, 0); //EPIC FAIL! This deletes the user from the channel Userlist -.- + //manually remove the user from the old userList + SYNCHRONIZE(cache_sync); + int userListIndex = get_nicklist_entry(user->nick[0]); + if(userListIndex != -1) { + struct UserNode *cuser, *last_user = NULL; + for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) { + if(cuser == user) { + if(last_user) + last_user->next = user->next; + else + userList[userListIndex] = user->next; + break; + } else + last_user = cuser; + } + } + userListIndex = get_nicklist_entry(*new_nick); strcpy(user->nick, new_nick); user->next = userList[userListIndex]; userList[userListIndex] = user; + DESYNCHRONIZE(cache_sync); return 1; } void delUser(struct UserNode* user, int freeUser) { - int userListIndex = get_nicklist_entry(user->nick[0]); + int userListIndex = ((user->flags & USERFLAG_ISTMPUSER) ? TEMPUSER_LIST_INDEX : get_nicklist_entry(user->nick[0])); if(userListIndex == -1) return; + SYNCHRONIZE(cache_sync); + event_freeuser(user); struct UserNode *cuser, *last_user = NULL; for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) { if(cuser == user) { @@ -316,6 +524,10 @@ void delUser(struct UserNode* user, int freeUser) { } else last_user = cuser; } + if(freeUser && (user->flags & USERFLAG_IS_ON_WHO_QUEUE)) { + user->flags |= USERFLAG_FREE_AFTER_WHO; + freeUser = 0; + } if(user->channel) { struct ChanUser *chanUser, *next; for(chanUser = user->channel; chanUser; chanUser = next) { @@ -323,25 +535,25 @@ void delUser(struct UserNode* user, int freeUser) { removeChanUserFromLists(chanUser, 1, 0, freeUser); } } - if(freeUser) + if(freeUser) { + if(user->ip) + freeIPNode(user->ip); free(user); - else + } else user->next = NULL; + DESYNCHRONIZE(cache_sync); } void clearTempUsers() { + SYNCHRONIZE(cache_sync); int userListIndex = TEMPUSER_LIST_INDEX; - struct UserNode *cuser, *last_user = NULL, *next; + struct UserNode *cuser, *next; time_t now = time(0); for(cuser = userList[userListIndex]; cuser; cuser = next) { next = cuser->next; if(cuser->flags & USERFLAG_FREETMPUSER || now - cuser->created >= 300) { - if(last_user) - last_user->next = cuser->next; - else - userList[userListIndex] = cuser->next; - break; - } else - last_user = cuser; + delUser(cuser, 1); + } } + DESYNCHRONIZE(cache_sync); }