#include "match.h"
#include "messages.h"
#include "parse.h"
+#include "irc.h"
#include "irc-info.h"
#include "irc-write.h"
#include "conf.h"
join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
const char *key)
{
- bool is_invited, is_banned;
+ bool is_invited, is_banned, is_exception;
const char *channel_modes;
/* Allow IRC operators to overwrite channel limits */
return true;
is_banned = Lists_Check(Channel_GetListBans(chan), Client);
+ is_exception = Lists_Check(Channel_GetListExcepts(chan), Client);
is_invited = Lists_Check(Channel_GetListInvites(chan), Client);
- if (is_banned && !is_invited) {
+ if (is_banned && !is_invited && !is_exception) {
/* Client is banned from channel (and not on invite list) */
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
Client_ID(Client), channame);
*
* See RFC 2812, 3.2.1 "Join message"; RFC 2813, 4.2.1 "Join message".
*
- * @param Client The client from which this command has been received
- * @param Req Request structure with prefix and all parameters
- * @returns CONNECTED or DISCONNECTED
+ * @param Client The client from which this command has been received
+ * @param Req Request structure with prefix and all parameters
+ * @returns CONNECTED or DISCONNECTED
*/
GLOBAL bool
IRC_JOIN( CLIENT *Client, REQUEST *Req )
CLIENT *target;
CHANNEL *chan;
- assert( Client != NULL );
- assert( Req != NULL );
+ assert (Client != NULL);
+ assert (Req != NULL);
/* Bad number of arguments? */
if (Req->argc < 1 || Req->argc > 2)
target = Client;
if (!target)
- return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
+ return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
+ Client_ID(Client), Req->prefix);
/* Is argument "0"? */
if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
chan = Channel_Search(channame);
if (!chan && Conf_PredefChannelsOnly) {
- /* channel must be created, but server does not allow this */
- IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame);
- break;
+ /* channel must be created, but forbidden by config */
+ IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
+ Client_ID(Client), channame);
+ goto join_next;
}
/* Local client? */
if (Client_Type(Client) == CLIENT_USER) {
+ if (chan) {
+ /* Already existing channel: already member? */
+ if (Channel_IsMemberOf(chan, Client))
+ goto join_next;
+ }
+
/* Test if the user has reached the channel limit */
if ((Conf_MaxJoins > 0) &&
- (Channel_CountForUser(Client) >= Conf_MaxJoins))
- return IRC_WriteStrClient(Client,
+ (Channel_CountForUser(Client) >= Conf_MaxJoins)) {
+ if (!IRC_WriteStrClient(Client,
ERR_TOOMANYCHANNELS_MSG,
- Client_ID(Client), channame);
+ Client_ID(Client), channame))
+ return DISCONNECTED;
+ goto join_next;
+ }
+
if (chan) {
/* Already existing channel: check if the
* client is allowed to join */
if (!join_allowed(Client, chan, channame, key))
- break;
+ goto join_next;
} else {
/* New channel: first user will become channel
* operator unless this is a modeless channel */
/* Join channel (and create channel if it doesn't exist) */
if (!Channel_Join(target, channame))
- break;
+ goto join_next;
if (!chan) { /* channel is new; it has been created above */
chan = Channel_Search(channame);
if (!join_send_topic(Client, target, chan, channame))
break; /* write error */
+ join_next:
/* next channel? */
channame = strtok_r(NULL, ",", &lastchan);
if (channame && key)
* This implementation handles the local case as well as the forwarding of the
* LIST command to other servers in the IRC network.
*
- * @param Client The client from which this command has been received
- * @param Req Request structure with prefix and all parameters
- * @returns CONNECTED or DISCONNECTED
+ * @param Client The client from which this command has been received.
+ * @param Req Request structure with prefix and all parameters.
+ * @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_LIST( CLIENT *Client, REQUEST *Req )
char *pattern;
CHANNEL *chan;
CLIENT *from, *target;
+ int count = 0;
- assert( Client != NULL );
- assert( Req != NULL );
+ assert(Client != NULL);
+ assert(Req != NULL);
/* Bad number of prameters? */
- if( Req->argc > 2 )
- return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
- Client_ID( Client ), Req->command );
+ if (Req->argc > 2)
+ return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+ Client_ID(Client), Req->command);
- if( Req->argc > 0 )
- pattern = strtok( Req->argv[0], "," );
+ if (Req->argc > 0)
+ pattern = strtok(Req->argv[0], ",");
else
pattern = "*";
/* Get sender from prefix, if any */
- if( Client_Type( Client ) == CLIENT_SERVER )
- from = Client_Search( Req->prefix );
+ if (Client_Type(Client) == CLIENT_SERVER)
+ from = Client_Search(Req->prefix);
else
from = Client;
- if( ! from )
- return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG,
- Client_ID( Client ), Req->prefix );
+ if (!from)
+ return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
+ Client_ID(Client), Req->prefix);
- if( Req->argc == 2 )
- {
+ if (Req->argc == 2) {
/* Forward to other server? */
- target = Client_Search( Req->argv[1] );
- if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER ))
- return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG,
- Client_ID( Client ), Req->argv[1] );
+ target = Client_Search(Req->argv[1]);
+ if (! target || Client_Type(target) != CLIENT_SERVER)
+ return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
+ Client_ID(Client),
+ Req->argv[1]);
- if( target != Client_ThisServer( ))
- {
+ if (target != Client_ThisServer()) {
/* Target is indeed an other server, forward it! */
- return IRC_WriteStrClientPrefix( target, from,
- "LIST %s :%s", Client_ID( from ),
- Req->argv[1] );
+ return IRC_WriteStrClientPrefix(target, from,
+ "LIST %s :%s",
+ Req->argv[0],
+ Req->argv[1]);
}
}
- while( pattern )
- {
+ while (pattern) {
/* Loop through all the channels */
- chan = Channel_First( );
- while( chan )
- {
+ if (Req->argc > 0)
+ ngt_LowerStr(pattern);
+ chan = Channel_First();
+ while (chan) {
/* Check search pattern */
- if( Match( pattern, Channel_Name( chan )))
- {
+ if (MatchCaseInsensitive(pattern, Channel_Name(chan))) {
/* Gotcha! */
- if( ! strchr( Channel_Modes( chan ), 's' ) ||
- Channel_IsMemberOf( chan, from ))
- {
- if( ! IRC_WriteStrClient( from,
- RPL_LIST_MSG, Client_ID( from ),
- Channel_Name( chan ),
- Channel_MemberCount( chan ),
- Channel_Topic( chan )))
+ if (!strchr(Channel_Modes(chan), 's')
+ || Channel_IsMemberOf(chan, from)) {
+ if (IRC_CheckListTooBig(from, count,
+ MAX_RPL_LIST,
+ "LIST"))
+ break;
+ if (!IRC_WriteStrClient(from,
+ RPL_LIST_MSG, Client_ID(from),
+ Channel_Name(chan),
+ Channel_MemberCount(chan),
+ Channel_Topic( chan )))
return DISCONNECTED;
+ count++;
}
}
- chan = Channel_Next( chan );
+ chan = Channel_Next(chan);
}
/* Get next name ... */
- if( Req->argc > 0 )
- pattern = strtok( NULL, "," );
+ if(Req->argc > 0)
+ pattern = strtok(NULL, ",");
else
pattern = NULL;
}
- return IRC_WriteStrClient( from, RPL_LISTEND_MSG, Client_ID( from ));
+ IRC_SetPenalty(from, 2);
+ return IRC_WriteStrClient(from, RPL_LISTEND_MSG, Client_ID(from));
} /* IRC_LIST */