diff --git a/include/channel.h b/include/channel.h index 381e5e3..27b94b6 100644 --- a/include/channel.h +++ b/include/channel.h @@ -96,6 +96,7 @@ struct c_Metadata { const char *name; const char *value; + time_t timevalue; }; #define BANLEN 195 @@ -308,4 +309,10 @@ extern struct Metadata *channel_metadata_add(struct Channel *target, const char extern void channel_metadata_delete(struct Channel *target, const char *name, int propegate); extern struct Metadata *channel_metadata_find(struct Channel *target, const char *name); +extern struct Metadata *channel_metadata_add(struct Channel *target, const char *name, const char *value, int propegate); +extern struct Metadata *channel_metadata_time_add(struct Channel *target, const char *name, time_t value); +extern void channel_metadata_delete(struct Channel *target, const char *name, int propegate); +extern struct Metadata *channel_metadata_find(struct Channel *target, const char *name); + + #endif /* INCLUDED_channel_h */ diff --git a/include/numeric.h b/include/numeric.h index 0326926..d60f283 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -307,6 +307,8 @@ extern const char *form_str(int); #define ERR_NOCTCP 492 +#define ERR_KICKNOREJOIN 495 + #define ERR_UMODEUNKNOWNFLAG 501 #define ERR_USERSDONTMATCH 502 diff --git a/modules/core/m_kick.c b/modules/core/m_kick.c index 12bf5de..7255ba1 100644 --- a/modules/core/m_kick.c +++ b/modules/core/m_kick.c @@ -68,6 +68,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p char *comment; const char *name; char *p = NULL; + char *text = rb_strdup(""); const char *user; static char buf[BUFSIZE]; int is_override = 0; @@ -228,6 +229,12 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p ":%s KICK %s %s :%s", use_id(source_p), chptr->chname, use_id(who), comment); remove_user_from_channel(msptr); + + rb_sprintf(text, "K%s",who->name); + + /* we don't need to track NOKICK stuff unless it's our client being kicked */ + if(MyClient(source_p) && chptr->mode.mode & MODE_NOREJOIN) + channel_metadata_time_add(chptr, text, rb_current_time()); } else if (MyClient(source_p)) sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, diff --git a/src/channel.c b/src/channel.c index 156b6df..f8269fc 100644 --- a/src/channel.c +++ b/src/channel.c @@ -829,6 +829,9 @@ can_join(struct Client *source_p, struct Channel *chptr, char *key) int use_althost = 0; int i = 0; hook_data_channel moduledata; + struct c_Metadata *md; + struct DictionaryIter iter; + char *text = rb_strdup(""); s_assert(source_p->localClient != NULL); @@ -857,6 +860,24 @@ can_join(struct Client *source_p, struct Channel *chptr, char *key) if((is_banned(chptr, source_p, NULL, src_host, src_iphost)) == CHFL_BAN) return (ERR_BANNEDFROMCHAN); + rb_sprintf(text, "K%s",source_p->name); + + if(md = channel_metadata_find(chptr, text)) + { + if(md->timevalue + ConfigChannel.kick_no_rejoin_time > rb_current_time()) + { + return ERR_KICKNOREJOIN; + } + /* cleanup the channel's kicknorejoin metadata. */ + DICTIONARY_FOREACH(md, &iter, chptr->c_metadata) + { + text = rb_strdup(md->name); + if((text[0] == 'K') && (md->timevalue + ConfigChannel.kick_no_rejoin_time > rb_current_time())) + channel_metadata_delete(chptr, md->name, 1); + } + + } + if(chptr->mode.mode & MODE_INVITEONLY) { RB_DLINK_FOREACH(invite, source_p->user->invited.head) @@ -1912,7 +1933,7 @@ void user_join(struct Client * client_p, struct Client * source_p, const char * struct Metadata * channel_metadata_add(struct Channel *target, const char *name, const char *value, int propegate) { - struct Metadata *md; + struct c_Metadata *md; md = rb_malloc(sizeof(struct Metadata)); md->name = rb_strdup(name); @@ -1927,6 +1948,29 @@ channel_metadata_add(struct Channel *target, const char *name, const char *value return md; } +/* + * channel_metadata_time_add + * + * inputs - pointer to channel struct + * - name of metadata item you wish to add + * - time_t you wish to add + * output - none + * side effects - metadata is added to the channel in question + */ +struct Metadata * +channel_metadata_time_add(struct Channel *target, const char *name, time_t value) +{ + struct c_Metadata *md; + + md = rb_malloc(sizeof(struct c_Metadata)); + md->name = rb_strdup(name); + md->timevalue = value; + + irc_dictionary_add(target->c_metadata, md->name, md); + + return md; +} + /* * channel_metadata_delete * @@ -1939,7 +1983,7 @@ channel_metadata_add(struct Channel *target, const char *name, const char *value void channel_metadata_delete(struct Channel *target, const char *name, int propegate) { - struct Metadata *md = channel_metadata_find(target, name); + struct c_Metadata *md = channel_metadata_find(target, name); if(!md) return; diff --git a/src/messages.tab b/src/messages.tab index af25afd..ba4530d 100644 --- a/src/messages.tab +++ b/src/messages.tab @@ -516,7 +516,7 @@ static const char * replies[] = { /* 492 ERR_NOCTCP */ ":Can't send CTCP to %s (+C set)", /* 493 */ NULL, /* 494 */ NULL, -/* 495 */ NULL, +/* 495 ERR_KICKNOREJOIN */ ":%s 495 %s %s :Cannot rejoin channel so soon after being kicked (+J set)", /* 496 */ NULL, /* 497 */ NULL, /* 498 */ NULL, diff --git a/src/newconf.c b/src/newconf.c index 7a07675..665374f 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2269,7 +2269,7 @@ static struct ConfEntry conf_channel_table[] = { "use_forward", CF_YESNO, NULL, 0, &ConfigChannel.use_forward }, { "use_local_channels", CF_YESNO, NULL, 0, &ConfigChannel.use_local_channels }, { "resv_forcepart", CF_YESNO, NULL, 0, &ConfigChannel.resv_forcepart }, - { "kick_no_rejoin_time", CF_INT, NULL, 0, &ConfigChannel.kick_no_rejoin_time }, + { "kick_no_rejoin_time", CF_TIME, NULL, 0, &ConfigChannel.kick_no_rejoin_time }, { "exempt_cmode_c", CF_YESNO, NULL, 0, &ConfigChannel.exempt_cmode_c }, { "exempt_cmode_C", CF_YESNO, NULL, 0, &ConfigChannel.exempt_cmode_C }, { "exempt_cmode_D", CF_YESNO, NULL, 0, &ConfigChannel.exempt_cmode_D }, diff --git a/src/s_serv.c b/src/s_serv.c index 6693c2f..cc3db10 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -589,8 +589,10 @@ burst_TS6(struct Client *client_p) DICTIONARY_FOREACH(md, &iter, chptr->c_metadata) { - sendto_one(client_p, ":%s ENCAP * METADATA ADD %s %s :%s", - use_id(target_p), use_id(target_p), md->name, md->value); + /* don't bother bursting +J metadata */ + if(!(md->name[0] == 'K')) + sendto_one(client_p, ":%s ENCAP * METADATA ADD %s %s :%s", + use_id(target_p), use_id(target_p), md->name, md->value); } if(rb_dlink_list_length(&chptr->banlist) > 0)