From 6f659342dcffe7019f480223fe1ebb55a78818b6 Mon Sep 17 00:00:00 2001 From: "B.Greenham" Date: Thu, 4 Mar 2010 15:08:16 -0500 Subject: [PATCH] Add channel metadata system. --- include/channel.h | 12 ++++++ modules/core/m_metadata.c | 36 ++++++++++++----- src/channel.c | 84 +++++++++++++++++++++++++++++++++++++++ src/s_serv.c | 8 +++- 4 files changed, 129 insertions(+), 11 deletions(-) diff --git a/include/channel.h b/include/channel.h index 1cbcb1d..381e5e3 100644 --- a/include/channel.h +++ b/include/channel.h @@ -72,6 +72,8 @@ struct Channel unsigned int join_count; /* joins within delta */ unsigned int join_delta; /* last ts of join */ + struct Dictionary *c_metadata; + unsigned long bants; time_t channelts; char *chname; @@ -90,6 +92,12 @@ struct membership unsigned long bants; }; +struct c_Metadata +{ + const char *name; + const char *value; +}; + #define BANLEN 195 struct Ban { @@ -296,4 +304,8 @@ extern void user_join(struct Client * client_p, struct Client * source_p, const extern void do_join_0(struct Client *client_p, struct Client *source_p); extern int check_channel_name_loc(struct Client *source_p, const char *name); +extern struct Metadata *channel_metadata_add(struct Channel *target, const char *name, const char *value, int propegate); +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/modules/core/m_metadata.c b/modules/core/m_metadata.c index 889bd88..dc85dfb 100644 --- a/modules/core/m_metadata.c +++ b/modules/core/m_metadata.c @@ -33,16 +33,32 @@ DECLARE_MODULE_AV1(metadata, NULL, NULL, metadata_clist, NULL, NULL, "$Revision$ void me_metadata(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - struct Client *target_p; + if(parv[2][0] == '#') + { + struct Channel *chptr; - if((target_p = find_client(parv[2])) == NULL) - return; + if((chptr = find_channel(parv[2])) == NULL) + return; - if(!target_p->user) - return; + if(!strcmp(parv[1], "ADD") && parv[4] != NULL) + channel_metadata_add(chptr, parv[3], parv[4], 0); + if(!strcmp(parv[1], "DELETE") && parv[3] != NULL) + channel_metadata_delete(chptr, parv[3], 0); + } - if(!strcmp(parv[1], "ADD") && parv[4] != NULL) - user_metadata_add(target_p, parv[3], parv[4], 0); - if(!strcmp(parv[1], "DELETE") && parv[3] != NULL) - user_metadata_delete(target_p, parv[3], 0); -} \ No newline at end of file + else + { + struct Client *target_p; + + if((target_p = find_client(parv[2])) == NULL) + return; + + if(!target_p->user) + return; + + if(!strcmp(parv[1], "ADD") && parv[4] != NULL) + user_metadata_add(target_p, parv[3], parv[4], 0); + if(!strcmp(parv[1], "DELETE") && parv[3] != NULL) + user_metadata_delete(target_p, parv[3], 0); + } +} diff --git a/src/channel.c b/src/channel.c index 4dd6b82..44c8d9f 100644 --- a/src/channel.c +++ b/src/channel.c @@ -42,6 +42,7 @@ #include "s_newconf.h" #include "logger.h" #include "packet.h" +#include "irc_dictionary.h" struct config_channel_entry ConfigChannel; rb_dlink_list global_channel_list; @@ -92,14 +93,19 @@ struct Channel * allocate_channel(const char *chname) { struct Channel *chptr; + struct Dictionary *c_metadata; chptr = rb_bh_alloc(channel_heap); chptr->chname = rb_strdup(chname); + + c_metadata = irc_dictionary_create(irccmp); + chptr->c_metadata = c_metadata; return (chptr); } void free_channel(struct Channel *chptr) { + /* insert deletion of metadata here! */ rb_free(chptr->chname); rb_bh_free(channel_heap, chptr); } @@ -1891,3 +1897,81 @@ void user_join(struct Client * client_p, struct Client * source_p, const char * return; } + +/* + * channel_metadata_add + * + * inputs - pointer to channel struct + * - name of metadata item you wish to add + * - value of metadata item + * - 1 if metadata should be propegated, 0 if not + * output - none + * side effects - metadata is added to the channel in question + * - metadata is propegated if propegate is set. + */ +struct Metadata * +channel_metadata_add(struct Channel *target, const char *name, const char *value, int propegate) +{ + struct Metadata *md; + + if(irc_dictionary_find(target->c_metadata, name) != NULL) + return NULL; + + md = rb_malloc(sizeof(struct Metadata)); + md->name = rb_strdup(name); + md->value = rb_strdup(value); + + irc_dictionary_add(target->c_metadata, md->name, md); + + if(propegate) + sendto_match_servs(&me, "*", CAP_ENCAP, NOCAPS, "ENCAP * METADATA ADD %s %s :%s", + target->chname, name, value); + + return md; +} + +/* + * channel_metadata_delete + * + * inputs - pointer to channel struct + * - name of metadata item you wish to delete + * output - none + * side effects - metadata is deleted from the channel in question + * - deletion is propegated if propegate is set + */ +void +channel_metadata_delete(struct Channel *target, const char *name, int propegate) +{ + struct Metadata *md = channel_metadata_find(target, name); + + if(!md) + return; + + irc_dictionary_delete(target->c_metadata, md->name); + + rb_free(md); + + if(propegate) + sendto_match_servs(&me, "*", CAP_ENCAP, NOCAPS, "ENCAP * METADATA DELETE %s %s", + target->chname, name); +} + +/* + * channel_metadata_find + * + * inputs - pointer to channel struct + * - name of metadata item you wish to read + * output - the requested metadata, if it exists, elsewise null. + * side effects - + */ +struct Metadata * +channel_metadata_find(struct Channel *target, const char *name) +{ + if(!target) + return NULL; + + if(!target->c_metadata) + return NULL; + + return irc_dictionary_retrieve(target->c_metadata, name); +} diff --git a/src/s_serv.c b/src/s_serv.c index e66c021..6693c2f 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -525,7 +525,7 @@ burst_TS6(struct Client *client_p) DICTIONARY_FOREACH(md, &iter, target_p->user->metadata) { - sendto_one(client_p, ":%s ENCAP * METADATA %s %s :%s", + sendto_one(client_p, ":%s ENCAP * METADATA ADD %s %s :%s", use_id(target_p), use_id(target_p), md->name, md->value); } @@ -587,6 +587,12 @@ burst_TS6(struct Client *client_p) } sendto_one(client_p, "%s", buf); + 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); + } + if(rb_dlink_list_length(&chptr->banlist) > 0) burst_modes_TS6(client_p, chptr, &chptr->banlist, 'b');