]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc-channel.c
1a1fd931a49693708365f1693ffcf92baed8e88f
[ngircd-alex.git] / src / ngircd / irc-channel.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
5  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6  * der GNU General Public License (GPL), wie von der Free Software Foundation
7  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: irc-channel.c,v 1.1 2002/03/03 17:15:11 alex Exp $
13  *
14  * irc-channel.c: IRC-Channel-Befehle
15  *
16  * $Log: irc-channel.c,v $
17  * Revision 1.1  2002/03/03 17:15:11  alex
18  * - Source in weitere Module fuer IRC-Befehle aufgesplitted.
19  *
20  */
21
22
23 #include <portab.h>
24 #include "global.h"
25
26 #include <imp.h>
27 #include <assert.h>
28 #include <string.h>
29
30 #include "irc.h"
31 #include "irc-write.h"
32 #include "log.h"
33 #include "messages.h"
34
35 #include <exp.h>
36 #include "irc-channel.h"
37
38
39 GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
40 {
41         CHAR *channame, *flags, *topic, modes[8];
42         BOOLEAN is_new_chan;
43         CLIENT *target;
44         CHANNEL *chan;
45
46         assert( Client != NULL );
47         assert( Req != NULL );
48
49         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
50
51         /* Falsche Anzahl Parameter? */
52         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
53
54         /* Wer ist der Absender? */
55         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
56         else target = Client;
57         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
58
59         /* Channel-Namen durchgehen */
60         channame = strtok( Req->argv[0], "," );
61         while( channame )
62         {
63                 /* wird der Channel neu angelegt? */
64                 flags = NULL;
65
66                 if( Channel_Search( channame )) is_new_chan = FALSE;
67                 else is_new_chan = TRUE;
68
69                 /* Hat ein Server Channel-User-Modes uebergeben? */
70                 if( Client_Type( Client ) == CLIENT_SERVER )
71                 {
72                         /* Channel-Flags extrahieren */
73                         flags = strchr( channame, 0x7 );
74                         if( flags ) *flags++ = '\0';
75                 }
76
77                 /* neuer Channel udn lokaler Client? */
78                 if( is_new_chan && ( Client_Type( Client ) == CLIENT_USER ))
79                 {
80                         /* Dann soll der Client Channel-Operator werden! */
81                         flags = "o";
82                 }
83
84                 /* Channel joinen (und ggf. anlegen) */
85                 if( ! Channel_Join( target, channame ))
86                 {
87                         /* naechsten Namen ermitteln */
88                         channame = strtok( NULL, "," );
89                         continue;
90                 }
91                 chan = Channel_Search( channame );
92                 assert( chan != NULL );
93
94                 /* Modes setzen (wenn vorhanden) */
95                 while( flags && *flags )
96                 {
97                         Channel_UserModeAdd( chan, target, *flags );
98                         flags++;
99                 }
100
101                 /* Muessen Modes an andere Server gemeldet werden? */
102                 strcpy( &modes[1], Channel_UserModes( chan, target ));
103                 if( modes[1] ) modes[0] = 0x7;
104                 else modes[0] = '\0';
105
106                 /* An andere Server weiterleiten */
107                 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
108
109                 /* im Channel bekannt machen */
110                 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
111                 if( modes[1] )
112                 {
113                         /* Modes im Channel bekannt machen */
114                         IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
115                 }
116
117                 if( Client_Type( Client ) == CLIENT_USER )
118                 {
119                         /* an Client bestaetigen */
120                         IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
121
122                         /* Topic an Client schicken */
123                         topic = Channel_Topic( chan );
124                         if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
125
126                         /* Mitglieder an Client Melden */
127                         IRC_Send_NAMES( Client, chan );
128                         IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
129                 }
130
131                 /* naechsten Namen ermitteln */
132                 channame = strtok( NULL, "," );
133         }
134         return CONNECTED;
135 } /* IRC_JOIN */
136
137
138 GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req )
139 {
140         CLIENT *target;
141         CHAR *chan;
142
143         assert( Client != NULL );
144         assert( Req != NULL );
145
146         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
147
148         /* Falsche Anzahl Parameter? */
149         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
150
151         /* Wer ist der Absender? */
152         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
153         else target = Client;
154         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
155
156         /* Channel-Namen durchgehen */
157         chan = strtok( Req->argv[0], "," );
158         while( chan )
159         {
160                 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
161                 {
162                         /* naechsten Namen ermitteln */
163                         chan = strtok( NULL, "," );
164                         continue;
165                 }
166
167                 /* naechsten Namen ermitteln */
168                 chan = strtok( NULL, "," );
169         }
170         return CONNECTED;
171 } /* IRC_PART */
172
173
174 GLOBAL BOOLEAN IRC_TOPIC( CLIENT *Client, REQUEST *Req )
175 {
176         CHANNEL *chan;
177         CLIENT *from;
178         CHAR *topic;
179
180         assert( Client != NULL );
181         assert( Req != NULL );
182
183         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
184
185         /* Falsche Anzahl Parameter? */
186         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
187
188         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
189         else from = Client;
190         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
191
192         /* Welcher Channel? */
193         chan = Channel_Search( Req->argv[0] );
194         if( ! chan ) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
195
196         /* Ist der User Mitglied in dem Channel? */
197         if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
198
199         if( Req->argc == 1 )
200         {
201                 /* Topic erfragen */
202                 topic = Channel_Topic( chan );
203                 if( *topic ) return IRC_WriteStrClient( from, RPL_TOPIC_MSG, Client_ID( from ), Channel_Name( chan ), topic );
204                 else return IRC_WriteStrClient( from, RPL_NOTOPIC_MSG, Client_ID( from ), Channel_Name( chan ));
205         }
206
207         if( strchr( Channel_Modes( chan ), 't' ))
208         {
209                 /* Topic Lock. Ist der User ein Channel Operator? */
210                 if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
211         }
212
213         /* Topic setzen */
214         Channel_SetTopic( chan, Req->argv[1] );
215         Log( LOG_DEBUG, "User \"%s\" set topic on \"%s\": %s", Client_Mask( from ), Channel_Name( chan ), Req->argv[1][0] ? Req->argv[1] : "<none>" );
216
217         /* im Channel bekannt machen und an Server weiterleiten */
218         IRC_WriteStrServersPrefix( Client, from, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
219         IRC_WriteStrChannelPrefix( Client, chan, from, FALSE, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
220
221         if( Client_Type( Client ) == CLIENT_USER ) return IRC_WriteStrClientPrefix( Client, Client, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
222         else return CONNECTED;
223 } /* IRC_TOPIC */
224
225
226 /* -eof- */