xmpp.custom_smiley: a21aa16c: New files used for custom smileys.
sadrul at pidgin.im
sadrul at pidgin.im
Sun Jun 1 17:40:53 EDT 2008
-----------------------------------------------------------------
Revision: a21aa16c365d48c3255358530932190b7263cc9d
Ancestor: 710296eb0b1e3c18b4174ccfcece95be33d65c21
Author: ml at update.uu.se
Date: 2008-06-01T21:39:15
Branch: im.pidgin.xmpp.custom_smiley
URL: http://d.pidgin.im/viewmtn/revision/info/a21aa16c365d48c3255358530932190b7263cc9d
Added files:
libpurple/protocols/jabber/data.c
libpurple/protocols/jabber/data.h
ChangeLog:
New files used for custom smileys.
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/data.c 49260e93548a3c276fe802c1b38cea3e23474e86
+++ libpurple/protocols/jabber/data.c 49260e93548a3c276fe802c1b38cea3e23474e86
@@ -0,0 +1,320 @@
+/*
+ * 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);
+}
============================================================
--- libpurple/protocols/jabber/data.h 7b1d2be796e6180402ee9be0a0664f3fbd1b2e1a
+++ libpurple/protocols/jabber/data.h 7b1d2be796e6180402ee9be0a0664f3fbd1b2e1a
@@ -0,0 +1,83 @@
+/*
+ * 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
+ */
+
+#ifndef JABBER_DATA_H
+#define JABBER_DATA_H
+
+#include "xmlnode.h"
+#include "conversation.h"
+#include "jabber.h"
+
+#define XEP_0231_NAMESPACE "urn:xmpp:tmp:data-element"
+#define XEP_0231_IB_IMAGE_NAMESPACE "urn:xmpp:tmp:data-element:inband-image"
+
+#include <glib.h>
+
+typedef struct {
+ char *cid;
+ char *alt;
+ char *type;
+ gsize size;
+ gpointer data;
+} JabberData;
+
+void jabber_data_init(void);
+
+/* creates a JabberData instance from raw data */
+JabberData *jabber_data_create_from_data(gconstpointer data, gsize size,
+ const char *type, const char *alt);
+
+/* create a JabberData instance from an XML "data" element (as defined by
+ XEP 0231 */
+JabberData *jabber_data_create_from_xml(xmlnode *tag);
+
+void jabber_data_delete(JabberData *data);
+
+const char *jabber_data_get_cid(const JabberData *data);
+const char *jabber_data_get_alt(const JabberData *data);
+const char *jabber_data_get_type(const JabberData *data);
+
+gsize jabber_data_get_size(const JabberData *data);
+gpointer jabber_data_get_data(const JabberData *data);
+
+/* returns the XML definition for the data element */
+xmlnode *jabber_data_get_xml_definition(const JabberData *data);
+
+/* returns an XHTML-IM "img" tag given a data instance */
+xmlnode *jabber_data_get_xhtml_im(const JabberData *data);
+
+/* returns a data request element (to be included in an iq stanza) for requesting
+ data */
+xmlnode *jabber_data_get_xml_request(const gchar *cid);
+
+/* lookup functions */
+const JabberData *jabber_data_find_local_by_alt(const PurpleConversation *conv,
+ const char *alt);
+const JabberData *jabber_data_find_local_by_cid(const PurpleConversation *conv,
+ const char *cid);
+const JabberData *jabber_data_find_remote_by_cid(const PurpleConversation *conv,
+ const char *cid);
+
+/* associate data objects with a conversation */
+void jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv);
+void jabber_data_associate_remote_with_conv(JabberData *data, PurpleConversation *conv);
+void jabber_data_delete_associated_with_conv(PurpleConversation *conv);
+
+/* handles iq requests */
+void jabber_data_parse(JabberStream *js, xmlnode *packet);
+
+
+#endif /* JABBER_DATA_H */
More information about the Commits
mailing list