2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2 (b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: favicon.c 14133 2013-07-20 16:37:59Z jordan $
13 #include <glib/gstdio.h> /* g_remove () */
16 #include <libtransmission/transmission.h>
17 #include <libtransmission/web.h> /* tr_webRun () */
20 #include "util.h" /* gtr_get_host_from_url () */
23 static const char * image_types
[IMAGE_TYPES
] = { "ico", "png", "gif", "jpg" };
37 get_url (const char * host
, int image_type
)
39 return g_strdup_printf ("http://%s/favicon.%s", host
, image_types
[image_type
]);
43 favicon_get_cache_dir (void)
45 static char * dir
= NULL
;
49 dir
= g_build_filename (g_get_user_cache_dir (),
53 g_mkdir_with_parents (dir
, 0777);
60 favicon_get_cache_filename (const char * host
)
62 return g_build_filename (favicon_get_cache_dir (), host
, NULL
);
66 favicon_save_to_cache (const char * host
, const void * data
, size_t len
)
68 char * filename
= favicon_get_cache_filename (host
);
69 g_file_set_contents (filename
, data
, len
, NULL
);
74 favicon_load_from_cache (const char * host
)
76 char * filename
= favicon_get_cache_filename (host
);
77 GdkPixbuf
* pixbuf
= gdk_pixbuf_new_from_file_at_size (filename
, 16, 16, NULL
);
78 if (pixbuf
== NULL
) /* bad file */
84 static void favicon_web_done_cb (tr_session
*, bool, bool, long, const void*, size_t, void*);
87 favicon_web_done_idle_cb (gpointer vfav
)
89 GdkPixbuf
* pixbuf
= NULL
;
90 gboolean finished
= FALSE
;
91 struct favicon_data
* fav
= vfav
;
93 if (fav
->len
> 0) /* we got something... try to make a pixbuf from it */
95 favicon_save_to_cache (fav
->host
, fav
->contents
, fav
->len
);
96 pixbuf
= favicon_load_from_cache (fav
->host
);
97 finished
= pixbuf
!= NULL
;
100 if (!finished
) /* no pixbuf yet... */
102 if (++fav
->type
== IMAGE_TYPES
) /* failure */
106 else /* keep trying */
108 char * url
= get_url (fav
->host
, fav
->type
);
110 g_free (fav
->contents
);
111 fav
->contents
= NULL
;
114 tr_webRun (fav
->session
, url
, favicon_web_done_cb
, fav
);
121 fav
->func (pixbuf
, fav
->data
);
123 g_free (fav
->contents
);
127 return G_SOURCE_REMOVE
;
131 favicon_web_done_cb (tr_session
* session UNUSED
,
132 bool did_connect UNUSED
,
133 bool did_timeout UNUSED
,
139 struct favicon_data
* fav
= vfav
;
140 fav
->contents
= g_memdup (data
, len
);
143 gdk_threads_add_idle (favicon_web_done_idle_cb
, fav
);
147 gtr_get_favicon (tr_session
* session
,
149 GFunc pixbuf_ready_func
,
150 gpointer pixbuf_ready_func_data
)
152 GdkPixbuf
* pixbuf
= favicon_load_from_cache (host
);
156 pixbuf_ready_func (pixbuf
, pixbuf_ready_func_data
);
160 struct favicon_data
* data
;
161 char * url
= get_url (host
, 0);
163 data
= g_new (struct favicon_data
, 1);
164 data
->session
= session
;
165 data
->func
= pixbuf_ready_func
;
166 data
->data
= pixbuf_ready_func_data
;
167 data
->host
= g_strdup (host
);
170 tr_webRun (session
, url
, favicon_web_done_cb
, data
);
176 gtr_get_favicon_from_url (tr_session
* session
,
178 GFunc pixbuf_ready_func
,
179 gpointer pixbuf_ready_func_data
)
182 gtr_get_host_from_url (host
, sizeof (host
), url
);
183 gtr_get_favicon (session
, host
, pixbuf_ready_func
, pixbuf_ready_func_data
);