mirror of
https://github.com/transmission/transmission
synced 2024-12-25 01:03:01 +00:00
879a2afcbd
The Berne Convention says that the copyright year is moot, so instead of adding another year to each file as in previous years, I've removed the year altogether from the source code comments in libtransmission, gtk, qt, utils, daemon, and cli. Juliusz's copyright notice in tr-dht and Johannes' copyright notice in tr-lpd have been left alone; it didn't seem appropriate to modify them.
182 lines
4.6 KiB
C
182 lines
4.6 KiB
C
/*
|
|
* This file Copyright (C) Mnemosyne LLC
|
|
*
|
|
* This file is licensed by the GPL version 2. Works owned by the
|
|
* Transmission project are granted a special exemption to clause 2(b)
|
|
* so that the bulk of its code can remain under the MIT license.
|
|
* This exemption does not extend to derived works not owned by
|
|
* the Transmission project.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include <glib/gstdio.h> /* g_remove() */
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <libtransmission/transmission.h>
|
|
#include <libtransmission/web.h> /* tr_webRun() */
|
|
|
|
#include "favicon.h"
|
|
#include "util.h" /* gtr_mkdir_with_parents(), gtr_idle_add() */
|
|
|
|
#define IMAGE_TYPES 4
|
|
static const char * image_types[IMAGE_TYPES] = { "ico", "png", "gif", "jpg" };
|
|
|
|
struct favicon_data
|
|
{
|
|
tr_session * session;
|
|
GFunc func;
|
|
gpointer data;
|
|
char * host;
|
|
char * contents;
|
|
size_t len;
|
|
int type;
|
|
};
|
|
|
|
static char*
|
|
get_url( const char * host, int image_type )
|
|
{
|
|
return g_strdup_printf( "http://%s/favicon.%s", host, image_types[image_type] );
|
|
}
|
|
|
|
static char*
|
|
favicon_get_cache_dir( void )
|
|
{
|
|
static char * dir = NULL;
|
|
|
|
if( dir == NULL )
|
|
{
|
|
dir = g_build_filename( g_get_user_cache_dir(),
|
|
"transmission",
|
|
"favicons",
|
|
NULL );
|
|
gtr_mkdir_with_parents( dir, 0777 );
|
|
}
|
|
|
|
return dir;
|
|
}
|
|
|
|
static char*
|
|
favicon_get_cache_filename( const char * host )
|
|
{
|
|
return g_build_filename( favicon_get_cache_dir(), host, NULL );
|
|
}
|
|
|
|
static void
|
|
favicon_save_to_cache( const char * host, const void * data, size_t len )
|
|
{
|
|
char * filename = favicon_get_cache_filename( host );
|
|
g_file_set_contents( filename, data, len, NULL );
|
|
g_free( filename );
|
|
}
|
|
|
|
static GdkPixbuf*
|
|
favicon_load_from_cache( const char * host )
|
|
{
|
|
char * filename = favicon_get_cache_filename( host );
|
|
GdkPixbuf * pixbuf = gdk_pixbuf_new_from_file_at_size( filename, 16, 16, NULL );
|
|
if( pixbuf == NULL ) /* bad file */
|
|
g_remove( filename );
|
|
g_free( filename );
|
|
return pixbuf;
|
|
}
|
|
|
|
static void favicon_web_done_cb( tr_session*, long, const void*, size_t, void* );
|
|
|
|
static gboolean
|
|
favicon_web_done_idle_cb( gpointer vfav )
|
|
{
|
|
GdkPixbuf * pixbuf = NULL;
|
|
gboolean finished = FALSE;
|
|
struct favicon_data * fav = vfav;
|
|
|
|
if( fav->len > 0 ) /* we got something... try to make a pixbuf from it */
|
|
{
|
|
favicon_save_to_cache( fav->host, fav->contents, fav->len );
|
|
pixbuf = favicon_load_from_cache( fav->host );
|
|
finished = pixbuf != NULL;
|
|
}
|
|
|
|
if( !finished ) /* no pixbuf yet... */
|
|
{
|
|
if( ++fav->type == IMAGE_TYPES ) /* failure */
|
|
{
|
|
finished = TRUE;
|
|
}
|
|
else /* keep trying */
|
|
{
|
|
char * url = get_url( fav->host, fav->type );
|
|
|
|
g_free( fav->contents );
|
|
fav->contents = NULL;
|
|
fav->len = 0;
|
|
|
|
tr_webRun( fav->session, url, NULL, favicon_web_done_cb, fav );
|
|
g_free( url );
|
|
}
|
|
}
|
|
|
|
if( finished )
|
|
{
|
|
fav->func( pixbuf, fav->data );
|
|
g_free( fav->host );
|
|
g_free( fav->contents );
|
|
g_free( fav );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
favicon_web_done_cb( tr_session * session UNUSED,
|
|
long code UNUSED,
|
|
const void * data,
|
|
size_t len,
|
|
void * vfav )
|
|
{
|
|
struct favicon_data * fav = vfav;
|
|
fav->contents = g_memdup( data, len );
|
|
fav->len = len;
|
|
|
|
gtr_idle_add( favicon_web_done_idle_cb, fav );
|
|
}
|
|
|
|
void
|
|
gtr_get_favicon( tr_session * session,
|
|
const char * host,
|
|
GFunc pixbuf_ready_func,
|
|
gpointer pixbuf_ready_func_data )
|
|
{
|
|
GdkPixbuf * pixbuf = favicon_load_from_cache( host );
|
|
|
|
if( pixbuf != NULL )
|
|
{
|
|
pixbuf_ready_func( pixbuf, pixbuf_ready_func_data );
|
|
}
|
|
else
|
|
{
|
|
struct favicon_data * data;
|
|
char * url = get_url( host, 0 );
|
|
|
|
data = g_new( struct favicon_data, 1 );
|
|
data->session = session;
|
|
data->func = pixbuf_ready_func;
|
|
data->data = pixbuf_ready_func_data;
|
|
data->host = g_strdup( host );
|
|
data->type = 0;
|
|
|
|
tr_webRun( session, url, NULL, favicon_web_done_cb, data );
|
|
g_free( url );
|
|
}
|
|
}
|
|
|
|
void
|
|
gtr_get_favicon_from_url( tr_session * session,
|
|
const char * url,
|
|
GFunc pixbuf_ready_func,
|
|
gpointer pixbuf_ready_func_data )
|
|
{
|
|
char * host = gtr_get_host_from_url( url );
|
|
gtr_get_favicon( session, host, pixbuf_ready_func, pixbuf_ready_func_data );
|
|
g_free( host );
|
|
}
|