comparison 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
comparison
equal deleted inserted replaced
23779:b2697ab66d23 23780:9d83ae2c1a4f
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
15 */
16
17 #include <stdlib.h>
18 #include <glib.h>
19 #include <string.h>
20
21 #include "data.h"
22 #include "debug.h"
23 #include "xmlnode.h"
24 #include "util.h"
25 #include "conversation.h"
26 #include "iq.h"
27
28 /* hash table to store locally supplied data objects, by conversation and
29 alt text (smiley shortcut) */
30 static GHashTable *local_datas_by_alt = NULL;
31
32 /* hash table to store locally supplied data objects, by content id */
33 static GHashTable *local_datas_by_cid = NULL;
34
35 /* remote supplied data objects by content id */
36 static GHashTable *remote_datas_by_cid = NULL;
37
38
39 void
40 jabber_data_init(void)
41 {
42 /* setup hash tables for storing data instances here */
43 purple_debug_info("jabber", "Setting up data handling\n");
44
45 local_datas_by_alt = g_hash_table_new(NULL, NULL);
46 local_datas_by_cid = g_hash_table_new(NULL, NULL);
47 remote_datas_by_cid = g_hash_table_new(NULL, NULL);
48 }
49
50 JabberData *
51 jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type,
52 const char *alt)
53 {
54 JabberData *data = g_new0(JabberData, 1);
55 gchar *checksum = purple_util_get_image_checksum(rawdata, size);
56 gchar cid[256];
57
58 /* is there some better way to generate a content ID? */
59 g_snprintf(cid, sizeof(cid), "%s@%s", checksum, g_get_host_name());
60 g_free(checksum);
61
62 data->cid = g_strdup(cid);
63 data->type = g_strdup(type);
64 data->alt = g_strdup(alt);
65 data->size = size;
66
67 data->data = g_memdup(rawdata, size);
68
69 return data;
70 }
71
72 JabberData *
73 jabber_data_create_from_xml(xmlnode *tag)
74 {
75 JabberData *data = g_new0(JabberData, 1);
76 gsize size;
77 gpointer raw_data = NULL;
78
79 if (data == NULL) {
80 purple_debug_error("jabber", "Could not allocate data object\n");
81 g_free(data);
82 return NULL;
83 }
84
85 /* check if this is a "data" tag */
86 if (strcmp(tag->name, "data") != 0) {
87 purple_debug_error("jabber", "Invalid data element");
88 g_free(data);
89 return NULL;
90 }
91
92 data->cid = g_strdup(xmlnode_get_attrib(tag, "cid"));
93 data->type = g_strdup(xmlnode_get_attrib(tag, "type"));
94 data->alt = g_strdup(xmlnode_get_attrib(tag, "alt"));
95
96 raw_data = xmlnode_get_data(tag);
97 data->data = purple_base64_decode(raw_data, &size);
98 data->size = size;
99
100 g_free(raw_data);
101
102 return data;
103 }
104
105
106 void
107 jabber_data_delete(JabberData *data)
108 {
109 g_free(data->cid);
110 g_free(data->alt);
111 g_free(data->type);
112 g_free(data->data);
113 g_free(data);
114 }
115
116 const char *
117 jabber_data_get_cid(const JabberData *data)
118 {
119 return data->cid;
120 }
121
122 const char *
123 jabber_data_get_alt(const JabberData *data)
124 {
125 return data->alt;
126 }
127
128 const char *
129 jabber_data_get_type(const JabberData *data)
130 {
131 return data->type;
132 }
133
134 gsize
135 jabber_data_get_size(const JabberData *data)
136 {
137 return data->size;
138 }
139
140 gpointer
141 jabber_data_get_data(const JabberData *data)
142 {
143 return data->data;
144 }
145
146 xmlnode *
147 jabber_data_get_xml_definition(const JabberData *data)
148 {
149 xmlnode *tag = xmlnode_new("data");
150 char *base64data = purple_base64_encode(data->data, data->size);
151
152 xmlnode_set_namespace(tag, XEP_0231_NAMESPACE);
153 xmlnode_set_attrib(tag, "alt", data->alt);
154 xmlnode_set_attrib(tag, "cid", data->cid);
155 xmlnode_set_attrib(tag, "type", data->type);
156
157 xmlnode_insert_data(tag, base64data, -1);
158
159 g_free(base64data);
160
161 return tag;
162 }
163
164 xmlnode *
165 jabber_data_get_xhtml_im(const JabberData *data)
166 {
167 xmlnode *img = xmlnode_new("img");
168 char src[128];
169
170 xmlnode_set_attrib(img, "alt", data->alt);
171 g_snprintf(src, sizeof(src), "cid:%s", data->cid);
172 xmlnode_set_attrib(img, "src", src);
173
174 return img;
175 }
176
177 xmlnode *
178 jabber_data_get_xml_request(const gchar *cid)
179 {
180 xmlnode *tag = xmlnode_new("data");
181
182 xmlnode_set_namespace(tag, XEP_0231_NAMESPACE);
183 xmlnode_set_attrib(tag, "cid", cid);
184
185 return tag;
186 }
187
188 const JabberData *
189 jabber_data_find_local_by_alt(const PurpleConversation *conv, const char *alt)
190 {
191 GHashTable *local_datas = g_hash_table_lookup(local_datas_by_alt, conv);
192
193 if (local_datas) {
194 return g_hash_table_lookup(local_datas, alt);
195 } else {
196 return NULL;
197 }
198 }
199
200
201 const JabberData *
202 jabber_data_find_local_by_cid(const PurpleConversation *conv, const char *cid)
203 {
204 GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv);
205
206 if (local_datas) {
207 return g_hash_table_lookup(local_datas, cid);
208 } else {
209 return NULL;
210 }
211 }
212
213 const JabberData *
214 jabber_data_find_remote_by_cid(const PurpleConversation *conv, const char *cid)
215 {
216 GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv);
217
218 if (remote_datas) {
219 return g_hash_table_lookup(remote_datas, cid);
220 } else {
221 return NULL;
222 }
223 }
224
225 void
226 jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv)
227 {
228 GHashTable *datas_by_alt = g_hash_table_lookup(local_datas_by_alt, conv);
229 GHashTable *datas_by_cid = g_hash_table_lookup(local_datas_by_cid, conv);
230
231 if (!datas_by_alt) {
232 datas_by_alt = g_hash_table_new(g_str_hash, g_str_equal);
233 g_hash_table_insert(local_datas_by_alt, conv, datas_by_alt);
234 }
235
236 if (!datas_by_cid) {
237 datas_by_cid = g_hash_table_new(g_str_hash, g_str_equal);
238 g_hash_table_insert(local_datas_by_cid, conv, datas_by_cid);
239 }
240
241 g_hash_table_insert(datas_by_alt, g_strdup(jabber_data_get_alt(data)), data);
242 g_hash_table_insert(datas_by_cid, g_strdup(jabber_data_get_cid(data)), data);
243 }
244
245 void
246 jabber_data_associate_remote_with_conv(JabberData *data, PurpleConversation *conv)
247 {
248 GHashTable *datas_by_cid = g_hash_table_lookup(remote_datas_by_cid, conv);
249
250 if (!datas_by_cid) {
251 datas_by_cid = g_hash_table_new(g_str_hash, g_str_equal);
252 g_hash_table_insert(remote_datas_by_cid, conv, datas_by_cid);
253 }
254
255 g_hash_table_insert(datas_by_cid, g_strdup(jabber_data_get_cid(data)), data);
256 }
257
258 static void
259 jabber_data_delete_from_hash_table(gpointer key, gpointer value,
260 gpointer user_data)
261 {
262 JabberData *data = (JabberData *) value;
263 jabber_data_delete(data);
264 g_free(key);
265 }
266
267 void
268 jabber_data_delete_associated_with_conv(PurpleConversation *conv)
269 {
270 GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv);
271 GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv);
272 GHashTable *local_datas_alt = g_hash_table_lookup(local_datas_by_alt, conv);
273
274 if (local_datas) {
275 g_hash_table_foreach(local_datas, jabber_data_delete_from_hash_table,
276 NULL);
277 g_hash_table_destroy(local_datas);
278 g_hash_table_remove(local_datas_by_cid, conv);
279 }
280 if (remote_datas) {
281 g_hash_table_foreach(remote_datas, jabber_data_delete_from_hash_table,
282 NULL);
283 g_hash_table_destroy(remote_datas);
284 g_hash_table_remove(remote_datas_by_cid, conv);
285 }
286 if (local_datas_alt) {
287 g_hash_table_destroy(local_datas_alt);
288 g_hash_table_remove(local_datas_by_alt, conv);
289 }
290 }
291
292 void
293 jabber_data_parse(JabberStream *js, xmlnode *packet)
294 {
295 JabberIq *result = NULL;
296 const char *who = xmlnode_get_attrib(packet, "from");
297 const PurpleConnection *gc = js->gc;
298 const PurpleAccount *account = purple_connection_get_account(gc);
299 const PurpleConversation *conv =
300 purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account);
301 xmlnode *data_node = xmlnode_get_child(packet, "data");
302 const JabberData *data =
303 jabber_data_find_local_by_cid(conv, xmlnode_get_attrib(data_node, "cid"));
304
305 if (!conv || !data) {
306 xmlnode *item_not_found = xmlnode_new("item-not-found");
307
308 result = jabber_iq_new(js, JABBER_IQ_ERROR);
309 xmlnode_set_attrib(result->node, "to", who);
310 xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
311 xmlnode_insert_child(result->node, item_not_found);
312 } else {
313 result = jabber_iq_new(js, JABBER_IQ_RESULT);
314 xmlnode_set_attrib(result->node, "to", who);
315 xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
316 xmlnode_insert_child(result->node,
317 jabber_data_get_xml_definition(data));
318 }
319 jabber_iq_send(result);
320 }