Mercurial > pidgin
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); |