2ced2eb5b88d3f3129173b9b867a0fbf3823d048
[NeonServV5.git] / UserNode.c
1 #include "UserNode.h"
2 #include "ChanUser.h"
3 #include "tools.h"
4
5 static struct UserNode **userList;
6
7 void init_UserNode() {
8     userList = calloc(VALID_NICK_CHARS_FIRST_LEN+1, sizeof(*userList));
9 }
10
11 void free_UserNode() {
12     //kamikaze free all users
13     //chanusers will be destroyed in free_ChanNode()
14     int i;
15     struct UserNode *user, *next;
16     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
17         for(user = userList[i]; user; user = next) {
18             next = user->next;
19             free(user);
20         }
21     }
22     free(userList);
23 }
24
25 int is_valid_nick(const char *nick) {
26     unsigned int i;
27     //first char must be one of: a-zA-Z{|}~[\]^_`
28     if (!strchr(VALID_NICK_CHARS_FIRST, *nick))
29         return 0;
30     //all other chars must be one of: a-zA-Z0-9{|}~[\]^_`
31     for (i = 0; nick[i]; ++i)
32         if (!strchr(VALID_NICK_CHARS, nick[i]))
33             return 0;
34     if (strlen(nick) > NICKLEN)
35         return 0;
36     return 1;
37 }
38
39 static int get_nicklist_entry(int nick) {
40     int i;
41     char *valid_chars = VALID_NICK_CHARS_FIRST;
42     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) {
43         if(valid_chars[i] == nick)
44             return i;
45     }
46     return -1; //ERROR!
47 }
48
49 struct UserNode* getUserByNick(const char *nick) { //case sensitive
50     int userListIndex = get_nicklist_entry(*nick);
51     if(userListIndex == -1 || userList[userListIndex] == NULL)
52         return NULL;
53     struct UserNode *user;
54     for(user = userList[userListIndex]; user; user = user->next) {
55         if(!stricmp(nick, user->nick))
56             return user;
57     }
58     return NULL;
59 }
60
61 struct UserNode* getUserByMask(const char *mask) { //case sensitive
62     char cmask[strlen(mask)+1];
63     strcpy(cmask, mask);
64     int i;
65     struct UserNode *user = NULL;
66     for(i = 0; i < strlen(mask); i++) {
67         if(cmask[i] == '!') {
68             cmask[i] = 0;
69             user = getUserByNick(&cmask[0]);
70             return user;
71         } else if(cmask[i] == '.') {
72             //it's a server
73             return NULL;
74         }
75     }
76     return NULL;
77 }
78
79 struct UserNode* searchUserByNick(const char *nick) { //case insensitive
80     if(!isalpha(*nick)) 
81         return getUserByNick(nick);
82
83     int userListIndex;
84     struct UserNode *user;
85
86     //search in the lower case "section"
87     userListIndex = get_nicklist_entry(tolower(*nick));
88     if(userListIndex != -1 && userList[userListIndex] != NULL) {
89         for(user = userList[userListIndex]; user; user = user->next) {
90             if(!stricmp(nick, user->nick))
91                 return user;
92         }
93     }
94     //search in the upper case "section"
95     userListIndex = get_nicklist_entry(toupper(*nick));
96     if(userListIndex != -1 && userList[userListIndex] != NULL) {
97         for(user = userList[userListIndex]; user; user = user->next) {
98             if(!stricmp(nick, user->nick))
99                 return user;
100         }
101     }
102     return NULL;
103 }
104
105 int countUsersWithHost(char *host) {
106     int i, count = 0;
107     struct UserNode *user;
108     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
109         for(user = userList[i]; user; user = user->next) {
110             if(!strcmp(user->host, host)) {
111                 count++;
112             }
113         }
114     }
115     return count;
116 }
117
118 char *getAuthFakehost(char *auth) {
119     int i;
120     struct UserNode *user;
121     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
122         for(user = userList[i]; user; user = user->next) {
123             if((user->flags & USERFLAG_ISAUTHED) && !strcmp(user->auth, auth) && isFakeHost(user->host)) {
124                 return user->host;
125             }
126         }
127     }
128     return NULL;
129 }
130
131 struct UserNode* getAllUsers(struct UserNode *last) {
132     if(last == NULL || last->next == NULL) {
133         int cindex;
134         if(last == NULL)
135             cindex = 0;
136         else
137             cindex = get_nicklist_entry(last->nick[0]) + 1;
138         while(userList[cindex] == NULL && cindex <= VALID_NICK_CHARS_FIRST_LEN)
139             cindex++;
140         if(cindex > VALID_NICK_CHARS_FIRST_LEN) return NULL;
141         return userList[cindex];
142     } else
143         return last->next;
144 }
145
146 int getUserCount() {
147     int i, count = 0;
148     struct UserNode *user;
149     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
150         for(user = userList[i]; user; user = user->next) {
151             count++;
152         }
153     }
154     return count;
155 }
156
157 struct UserNode* addUser(const char *nick) {
158     int userListIndex = get_nicklist_entry(*nick);
159     if(userListIndex == -1 || !is_valid_nick(nick))
160         return NULL;
161     struct UserNode *user = malloc(sizeof(*user));
162     if (!user)
163     {
164         perror("malloc() failed");
165         return NULL;
166     }
167     strcpy(user->nick, nick);
168     user->created = time(0);
169     user->ident[0] = 0;
170     user->host[0] = 0;
171     user->realname[0] = 0;
172     user->flags = 0;
173     user->channel = NULL;
174     user->next = userList[userListIndex];
175     userList[userListIndex] = user;
176     return user;
177 }
178
179 struct UserNode* addUserMask(const char *mask) {
180     char cmask[strlen(mask)+1];
181     strcpy(cmask, mask);
182     int i, ii = 0;
183     struct UserNode *user = NULL;
184     for(i = 0; i < strlen(mask)+1; i++) {
185         if(cmask[i] == '!') {
186             cmask[i] = 0;
187             user = addUser(cmask);
188             if(user == NULL) return NULL;
189             ii = i+1;
190         } else if(cmask[i] == '.' && !user) {
191             //it's a server
192             return NULL;
193         } else if(cmask[i] == '@') {
194             if(user == NULL) return NULL;
195             cmask[i] = 0;
196             strcpy(user->ident, &cmask[ii]);
197             ii = i+1;
198         } else if(cmask[i] == '\0') {
199             if(user == NULL) return NULL;
200             strcpy(user->host, &cmask[ii]);
201         }
202     }
203     return user;
204 }
205
206 struct UserNode* createTempUser(const char *mask) {
207     //note: it could also be a server we have to create a temponary user for...
208     char cmask[strlen(mask)+1];
209     strcpy(cmask, mask);
210     int i, ii = 0;
211     struct UserNode *user = NULL;
212     for(i = 0; i < strlen(mask)+1; i++) {
213         if(cmask[i] == '!') {
214             cmask[i] = 0;
215             user = malloc(sizeof(*user));
216             if (!user)
217             {
218                 perror("malloc() failed");
219                 return NULL;
220             }
221             strcpy(user->nick, cmask);
222             user->created = time(0);
223             user->ident[0] = 0;
224             user->host[0] = 0;
225             user->realname[0] = 0;
226             user->flags = 0;
227             user->channel = NULL;
228             ii = i+1;
229         } else if(cmask[i] == '.' && !user) {
230             //it's a server
231             user = malloc(sizeof(*user));
232             if (!user)
233             {
234                 perror("malloc() failed");
235                 return NULL;
236             }
237             strcpy(user->host, cmask);
238             user->created = time(0);
239             user->ident[0] = 0;
240             user->host[0] = 0;
241             user->realname[0] = 0;
242             user->flags = USERFLAG_ISSERVER;
243             user->channel = NULL;
244             return user;
245         } else if(cmask[i] == '@') {
246             if(user == NULL) return NULL;
247             cmask[i] = 0;
248             strcpy(user->ident, &cmask[ii]);
249             ii = i+1;
250         } else if(cmask[i] == '\0') {
251             if(user == NULL) {
252                 //nick only
253                 user = malloc(sizeof(*user));
254                 if (!user)
255                 {
256                     perror("malloc() failed");
257                     return NULL;
258                 }
259                 strcpy(user->nick, cmask);
260                 user->created = time(0);
261                 user->ident[0] = 0;
262                 user->host[0] = 0;
263                 user->realname[0] = 0;
264                 user->flags = 0;
265                 user->channel = NULL;
266                 return user;
267             }
268             strcpy(user->host, &cmask[ii]);
269         }
270     }
271     return user;
272 }
273
274 int renameUser(struct UserNode* user, const char *new_nick) {
275     if(!is_valid_nick(new_nick))
276         return 0;
277     if(user->nick[0] == *new_nick) {
278         strcpy(user->nick, new_nick);
279         return 1;
280     }
281     int userListIndex = get_nicklist_entry(*new_nick);
282     delUser(user, 0);
283     strcpy(user->nick, new_nick);
284     user->next = userList[userListIndex];
285     userList[userListIndex] = user;
286     return 1;
287 }
288
289 void delUser(struct UserNode* user, int freeUser) {
290     int userListIndex = get_nicklist_entry(user->nick[0]);
291     if(userListIndex == -1) return;
292     struct UserNode *cuser, *last_user = NULL;
293     for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) {
294         if(cuser == user) {
295             if(last_user)
296                 last_user->next = user->next;
297             else
298                 userList[userListIndex] = user->next;
299             break;
300         } else
301             last_user = cuser;
302     }
303     if(user->channel) {
304         struct ChanUser *chanUser, *next;
305         for(chanUser = user->channel; chanUser; chanUser = next) {
306             next = chanUser->next_chan;
307             removeChanUserFromLists(chanUser, 1, 0, freeUser);
308         }
309     }
310     if(freeUser)
311         free(user);
312     else
313         user->next = NULL;
314 }
315
316 void clearTempUsers() {
317     int userListIndex = TEMPUSER_LIST_INDEX;
318     struct UserNode *cuser, *last_user = NULL, *next;
319     time_t now = time(0);
320     for(cuser = userList[userListIndex]; cuser; cuser = next) {
321         next = cuser->next;
322         if(cuser->flags & USERFLAG_FREETMPUSER || now - cuser->created >= 300) {
323             if(last_user)
324                 last_user->next = cuser->next;
325             else
326                 userList[userListIndex] = cuser->next;
327             break;
328         } else
329             last_user = cuser;
330     }
331 }