]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - src/channel.c
Clean up cmode norepeat's metadata when unsetting +K.
[irc/rqf/shadowircd.git] / src / channel.c
index 991c0264645f2709e625a7d37f55cf8a483c44a8..ddc397cd5bfba83972f08c3f0cc258f6d1257b8a 100644 (file)
@@ -93,19 +93,19 @@ struct Channel *
 allocate_channel(const char *chname)
 {
        struct Channel *chptr;
-       struct Dictionary *c_metadata;
+       struct Dictionary *metadata;
        chptr = rb_bh_alloc(channel_heap);
        chptr->chname = rb_strdup(chname);
        
-       c_metadata = irc_dictionary_create(irccmp);
-       chptr->c_metadata = c_metadata;
+       metadata = irc_dictionary_create(irccmp);
+       chptr->metadata = metadata;
        return (chptr);
 }
 
 void
 free_channel(struct Channel *chptr)
 {
-       /* insert deletion of metadata here! */
+       channel_metadata_clear(chptr);
        rb_free(chptr->chname);
        rb_bh_free(channel_heap, chptr);
 }
@@ -829,6 +829,8 @@ can_join(struct Client *source_p, struct Channel *chptr, char *key)
        int use_althost = 0;
        int i = 0;
        hook_data_channel moduledata;
+       struct Metadata *md;
+       struct DictionaryIter iter;
 
        s_assert(source_p->localClient != NULL);
 
@@ -857,6 +859,15 @@ 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);
 
+       DICTIONARY_FOREACH(md, &iter, chptr->metadata)
+       {
+               if(!strcmp(md->name, "KICKNOREJOIN") && !strcmp(md->value, source_p->id) && (md->timevalue + ConfigChannel.kick_no_rejoin_time > rb_current_time()))
+                       return ERR_KICKNOREJOIN;
+               /* cleanup any stale KICKNOREJOIN metadata we find while we're at it */
+               if(!strcmp(md->name, "KICKNOREJOIN") && !(md->timevalue + ConfigChannel.kick_no_rejoin_time > rb_current_time()))  
+                       channel_metadata_delete(chptr, md->name, 0);
+       }
+
        if(chptr->mode.mode & MODE_INVITEONLY)
        {
                RB_DLINK_FOREACH(invite, source_p->user->invited.head)
@@ -1918,7 +1929,7 @@ channel_metadata_add(struct Channel *target, const char *name, const char *value
        md->name = rb_strdup(name);
        md->value = rb_strdup(value);
 
-       irc_dictionary_add(target->c_metadata, md->name, md);
+       irc_dictionary_add(target->metadata, md->name, md);
        
        if(propegate)
                sendto_match_servs(&me, "*", CAP_ENCAP, NOCAPS, "ENCAP * METADATA ADD %s %s :%s",
@@ -1927,6 +1938,31 @@ 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
+ *             - value 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 timevalue, const char *value)
+{
+       struct Metadata *md;
+
+       md = rb_malloc(sizeof(struct Metadata));
+       md->name = rb_strdup(name);
+       md->value = rb_strdup(value);
+       md->timevalue = timevalue;
+
+       irc_dictionary_add(target->metadata, md->name, md);
+
+       return md;
+}
+
 /*
  * channel_metadata_delete
  * 
@@ -1944,7 +1980,7 @@ channel_metadata_delete(struct Channel *target, const char *name, int propegate)
        if(!md)
                return;
 
-       irc_dictionary_delete(target->c_metadata, md->name);
+       irc_dictionary_delete(target->metadata, md->name);
 
        rb_free(md);
 
@@ -1967,8 +2003,27 @@ channel_metadata_find(struct Channel *target, const char *name)
        if(!target)
                return NULL;
 
-       if(!target->c_metadata)
+       if(!target->metadata)
                return NULL;
 
-       return irc_dictionary_retrieve(target->c_metadata, name);
+       return irc_dictionary_retrieve(target->metadata, name);
+}
+
+/*
+ * channel_metadata_clear
+ * 
+ * inputs      - pointer to channel struct
+ * output      - none
+ * side effects - metadata is cleared from the channel in question
+ */
+void
+channel_metadata_clear(struct Channel *chptr)
+{
+       struct Metadata *md;
+       struct DictionaryIter iter;
+       
+       DICTIONARY_FOREACH(md, &iter, chptr->metadata)
+       {
+               channel_metadata_delete(chptr, md->name, 0);
+       }
 }