mcabber/mcabber/caps.c
changeset 2337 ffd0e57e9563
parent 2268 f5402d705f67
equal deleted inserted replaced
2336:0dc317b5599d 2337:ffd0e57e9563
    28 
    28 
    29 typedef struct {
    29 typedef struct {
    30   char *category;
    30   char *category;
    31   char *type;
    31   char *type;
    32   char *name;
    32   char *name;
    33 } identity;
    33 } identity_t;
    34 
    34 
    35 typedef struct {
    35 typedef struct {
    36   GHashTable *fields;
    36   GHashTable *fields;
    37 } dataform;
    37 } dataform_t;
    38 
    38 
    39 typedef struct {
    39 typedef struct {
    40   GHashTable *identities;
    40   GHashTable *identities;
    41   GHashTable *features;
    41   GHashTable *features;
    42   GHashTable *forms;
    42   GHashTable *forms;
    43 } caps;
    43 } caps_t;
    44 
    44 
    45 static GHashTable *caps_cache = NULL;
    45 static GHashTable *caps_cache = NULL;
    46 
    46 
    47 void caps_destroy(gpointer data)
    47 void caps_destroy(gpointer data)
    48 {
    48 {
    49   caps *c = data;
    49   caps_t *c = data;
    50   g_hash_table_destroy(c->identities);
    50   g_hash_table_destroy(c->identities);
    51   g_hash_table_destroy(c->features);
    51   g_hash_table_destroy(c->features);
    52   g_hash_table_destroy(c->forms);
    52   g_hash_table_destroy(c->forms);
    53   g_free(c);
    53   g_free(c);
    54 }
    54 }
    55 
    55 
    56 void identity_destroy(gpointer data)
    56 void identity_destroy(gpointer data)
    57 {
    57 {
    58   identity *i = data;
    58   identity_t *i = data;
    59   g_free(i->category);
    59   g_free(i->category);
    60   g_free(i->type);
    60   g_free(i->type);
    61   g_free(i->name);
    61   g_free(i->name);
    62   g_free(i);
    62   g_free(i);
    63 }
    63 }
    64 
    64 
    65 void form_destroy(gpointer data)
    65 void form_destroy(gpointer data)
    66 {
    66 {
    67   dataform *f = data;
    67   dataform_t *f = data;
    68   g_hash_table_destroy(f->fields);
    68   g_hash_table_destroy(f->fields);
    69   g_free(f);
    69   g_free(f);
    70 }
    70 }
    71 
    71 
    72 void field_destroy(gpointer data)
    72 void field_destroy(gpointer data)
    93 
    93 
    94 void caps_add(const char *hash)
    94 void caps_add(const char *hash)
    95 {
    95 {
    96   if (!hash)
    96   if (!hash)
    97     return;
    97     return;
    98   caps *c = g_new0(caps, 1);
    98   caps_t *c = g_new0(caps_t, 1);
    99   c->features = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
    99   c->features = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
   100   c->identities = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, identity_destroy);
   100   c->identities = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, identity_destroy);
   101   c->forms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, form_destroy);
   101   c->forms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, form_destroy);
   102   g_hash_table_replace(caps_cache, g_strdup(hash), c);
   102   g_hash_table_replace(caps_cache, g_strdup(hash), c);
   103 }
   103 }
   111 
   111 
   112 /* if hash is not verified, this will bind capabilities set only with bare jid */
   112 /* if hash is not verified, this will bind capabilities set only with bare jid */
   113 void caps_move_to_local(char *hash, char *bjid)
   113 void caps_move_to_local(char *hash, char *bjid)
   114 {
   114 {
   115   char *orig_hash;
   115   char *orig_hash;
   116   caps *c = NULL;
   116   caps_t *c = NULL;
   117   if (!hash || !bjid)
   117   if (!hash || !bjid)
   118     return;
   118     return;
   119   g_hash_table_lookup_extended(caps_cache, hash, (gpointer*)&orig_hash, (gpointer*)&c);
   119   g_hash_table_lookup_extended(caps_cache, hash, (gpointer*)&orig_hash, (gpointer*)&c);
   120   if (c) {
   120   if (c) {
   121     g_hash_table_steal(caps_cache, hash);
   121     g_hash_table_steal(caps_cache, hash);
   128 }
   128 }
   129 
   129 
   130 /*if bjid is NULL, it will check only verified hashes */
   130 /*if bjid is NULL, it will check only verified hashes */
   131 int caps_has_hash(const char *hash, const char *bjid)
   131 int caps_has_hash(const char *hash, const char *bjid)
   132 {
   132 {
   133   caps *c = NULL;
   133   caps_t *c = NULL;
   134   if (!hash)
   134   if (!hash)
   135     return 0;
   135     return 0;
   136   c = g_hash_table_lookup(caps_cache, hash);
   136   c = g_hash_table_lookup(caps_cache, hash);
   137   if (!c && bjid) {
   137   if (!c && bjid) {
   138     char *key = g_strdup_printf("%s/#%s", bjid, hash);
   138     char *key = g_strdup_printf("%s/#%s", bjid, hash);
   146                        const char *category,
   146                        const char *category,
   147                        const char *name,
   147                        const char *name,
   148                        const char *type,
   148                        const char *type,
   149                        const char *lang)
   149                        const char *lang)
   150 {
   150 {
   151   caps *c;
   151   caps_t *c;
   152   if (!hash || !category || !type)
   152   if (!hash || !category || !type)
   153     return;
   153     return;
   154   if (!lang)
   154   if (!lang)
   155     lang = "";
   155     lang = "";
   156 
   156 
   157   c = g_hash_table_lookup(caps_cache, hash);
   157   c = g_hash_table_lookup(caps_cache, hash);
   158   if (c) {
   158   if (c) {
   159     identity *i = g_new0(identity, 1);
   159     identity_t *i = g_new0(identity_t, 1);
   160 
   160 
   161     i->category = g_strdup(category);
   161     i->category = g_strdup(category);
   162     i->name = g_strdup(name);
   162     i->name = g_strdup(name);
   163     i->type = g_strdup(type);
   163     i->type = g_strdup(type);
   164     g_hash_table_replace(c->identities, g_strdup(lang), i);
   164     g_hash_table_replace(c->identities, g_strdup(lang), i);
   173   caps_add_identity(hash, category, name, type, NULL);
   173   caps_add_identity(hash, category, name, type, NULL);
   174 }
   174 }
   175 
   175 
   176 void caps_add_dataform(const char *hash, const char *formtype)
   176 void caps_add_dataform(const char *hash, const char *formtype)
   177 {
   177 {
   178   caps *c;
   178   caps_t *c;
   179   if (!formtype)
   179   if (!formtype)
   180     return;
   180     return;
   181   c = g_hash_table_lookup(caps_cache, hash);
   181   c = g_hash_table_lookup(caps_cache, hash);
   182   if (c) {
   182   if (c) {
   183     dataform *d = g_new0(dataform, 1);
   183     dataform_t *d = g_new0(dataform_t, 1);
   184     char *f = g_strdup(formtype);
   184     char *f = g_strdup(formtype);
   185 
   185 
   186     d->fields = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, field_destroy);
   186     d->fields = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, field_destroy);
   187     g_hash_table_replace(c->forms, f, d);
   187     g_hash_table_replace(c->forms, f, d);
   188   }
   188   }
   194 }
   194 }
   195 
   195 
   196 void caps_add_dataform_field(const char *hash, const char *formtype,
   196 void caps_add_dataform_field(const char *hash, const char *formtype,
   197                              const char *field, const char *value)
   197                              const char *field, const char *value)
   198 {
   198 {
   199   caps *c;
   199   caps_t *c;
   200   if (!formtype || !field || !value)
   200   if (!formtype || !field || !value)
   201     return;
   201     return;
   202   c = g_hash_table_lookup(caps_cache, hash);
   202   c = g_hash_table_lookup(caps_cache, hash);
   203   if (c) {
   203   if (c) {
   204     dataform *d;
   204     dataform_t *d;
   205     d = g_hash_table_lookup(c->forms, formtype);
   205     d = g_hash_table_lookup(c->forms, formtype);
   206     if (d) {
   206     if (d) {
   207       gpointer key, val;
   207       gpointer key, val;
   208       char *f;
   208       char *f;
   209       GList *v = NULL;
   209       GList *v = NULL;
   219   }
   219   }
   220 }
   220 }
   221 
   221 
   222 void caps_add_feature(const char *hash, const char *feature)
   222 void caps_add_feature(const char *hash, const char *feature)
   223 {
   223 {
   224   caps *c;
   224   caps_t *c;
   225   if (!hash || !feature)
   225   if (!hash || !feature)
   226     return;
   226     return;
   227   c = g_hash_table_lookup(caps_cache, hash);
   227   c = g_hash_table_lookup(caps_cache, hash);
   228   if (c) {
   228   if (c) {
   229     char *f = g_strdup(feature);
   229     char *f = g_strdup(feature);
   234 /* If hash is verified, then bare jid is ignored.
   234 /* If hash is verified, then bare jid is ignored.
   235  * If there is no globally verified hash, and bare jid is not null,
   235  * If there is no globally verified hash, and bare jid is not null,
   236  * then local storage for that jid will be checked */
   236  * then local storage for that jid will be checked */
   237 int caps_has_feature(const char *hash, char *feature, char *bjid)
   237 int caps_has_feature(const char *hash, char *feature, char *bjid)
   238 {
   238 {
   239   caps *c = NULL;
   239   caps_t *c = NULL;
   240   if (!hash || !feature)
   240   if (!hash || !feature)
   241     return 0;
   241     return 0;
   242   c = g_hash_table_lookup(caps_cache, hash);
   242   c = g_hash_table_lookup(caps_cache, hash);
   243   if (!c && bjid) {
   243   if (!c && bjid) {
   244     char *key = g_strdup_printf("%s/#%s", bjid, hash);
   244     char *key = g_strdup_printf("%s/#%s", bjid, hash);
   258   _foreach_function(value, user_data);
   258   _foreach_function(value, user_data);
   259 }
   259 }
   260 
   260 
   261 void caps_foreach_feature(const char *hash, GFunc func, gpointer user_data)
   261 void caps_foreach_feature(const char *hash, GFunc func, gpointer user_data)
   262 {
   262 {
   263   caps *c;
   263   caps_t *c;
   264   if (!hash)
   264   if (!hash)
   265     return;
   265     return;
   266   c = g_hash_table_lookup(caps_cache, hash);
   266   c = g_hash_table_lookup(caps_cache, hash);
   267   if (!c)
   267   if (!c)
   268     return;
   268     return;
   276   GList *features, *langs;
   276   GList *features, *langs;
   277   GChecksum *sha1;
   277   GChecksum *sha1;
   278   guint8 digest[20];
   278   guint8 digest[20];
   279   gsize digest_size = 20;
   279   gsize digest_size = 20;
   280   gchar *hash, *old_hash = NULL;
   280   gchar *hash, *old_hash = NULL;
   281   caps *old_caps, *c;
   281   caps_t *old_caps, *c;
   282   gpointer key;
   282   gpointer key;
   283 
   283 
   284   if (!g_hash_table_lookup_extended(caps_cache, "", &key, (gpointer *)&c))
   284   if (!g_hash_table_lookup_extended(caps_cache, "", &key, (gpointer *)&c))
   285     return NULL;
   285     return NULL;
   286 
   286 
   290   sha1 = g_checksum_new(G_CHECKSUM_SHA1);
   290   sha1 = g_checksum_new(G_CHECKSUM_SHA1);
   291 
   291 
   292   langs = g_hash_table_get_keys(c->identities);
   292   langs = g_hash_table_get_keys(c->identities);
   293   langs = g_list_sort(langs, _strcmp_sort);
   293   langs = g_list_sort(langs, _strcmp_sort);
   294   {
   294   {
   295     identity *i;
   295     identity_t *i;
   296     GList *lang;
   296     GList *lang;
   297     char *identity_S;
   297     char *identity_S;
   298     for (lang=langs; lang; lang=lang->next) {
   298     for (lang=langs; lang; lang=lang->next) {
   299       i = g_hash_table_lookup(c->identities, lang->data);
   299       i = g_hash_table_lookup(c->identities, lang->data);
   300       identity_S = g_strdup_printf("%s/%s/%s/%s<", i->category, i->type,
   300       identity_S = g_strdup_printf("%s/%s/%s/%s<", i->category, i->type,
   334   GChecksum *checksum;
   334   GChecksum *checksum;
   335   guint8 digest[20];
   335   guint8 digest[20];
   336   gsize digest_size = 20;
   336   gsize digest_size = 20;
   337   gchar *local_hash;
   337   gchar *local_hash;
   338   gboolean match = FALSE;
   338   gboolean match = FALSE;
   339   caps *c = g_hash_table_lookup(caps_cache, hash);
   339   caps_t *c = g_hash_table_lookup(caps_cache, hash);
   340 
   340 
   341   if (!g_strcmp0(function, "sha-1")) {
   341   if (!g_strcmp0(function, "sha-1")) {
   342     checksum = g_checksum_new(G_CHECKSUM_SHA1);
   342     checksum = g_checksum_new(G_CHECKSUM_SHA1);
   343   } else if (!g_strcmp0(function, "md5")) {
   343   } else if (!g_strcmp0(function, "md5")) {
   344     checksum = g_checksum_new(G_CHECKSUM_MD5);
   344     checksum = g_checksum_new(G_CHECKSUM_MD5);
   347     return FALSE;
   347     return FALSE;
   348 
   348 
   349   langs = g_hash_table_get_keys(c->identities);
   349   langs = g_hash_table_get_keys(c->identities);
   350   langs = g_list_sort(langs, _strcmp_sort);
   350   langs = g_list_sort(langs, _strcmp_sort);
   351   {
   351   {
   352     identity *i;
   352     identity_t *i;
   353     GList *lang;
   353     GList *lang;
   354     char *identity_S;
   354     char *identity_S;
   355     for (lang=langs; lang; lang=lang->next) {
   355     for (lang=langs; lang; lang=lang->next) {
   356       i = g_hash_table_lookup(c->identities, lang->data);
   356       i = g_hash_table_lookup(c->identities, lang->data);
   357       identity_S = g_strdup_printf("%s/%s/%s/%s<", i->category, i->type,
   357       identity_S = g_strdup_printf("%s/%s/%s/%s<", i->category, i->type,
   374   g_list_free(features);
   374   g_list_free(features);
   375 
   375 
   376   forms = g_hash_table_get_keys(c->forms);
   376   forms = g_hash_table_get_keys(c->forms);
   377   forms = g_list_sort(forms, _strcmp_sort);
   377   forms = g_list_sort(forms, _strcmp_sort);
   378   {
   378   {
   379     dataform *d;
   379     dataform_t *d;
   380     GList *form, *fields;
   380     GList *form, *fields;
   381     for (form=forms; form; form=form->next) {
   381     for (form=forms; form; form=form->next) {
   382       d = g_hash_table_lookup(c->forms, form->data);
   382       d = g_hash_table_lookup(c->forms, form->data);
   383       g_checksum_update(checksum, form->data, -1);
   383       g_checksum_update(checksum, form->data, -1);
   384       g_checksum_update(checksum, (guchar *)"<", -1);
   384       g_checksum_update(checksum, (guchar *)"<", -1);
   444 void caps_copy_to_persistent(const char* hash, char* xml)
   444 void caps_copy_to_persistent(const char* hash, char* xml)
   445 {
   445 {
   446   gchar *file;
   446   gchar *file;
   447   GList *features, *langs, *forms;
   447   GList *features, *langs, *forms;
   448   GKeyFile *key_file;
   448   GKeyFile *key_file;
   449   caps *c;
   449   caps_t *c;
   450   int fd;
   450   int fd;
   451 
   451 
   452   g_free (xml);
   452   g_free (xml);
   453 
   453 
   454   c = g_hash_table_lookup (caps_cache, hash);
   454   c = g_hash_table_lookup (caps_cache, hash);
   468                           "This is autogenerated file. Please do not modify.",
   468                           "This is autogenerated file. Please do not modify.",
   469                           NULL);
   469                           NULL);
   470 
   470 
   471   langs = g_hash_table_get_keys (c->identities);
   471   langs = g_hash_table_get_keys (c->identities);
   472   {
   472   {
   473     identity *i;
   473     identity_t *i;
   474     GList *lang;
   474     GList *lang;
   475     gchar *group;
   475     gchar *group;
   476     for (lang=langs; lang; lang=lang->next) {
   476     for (lang=langs; lang; lang=lang->next) {
   477       i = g_hash_table_lookup (c->identities, lang->data);
   477       i = g_hash_table_lookup (c->identities, lang->data);
   478       group = g_strdup_printf("identity_%s", (gchar *)lang->data);
   478       group = g_strdup_printf("identity_%s", (gchar *)lang->data);
   505   }
   505   }
   506   g_list_free (features);
   506   g_list_free (features);
   507 
   507 
   508   forms = g_hash_table_get_keys(c->forms);
   508   forms = g_hash_table_get_keys(c->forms);
   509   {
   509   {
   510     dataform *d;
   510     dataform_t *d;
   511     GList *form, *fields;
   511     GList *form, *fields;
   512     gchar *group;
   512     gchar *group;
   513     for (form=forms; form; form=form->next) {
   513     for (form=forms; form; form=form->next) {
   514       d = g_hash_table_lookup (c->forms, form->data);
   514       d = g_hash_table_lookup (c->forms, form->data);
   515       group = g_strdup_printf ("form_%s", (gchar *)form->data);
   515       group = g_strdup_printf ("form_%s", (gchar *)form->data);