4 * Created on: 2009-12-18
8 #include "http_utils.h"
10 #define HTTP_CACHE_PATH "/tmp/jamendo-cache"
11 #define MAX_CACHE_DAYS 2
13 static GInputStream* http_cache_get(const gchar* uri);
15 xmlDocPtr http_get_xml(const gchar* uri) {
16 GInputStream* stream = NULL;
20 xmlParserCtxtPtr ctxt = NULL;
23 g_debug("http_get_xml: uri=%s", uri);
26 * I found out that, this line will also do parsing xml from HTTP, instead of this complicated function
28 xmlDocPtr doc = xmlReadFile(uri,NULL,0);
31 stream = http_cache_get(uri);
34 g_warning("http_get_xml: ERROR");
39 ncount = g_input_stream_read(G_INPUT_STREAM(stream), buf, G_N_ELEMENTS(buf), NULL, &error);
41 g_error("http_get_xml: %s", error->message);
47 ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, ncount, uri);
49 xmlParseChunk(ctxt, buf, ncount, 0);
52 } while (ncount != 0);
55 xmlParseChunk(ctxt, buf, 0, 1);
57 if (!ctxt->wellFormed) {
58 g_warning("http_get_xml: wellFormed=%d", ctxt->wellFormed);
60 xmlFreeParserCtxt(ctxt);
63 g_input_stream_close(stream, NULL, NULL);
68 GdkPixbuf* http_get_image(const gchar* uri, gint width, gint height) {
70 GdkPixbuf* image = NULL;
72 GInputStream* stream = http_cache_get(uri);
74 image = gdk_pixbuf_new_from_stream_at_scale(stream, width, height, TRUE, NULL, &error);
75 g_input_stream_close(stream, NULL, NULL);
81 //TODO: add parameter to support cache expiration
82 static GInputStream* http_cache_get(const gchar* uri) {
88 GInputStream* input_stream;
89 GOutputStream* output_stream;
91 cache_file = g_file_new_for_path(HTTP_CACHE_PATH);
92 if (!g_file_query_exists(cache_file, NULL)) {
93 g_file_make_directory_with_parents(cache_file, NULL, NULL);
95 g_object_unref(cache_file);
97 /** check if uri is in our cache **/
98 tmp = g_uri_escape_string(uri, NULL, FALSE);
99 cache_path = g_strdup_printf("%s/%s", HTTP_CACHE_PATH, tmp);
102 cache_file = g_file_new_for_path(cache_path);
105 if (g_file_query_exists(cache_file, NULL)) {
108 GDate *modDate = g_date_new(), *curDate = g_date_new();
110 info = g_file_query_info(cache_file, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, NULL, NULL);
111 mod.tv_sec = g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
112 g_object_unref(info);
113 g_date_set_time_val(modDate, &mod);
115 g_get_current_time(&cur);
116 g_date_set_time_val(curDate, &cur);
118 gint days = g_date_days_between(modDate, curDate);
120 if (days <= MAX_CACHE_DAYS) {
121 g_debug("http_cache_get: cache age %d days - ok", days);
122 input_stream = G_INPUT_STREAM(g_file_read(cache_file, NULL, &error));
125 g_object_unref(cache_file);
129 g_warning("http_cache_get: cannot read cache file: %s", error->message);
134 g_debug("http_cache_get: cache age %d days - to old", days);
138 /** not in cache, get it from http */
139 http_file = g_file_new_for_uri(uri);
140 input_stream = G_INPUT_STREAM(g_file_read(http_file, NULL, &error));
141 g_object_unref(http_file);
143 g_warning("http_cache_get: cannot read from HTTP: %s", error->message);
145 g_object_unref(cache_file);
149 output_stream = G_OUTPUT_STREAM(g_file_replace(cache_file,NULL,0,G_FILE_CREATE_REPLACE_DESTINATION,NULL,&error));
151 g_warning("http_cache_get: cannot create cache file: %s", error->message);
153 g_object_unref(cache_file);
157 g_output_stream_splice(output_stream, input_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE
158 | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
160 g_warning("http_cache_get: cannot write HTTP file to cache: %s", error->message);
162 g_object_unref(cache_file);
166 /** input and output streams are closed by g_output_stream_splice **/
167 input_stream = G_INPUT_STREAM(g_file_read(cache_file, NULL, &error));
168 g_object_unref(cache_file);
170 g_warning("http_cache_get: cannot reopen cache file %s", error->message);