*** VERSION 5.4.0 ***
[NeonServV5.git] / src / ChanUser.c
1 /* ChanUser.c - NeonServ v5.4
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "ChanUser.h"
19 #include "ChanNode.h"
20 #include "ModeNode.h"
21 #include "UserNode.h"
22
23 struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) {
24     struct ChanUser *chanuser = malloc(sizeof(*chanuser));
25     if (!chanuser)
26     {
27         perror("malloc() failed");
28         return NULL;
29     }
30     chanuser->flags = 0;
31     chanuser->user = user;
32     chanuser->chan = chan;
33     
34     chanuser->changeTime = 0;
35     chanuser->spamnode = NULL;
36
37     SYNCHRONIZE(cache_sync);
38
39     chanuser->next_user = chan->user;
40     chan->user = chanuser;
41     chan->usercount++;
42
43     chanuser->next_chan = user->channel;
44     user->channel = chanuser;
45
46     DESYNCHRONIZE(cache_sync);
47
48     return chanuser;
49 }
50
51 struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user) {
52     struct ChanUser *chanuser = malloc(sizeof(*chanuser));
53     if (!chanuser)
54     {
55         perror("malloc() failed");
56         return NULL;
57     }
58     chanuser->flags = CHANUSERFLAG_INVISIBLE;
59     chanuser->user = user;
60     chanuser->chan = chan;
61     
62     chanuser->changeTime = 0;
63     chanuser->spamnode = NULL;
64
65     SYNCHRONIZE(cache_sync);
66     chanuser->next_user = chan->user;
67     chan->user = chanuser;
68     DESYNCHRONIZE(cache_sync);
69     chan->usercount++;
70
71     return chanuser;
72 }
73
74 int isUserOnChan(struct UserNode *user, struct ChanNode *chan) {
75     struct ChanUser *chanuser;
76     if(isModeSet(chan->modes, 'd') || isModeSet(chan->modes, 'D')) {
77         for(chanuser = chan->user; chanuser; chanuser = chanuser->next_user) {
78             if(chanuser->user == user)
79                 return 1;
80         }
81     } else {
82         for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
83             if(chanuser->chan == chan)
84                 return 1;
85         }
86     }
87     return 0;
88 }
89
90 struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan) {
91     struct ChanUser *chanuser;
92     if(isModeSet(chan->modes, 'd') || isModeSet(chan->modes, 'D')) {
93         for(chanuser = chan->user; chanuser; chanuser = chanuser->next_user) {
94             if(chanuser->user == user)
95                 return chanuser;
96         }
97     } else {
98         for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
99             if(chanuser->chan == chan)
100                 return chanuser;
101         }
102     }
103     return NULL;
104 }
105
106 struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last) {
107     if(last == NULL)
108         return chan->user;
109     else
110         return last->next_user;
111 }
112
113 struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last) {
114     if(last == NULL)
115         return user->channel;
116     else
117         return last->next_chan;
118 }
119
120 void delChanUser(struct ChanUser *chanuser, int do_freeChanUser) {
121     SYNCHRONIZE(cache_sync);
122     struct ChanUser *cchanuser, *last;
123     //remove it from the user's channel-list
124     if(!(chanuser->flags & CHANUSERFLAG_INVISIBLE)) {
125         last = NULL;
126         for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
127             if(cchanuser == chanuser) {
128                 if(last) 
129                     last->next_chan = chanuser->next_chan;
130                 else
131                     chanuser->user->channel = chanuser->next_chan;
132                 break;
133             } else
134                 last = cchanuser;
135         }
136     }
137
138     //remove it from the channel's user-list
139     last = NULL;
140     for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
141         if(cchanuser == chanuser) {
142             chanuser->chan->usercount--;
143             if(last) 
144                 last->next_user = chanuser->next_user;
145             else
146                 chanuser->chan->user = chanuser->next_user;
147             break;
148         } else
149             last = cchanuser;
150     }
151     
152     if(do_freeChanUser) {
153         freeChanUser(chanuser);
154     } else {
155         chanuser->next_chan = NULL;
156         chanuser->next_user = NULL;
157     }
158     DESYNCHRONIZE(cache_sync);
159 }
160
161 void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int do_freeChanUser) {
162     SYNCHRONIZE(cache_sync);
163     struct ChanUser *cchanuser, *last;
164     if(remove_from_userlist) {
165         //remove it from the channel's user-list
166         last = NULL;
167         for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
168             if(cchanuser == chanuser) {
169                 chanuser->chan->usercount--;
170                 if(last) 
171                     last->next_user = chanuser->next_user;
172                 else
173                     chanuser->chan->user = chanuser->next_user;
174                 break;
175             } else
176                 last = cchanuser;
177         }
178         chanuser->next_user = NULL;
179     }
180     if(remove_from_channellist) {
181         //remove it from the user's channel-list
182         last = NULL;
183         for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
184             if(cchanuser == chanuser) {
185                 if(last) 
186                     last->next_chan = chanuser->next_chan;
187                 else
188                     chanuser->user->channel = chanuser->next_chan;
189                 break;
190             } else
191                 last = cchanuser;
192         }
193         chanuser->next_chan = NULL;
194     }
195     
196     if(do_freeChanUser) {
197         freeChanUser(chanuser);
198     }
199     DESYNCHRONIZE(cache_sync);
200 }
201
202 void freeChanUser(struct ChanUser *chanuser) {
203     if(chanuser->spamnode)
204         free(chanuser->spamnode);
205     free(chanuser);
206 }
207