summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2011-02-23 00:54:29 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2011-02-23 00:54:29 +0000
commit6878eba2953bc2374425d5931b4c87d27aea213b (patch)
treeff171cc870b8db8c63da1ce3aad3e108c5ddc106 /desktop
parente8ce7bd953095f0120b6a04db424c51989e97572 (diff)
downloadnetsurf-6878eba2953bc2374425d5931b4c87d27aea213b.tar.gz
netsurf-6878eba2953bc2374425d5931b4c87d27aea213b.tar.bz2
Consider filename in Content-Disposition header when downloading, or generate reasonably sane default if there isn't one.
svn path=/trunk/netsurf/; revision=11767
Diffstat (limited to 'desktop')
-rw-r--r--desktop/download.c81
-rw-r--r--desktop/download.h8
2 files changed, 89 insertions, 0 deletions
diff --git a/desktop/download.c b/desktop/download.c
index 211bc3b37..28493ad3b 100644
--- a/desktop/download.c
+++ b/desktop/download.c
@@ -27,6 +27,7 @@
#include "desktop/download.h"
#include "desktop/gui.h"
#include "utils/http.h"
+#include "utils/url.h"
/**
* A context for a download
@@ -37,11 +38,46 @@ struct download_context {
char *mime_type; /**< MIME type of download */
unsigned long total_length; /**< Length of data, in bytes */
+ char *filename; /**< Suggested filename */
struct gui_download_window *window; /**< GUI download window */
};
/**
+ * Parse a filename parameter value
+ *
+ * \param filename Value to parse
+ * \return Sanitised filename, or NULL on memory exhaustion
+ */
+static char *download_parse_filename(const char *filename)
+{
+ const char *slash = strrchr(filename, '/');
+
+ if (slash != NULL)
+ slash++;
+ else
+ slash = filename;
+
+ return strdup(slash);
+}
+
+/**
+ * Compute a default filename for a download
+ *
+ * \param url URL of item being fetched
+ * \return Default filename, or NULL on memory exhaustion
+ */
+static char *download_default_filename(const char *url)
+{
+ char *nice;
+
+ if (url_nice(url, &nice, false) == URL_FUNC_OK)
+ return nice;
+
+ return NULL;
+}
+
+/**
* Process fetch headers for a download context.
* Extracts MIME type, total length, and creates gui_download_window
*
@@ -75,12 +111,48 @@ static nserror download_context_process_headers(download_context *ctx)
else
length = strtoul(http_header, NULL, 10);
+ /* Retrieve and parse Content-Disposition */
+ http_header = llcache_handle_get_header(ctx->llcache,
+ "Content-Disposition");
+ if (http_header != NULL) {
+ const char *filename;
+ char *disposition;
+
+ error = http_parse_content_disposition(http_header,
+ &disposition, &params);
+ if (error != NSERROR_OK) {
+ free(mime_type);
+ return error;
+ }
+
+ free(disposition);
+
+ error = http_parameter_list_find_item(params,
+ "filename", &filename);
+ if (error == NSERROR_OK)
+ ctx->filename = download_parse_filename(filename);
+
+ http_parameter_list_destroy(params);
+ }
+
ctx->mime_type = mime_type;
ctx->total_length = length;
+ if (ctx->filename == NULL) {
+ ctx->filename = download_default_filename(
+ llcache_handle_get_url(ctx->llcache));
+ }
+
+ if (ctx->filename == NULL) {
+ free(ctx->mime_type);
+ ctx->mime_type = NULL;
+ return NSERROR_NOMEM;
+ }
/* Create the frontend window */
ctx->window = gui_download_window_create(ctx, ctx->parent);
if (ctx->window == NULL) {
+ free(ctx->filename);
+ ctx->filename = NULL;
free(ctx->mime_type);
ctx->mime_type = NULL;
return NSERROR_NOMEM;
@@ -174,6 +246,7 @@ nserror download_context_create(llcache_handle *llcache,
ctx->parent = parent;
ctx->mime_type = NULL;
ctx->total_length = 0;
+ ctx->filename = NULL;
ctx->window = NULL;
llcache_handle_change_callback(llcache, download_callback, ctx);
@@ -188,6 +261,8 @@ void download_context_destroy(download_context *ctx)
free(ctx->mime_type);
+ free(ctx->filename);
+
/* Window is not owned by us, so don't attempt to destroy it */
free(ctx);
@@ -217,3 +292,9 @@ unsigned long download_context_get_total_length(const download_context *ctx)
return ctx->total_length;
}
+/* See download.h for documentation */
+const char *download_context_get_filename(const download_context *ctx)
+{
+ return ctx->filename;
+}
+
diff --git a/desktop/download.h b/desktop/download.h
index 206253602..cbdf96718 100644
--- a/desktop/download.h
+++ b/desktop/download.h
@@ -87,4 +87,12 @@ const char *download_context_get_mime_type(const download_context *ctx);
*/
unsigned long download_context_get_total_length(const download_context *ctx);
+/**
+ * Retrieve the filename for a download
+ *
+ * \param ctx Context to retrieve filename from
+ * \return Filename string
+ */
+const char *download_context_get_filename(const download_context *ctx);
+
#endif