#include "portab.h"
-static char UNUSED id[] = "$Id: channel.c,v 1.48 2005/06/04 11:53:25 fw Exp $";
+static char UNUSED id[] = "$Id: channel.c,v 1.55 2006/04/23 10:33:37 fw Exp $";
#include "imp.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <strings.h>
#include "defines.h"
#define REMOVE_KICK 2
-LOCAL CHANNEL *My_Channels;
-LOCAL CL2CHAN *My_Cl2Chan;
+static CHANNEL *My_Channels;
+static CL2CHAN *My_Cl2Chan;
-LOCAL CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client ));
-LOCAL CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client ));
-LOCAL bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer ));
-LOCAL CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan ));
-LOCAL CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ));
-LOCAL bool Delete_Channel PARAMS(( CHANNEL *Chan ));
+static CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client ));
+static CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client ));
+static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer ));
+static CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan ));
+static CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ));
+static bool Delete_Channel PARAMS(( CHANNEL *Chan ));
GLOBAL void
CHANNEL *chan;
char *c;
- int i;
+ unsigned int i;
for( i = 0; i < Conf_Channel_Count; i++ )
{
if( ! Channel_IsValidName( Conf_Channel[i].name ))
{
Log( LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"!", Conf_Channel[i].name );
+ array_free(&Conf_Channel[i].topic);
continue;
}
if( chan )
{
Log( LOG_INFO, "Can't create pre-defined channel \"%s\": name already in use.", Conf_Channel[i].name );
+ array_free(&Conf_Channel[i].topic);
continue;
}
-
- /* Channel anlegen */
- chan = Channel_Create( Conf_Channel[i].name );
- if( chan )
- {
- Channel_ModeAdd( chan, 'P' );
- Channel_SetTopic( chan, Conf_Channel[i].topic );
+
+ /* Create channel */
+ chan = Channel_Create(Conf_Channel[i].name);
+ if (chan) {
+ Channel_ModeAdd(chan, 'P');
+
+ Channel_SetTopic(chan, NULL,
+ array_start(&Conf_Channel[i].topic));
+ array_free(&Conf_Channel[i].topic);
+
c = Conf_Channel[i].modes;
- while( *c ) Channel_ModeAdd( chan, *c++ );
- Log( LOG_INFO, "Created pre-defined channel \"%s\".", Conf_Channel[i].name );
+ while (*c)
+ Channel_ModeAdd(chan, *c++);
+
+ Log(LOG_INFO, "Created pre-defined channel \"%s\".",
+ Conf_Channel[i].name );
}
- else Log( LOG_ERR, "Can't create pre-defined channel \"%s\"!", Conf_Channel[i].name );
+ else Log(LOG_ERR, "Can't create pre-defined channel \"%s\"!",
+ Conf_Channel[i].name );
}
} /* Channel_InitPredefined */
while( c )
{
c_next = c->next;
+ array_free(&c->topic);
free( c );
c = c_next;
}
assert( Client != NULL );
assert( Name != NULL );
- /* Valider Channel-Name? */
- if( ! Channel_IsValidName( Name ))
- {
+ if( ! Channel_IsValidName( Name )) {
IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
return false;
}
- /* Channel suchen */
chan = Channel_Search( Name );
- if( chan )
- {
+ if( chan ) {
/* Ist der Client bereits Mitglied? */
if( Get_Cl2Chan( chan, Client )) return false;
}
assert( Name != NULL );
assert( Reason != NULL );
- /* Channel suchen */
chan = Channel_Search( Name );
if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client )))
{
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? */
+ /* Is 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? */
+ /* Ist the kickED User member of channel? */
if( ! Channel_IsMemberOf( chan, Client ))
{
IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( Client ), Name );
* if the mode was removed return true.
* if the channel did not have the mode, return false.
*/
- char x[2], *p;
+ char *p;
assert( Chan != NULL );
- x[0] = Mode; x[1] = '\0';
-
- p = strchr( Chan->modes, x[0] );
+ p = strchr( Chan->modes, Mode );
if( ! p ) return false;
/* Channel has mode -> delete */
*/
CL2CHAN *cl2chan;
- char x[2], *p;
+ char *p;
assert( Chan != NULL );
assert( Client != NULL );
cl2chan = Get_Cl2Chan( Chan, Client );
assert( cl2chan != NULL );
- x[0] = Mode; x[1] = '\0';
-
- p = strchr( cl2chan->modes, x[0] );
+ p = strchr( cl2chan->modes, Mode );
if( ! p ) return false;
/* Client has Mode -> delete */
GLOBAL char *
Channel_Topic( CHANNEL *Chan )
{
+ char *ret;
assert( Chan != NULL );
- return Chan->topic;
+ ret = array_start(&Chan->topic);
+ return ret ? ret : "";
} /* Channel_Topic */
+
+#ifndef STRICT_RFC
+
+GLOBAL unsigned int
+Channel_TopicTime(CHANNEL *Chan)
+{
+ assert(Chan != NULL);
+ return (unsigned int) Chan->topic_time;
+} /* Channel_TopicTime */
+
+
+GLOBAL char *
+Channel_TopicWho(CHANNEL *Chan)
+{
+ assert(Chan != NULL);
+ return Chan->topic_who;
+} /* Channel_TopicWho */
+
+#endif
+
GLOBAL void
-Channel_SetTopic( CHANNEL *Chan, char *Topic )
+Channel_SetTopic(CHANNEL *Chan, CLIENT *Client, char *Topic)
{
+ size_t len;
assert( Chan != NULL );
assert( Topic != NULL );
-
- strlcpy( Chan->topic, Topic, sizeof( Chan->topic ));
+
+ len = strlen(Topic);
+ if (len < array_bytes(&Chan->topic))
+ array_free(&Chan->topic);
+
+ if (!array_copyb(&Chan->topic, Topic, len))
+ Log(LOG_WARNING, "could not set new Topic \"%s\" on %s: %s",
+ Topic, Chan->name, strerror(errno));
+
+ array_cat0(&Chan->topic);
+
+#ifndef STRICT_RFC
+ Chan->topic_time = time(NULL);
+ if (Client != NULL && Client_Type(Client) != CLIENT_SERVER)
+ strlcpy(Chan->topic_who, Client_ID(Client),
+ sizeof Chan->topic_who);
+ else
+ strlcpy(Chan->topic_who, DEFAULT_TOPIC_ID,
+ sizeof Chan->topic_who);
+#else
+ (void) Client;
+#endif
} /* Channel_SetTopic */
/* Is the client banned? */
if( Lists_CheckBanned( From, Chan ))
{
- /* Client is banned, bus is he channel operator or has voice? */
+ /* Client is banned, but is he channel operator or has voice? */
if(( ! has_voice ) && ( ! is_op )) ok = false;
}
c->hash = Hash( c->name );
c->next = My_Channels;
My_Channels = c;
-
+#ifdef DEBUG
Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name );
-
+#endif
return c;
} /* Channel_Create */
-LOCAL CL2CHAN *
+static CL2CHAN *
Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
{
CL2CHAN *cl2chan;
} /* Get_Cl2Chan */
-LOCAL CL2CHAN *
+static CL2CHAN *
Add_Client( CHANNEL *Chan, CLIENT *Client )
{
CL2CHAN *cl2chan;
} /* Add_Client */
-LOCAL bool
+static bool
Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer )
{
CL2CHAN *cl2chan, *last_cl2chan;
} /* Remove_Client */
-LOCAL CL2CHAN *
+static CL2CHAN *
Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
{
return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
} /* Get_First_Cl2Chan */
-LOCAL CL2CHAN *
+static CL2CHAN *
Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
{
CL2CHAN *cl2chan;
} /* Get_Next_Cl2Chan */
-LOCAL bool
+static bool
Delete_Channel( CHANNEL *Chan )
{
/* Channel-Struktur loeschen */