soc.2008.xmpp: 205109ea: * implemented jabber_caps_calcualte_hash...
tfar at soc.pidgin.im
tfar at soc.pidgin.im
Sun Jul 6 17:16:33 EDT 2008
-----------------------------------------------------------------
Revision: 205109eaadff2ff58bf4efc9835a366792efed23
Ancestor: 24b5f892917273cef92a91180006ec8bbd802a25
Author: tfar at soc.pidgin.im
Date: 2008-06-29T14:32:33
Branch: im.pidgin.soc.2008.xmpp
URL: http://d.pidgin.im/viewmtn/revision/info/205109eaadff2ff58bf4efc9835a366792efed23
Modified files:
libpurple/protocols/jabber/caps.c
libpurple/protocols/jabber/caps.h
ChangeLog:
* implemented jabber_caps_calcualte_hash() which calculates the SHA-1 hash for someones disco response according to XEP-0115
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/caps.c f94e52da14d281a9806174d7fe470bbe1e930a3e
+++ libpurple/protocols/jabber/caps.c 3fd3414d7cf44c525d4fe3f1cdfe7f91e784e57f
@@ -383,7 +383,7 @@ static void jabber_caps_ext_iqcb(JabberS
--userdata->extOutstanding;
/* TODO: Better error handling */
-
+ printf("\n\tjabber_caps_ext_iqcb for %s", xmlnode_get_attrib(packet, "from"));
if(node && query) {
const char *key;
JabberCapsValue *client;
@@ -446,7 +446,7 @@ static void jabber_caps_client_iqcb(Jabb
jabber_caps_cbplususerdata *userdata = data;
/* TODO: Better error checking! */
-
+ printf("\n\tjabber_caps_client_iqcb for %s", xmlnode_get_attrib(packet, "from"));
if (query) {
JabberCapsValue *value = g_new0(JabberCapsValue, 1);
@@ -605,6 +605,14 @@ static gint jabber_caps_string_compare(g
return strcmp(ac, bc);
}
+gchar *jabber_caps_get_formtype(const xmlnode *x) {
+ xmlnode *formtypefield;
+ formtypefield = xmlnode_get_child(x, "field");
+ while (formtypefield && strcmp(xmlnode_get_attrib(formtypefield, "var"), "FORM_TYPE")) formtypefield = xmlnode_get_next_twin(formtypefield);
+ formtypefield = xmlnode_get_child(formtypefield, "value");
+ return xmlnode_get_data(formtypefield);;
+}
+
static gint jabber_caps_jabber_xdata_compare(gconstpointer a, gconstpointer b) {
const xmlnode *ac;
const xmlnode *bc;
@@ -617,13 +625,10 @@ static gint jabber_caps_jabber_xdata_com
ac = a;
bc = b;
- aformtypefield = xmlnode_get_child(ac, "field");
- while (aformtypefield && strcmp(xmlnode_get_attrib(aformtypefield, "var"), "FORM_TYPE")) aformtypefield = xmlnode_get_next_twin(aformtypefield);
- aformtype = xmlnode_get_data(aformtypefield);
+
+ aformtype = jabber_caps_get_formtype(aformtypefield);
- bformtypefield = xmlnode_get_child(bc, "field");
- while (bformtypefield && strcmp(xmlnode_get_attrib(bformtypefield, "var"), "FORM_TYPE")) bformtypefield = xmlnode_get_next_twin(bformtypefield);
- bformtype = xmlnode_get_data(bformtypefield);
+ bformtype = jabber_caps_get_formtype(bformtypefield);
result = strcmp(aformtype, bformtype);
g_free(aformtype);
@@ -669,13 +674,132 @@ JabberCapsClientInfo *jabber_caps_parse_
return info;
}
+static gint jabber_caps_xdata_field_compare(gconstpointer a, gconstpointer b) {
+ const JabberDataFormField *ac;
+ const JabberDataFormField *bc;
+
+ ac = a;
+ bc = b;
+
+ return strcmp(ac->var, bc->var);
+}
+
+GList *jabber_caps_xdata_get_fields(xmlnode *x) {
+ GList *fields = 0;
+ xmlnode *field;
+ xmlnode *value;
+ JabberDataFormField *xdatafield;
+
+ if(!x) return 0;
+
+ for(field = xmlnode_get_child(x, "field"); field != 0; field = xmlnode_get_next_twin(field)) {
+ xdatafield = g_new0(JabberDataFormField, 1);
+ xdatafield->var = g_strdup(xmlnode_get_attrib(field, "var"));
+ for(value = xmlnode_get_child(field, "value"); value != 0; value = xmlnode_get_next_twin(value)) {
+ gchar *val = xmlnode_get_data(value);
+ xdatafield->values = g_list_append(xdatafield->values, val);
+ }
+ xdatafield->values = g_list_sort(xdatafield->values, jabber_caps_string_compare);
+ fields = g_list_append(fields, xdatafield);
+ }
+ fields = g_list_sort(fields, jabber_caps_xdata_field_compare);
+ return fields;
+}
+
+gchar *jabber_caps_verification_append(gchar *verification_string, gchar *string) {
+ gchar *verification;
+ verification = g_strconcat(verification_string, string, "<", NULL);
+ g_free(verification_string);
+ return verification;
+}
+
gchar *jabber_caps_calcualte_hash(JabberCapsClientInfo *info) {
+ GList *identities;
+ GList *features;
+ GList *xdata;
+ gchar *verification = 0;
+ gchar *feature_string;
+ gchar *free_verification;
+ gchar *identity_string;
+ PurpleCipherContext *context;
+ guint8 checksum[20];
+ gsize checksum_size = 20;
+
if (!info) return 0;
/* sort identities, features and x-data forms */
info->identities = g_list_sort(info->identities, jabber_caps_jabber_identity_compare);
info->features = g_list_sort(info->features, jabber_caps_string_compare);
info->forms = g_list_sort(info->forms, jabber_caps_jabber_xdata_compare);
+
+ /* concat identities to the verification string */
+ for(identities = info->identities; identities; identities = identities->next) {
+ JabberIdentity *ident = (JabberIdentity*)identities->data;
+ identity_string = g_strdup_printf("%s/%s//%s<", ident->category, ident->type, ident->name);
+ free_verification = verification;
+ if(verification == 0) verification = g_strdup(identity_string);
+ else verification = g_strconcat(verification, identity_string, NULL);
+ g_free(identity_string);
+ g_free(free_verification);
+ }
+
+ /* concat features to the verification string */
+ for(features = info->features; features; features = features->next) {
+ feature_string = g_strdup_printf("%s<", (gchar*)features->data);
+ verification = jabber_caps_verification_append(verification, feature_string);
+ g_free(feature_string);
+ }
+
+ /* concat x-data forms to the verification string */
+ for(xdata = info->forms; xdata; xdata = xdata->next) {
+ gchar *formtype = 0;
+ GList *fields;
+ /* append FORM_TYPE's field value to the verification string */
+ formtype = jabber_caps_get_formtype((xmlnode*)xdata->data);
+ verification = jabber_caps_verification_append(verification, formtype);
+ g_free(formtype);
+
+ for(fields = jabber_caps_xdata_get_fields((xmlnode*)(xdata->data)); fields != 0; fields = fields->next) {
+ GList *value;
+ JabberDataFormField *field = (JabberDataFormField*)fields;
+ if(strcmp(field->var, "FORM_TYPE")) {
+ /* Append the value of the "var" attribute, followed by the '<' character. */
+ verification = jabber_caps_verification_append(verification, field->var);
+ /* For each <value/> element, append the XML character data, followed by the '<' character. */
+ for(value = field->values; value != 0; value = value->next) {
+ verification = jabber_caps_verification_append(verification, value->data);
+ }
+ }
+ for(value = field->values; value != 0; value = value->next) {
+ g_free(value->data);
+ }
+ g_free(field->var);
+ g_list_free(field->values);
+ }
+ g_list_free(fields);
+ }
+
+ /* generate SHA-1 hash */
+ context = purple_cipher_context_new_by_name("sha1", NULL);
+ if (context == NULL) {
+ purple_debug_error("jabber", "Could not find sha1 cipher\n");
+ return 0;
+ }
+ purple_cipher_context_append(context, verification, strlen(verification));
+
+ if (!purple_cipher_context_digest(context, strlen(verification), checksum, &checksum_size)) {
+ purple_debug_error("util", "Failed to get SHA-1 digest.\n");
+ }
+ purple_cipher_context_destroy(context);
+
+ /* apply Base64 on hash */
+
+ g_free(verification);
+ verification = purple_base64_encode(checksum, checksum_size);
+ printf("\n%s", verification);
+
+ if (caps_hash != 0) g_free(caps_hash);
+ return verification;
}
void jabber_caps_calculate_own_hash() {
@@ -713,10 +837,8 @@ void jabber_caps_calculate_own_hash() {
else verification = g_strconcat(verification, feature_string, NULL);
g_free(feature_string);
if(free_verification) g_free(free_verification);
- }
- printf("\n%s", verification);
+ }
-
/* generate SHA-1 hash */
context = purple_cipher_context_new_by_name("sha1", NULL);
if (context == NULL) {
@@ -734,7 +856,6 @@ void jabber_caps_calculate_own_hash() {
g_free(verification);
verification = purple_base64_encode(checksum, checksum_size); // for 2.0 compability
- printf("\n%s", verification);
if (caps_hash != 0) g_free(caps_hash);
caps_hash = verification;
============================================================
--- libpurple/protocols/jabber/caps.h f32f510059e82487b840fc379893b7d808d3ce90
+++ libpurple/protocols/jabber/caps.h b70d9d20ba848ce49c5df9c36397889c80e70bd0
@@ -36,6 +36,11 @@ struct _JabberCapsClientInfo {
GList *forms; /* xmlnode * */
};
+typedef struct _JabberDataFormField {
+ gchar *var;
+ GList *values;
+} JabberDataFormField;
+
typedef void (*jabber_caps_get_info_cb)(JabberCapsClientInfo *info, gpointer user_data);
void jabber_caps_init(void);
More information about the Commits
mailing list