X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/ff91faaf76a7d42b1549b4481566b1460159c030..b2c208be091670e3c5259eba77187bae6ac6eece:/modules/core/m_join.c?ds=sidebyside diff --git a/modules/core/m_join.c b/modules/core/m_join.c index c01aba77..bba9eaf1 100644 --- a/modules/core/m_join.c +++ b/modules/core/m_join.c @@ -41,6 +41,7 @@ #include "modules.h" #include "packet.h" #include "chmode.h" +#include "ratelimit.h" static int m_join(struct Client *, struct Client *, int, const char **); static int ms_join(struct Client *, struct Client *, int, const char **); @@ -89,17 +90,26 @@ static int pargs; */ static struct Channel * check_forward(struct Client *source_p, struct Channel *chptr, - char *key) + char *key, int *err) { int depth = 0, i; + const char *next = NULL; - /* User is +Q */ - if (IsNoForward(source_p)) + /* The caller (m_join) is only interested in the reason + * for the original channel. + */ + if ((*err = can_join(source_p, chptr, key, &next)) == 0) + return chptr; + + /* User is +Q, or forwarding disabled */ + if (IsNoForward(source_p) || !ConfigChannel.use_forward) return NULL; while (depth < 16) { - chptr = find_channel(chptr->mode.forward); + if (next == NULL) + return NULL; + chptr = find_channel(next); /* Can only forward to existing channels */ if (chptr == NULL) return NULL; @@ -112,11 +122,9 @@ check_forward(struct Client *source_p, struct Channel *chptr, /* Don't forward to +Q channel */ if (chptr->mode.mode & MODE_DISFORWARD) return NULL; - i = can_join(source_p, chptr, key); + i = can_join(source_p, chptr, key, &next); if (i == 0) return chptr; - if (i != ERR_INVITEONLYCHAN && i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_CHANNELISFULL) - return NULL; depth++; } @@ -132,7 +140,7 @@ static int m_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { static char jbuf[BUFSIZE]; - struct Channel *chptr = NULL; + struct Channel *chptr = NULL, *chptr2 = NULL; struct ConfItem *aconf; char *name; char *key = NULL; @@ -166,7 +174,8 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p } /* check it begins with # or &, and local chans are disabled */ - else if(!IsChannelName(name)) + else if(!IsChannelName(name) || + ( ConfigChannel.disable_local_channels && name[0] == '&')) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); @@ -247,8 +256,10 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p if(moduledata.approved != 0) { +#ifdef XXX_NOTYET sendto_one(source_p, form_str(moduledata.approved), me.name, source_p->name, name); +#endif continue; } @@ -271,7 +282,7 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p { sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS), me.name, source_p->name, name); - return 0; + continue; } if(chptr == NULL) /* If I already have a chptr, no point doing this */ @@ -286,24 +297,23 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p } } - /* can_join checks for +i key, bans etc */ - if((i = can_join(source_p, chptr, key))) + /* If check_forward returns NULL, they couldn't join and there wasn't a usable forward channel. */ + if(!(chptr2 = check_forward(source_p, chptr, key, &i))) { - if ((i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_INVITEONLYCHAN && i != ERR_CHANNELISFULL) || - (!ConfigChannel.use_forward || (chptr = check_forward(source_p, chptr, key)) == NULL)) - { - /* might be wrong, but is there any other better location for such? - * see extensions/chm_operonly.c for other comments on this - * -- dwr - */ - if(i != ERR_CUSTOM) - sendto_one(source_p, form_str(i), me.name, source_p->name, name); - - continue; - } - - sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr->chname); + /* might be wrong, but is there any other better location for such? + * see extensions/chm_operonly.c for other comments on this + * -- dwr + */ +#ifdef XXX_NOTYET + if(i != ERR_CUSTOM) + sendto_one(source_p, form_str(i), me.name, source_p->name, name); +#endif + continue; } + else if(chptr != chptr2) + sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr2->chname); + + chptr = chptr2; if(flags == 0 && !IsOper(source_p) && !IsExemptSpambot(source_p)) @@ -319,12 +329,13 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p } chptr->join_count++; + /* credit user for join */ + credit_client_join(source_p); + /* we send the user their join here, because we could have to * send a mode out next. */ - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", - source_p->name, - source_p->username, source_p->host, chptr->chname); + send_channel_join(chptr, source_p); /* its a new channel, set +nt and burst. */ if(flags & CHFL_CHANOP) @@ -359,7 +370,8 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, - chptr->topic_info, chptr->topic_time); + chptr->topic_info, + (unsigned long)chptr->topic_time); } channel_member_names(chptr, source_p, 1); @@ -389,7 +401,6 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char * time_t newts; int isnew; int keep_our_modes = YES; - int keep_new_modes = YES; rb_dlink_node *ptr, *next_ptr; /* special case for join 0 */ @@ -451,8 +462,6 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char * keep_our_modes = NO; chptr->channelts = newts; } - else - keep_new_modes = NO; /* Lost the TS, other side wins, so remove modes on this side */ if(!keep_our_modes) @@ -479,6 +488,9 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char * source_p->servptr->name, chptr->chname, modebuf, parabuf); *modebuf = *parabuf = '\0'; + + /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */ + set_channel_mlock(client_p, source_p, chptr, NULL, FALSE); } if(!IsMember(source_p, chptr)) @@ -491,9 +503,7 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char * chptr->join_delta = rb_current_time(); } chptr->join_count++; - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", - source_p->name, source_p->username, - source_p->host, chptr->chname); + send_channel_join(chptr, source_p); } sendto_server(client_p, chptr, CAP_TS6, NOCAPS, @@ -639,12 +649,15 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char { /* If configured, kick people trying to join +i/+k * channels by recreating them on split servers. - * Don't kick if the source has sent EOB (services - * deopping everyone by TS-1 SJOIN). + * If the source has sent EOB, assume this is some + * sort of hack by services. If cmode +i is set, + * services can send kicks if needed; if the key + * differs, services cannot kick in a race-free + * manner so do so here. * -- jilles */ if (ConfigChannel.kick_on_split_riding && - !HasSentEob(source_p) && - ((mode.mode & MODE_INVITEONLY) || + ((!HasSentEob(source_p) && + mode.mode & MODE_INVITEONLY) || (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0))) { struct membership *msptr; @@ -739,6 +752,9 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char /* Update capitalization in channel name, this makes the * capitalization timestamped like modes are -- jilles */ strcpy(chptr->chname, parv[2]); + + /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */ + set_channel_mlock(client_p, source_p, chptr, NULL, FALSE); } if(*modebuf != '\0') @@ -833,9 +849,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char if(!IsMember(target_p, chptr)) { add_user_to_channel(chptr, target_p, fl); - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", - target_p->name, - target_p->username, target_p->host, parv[2]); + send_channel_join(chptr, target_p); joins++; } @@ -1116,7 +1130,8 @@ set_final_mode(struct Mode *mode, struct Mode *oldmode) len = rb_sprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time); pbuf += len; } - if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) && ConfigChannel.use_forward) + if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) && + ConfigChannel.use_forward) { if(dir != MODE_ADD) { @@ -1257,7 +1272,8 @@ remove_ban_list(struct Channel *chptr, struct Client *source_p, banptr = ptr->data; /* trailing space, and the mode letter itself */ - plen = strlen(banptr->banstr) + 2; + plen = strlen(banptr->banstr) + + (banptr->forward ? strlen(banptr->forward) + 1 : 0) + 2; if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4) { @@ -1275,7 +1291,10 @@ remove_ban_list(struct Channel *chptr, struct Client *source_p, *mbuf++ = c; cur_len += plen; - pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr); + if (banptr->forward) + pbuf += rb_sprintf(pbuf, "%s$%s ", banptr->banstr, banptr->forward); + else + pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr); count++; free_ban(banptr);