mcabber/src/caps.c
changeset 1600 c5ee395fbc8c
child 1645 d3cd4db23f55
equal deleted inserted replaced
1599:dcd5d4c75199 1600:c5ee395fbc8c
       
     1 /*
       
     2  * caps.c       -- Entity Capabilities Cache for mcabber
       
     3  *
       
     4  * Copyright (C) 2008 Frank Zschockelt <mcabber@freakysoft.de>
       
     5  *
       
     6  * This program is free software; you can redistribute it and/or modify
       
     7  * it under the terms of the GNU General Public License as published by
       
     8  * the Free Software Foundation; either version 2 of the License, or (at
       
     9  * your option) any later version.
       
    10  *
       
    11  * This program is distributed in the hope that it will be useful, but
       
    12  * WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License
       
    17  * along with this program; if not, write to the Free Software
       
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
       
    19  * USA
       
    20  */
       
    21 
       
    22 #include <glib.h>
       
    23 
       
    24 typedef struct {
       
    25   char *category;
       
    26   char *name;
       
    27   char *type;
       
    28   GHashTable *features;
       
    29 } caps;
       
    30 
       
    31 static GHashTable *caps_cache = NULL;
       
    32 
       
    33 void caps_destroy(gpointer data)
       
    34 {
       
    35   caps *c = data;
       
    36   g_free(c->category);
       
    37   g_free(c->name);
       
    38   g_free(c->type);
       
    39   g_hash_table_destroy(c->features);
       
    40   g_free(c);
       
    41 }
       
    42 
       
    43 void caps_init(void)
       
    44 {
       
    45   if (!caps_cache)
       
    46     caps_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
       
    47                                        g_free, caps_destroy);
       
    48 }
       
    49 
       
    50 void caps_free(void)
       
    51 {
       
    52   if (caps_cache) {
       
    53     g_hash_table_destroy(caps_cache);
       
    54     caps_cache = NULL;
       
    55   }
       
    56 }
       
    57 
       
    58 void caps_add(char *hash)
       
    59 {
       
    60   if (!hash)
       
    61     return;
       
    62   caps *c = g_new0(caps, 1);
       
    63   c->features = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
       
    64   g_hash_table_insert(caps_cache, g_strdup(hash), c);
       
    65 }
       
    66 
       
    67 int caps_has_hash(const char *hash)
       
    68 {
       
    69   return (hash != NULL && (g_hash_table_lookup(caps_cache, hash) != NULL));
       
    70 }
       
    71 
       
    72 void caps_set_identity(char *hash,
       
    73                        const char *category,
       
    74                        const char *name,
       
    75                        const char *type)
       
    76 {
       
    77   caps *c;
       
    78   if (!hash)
       
    79     return;
       
    80 
       
    81   c = g_hash_table_lookup(caps_cache, hash);
       
    82   if (c) {
       
    83     c->category = g_strdup(category);
       
    84     c->name = g_strdup(name);
       
    85     c->type = g_strdup(type);
       
    86   }
       
    87 }
       
    88 
       
    89 void caps_add_feature(char *hash, const char *feature)
       
    90 {
       
    91   caps *c;
       
    92   if (!hash)
       
    93     return;
       
    94   c = g_hash_table_lookup(caps_cache, hash);
       
    95   if (c) {
       
    96     char *f = g_strdup(feature);
       
    97     g_hash_table_insert(c->features, f, f);
       
    98   }
       
    99 }
       
   100 
       
   101 int caps_has_feature(char *hash, char *feature)
       
   102 {
       
   103   caps *c;
       
   104   if (!hash)
       
   105     return 0;
       
   106   c = g_hash_table_lookup(caps_cache, hash);
       
   107   if (c)
       
   108     return (g_hash_table_lookup(c->features, feature) != NULL);
       
   109   return 0;
       
   110 }
       
   111 
       
   112 static GFunc _foreach_function;
       
   113 
       
   114 void _caps_foreach_helper(gpointer key, gpointer value, gpointer user_data)
       
   115 {
       
   116   // GFunc func = (GFunc)user_data;
       
   117   _foreach_function(value, user_data);
       
   118 }
       
   119 
       
   120 void caps_foreach_feature(const char *hash, GFunc func, gpointer user_data)
       
   121 {
       
   122   caps *c;
       
   123   if (!hash)
       
   124     return;
       
   125   c = g_hash_table_lookup(caps_cache, hash);
       
   126   if (!c)
       
   127     return;
       
   128   _foreach_function = func;
       
   129   g_hash_table_foreach(c->features, _caps_foreach_helper, user_data);
       
   130 }
       
   131 
       
   132 gint _strcmp_sort(gconstpointer a, gconstpointer b)
       
   133 {
       
   134   return g_strcmp0(a, b);
       
   135 }
       
   136 
       
   137 //generates the sha1 hash for the special capability "" and returns it
       
   138 const char *caps_generate(void)
       
   139 {
       
   140   char *identity;
       
   141   GList *features;
       
   142   GChecksum *sha1;
       
   143   guint8 digest[20];
       
   144   gsize digest_size = 20;
       
   145   gchar *hash, *old_hash = NULL;
       
   146   caps *old_caps;
       
   147   unsigned int i;
       
   148   caps *c = g_hash_table_lookup(caps_cache, "");
       
   149 
       
   150   g_hash_table_steal(caps_cache, "");
       
   151   sha1 = g_checksum_new(G_CHECKSUM_SHA1);
       
   152   identity = g_strdup_printf("%s/%s/%s<", c->category, c->type, c->name);
       
   153   g_checksum_update(sha1, (guchar*)identity, -1);
       
   154   g_free(identity);
       
   155 
       
   156   features = g_list_copy(g_hash_table_get_values(c->features));
       
   157   features = g_list_sort(features, _strcmp_sort);
       
   158   for (i=0; i < g_list_length(features); i++) {
       
   159     g_checksum_update(sha1, g_list_nth_data(features, i), -1);
       
   160     g_checksum_update(sha1, (guchar *)"<", -1);
       
   161   }
       
   162   g_list_free(features);
       
   163 
       
   164   g_checksum_get_digest(sha1, digest, &digest_size);
       
   165   hash = g_base64_encode(digest, digest_size);
       
   166   g_checksum_free(sha1);
       
   167   g_hash_table_lookup_extended(caps_cache, hash,
       
   168                                (gpointer *)&old_hash, (gpointer *)&old_caps);
       
   169   g_hash_table_insert(caps_cache, hash, c);
       
   170   if (old_hash)
       
   171     return old_hash;
       
   172   else
       
   173     return hash;
       
   174 }
       
   175 
       
   176 /* vim: set expandtab cindent cinoptions=>2\:2(0:  For Vim users... */