Mercurial > pidgin
comparison libpurple/protocols/jabber/data.c @ 24058:305fac6af8f9
Updated to use latest spec. in XEP-0231
New namespace. Cache data globally in a running instance based on CID.
Set the PNG compression level param when saving a custom smiley from
GTKIMHTML.
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Fri, 05 Sep 2008 21:55:09 +0000 |
parents | 9d83ae2c1a4f |
children | 7b11072ba907 |
comparison
equal
deleted
inserted
replaced
24057:8997acd7d143 | 24058:305fac6af8f9 |
---|---|
23 #include "xmlnode.h" | 23 #include "xmlnode.h" |
24 #include "util.h" | 24 #include "util.h" |
25 #include "conversation.h" | 25 #include "conversation.h" |
26 #include "iq.h" | 26 #include "iq.h" |
27 | 27 |
28 /* hash table to store locally supplied data objects, by conversation and | 28 static GHashTable *local_data_by_alt = NULL; |
29 alt text (smiley shortcut) */ | 29 static GHashTable *local_data_by_cid = NULL; |
30 static GHashTable *local_datas_by_alt = NULL; | 30 static GHashTable *remote_data_by_cid = 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 | 31 |
50 JabberData * | 32 JabberData * |
51 jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type, | 33 jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type, |
52 const char *alt) | 34 JabberStream *js) |
53 { | 35 { |
54 JabberData *data = g_new0(JabberData, 1); | 36 JabberData *data = g_new0(JabberData, 1); |
55 gchar *checksum = purple_util_get_image_checksum(rawdata, size); | 37 gchar *checksum = purple_util_get_image_checksum(rawdata, size); |
56 gchar cid[256]; | 38 gchar cid[256]; |
57 | 39 |
58 /* is there some better way to generate a content ID? */ | 40 g_snprintf(cid, sizeof(cid), "sha1+%s@bob.xmpp.org", checksum); |
59 g_snprintf(cid, sizeof(cid), "%s@%s", checksum, g_get_host_name()); | |
60 g_free(checksum); | 41 g_free(checksum); |
61 | 42 |
62 data->cid = g_strdup(cid); | 43 data->cid = g_strdup(cid); |
63 data->type = g_strdup(type); | 44 data->type = g_strdup(type); |
64 data->alt = g_strdup(alt); | |
65 data->size = size; | 45 data->size = size; |
66 | 46 |
67 data->data = g_memdup(rawdata, size); | 47 data->data = g_memdup(rawdata, size); |
68 | 48 |
69 return data; | 49 return data; |
89 return NULL; | 69 return NULL; |
90 } | 70 } |
91 | 71 |
92 data->cid = g_strdup(xmlnode_get_attrib(tag, "cid")); | 72 data->cid = g_strdup(xmlnode_get_attrib(tag, "cid")); |
93 data->type = g_strdup(xmlnode_get_attrib(tag, "type")); | 73 data->type = g_strdup(xmlnode_get_attrib(tag, "type")); |
94 data->alt = g_strdup(xmlnode_get_attrib(tag, "alt")); | 74 |
95 | |
96 raw_data = xmlnode_get_data(tag); | 75 raw_data = xmlnode_get_data(tag); |
97 data->data = purple_base64_decode(raw_data, &size); | 76 data->data = purple_base64_decode(raw_data, &size); |
98 data->size = size; | 77 data->size = size; |
99 | 78 |
100 g_free(raw_data); | 79 g_free(raw_data); |
105 | 84 |
106 void | 85 void |
107 jabber_data_delete(JabberData *data) | 86 jabber_data_delete(JabberData *data) |
108 { | 87 { |
109 g_free(data->cid); | 88 g_free(data->cid); |
110 g_free(data->alt); | |
111 g_free(data->type); | 89 g_free(data->type); |
112 g_free(data->data); | 90 g_free(data->data); |
113 g_free(data); | 91 g_free(data); |
114 } | 92 } |
115 | 93 |
117 jabber_data_get_cid(const JabberData *data) | 95 jabber_data_get_cid(const JabberData *data) |
118 { | 96 { |
119 return data->cid; | 97 return data->cid; |
120 } | 98 } |
121 | 99 |
122 const char * | |
123 jabber_data_get_alt(const JabberData *data) | |
124 { | |
125 return data->alt; | |
126 } | |
127 | 100 |
128 const char * | 101 const char * |
129 jabber_data_get_type(const JabberData *data) | 102 jabber_data_get_type(const JabberData *data) |
130 { | 103 { |
131 return data->type; | 104 return data->type; |
148 { | 121 { |
149 xmlnode *tag = xmlnode_new("data"); | 122 xmlnode *tag = xmlnode_new("data"); |
150 char *base64data = purple_base64_encode(data->data, data->size); | 123 char *base64data = purple_base64_encode(data->data, data->size); |
151 | 124 |
152 xmlnode_set_namespace(tag, XEP_0231_NAMESPACE); | 125 xmlnode_set_namespace(tag, XEP_0231_NAMESPACE); |
153 xmlnode_set_attrib(tag, "alt", data->alt); | |
154 xmlnode_set_attrib(tag, "cid", data->cid); | 126 xmlnode_set_attrib(tag, "cid", data->cid); |
155 xmlnode_set_attrib(tag, "type", data->type); | 127 xmlnode_set_attrib(tag, "type", data->type); |
156 | 128 |
157 xmlnode_insert_data(tag, base64data, -1); | 129 xmlnode_insert_data(tag, base64data, -1); |
158 | 130 |
160 | 132 |
161 return tag; | 133 return tag; |
162 } | 134 } |
163 | 135 |
164 xmlnode * | 136 xmlnode * |
165 jabber_data_get_xhtml_im(const JabberData *data) | 137 jabber_data_get_xhtml_im(const JabberData *data, const gchar *alt) |
166 { | 138 { |
167 xmlnode *img = xmlnode_new("img"); | 139 xmlnode *img = xmlnode_new("img"); |
168 char src[128]; | 140 char src[128]; |
169 | 141 |
170 xmlnode_set_attrib(img, "alt", data->alt); | 142 xmlnode_set_attrib(img, "alt", alt); |
171 g_snprintf(src, sizeof(src), "cid:%s", data->cid); | 143 g_snprintf(src, sizeof(src), "cid:%s", data->cid); |
172 xmlnode_set_attrib(img, "src", src); | 144 xmlnode_set_attrib(img, "src", src); |
173 | 145 |
174 return img; | 146 return img; |
175 } | 147 } |
184 | 156 |
185 return tag; | 157 return tag; |
186 } | 158 } |
187 | 159 |
188 const JabberData * | 160 const JabberData * |
189 jabber_data_find_local_by_alt(const PurpleConversation *conv, const char *alt) | 161 jabber_data_find_local_by_alt(const gchar *alt) |
190 { | 162 { |
191 GHashTable *local_datas = g_hash_table_lookup(local_datas_by_alt, conv); | 163 return g_hash_table_lookup(local_data_by_alt, alt); |
192 | 164 } |
193 if (local_datas) { | |
194 return g_hash_table_lookup(local_datas, alt); | |
195 } else { | |
196 return NULL; | |
197 } | |
198 } | |
199 | |
200 | 165 |
201 const JabberData * | 166 const JabberData * |
202 jabber_data_find_local_by_cid(const PurpleConversation *conv, const char *cid) | 167 jabber_data_find_local_by_cid(const gchar *cid) |
203 { | 168 { |
204 GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv); | 169 return g_hash_table_lookup(local_data_by_cid, cid); |
205 | |
206 if (local_datas) { | |
207 return g_hash_table_lookup(local_datas, cid); | |
208 } else { | |
209 return NULL; | |
210 } | |
211 } | 170 } |
212 | 171 |
213 const JabberData * | 172 const JabberData * |
214 jabber_data_find_remote_by_cid(const PurpleConversation *conv, const char *cid) | 173 jabber_data_find_remote_by_cid(const gchar *cid) |
215 { | 174 { |
216 GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv); | 175 return g_hash_table_lookup(remote_data_by_cid, cid); |
217 | 176 } |
218 if (remote_datas) { | 177 |
219 return g_hash_table_lookup(remote_datas, cid); | 178 void |
220 } else { | 179 jabber_data_associate_local(JabberData *data, const gchar *alt) |
221 return NULL; | 180 { |
222 } | 181 g_hash_table_insert(local_data_by_alt, g_strdup(alt), data); |
223 } | 182 g_hash_table_insert(local_data_by_cid, g_strdup(jabber_data_get_cid(data)), |
224 | 183 data); |
225 void | 184 } |
226 jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv) | 185 |
227 { | 186 void |
228 GHashTable *datas_by_alt = g_hash_table_lookup(local_datas_by_alt, conv); | 187 jabber_data_associate_remote(JabberData *data) |
229 GHashTable *datas_by_cid = g_hash_table_lookup(local_datas_by_cid, conv); | 188 { |
230 | 189 g_hash_table_insert(remote_data_by_cid, g_strdup(jabber_data_get_cid(data)), |
231 if (!datas_by_alt) { | 190 data); |
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 } | 191 } |
291 | 192 |
292 void | 193 void |
293 jabber_data_parse(JabberStream *js, xmlnode *packet) | 194 jabber_data_parse(JabberStream *js, xmlnode *packet) |
294 { | 195 { |
295 JabberIq *result = NULL; | 196 JabberIq *result = NULL; |
296 const char *who = xmlnode_get_attrib(packet, "from"); | 197 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"); | 198 xmlnode *data_node = xmlnode_get_child(packet, "data"); |
302 const JabberData *data = | 199 const JabberData *data = |
303 jabber_data_find_local_by_cid(conv, xmlnode_get_attrib(data_node, "cid")); | 200 jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid")); |
304 | 201 |
305 if (!conv || !data) { | 202 if (!data) { |
306 xmlnode *item_not_found = xmlnode_new("item-not-found"); | 203 xmlnode *item_not_found = xmlnode_new("item-not-found"); |
307 | 204 |
308 result = jabber_iq_new(js, JABBER_IQ_ERROR); | 205 result = jabber_iq_new(js, JABBER_IQ_ERROR); |
309 xmlnode_set_attrib(result->node, "to", who); | 206 xmlnode_set_attrib(result->node, "to", who); |
310 xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); | 207 xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); |
316 xmlnode_insert_child(result->node, | 213 xmlnode_insert_child(result->node, |
317 jabber_data_get_xml_definition(data)); | 214 jabber_data_get_xml_definition(data)); |
318 } | 215 } |
319 jabber_iq_send(result); | 216 jabber_iq_send(result); |
320 } | 217 } |
218 | |
219 void | |
220 jabber_data_init(void) | |
221 { | |
222 purple_debug_info("jabber", "creating hash tables for data objects\n"); | |
223 local_data_by_alt = g_hash_table_new_full(g_str_hash, g_str_equal, | |
224 g_free, NULL); | |
225 local_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, | |
226 g_free, jabber_data_delete); | |
227 remote_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, | |
228 g_free, jabber_data_delete); | |
229 } | |
230 | |
231 void | |
232 jabber_data_uninit(void) | |
233 { | |
234 purple_debug_info("jabber", "destroying hash tables for data objects\n"); | |
235 g_hash_table_destroy(local_data_by_alt); | |
236 g_hash_table_destroy(local_data_by_cid); | |
237 g_hash_table_destroy(remote_data_by_cid); | |
238 } |