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