added some more events and changed TempUser-Handling
[NeonServV5.git] / UserNode.c
1 #include "UserNode.h"
2 #include "ChanUser.h"
3
4 static struct UserNode **userList;
5
6 void init_UserNode() {
7     userList = calloc(VALID_NICK_CHARS_FIRST_LEN+1, sizeof(*userList));
8 }
9
10 int is_valid_nick(const char *nick) {
11     unsigned int i;
12     //first char must be one of: a-zA-Z{|}~[\]^_`
13     if (!strchr(VALID_NICK_CHARS_FIRST, *nick))
14         return 0;
15     //all other chars must be one of: a-zA-Z0-9{|}~[\]^_`
16     for (i = 0; nick[i]; ++i)
17         if (!strchr(VALID_NICK_CHARS, nick[i]))
18             return 0;
19     if (strlen(nick) > NICKLEN)
20         return 0;
21     return 1;
22 }
23
24 static int get_nicklist_entry(int nick) {
25     int i;
26     char *valid_chars = VALID_NICK_CHARS_FIRST;
27     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) {
28         if(valid_chars[i] == nick)
29             return i;
30     }
31     return -1; //ERROR!
32 }
33
34 struct UserNode* getUserByNick(const char *nick) { //case sensitive
35     int userListIndex = get_nicklist_entry(*nick);
36     if(userListIndex == -1 || userList[userListIndex] == NULL)
37         return NULL;
38     struct UserNode *user;
39     for(user = userList[userListIndex]; user; user = user->next) {
40         if(!stricmp(nick, user->nick))
41             return user;
42     }
43     return NULL;
44 }
45
46 struct UserNode* getUserByMask(const char *mask) { //case sensitive
47     char cmask[strlen(mask)+1];
48     strcpy(cmask, mask);
49     int i;
50     struct UserNode *user = NULL;
51     for(i = 0; i < strlen(mask); i++) {
52         if(cmask[i] == '!') {
53             cmask[i] = 0;
54             user = getUserByNick(&cmask[0]);
55             return user;
56         } else if(cmask[i] == '.') {
57             //it's a server
58             return NULL;
59         }
60     }
61     return NULL;
62 }
63
64 struct UserNode* searchUserByNick(const char *nick) { //case insensitive
65     if(!isalpha(*nick)) 
66         return getUserByNick(nick);
67
68     int userListIndex;
69     struct UserNode *user;
70
71     //search in the lower case "section"
72     userListIndex = get_nicklist_entry(tolower(*nick));
73     if(userListIndex != -1 && userList[userListIndex] != NULL) {
74         for(user = userList[userListIndex]; user; user = user->next) {
75             if(!stricmp(nick, user->nick))
76                 return user;
77         }
78     }
79     //search in the upper case "section"
80     userListIndex = get_nicklist_entry(toupper(*nick));
81     if(userListIndex != -1 && userList[userListIndex] != NULL) {
82         for(user = userList[userListIndex]; user; user = user->next) {
83             if(!stricmp(nick, user->nick))
84                 return user;
85         }
86     }
87     return NULL;
88 }
89
90 struct UserNode* addUser(const char *nick) {
91     int userListIndex = get_nicklist_entry(*nick);
92     if(userListIndex == -1 || !is_valid_nick(nick))
93         return NULL;
94     struct UserNode *user = malloc(sizeof(*user));
95     if (!user)
96     {
97         perror("malloc() failed");
98         return NULL;
99     }
100     strcpy(user->nick, nick);
101     user->created = time(0);
102     user->ident[0] = 0;
103     user->host[0] = 0;
104     user->realname[0] = 0;
105     user->flags = 0;
106     user->channel = NULL;
107     user->next = userList[userListIndex];
108     userList[userListIndex] = user;
109     return user;
110 }
111
112 struct UserNode* addUserMask(const char *mask) {
113     char cmask[strlen(mask)+1];
114     strcpy(cmask, mask);
115     int i, ii = 0;
116     struct UserNode *user = NULL;
117     for(i = 0; i < strlen(mask)+1; i++) {
118         if(cmask[i] == '!') {
119             cmask[i] = 0;
120             user = addUser(cmask);
121             if(user == NULL) return NULL;
122             ii = i+1;
123         } else if(cmask[i] == '.' && !user) {
124             //it's a server
125             return NULL;
126         } else if(cmask[i] == '@') {
127             if(user == NULL) return NULL;
128             cmask[i] = 0;
129             strcpy(user->ident, &cmask[ii]);
130             ii = i+1;
131         } else if(cmask[i] == '\0') {
132             if(user == NULL) return NULL;
133             strcpy(user->host, &cmask[ii]);
134         }
135     }
136     return user;
137 }
138
139 struct UserNode* createTempUser(const char *mask) {
140     //note: it could also be a server we have to create a temponary user for...
141     char cmask[strlen(mask)+1];
142     strcpy(cmask, mask);
143     int i, ii = 0;
144     struct UserNode *user = NULL;
145     for(i = 0; i < strlen(mask)+1; i++) {
146         if(cmask[i] == '!') {
147             cmask[i] = 0;
148             user = malloc(sizeof(*user));
149             if (!user)
150             {
151                 perror("malloc() failed");
152                 return NULL;
153             }
154             strcpy(user->nick, cmask);
155             user->created = time(0);
156             user->ident[0] = 0;
157             user->host[0] = 0;
158             user->realname[0] = 0;
159             user->flags = 0;
160             user->channel = NULL;
161             ii = i+1;
162         } else if(cmask[i] == '.' && !user) {
163             //it's a server
164             user = malloc(sizeof(*user));
165             if (!user)
166             {
167                 perror("malloc() failed");
168                 return NULL;
169             }
170             strcpy(user->host, cmask);
171             user->created = time(0);
172             user->ident[0] = 0;
173             user->host[0] = 0;
174             user->realname[0] = 0;
175             user->flags = USERFLAG_ISSERVER;
176             user->channel = NULL;
177             return user;
178         } else if(cmask[i] == '@') {
179             if(user == NULL) return NULL;
180             cmask[i] = 0;
181             strcpy(user->ident, &cmask[ii]);
182             ii = i+1;
183         } else if(cmask[i] == '\0') {
184             if(user == NULL) return NULL;
185             strcpy(user->host, &cmask[ii]);
186         }
187     }
188     return user;
189 }
190
191 int renameUser(struct UserNode* user, const char *new_nick) {
192     if(!is_valid_nick(new_nick))
193         return 0;
194     if(user->nick[0] == *new_nick) {
195         strcpy(user->nick, new_nick);
196         return 1;
197     }
198     int userListIndex = get_nicklist_entry(*new_nick);
199     delUser(user, 0);
200     strcpy(user->nick, new_nick);
201     user->next = userList[userListIndex];
202     userList[userListIndex] = user;
203     return 1;
204 }
205
206 void delUser(struct UserNode* user, int freeUser) {
207     int userListIndex = get_nicklist_entry(user->nick[0]);
208     if(userListIndex == -1) return;
209     struct UserNode *cuser, *last_user = NULL;
210     for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) {
211         if(cuser == user) {
212             if(last_user)
213                 last_user->next = user->next;
214             else
215                 userList[userListIndex] = user->next;
216             break;
217         } else
218             last_user = cuser;
219     }
220     if(user->channel) {
221         struct ChanUser *chanUser, *next;
222         for(chanUser = user->channel; chanUser; chanUser = next) {
223             next = chanUser->next_chan;
224             removeChanUserFromLists(chanUser, 1, 0, freeUser);
225         }
226     }
227     if(freeUser)
228         free(user);
229     else
230         user->next = NULL;
231 }
232
233 void clearTempUsers() {
234     int userListIndex = TEMPUSER_LIST_INDEX;
235     struct UserNode *cuser, *last_user = NULL, *next;
236     time_t now = time(0);
237     for(cuser = userList[userListIndex]; cuser; cuser = next) {
238         next = cuser->next;
239         if(cuser->flags & USERFLAG_FREETMPUSER || now - cuser->created >= 300) {
240             if(last_user)
241                 last_user->next = cuser->next;
242             else
243                 userList[userListIndex] = cuser->next;
244             break;
245         } else
246             last_user = cuser;
247     }
248 }