| 40 } JabberCapsKey; |
40 } JabberCapsKey; |
| 41 |
41 |
| 42 typedef struct _JabberCapsValueExt { |
42 typedef struct _JabberCapsValueExt { |
| 43 GList *identities; /* JabberCapsIdentity */ |
43 GList *identities; /* JabberCapsIdentity */ |
| 44 GList *features; /* char * */ |
44 GList *features; /* char * */ |
| |
45 GList *xdatas; /* xmlnode * */ |
| 45 } JabberCapsValueExt; |
46 } JabberCapsValueExt; |
| 46 |
47 |
| 47 typedef struct _JabberCapsValue { |
48 typedef struct _JabberCapsValue { |
| 48 GList *identities; /* JabberCapsIdentity */ |
49 GList *identities; /* JabberCapsIdentity */ |
| 49 GList *features; /* char * */ |
50 GList *features; /* char * */ |
| 59 } |
60 } |
| 60 |
61 |
| 61 static gboolean jabber_caps_compare(gconstpointer v1, gconstpointer v2) { |
62 static gboolean jabber_caps_compare(gconstpointer v1, gconstpointer v2) { |
| 62 const JabberCapsKey *name1 = v1; |
63 const JabberCapsKey *name1 = v1; |
| 63 const JabberCapsKey *name2 = v2; |
64 const JabberCapsKey *name2 = v2; |
| 64 |
65 |
| 65 return strcmp(name1->node,name2->node) == 0 && strcmp(name1->ver,name2->ver) == 0; |
66 return strcmp(name1->node,name2->node) == 0 && strcmp(name1->ver,name2->ver) == 0; |
| 66 } |
67 } |
| 67 |
68 |
| 68 static void jabber_caps_destroy_key(gpointer key) { |
69 static void jabber_caps_destroy_key(gpointer key) { |
| 69 JabberCapsKey *keystruct = key; |
70 JabberCapsKey *keystruct = key; |
| 445 xmlnode *child; |
446 xmlnode *child; |
| 446 GList *iter; |
447 GList *iter; |
| 447 jabber_caps_cbplususerdata *userdata = data; |
448 jabber_caps_cbplususerdata *userdata = data; |
| 448 |
449 |
| 449 /* TODO: Better error checking! */ |
450 /* TODO: Better error checking! */ |
| |
451 if (!strcmp(xmlnode_get_attrib(packet, "type"), "error"))return; |
| 450 if (query) { |
452 if (query) { |
| 451 // check hash |
453 // check hash |
| 452 JabberCapsClientInfo *info = jabber_caps_parse_client_info(query); |
454 JabberCapsClientInfo *info = jabber_caps_parse_client_info(query); |
| 453 gchar *sha_hash = jabber_caps_calcualte_hash(info); |
455 gchar *hash = 0; |
| 454 |
456 if (!strcmp(userdata->hash, "sha-1")) { |
| 455 #warning INSERT HASH CHECKING CODE HERE! ONLY ADD TO CACHE IF HASH IS THE SAME. |
457 hash = jabber_caps_calcualte_hash(info, "sha1"); |
| 456 |
458 } else if (!strcmp(userdata->hash, "md5")) { |
| |
459 hash = jabber_caps_calcualte_hash(info, "md5"); |
| |
460 } else { |
| |
461 // clean up |
| |
462 return; |
| |
463 } |
| |
464 |
| |
465 printf("\n\tfrom: %s", xmlnode_get_attrib(packet, "from")); |
| |
466 printf("\n\tnode: %s", xmlnode_get_attrib(query, "node")); |
| |
467 printf("\n\tcalculated key: %s", hash); |
| |
468 printf("\n\thash: %s", userdata->hash); |
| |
469 printf("\n"); |
| |
470 |
| |
471 if (strcmp(hash, userdata->ver)) { |
| |
472 g_free(info); |
| |
473 g_free(hash); |
| |
474 printf("\n! ! ! invalid hash ! ! !"); |
| |
475 return; |
| |
476 } |
| |
477 |
| 457 g_free(info); |
478 g_free(info); |
| 458 g_free(sha_hash); |
479 g_free(hash); |
| 459 |
480 |
| 460 JabberCapsValue *value = g_new0(JabberCapsValue, 1); |
481 JabberCapsValue *value = g_new0(JabberCapsValue, 1); |
| 461 JabberCapsKey *key = g_new0(JabberCapsKey, 1); |
482 JabberCapsKey *key = g_new0(JabberCapsKey, 1); |
| 462 |
483 |
| 463 value->ext = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, jabber_caps_ext_destroy_value); |
484 value->ext = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, jabber_caps_ext_destroy_value); |
| 475 value->features = g_list_append(value->features, g_strdup(var)); |
496 value->features = g_list_append(value->features, g_strdup(var)); |
| 476 } else if(!strcmp(child->name,"identity")) { |
497 } else if(!strcmp(child->name,"identity")) { |
| 477 const char *category = xmlnode_get_attrib(child, "category"); |
498 const char *category = xmlnode_get_attrib(child, "category"); |
| 478 const char *type = xmlnode_get_attrib(child, "type"); |
499 const char *type = xmlnode_get_attrib(child, "type"); |
| 479 const char *name = xmlnode_get_attrib(child, "name"); |
500 const char *name = xmlnode_get_attrib(child, "name"); |
| 480 |
501 |
| |
502 if (category == 0 || type == 0 || name == 0) printf("\nMISSING"); |
| |
503 |
| 481 JabberCapsIdentity *id = g_new0(JabberCapsIdentity, 1); |
504 JabberCapsIdentity *id = g_new0(JabberCapsIdentity, 1); |
| 482 id->category = g_strdup(category); |
505 id->category = g_strdup(category); |
| 483 id->type = g_strdup(type); |
506 id->type = g_strdup(type); |
| 484 id->name = g_strdup(name); |
507 id->name = g_strdup(name); |
| 485 |
508 |
| 486 value->identities = g_list_append(value->identities,id); |
509 value->identities = g_list_append(value->identities,id); |
| 487 } |
510 } |
| 488 } |
511 } |
| 489 g_hash_table_replace(capstable, key, value); |
512 |
| 490 jabber_caps_store(); |
513 //g_hash_table_replace(capstable, key, value); |
| |
514 //jabber_caps_store(); |
| 491 } |
515 } |
| 492 |
516 |
| 493 /* fetch all exts */ |
517 /* fetch all exts */ |
| 494 for(iter = userdata->ext; iter; iter = g_list_next(iter)) { |
518 for(iter = userdata->ext; iter; iter = g_list_next(iter)) { |
| 495 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); |
519 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); |
| 720 verification = g_strconcat(verification_string, string, "<", NULL); |
744 verification = g_strconcat(verification_string, string, "<", NULL); |
| 721 g_free(verification_string); |
745 g_free(verification_string); |
| 722 return verification; |
746 return verification; |
| 723 } |
747 } |
| 724 |
748 |
| 725 gchar *jabber_caps_calcualte_hash(JabberCapsClientInfo *info) { |
749 gchar *jabber_caps_calcualte_hash(JabberCapsClientInfo *info, const char *hash) { |
| 726 GList *identities; |
750 GList *identities; |
| 727 GList *features; |
751 GList *features; |
| 728 GList *xdata; |
752 GList *xdata; |
| 729 gchar *verification = 0; |
753 gchar *verification = 0; |
| 730 gchar *feature_string; |
754 gchar *feature_string; |
| 786 g_list_free(field->values); |
810 g_list_free(field->values); |
| 787 } |
811 } |
| 788 g_list_free(fields); |
812 g_list_free(fields); |
| 789 } |
813 } |
| 790 |
814 |
| 791 /* generate SHA-1 hash */ |
815 /* generate hash */ |
| 792 context = purple_cipher_context_new_by_name("sha1", NULL); |
816 context = purple_cipher_context_new_by_name(hash, NULL); |
| 793 if (context == NULL) { |
817 if (context == NULL) { |
| 794 purple_debug_error("jabber", "Could not find sha1 cipher\n"); |
818 //purple_debug_error("jabber", "Could not find cipher\n"); |
| 795 return 0; |
819 return 0; |
| 796 } |
820 } |
| 797 purple_cipher_context_append(context, verification, strlen(verification)); |
821 purple_cipher_context_append(context, verification, strlen(verification)); |
| 798 |
822 |
| 799 if (!purple_cipher_context_digest(context, strlen(verification), checksum, &checksum_size)) { |
823 if (!purple_cipher_context_digest(context, strlen(verification), checksum, &checksum_size)) { |
| 800 purple_debug_error("util", "Failed to get SHA-1 digest.\n"); |
824 //purple_debug_error("util", "Failed to get digest.\n"); |
| 801 } |
825 } |
| 802 purple_cipher_context_destroy(context); |
826 purple_cipher_context_destroy(context); |
| 803 |
827 |
| 804 /* apply Base64 on hash */ |
828 /* apply Base64 on hash */ |
| 805 |
829 |