Mercurial > pidgin
view libpurple/protocols/jabber/data.c @ 23780:9d83ae2c1a4f
New files used for custom smileys.
committer: Sadrul Habib Chowdhury <imadil@gmail.com>
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Sun, 01 Jun 2008 21:39:15 +0000 |
parents | |
children | 305fac6af8f9 |
line wrap: on
line source
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA */ #include <stdlib.h> #include <glib.h> #include <string.h> #include "data.h" #include "debug.h" #include "xmlnode.h" #include "util.h" #include "conversation.h" #include "iq.h" /* hash table to store locally supplied data objects, by conversation and alt text (smiley shortcut) */ static GHashTable *local_datas_by_alt = NULL; /* hash table to store locally supplied data objects, by content id */ static GHashTable *local_datas_by_cid = NULL; /* remote supplied data objects by content id */ static GHashTable *remote_datas_by_cid = NULL; void jabber_data_init(void) { /* setup hash tables for storing data instances here */ purple_debug_info("jabber", "Setting up data handling\n"); local_datas_by_alt = g_hash_table_new(NULL, NULL); local_datas_by_cid = g_hash_table_new(NULL, NULL); remote_datas_by_cid = g_hash_table_new(NULL, NULL); } JabberData * jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type, const char *alt) { JabberData *data = g_new0(JabberData, 1); gchar *checksum = purple_util_get_image_checksum(rawdata, size); gchar cid[256]; /* is there some better way to generate a content ID? */ g_snprintf(cid, sizeof(cid), "%s@%s", checksum, g_get_host_name()); g_free(checksum); data->cid = g_strdup(cid); data->type = g_strdup(type); data->alt = g_strdup(alt); data->size = size; data->data = g_memdup(rawdata, size); return data; } JabberData * jabber_data_create_from_xml(xmlnode *tag) { JabberData *data = g_new0(JabberData, 1); gsize size; gpointer raw_data = NULL; if (data == NULL) { purple_debug_error("jabber", "Could not allocate data object\n"); g_free(data); return NULL; } /* check if this is a "data" tag */ if (strcmp(tag->name, "data") != 0) { purple_debug_error("jabber", "Invalid data element"); g_free(data); return NULL; } data->cid = g_strdup(xmlnode_get_attrib(tag, "cid")); data->type = g_strdup(xmlnode_get_attrib(tag, "type")); data->alt = g_strdup(xmlnode_get_attrib(tag, "alt")); raw_data = xmlnode_get_data(tag); data->data = purple_base64_decode(raw_data, &size); data->size = size; g_free(raw_data); return data; } void jabber_data_delete(JabberData *data) { g_free(data->cid); g_free(data->alt); g_free(data->type); g_free(data->data); g_free(data); } const char * jabber_data_get_cid(const JabberData *data) { return data->cid; } const char * jabber_data_get_alt(const JabberData *data) { return data->alt; } const char * jabber_data_get_type(const JabberData *data) { return data->type; } gsize jabber_data_get_size(const JabberData *data) { return data->size; } gpointer jabber_data_get_data(const JabberData *data) { return data->data; } xmlnode * jabber_data_get_xml_definition(const JabberData *data) { xmlnode *tag = xmlnode_new("data"); char *base64data = purple_base64_encode(data->data, data->size); xmlnode_set_namespace(tag, XEP_0231_NAMESPACE); xmlnode_set_attrib(tag, "alt", data->alt); xmlnode_set_attrib(tag, "cid", data->cid); xmlnode_set_attrib(tag, "type", data->type); xmlnode_insert_data(tag, base64data, -1); g_free(base64data); return tag; } xmlnode * jabber_data_get_xhtml_im(const JabberData *data) { xmlnode *img = xmlnode_new("img"); char src[128]; xmlnode_set_attrib(img, "alt", data->alt); g_snprintf(src, sizeof(src), "cid:%s", data->cid); xmlnode_set_attrib(img, "src", src); return img; } xmlnode * jabber_data_get_xml_request(const gchar *cid) { xmlnode *tag = xmlnode_new("data"); xmlnode_set_namespace(tag, XEP_0231_NAMESPACE); xmlnode_set_attrib(tag, "cid", cid); return tag; } const JabberData * jabber_data_find_local_by_alt(const PurpleConversation *conv, const char *alt) { GHashTable *local_datas = g_hash_table_lookup(local_datas_by_alt, conv); if (local_datas) { return g_hash_table_lookup(local_datas, alt); } else { return NULL; } } const JabberData * jabber_data_find_local_by_cid(const PurpleConversation *conv, const char *cid) { GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv); if (local_datas) { return g_hash_table_lookup(local_datas, cid); } else { return NULL; } } const JabberData * jabber_data_find_remote_by_cid(const PurpleConversation *conv, const char *cid) { GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv); if (remote_datas) { return g_hash_table_lookup(remote_datas, cid); } else { return NULL; } } void jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv) { GHashTable *datas_by_alt = g_hash_table_lookup(local_datas_by_alt, conv); GHashTable *datas_by_cid = g_hash_table_lookup(local_datas_by_cid, conv); if (!datas_by_alt) { datas_by_alt = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(local_datas_by_alt, conv, datas_by_alt); } if (!datas_by_cid) { datas_by_cid = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(local_datas_by_cid, conv, datas_by_cid); } g_hash_table_insert(datas_by_alt, g_strdup(jabber_data_get_alt(data)), data); g_hash_table_insert(datas_by_cid, g_strdup(jabber_data_get_cid(data)), data); } void jabber_data_associate_remote_with_conv(JabberData *data, PurpleConversation *conv) { GHashTable *datas_by_cid = g_hash_table_lookup(remote_datas_by_cid, conv); if (!datas_by_cid) { datas_by_cid = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(remote_datas_by_cid, conv, datas_by_cid); } g_hash_table_insert(datas_by_cid, g_strdup(jabber_data_get_cid(data)), data); } static void jabber_data_delete_from_hash_table(gpointer key, gpointer value, gpointer user_data) { JabberData *data = (JabberData *) value; jabber_data_delete(data); g_free(key); } void jabber_data_delete_associated_with_conv(PurpleConversation *conv) { GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv); GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv); GHashTable *local_datas_alt = g_hash_table_lookup(local_datas_by_alt, conv); if (local_datas) { g_hash_table_foreach(local_datas, jabber_data_delete_from_hash_table, NULL); g_hash_table_destroy(local_datas); g_hash_table_remove(local_datas_by_cid, conv); } if (remote_datas) { g_hash_table_foreach(remote_datas, jabber_data_delete_from_hash_table, NULL); g_hash_table_destroy(remote_datas); g_hash_table_remove(remote_datas_by_cid, conv); } if (local_datas_alt) { g_hash_table_destroy(local_datas_alt); g_hash_table_remove(local_datas_by_alt, conv); } } void jabber_data_parse(JabberStream *js, xmlnode *packet) { JabberIq *result = NULL; const char *who = xmlnode_get_attrib(packet, "from"); const PurpleConnection *gc = js->gc; const PurpleAccount *account = purple_connection_get_account(gc); const PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account); xmlnode *data_node = xmlnode_get_child(packet, "data"); const JabberData *data = jabber_data_find_local_by_cid(conv, xmlnode_get_attrib(data_node, "cid")); if (!conv || !data) { xmlnode *item_not_found = xmlnode_new("item-not-found"); result = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_set_attrib(result->node, "to", who); xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); xmlnode_insert_child(result->node, item_not_found); } else { result = jabber_iq_new(js, JABBER_IQ_RESULT); xmlnode_set_attrib(result->node, "to", who); xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); xmlnode_insert_child(result->node, jabber_data_get_xml_definition(data)); } jabber_iq_send(result); }