Mercurial > pidgin.yaz
annotate src/protocols/yahoo/yahoo_picture.c @ 12463:b1717befbb26
[gaim-migrate @ 14773]
SF Patch #1377719 from Evan Schoenberg
"A recent reorganization of how the chat_add_users() conversation UI op is
sent removed passing to the UI of whether the additions are new arrivals
or not. This information lets the UI make decisions about how to handle
the new people, what if anything to display, etc."
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Mon, 12 Dec 2005 07:35:43 +0000 |
parents | a88ca6da0b38 |
children | 33bef17125c2 |
rev | line source |
---|---|
9306 | 1 /* |
2 * gaim | |
3 * | |
4 * Gaim is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
23 | |
24 #include "internal.h" | |
25 | |
26 #include "account.h" | |
27 #include "accountopt.h" | |
28 #include "blist.h" | |
29 #include "debug.h" | |
30 #include "prpl.h" | |
31 #include "proxy.h" | |
32 #include "util.h" | |
33 | |
34 #include "yahoo.h" | |
10392 | 35 #include "yahoo_packet.h" |
9306 | 36 #include "yahoo_friend.h" |
37 #include "yahoo_picture.h" | |
38 | |
39 | |
40 struct yahoo_fetch_picture_data { | |
41 GaimConnection *gc; | |
42 char *who; | |
43 int checksum; | |
44 }; | |
45 | |
12412
a88ca6da0b38
[gaim-migrate @ 14719]
Richard Laager <rlaager@wiktel.com>
parents:
11644
diff
changeset
|
46 static void yahoo_fetch_picture_cb(void *user_data, const char *pic_data, size_t len) |
9306 | 47 { |
48 struct yahoo_fetch_picture_data *d = user_data; | |
49 GaimBuddy *b; | |
50 | |
51 if (GAIM_CONNECTION_IS_VALID(d->gc) && len) { | |
52 gaim_buddy_icons_set_for_user(gaim_connection_get_account(d->gc), d->who, (void *)pic_data, len); | |
53 b = gaim_find_buddy(gaim_connection_get_account(d->gc), d->who); | |
54 if (b) | |
55 gaim_blist_node_set_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY, d->checksum); | |
56 } else { | |
57 gaim_debug_error("yahoo", "Fetching buddy icon failed.\n"); | |
58 } | |
59 | |
60 g_free(d->who); | |
61 g_free(d); | |
62 } | |
63 | |
64 void yahoo_process_picture(GaimConnection *gc, struct yahoo_packet *pkt) | |
65 { | |
66 GSList *l = pkt->hash; | |
67 char *who = NULL, *us = NULL; | |
68 gboolean got_icon_info = FALSE, send_icon_info = FALSE; | |
69 char *url = NULL; | |
70 int checksum = 0; | |
71 | |
72 while (l) { | |
73 struct yahoo_pair *pair = l->data; | |
74 | |
75 switch (pair->key) { | |
76 case 1: | |
77 case 4: | |
78 who = pair->value; | |
79 break; | |
80 case 5: | |
81 us = pair->value; | |
82 break; | |
83 case 13: { | |
84 int tmp; | |
85 tmp = strtol(pair->value, NULL, 10); | |
86 if (tmp == 1) { | |
87 send_icon_info = TRUE; | |
88 } else if (tmp == 2) { | |
89 got_icon_info = TRUE; | |
90 } | |
91 break; | |
92 } | |
93 case 20: | |
94 url = pair->value; | |
95 break; | |
96 case 192: | |
97 checksum = strtol(pair->value, NULL, 10); | |
98 break; | |
99 } | |
100 | |
101 l = l->next; | |
102 } | |
103 | |
9675 | 104 /* Yahoo IM 6 spits out 0.png as the URL if the buddy icon is not set */ |
105 if (who && got_icon_info && url && !strncasecmp(url, "http://", 7)) { | |
9306 | 106 /* TODO: make this work p2p, try p2p before the url */ |
107 struct yahoo_fetch_picture_data *data; | |
108 GaimBuddy *b = gaim_find_buddy(gc->account, who); | |
109 if (b && (checksum == gaim_blist_node_get_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY))) | |
110 return; | |
111 | |
112 data = g_new0(struct yahoo_fetch_picture_data, 1); | |
113 data->gc = gc; | |
114 data->who = g_strdup(who); | |
115 data->checksum = checksum; | |
10651 | 116 gaim_url_fetch(url, FALSE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE, |
9306 | 117 yahoo_fetch_picture_cb, data); |
118 } else if (who && send_icon_info) { | |
119 yahoo_send_picture_info(gc, who); | |
120 } | |
121 } | |
122 | |
123 void yahoo_process_picture_update(GaimConnection *gc, struct yahoo_packet *pkt) | |
124 { | |
125 GSList *l = pkt->hash; | |
126 char *who = NULL; | |
127 int icon = 0; | |
128 | |
129 while (l) { | |
130 struct yahoo_pair *pair = l->data; | |
131 | |
132 switch (pair->key) { | |
133 case 4: | |
134 who = pair->value; | |
135 break; | |
136 case 5: | |
137 /* us */ | |
138 break; | |
139 case 206: | |
140 icon = strtol(pair->value, NULL, 10); | |
141 break; | |
142 } | |
143 l = l->next; | |
144 } | |
145 | |
146 if (who) { | |
147 if (icon == 2) | |
9310 | 148 yahoo_send_picture_request(gc, who); |
9322 | 149 else if ((icon == 0) || (icon == 1)) { |
9325 | 150 GaimBuddy *b = gaim_find_buddy(gc->account, who); |
151 YahooFriend *f; | |
9306 | 152 gaim_buddy_icons_set_for_user(gc->account, who, NULL, 0); |
9325 | 153 if (b) |
154 gaim_blist_node_remove_setting((GaimBlistNode *)b, YAHOO_ICON_CHECKSUM_KEY); | |
155 if ((f = yahoo_friend_find(gc, who))) | |
156 yahoo_friend_set_buddy_icon_need_request(f, TRUE); | |
9322 | 157 gaim_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who); |
158 } | |
9306 | 159 } |
160 } | |
161 | |
162 void yahoo_process_picture_checksum(GaimConnection *gc, struct yahoo_packet *pkt) | |
163 { | |
164 GSList *l = pkt->hash; | |
165 char *who = NULL; | |
166 int checksum = 0; | |
167 | |
168 while (l) { | |
169 struct yahoo_pair *pair = l->data; | |
170 | |
171 switch (pair->key) { | |
172 case 4: | |
173 who = pair->value; | |
174 break; | |
175 case 5: | |
176 /* us */ | |
177 break; | |
178 case 192: | |
179 checksum = strtol(pair->value, NULL, 10); | |
180 break; | |
181 } | |
182 l = l->next; | |
183 } | |
184 | |
185 if (who) { | |
186 GaimBuddy *b = gaim_find_buddy(gc->account, who); | |
187 if (b && (checksum != gaim_blist_node_get_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY))) | |
9310 | 188 yahoo_send_picture_request(gc, who); |
9306 | 189 } |
190 } | |
191 | |
192 void yahoo_process_picture_upload(GaimConnection *gc, struct yahoo_packet *pkt) | |
193 { | |
194 GaimAccount *account = gaim_connection_get_account(gc); | |
195 struct yahoo_data *yd = gc->proto_data; | |
196 GSList *l = pkt->hash; | |
197 char *url = NULL; | |
198 | |
199 while (l) { | |
200 struct yahoo_pair *pair = l->data; | |
201 | |
202 switch (pair->key) { | |
203 case 5: | |
204 /* us */ | |
205 break; | |
206 case 27: | |
207 /* filename on our computer. */ | |
208 break; | |
209 case 20: /* url at yahoo */ | |
210 url = pair->value; | |
211 case 38: /* timestamp */ | |
212 break; | |
213 } | |
214 l = l->next; | |
215 } | |
216 | |
217 if (url) { | |
218 if (yd->picture_url) | |
219 g_free(yd->picture_url); | |
220 yd->picture_url = g_strdup(url); | |
221 gaim_account_set_string(account, YAHOO_PICURL_SETTING, url); | |
222 gaim_account_set_int(account, YAHOO_PICCKSUM_SETTING, yd->picture_checksum); | |
9310 | 223 yahoo_send_picture_update(gc, 2); |
224 yahoo_send_picture_checksum(gc); | |
9306 | 225 } |
226 } | |
227 | |
9322 | 228 void yahoo_send_picture_info(GaimConnection *gc, const char *who) |
229 { | |
230 struct yahoo_data *yd = gc->proto_data; | |
231 struct yahoo_packet *pkt; | |
232 | |
9329 | 233 if (!yd->picture_url) { |
234 gaim_debug_warning("yahoo", "Attempted to send picture info without a picture\n"); | |
9322 | 235 return; |
9329 | 236 } |
9322 | 237 |
238 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0); | |
10394 | 239 yahoo_packet_hash(pkt, "sssssi", 1, gaim_connection_get_display_name(gc), |
240 4, gaim_connection_get_display_name(gc), 5, who, | |
241 13, "2", 20, yd->picture_url, 192, yd->picture_checksum); | |
10392 | 242 yahoo_packet_send_and_free(pkt, yd); |
9322 | 243 } |
9306 | 244 |
9310 | 245 void yahoo_send_picture_request(GaimConnection *gc, const char *who) |
9306 | 246 { |
247 struct yahoo_data *yd = gc->proto_data; | |
248 struct yahoo_packet *pkt; | |
249 | |
250 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0); | |
10394 | 251 yahoo_packet_hash_str(pkt, 4, gaim_connection_get_display_name(gc)); /* me */ |
252 yahoo_packet_hash_str(pkt, 5, who); /* the other guy */ | |
253 yahoo_packet_hash_str(pkt, 13, "1"); /* 1 = request, 2 = reply */ | |
10392 | 254 yahoo_packet_send_and_free(pkt, yd); |
9306 | 255 } |
256 | |
9310 | 257 void yahoo_send_picture_checksum(GaimConnection *gc) |
258 { | |
259 struct yahoo_data *yd = gc->proto_data; | |
260 struct yahoo_packet *pkt; | |
261 | |
262 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, 0); | |
11384 | 263 yahoo_packet_hash(pkt, "ssi", 1, gaim_connection_get_display_name(gc), |
10394 | 264 212, "1", 192, yd->picture_checksum); |
10392 | 265 yahoo_packet_send_and_free(pkt, yd); |
9310 | 266 } |
267 | |
268 void yahoo_send_picture_update_to_user(GaimConnection *gc, const char *who, int type) | |
269 { | |
270 struct yahoo_data *yd = gc->proto_data; | |
271 struct yahoo_packet *pkt; | |
272 | |
273 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, YAHOO_STATUS_AVAILABLE, 0); | |
11384 | 274 yahoo_packet_hash(pkt, "ssi", 1, gaim_connection_get_display_name(gc), 5, who, 206, type); |
10392 | 275 yahoo_packet_send_and_free(pkt, yd); |
9310 | 276 } |
277 | |
278 struct yspufe { | |
279 GaimConnection *gc; | |
280 int type; | |
281 }; | |
282 | |
283 static void yahoo_send_picture_update_foreach(gpointer key, gpointer value, gpointer data) | |
284 { | |
285 char *who = key; | |
286 YahooFriend *f = value; | |
287 struct yspufe *d = data; | |
288 | |
289 if (f->status != YAHOO_STATUS_OFFLINE) | |
290 yahoo_send_picture_update_to_user(d->gc, who, d->type); | |
291 } | |
292 | |
293 void yahoo_send_picture_update(GaimConnection *gc, int type) | |
294 { | |
295 struct yahoo_data *yd = gc->proto_data; | |
296 struct yspufe data; | |
297 | |
298 data.gc = gc; | |
299 data.type = type; | |
300 | |
301 g_hash_table_foreach(yd->friends, yahoo_send_picture_update_foreach, &data); | |
302 } | |
303 | |
9306 | 304 void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d) |
305 { | |
306 gaim_debug_misc("yahoo", "In yahoo_buddy_icon_upload_data_free()\n"); | |
307 | |
308 if (d->str) | |
309 g_string_free(d->str, TRUE); | |
310 if (d->filename) | |
311 g_free(d->filename); | |
312 if (d->watcher) | |
313 gaim_input_remove(d->watcher); | |
314 if (d->fd != -1) | |
315 close(d->fd); | |
316 g_free(d); | |
317 } | |
318 | |
319 /* we could care less about the server's responce, but yahoo gets grumpy if we close before it sends it */ | |
320 static void yahoo_buddy_icon_upload_reading(gpointer data, gint source, GaimInputCondition condition) | |
321 { | |
322 struct yahoo_buddy_icon_upload_data *d = data; | |
323 GaimConnection *gc = d->gc; | |
324 char buf[1024]; | |
325 | |
326 if (!GAIM_CONNECTION_IS_VALID(gc)) { | |
327 yahoo_buddy_icon_upload_data_free(d); | |
328 return; | |
329 } | |
330 | |
331 if (read(d->fd, buf, sizeof(buf)) <= 0) | |
332 yahoo_buddy_icon_upload_data_free(d); | |
333 } | |
334 | |
335 static void yahoo_buddy_icon_upload_pending(gpointer data, gint source, GaimInputCondition condition) | |
336 { | |
337 struct yahoo_buddy_icon_upload_data *d = data; | |
338 GaimConnection *gc = d->gc; | |
339 ssize_t wrote; | |
340 | |
341 if (!GAIM_CONNECTION_IS_VALID(gc)) { | |
342 yahoo_buddy_icon_upload_data_free(d); | |
343 return; | |
344 } | |
345 | |
346 wrote = write(d->fd, d->str->str + d->pos, d->str->len - d->pos); | |
347 if (wrote <= 0) { | |
348 yahoo_buddy_icon_upload_data_free(d); | |
349 return; | |
350 } | |
351 d->pos += wrote; | |
352 if (d->pos >= d->str->len) { | |
353 gaim_debug_misc("yahoo", "Finished uploading buddy icon.\n"); | |
354 gaim_input_remove(d->watcher); | |
355 d->watcher = gaim_input_add(d->fd, GAIM_INPUT_READ, yahoo_buddy_icon_upload_reading, d); | |
356 } | |
357 } | |
358 | |
359 static void yahoo_buddy_icon_upload_connected(gpointer data, gint source, GaimInputCondition condition) | |
360 { | |
361 struct yahoo_buddy_icon_upload_data *d = data; | |
362 struct yahoo_packet *pkt; | |
363 gchar *size, *post, *buf; | |
10576 | 364 const char *host; |
365 int content_length, port; | |
9306 | 366 GaimConnection *gc; |
367 GaimAccount *account; | |
368 struct yahoo_data *yd; | |
369 | |
370 if (!d) | |
371 return; | |
372 | |
373 gc = d->gc; | |
374 account = gaim_connection_get_account(gc); | |
375 yd = gc->proto_data; | |
376 | |
377 if (source < 0) { | |
378 gaim_debug_error("yahoo", "Buddy icon upload failed, no file desc.\n"); | |
379 yahoo_buddy_icon_upload_data_free(d); | |
380 return; | |
381 } | |
382 | |
383 d->fd = source; | |
384 d->watcher = gaim_input_add(d->fd, GAIM_INPUT_WRITE, yahoo_buddy_icon_upload_pending, d); | |
385 | |
386 pkt = yahoo_packet_new(0xc2, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
387 | |
10111 | 388 size = g_strdup_printf("%" G_GSIZE_FORMAT, d->str->len); |
9306 | 389 /* 1 = me, 38 = expire time(?), 0 = me, 28 = size, 27 = filename, 14 = NULL, 29 = data */ |
10394 | 390 yahoo_packet_hash_str(pkt, 1, gaim_connection_get_display_name(gc)); |
391 yahoo_packet_hash_str(pkt, 38, "604800"); /* time til expire */ | |
9306 | 392 gaim_account_set_int(account, YAHOO_PICEXPIRE_SETTING, time(NULL) + 604800); |
10394 | 393 yahoo_packet_hash_str(pkt, 0, gaim_connection_get_display_name(gc)); |
394 yahoo_packet_hash_str(pkt, 28, size); | |
395 yahoo_packet_hash_str(pkt, 27, d->filename); | |
396 yahoo_packet_hash_str(pkt, 14, ""); | |
9306 | 397 |
398 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); | |
399 buf = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t); | |
400 | |
10576 | 401 host = gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST); |
402 port = gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT); | |
403 post = g_strdup_printf("POST http://%s:%d/notifyft HTTP/1.0\r\n" | |
10111 | 404 "Content-length: %" G_GSIZE_FORMAT "\r\n" |
9306 | 405 "Host: %s:%d\r\n" |
406 "Cookie: %s\r\n" | |
407 "\r\n", | |
10576 | 408 host, port, content_length + 4 + d->str->len, host, port, buf); |
9306 | 409 write(d->fd, post, strlen(post)); |
410 | |
10392 | 411 yahoo_packet_send_special(pkt, d->fd, 8); |
9306 | 412 yahoo_packet_free(pkt); |
413 | |
414 write(d->fd, "29\xc0\x80", 4); | |
415 | |
416 g_free(size); | |
417 g_free(post); | |
418 g_free(buf); | |
419 } | |
420 | |
421 void yahoo_buddy_icon_upload(GaimConnection *gc, struct yahoo_buddy_icon_upload_data *d) | |
422 { | |
423 GaimAccount *account = gaim_connection_get_account(gc); | |
424 struct yahoo_data *yd = gc->proto_data; | |
425 | |
426 if (yd->jp) { | |
427 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xferjp_host", YAHOOJP_XFER_HOST), | |
428 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
429 yahoo_buddy_icon_upload_connected, d) == -1) | |
430 { | |
431 gaim_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n"); | |
432 yahoo_buddy_icon_upload_data_free(d); | |
433 } | |
434 } else { | |
435 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST), | |
436 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
437 yahoo_buddy_icon_upload_connected, d) == -1) | |
438 { | |
439 gaim_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n"); | |
440 yahoo_buddy_icon_upload_data_free(d); | |
441 } | |
442 } | |
443 } | |
444 | |
445 void yahoo_set_buddy_icon(GaimConnection *gc, const char *iconfile) | |
446 { | |
447 struct yahoo_data *yd = gc->proto_data; | |
448 GaimAccount *account = gc->account; | |
449 FILE *file; | |
450 struct stat st; | |
451 | |
452 if (iconfile == NULL) { | |
453 if (yd->picture_url) | |
454 g_free(yd->picture_url); | |
455 yd->picture_url = NULL; | |
456 | |
457 gaim_account_set_string(account, YAHOO_PICURL_SETTING, NULL); | |
458 gaim_account_set_int(account, YAHOO_PICCKSUM_SETTING, 0); | |
459 gaim_account_set_int(account, YAHOO_PICEXPIRE_SETTING, 0); | |
9310 | 460 if (yd->logged_in) |
461 yahoo_send_picture_update(gc, 0); | |
9306 | 462 /* TODO: check if we're connected and tell everyone we ain't not one no more */ |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10576
diff
changeset
|
463 } else if (!g_stat(iconfile, &st)) { |
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10576
diff
changeset
|
464 file = g_fopen(iconfile, "rb"); |
9306 | 465 if (file) { |
466 GString *s = g_string_sized_new(st.st_size); | |
467 size_t len; | |
468 struct yahoo_buddy_icon_upload_data *d; | |
469 int oldcksum = gaim_account_get_int(account, YAHOO_PICCKSUM_SETTING, 0); | |
470 int expire = gaim_account_get_int(account, YAHOO_PICEXPIRE_SETTING, 0); | |
471 const char *oldurl = gaim_account_get_string(account, YAHOO_PICURL_SETTING, NULL); | |
472 | |
473 g_string_set_size(s, st.st_size); | |
474 len = fread(s->str, 1, st.st_size, file); | |
475 fclose(file); | |
476 g_string_set_size(s, len); | |
477 yd->picture_checksum = g_string_hash(s); | |
478 | |
479 if ((yd->picture_checksum == oldcksum) && (expire > (time(NULL) + 60*60*24)) && | |
480 oldcksum && expire && oldurl) { | |
481 gaim_debug_misc("yahoo", "buddy icon is up to date. Not reuploading.\n"); | |
482 g_string_free(s, TRUE); | |
483 if (yd->picture_url) | |
484 g_free(yd->picture_url); | |
485 yd->picture_url = g_strdup(oldurl); | |
486 return; | |
487 } | |
488 | |
489 d = g_new0(struct yahoo_buddy_icon_upload_data, 1); | |
490 d->gc = gc; | |
491 d->str = s; | |
492 d->fd = -1; | |
493 d->filename = g_strdup(iconfile); | |
494 | |
495 if (!yd->logged_in) { | |
496 yd->picture_upload_todo = d; | |
497 return; | |
498 } | |
499 | |
500 yahoo_buddy_icon_upload(gc, d); | |
501 } else | |
502 gaim_debug_error("yahoo", | |
503 "Can't open buddy icon file!\n"); | |
504 } else | |
9779 | 505 gaim_debug_error("yahoo", |
9306 | 506 "Can't stat buddy icon file!\n"); |
507 } |