X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fchannel.c;h=9e1820f01b8ff4753da9c130ca1cec8276216718;hp=c4231dc9ebf70cb31840cde0b87adb82357e1452;hb=490f28ffd1b42ee2076ce89c62d0e672ee7e541e;hpb=040f5422f2c8262ab19832f1e9d0e269afad8ec1 diff --git a/src/ngircd/channel.c b/src/ngircd/channel.c index c4231dc9..9e1820f0 100644 --- a/src/ngircd/channel.c +++ b/src/ngircd/channel.c @@ -2,16 +2,13 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: channel.c,v 1.22 2002/05/21 00:10:16 alex Exp $ - * - * channel.c: Management der Channels + * Channel management */ @@ -20,49 +17,69 @@ #include "portab.h" +static char UNUSED id[] = "$Id: channel.c,v 1.35 2002/12/12 12:24:18 alex Exp $"; + #include "imp.h" #include #include #include +#include "conn.h" #include "client.h" + +#include "exp.h" +#include "channel.h" + +#include "imp.h" +#include "irc-write.h" +#include "resolve.h" #include "conf.h" #include "hash.h" -#include "irc-write.h" +#include "lists.h" #include "log.h" #include "messages.h" #include "exp.h" -#include "channel.h" + + +#define REMOVE_PART 0 +#define REMOVE_QUIT 1 +#define REMOVE_KICK 2 LOCAL CHANNEL *My_Channels; LOCAL CL2CHAN *My_Cl2Chan; -LOCAL CHANNEL *New_Chan( CHAR *Name ); -LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client ); -LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client ); -LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART ); -LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan ); -LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ); -LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan ); +LOCAL CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client )); +LOCAL CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client )); +LOCAL BOOLEAN Remove_Client PARAMS(( INT Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN InformServer )); +LOCAL CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan )); +LOCAL CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan )); +LOCAL BOOLEAN Delete_Channel PARAMS(( CHANNEL *Chan )); -GLOBAL VOID Channel_Init( VOID ) +GLOBAL VOID +Channel_Init( VOID ) { - CHANNEL *chan; - CHAR *c; - INT i; - My_Channels = NULL; My_Cl2Chan = NULL; +} /* Channel_Init */ + +GLOBAL VOID +Channel_InitPredefined( VOID ) +{ /* Vordefinierte persistente Channels erzeugen */ + + CHANNEL *chan; + CHAR *c; + INT i; + for( i = 0; i < Conf_Channel_Count; i++ ) { /* Ist ein Name konfiguriert? */ - if( ! Conf_Channel[i].name ) continue; + if( ! Conf_Channel[i].name[0] ) continue; /* Gueltiger Channel-Name? */ if( ! Channel_IsValidName( Conf_Channel[i].name )) @@ -70,14 +87,19 @@ GLOBAL VOID Channel_Init( VOID ) Log( LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"!", Conf_Channel[i].name ); continue; } + + /* Gibt es den Channel bereits? */ + chan = Channel_Search( Conf_Channel[i].name ); + if( chan ) + { + Log( LOG_INFO, "Can't create pre-defined channel \"%s\": name already in use.", Conf_Channel[i].name ); + continue; + } /* Channel anlegen */ - chan = New_Chan( Conf_Channel[i].name ); + chan = Channel_Create( Conf_Channel[i].name ); if( chan ) { - /* Verketten */ - chan->next = My_Channels; - My_Channels = chan; Channel_ModeAdd( chan, 'P' ); Channel_SetTopic( chan, Conf_Channel[i].topic ); c = Conf_Channel[i].modes; @@ -86,10 +108,11 @@ GLOBAL VOID Channel_Init( VOID ) } else Log( LOG_ERR, "Can't create pre-defined channel \"%s\"!", Conf_Channel[i].name ); } -} /* Channel_Init */ +} /* Channel_InitPredefined */ -GLOBAL VOID Channel_Exit( VOID ) +GLOBAL VOID +Channel_Exit( VOID ) { CHANNEL *c, *c_next; CL2CHAN *cl2chan, *cl2chan_next; @@ -114,7 +137,8 @@ GLOBAL VOID Channel_Exit( VOID ) } /* Channel_Exit */ -GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name ) +GLOBAL BOOLEAN +Channel_Join( CLIENT *Client, CHAR *Name ) { CHANNEL *chan; @@ -138,12 +162,8 @@ GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name ) else { /* Gibt es noch nicht? Dann neu anlegen: */ - chan = New_Chan( Name ); + chan = Channel_Create( Name ); if( ! chan ) return FALSE; - - /* Verketten */ - chan->next = My_Channels; - My_Channels = chan; } /* User dem Channel hinzufuegen */ @@ -152,12 +172,14 @@ GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name ) } /* Channel_Join */ -GLOBAL BOOLEAN Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason ) +GLOBAL BOOLEAN +Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason ) { CHANNEL *chan; assert( Client != NULL ); assert( Name != NULL ); + assert( Reason != NULL ); /* Channel suchen */ chan = Channel_Search( Name ); @@ -168,31 +190,77 @@ GLOBAL BOOLEAN Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *R } /* User aus Channel entfernen */ - if( ! Remove_Client( chan, Client, Origin, Reason, TRUE )) return FALSE; + if( ! Remove_Client( REMOVE_PART, chan, Client, Origin, Reason, TRUE )) return FALSE; else return TRUE; } /* Channel_Part */ -GLOBAL VOID Channel_RemoveClient( CLIENT *Client, CHAR *Reason ) +GLOBAL VOID +Channel_Kick( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason ) +{ + CHANNEL *chan; + + assert( Client != NULL ); + assert( Origin != NULL ); + assert( Name != NULL ); + assert( Reason != NULL ); + + /* Channel suchen */ + chan = Channel_Search( Name ); + if( ! chan ) + { + IRC_WriteStrClient( Origin, ERR_NOSUCHCHANNEL_MSG, Client_ID( Origin ), Name ); + return; + } + + /* Ist der User Mitglied in dem Channel? */ + if( ! Channel_IsMemberOf( chan, Origin )) + { + IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Name ); + return; + } + + /* Ist der User Channel-Operator? */ + if( ! strchr( Channel_UserModes( chan, Origin ), 'o' )) + { + IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Name); + return; + } + + /* Ist der Ziel-User Mitglied im Channel? */ + if( ! Channel_IsMemberOf( chan, Client )) + { + IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( Client ), Name ); + return; + } + + Remove_Client( REMOVE_KICK, chan, Client, Origin, Reason, TRUE ); +} /* Channel_Kick */ + + +GLOBAL VOID +Channel_Quit( CLIENT *Client, CHAR *Reason ) { CHANNEL *c, *next_c; assert( Client != NULL ); + assert( Reason != NULL ); c = My_Channels; while( c ) { next_c = c->next; - Remove_Client( c, Client, Client_ThisServer( ), Reason, FALSE ); + Remove_Client( REMOVE_QUIT, c, Client, Client, Reason, FALSE ); c = next_c; } -} /* Channel_RemoveClient */ +} /* Channel_Quit */ -GLOBAL INT Channel_Count( VOID ) +GLOBAL LONG +Channel_Count( VOID ) { CHANNEL *c; - INT count; + LONG count; count = 0; c = My_Channels; @@ -205,10 +273,11 @@ GLOBAL INT Channel_Count( VOID ) } /* Channel_Count */ -GLOBAL INT Channel_MemberCount( CHANNEL *Chan ) +GLOBAL LONG +Channel_MemberCount( CHANNEL *Chan ) { CL2CHAN *cl2chan; - INT count; + LONG count; assert( Chan != NULL ); @@ -223,34 +292,39 @@ GLOBAL INT Channel_MemberCount( CHANNEL *Chan ) } /* Channel_MemberCount */ -GLOBAL CHAR *Channel_Name( CHANNEL *Chan ) +GLOBAL CHAR * +Channel_Name( CHANNEL *Chan ) { assert( Chan != NULL ); return Chan->name; } /* Channel_Name */ -GLOBAL CHAR *Channel_Modes( CHANNEL *Chan ) +GLOBAL CHAR * +Channel_Modes( CHANNEL *Chan ) { assert( Chan != NULL ); return Chan->modes; } /* Channel_Modes */ -GLOBAL CHANNEL *Channel_First( VOID ) +GLOBAL CHANNEL * +Channel_First( VOID ) { return My_Channels; } /* Channel_First */ -GLOBAL CHANNEL *Channel_Next( CHANNEL *Chan ) +GLOBAL CHANNEL * +Channel_Next( CHANNEL *Chan ) { assert( Chan != NULL ); return Chan->next; } /* Channel_Next */ -GLOBAL CHANNEL *Channel_Search( CHAR *Name ) +GLOBAL CHANNEL * +Channel_Search( CHAR *Name ) { /* Channel-Struktur suchen */ @@ -274,14 +348,16 @@ GLOBAL CHANNEL *Channel_Search( CHAR *Name ) } /* Channel_Search */ -GLOBAL CL2CHAN *Channel_FirstMember( CHANNEL *Chan ) +GLOBAL CL2CHAN * +Channel_FirstMember( CHANNEL *Chan ) { assert( Chan != NULL ); return Get_First_Cl2Chan( NULL, Chan ); } /* Channel_FirstMember */ -GLOBAL CL2CHAN *Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan ) +GLOBAL CL2CHAN * +Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan ) { assert( Chan != NULL ); assert( Cl2Chan != NULL ); @@ -289,14 +365,16 @@ GLOBAL CL2CHAN *Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan ) } /* Channel_NextMember */ -GLOBAL CL2CHAN *Channel_FirstChannelOf( CLIENT *Client ) +GLOBAL CL2CHAN * +Channel_FirstChannelOf( CLIENT *Client ) { assert( Client != NULL ); return Get_First_Cl2Chan( Client, NULL ); } /* Channel_FirstChannelOf */ -GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan ) +GLOBAL CL2CHAN * +Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan ) { assert( Client != NULL ); assert( Cl2Chan != NULL ); @@ -304,31 +382,35 @@ GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan ) } /* Channel_NextChannelOf */ -GLOBAL CLIENT *Channel_GetClient( CL2CHAN *Cl2Chan ) +GLOBAL CLIENT * +Channel_GetClient( CL2CHAN *Cl2Chan ) { assert( Cl2Chan != NULL ); return Cl2Chan->client; } /* Channel_GetClient */ -GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan ) +GLOBAL CHANNEL * +Channel_GetChannel( CL2CHAN *Cl2Chan ) { assert( Cl2Chan != NULL ); return Cl2Chan->channel; } /* Channel_GetChannel */ -GLOBAL BOOLEAN Channel_IsValidName( CHAR *Name ) +GLOBAL BOOLEAN +Channel_IsValidName( CHAR *Name ) { - /* PrŸfen, ob Name als Channelname gueltig */ + /* Pruefen, ob Name als Channelname gueltig */ - CHAR *ptr, badchars[] = " ,:\x07"; + CHAR *ptr, badchars[10]; assert( Name != NULL ); if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return FALSE; ptr = Name; + strcpy( badchars, " ,:\x07" ); while( *ptr ) { if( strchr( badchars, *ptr )) return FALSE; @@ -339,7 +421,8 @@ GLOBAL BOOLEAN Channel_IsValidName( CHAR *Name ) } /* Channel_IsValidName */ -GLOBAL BOOLEAN Channel_ModeAdd( CHANNEL *Chan, CHAR Mode ) +GLOBAL BOOLEAN +Channel_ModeAdd( CHANNEL *Chan, CHAR Mode ) { /* Mode soll gesetzt werden. TRUE wird geliefert, wenn der * Mode neu gesetzt wurde, FALSE, wenn der Channel den Mode @@ -360,7 +443,8 @@ GLOBAL BOOLEAN Channel_ModeAdd( CHANNEL *Chan, CHAR Mode ) } /* Channel_ModeAdd */ -GLOBAL BOOLEAN Channel_ModeDel( CHANNEL *Chan, CHAR Mode ) +GLOBAL BOOLEAN +Channel_ModeDel( CHANNEL *Chan, CHAR Mode ) { /* Mode soll geloescht werden. TRUE wird geliefert, wenn der * Mode entfernt wurde, FALSE, wenn der Channel den Mode @@ -385,7 +469,8 @@ GLOBAL BOOLEAN Channel_ModeDel( CHANNEL *Chan, CHAR Mode ) } /* Channel_ModeDel */ -GLOBAL BOOLEAN Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode ) +GLOBAL BOOLEAN +Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode ) { /* Channel-User-Mode soll gesetzt werden. TRUE wird geliefert, * wenn der Mode neu gesetzt wurde, FALSE, wenn der User den @@ -411,7 +496,8 @@ GLOBAL BOOLEAN Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode ) } /* Channel_UserModeAdd */ -GLOBAL BOOLEAN Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode ) +GLOBAL BOOLEAN +Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode ) { /* Channel-User-Mode soll geloescht werden. TRUE wird geliefert, * wenn der Mode entfernt wurde, FALSE, wenn der User den Channel-Mode @@ -441,7 +527,8 @@ GLOBAL BOOLEAN Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode ) } /* Channel_UserModeDel */ -GLOBAL CHAR *Channel_UserModes( CHANNEL *Chan, CLIENT *Client ) +GLOBAL CHAR * +Channel_UserModes( CHANNEL *Chan, CLIENT *Client ) { /* Channel-Modes eines Users liefern */ @@ -457,7 +544,8 @@ GLOBAL CHAR *Channel_UserModes( CHANNEL *Chan, CLIENT *Client ) } /* Channel_UserModes */ -GLOBAL BOOLEAN Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client ) +GLOBAL BOOLEAN +Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client ) { /* Pruefen, ob Client Mitglied in Channel ist */ @@ -469,14 +557,16 @@ GLOBAL BOOLEAN Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client ) } /* Channel_IsMemberOf */ -GLOBAL CHAR *Channel_Topic( CHANNEL *Chan ) +GLOBAL CHAR * +Channel_Topic( CHANNEL *Chan ) { assert( Chan != NULL ); return Chan->topic; } /* Channel_Topic */ -GLOBAL VOID Channel_SetTopic( CHANNEL *Chan, CHAR *Topic ) +GLOBAL VOID +Channel_SetTopic( CHANNEL *Chan, CHAR *Topic ) { assert( Chan != NULL ); assert( Topic != NULL ); @@ -486,7 +576,20 @@ GLOBAL VOID Channel_SetTopic( CHANNEL *Chan, CHAR *Topic ) } /* Channel_SetTopic */ -GLOBAL BOOLEAN Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text ) +GLOBAL VOID +Channel_SetModes( CHANNEL *Chan, CHAR *Modes ) +{ + assert( Chan != NULL ); + assert( Modes != NULL ); + + strncpy( Chan->modes, Modes, CHANNEL_MODE_LEN - 1 ); + Chan->topic[CHANNEL_MODE_LEN - 1] = '\0'; +} /* Channel_SetModes */ + + + +GLOBAL BOOLEAN +Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text ) { BOOLEAN is_member, has_voice, is_op, ok; @@ -512,8 +615,8 @@ GLOBAL BOOLEAN Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR } /* Channel_Write */ - -LOCAL CHANNEL *New_Chan( CHAR *Name ) +GLOBAL CHANNEL * +Channel_Create( CHAR *Name ) { /* Neue Channel-Struktur anlegen */ @@ -524,7 +627,7 @@ LOCAL CHANNEL *New_Chan( CHAR *Name ) c = malloc( sizeof( CHANNEL )); if( ! c ) { - Log( LOG_EMERG, "Can't allocate memory!" ); + Log( LOG_EMERG, "Can't allocate memory! [New_Chan]" ); return NULL; } c->next = NULL; @@ -534,13 +637,18 @@ LOCAL CHANNEL *New_Chan( CHAR *Name ) strcpy( c->topic, "" ); c->hash = Hash( c->name ); + /* Verketten */ + c->next = My_Channels; + My_Channels = c; + Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name ); return c; -} /* New_Chan */ +} /* Channel_Create */ -LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client ) +LOCAL CL2CHAN * +Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client ) { CL2CHAN *cl2chan; @@ -557,7 +665,8 @@ LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client ) } /* Get_Cl2Chan */ -LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client ) +LOCAL CL2CHAN * +Add_Client( CHANNEL *Chan, CLIENT *Client ) { CL2CHAN *cl2chan; @@ -568,7 +677,7 @@ LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client ) cl2chan = malloc( sizeof( CL2CHAN )); if( ! cl2chan ) { - Log( LOG_EMERG, "Can't allocate memory!" ); + Log( LOG_EMERG, "Can't allocate memory! [Add_Client]" ); return NULL; } cl2chan->channel = Chan; @@ -585,7 +694,8 @@ LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client ) } /* Add_Client */ -LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART ) +LOCAL BOOLEAN +Remove_Client( INT Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN InformServer ) { CL2CHAN *cl2chan, *last_cl2chan; CHANNEL *c; @@ -613,11 +723,30 @@ LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR else My_Cl2Chan = cl2chan->next; free( cl2chan ); - if( ServerPART ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason ); - IRC_WriteStrChannelPrefix( Origin, c, Client, FALSE, "PART %s :%s", c->name, Reason ); - if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason ); - - Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason ); + switch( Type ) + { + case REMOVE_QUIT: + /* QUIT: andere Server wurden bereits informiert, vgl. Client_Destroy(); + * hier also "nur" noch alle User in betroffenen Channeln infomieren */ + assert( InformServer == FALSE ); + IRC_WriteStrChannelPrefix( Origin, c, Origin, FALSE, "QUIT :%s", Reason ); + Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason ); + break; + case REMOVE_KICK: + /* User wurde geKICKed: ggf. andere Server sowie alle betroffenen User + * im entsprechenden Channel informieren */ + if( InformServer ) IRC_WriteStrServersPrefix( Client_NextHop( Origin ), Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason ); + IRC_WriteStrChannelPrefix( Client, c, Origin, FALSE, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason ); + if(( Client_Conn( Client ) > NONE ) && ( Client_Type( Client ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Client, Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason ); + Log( LOG_DEBUG, "User \"%s\" has been kicked of \"%s\" by \"%s\": %s.", Client_Mask( Client ), c->name, Client_ID( Origin ), Reason ); + break; + default: + /* PART */ + if( InformServer ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason ); + IRC_WriteStrChannelPrefix( Origin, c, Client, FALSE, "PART %s :%s", c->name, Reason ); + if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason ); + Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason ); + } /* Wenn Channel nun leer und nicht pre-defined: loeschen */ if( ! strchr( Channel_Modes( Chan ), 'P' )) @@ -629,13 +758,15 @@ LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR } /* Remove_Client */ -LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan ) +LOCAL CL2CHAN * +Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan ) { return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan ); } /* Get_First_Cl2Chan */ -LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel ) +LOCAL CL2CHAN * +Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel ) { CL2CHAN *cl2chan; @@ -652,7 +783,8 @@ LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channe } /* Get_Next_Cl2Chan */ -LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan ) +LOCAL BOOLEAN +Delete_Channel( CHANNEL *Chan ) { /* Channel-Struktur loeschen */ @@ -670,6 +802,9 @@ LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan ) Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name ); + /* Invite- und Ban-Lists aufraeumen */ + Lists_DeleteChannel( chan ); + /* Neu verketten und freigeben */ if( last_chan ) last_chan->next = chan->next; else My_Channels = chan->next;