IRC_JOIN cleanups.

- put sending of mode and forwarding of JOIN to other clients
 into seperate function.
- put sending of topic/channel names into seperate function.
- put access check into seperate function.
- translate/remove remaining german comments.
- stop if JOIN to a channel in a list (JOIN #a,#,b,#c...) fails
(This doesn't change the behaviour: skip-to-next-channel-on-error
did never work as intended)
This commit is contained in:
Florian Westphal 2008-02-16 11:21:33 +00:00
parent 4d152b771e
commit 634ef8c131
1 changed files with 152 additions and 153 deletions

View File

@ -14,7 +14,7 @@
#include "portab.h" #include "portab.h"
static char UNUSED id[] = "$Id: irc-channel.c,v 1.43 2008/02/05 19:00:52 fw Exp $"; static char UNUSED id[] = "$Id: irc-channel.c,v 1.44 2008/02/16 11:21:33 fw Exp $";
#include "imp.h" #include "imp.h"
#include <assert.h> #include <assert.h>
@ -63,11 +63,121 @@ part_from_all_channels(CLIENT* client, CLIENT *target)
} }
static bool
join_allowed(CLIENT *Client, CLIENT *target, CHANNEL *chan,
const char *channame, const char *key)
{
bool is_invited, is_banned;
const char *channel_modes;
is_banned = Lists_Check(Channel_GetListBans(chan), target);
is_invited = Lists_Check(Channel_GetListInvites(chan), target);
if (is_banned && !is_invited) {
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame);
return false;
}
channel_modes = Channel_Modes(chan);
if ((strchr(channel_modes, 'i')) && !is_invited) {
/* Channel is "invite-only" (and Client wasn't invited) */
IRC_WriteStrClient(Client, ERR_INVITEONLYCHAN_MSG, Client_ID(Client), channame);
return false;
}
/* Is the channel protected by a key? */
if (strchr(channel_modes, 'k') &&
strcmp(Channel_Key(chan), key ? key : ""))
{
IRC_WriteStrClient(Client, ERR_BADCHANNELKEY_MSG, Client_ID(Client), channame);
return false;
}
/* Are there already too many members? */
if ((strchr(channel_modes, 'l')) && (Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) {
IRC_WriteStrClient(Client, ERR_CHANNELISFULL_MSG, Client_ID(Client), channame);
return false;
}
return true;
}
static void
join_set_channelmodes(CHANNEL *chan, CLIENT *target, const char *flags)
{
if (flags) {
while (*flags) {
Channel_UserModeAdd(chan, target, *flags);
flags++;
}
}
/* If channel persistent and client is ircop: make client chanop */
if (strchr(Channel_Modes(chan), 'P') && strchr(Client_Modes(target), 'o'))
Channel_UserModeAdd(chan, target, 'o');
}
static void
join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan,
const char *channame)
{
char modes[8];
strlcpy(&modes[1], Channel_UserModes(chan, target), sizeof(modes) - 1);
if (modes[1])
modes[0] = 0x7;
else
modes[0] = '\0';
/* forward to other servers */
IRC_WriteStrServersPrefix(Client, target, "JOIN :%s%s", channame, modes);
/* tell users in this channel about the new client */
IRC_WriteStrChannelPrefix(Client, chan, target, false, "JOIN :%s", channame);
if (modes[1])
IRC_WriteStrChannelPrefix(Client, chan, target, false, "MODE %s +%s %s",
channame, &modes[1], Client_ID(target));
}
static bool
join_send_topic(CLIENT *Client, CLIENT *target, CHANNEL *chan,
const char *channame)
{
const char *topic;
if (Client_Type(Client) != CLIENT_USER)
return true;
/* acknowledge join */
if (!IRC_WriteStrClientPrefix(Client, target, "JOIN :%s", channame))
return false;
/* Send topic to client, if any */
topic = Channel_Topic(chan);
assert(topic != NULL);
if (*topic) {
if (!IRC_WriteStrClient(Client, RPL_TOPIC_MSG,
Client_ID(Client), channame, topic))
return false;
#ifndef STRICT_RFC
if (!IRC_WriteStrClient(Client, RPL_TOPICSETBY_MSG,
Client_ID(Client), channame,
Channel_TopicWho(chan),
Channel_TopicTime(chan)))
return false;
#endif
}
/* send list of channel members to client */
if (!IRC_Send_NAMES(Client, chan))
return false;
return IRC_WriteStrClient(Client, RPL_ENDOFNAMES_MSG, Client_ID(Client), Channel_Name(chan));
}
GLOBAL bool GLOBAL bool
IRC_JOIN( CLIENT *Client, REQUEST *Req ) IRC_JOIN( CLIENT *Client, REQUEST *Req )
{ {
char *channame, *channame_ptr, *key, *key_ptr, *flags, *topic, modes[8]; char *channame, *channame_ptr, *key, *key_ptr, *flags;
bool is_new_chan, is_invited, is_banned;
CLIENT *target; CLIENT *target;
CHANNEL *chan; CHANNEL *chan;
@ -80,9 +190,13 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
/* Who is the sender? */ /* Who is the sender? */
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix ); if (Client_Type(Client) == CLIENT_SERVER)
else target = Client; target = Client_Search(Req->prefix);
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); else
target = Client;
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
/* Is argument "0"? */ /* Is argument "0"? */
if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2)) if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
@ -93,181 +207,66 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
key = Req->argv[1]; key = Req->argv[1];
key_ptr = strchr(key, ','); key_ptr = strchr(key, ',');
if (key_ptr) *key_ptr = '\0'; if (key_ptr) *key_ptr = '\0';
} } else {
else
key = key_ptr = NULL; key = key_ptr = NULL;
}
channame = Req->argv[0]; channame = Req->argv[0];
channame_ptr = strchr(channame, ','); channame_ptr = strchr(channame, ',');
if (channame_ptr) *channame_ptr = '\0'; if (channame_ptr) *channame_ptr = '\0';
/* Channel-Namen durchgehen */ while (channame) {
while (channame) flags = NULL;
{
chan = NULL; flags = NULL;
/* wird der Channel neu angelegt? */ chan = Channel_Search(channame);
if( Channel_Search( channame )) { if (!chan && Conf_PredefChannelsOnly) {
is_new_chan = false; /* channel must be created, but server does not allow this */
} else { IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame);
if (Conf_PredefChannelsOnly) { /* this server does not allow creation of channels */ break;
IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
is_new_chan = true;
} }
/* Hat ein Server Channel-User-Modes uebergeben? */ /* Did the server include channel-user-modes? */
if( Client_Type( Client ) == CLIENT_SERVER ) if (Client_Type(Client) == CLIENT_SERVER) {
{ flags = strchr(channame, 0x7);
/* Channel-Flags extrahieren */ if (flags) {
flags = strchr( channame, 0x7 );
if( flags )
{
*flags = '\0'; *flags = '\0';
flags++; flags++;
} }
} }
/* Local client? */ /* Local client? */
if( Client_Type( Client ) == CLIENT_USER ) if (Client_Type(Client) == CLIENT_USER) {
{
/* Test if the user has reached his maximum channel count */ /* Test if the user has reached his maximum channel count */
if(( Conf_MaxJoins > 0 ) && ( Channel_CountForUser( Client ) >= Conf_MaxJoins )) if ((Conf_MaxJoins > 0) && (Channel_CountForUser(Client) >= Conf_MaxJoins))
return IRC_WriteStrClient( Client, ERR_TOOMANYCHANNELS_MSG, return IRC_WriteStrClient(Client, ERR_TOOMANYCHANNELS_MSG,
Client_ID( Client ), channame ); Client_ID(Client), channame);
if (!chan) /* New Channel: first user will be channel operator */
/* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
if( is_new_chan )
{
/* Erster User im Channel: Operator-Flag setzen */
flags = "o"; flags = "o";
}
else else
{ if (!join_allowed(Client, target, chan, channame, key))
/* Existierenden Channel suchen */ break;
chan = Channel_Search( channame ); } else {
assert( chan != NULL );
is_banned = Lists_Check(Channel_GetListBans(chan), target );
is_invited = Lists_Check(Channel_GetListInvites(chan), target );
/* Testen, ob Client gebanned ist */
if(( is_banned == true) && ( is_invited == false ))
{
/* Client ist gebanned (und nicht invited): */
IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
/* Ist der Channel "invite-only"? */
if(( strchr( Channel_Modes( chan ), 'i' )) && ( is_invited == false ))
{
/* Channel ist "invite-only" und Client wurde nicht invited: */
IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
/* Is the channel protected by a key? */
if(( strchr( Channel_Modes( chan ), 'k' )) && ( strcmp( Channel_Key( chan ), key ? key : "" ) != 0 ))
{
/* Bad channel key! */
IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
/* Are there already too many members? */
if(( strchr( Channel_Modes( chan ), 'l' )) && ( Channel_MaxUsers( chan ) <= Channel_MemberCount( chan )))
{
/* Bad channel key! */
IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
}
}
else
{
/* Remote server: we don't need to know whether the /* Remote server: we don't need to know whether the
* client is invited or not, but we have to make sure * client is invited or not, but we have to make sure
* that the "one shot" entries (generated by INVITE * that the "one shot" entries (generated by INVITE
* commands) in this list become deleted when a user * commands) in this list become deleted when a user
* joins a channel this way. */ * joins a channel this way. */
chan = Channel_Search( channame ); if (chan) (void)Lists_Check(Channel_GetListInvites(chan), target);
if( chan != NULL ) (void)Lists_Check(Channel_GetListInvites(chan), target);
} }
/* Channel joinen (und ggf. anlegen) */ /* Join channel (and create channel if it doesn't exist) */
if( ! Channel_Join( target, channame )) if (!Channel_Join(target, channame))
{ break;
/* naechsten Namen ermitteln */
channame = strchr(channame, ',');
continue;
}
if( ! chan ) chan = Channel_Search( channame );
assert( chan != NULL );
/* Modes setzen (wenn vorhanden) */ if (!chan) /* channel is new; it has been created above */
while( flags && *flags ) chan = Channel_Search(channame);
{ assert(chan != NULL);
Channel_UserModeAdd( chan, target, *flags );
flags++;
}
/* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */ join_set_channelmodes(chan, target, flags);
if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
/* Muessen Modes an andere Server gemeldet werden? */ join_forward(Client, target, chan, channame);
strlcpy( &modes[1], Channel_UserModes( chan, target ), sizeof( modes ) - 1 );
if( modes[1] ) modes[0] = 0x7;
else modes[0] = '\0';
/* An andere Server weiterleiten */ if (!join_send_topic(Client, target, chan, channame))
IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes ); break; /* write error */
/* im Channel bekannt machen */
IRC_WriteStrChannelPrefix( Client, chan, target, false, "JOIN :%s", channame );
if( modes[1] )
{
/* Modes im Channel bekannt machen */
IRC_WriteStrChannelPrefix( Client, chan, target, false, "MODE %s +%s %s", channame, &modes[1], Client_ID( target ));
}
if( Client_Type( Client ) == CLIENT_USER )
{
/* an Client bestaetigen */
IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
/* Send topic to client, if any */
topic = Channel_Topic(chan);
if (*topic) {
IRC_WriteStrClient(Client, RPL_TOPIC_MSG,
Client_ID(Client), channame, topic);
#ifndef STRICT_RFC
IRC_WriteStrClient(Client, RPL_TOPICSETBY_MSG,
Client_ID(Client), channame,
Channel_TopicWho(chan),
Channel_TopicTime(chan));
#endif
}
/* Mitglieder an Client Melden */
IRC_Send_NAMES( Client, chan );
IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
}
/* next channel? */ /* next channel? */
channame = channame_ptr; channame = channame_ptr;