2 * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <glib/gstdio.h>
21 #include <libsoup/soup.h>
25 GisHttp *gis_http_new(const gchar *prefix)
27 GisHttp *self = g_new0(GisHttp, 1);
28 self->soup = soup_session_sync_new();
29 self->prefix = g_strdup(prefix);
30 g_object_set(self->soup, "user-agent", PACKAGE_STRING, NULL);
34 void gis_http_free(GisHttp *self)
36 g_object_unref(self->soup);
41 /* For passing data to the chunck callback */
45 GisChunkCallback callback;
50 * Append data to the file and call the users callback if they supplied one.
52 static void _chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _info)
54 struct _cache_info *info = _info;
56 if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) {
57 g_warning("GisHttp: _chunk_cb - soup failed with %d",
58 message->status_code);
62 if (!fwrite(chunk->data, chunk->length, 1, info->fp))
63 g_error("GisHttp: _chunk_cb - Unable to write data");
66 goffset cur = ftell(info->fp);
67 goffset st=0, end=0, total=0;
68 soup_message_headers_get_content_range(message->response_headers,
70 info->callback(info->path, cur, total, info->user_data);
74 /* TODO: use .part extentions and continue even when using GIS_ONCE */
75 gchar *gis_http_fetch(GisHttp *self, const gchar *uri, const char *local,
76 GisCacheType mode, GisChunkCallback callback, gpointer user_data)
78 g_debug("GisHttp: fetch - %s >> %s mode=%d", uri, self->prefix, mode);
80 gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE,
81 self->prefix, local, NULL);
83 /* Unlink the file if we're refreshing it */
84 if (mode == GIS_REFRESH)
87 /* Do the cache if necessasairy */
88 if (!(mode == GIS_ONCE && g_file_test(path, G_FILE_TEST_EXISTS)) &&
90 g_debug("GisHttp: do_cache - Caching file %s", local);
92 /* Open the file for writting */
93 FILE *fp = fopen_p(path, "a");
96 struct _cache_info info = {
100 .user_data = user_data,
103 /* Download the file */
104 SoupMessage *message = soup_message_new("GET", uri);
106 g_error("message is null, cannot parse uri");
107 g_signal_connect(message, "got-chunk", G_CALLBACK(_chunk_cb), &info);
108 soup_message_headers_set_range(message->request_headers, ftell(fp), -1);
109 soup_session_send_message(self->soup, message);
112 if (message->status_code == 416) {
113 /* Range unsatisfiable, file already complete */
114 } else if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
115 g_warning("GisHttp: done_cb - error copying file, status=%d\n"
118 message->status_code, uri, path);
121 /* TODO: free everything.. */