]> Pileus Git - grits/blobdiff - src/data/gis-http.c
Win32 port
[grits] / src / data / gis-http.c
index fb742c7e0e8d1d8b5c0d3981226c7e45cc197902..b5259e47108e15a92f0f95b44c24d4b19828a873 100644 (file)
 
 #include "gis-http.h"
 
+gchar *_get_cache_path(GisHttp *http, const gchar *local)
+{
+       return g_build_filename(g_get_user_cache_dir(), PACKAGE,
+                       http->prefix, local, NULL);
+}
+
 /**
  * gis_http_new:
  * @prefix: The prefix in the cache to store the downloaded files.
@@ -117,11 +123,9 @@ static void _chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _info)
 gchar *gis_http_fetch(GisHttp *http, const gchar *uri, const char *local,
                GisCacheType mode, GisChunkCallback callback, gpointer user_data)
 {
-       g_debug("GisHttp: fetch - %.20s... >> %s/%s  mode=%d",
+       g_debug("GisHttp: fetch - %s... >> %s/%s  mode=%d",
                        uri, http->prefix, local, mode);
-
-       gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE,
-                       http->prefix, local, NULL);
+       gchar *path = _get_cache_path(http, local);
 
        /* Unlink the file if we're refreshing it */
        if (mode == GIS_REFRESH)
@@ -130,10 +134,14 @@ gchar *gis_http_fetch(GisHttp *http, const gchar *uri, const char *local,
        /* Do the cache if necessasairy */
        if (!(mode == GIS_ONCE && g_file_test(path, G_FILE_TEST_EXISTS)) &&
                        mode != GIS_LOCAL) {
-               g_debug("GisHttp: do_cache - Caching file %s", local);
+               g_debug("GisHttp: fetch - Caching file %s", local);
 
                /* Open the file for writting */
-               FILE *fp = fopen_p(path, "a");
+               gchar *part = path;
+               if (!g_file_test(path, G_FILE_TEST_EXISTS))
+                       part = g_strdup_printf("%s.part", path);
+               FILE *fp = fopen_p(part, "ab");
+               fseek(fp, 0, SEEK_END); // "a" is broken on Windows, twice
 
                /* Make temp data */
                struct _CacheInfo info = {
@@ -151,16 +159,95 @@ gchar *gis_http_fetch(GisHttp *http, const gchar *uri, const char *local,
                soup_message_headers_set_range(message->request_headers, ftell(fp), -1);
                soup_session_send_message(http->soup, message);
 
+               /* Close file */
+               fclose(fp);
+               if (path != part && SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) {
+                       g_rename(part, path);
+                       g_free(part);
+               }
+
                /* Finished */
                if (message->status_code == 416) {
                        /* Range unsatisfiable, file already complete */
-               } else if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
+               } else if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) {
                        g_warning("GisHttp: done_cb - error copying file, status=%d\n"
                                        "\tsrc=%s\n"
                                        "\tdst=%s",
                                        message->status_code, uri, path);
+                       return NULL;
+               }
        }
 
+
        /* TODO: free everything.. */
        return path;
 }
+
+/**
+ * gis_http_available:
+ * @http:    the #GisHttp connection to use
+ * @filter:  filter used to extract files from the index, or NULL
+ *           For example: "href=\"([^"]*)\""
+ * @cache:   path to the local cache, or NULL to not search the cache
+ * @extract: regex used to extract filenames from the page, should match the
+ *           filename as $1, or NULL to use /http="([^"])"/
+ * @index:   path to the index page, or NULL to not search online
+ *
+ * Look through the cache and an HTTP index page for a list of available files.
+ * The name of each file that matches the filter is added to the returned list.
+ *
+ * The list as well as the strings contained in it should be freed afterwards.
+ *
+ * Returns the list of matching filenames
+ */
+GList *gis_http_available(GisHttp *http,
+               gchar *filter, gchar *cache,
+               gchar *extract, gchar *index)
+{
+       g_debug("GisHttp: available - %s~=%s %s~=%s",
+                       filter, cache, extract, index);
+       GRegex *filter_re = g_regex_new(filter, 0, 0, NULL);
+       GList  *files = NULL;
+
+       /* Add cached files */
+       if (cache) {
+               const gchar *file;
+               gchar *path = _get_cache_path(http, cache);
+               GDir  *dir  = g_dir_open(path, 0, NULL);
+               while ((file = g_dir_read_name(dir)))
+                       if (g_regex_match(filter_re, file, 0, NULL))
+                               files = g_list_prepend(files, g_strdup(file));
+               g_free(path);
+       }
+
+       /* Add online files if online */
+       if (index) {
+               gchar tmp[16];
+               g_snprintf(tmp, sizeof(tmp), ".index.%x", g_random_int());
+               gchar *path = gis_http_fetch(http, index, tmp,
+                               GIS_REFRESH, NULL, NULL);
+               gchar *html;
+               g_file_get_contents(path, &html, NULL, NULL);
+
+               /* Match hrefs by default, this regex is not very accurate */
+               GRegex *extract_re = g_regex_new(
+                               extract ?: "href=\"([^\"]*)\"", 0, 0, NULL);
+               GMatchInfo *info;
+               g_regex_match(extract_re, html, 0, &info);
+               while (g_match_info_matches(info)) {
+                       gchar *file = g_match_info_fetch(info, 1);
+                       if (g_regex_match(filter_re, file, 0, NULL))
+                               files = g_list_prepend(files, file);
+                       else
+                               g_free(file);
+                       g_match_info_next(info, NULL);
+               }
+
+               g_match_info_free(info);
+               g_unlink(path);
+               g_free(path);
+               g_free(html);
+       }
+
+       return files;
+}