Merge branch 'development'
[NeonServV5.git] / src / ChanUser.c
1 /* ChanUser.c - NeonServ v5.6
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 #include "log.h"
23
24 struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) {
25     struct ChanUser *chanuser = malloc(sizeof(*chanuser));
26     if (!chanuser)
27     {
28         printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__);
29         return NULL;
30     }
31     chanuser->flags = 0;
32     chanuser->user = user;
33     chanuser->chan = chan;
34     chanuser->visCount = 0;
35     
36     chanuser->changeTime = 0;
37     chanuser->spamnode = NULL;
38
39     SYNCHRONIZE(cache_sync);
40
41     chanuser->next_user = chan->user;
42     chan->user = chanuser;
43     chan->usercount++;
44
45     chanuser->next_chan = user->channel;
46     user->channel = chanuser;
47
48     DESYNCHRONIZE(cache_sync);
49
50     return chanuser;
51 }
52
53 struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user) {
54     struct ChanUser *chanuser = malloc(sizeof(*chanuser));
55     if (!chanuser)
56     {
57         printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__);
58         return NULL;
59     }
60     chanuser->flags = CHANUSERFLAG_INVISIBLE;
61     chanuser->user = user;
62     chanuser->chan = chan;
63     chanuser->visCount = 0;
64     
65     chanuser->changeTime = 0;
66     chanuser->spamnode = NULL;
67
68     SYNCHRONIZE(cache_sync);
69     chanuser->next_user = chan->user;
70     chan->user = chanuser;
71     DESYNCHRONIZE(cache_sync);
72     chan->usercount++;
73
74     return chanuser;
75 }
76
77 int isUserOnChan(struct UserNode *user, struct ChanNode *chan) {
78     struct ChanUser *chanuser;
79     if(isModeSet(chan->modes, 'd') || isModeSet(chan->modes, 'D')) {
80         for(chanuser = chan->user; chanuser; chanuser = chanuser->next_user) {
81             if(chanuser->user == user)
82                 return 1;
83         }
84     } else {
85         for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
86             if(chanuser->chan == chan)
87                 return 1;
88         }
89     }
90     return 0;
91 }
92
93 struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan) {
94     struct ChanUser *chanuser;
95     if(isModeSet(chan->modes, 'd') || isModeSet(chan->modes, 'D')) {
96         for(chanuser = chan->user; chanuser; chanuser = chanuser->next_user) {
97             if(chanuser->user == user)
98                 return chanuser;
99         }
100     } else {
101         for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
102             if(chanuser->chan == chan)
103                 return chanuser;
104         }
105     }
106     return NULL;
107 }
108
109 struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last) {
110     if(last == NULL)
111         return chan->user;
112     else
113         return last->next_user;
114 }
115
116 struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last) {
117     if(last == NULL)
118         return user->channel;
119     else
120         return last->next_chan;
121 }
122
123 void delChanUser(struct ChanUser *chanuser, int do_freeChanUser) {
124     SYNCHRONIZE(cache_sync);
125     struct ChanUser *cchanuser, *last;
126     //remove it from the user's channel-list
127     last = NULL;
128     for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
129         if(cchanuser == chanuser) {
130             if(last) 
131                 last->next_chan = chanuser->next_chan;
132             else
133                 chanuser->user->channel = chanuser->next_chan;
134             break;
135         } else
136             last = cchanuser;
137     }
138
139     //remove it from the channel's user-list
140     last = NULL;
141     for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
142         if(cchanuser == chanuser) {
143             chanuser->chan->usercount--;
144             if(last) 
145                 last->next_user = chanuser->next_user;
146             else
147                 chanuser->chan->user = chanuser->next_user;
148             break;
149         } else
150             last = cchanuser;
151     }
152     
153     if(do_freeChanUser) {
154         freeChanUser(chanuser);
155     } else {
156         chanuser->next_chan = NULL;
157         chanuser->next_user = NULL;
158     }
159     DESYNCHRONIZE(cache_sync);
160 }
161
162 void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int do_freeChanUser) {
163     SYNCHRONIZE(cache_sync);
164     struct ChanUser *cchanuser, *last;
165     if(remove_from_userlist) {
166         //remove it from the channel's user-list
167         last = NULL;
168         for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
169             if(cchanuser == chanuser) {
170                 chanuser->chan->usercount--;
171                 if(last) 
172                     last->next_user = chanuser->next_user;
173                 else
174                     chanuser->chan->user = chanuser->next_user;
175                 break;
176             } else
177                 last = cchanuser;
178         }
179         chanuser->next_user = NULL;
180     }
181     if(remove_from_channellist) {
182         //remove it from the user's channel-list
183         last = NULL;
184         for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
185             if(cchanuser == chanuser) {
186                 if(last) 
187                     last->next_chan = chanuser->next_chan;
188                 else
189                     chanuser->user->channel = chanuser->next_chan;
190                 break;
191             } else
192                 last = cchanuser;
193         }
194         chanuser->next_chan = NULL;
195     }
196     
197     if(do_freeChanUser) {
198         freeChanUser(chanuser);
199     }
200     DESYNCHRONIZE(cache_sync);
201 }
202
203 void freeChanUser(struct ChanUser *chanuser) {
204     if(chanuser->spamnode)
205         free(chanuser->spamnode);
206     free(chanuser);
207 }
208