Blame


1 38b9cb88 2001-12-14 alex /*
2 38b9cb88 2001-12-14 alex * ngIRCd -- The Next Generation IRC Daemon
3 1547f76c 2002-01-02 alex * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4 38b9cb88 2001-12-14 alex *
5 38b9cb88 2001-12-14 alex * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6 38b9cb88 2001-12-14 alex * der GNU General Public License (GPL), wie von der Free Software Foundation
7 38b9cb88 2001-12-14 alex * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8 38b9cb88 2001-12-14 alex * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9 38b9cb88 2001-12-14 alex * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10 804b1ec4 2001-12-31 alex * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
11 38b9cb88 2001-12-14 alex *
12 0e38d10b 2002-03-25 alex * $Id: channel.c,v 1.20 2002/03/25 16:54:26 alex Exp $
13 38b9cb88 2001-12-14 alex *
14 38b9cb88 2001-12-14 alex * channel.c: Management der Channels
15 38b9cb88 2001-12-14 alex */
16 38b9cb88 2001-12-14 alex
17 38b9cb88 2001-12-14 alex
18 8a324b6d 2002-01-26 alex #define __channel_c__
19 8a324b6d 2002-01-26 alex
20 8a324b6d 2002-01-26 alex
21 ca33cbda 2002-03-12 alex #include "portab.h"
22 38b9cb88 2001-12-14 alex
23 ca33cbda 2002-03-12 alex #include "imp.h"
24 38b9cb88 2001-12-14 alex #include <assert.h>
25 bb19cfda 2002-01-21 alex #include <stdlib.h>
26 bb19cfda 2002-01-21 alex #include <string.h>
27 38b9cb88 2001-12-14 alex
28 bb19cfda 2002-01-21 alex #include "client.h"
29 0e38d10b 2002-03-25 alex #include "hash.h"
30 ff54198f 2002-02-27 alex #include "irc-write.h"
31 bb19cfda 2002-01-21 alex #include "log.h"
32 bb19cfda 2002-01-21 alex #include "messages.h"
33 bb19cfda 2002-01-21 alex
34 ca33cbda 2002-03-12 alex #include "exp.h"
35 38b9cb88 2001-12-14 alex #include "channel.h"
36 38b9cb88 2001-12-14 alex
37 38b9cb88 2001-12-14 alex
38 38b9cb88 2001-12-14 alex LOCAL CHANNEL *My_Channels;
39 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *My_Cl2Chan;
40 38b9cb88 2001-12-14 alex
41 38b9cb88 2001-12-14 alex
42 bb19cfda 2002-01-21 alex LOCAL CHANNEL *New_Chan( CHAR *Name );
43 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client );
44 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client );
45 d569c924 2002-01-27 alex LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART );
46 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan );
47 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan );
48 bb19cfda 2002-01-21 alex LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan );
49 bb19cfda 2002-01-21 alex
50 bb19cfda 2002-01-21 alex
51 38b9cb88 2001-12-14 alex GLOBAL VOID Channel_Init( VOID )
52 38b9cb88 2001-12-14 alex {
53 38b9cb88 2001-12-14 alex My_Channels = NULL;
54 bb19cfda 2002-01-21 alex My_Cl2Chan = NULL;
55 38b9cb88 2001-12-14 alex } /* Channel_Init */
56 38b9cb88 2001-12-14 alex
57 38b9cb88 2001-12-14 alex
58 38b9cb88 2001-12-14 alex GLOBAL VOID Channel_Exit( VOID )
59 38b9cb88 2001-12-14 alex {
60 bb19cfda 2002-01-21 alex CHANNEL *c, *c_next;
61 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan, *cl2chan_next;
62 bb19cfda 2002-01-21 alex
63 bb19cfda 2002-01-21 alex /* Channel-Strukturen freigeben */
64 bb19cfda 2002-01-21 alex c = My_Channels;
65 bb19cfda 2002-01-21 alex while( c )
66 bb19cfda 2002-01-21 alex {
67 bb19cfda 2002-01-21 alex c_next = c->next;
68 bb19cfda 2002-01-21 alex free( c );
69 bb19cfda 2002-01-21 alex c = c_next;
70 bb19cfda 2002-01-21 alex }
71 bb19cfda 2002-01-21 alex
72 bb19cfda 2002-01-21 alex /* Channel-Zuordnungstabelle freigeben */
73 bb19cfda 2002-01-21 alex cl2chan = My_Cl2Chan;
74 bb19cfda 2002-01-21 alex while( c )
75 bb19cfda 2002-01-21 alex {
76 bb19cfda 2002-01-21 alex cl2chan_next = cl2chan->next;
77 bb19cfda 2002-01-21 alex free( cl2chan );
78 bb19cfda 2002-01-21 alex cl2chan = cl2chan_next;
79 bb19cfda 2002-01-21 alex }
80 38b9cb88 2001-12-14 alex } /* Channel_Exit */
81 38b9cb88 2001-12-14 alex
82 38b9cb88 2001-12-14 alex
83 bb19cfda 2002-01-21 alex GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name )
84 bb19cfda 2002-01-21 alex {
85 bb19cfda 2002-01-21 alex CHANNEL *chan;
86 bb19cfda 2002-01-21 alex
87 bb19cfda 2002-01-21 alex assert( Client != NULL );
88 bb19cfda 2002-01-21 alex assert( Name != NULL );
89 bb19cfda 2002-01-21 alex
90 bb19cfda 2002-01-21 alex /* Valider Channel-Name? */
91 f53914b1 2002-02-06 alex if( ! Channel_IsValidName( Name ))
92 bb19cfda 2002-01-21 alex {
93 bb19cfda 2002-01-21 alex IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
94 bb19cfda 2002-01-21 alex return FALSE;
95 bb19cfda 2002-01-21 alex }
96 bb19cfda 2002-01-21 alex
97 bb19cfda 2002-01-21 alex /* Channel suchen */
98 8a324b6d 2002-01-26 alex chan = Channel_Search( Name );
99 bb19cfda 2002-01-21 alex if( chan )
100 bb19cfda 2002-01-21 alex {
101 bb19cfda 2002-01-21 alex /* Ist der Client bereits Mitglied? */
102 bb19cfda 2002-01-21 alex if( Get_Cl2Chan( chan, Client )) return FALSE;
103 bb19cfda 2002-01-21 alex }
104 bb19cfda 2002-01-21 alex else
105 bb19cfda 2002-01-21 alex {
106 bb19cfda 2002-01-21 alex /* Gibt es noch nicht? Dann neu anlegen: */
107 bb19cfda 2002-01-21 alex chan = New_Chan( Name );
108 bb19cfda 2002-01-21 alex if( ! chan ) return FALSE;
109 bb19cfda 2002-01-21 alex
110 bb19cfda 2002-01-21 alex /* Verketten */
111 bb19cfda 2002-01-21 alex chan->next = My_Channels;
112 bb19cfda 2002-01-21 alex My_Channels = chan;
113 bb19cfda 2002-01-21 alex }
114 bb19cfda 2002-01-21 alex
115 bb19cfda 2002-01-21 alex /* User dem Channel hinzufuegen */
116 bb19cfda 2002-01-21 alex if( ! Add_Client( chan, Client )) return FALSE;
117 bb19cfda 2002-01-21 alex else return TRUE;
118 bb19cfda 2002-01-21 alex } /* Channel_Join */
119 bb19cfda 2002-01-21 alex
120 bb19cfda 2002-01-21 alex
121 bb19cfda 2002-01-21 alex GLOBAL BOOLEAN Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason )
122 bb19cfda 2002-01-21 alex {
123 bb19cfda 2002-01-21 alex CHANNEL *chan;
124 bb19cfda 2002-01-21 alex
125 bb19cfda 2002-01-21 alex assert( Client != NULL );
126 bb19cfda 2002-01-21 alex assert( Name != NULL );
127 bb19cfda 2002-01-21 alex
128 bb19cfda 2002-01-21 alex /* Channel suchen */
129 8a324b6d 2002-01-26 alex chan = Channel_Search( Name );
130 bb19cfda 2002-01-21 alex if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client )))
131 bb19cfda 2002-01-21 alex {
132 bb19cfda 2002-01-21 alex IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
133 bb19cfda 2002-01-21 alex return FALSE;
134 bb19cfda 2002-01-21 alex }
135 bb19cfda 2002-01-21 alex
136 bb19cfda 2002-01-21 alex /* User aus Channel entfernen */
137 d569c924 2002-01-27 alex if( ! Remove_Client( chan, Client, Origin, Reason, TRUE )) return FALSE;
138 bb19cfda 2002-01-21 alex else return TRUE;
139 bb19cfda 2002-01-21 alex } /* Channel_Part */
140 bb19cfda 2002-01-21 alex
141 bb19cfda 2002-01-21 alex
142 bb19cfda 2002-01-21 alex GLOBAL VOID Channel_RemoveClient( CLIENT *Client, CHAR *Reason )
143 bb19cfda 2002-01-21 alex {
144 bb19cfda 2002-01-21 alex CHANNEL *c, *next_c;
145 bb19cfda 2002-01-21 alex
146 bb19cfda 2002-01-21 alex assert( Client != NULL );
147 bb19cfda 2002-01-21 alex
148 bb19cfda 2002-01-21 alex c = My_Channels;
149 bb19cfda 2002-01-21 alex while( c )
150 bb19cfda 2002-01-21 alex {
151 bb19cfda 2002-01-21 alex next_c = c->next;
152 d569c924 2002-01-27 alex Remove_Client( c, Client, Client_ThisServer( ), Reason, FALSE );
153 bb19cfda 2002-01-21 alex c = next_c;
154 bb19cfda 2002-01-21 alex }
155 bb19cfda 2002-01-21 alex } /* Channel_RemoveClient */
156 bb19cfda 2002-01-21 alex
157 bb19cfda 2002-01-21 alex
158 56823924 2002-01-16 alex GLOBAL INT Channel_Count( VOID )
159 56823924 2002-01-16 alex {
160 bb19cfda 2002-01-21 alex CHANNEL *c;
161 bb19cfda 2002-01-21 alex INT count;
162 bb19cfda 2002-01-21 alex
163 bb19cfda 2002-01-21 alex count = 0;
164 bb19cfda 2002-01-21 alex c = My_Channels;
165 bb19cfda 2002-01-21 alex while( c )
166 bb19cfda 2002-01-21 alex {
167 bb19cfda 2002-01-21 alex count++;
168 bb19cfda 2002-01-21 alex c = c->next;
169 bb19cfda 2002-01-21 alex }
170 bb19cfda 2002-01-21 alex return count;
171 56823924 2002-01-16 alex } /* Channel_Count */
172 56823924 2002-01-16 alex
173 56823924 2002-01-16 alex
174 71c7a6fc 2002-01-28 alex GLOBAL CHAR *Channel_Name( CHANNEL *Chan )
175 71c7a6fc 2002-01-28 alex {
176 71c7a6fc 2002-01-28 alex assert( Chan != NULL );
177 71c7a6fc 2002-01-28 alex return Chan->name;
178 71c7a6fc 2002-01-28 alex } /* Channel_Name */
179 f53914b1 2002-02-06 alex
180 f53914b1 2002-02-06 alex
181 f53914b1 2002-02-06 alex GLOBAL CHAR *Channel_Modes( CHANNEL *Chan )
182 f53914b1 2002-02-06 alex {
183 f53914b1 2002-02-06 alex assert( Chan != NULL );
184 f53914b1 2002-02-06 alex return Chan->modes;
185 f53914b1 2002-02-06 alex } /* Channel_Modes */
186 71c7a6fc 2002-01-28 alex
187 71c7a6fc 2002-01-28 alex
188 71c7a6fc 2002-01-28 alex GLOBAL CHANNEL *Channel_First( VOID )
189 71c7a6fc 2002-01-28 alex {
190 71c7a6fc 2002-01-28 alex return My_Channels;
191 71c7a6fc 2002-01-28 alex } /* Channel_First */
192 71c7a6fc 2002-01-28 alex
193 71c7a6fc 2002-01-28 alex
194 71c7a6fc 2002-01-28 alex GLOBAL CHANNEL *Channel_Next( CHANNEL *Chan )
195 71c7a6fc 2002-01-28 alex {
196 71c7a6fc 2002-01-28 alex assert( Chan != NULL );
197 71c7a6fc 2002-01-28 alex return Chan->next;
198 71c7a6fc 2002-01-28 alex } /* Channel_Next */
199 71c7a6fc 2002-01-28 alex
200 71c7a6fc 2002-01-28 alex
201 8a324b6d 2002-01-26 alex GLOBAL CHANNEL *Channel_Search( CHAR *Name )
202 bb19cfda 2002-01-21 alex {
203 bb19cfda 2002-01-21 alex /* Channel-Struktur suchen */
204 bb19cfda 2002-01-21 alex
205 bb19cfda 2002-01-21 alex CHANNEL *c;
206 0e38d10b 2002-03-25 alex UINT32 search_hash;
207 bb19cfda 2002-01-21 alex
208 bb19cfda 2002-01-21 alex assert( Name != NULL );
209 0e38d10b 2002-03-25 alex
210 0e38d10b 2002-03-25 alex search_hash = Hash( Name );
211 bb19cfda 2002-01-21 alex c = My_Channels;
212 bb19cfda 2002-01-21 alex while( c )
213 bb19cfda 2002-01-21 alex {
214 0e38d10b 2002-03-25 alex if( search_hash == c->hash )
215 0e38d10b 2002-03-25 alex {
216 0e38d10b 2002-03-25 alex /* lt. Hash-Wert: Treffer! */
217 0e38d10b 2002-03-25 alex if( strcasecmp( Name, c->name ) == 0 ) return c;
218 0e38d10b 2002-03-25 alex }
219 bb19cfda 2002-01-21 alex c = c->next;
220 bb19cfda 2002-01-21 alex }
221 bb19cfda 2002-01-21 alex return NULL;
222 8a324b6d 2002-01-26 alex } /* Channel_Search */
223 bb19cfda 2002-01-21 alex
224 bb19cfda 2002-01-21 alex
225 8a324b6d 2002-01-26 alex GLOBAL CL2CHAN *Channel_FirstMember( CHANNEL *Chan )
226 8a324b6d 2002-01-26 alex {
227 8a324b6d 2002-01-26 alex assert( Chan != NULL );
228 8a324b6d 2002-01-26 alex return Get_First_Cl2Chan( NULL, Chan );
229 0bb9db1a 2002-01-29 alex } /* Channel_FirstMember */
230 8a324b6d 2002-01-26 alex
231 8a324b6d 2002-01-26 alex
232 8a324b6d 2002-01-26 alex GLOBAL CL2CHAN *Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan )
233 8a324b6d 2002-01-26 alex {
234 8a324b6d 2002-01-26 alex assert( Chan != NULL );
235 8a324b6d 2002-01-26 alex assert( Cl2Chan != NULL );
236 8a324b6d 2002-01-26 alex return Get_Next_Cl2Chan( Cl2Chan->next, NULL, Chan );
237 8a324b6d 2002-01-26 alex } /* Channel_NextMember */
238 0bb9db1a 2002-01-29 alex
239 0bb9db1a 2002-01-29 alex
240 0bb9db1a 2002-01-29 alex GLOBAL CL2CHAN *Channel_FirstChannelOf( CLIENT *Client )
241 0bb9db1a 2002-01-29 alex {
242 0bb9db1a 2002-01-29 alex assert( Client != NULL );
243 0bb9db1a 2002-01-29 alex return Get_First_Cl2Chan( Client, NULL );
244 0bb9db1a 2002-01-29 alex } /* Channel_FirstChannelOf */
245 8a324b6d 2002-01-26 alex
246 8a324b6d 2002-01-26 alex
247 0bb9db1a 2002-01-29 alex GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan )
248 0bb9db1a 2002-01-29 alex {
249 0bb9db1a 2002-01-29 alex assert( Client != NULL );
250 0bb9db1a 2002-01-29 alex assert( Cl2Chan != NULL );
251 0bb9db1a 2002-01-29 alex return Get_Next_Cl2Chan( Cl2Chan->next, Client, NULL );
252 0bb9db1a 2002-01-29 alex } /* Channel_NextChannelOf */
253 0bb9db1a 2002-01-29 alex
254 0bb9db1a 2002-01-29 alex
255 8a324b6d 2002-01-26 alex GLOBAL CLIENT *Channel_GetClient( CL2CHAN *Cl2Chan )
256 8a324b6d 2002-01-26 alex {
257 8a324b6d 2002-01-26 alex assert( Cl2Chan != NULL );
258 8a324b6d 2002-01-26 alex return Cl2Chan->client;
259 8a324b6d 2002-01-26 alex } /* Channel_GetClient */
260 8a324b6d 2002-01-26 alex
261 8a324b6d 2002-01-26 alex
262 8a324b6d 2002-01-26 alex GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan )
263 8a324b6d 2002-01-26 alex {
264 8a324b6d 2002-01-26 alex assert( Cl2Chan != NULL );
265 8a324b6d 2002-01-26 alex return Cl2Chan->channel;
266 8a324b6d 2002-01-26 alex } /* Channel_GetChannel */
267 8a324b6d 2002-01-26 alex
268 8a324b6d 2002-01-26 alex
269 f53914b1 2002-02-06 alex GLOBAL BOOLEAN Channel_IsValidName( CHAR *Name )
270 f53914b1 2002-02-06 alex {
271 f53914b1 2002-02-06 alex /* PrŸfen, ob Name als Channelname gueltig */
272 7157d936 2002-03-02 alex
273 7157d936 2002-03-02 alex CHAR *ptr, badchars[] = " ,:\x07";
274 f53914b1 2002-02-06 alex
275 f53914b1 2002-02-06 alex assert( Name != NULL );
276 f53914b1 2002-02-06 alex
277 f53914b1 2002-02-06 alex if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return FALSE;
278 7157d936 2002-03-02 alex
279 7157d936 2002-03-02 alex ptr = Name;
280 7157d936 2002-03-02 alex while( *ptr )
281 7157d936 2002-03-02 alex {
282 7157d936 2002-03-02 alex if( strchr( badchars, *ptr )) return FALSE;
283 7157d936 2002-03-02 alex ptr++;
284 7157d936 2002-03-02 alex }
285 7157d936 2002-03-02 alex
286 f53914b1 2002-02-06 alex return TRUE;
287 f53914b1 2002-02-06 alex } /* Channel_IsValidName */
288 f53914b1 2002-02-06 alex
289 f53914b1 2002-02-06 alex
290 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_ModeAdd( CHANNEL *Chan, CHAR Mode )
291 d72c55a0 2002-02-11 alex {
292 d72c55a0 2002-02-11 alex /* Mode soll gesetzt werden. TRUE wird geliefert, wenn der
293 d72c55a0 2002-02-11 alex * Mode neu gesetzt wurde, FALSE, wenn der Channel den Mode
294 d72c55a0 2002-02-11 alex * bereits hatte. */
295 d72c55a0 2002-02-11 alex
296 d72c55a0 2002-02-11 alex CHAR x[2];
297 d72c55a0 2002-02-11 alex
298 d72c55a0 2002-02-11 alex assert( Chan != NULL );
299 d72c55a0 2002-02-11 alex
300 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
301 d72c55a0 2002-02-11 alex if( ! strchr( Chan->modes, x[0] ))
302 d72c55a0 2002-02-11 alex {
303 d72c55a0 2002-02-11 alex /* Client hat den Mode noch nicht -> setzen */
304 d72c55a0 2002-02-11 alex strcat( Chan->modes, x );
305 d72c55a0 2002-02-11 alex return TRUE;
306 d72c55a0 2002-02-11 alex }
307 d72c55a0 2002-02-11 alex else return FALSE;
308 d72c55a0 2002-02-11 alex } /* Channel_ModeAdd */
309 d72c55a0 2002-02-11 alex
310 d72c55a0 2002-02-11 alex
311 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_ModeDel( CHANNEL *Chan, CHAR Mode )
312 d72c55a0 2002-02-11 alex {
313 d72c55a0 2002-02-11 alex /* Mode soll geloescht werden. TRUE wird geliefert, wenn der
314 d72c55a0 2002-02-11 alex * Mode entfernt wurde, FALSE, wenn der Channel den Mode
315 d72c55a0 2002-02-11 alex * ueberhaupt nicht hatte. */
316 d72c55a0 2002-02-11 alex
317 d72c55a0 2002-02-11 alex CHAR x[2], *p;
318 d72c55a0 2002-02-11 alex
319 d72c55a0 2002-02-11 alex assert( Chan != NULL );
320 d72c55a0 2002-02-11 alex
321 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
322 d72c55a0 2002-02-11 alex
323 d72c55a0 2002-02-11 alex p = strchr( Chan->modes, x[0] );
324 d72c55a0 2002-02-11 alex if( ! p ) return FALSE;
325 d72c55a0 2002-02-11 alex
326 d72c55a0 2002-02-11 alex /* Client hat den Mode -> loeschen */
327 d72c55a0 2002-02-11 alex while( *p )
328 d72c55a0 2002-02-11 alex {
329 d72c55a0 2002-02-11 alex *p = *(p + 1);
330 d72c55a0 2002-02-11 alex p++;
331 d72c55a0 2002-02-11 alex }
332 d72c55a0 2002-02-11 alex return TRUE;
333 d72c55a0 2002-02-11 alex } /* Channel_ModeDel */
334 d72c55a0 2002-02-11 alex
335 d72c55a0 2002-02-11 alex
336 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode )
337 d72c55a0 2002-02-11 alex {
338 d72c55a0 2002-02-11 alex /* Channel-User-Mode soll gesetzt werden. TRUE wird geliefert,
339 d72c55a0 2002-02-11 alex * wenn der Mode neu gesetzt wurde, FALSE, wenn der User den
340 d72c55a0 2002-02-11 alex * Channel-Mode bereits hatte. */
341 d72c55a0 2002-02-11 alex
342 d72c55a0 2002-02-11 alex CL2CHAN *cl2chan;
343 d72c55a0 2002-02-11 alex CHAR x[2];
344 d72c55a0 2002-02-11 alex
345 d72c55a0 2002-02-11 alex assert( Chan != NULL );
346 d72c55a0 2002-02-11 alex assert( Client != NULL );
347 d72c55a0 2002-02-11 alex
348 d72c55a0 2002-02-11 alex cl2chan = Get_Cl2Chan( Chan, Client );
349 d72c55a0 2002-02-11 alex assert( cl2chan != NULL );
350 d72c55a0 2002-02-11 alex
351 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
352 d72c55a0 2002-02-11 alex if( ! strchr( cl2chan->modes, x[0] ))
353 d72c55a0 2002-02-11 alex {
354 d72c55a0 2002-02-11 alex /* Client hat den Mode noch nicht -> setzen */
355 d72c55a0 2002-02-11 alex strcat( cl2chan->modes, x );
356 d72c55a0 2002-02-11 alex return TRUE;
357 d72c55a0 2002-02-11 alex }
358 d72c55a0 2002-02-11 alex else return FALSE;
359 d72c55a0 2002-02-11 alex } /* Channel_UserModeAdd */
360 d72c55a0 2002-02-11 alex
361 d72c55a0 2002-02-11 alex
362 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode )
363 d72c55a0 2002-02-11 alex {
364 d72c55a0 2002-02-11 alex /* Channel-User-Mode soll geloescht werden. TRUE wird geliefert,
365 d72c55a0 2002-02-11 alex * wenn der Mode entfernt wurde, FALSE, wenn der User den Channel-Mode
366 d72c55a0 2002-02-11 alex * ueberhaupt nicht hatte. */
367 d72c55a0 2002-02-11 alex
368 d72c55a0 2002-02-11 alex CL2CHAN *cl2chan;
369 d72c55a0 2002-02-11 alex CHAR x[2], *p;
370 d72c55a0 2002-02-11 alex
371 d72c55a0 2002-02-11 alex assert( Chan != NULL );
372 d72c55a0 2002-02-11 alex assert( Client != NULL );
373 d72c55a0 2002-02-11 alex
374 d72c55a0 2002-02-11 alex cl2chan = Get_Cl2Chan( Chan, Client );
375 d72c55a0 2002-02-11 alex assert( cl2chan != NULL );
376 d72c55a0 2002-02-11 alex
377 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
378 d72c55a0 2002-02-11 alex
379 d72c55a0 2002-02-11 alex p = strchr( cl2chan->modes, x[0] );
380 d72c55a0 2002-02-11 alex if( ! p ) return FALSE;
381 d72c55a0 2002-02-11 alex
382 d72c55a0 2002-02-11 alex /* Client hat den Mode -> loeschen */
383 d72c55a0 2002-02-11 alex while( *p )
384 d72c55a0 2002-02-11 alex {
385 d72c55a0 2002-02-11 alex *p = *(p + 1);
386 d72c55a0 2002-02-11 alex p++;
387 d72c55a0 2002-02-11 alex }
388 d72c55a0 2002-02-11 alex return TRUE;
389 d72c55a0 2002-02-11 alex } /* Channel_UserModeDel */
390 d72c55a0 2002-02-11 alex
391 d72c55a0 2002-02-11 alex
392 d72c55a0 2002-02-11 alex GLOBAL CHAR *Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
393 d72c55a0 2002-02-11 alex {
394 d72c55a0 2002-02-11 alex /* Channel-Modes eines Users liefern */
395 d72c55a0 2002-02-11 alex
396 d72c55a0 2002-02-11 alex CL2CHAN *cl2chan;
397 d72c55a0 2002-02-11 alex
398 d72c55a0 2002-02-11 alex assert( Chan != NULL );
399 d72c55a0 2002-02-11 alex assert( Client != NULL );
400 d72c55a0 2002-02-11 alex
401 d72c55a0 2002-02-11 alex cl2chan = Get_Cl2Chan( Chan, Client );
402 d72c55a0 2002-02-11 alex assert( cl2chan != NULL );
403 d72c55a0 2002-02-11 alex
404 d72c55a0 2002-02-11 alex return cl2chan->modes;
405 d72c55a0 2002-02-11 alex } /* Channel_UserModes */
406 d72c55a0 2002-02-11 alex
407 d72c55a0 2002-02-11 alex
408 153aa0aa 2002-02-27 alex GLOBAL BOOLEAN Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
409 153aa0aa 2002-02-27 alex {
410 153aa0aa 2002-02-27 alex /* Pruefen, ob Client Mitglied in Channel ist */
411 153aa0aa 2002-02-27 alex
412 153aa0aa 2002-02-27 alex assert( Chan != NULL );
413 153aa0aa 2002-02-27 alex assert( Client != NULL );
414 153aa0aa 2002-02-27 alex
415 153aa0aa 2002-02-27 alex if( Get_Cl2Chan( Chan, Client )) return TRUE;
416 153aa0aa 2002-02-27 alex else return FALSE;
417 153aa0aa 2002-02-27 alex } /* Channel_IsMemberOf */
418 153aa0aa 2002-02-27 alex
419 153aa0aa 2002-02-27 alex
420 52548bd3 2002-02-27 alex GLOBAL CHAR *Channel_Topic( CHANNEL *Chan )
421 52548bd3 2002-02-27 alex {
422 52548bd3 2002-02-27 alex assert( Chan != NULL );
423 52548bd3 2002-02-27 alex return Chan->topic;
424 52548bd3 2002-02-27 alex } /* Channel_Topic */
425 52548bd3 2002-02-27 alex
426 52548bd3 2002-02-27 alex
427 52548bd3 2002-02-27 alex GLOBAL VOID Channel_SetTopic( CHANNEL *Chan, CHAR *Topic )
428 52548bd3 2002-02-27 alex {
429 52548bd3 2002-02-27 alex assert( Chan != NULL );
430 52548bd3 2002-02-27 alex assert( Topic != NULL );
431 52548bd3 2002-02-27 alex
432 10363b39 2002-03-03 alex strncpy( Chan->topic, Topic, CHANNEL_TOPIC_LEN - 1 );
433 52548bd3 2002-02-27 alex Chan->topic[CHANNEL_TOPIC_LEN - 1] = '\0';
434 52548bd3 2002-02-27 alex } /* Channel_SetTopic */
435 0e38d10b 2002-03-25 alex
436 0e38d10b 2002-03-25 alex
437 0e38d10b 2002-03-25 alex GLOBAL BOOLEAN Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text )
438 0e38d10b 2002-03-25 alex {
439 0e38d10b 2002-03-25 alex BOOLEAN is_member, has_voice, is_op, ok;
440 0e38d10b 2002-03-25 alex
441 0e38d10b 2002-03-25 alex /* Okay, Ziel ist ein Channel */
442 0e38d10b 2002-03-25 alex is_member = has_voice = is_op = FALSE;
443 0e38d10b 2002-03-25 alex if( Channel_IsMemberOf( Chan, From ))
444 0e38d10b 2002-03-25 alex {
445 0e38d10b 2002-03-25 alex is_member = TRUE;
446 0e38d10b 2002-03-25 alex if( strchr( Channel_UserModes( Chan, From ), 'v' )) has_voice = TRUE;
447 0e38d10b 2002-03-25 alex if( strchr( Channel_UserModes( Chan, From ), 'o' )) is_op = TRUE;
448 0e38d10b 2002-03-25 alex }
449 52548bd3 2002-02-27 alex
450 0e38d10b 2002-03-25 alex /* pruefen, ob Client in Channel schreiben darf */
451 0e38d10b 2002-03-25 alex ok = TRUE;
452 0e38d10b 2002-03-25 alex if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = FALSE;
453 0e38d10b 2002-03-25 alex if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = FALSE;
454 52548bd3 2002-02-27 alex
455 0e38d10b 2002-03-25 alex if( ! ok ) return IRC_WriteStrClient( From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( From ), Channel_Name( Chan ));
456 0e38d10b 2002-03-25 alex
457 0e38d10b 2002-03-25 alex /* Text senden */
458 0e38d10b 2002-03-25 alex if( Client_Conn( From ) > NONE ) Conn_UpdateIdle( Client_Conn( From ));
459 0e38d10b 2002-03-25 alex return IRC_WriteStrChannelPrefix( Client, Chan, From, TRUE, "PRIVMSG %s :%s", Channel_Name( Chan ), Text );
460 0e38d10b 2002-03-25 alex } /* Channel_Write */
461 0e38d10b 2002-03-25 alex
462 0e38d10b 2002-03-25 alex
463 0e38d10b 2002-03-25 alex
464 bb19cfda 2002-01-21 alex LOCAL CHANNEL *New_Chan( CHAR *Name )
465 bb19cfda 2002-01-21 alex {
466 bb19cfda 2002-01-21 alex /* Neue Channel-Struktur anlegen */
467 0e38d10b 2002-03-25 alex
468 bb19cfda 2002-01-21 alex CHANNEL *c;
469 bb19cfda 2002-01-21 alex
470 bb19cfda 2002-01-21 alex assert( Name != NULL );
471 bb19cfda 2002-01-21 alex
472 bb19cfda 2002-01-21 alex c = malloc( sizeof( CHANNEL ));
473 bb19cfda 2002-01-21 alex if( ! c )
474 bb19cfda 2002-01-21 alex {
475 bb19cfda 2002-01-21 alex Log( LOG_EMERG, "Can't allocate memory!" );
476 bb19cfda 2002-01-21 alex return NULL;
477 bb19cfda 2002-01-21 alex }
478 bb19cfda 2002-01-21 alex c->next = NULL;
479 10363b39 2002-03-03 alex strncpy( c->name, Name, CHANNEL_NAME_LEN - 1 );
480 bb19cfda 2002-01-21 alex c->name[CHANNEL_NAME_LEN - 1] = '\0';
481 bb19cfda 2002-01-21 alex strcpy( c->modes, "" );
482 52548bd3 2002-02-27 alex strcpy( c->topic, "" );
483 0e38d10b 2002-03-25 alex c->hash = Hash( c->name );
484 bb19cfda 2002-01-21 alex
485 bb19cfda 2002-01-21 alex Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name );
486 bb19cfda 2002-01-21 alex
487 bb19cfda 2002-01-21 alex return c;
488 bb19cfda 2002-01-21 alex } /* New_Chan */
489 bb19cfda 2002-01-21 alex
490 bb19cfda 2002-01-21 alex
491 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
492 bb19cfda 2002-01-21 alex {
493 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan;
494 bb19cfda 2002-01-21 alex
495 bb19cfda 2002-01-21 alex assert( Chan != NULL );
496 bb19cfda 2002-01-21 alex assert( Client != NULL );
497 bb19cfda 2002-01-21 alex
498 bb19cfda 2002-01-21 alex cl2chan = My_Cl2Chan;
499 bb19cfda 2002-01-21 alex while( cl2chan )
500 bb19cfda 2002-01-21 alex {
501 bb19cfda 2002-01-21 alex if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) return cl2chan;
502 bb19cfda 2002-01-21 alex cl2chan = cl2chan->next;
503 bb19cfda 2002-01-21 alex }
504 bb19cfda 2002-01-21 alex return NULL;
505 bb19cfda 2002-01-21 alex } /* Get_Cl2Chan */
506 bb19cfda 2002-01-21 alex
507 bb19cfda 2002-01-21 alex
508 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client )
509 bb19cfda 2002-01-21 alex {
510 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan;
511 bb19cfda 2002-01-21 alex
512 bb19cfda 2002-01-21 alex assert( Chan != NULL );
513 bb19cfda 2002-01-21 alex assert( Client != NULL );
514 bb19cfda 2002-01-21 alex
515 d72c55a0 2002-02-11 alex /* neue CL2CHAN-Struktur anlegen */
516 bb19cfda 2002-01-21 alex cl2chan = malloc( sizeof( CL2CHAN ));
517 bb19cfda 2002-01-21 alex if( ! cl2chan )
518 bb19cfda 2002-01-21 alex {
519 bb19cfda 2002-01-21 alex Log( LOG_EMERG, "Can't allocate memory!" );
520 bb19cfda 2002-01-21 alex return NULL;
521 bb19cfda 2002-01-21 alex }
522 bb19cfda 2002-01-21 alex cl2chan->channel = Chan;
523 bb19cfda 2002-01-21 alex cl2chan->client = Client;
524 d72c55a0 2002-02-11 alex strcpy( cl2chan->modes, "" );
525 bb19cfda 2002-01-21 alex
526 bb19cfda 2002-01-21 alex /* Verketten */
527 bb19cfda 2002-01-21 alex cl2chan->next = My_Cl2Chan;
528 bb19cfda 2002-01-21 alex My_Cl2Chan = cl2chan;
529 d569c924 2002-01-27 alex
530 d569c924 2002-01-27 alex Log( LOG_DEBUG, "User \"%s\" joined channel \"%s\".", Client_Mask( Client ), Chan->name );
531 d569c924 2002-01-27 alex
532 bb19cfda 2002-01-21 alex return cl2chan;
533 bb19cfda 2002-01-21 alex } /* Add_Client */
534 bb19cfda 2002-01-21 alex
535 bb19cfda 2002-01-21 alex
536 d569c924 2002-01-27 alex LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART )
537 bb19cfda 2002-01-21 alex {
538 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan, *last_cl2chan;
539 bb19cfda 2002-01-21 alex CHANNEL *c;
540 bb19cfda 2002-01-21 alex
541 bb19cfda 2002-01-21 alex assert( Chan != NULL );
542 bb19cfda 2002-01-21 alex assert( Client != NULL );
543 bb19cfda 2002-01-21 alex assert( Origin != NULL );
544 bb19cfda 2002-01-21 alex assert( Reason != NULL );
545 bb19cfda 2002-01-21 alex
546 bb19cfda 2002-01-21 alex last_cl2chan = NULL;
547 bb19cfda 2002-01-21 alex cl2chan = My_Cl2Chan;
548 bb19cfda 2002-01-21 alex while( cl2chan )
549 bb19cfda 2002-01-21 alex {
550 bb19cfda 2002-01-21 alex if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) break;
551 bb19cfda 2002-01-21 alex last_cl2chan = cl2chan;
552 bb19cfda 2002-01-21 alex cl2chan = cl2chan->next;
553 bb19cfda 2002-01-21 alex }
554 bb19cfda 2002-01-21 alex if( ! cl2chan ) return FALSE;
555 bb19cfda 2002-01-21 alex
556 bb19cfda 2002-01-21 alex c = cl2chan->channel;
557 bb19cfda 2002-01-21 alex assert( c != NULL );
558 bb19cfda 2002-01-21 alex
559 bb19cfda 2002-01-21 alex /* Aus Verkettung loesen und freigeben */
560 bb19cfda 2002-01-21 alex if( last_cl2chan ) last_cl2chan->next = cl2chan->next;
561 bb19cfda 2002-01-21 alex else My_Cl2Chan = cl2chan->next;
562 bb19cfda 2002-01-21 alex free( cl2chan );
563 bb19cfda 2002-01-21 alex
564 b5ee4552 2002-01-27 alex if( ServerPART ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
565 d569c924 2002-01-27 alex IRC_WriteStrChannelPrefix( Origin, c, Client, FALSE, "PART %s :%s", c->name, Reason );
566 6491b984 2002-01-27 alex if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
567 bb19cfda 2002-01-21 alex
568 bb19cfda 2002-01-21 alex Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
569 bb19cfda 2002-01-21 alex
570 bb19cfda 2002-01-21 alex /* Wenn Channel nun leer: loeschen */
571 bb19cfda 2002-01-21 alex if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
572 bb19cfda 2002-01-21 alex
573 bb19cfda 2002-01-21 alex return TRUE;
574 bb19cfda 2002-01-21 alex } /* Remove_Client */
575 bb19cfda 2002-01-21 alex
576 bb19cfda 2002-01-21 alex
577 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
578 bb19cfda 2002-01-21 alex {
579 bb19cfda 2002-01-21 alex return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
580 bb19cfda 2002-01-21 alex } /* Get_First_Cl2Chan */
581 bb19cfda 2002-01-21 alex
582 bb19cfda 2002-01-21 alex
583 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
584 bb19cfda 2002-01-21 alex {
585 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan;
586 bb19cfda 2002-01-21 alex
587 bb19cfda 2002-01-21 alex assert( Client != NULL || Channel != NULL );
588 bb19cfda 2002-01-21 alex
589 bb19cfda 2002-01-21 alex cl2chan = Start;
590 bb19cfda 2002-01-21 alex while( cl2chan )
591 bb19cfda 2002-01-21 alex {
592 bb19cfda 2002-01-21 alex if(( Client ) && ( cl2chan->client == Client )) return cl2chan;
593 bb19cfda 2002-01-21 alex if(( Channel ) && ( cl2chan->channel == Channel )) return cl2chan;
594 bb19cfda 2002-01-21 alex cl2chan = cl2chan->next;
595 bb19cfda 2002-01-21 alex }
596 bb19cfda 2002-01-21 alex return NULL;
597 bb19cfda 2002-01-21 alex } /* Get_Next_Cl2Chan */
598 bb19cfda 2002-01-21 alex
599 bb19cfda 2002-01-21 alex
600 bb19cfda 2002-01-21 alex LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan )
601 bb19cfda 2002-01-21 alex {
602 bb19cfda 2002-01-21 alex /* Channel-Struktur loeschen */
603 bb19cfda 2002-01-21 alex
604 bb19cfda 2002-01-21 alex CHANNEL *chan, *last_chan;
605 bb19cfda 2002-01-21 alex
606 bb19cfda 2002-01-21 alex last_chan = NULL;
607 bb19cfda 2002-01-21 alex chan = My_Channels;
608 bb19cfda 2002-01-21 alex while( chan )
609 bb19cfda 2002-01-21 alex {
610 bb19cfda 2002-01-21 alex if( chan == Chan ) break;
611 bb19cfda 2002-01-21 alex last_chan = chan;
612 bb19cfda 2002-01-21 alex chan = chan->next;
613 bb19cfda 2002-01-21 alex }
614 bb19cfda 2002-01-21 alex if( ! chan ) return FALSE;
615 bb19cfda 2002-01-21 alex
616 bb19cfda 2002-01-21 alex Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
617 bb19cfda 2002-01-21 alex
618 bb19cfda 2002-01-21 alex /* Neu verketten und freigeben */
619 bb19cfda 2002-01-21 alex if( last_chan ) last_chan->next = chan->next;
620 bb19cfda 2002-01-21 alex else My_Channels = chan->next;
621 bb19cfda 2002-01-21 alex free( chan );
622 bb19cfda 2002-01-21 alex
623 bb19cfda 2002-01-21 alex return TRUE;
624 bb19cfda 2002-01-21 alex } /* Delete_Channel */
625 bb19cfda 2002-01-21 alex
626 bb19cfda 2002-01-21 alex
627 38b9cb88 2001-12-14 alex /* -eof- */