comparison libpurple/protocols/jabber/caps.c @ 25025:a85f9b85a7fb

* changed storage format for cache to mirror all needed features for XEP-0115v1.5 * exlcuded all shortnames (ext-attribute) realed functions; mostly storage/loading functions. Will be removed completely later.
author Tobias Markmann <tfar@soc.pidgin.im>
date Fri, 04 Jul 2008 19:11:09 +0000
parents fd19927e2b64
children e61603ab10c6
comparison
equal deleted inserted replaced
25024:fd19927e2b64 25025:a85f9b85a7fb
35 static gchar *caps_hash = NULL; 35 static gchar *caps_hash = NULL;
36 36
37 typedef struct _JabberCapsKey { 37 typedef struct _JabberCapsKey {
38 char *node; 38 char *node;
39 char *ver; 39 char *ver;
40 char *hash;
40 } JabberCapsKey; 41 } JabberCapsKey;
41 42
42 typedef struct _JabberCapsValueExt { 43 #if 0
43 GList *identities; /* JabberCapsIdentity */
44 GList *features; /* char * */
45 GList *xdatas; /* xmlnode * */
46 } JabberCapsValueExt;
47
48 typedef struct _JabberCapsValue { 44 typedef struct _JabberCapsValue {
49 GList *identities; /* JabberCapsIdentity */ 45 GList *identities; /* JabberCapsIdentity */
50 GList *features; /* char * */ 46 GList *features; /* char * */
51 GHashTable *ext; /* char * -> JabberCapsValueExt */ 47 GHashTable *ext; /* char * -> JabberCapsValueExt */
52 } JabberCapsValue; 48 } JabberCapsValue;
49 #endif
50 typedef struct _JabberCapsClientInfo JabberCapsValue;
53 51
54 static guint jabber_caps_hash(gconstpointer key) { 52 static guint jabber_caps_hash(gconstpointer key) {
55 const JabberCapsKey *name = key; 53 const JabberCapsKey *name = key;
56 guint nodehash = g_str_hash(name->node); 54 guint nodehash = g_str_hash(name->node);
57 guint verhash = g_str_hash(name->ver); 55 guint verhash = g_str_hash(name->ver);
68 66
69 static void jabber_caps_destroy_key(gpointer key) { 67 static void jabber_caps_destroy_key(gpointer key) {
70 JabberCapsKey *keystruct = key; 68 JabberCapsKey *keystruct = key;
71 g_free(keystruct->node); 69 g_free(keystruct->node);
72 g_free(keystruct->ver); 70 g_free(keystruct->ver);
71 g_free(keystruct->hash);
73 g_free(keystruct); 72 g_free(keystruct);
74 } 73 }
75 74
76 static void jabber_caps_destroy_value(gpointer value) { 75 static void jabber_caps_destroy_value(gpointer value) {
77 JabberCapsValue *valuestruct = value; 76 JabberCapsValue *valuestruct = value;
86 } 85 }
87 while(valuestruct->features) { 86 while(valuestruct->features) {
88 g_free(valuestruct->features->data); 87 g_free(valuestruct->features->data);
89 valuestruct->features = g_list_delete_link(valuestruct->features,valuestruct->features); 88 valuestruct->features = g_list_delete_link(valuestruct->features,valuestruct->features);
90 } 89 }
91 g_hash_table_destroy(valuestruct->ext); 90
91 while(valuestruct->forms) {
92 g_free(valuestruct->forms->data);
93 valuestruct->forms = g_list_delete_link(valuestruct->forms,valuestruct->forms);
94 }
95 //g_hash_table_destroy(valuestruct->ext);
92 g_free(valuestruct); 96 g_free(valuestruct);
93 } 97 }
94 98
95 static void jabber_caps_ext_destroy_value(gpointer value) { 99 static void jabber_caps_ext_destroy_value(gpointer value) {
96 JabberCapsValueExt *valuestruct = value; 100 JabberCapsValueExt *valuestruct = value;
137 JabberCapsKey *key = g_new0(JabberCapsKey, 1); 141 JabberCapsKey *key = g_new0(JabberCapsKey, 1);
138 JabberCapsValue *value = g_new0(JabberCapsValue, 1); 142 JabberCapsValue *value = g_new0(JabberCapsValue, 1);
139 xmlnode *child; 143 xmlnode *child;
140 key->node = g_strdup(xmlnode_get_attrib(client,"node")); 144 key->node = g_strdup(xmlnode_get_attrib(client,"node"));
141 key->ver = g_strdup(xmlnode_get_attrib(client,"ver")); 145 key->ver = g_strdup(xmlnode_get_attrib(client,"ver"));
142 value->ext = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, jabber_caps_ext_destroy_value); 146 key->hash = g_strdup(xmlnode_get_attrib(client,"hash"));
143 for(child = client->child; child; child = child->next) { 147 for(child = client->child; child; child = child->next) {
144 if(child->type != XMLNODE_TYPE_TAG) 148 if(child->type != XMLNODE_TYPE_TAG)
145 continue; 149 continue;
146 if(!strcmp(child->name,"feature")) { 150 if(!strcmp(child->name,"feature")) {
147 const char *var = xmlnode_get_attrib(child, "var"); 151 const char *var = xmlnode_get_attrib(child, "var");
157 id->category = g_strdup(category); 161 id->category = g_strdup(category);
158 id->type = g_strdup(type); 162 id->type = g_strdup(type);
159 id->name = g_strdup(name); 163 id->name = g_strdup(name);
160 164
161 value->identities = g_list_append(value->identities,id); 165 value->identities = g_list_append(value->identities,id);
162 } else if(!strcmp(child->name,"ext")) { 166 } else if(!strcmp(child->name,"x")) {
163 const char *identifier = xmlnode_get_attrib(child, "identifier"); 167 value->forms = g_list_append(value->forms, xmlnode_copy(child));
164 if(identifier) {
165 xmlnode *extchild;
166
167 JabberCapsValueExt *extvalue = g_new0(JabberCapsValueExt, 1);
168
169 for(extchild = child->child; extchild; extchild = extchild->next) {
170 if(extchild->type != XMLNODE_TYPE_TAG)
171 continue;
172 if(!strcmp(extchild->name,"feature")) {
173 const char *var = xmlnode_get_attrib(extchild, "var");
174 if(!var)
175 continue;
176 extvalue->features = g_list_append(extvalue->features,g_strdup(var));
177 } else if(!strcmp(extchild->name,"identity")) {
178 const char *category = xmlnode_get_attrib(extchild, "category");
179 const char *type = xmlnode_get_attrib(extchild, "type");
180 const char *name = xmlnode_get_attrib(extchild, "name");
181
182 JabberCapsIdentity *id = g_new0(JabberCapsIdentity, 1);
183 id->category = g_strdup(category);
184 id->type = g_strdup(type);
185 id->name = g_strdup(name);
186
187 extvalue->identities = g_list_append(extvalue->identities,id);
188 }
189 }
190 g_hash_table_replace(value->ext, g_strdup(identifier), extvalue);
191 }
192 } 168 }
193 } 169 }
194 g_hash_table_replace(capstable, key, value); 170 g_hash_table_replace(capstable, key, value);
195 } 171 }
196 } 172 }
197 xmlnode_free(capsdata); 173 xmlnode_free(capsdata);
198 } 174 }
199 175
176 #if 0
200 static void jabber_caps_store_ext(gpointer key, gpointer value, gpointer user_data) { 177 static void jabber_caps_store_ext(gpointer key, gpointer value, gpointer user_data) {
201 const char *extname = key; 178 const char *extname = key;
202 JabberCapsValueExt *props = value; 179 JabberCapsValueExt *props = value;
203 xmlnode *root = user_data; 180 xmlnode *root = user_data;
204 xmlnode *ext = xmlnode_new_child(root,"ext"); 181 xmlnode *ext = xmlnode_new_child(root,"ext");
219 const char *feat = iter->data; 196 const char *feat = iter->data;
220 xmlnode *feature = xmlnode_new_child(ext, "feature"); 197 xmlnode *feature = xmlnode_new_child(ext, "feature");
221 xmlnode_set_attrib(feature, "var", feat); 198 xmlnode_set_attrib(feature, "var", feat);
222 } 199 }
223 } 200 }
201 #endif
224 202
225 static void jabber_caps_store_client(gpointer key, gpointer value, gpointer user_data) { 203 static void jabber_caps_store_client(gpointer key, gpointer value, gpointer user_data) {
226 JabberCapsKey *clientinfo = key; 204 JabberCapsKey *clientinfo = key;
227 JabberCapsValue *props = value; 205 JabberCapsValue *props = value;
228 xmlnode *root = user_data; 206 xmlnode *root = user_data;
229 xmlnode *client = xmlnode_new_child(root,"client"); 207 xmlnode *client = xmlnode_new_child(root,"client");
230 GList *iter; 208 GList *iter;
231 209
232 xmlnode_set_attrib(client,"node",clientinfo->node); 210 xmlnode_set_attrib(client,"node",clientinfo->node);
233 xmlnode_set_attrib(client,"ver",clientinfo->ver); 211 xmlnode_set_attrib(client,"ver",clientinfo->ver);
234 212 xmlnode_set_attrib(client,"hash",clientinfo->hash);
235 for(iter = props->identities; iter; iter = g_list_next(iter)) { 213 for(iter = props->identities; iter; iter = g_list_next(iter)) {
236 JabberCapsIdentity *id = iter->data; 214 JabberCapsIdentity *id = iter->data;
237 xmlnode *identity = xmlnode_new_child(client, "identity"); 215 xmlnode *identity = xmlnode_new_child(client, "identity");
238 xmlnode_set_attrib(identity, "category", id->category); 216 xmlnode_set_attrib(identity, "category", id->category);
239 xmlnode_set_attrib(identity, "type", id->type); 217 xmlnode_set_attrib(identity, "type", id->type);
245 const char *feat = iter->data; 223 const char *feat = iter->data;
246 xmlnode *feature = xmlnode_new_child(client, "feature"); 224 xmlnode *feature = xmlnode_new_child(client, "feature");
247 xmlnode_set_attrib(feature, "var", feat); 225 xmlnode_set_attrib(feature, "var", feat);
248 } 226 }
249 227
250 g_hash_table_foreach(props->ext,jabber_caps_store_ext,client); 228 for(iter = props->forms; iter; iter = g_list_next(iter)) {
229 xmlnode *xdata = iter->data;
230 xmlnode_insert_child(client, xdata);
231 }
251 } 232 }
252 233
253 static void jabber_caps_store(void) { 234 static void jabber_caps_store(void) {
254 char *str; 235 char *str;
255 xmlnode *root = xmlnode_new("capabilities"); 236 xmlnode *root = xmlnode_new("capabilities");
293 const char *feat = iter->data; 274 const char *feat = iter->data;
294 char *newfeat = g_strdup(feat); 275 char *newfeat = g_strdup(feat);
295 276
296 result->features = g_list_append(result->features,newfeat); 277 result->features = g_list_append(result->features,newfeat);
297 } 278 }
298 279 #if 0
299 for(iter = ext; iter; iter = g_list_next(iter)) { 280 for(iter = ext; iter; iter = g_list_next(iter)) {
300 const char *extname = iter->data; 281 const char *extname = iter->data;
301 JabberCapsValueExt *extinfo = g_hash_table_lookup(caps->ext,extname); 282 JabberCapsValueExt *extinfo = g_hash_table_lookup(caps->ext,extname);
302 283
303 if(extinfo) { 284 if(extinfo) {
317 298
318 result->features = g_list_append(result->features,newfeat); 299 result->features = g_list_append(result->features,newfeat);
319 } 300 }
320 } 301 }
321 } 302 }
303 #endif
322 return result; 304 return result;
323 } 305 }
324 306
325 void jabber_caps_free_clientinfo(JabberCapsClientInfo *clientinfo) { 307 void jabber_caps_free_clientinfo(JabberCapsClientInfo *clientinfo) {
326 if(!clientinfo) 308 if(!clientinfo)
349 gpointer user_data; 331 gpointer user_data;
350 332
351 char *who; 333 char *who;
352 char *node; 334 char *node;
353 char *ver; 335 char *ver;
354 GList *ext;
355 char *hash; 336 char *hash;
356 unsigned extOutstanding; 337 unsigned extOutstanding;
357 } jabber_caps_cbplususerdata; 338 } jabber_caps_cbplususerdata;
358 339
359 typedef struct jabber_ext_userdata { 340 typedef struct jabber_ext_userdata {
360 jabber_caps_cbplususerdata *userdata; 341 jabber_caps_cbplususerdata *userdata;
361 char *node; 342 char *node;
362 } jabber_ext_userdata; 343 } jabber_ext_userdata;
363 344
345 #if 0
364 static void jabber_caps_get_info_check_completion(jabber_caps_cbplususerdata *userdata) { 346 static void jabber_caps_get_info_check_completion(jabber_caps_cbplususerdata *userdata) {
365 if(userdata->extOutstanding == 0) { 347 if(userdata->extOutstanding == 0) {
366 userdata->cb(jabber_caps_collect_info(userdata->node, userdata->ver, userdata->ext), userdata->user_data); 348 userdata->cb(jabber_caps_collect_info(userdata->node, userdata->ver, userdata->ext), userdata->user_data);
367 g_free(userdata->who); 349 g_free(userdata->who);
368 g_free(userdata->node); 350 g_free(userdata->node);
372 userdata->ext = g_list_delete_link(userdata->ext,userdata->ext); 354 userdata->ext = g_list_delete_link(userdata->ext,userdata->ext);
373 } 355 }
374 g_free(userdata); 356 g_free(userdata);
375 } 357 }
376 } 358 }
359 #endif
377 360
378 static void jabber_caps_ext_iqcb(JabberStream *js, xmlnode *packet, gpointer data) { 361 static void jabber_caps_ext_iqcb(JabberStream *js, xmlnode *packet, gpointer data) {
379 /* collect data and fetch all exts */ 362 /* collect data and fetch all exts */
380 xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info"); 363 xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info");
381 jabber_ext_userdata *extuserdata = data; 364 jabber_ext_userdata *extuserdata = data;
427 id->name = g_strdup(name); 410 id->name = g_strdup(name);
428 411
429 value->identities = g_list_append(value->identities,id); 412 value->identities = g_list_append(value->identities,id);
430 } 413 }
431 } 414 }
432 g_hash_table_replace(client->ext, g_strdup(key), value); 415 //g_hash_table_replace(client->ext, g_strdup(key), value);
433 416
434 jabber_caps_store(); 417 jabber_caps_store();
435 } 418 }
436 419
437 g_free(extuserdata->node); 420 g_free(extuserdata->node);
473 g_free(hash); 456 g_free(hash);
474 printf("\n! ! ! invalid hash ! ! !"); 457 printf("\n! ! ! invalid hash ! ! !");
475 return; 458 return;
476 } 459 }
477 460
478 g_free(info);
479 g_free(hash); 461 g_free(hash);
480 462
481 JabberCapsValue *value = g_new0(JabberCapsValue, 1); 463 JabberCapsValue *value = g_new0(JabberCapsValue, 1);
482 JabberCapsKey *key = g_new0(JabberCapsKey, 1); 464 JabberCapsKey *key = g_new0(JabberCapsKey, 1);
483 465 #if 0
484 value->ext = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, jabber_caps_ext_destroy_value); 466 value->ext = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, jabber_caps_ext_destroy_value);
485 467 #endif
486 key->node = g_strdup(userdata->node); 468 key->node = g_strdup(userdata->node);
487 key->ver = g_strdup(userdata->ver); 469 key->ver = g_strdup(userdata->ver);
488 470 key->hash = g_strdup(userdata->hash);
471
472
489 for(child = query->child; child; child = child->next) { 473 for(child = query->child; child; child = child->next) {
490 if(child->type != XMLNODE_TYPE_TAG) 474 if(child->type != XMLNODE_TYPE_TAG)
491 continue; 475 continue;
492 if(!strcmp(child->name,"feature")) { 476 if(!strcmp(child->name,"feature")) {
493 const char *var = xmlnode_get_attrib(child, "var"); 477 const char *var = xmlnode_get_attrib(child, "var");
497 } else if(!strcmp(child->name,"identity")) { 481 } else if(!strcmp(child->name,"identity")) {
498 const char *category = xmlnode_get_attrib(child, "category"); 482 const char *category = xmlnode_get_attrib(child, "category");
499 const char *type = xmlnode_get_attrib(child, "type"); 483 const char *type = xmlnode_get_attrib(child, "type");
500 const char *name = xmlnode_get_attrib(child, "name"); 484 const char *name = xmlnode_get_attrib(child, "name");
501 485
502 if (category == 0 || type == 0 || name == 0) printf("\nMISSING");
503
504 JabberCapsIdentity *id = g_new0(JabberCapsIdentity, 1); 486 JabberCapsIdentity *id = g_new0(JabberCapsIdentity, 1);
505 id->category = g_strdup(category); 487 id->category = g_strdup(category);
506 id->type = g_strdup(type); 488 id->type = g_strdup(type);
507 id->name = g_strdup(name); 489 id->name = g_strdup(name);
508 490
509 value->identities = g_list_append(value->identities,id); 491 value->identities = g_list_append(value->identities,id);
510 } 492 } else if(!strcmp(child->name, "x")) {
511 } 493 value->forms = g_list_append(value->forms, xmlnode_copy(child));
512 494 }
513 //g_hash_table_replace(capstable, key, value); 495 }
514 //jabber_caps_store(); 496
515 } 497 g_hash_table_replace(capstable, key, value);
516 498 jabber_caps_store();
499 }
500
501 #if 0
517 /* fetch all exts */ 502 /* fetch all exts */
518 for(iter = userdata->ext; iter; iter = g_list_next(iter)) { 503 for(iter = userdata->ext; iter; iter = g_list_next(iter)) {
519 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); 504 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info");
520 xmlnode *query = xmlnode_get_child_with_namespace(iq->node, "query", "http://jabber.org/protocol/disco#info"); 505 xmlnode *query = xmlnode_get_child_with_namespace(iq->node, "query", "http://jabber.org/protocol/disco#info");
521 char *node = g_strdup_printf("%s#%s", userdata->node, (const char*)iter->data); 506 char *node = g_strdup_printf("%s#%s", userdata->node, (const char*)iter->data);
529 jabber_iq_set_callback(iq, jabber_caps_ext_iqcb, ext_data); 514 jabber_iq_set_callback(iq, jabber_caps_ext_iqcb, ext_data);
530 jabber_iq_send(iq); 515 jabber_iq_send(iq);
531 } 516 }
532 517
533 jabber_caps_get_info_check_completion(userdata); 518 jabber_caps_get_info_check_completion(userdata);
519 #endif
534 } 520 }
535 521
536 void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, const char *ver, const char *hash, jabber_caps_get_info_cb cb, gpointer user_data) { 522 void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, const char *ver, const char *hash, jabber_caps_get_info_cb cb, gpointer user_data) {
537 JabberCapsValue *client; 523 JabberCapsValue *client;
538 JabberCapsKey *key = g_new0(JabberCapsKey, 1); 524 JabberCapsKey *key = g_new0(JabberCapsKey, 1);