source: trunk/gtk/favicon.c @ 14070

Last change on this file since 14070 was 14070, checked in by jordan, 9 years ago

(trunk) update web.h's API s.t. there's an explicit function to use when downloading webseed content.

  • Property svn:keywords set to Date Rev Author Id
File size: 4.7 KB
Line 
1/*
2 * This file Copyright (C) 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 14070 2013-04-13 20:25:28Z jordan $
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_get_host_from_url () */
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        g_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*, bool, bool, 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, 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                     bool            did_connect UNUSED,
133                     bool            did_timeout UNUSED,
134                     long            code UNUSED,
135                     const void    * data,
136                     size_t          len,
137                     void          * vfav)
138{
139    struct favicon_data * fav = vfav;
140    fav->contents = g_memdup (data, len);
141    fav->len = len;
142
143    gdk_threads_add_idle (favicon_web_done_idle_cb, fav);
144}
145
146void
147gtr_get_favicon (tr_session  * session,
148                 const char  * host,
149                 GFunc         pixbuf_ready_func,
150                 gpointer      pixbuf_ready_func_data)
151{
152    GdkPixbuf * pixbuf = favicon_load_from_cache (host);
153
154    if (pixbuf != NULL)
155    {
156        pixbuf_ready_func (pixbuf, pixbuf_ready_func_data);
157    }
158    else
159    {
160        struct favicon_data * data;
161        char * url = get_url (host, 0);
162
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);
168        data->type = 0;
169
170        tr_webRun (session, url, favicon_web_done_cb, data);
171        g_free (url);
172    }
173}
174
175void
176gtr_get_favicon_from_url (tr_session  * session,
177                          const char  * url,
178                          GFunc         pixbuf_ready_func,
179                          gpointer      pixbuf_ready_func_data)
180{
181    char host[1024];
182    gtr_get_host_from_url (host, sizeof (host), url);
183    gtr_get_favicon (session, host, pixbuf_ready_func, pixbuf_ready_func_data);
184}
Note: See TracBrowser for help on using the repository browser.