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 *http = g_new0(GisHttp, 1);
28 http->prefix = g_strdup(prefix);
29 http->soup = soup_session_sync_new();
30 g_object_set(http->soup, "user-agent", PACKAGE_STRING, NULL);
34 /* For passing data to the chunck callback */
38 GisChunkCallback callback;
43 * Append data to the file and call the users callback if they supplied one.
45 static void _chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _info)
47 struct _cache_info *info = _info;
49 if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) {
50 g_warning("GisHttp: _chunk_cb - soup failed with %d",
51 message->status_code);
55 if (!fwrite(chunk->data, chunk->length, 1, info->fp))
56 g_error("GisHttp: _chunk_cb - Unable to write data");
59 goffset cur = ftell(info->fp);
60 goffset st=0, end=0, total=0;
61 soup_message_headers_get_content_range(message->response_headers,
63 info->callback(info->path, cur, total, info->user_data);
67 /* TODO: use .part extentions and continue even when using GIS_ONCE */
68 gchar *gis_http_fetch(GisHttp *self, const gchar *uri, const char *local,
69 GisCacheType mode, GisChunkCallback callback, gpointer user_data)
71 g_debug("GisHttp: fetch - %s >> %s mode=%d", uri, self->prefix, mode);
73 gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE,
74 self->prefix, local, NULL);
76 /* Unlink the file if we're refreshing it */
77 if (mode == GIS_REFRESH)
80 /* Do the cache if necessasairy */
81 if (!(mode == GIS_ONCE && g_file_test(path, G_FILE_TEST_EXISTS)) &&
83 g_debug("GisHttp: do_cache - Caching file %s", local);
85 /* Open the file for writting */
86 FILE *fp = fopen_p(path, "a");
89 struct _cache_info info = {
93 .user_data = user_data,
96 /* Download the file */
97 SoupMessage *message = soup_message_new("GET", uri);
99 g_error("message is null, cannot parse uri");
100 g_signal_connect(message, "got-chunk", G_CALLBACK(_chunk_cb), &info);
101 soup_message_headers_set_range(message->request_headers, ftell(fp), -1);
102 soup_session_send_message(self->soup, message);
105 if (message->status_code == 416) {
106 /* Range unsatisfiable, file already complete */
107 } else if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
108 g_warning("GisHttp: done_cb - error copying file, status=%d\n"
111 message->status_code, uri, path);
114 /* TODO: free everything.. */