2010-03-15 02:53:31 +00:00
|
|
|
/*
|
2014-01-19 01:09:44 +00:00
|
|
|
* This file Copyright (C) 2012-2014 Mnemosyne LLC
|
2010-03-15 02:53:31 +00:00
|
|
|
*
|
2014-01-21 03:10:30 +00:00
|
|
|
* It may be used under the GNU GPL versions 2 or 3
|
2014-01-19 01:09:44 +00:00
|
|
|
* or any future license endorsed by Mnemosyne LLC.
|
2010-03-15 02:53:31 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-04-21 07:40:57 +00:00
|
|
|
#include <glib/gstdio.h> /* g_remove() */
|
2010-03-15 02:53:31 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
#include <libtransmission/transmission.h>
|
2017-04-21 07:40:57 +00:00
|
|
|
#include <libtransmission/web.h> /* tr_webRun() */
|
2010-03-15 02:53:31 +00:00
|
|
|
|
|
|
|
#include "favicon.h"
|
2017-04-21 07:40:57 +00:00
|
|
|
#include "util.h" /* gtr_get_host_from_url() */
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2010-03-17 20:30:04 +00:00
|
|
|
#define IMAGE_TYPES 4
|
2017-04-20 16:02:19 +00:00
|
|
|
static char const* image_types[IMAGE_TYPES] = { "ico", "png", "gif", "jpg" };
|
2010-03-17 20:30:04 +00:00
|
|
|
|
2010-03-15 02:53:31 +00:00
|
|
|
struct favicon_data
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_session* session;
|
2010-03-15 02:53:31 +00:00
|
|
|
GFunc func;
|
|
|
|
gpointer data;
|
2017-04-19 12:04:45 +00:00
|
|
|
char* host;
|
|
|
|
char* contents;
|
2010-03-15 02:53:31 +00:00
|
|
|
size_t len;
|
2010-03-17 20:30:04 +00:00
|
|
|
int type;
|
2010-03-15 02:53:31 +00:00
|
|
|
};
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static char* get_url(char const* host, int image_type)
|
2010-03-17 20:30:04 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
return g_strdup_printf("http://%s/favicon.%s", host, image_types[image_type]);
|
2010-03-17 20:30:04 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static char* favicon_get_cache_dir(void)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
static char* dir = NULL;
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2012-12-05 17:29:46 +00:00
|
|
|
if (dir == NULL)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
dir = g_build_filename(g_get_user_cache_dir(), "transmission", "favicons", NULL);
|
|
|
|
g_mkdir_with_parents(dir, 0777);
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static char* favicon_get_cache_filename(char const* host)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
return g_build_filename(favicon_get_cache_dir(), host, NULL);
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static void favicon_save_to_cache(char const* host, void const* data, size_t len)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
char* filename = favicon_get_cache_filename(host);
|
|
|
|
g_file_set_contents(filename, data, len, NULL);
|
|
|
|
g_free(filename);
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static GdkPixbuf* favicon_load_from_cache(char const* host)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
char* filename = favicon_get_cache_filename(host);
|
|
|
|
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 16, 16, NULL);
|
|
|
|
|
2012-12-05 17:29:46 +00:00
|
|
|
if (pixbuf == NULL) /* bad file */
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
g_remove(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(filename);
|
2010-03-15 02:53:31 +00:00
|
|
|
return pixbuf;
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static void favicon_web_done_cb(tr_session*, bool, bool, long, void const*, size_t, void*);
|
2010-03-17 20:30:04 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static gboolean favicon_web_done_idle_cb(gpointer vfav)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GdkPixbuf* pixbuf = NULL;
|
2010-03-17 20:30:04 +00:00
|
|
|
gboolean finished = FALSE;
|
2017-04-19 12:04:45 +00:00
|
|
|
struct favicon_data* fav = vfav;
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2012-12-05 17:29:46 +00:00
|
|
|
if (fav->len > 0) /* we got something... try to make a pixbuf from it */
|
2010-03-15 15:07:23 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
favicon_save_to_cache(fav->host, fav->contents, fav->len);
|
|
|
|
pixbuf = favicon_load_from_cache(fav->host);
|
2010-03-17 20:30:04 +00:00
|
|
|
finished = pixbuf != NULL;
|
2010-03-15 15:07:23 +00:00
|
|
|
}
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2012-12-05 17:29:46 +00:00
|
|
|
if (!finished) /* no pixbuf yet... */
|
2010-03-17 20:30:04 +00:00
|
|
|
{
|
2012-12-05 17:29:46 +00:00
|
|
|
if (++fav->type == IMAGE_TYPES) /* failure */
|
2010-03-17 20:30:04 +00:00
|
|
|
{
|
|
|
|
finished = TRUE;
|
|
|
|
}
|
|
|
|
else /* keep trying */
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
char* url = get_url(fav->host, fav->type);
|
2010-03-17 20:30:04 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(fav->contents);
|
2010-03-17 20:30:04 +00:00
|
|
|
fav->contents = NULL;
|
|
|
|
fav->len = 0;
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_webRun(fav->session, url, favicon_web_done_cb, fav);
|
|
|
|
g_free(url);
|
2010-03-17 20:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-05 17:29:46 +00:00
|
|
|
if (finished)
|
2010-03-17 20:30:04 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
fav->func(pixbuf, fav->data);
|
|
|
|
g_free(fav->host);
|
|
|
|
g_free(fav->contents);
|
|
|
|
g_free(fav);
|
2010-03-17 20:30:04 +00:00
|
|
|
}
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2013-07-20 16:37:59 +00:00
|
|
|
return G_SOURCE_REMOVE;
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
|
|
|
|
2020-08-18 17:31:06 +00:00
|
|
|
static void favicon_web_done_cb(tr_session* session, bool did_connect, bool did_timeout, long code, void const* data,
|
|
|
|
size_t len, void* vfav)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2020-08-18 10:36:10 +00:00
|
|
|
TR_UNUSED(session);
|
|
|
|
TR_UNUSED(did_connect);
|
|
|
|
TR_UNUSED(did_timeout);
|
|
|
|
TR_UNUSED(code);
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
struct favicon_data* fav = vfav;
|
|
|
|
fav->contents = g_memdup(data, len);
|
2010-03-15 02:53:31 +00:00
|
|
|
fav->len = len;
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
gdk_threads_add_idle(favicon_web_done_idle_cb, fav);
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
2010-03-17 17:07:40 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
void gtr_get_favicon(tr_session* session, char const* host, GFunc pixbuf_ready_func, gpointer pixbuf_ready_func_data)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GdkPixbuf* pixbuf = favicon_load_from_cache(host);
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2012-12-05 17:29:46 +00:00
|
|
|
if (pixbuf != NULL)
|
2010-03-15 02:53:31 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
pixbuf_ready_func(pixbuf, pixbuf_ready_func_data);
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
struct favicon_data* data;
|
|
|
|
char* url = get_url(host, 0);
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
data = g_new(struct favicon_data, 1);
|
2010-03-17 20:30:04 +00:00
|
|
|
data->session = session;
|
2010-03-15 02:53:31 +00:00
|
|
|
data->func = pixbuf_ready_func;
|
|
|
|
data->data = pixbuf_ready_func_data;
|
2017-04-19 12:04:45 +00:00
|
|
|
data->host = g_strdup(host);
|
2010-03-17 20:30:04 +00:00
|
|
|
data->type = 0;
|
2010-03-15 02:53:31 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_webRun(session, url, favicon_web_done_cb, data);
|
|
|
|
g_free(url);
|
2010-03-15 02:53:31 +00:00
|
|
|
}
|
|
|
|
}
|
2010-04-23 01:46:02 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
void gtr_get_favicon_from_url(tr_session* session, char const* url, GFunc pixbuf_ready_func, gpointer pixbuf_ready_func_data)
|
2010-04-23 01:46:02 +00:00
|
|
|
{
|
2011-04-04 16:54:09 +00:00
|
|
|
char host[1024];
|
2017-04-19 12:04:45 +00:00
|
|
|
gtr_get_host_from_url(host, sizeof(host), url);
|
|
|
|
gtr_get_favicon(session, host, pixbuf_ready_func, pixbuf_ready_func_data);
|
2010-04-23 01:46:02 +00:00
|
|
|
}
|