source: trunk/gtk/favicon.c @ 11599

Last change on this file since 11599 was 11599, checked in by charles, 11 years ago

(trunk) Join the 21st century and use only 1 space at the end sentences. This commit is nearly as important as the semi-annual ones that remove trailing spaces from the ends of lines of code... :)

  • Property svn:keywords set to Date Rev Author Id
File size: 4.6 KB
Line 
1/*
2 * This file Copyright (C) 2010 Mnemosyne LLC
3 *
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.
9 *
10 * $Id: favicon.c 11599 2010-12-27 19:18:17Z charles $
11 */
12
13#include <glib/gstdio.h> /* g_remove() */
14#include <gtk/gtk.h>
15
16#include <libtransmission/transmission.h>
17#include <libtransmission/web.h> /* tr_webRun() */
18
19#include "favicon.h"
20#include "util.h" /* gtr_mkdir_with_parents(), gtr_idle_add() */
21
22#define IMAGE_TYPES 4
23static const char * image_types[IMAGE_TYPES] = { "ico", "png", "gif", "jpg" };
24
25struct favicon_data
26{
27    tr_session * session;
28    GFunc func;
29    gpointer data;
30    char * host;
31    char * contents;
32    size_t len;
33    int type;
34};
35
36static char*
37get_url( const char * host, int image_type )
38{
39    return g_strdup_printf( "http://%s/favicon.%s", host, image_types[image_type] );
40}
41
42static char*
43favicon_get_cache_dir( void )
44{
45    static char * dir = NULL;
46
47    if( dir == NULL )
48    {
49        dir = g_build_filename( g_get_user_cache_dir(),
50                                "transmission",
51                                "favicons",
52                                NULL );
53        gtr_mkdir_with_parents( dir, 0777 );
54    }
55
56    return dir;
57}
58
59static char*
60favicon_get_cache_filename( const char * host )
61{
62    return g_build_filename( favicon_get_cache_dir(), host, NULL );
63}
64
65static void
66favicon_save_to_cache( const char * host, const void * data, size_t len )
67{
68    char * filename = favicon_get_cache_filename( host );
69    g_file_set_contents( filename, data, len, NULL );
70    g_free( filename );
71}
72
73static GdkPixbuf*
74favicon_load_from_cache( const char * host )
75{
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 */
79        g_remove( filename );
80    g_free( filename );
81    return pixbuf;
82}
83
84static void favicon_web_done_cb( tr_session*, long, const void*, size_t, void* );
85
86static gboolean
87favicon_web_done_idle_cb( gpointer vfav )
88{
89    GdkPixbuf * pixbuf = NULL;
90    gboolean finished = FALSE;
91    struct favicon_data * fav = vfav;
92
93    if( fav->len > 0 ) /* we got something... try to make a pixbuf from it */
94    {
95        favicon_save_to_cache( fav->host, fav->contents, fav->len );
96        pixbuf = favicon_load_from_cache( fav->host );
97        finished = pixbuf != NULL;
98    }
99
100    if( !finished ) /* no pixbuf yet... */
101    {
102        if( ++fav->type == IMAGE_TYPES ) /* failure */
103        {
104            finished = TRUE;
105        }
106        else /* keep trying */
107        {
108            char * url = get_url( fav->host, fav->type );
109
110            g_free( fav->contents );
111            fav->contents = NULL;
112            fav->len = 0;
113
114            tr_webRun( fav->session, url, NULL, favicon_web_done_cb, fav );
115            g_free( url );
116        }
117    }
118
119    if( finished )
120    {
121        fav->func( pixbuf, fav->data );
122        g_free( fav->host );
123        g_free( fav->contents );
124        g_free( fav );
125    }
126
127    return FALSE;
128}
129
130static void
131favicon_web_done_cb( tr_session    * session UNUSED,
132                     long            code UNUSED,
133                     const void    * data,
134                     size_t          len,
135                     void          * vfav )
136{
137    struct favicon_data * fav = vfav;
138    fav->contents = g_memdup( data, len );
139    fav->len = len;
140
141    gtr_idle_add( favicon_web_done_idle_cb, fav );
142}
143
144void
145gtr_get_favicon( tr_session  * session,
146                 const char  * host,
147                 GFunc         pixbuf_ready_func,
148                 gpointer      pixbuf_ready_func_data )
149{
150    GdkPixbuf * pixbuf = favicon_load_from_cache( host );
151
152    if( pixbuf != NULL )
153    {
154        pixbuf_ready_func( pixbuf, pixbuf_ready_func_data );
155    }
156    else
157    {
158        struct favicon_data * data;
159        char * url = get_url( host, 0 );
160
161        data = g_new( struct favicon_data, 1 );
162        data->session = session;
163        data->func = pixbuf_ready_func;
164        data->data = pixbuf_ready_func_data;
165        data->host = g_strdup( host );
166        data->type = 0;
167
168        tr_webRun( session, url, NULL, favicon_web_done_cb, data );
169        g_free( url );
170    }
171}
172
173void
174gtr_get_favicon_from_url( tr_session  * session,
175                          const char  * url,
176                          GFunc         pixbuf_ready_func,
177                          gpointer      pixbuf_ready_func_data )
178{
179    char * host = gtr_get_host_from_url( url );
180    gtr_get_favicon( session, host, pixbuf_ready_func, pixbuf_ready_func_data );
181    g_free( host );
182}
Note: See TracBrowser for help on using the repository browser.