added cmd_ban and all functions depending on
[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* addUser(const char *nick) {
132     int userListIndex = get_nicklist_entry(*nick);
133     if(userListIndex == -1 || !is_valid_nick(nick))
134         return NULL;
135     struct UserNode *user = malloc(sizeof(*user));
136     if (!user)
137     {
138         perror("malloc() failed");
139         return NULL;
140     }
141     strcpy(user->nick, nick);
142     user->created = time(0);
143     user->ident[0] = 0;
144     user->host[0] = 0;
145     user->realname[0] = 0;
146     user->flags = 0;
147     user->channel = NULL;
148     user->next = userList[userListIndex];
149     userList[userListIndex] = user;
150     return user;
151 }
152
153 struct UserNode* addUserMask(const char *mask) {
154     char cmask[strlen(mask)+1];
155     strcpy(cmask, mask);
156     int i, ii = 0;
157     struct UserNode *user = NULL;
158     for(i = 0; i < strlen(mask)+1; i++) {
159         if(cmask[i] == '!') {
160             cmask[i] = 0;
161             user = addUser(cmask);
162             if(user == NULL) return NULL;
163             ii = i+1;
164         } else if(cmask[i] == '.' && !user) {
165             //it's a server
166             return NULL;
167         } else if(cmask[i] == '@') {
168             if(user == NULL) return NULL;
169             cmask[i] = 0;
170             strcpy(user->ident, &cmask[ii]);
171             ii = i+1;
172         } else if(cmask[i] == '\0') {
173             if(user == NULL) return NULL;
174             strcpy(user->host, &cmask[ii]);
175         }
176     }
177     return user;
178 }
179
180 struct UserNode* createTempUser(const char *mask) {
181     //note: it could also be a server we have to create a temponary user for...
182     char cmask[strlen(mask)+1];
183     strcpy(cmask, mask);
184     int i, ii = 0;
185     struct UserNode *user = NULL;
186     for(i = 0; i < strlen(mask)+1; i++) {
187         if(cmask[i] == '!') {
188             cmask[i] = 0;
189             user = malloc(sizeof(*user));
190             if (!user)
191             {
192                 perror("malloc() failed");
193                 return NULL;
194             }
195             strcpy(user->nick, cmask);
196             user->created = time(0);
197             user->ident[0] = 0;
198             user->host[0] = 0;
199             user->realname[0] = 0;
200             user->flags = 0;
201             user->channel = NULL;
202             ii = i+1;
203         } else if(cmask[i] == '.' && !user) {
204             //it's a server
205             user = malloc(sizeof(*user));
206             if (!user)
207             {
208                 perror("malloc() failed");
209                 return NULL;
210             }
211             strcpy(user->host, cmask);
212             user->created = time(0);
213             user->ident[0] = 0;
214             user->host[0] = 0;
215             user->realname[0] = 0;
216             user->flags = USERFLAG_ISSERVER;
217             user->channel = NULL;
218             return user;
219         } else if(cmask[i] == '@') {
220             if(user == NULL) return NULL;
221             cmask[i] = 0;
222             strcpy(user->ident, &cmask[ii]);
223             ii = i+1;
224         } else if(cmask[i] == '\0') {
225             if(user == NULL) {
226                 //nick only
227                 user = malloc(sizeof(*user));
228                 if (!user)
229                 {
230                     perror("malloc() failed");
231                     return NULL;
232                 }
233                 strcpy(user->nick, cmask);
234                 user->created = time(0);
235                 user->ident[0] = 0;
236                 user->host[0] = 0;
237                 user->realname[0] = 0;
238                 user->flags = 0;
239                 user->channel = NULL;
240                 return user;
241             }
242             strcpy(user->host, &cmask[ii]);
243         }
244     }
245     return user;
246 }
247
248 int renameUser(struct UserNode* user, const char *new_nick) {
249     if(!is_valid_nick(new_nick))
250         return 0;
251     if(user->nick[0] == *new_nick) {
252         strcpy(user->nick, new_nick);
253         return 1;
254     }
255     int userListIndex = get_nicklist_entry(*new_nick);
256     delUser(user, 0);
257     strcpy(user->nick, new_nick);
258     user->next = userList[userListIndex];
259     userList[userListIndex] = user;
260     return 1;
261 }
262
263 void delUser(struct UserNode* user, int freeUser) {
264     int userListIndex = get_nicklist_entry(user->nick[0]);
265     if(userListIndex == -1) return;
266     struct UserNode *cuser, *last_user = NULL;
267     for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) {
268         if(cuser == user) {
269             if(last_user)
270                 last_user->next = user->next;
271             else
272                 userList[userListIndex] = user->next;
273             break;
274         } else
275             last_user = cuser;
276     }
277     if(user->channel) {
278         struct ChanUser *chanUser, *next;
279         for(chanUser = user->channel; chanUser; chanUser = next) {
280             next = chanUser->next_chan;
281             removeChanUserFromLists(chanUser, 1, 0, freeUser);
282         }
283     }
284     if(freeUser)
285         free(user);
286     else
287         user->next = NULL;
288 }
289
290 void clearTempUsers() {
291     int userListIndex = TEMPUSER_LIST_INDEX;
292     struct UserNode *cuser, *last_user = NULL, *next;
293     time_t now = time(0);
294     for(cuser = userList[userListIndex]; cuser; cuser = next) {
295         next = cuser->next;
296         if(cuser->flags & USERFLAG_FREETMPUSER || now - cuser->created >= 300) {
297             if(last_user)
298                 last_user->next = cuser->next;
299             else
300                 userList[userListIndex] = cuser->next;
301             break;
302         } else
303             last_user = cuser;
304     }
305 }