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:
parent
4d152b771e
commit
634ef8c131
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue