Mercurial > pidgin
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 } |