Mercurial > pidgin
annotate src/buddyicon.c @ 13967:99b9b58b19dd
[gaim-migrate @ 16523]
Fix a crazy MSN crash. Basically it's possible to have more than one
slplink associated with a given switchboard, but our code did not
allow for that. I think it happens when you're in a multi-user
chat and you do stuff with multiple users that involves slplinks.
Like maybe file transfer and buddy icon related stuff.
Tracking this down took an ungodly amount of time, but thanks to
Meebo for letting me do it :-)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 20 Jul 2006 07:31:15 +0000 |
parents | d1da27a099d2 |
children | 8bda65b88e49 |
rev | line source |
---|---|
6846 | 1 /** |
2 * @file icon.c Buddy Icon API | |
3 * @ingroup core | |
4 * | |
5 * gaim | |
6 * | |
8046 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
6846 | 10 * |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 #include "internal.h" | |
26 #include "buddyicon.h" | |
27 #include "conversation.h" | |
13554
52985bb3ec70
[gaim-migrate @ 15932]
Richard Laager <rlaager@wiktel.com>
parents:
12996
diff
changeset
|
28 #include "dbus-maybe.h" |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
29 #include "debug.h" |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
30 #include "util.h" |
6846 | 31 |
32 static GHashTable *account_cache = NULL; | |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
33 static char *cache_dir = NULL; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
34 static gboolean icon_caching = TRUE; |
6846 | 35 |
9396 | 36 static GaimBuddyIcon * |
37 gaim_buddy_icon_create(GaimAccount *account, const char *username) | |
38 { | |
39 GaimBuddyIcon *icon; | |
40 GHashTable *icon_cache; | |
41 | |
42 icon = g_new0(GaimBuddyIcon, 1); | |
13554
52985bb3ec70
[gaim-migrate @ 15932]
Richard Laager <rlaager@wiktel.com>
parents:
12996
diff
changeset
|
43 GAIM_DBUS_REGISTER_POINTER(icon, GaimBuddyIcon); |
9396 | 44 |
45 gaim_buddy_icon_set_account(icon, account); | |
46 gaim_buddy_icon_set_username(icon, username); | |
47 | |
48 icon_cache = g_hash_table_lookup(account_cache, account); | |
49 | |
50 if (icon_cache == NULL) | |
51 { | |
52 icon_cache = g_hash_table_new(g_str_hash, g_str_equal); | |
53 | |
54 g_hash_table_insert(account_cache, account, icon_cache); | |
55 } | |
56 | |
57 g_hash_table_insert(icon_cache, | |
58 (char *)gaim_buddy_icon_get_username(icon), icon); | |
59 return icon; | |
60 } | |
61 | |
6846 | 62 GaimBuddyIcon * |
63 gaim_buddy_icon_new(GaimAccount *account, const char *username, | |
64 void *icon_data, size_t icon_len) | |
65 { | |
66 GaimBuddyIcon *icon; | |
67 | |
68 g_return_val_if_fail(account != NULL, NULL); | |
69 g_return_val_if_fail(username != NULL, NULL); | |
70 g_return_val_if_fail(icon_data != NULL, NULL); | |
71 g_return_val_if_fail(icon_len > 0, NULL); | |
72 | |
73 icon = gaim_buddy_icons_find(account, username); | |
74 | |
75 if (icon == NULL) | |
9396 | 76 icon = gaim_buddy_icon_create(account, username); |
6846 | 77 |
9327 | 78 gaim_buddy_icon_ref(icon); |
6846 | 79 gaim_buddy_icon_set_data(icon, icon_data, icon_len); |
80 | |
11423
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
81 /* gaim_buddy_icon_set_data() makes blist.c or |
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
82 * conversation.c, or both, take a reference. |
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
83 * |
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
84 * Plus, we leave one for the caller of this function. |
9323 | 85 */ |
11423
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
86 |
6846 | 87 return icon; |
88 } | |
89 | |
90 void | |
91 gaim_buddy_icon_destroy(GaimBuddyIcon *icon) | |
92 { | |
7311
1c8830db0189
[gaim-migrate @ 7895]
Christian Hammond <chipx86@chipx86.com>
parents:
7125
diff
changeset
|
93 GaimConversation *conv; |
1c8830db0189
[gaim-migrate @ 7895]
Christian Hammond <chipx86@chipx86.com>
parents:
7125
diff
changeset
|
94 GaimAccount *account; |
6846 | 95 GHashTable *icon_cache; |
7311
1c8830db0189
[gaim-migrate @ 7895]
Christian Hammond <chipx86@chipx86.com>
parents:
7125
diff
changeset
|
96 const char *username; |
9305
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
97 GSList *sl, *list; |
6846 | 98 |
99 g_return_if_fail(icon != NULL); | |
100 | |
101 if (icon->ref_count > 0) | |
102 { | |
9323 | 103 /* If the ref count is greater than 0, then we weren't called from |
104 * gaim_buddy_icon_unref(). So we go through and ask everyone to | |
105 * unref us. Then we return, since we know somewhere along the | |
106 * line we got called recursively by one of the unrefs, and the | |
107 * icon is already destroyed. | |
108 */ | |
109 account = gaim_buddy_icon_get_account(icon); | |
110 username = gaim_buddy_icon_get_username(icon); | |
111 | |
11338 | 112 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, username, account); |
10246 | 113 if (conv != NULL) |
9323 | 114 gaim_conv_im_set_icon(GAIM_CONV_IM(conv), NULL); |
115 | |
116 for (list = sl = gaim_find_buddies(account, username); sl != NULL; | |
117 sl = sl->next) | |
118 { | |
119 GaimBuddy *buddy = (GaimBuddy *)sl->data; | |
120 | |
121 gaim_buddy_set_icon(buddy, NULL); | |
122 } | |
123 | |
124 g_slist_free(list); | |
6846 | 125 |
126 return; | |
127 } | |
128 | |
129 icon_cache = g_hash_table_lookup(account_cache, | |
130 gaim_buddy_icon_get_account(icon)); | |
131 | |
132 if (icon_cache != NULL) | |
133 g_hash_table_remove(icon_cache, gaim_buddy_icon_get_username(icon)); | |
134 | |
13872 | 135 g_free(icon->username); |
136 g_free(icon->data); | |
13554
52985bb3ec70
[gaim-migrate @ 15932]
Richard Laager <rlaager@wiktel.com>
parents:
12996
diff
changeset
|
137 GAIM_DBUS_UNREGISTER_POINTER(icon); |
6846 | 138 g_free(icon); |
139 } | |
140 | |
141 GaimBuddyIcon * | |
142 gaim_buddy_icon_ref(GaimBuddyIcon *icon) | |
143 { | |
144 g_return_val_if_fail(icon != NULL, NULL); | |
145 | |
146 icon->ref_count++; | |
147 | |
148 return icon; | |
149 } | |
150 | |
151 GaimBuddyIcon * | |
152 gaim_buddy_icon_unref(GaimBuddyIcon *icon) | |
153 { | |
154 g_return_val_if_fail(icon != NULL, NULL); | |
12250
5e2a365af01b
[gaim-migrate @ 14552]
Richard Laager <rlaager@wiktel.com>
parents:
12097
diff
changeset
|
155 g_return_val_if_fail(icon->ref_count > 0, NULL); |
6846 | 156 |
157 icon->ref_count--; | |
158 | |
159 if (icon->ref_count == 0) | |
160 { | |
161 gaim_buddy_icon_destroy(icon); | |
162 | |
163 return NULL; | |
164 } | |
165 | |
166 return icon; | |
167 } | |
168 | |
169 void | |
170 gaim_buddy_icon_update(GaimBuddyIcon *icon) | |
171 { | |
172 GaimConversation *conv; | |
173 GaimAccount *account; | |
174 const char *username; | |
8550 | 175 GSList *sl, *list; |
6846 | 176 |
177 g_return_if_fail(icon != NULL); | |
178 | |
179 account = gaim_buddy_icon_get_account(icon); | |
180 username = gaim_buddy_icon_get_username(icon); | |
181 | |
9305
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
182 for (list = sl = gaim_find_buddies(account, username); sl != NULL; |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
183 sl = sl->next) |
6846 | 184 { |
185 GaimBuddy *buddy = (GaimBuddy *)sl->data; | |
186 | |
187 gaim_buddy_set_icon(buddy, icon); | |
188 } | |
189 | |
8550 | 190 g_slist_free(list); |
191 | |
11338 | 192 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, username, account); |
6846 | 193 |
10246 | 194 if (conv != NULL) |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
6886
diff
changeset
|
195 gaim_conv_im_set_icon(GAIM_CONV_IM(conv), icon); |
6846 | 196 } |
197 | |
11040
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
198 static void |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
199 delete_icon_cache_file(const char *dirname, const char *old_icon) |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
200 { |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
201 struct stat st; |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
202 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
203 g_return_if_fail(dirname != NULL); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
204 g_return_if_fail(old_icon != NULL); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
205 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
206 if (g_stat(old_icon, &st) == 0) |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
207 g_unlink(old_icon); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
208 else |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
209 { |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
210 char *filename = g_build_filename(dirname, old_icon, NULL); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
211 if (g_stat(filename, &st) == 0) |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
212 g_unlink(filename); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
213 g_free(filename); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
214 } |
12996
fbdc9e7ef77a
[gaim-migrate @ 15349]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12995
diff
changeset
|
215 gaim_debug_info("buddyicon", "Uncached file %s\n", old_icon); |
11040
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
216 } |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
217 |
6846 | 218 void |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
219 gaim_buddy_icon_cache(GaimBuddyIcon *icon, GaimBuddy *buddy) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
220 { |
11137 | 221 const guchar *data; |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
222 const char *dirname; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
223 char *random; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
224 char *filename; |
7125 | 225 const char *old_icon; |
12995
595f690399e4
[gaim-migrate @ 15348]
Richard Laager <rlaager@wiktel.com>
parents:
12250
diff
changeset
|
226 size_t len = 0; |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
227 FILE *file = NULL; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
228 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
229 g_return_if_fail(icon != NULL); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
230 g_return_if_fail(buddy != NULL); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
231 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
232 if (!gaim_buddy_icons_is_caching()) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
233 return; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
234 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
235 data = gaim_buddy_icon_get_data(icon, &len); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
236 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
237 random = g_strdup_printf("%x", g_random_int()); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
238 dirname = gaim_buddy_icons_get_cache_dir(); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
239 filename = g_build_filename(dirname, random, NULL); |
7721 | 240 old_icon = gaim_blist_node_get_string((GaimBlistNode*)buddy, "buddy_icon"); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
241 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
242 if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
243 { |
12996
fbdc9e7ef77a
[gaim-migrate @ 15349]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12995
diff
changeset
|
244 gaim_debug_info("buddyicon", "Creating icon cache directory.\n"); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
245 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10523
diff
changeset
|
246 if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
247 { |
12996
fbdc9e7ef77a
[gaim-migrate @ 15349]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12995
diff
changeset
|
248 gaim_debug_error("buddyicon", |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
249 "Unable to create directory %s: %s\n", |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
250 dirname, strerror(errno)); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
251 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
252 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
253 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10523
diff
changeset
|
254 if ((file = g_fopen(filename, "wb")) != NULL) |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
255 { |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
256 fwrite(data, 1, len, file); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
257 fclose(file); |
12996
fbdc9e7ef77a
[gaim-migrate @ 15349]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12995
diff
changeset
|
258 gaim_debug_info("buddyicon", "Wrote file %s\n", filename); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
259 } |
11021 | 260 else |
261 { | |
12996
fbdc9e7ef77a
[gaim-migrate @ 15349]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12995
diff
changeset
|
262 gaim_debug_error("buddyicon", "Unable to create file %s: %s\n", |
11021 | 263 filename, strerror(errno)); |
264 } | |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
265 |
9747 | 266 g_free(filename); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
267 |
9747 | 268 if (old_icon != NULL) |
11040
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
269 delete_icon_cache_file(dirname, old_icon); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
270 |
9747 | 271 gaim_blist_node_set_string((GaimBlistNode *)buddy, "buddy_icon", random); |
272 | |
273 g_free(random); | |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
274 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
275 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
276 void |
11040
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
277 gaim_buddy_icon_uncache(GaimBuddy *buddy) |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
278 { |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
279 const char *old_icon; |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
280 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
281 g_return_if_fail(buddy != NULL); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
282 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
283 old_icon = gaim_blist_node_get_string((GaimBlistNode *)buddy, "buddy_icon"); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
284 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
285 if (old_icon != NULL) |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
286 delete_icon_cache_file(gaim_buddy_icons_get_cache_dir(), old_icon); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
287 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
288 gaim_blist_node_remove_setting((GaimBlistNode *)buddy, "buddy_icon"); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
289 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
290 /* Unset the icon in case this function is called from |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
291 * something other than gaim_buddy_set_icon(). */ |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
292 if (buddy->icon != NULL) |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
293 { |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
294 gaim_buddy_icon_unref(buddy->icon); |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
295 buddy->icon = NULL; |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
296 } |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
297 } |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
298 |
3428ad6f5049
[gaim-migrate @ 12940]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
299 void |
6846 | 300 gaim_buddy_icon_set_account(GaimBuddyIcon *icon, GaimAccount *account) |
301 { | |
302 g_return_if_fail(icon != NULL); | |
303 g_return_if_fail(account != NULL); | |
304 | |
305 icon->account = account; | |
306 } | |
307 | |
308 void | |
309 gaim_buddy_icon_set_username(GaimBuddyIcon *icon, const char *username) | |
310 { | |
311 g_return_if_fail(icon != NULL); | |
312 g_return_if_fail(username != NULL); | |
313 | |
13872 | 314 g_free(icon->username); |
6846 | 315 |
316 icon->username = g_strdup(username); | |
317 } | |
318 | |
319 void | |
320 gaim_buddy_icon_set_data(GaimBuddyIcon *icon, void *data, size_t len) | |
321 { | |
322 g_return_if_fail(icon != NULL); | |
323 | |
13872 | 324 g_free(icon->data); |
6846 | 325 |
326 if (data != NULL && len > 0) | |
327 { | |
328 icon->data = g_memdup(data, len); | |
329 icon->len = len; | |
330 } | |
331 else | |
332 { | |
333 icon->data = NULL; | |
334 icon->len = 0; | |
335 } | |
336 | |
337 gaim_buddy_icon_update(icon); | |
338 } | |
339 | |
340 GaimAccount * | |
341 gaim_buddy_icon_get_account(const GaimBuddyIcon *icon) | |
342 { | |
343 g_return_val_if_fail(icon != NULL, NULL); | |
344 | |
345 return icon->account; | |
346 } | |
347 | |
348 const char * | |
349 gaim_buddy_icon_get_username(const GaimBuddyIcon *icon) | |
350 { | |
351 g_return_val_if_fail(icon != NULL, NULL); | |
352 | |
353 return icon->username; | |
354 } | |
355 | |
11137 | 356 const guchar * |
6846 | 357 gaim_buddy_icon_get_data(const GaimBuddyIcon *icon, size_t *len) |
358 { | |
359 g_return_val_if_fail(icon != NULL, NULL); | |
360 | |
361 if (len != NULL) | |
362 *len = icon->len; | |
363 | |
364 return icon->data; | |
365 } | |
366 | |
10953 | 367 const char * |
368 gaim_buddy_icon_get_type(const GaimBuddyIcon *icon) | |
369 { | |
370 const void *data; | |
371 size_t len; | |
372 | |
373 g_return_val_if_fail(icon != NULL, NULL); | |
374 | |
375 data = gaim_buddy_icon_get_data(icon, &len); | |
376 | |
377 /* TODO: Find a way to do this with GDK */ | |
378 if (len >= 4) | |
379 { | |
380 if (!strncmp(data, "BM", 2)) | |
381 return "bmp"; | |
382 else if (!strncmp(data, "GIF8", 4)) | |
383 return "gif"; | |
384 else if (!strncmp(data, "\xff\xd8\xff\xe0", 4)) | |
385 return "jpg"; | |
386 else if (!strncmp(data, "\x89PNG", 4)) | |
387 return "png"; | |
388 } | |
389 | |
390 return NULL; | |
391 } | |
392 | |
6846 | 393 void |
394 gaim_buddy_icons_set_for_user(GaimAccount *account, const char *username, | |
395 void *icon_data, size_t icon_len) | |
396 { | |
397 g_return_if_fail(account != NULL); | |
398 g_return_if_fail(username != NULL); | |
399 | |
9305
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
400 if (icon_data == NULL || icon_len == 0) |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
401 { |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
402 GaimBuddyIcon *buddy_icon; |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
403 |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
404 buddy_icon = gaim_buddy_icons_find(account, username); |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
405 |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
406 if (buddy_icon != NULL) |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
407 gaim_buddy_icon_destroy(buddy_icon); |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
408 } |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
409 else |
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
410 { |
11423
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
411 GaimBuddyIcon *icon = gaim_buddy_icon_new(account, username, icon_data, icon_len); |
202a3b3c5a88
[gaim-migrate @ 13660]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
412 gaim_buddy_icon_unref(icon); |
9305
0c201a2386c7
[gaim-migrate @ 10113]
Christian Hammond <chipx86@chipx86.com>
parents:
9285
diff
changeset
|
413 } |
6846 | 414 } |
415 | |
416 GaimBuddyIcon * | |
9396 | 417 gaim_buddy_icons_find(GaimAccount *account, const char *username) |
6846 | 418 { |
419 GHashTable *icon_cache; | |
9396 | 420 GaimBuddyIcon *ret = NULL; |
9747 | 421 char *filename = NULL; |
6846 | 422 |
423 g_return_val_if_fail(account != NULL, NULL); | |
424 g_return_val_if_fail(username != NULL, NULL); | |
425 | |
426 icon_cache = g_hash_table_lookup(account_cache, account); | |
427 | |
9396 | 428 if ((icon_cache == NULL) || ((ret = g_hash_table_lookup(icon_cache, username)) == NULL)) { |
429 const char *file; | |
430 struct stat st; | |
431 GaimBuddy *b = gaim_find_buddy(account, username); | |
432 | |
433 if (!b) | |
434 return NULL; | |
435 | |
436 if ((file = gaim_blist_node_get_string((GaimBlistNode*)b, "buddy_icon")) == NULL) | |
437 return NULL; | |
6846 | 438 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10523
diff
changeset
|
439 if (!g_stat(file, &st)) |
9747 | 440 filename = g_strdup(file); |
441 else | |
442 filename = g_build_filename(gaim_buddy_icons_get_cache_dir(), file, NULL); | |
443 | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10523
diff
changeset
|
444 if (!g_stat(filename, &st)) { |
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10523
diff
changeset
|
445 FILE *f = g_fopen(filename, "rb"); |
9396 | 446 if (f) { |
447 char *data = g_malloc(st.st_size); | |
448 fread(data, 1, st.st_size, f); | |
449 fclose(f); | |
450 ret = gaim_buddy_icon_create(account, username); | |
451 gaim_buddy_icon_ref(ret); | |
452 gaim_buddy_icon_set_data(ret, data, st.st_size); | |
453 gaim_buddy_icon_unref(ret); | |
454 g_free(data); | |
9747 | 455 g_free(filename); |
9396 | 456 return ret; |
457 } | |
458 } | |
9747 | 459 g_free(filename); |
9396 | 460 } |
461 | |
462 return ret; | |
6846 | 463 } |
464 | |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
465 void |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
466 gaim_buddy_icons_set_caching(gboolean caching) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
467 { |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
468 icon_caching = caching; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
469 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
470 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
471 gboolean |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
472 gaim_buddy_icons_is_caching(void) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
473 { |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
474 return icon_caching; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
475 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
476 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
477 void |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
478 gaim_buddy_icons_set_cache_dir(const char *dir) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
479 { |
10811
dc59482c8d37
[gaim-migrate @ 12464]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
480 g_return_if_fail(dir != NULL); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
481 |
13872 | 482 g_free(cache_dir); |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
483 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
484 cache_dir = g_strdup(dir); |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
485 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
486 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
487 const char * |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
488 gaim_buddy_icons_get_cache_dir(void) |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
489 { |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
490 return cache_dir; |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
491 } |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
492 |
11303
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
493 char *gaim_buddy_icons_get_full_path(const char *icon) { |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
494 struct stat st; |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
495 |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
496 if (icon == NULL) |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
497 return NULL; |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
498 |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
499 if (g_stat(icon, &st) == 0) |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
500 return g_strdup(icon); |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
501 else |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
502 return g_build_filename(gaim_buddy_icons_get_cache_dir(), icon, NULL); |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
503 } |
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11256
diff
changeset
|
504 |
6846 | 505 void * |
506 gaim_buddy_icons_get_handle() | |
507 { | |
508 static int handle; | |
509 | |
510 return &handle; | |
511 } | |
512 | |
513 void | |
514 gaim_buddy_icons_init() | |
515 { | |
516 account_cache = g_hash_table_new_full( | |
517 g_direct_hash, g_direct_equal, | |
518 NULL, (GFreeFunc)g_hash_table_destroy); | |
6886
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
519 |
b5fb1d5282e5
[gaim-migrate @ 7432]
Christian Hammond <chipx86@chipx86.com>
parents:
6846
diff
changeset
|
520 cache_dir = g_build_filename(gaim_user_dir(), "icons", NULL); |
6846 | 521 } |
522 | |
523 void | |
524 gaim_buddy_icons_uninit() | |
525 { | |
526 g_hash_table_destroy(account_cache); | |
527 } | |
10483 | 528 |
529 void gaim_buddy_icon_get_scale_size(GaimBuddyIconSpec *spec, int *width, int *height) | |
530 { | |
531 if(spec && spec->scale_rules & GAIM_ICON_SCALE_DISPLAY) { | |
10523 | 532 int new_width, new_height; |
533 | |
534 new_width = *width; | |
535 new_height = *height; | |
536 | |
10483 | 537 if(*width < spec->min_width) |
10523 | 538 new_width = spec->min_width; |
10483 | 539 else if(*width > spec->max_width) |
10523 | 540 new_width = spec->max_width; |
10483 | 541 |
542 if(*height < spec->min_height) | |
10523 | 543 new_height = spec->min_height; |
10483 | 544 else if(*height > spec->max_height) |
10523 | 545 new_height = spec->max_height; |
546 | |
547 /* preserve aspect ratio */ | |
548 if ((double)*height * (double)new_width > | |
549 (double)*width * (double)new_height) { | |
550 new_width = 0.5 + (double)*width * (double)new_height / (double)*height; | |
551 } else { | |
552 new_height = 0.5 + (double)*height * (double)new_width / (double)*width; | |
553 } | |
554 | |
555 *width = new_width; | |
556 *height = new_height; | |
10483 | 557 } |
558 } | |
559 |