added raw_topic, raw_privmsg and wrote the small "dead channel garbage collector"
[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, sizeof(*userList));
8     
9 }
10
11 int is_valid_nick(const char *nick) {
12     unsigned int i;
13     //first char must be one of: a-zA-Z{|}~[\]^_`
14     if (!strchr(VALID_NICK_CHARS_FIRST, *nick))
15         return 0;
16     //all other chars must be one of: a-zA-Z0-9{|}~[\]^_`
17     for (i = 0; nick[i]; ++i)
18         if (!strchr(VALID_NICK_CHARS, nick[i]))
19             return 0;
20     if (strlen(nick) > NICKLEN)
21         return 0;
22     return 1;
23 }
24
25 static int get_nicklist_entry(int nick) {
26     int i;
27     char *valid_chars = VALID_NICK_CHARS_FIRST;
28     for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) {
29         if(valid_chars[i] == nick)
30             return i;
31     }
32     return -1; //ERROR!
33 }
34
35 struct UserNode* getUserByNick(const char *nick) { //case sensitive
36     int userListIndex = get_nicklist_entry(*nick);
37     if(userListIndex == -1 || userList[userListIndex] == NULL)
38         return NULL;
39     struct UserNode *user;
40     for(user = userList[userListIndex]; user; user = user->next) {
41         if(!stricmp(nick, user->nick))
42             return user;
43     }
44     return NULL;
45 }
46
47 struct UserNode* getUserByMask(const char *mask) { //case sensitive
48     char cmask[strlen(mask)+1];
49     strcpy(cmask, mask);
50     int i;
51     struct UserNode *user = NULL;
52     for(i = 0; i < strlen(mask); i++) {
53         if(cmask[i] == '!') {
54             cmask[i] = 0;
55             user = getUserByNick(&cmask[0]);
56             return user;
57         } else if(cmask[i] == '.') {
58             //it's a server
59             return NULL;
60         }
61     }
62     return NULL;
63 }
64
65 struct UserNode* searchUserByNick(const char *nick) { //case insensitive
66     if(!isalpha(*nick)) 
67         return getUserByNick(nick);
68
69     int userListIndex;
70     struct UserNode *user;
71
72     //search in the lower case "section"
73     userListIndex = get_nicklist_entry(tolower(*nick));
74     if(userListIndex != -1 && userList[userListIndex] != NULL) {
75         for(user = userList[userListIndex]; user; user = user->next) {
76             if(!stricmp(nick, user->nick))
77                 return user;
78         }
79     }
80     //search in the upper case "section"
81     userListIndex = get_nicklist_entry(toupper(*nick));
82     if(userListIndex != -1 && userList[userListIndex] != NULL) {
83         for(user = userList[userListIndex]; user; user = user->next) {
84             if(!stricmp(nick, user->nick))
85                 return user;
86         }
87     }
88     return NULL;
89 }
90
91 struct UserNode* addUser(const char *nick) {
92     int userListIndex = get_nicklist_entry(*nick);
93     if(userListIndex == -1 || !is_valid_nick(nick))
94         return NULL;
95     struct UserNode *user = malloc(sizeof(*user));
96     if (!user)
97     {
98         perror("malloc() failed");
99         return NULL;
100     }
101     strcpy(user->nick, nick);
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             struct UserNode *user = malloc(sizeof(*user));
149             if (!user)
150             {
151                 perror("malloc() failed");
152                 return NULL;
153             }
154             strcpy(user->nick, nick);
155             user->ident[0] = 0;
156             user->host[0] = 0;
157             user->realname[0] = 0;
158             user->flags = 0;
159             user->channel = NULL;
160             ii = i+1;
161         } else if(cmask[i] == '.' && !user) {
162             //it's a server
163             struct UserNode *user = malloc(sizeof(*user));
164             if (!user)
165             {
166                 perror("malloc() failed");
167                 return NULL;
168             }
169             strcpy(user->host, cmask);
170             user->ident[0] = 0;
171             user->host[0] = 0;
172             user->realname[0] = 0;
173             user->flags = USERFLAG_ISSERVER;
174             user->channel = NULL;
175             return user;
176         } else if(cmask[i] == '@') {
177             if(user == NULL) return NULL;
178             cmask[i] = 0;
179             strcpy(user->ident, &cmask[ii]);
180             ii = i+1;
181         } else if(cmask[i] == '\0') {
182             if(user == NULL) return NULL;
183             strcpy(user->host, &cmask[ii]);
184         }
185     }
186     return user;
187 }
188
189 int renameUser(struct UserNode* user, const char *new_nick) {
190     if(!is_valid_nick(new_nick))
191         return 0;
192     if(user->nick[0] == *new_nick) {
193         strcpy(user->nick, new_nick);
194         return 1;
195     }
196     int userListIndex = get_nicklist_entry(*new_nick);
197     delUser(user, 0);
198     strcpy(user->nick, new_nick);
199     user->next = userList[userListIndex];
200     userList[userListIndex] = user;
201     return 1;
202 }
203
204 void delUser(struct UserNode* user, int freeUser) {
205     int userListIndex = get_nicklist_entry(user->nick[0]);
206     if(userListIndex == -1) return;
207     struct UserNode *cuser, *last_user = NULL;
208     for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) {
209         if(cuser == user) {
210             if(last_user)
211                 last_user->next = user->next;
212             else
213                 userList[userListIndex] = user->next;
214             break;
215         } else
216             last_user = cuser;
217     }
218     if(user->channel) {
219         struct ChanUser *chanUser, *next;
220         for(chanUser = user->channel; chanUser; chanUser = next) {
221             next = chanUser->next_chan;
222             removeChanUserFromLists(chanUser, 1, 0, freeUser);
223         }
224     }
225     if(freeUser)
226         free(user);
227     else
228         user->next = NULL;
229 }