]> jfr.im git - irc/rqf/shadowircd.git/commitdiff
Add user metadata.
authorB.Greenham <redacted>
Thu, 4 Mar 2010 01:38:50 +0000 (20:38 -0500)
committerB.Greenham <redacted>
Thu, 4 Mar 2010 01:38:50 +0000 (20:38 -0500)
include/client.h
modules/Makefile.in
src/client.c
src/modules.c
src/s_serv.c
src/s_user.c

index 38a0ca9c03db91fdf3857597acf43cc25b2675f2..07cf7165ce0d12ebeff1c0325087a22bbbc74a91 100644 (file)
@@ -84,6 +84,8 @@ struct User
        char *away;             /* pointer to away message */
        int refcnt;             /* Number of times this block is referenced */
 
+       struct Dictionary *metadata;
+
        char suser[NICKLEN+1];
 };
 
@@ -311,6 +313,12 @@ struct ListClient
         */
 };
 
+struct Metadata
+{
+       const char *name;
+       const char *value;
+};
+
 /*
  * status macros.
  */
@@ -613,4 +621,8 @@ extern char *generate_uid(void);
 void allocate_away(struct Client *);
 void free_away(struct Client *);
 
+extern struct Metadata *user_metadata_add(struct Client *target, const char *name, const char *value, int propegate);
+extern void user_metadata_delete(struct Client *target, const char *name, int propegate);
+extern struct Metadata *user_metadata_find(struct Client *target, const char *name);
+
 #endif /* INCLUDED_client_h */
index dd9666448e38210078f04cf040bc5cb0063d74bb..6c80e2178dbb5c0a359b9cc54b17a9479ad83075 100644 (file)
@@ -42,6 +42,7 @@ CORE_SRCS = \
   core/m_kick.c \
   core/m_kill.c \
   core/m_message.c \
+  core/m_metadata.c \
   core/m_mode.c \
   core/m_nick.c \
   core/m_part.c \
index cad1b7f5a4b51f2dee94e36026a771b35f1a3943..d22c7ef8c562cc8d9cecdd92663b4edb0e6ecb5d 100644 (file)
@@ -1659,6 +1659,7 @@ struct User *
 make_user(struct Client *client_p)
 {
        struct User *user;
+       struct Dictionary *metadata;
 
        user = client_p->user;
        if(!user)
@@ -1666,6 +1667,9 @@ make_user(struct Client *client_p)
                user = (struct User *) rb_bh_alloc(user_heap);
                user->refcnt = 1;
                client_p->user = user;
+
+               metadata = irc_dictionary_create(irccmp);
+               client_p->user->metadata = metadata;
        }
        return user;
 }
@@ -1705,10 +1709,19 @@ free_user(struct User *user, struct Client *client_p)
 {
        free_away(client_p);
 
+       /* get rid of any metadata the user may have */
+       if(IsOper(client_p))
+       {
+               user_metadata_delete(client_p, "swhois", 0);
+               user_metadata_delete(client_p, "operstring", 0);
+       }
+       user_metadata_delete(client_p, "OACCEPT", 0);
+
        if(--user->refcnt <= 0)
        {
                if(user->away)
                        rb_free((char *) user->away);
+               
                /*
                 * sanity check
                 */
@@ -1924,3 +1937,81 @@ error_exit_client(struct Client *client_p, int error)
 
        exit_client(client_p, client_p, &me, errmsg);
 }
+
+/*
+ * user_metadata_add
+ * 
+ * inputs      - pointer to client 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 user in question
+ *             - metadata is propegated if propegate is set.
+ */
+struct Metadata *
+user_metadata_add(struct Client *target, const char *name, const char *value, int propegate)
+{
+       struct Metadata *md;
+
+       if(irc_dictionary_find(target->user->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->user->metadata, md->name, md);
+       
+       if(propegate)
+               sendto_match_servs(&me, "*", CAP_ENCAP, NOCAPS, "ENCAP * METADATA ADD %s %s :%s",
+                               target->name, name, value);
+
+       return md;
+}
+
+/*
+ * user_metadata_delete
+ * 
+ * inputs      - pointer to client struct
+ *             - name of metadata item you wish to delete
+ * output      - none
+ * side effects - metadata is deleted from the user in question
+ *             - deletion is propegated if propegate is set
+ */
+void
+user_metadata_delete(struct Client *target, const char *name, int propegate)
+{
+       struct Metadata *md = user_metadata_find(target, name);
+
+       if(!md)
+               return;
+
+       irc_dictionary_delete(target->user->metadata, md->name);
+
+       rb_free(md);
+
+       if(propegate)
+               sendto_match_servs(&me, "*", CAP_ENCAP, NOCAPS, "ENCAP * METADATA DELETE %s %s",
+                               target->name, name);
+}
+
+/*
+ * user_metadata_find
+ * 
+ * inputs      - pointer to client struct
+ *             - name of metadata item you wish to read
+ * output      - the requested metadata, if it exists, elsewise null.
+ * side effects - 
+ */
+struct Metadata *
+user_metadata_find(struct Client *target, const char *name)
+{
+       if(!target->user)
+               return NULL;
+
+       if(!target->user->metadata)
+               return NULL;
+
+       return irc_dictionary_retrieve(target->user->metadata, name);
+}
index ba56c96553c166e8a8b6ffbd3ce5ccc8bed7613c..4547e42dfca95fba830d8c7e29891e7da41a5f3e 100644 (file)
@@ -63,6 +63,7 @@ static const char *core_module_table[] = {
        "m_kick",
        "m_kill",
        "m_message",
+       "m_metadata",
        "m_mode",
        "m_nick",
        "m_part",
index 0cd1369401dd1166f1653eef606571a00ed78b38..e66c02114b237274a6ef49ecb3e44af22505483b 100644 (file)
@@ -54,6 +54,7 @@
 #include "msg.h"
 #include "reject.h"
 #include "sslproc.h"
+#include "irc_dictionary.h"
 
 #ifndef INADDR_NONE
 #define INADDR_NONE ((unsigned int) 0xffffffff)
@@ -469,6 +470,8 @@ burst_TS6(struct Client *client_p)
        char *t;
        int tlen, mlen;
        int cur_len = 0;
+       struct Metadata *md;
+       struct DictionaryIter iter;
 
        hclientinfo.client = hchaninfo.client = client_p;
 
@@ -520,6 +523,12 @@ burst_TS6(struct Client *client_p)
                                                use_id(target_p), target_p->user->suser);
                }
 
+               DICTIONARY_FOREACH(md, &iter, target_p->user->metadata)
+               {
+                       sendto_one(client_p, ":%s ENCAP * METADATA %s %s :%s",
+                                  use_id(target_p), use_id(target_p), md->name, md->value);
+               }
+
                if(ConfigFileEntry.burst_away && !EmptyString(target_p->user->away))
                        sendto_one(client_p, ":%s AWAY :%s",
                                   use_id(target_p),
index d5f163d0fdcfb31588d1ec1c0c1ba68434085d21..04b1838d90e841086946e7f9b3d573997b1f8f49 100644 (file)
@@ -1031,6 +1031,11 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
 
                                Count.oper--;
 
+                               /* Do we need to propegate these? I'm not 100% sure
+                                * so we should test it when we have a testnet */
+                               user_metadata_delete(source_p, "OPERSTRING", 1);
+                               user_metadata_delete(source_p, "SWHOIS", 1);
+
                                if(MyConnect(source_p))
                                {
                                        source_p->umodes &= ~ConfigFileEntry.oper_only_umodes;