NetSurf
download.c
Go to the documentation of this file.
1/*
2 * Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file desktop/download.c
21 * \brief Core download context implementation
22 */
23
24#include <assert.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "content/llcache.h"
29#include "utils/corestrings.h"
30#include "utils/http.h"
31#include "utils/utils.h"
32#include "utils/log.h"
33#include "desktop/download.h"
34#include "netsurf/download.h"
36
37/**
38 * A context for a download
39 */
41 llcache_handle *llcache; /**< Low-level cache handle */
42 struct gui_window *parent; /**< Parent window */
43
44 lwc_string *mime_type; /**< MIME type of download */
45 unsigned long long int total_length; /**< Length of data, in bytes */
46 char *filename; /**< Suggested filename */
47
48 struct gui_download_window *window; /**< GUI download window */
49};
50
51/**
52 * Parse a filename parameter value
53 *
54 * \param filename Value to parse
55 * \return Sanitised filename, or NULL on memory exhaustion
56 */
57static char *download_parse_filename(const char *filename)
58{
59 const char *slash = strrchr(filename, '/');
60
61 if (slash != NULL)
62 slash++;
63 else
64 slash = filename;
65
66 return strdup(slash);
67}
68
69/**
70 * Compute a default filename for a download
71 *
72 * \param url URL of item being fetched
73 * \return Default filename, or NULL on memory exhaustion
74 */
76{
77 char *nice;
78
79 if (nsurl_nice(url, &nice, false) == NSERROR_OK) {
80 return nice;
81 }
82
83 return NULL;
84}
85
86/**
87 * Process fetch headers for a download context.
88 * Extracts MIME type, total length, and creates gui_download_window
89 *
90 * \param ctx Context to process
91 * \return NSERROR_OK on success, appropriate error otherwise
92 */
94{
95 const char *http_header;
97 unsigned long long int length;
99
100 /* Retrieve and parse Content-Type */
101 http_header = llcache_handle_get_header(ctx->llcache, "Content-Type");
102 if (http_header == NULL)
103 http_header = "text/plain";
104
106 if (error != NSERROR_OK)
107 return error;
108
109 /* Retrieve and parse Content-Length */
110 http_header = llcache_handle_get_header(ctx->llcache, "Content-Length");
111 if (http_header == NULL) {
112 length = 0;
113 } else {
114 length = strtoull(http_header, NULL, 10);
115 }
116
117 /* Retrieve and parse Content-Disposition */
118 http_header = llcache_handle_get_header(ctx->llcache,
119 "Content-Disposition");
120 if (http_header != NULL) {
121 lwc_string *filename_value;
122 http_content_disposition *disposition;
123
125 &disposition);
126 if (error != NSERROR_OK) {
128 return error;
129 }
130
132 corestring_lwc_filename, &filename_value);
133 if (error == NSERROR_OK) {
135 lwc_string_data(filename_value));
136 lwc_string_unref(filename_value);
137 }
138
140 }
141
142 ctx->mime_type = lwc_string_ref(content_type->media_type);
143 ctx->total_length = length;
144 if (ctx->filename == NULL) {
147 }
148
150
151 if (ctx->filename == NULL) {
152 lwc_string_unref(ctx->mime_type);
153 ctx->mime_type = NULL;
154 return NSERROR_NOMEM;
155 }
156
157 /* Create the frontend window */
159 if (ctx->window == NULL) {
160 free(ctx->filename);
161 ctx->filename = NULL;
162 lwc_string_unref(ctx->mime_type);
163 ctx->mime_type = NULL;
164 return NSERROR_NOMEM;
165 }
166
167 return NSERROR_OK;
168}
169
170/**
171 * Callback for low-level cache events
172 *
173 * \param handle Low-level cache handle
174 * \param event Event object
175 * \param pw Our context
176 * \return NSERROR_OK on success, appropriate error otherwise
177 */
179 const llcache_event *event, void *pw)
180{
181 download_context *ctx = pw;
183
184 switch (event->type) {
186 /* Nominally not interested in these */
187 break;
190 if (error != NSERROR_OK) {
191 llcache_handle_abort(handle);
193 }
194
195 break;
196
198 /* If we didn't know up-front that this fetch was for download,
199 * then we won't receive the HAD_HEADERS event. Catch up now.
200 */
201 if (ctx->window == NULL) {
203 if (error != NSERROR_OK) {
204 llcache_handle_abort(handle);
206 }
207 }
208
209 if (error == NSERROR_OK) {
210 /** \todo Lose ugly cast */
212 (char *) event->data.data.buf,
213 event->data.data.len);
214 if (error != NSERROR_OK)
215 llcache_handle_abort(handle);
216 }
217
218 break;
219
221 /* There may be no associated window if there was no data or headers */
222 if (ctx->window != NULL)
224 else
226
227 break;
228
230 if (ctx->window != NULL)
232 else
234
235 break;
236
238 break;
239
241 break;
242 }
243
244 return error;
245}
246
247/* See download.h for documentation */
249 struct gui_window *parent)
250{
252
253 ctx = malloc(sizeof(*ctx));
254 if (ctx == NULL)
255 return NSERROR_NOMEM;
256
258 ctx->parent = parent;
259 ctx->mime_type = NULL;
260 ctx->total_length = 0;
261 ctx->filename = NULL;
262 ctx->window = NULL;
263
265
266 return NSERROR_OK;
267}
268
269/* See download.h for documentation */
271{
273
274 if (ctx->mime_type != NULL)
275 lwc_string_unref(ctx->mime_type);
276
277 free(ctx->filename);
278
279 /* Window is not owned by us, so don't attempt to destroy it */
280
281 free(ctx);
282}
283
284/* See download.h for documentation */
286{
288}
289
290/* See download.h for documentation */
292{
294}
295
296/* See download.h for documentation */
298{
299 return lwc_string_data(ctx->mime_type);
300}
301
302/* See download.h for documentation */
303unsigned long long int
305{
306 return ctx->total_length;
307}
308
309/* See download.h for documentation */
311{
312 return ctx->filename;
313}
314
nserror http_parse_content_disposition(const char *header_value, http_content_disposition **result)
Parse an HTTP Content-Disposition header value.
void http_content_disposition_destroy(http_content_disposition *victim)
Destroy a content disposition object.
nserror http_parse_content_type(const char *header_value, http_content_type **result)
Parse an HTTP Content-Type header value.
Definition: content-type.c:30
void http_content_type_destroy(http_content_type *victim)
Destroy a content type object.
Definition: content-type.c:122
content_type
The type of a content.
Definition: content_type.h:53
Useful interned string pointers (interface).
static nserror download_callback(llcache_handle *handle, const llcache_event *event, void *pw)
Callback for low-level cache events.
Definition: download.c:178
void download_context_destroy(download_context *ctx)
Destroy a download context.
Definition: download.c:270
nsurl * download_context_get_url(const download_context *ctx)
Retrieve the URL for a download.
Definition: download.c:291
const char * download_context_get_filename(const download_context *ctx)
Retrieve the filename for a download.
Definition: download.c:310
void download_context_abort(download_context *ctx)
Abort a download fetch.
Definition: download.c:285
static char * download_parse_filename(const char *filename)
Parse a filename parameter value.
Definition: download.c:57
static char * download_default_filename(nsurl *url)
Compute a default filename for a download.
Definition: download.c:75
const char * download_context_get_mime_type(const download_context *ctx)
Retrieve the MIME type for a download.
Definition: download.c:297
static nserror download_context_process_headers(download_context *ctx)
Process fetch headers for a download context.
Definition: download.c:93
nserror download_context_create(llcache_handle *llcache, struct gui_window *parent)
Create a download context.
Definition: download.c:248
unsigned long long int download_context_get_total_length(const download_context *ctx)
Retrieve total byte length of download.
Definition: download.c:304
Core download context (interface)
wimp_w parent
Definition: dialog.c:88
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:50
Interface to core interface table.
HTTP header parsing functions.
Interface to platform-specific download operations.
static struct llcache_s * llcache
low level cache state
Definition: llcache.c:267
nserror llcache_handle_abort(llcache_handle *handle)
Abort a low-level fetch, informing all users of this action.
Definition: llcache.c:4098
nsurl * llcache_handle_get_url(const llcache_handle *handle)
Retrieve the post-redirect URL of a low-level cache object.
Definition: llcache.c:4195
const char * llcache_handle_get_header(const llcache_handle *handle, const char *key)
Retrieve a header value associated with a low-level cache object.
Definition: llcache.c:4210
nserror llcache_handle_change_callback(llcache_handle *handle, llcache_handle_callback cb, void *pw)
Change the callback associated with a low-level cache handle.
Definition: llcache.c:4047
nserror llcache_handle_release(llcache_handle *handle)
Release a low-level cache handle.
Definition: llcache.c:4058
Low-level resource cache (interface)
@ LLCACHE_EVENT_DONE
Finished fetching data.
Definition: llcache.h:71
@ LLCACHE_EVENT_ERROR
An error occurred during fetch.
Definition: llcache.h:73
@ LLCACHE_EVENT_GOT_CERTS
SSL certificates arrived.
Definition: llcache.h:68
@ LLCACHE_EVENT_REDIRECT
Fetch URL redirect occured.
Definition: llcache.h:76
@ LLCACHE_EVENT_PROGRESS
Fetch progress update.
Definition: llcache.h:74
@ LLCACHE_EVENT_HAD_HEADERS
Received all headers.
Definition: llcache.h:69
@ LLCACHE_EVENT_HAD_DATA
Received some data.
Definition: llcache.h:70
nserror nsurl_nice(const nsurl *url, char **result, bool remove_extensions)
Attempt to find a nice filename for a URL.
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
nserror http_parameter_list_find_item(const http_parameter *list, lwc_string *name, lwc_string **value)
Find a named item in an HTTP parameter list.
Definition: parameter.c:114
Interface to utility string handling.
A context for a download.
Definition: download.c:40
char * filename
Suggested filename.
Definition: download.c:46
llcache_handle * llcache
Low-level cache handle.
Definition: download.c:41
struct gui_download_window * window
GUI download window.
Definition: download.c:48
lwc_string * mime_type
MIME type of download.
Definition: download.c:44
unsigned long long int total_length
Length of data, in bytes.
Definition: download.c:45
struct gui_window * parent
Parent window.
Definition: download.c:42
nserror(* data)(struct gui_download_window *dw, const char *data, unsigned int size)
Definition: download.h:37
void(* done)(struct gui_download_window *dw)
Definition: download.h:41
void(* error)(struct gui_download_window *dw, const char *error_msg)
Definition: download.h:39
struct gui_download_window *(* create)(struct download_context *ctx, struct gui_window *parent)
Definition: download.h:35
context for each download.
Definition: download.c:91
const char * url
Definition: download.c:102
struct download_context * ctx
Associated context, or 0 if the fetch has completed or aborted.
Definition: download.c:101
first entry in window list
Definition: gui.c:298
Low-level cache events.
Definition: llcache.h:85
struct llcache_event::@124::@126 error
const char * msg
Error message.
Definition: llcache.h:94
struct llcache_event::@124::@125 data
Received data.
size_t len
Byte length of buffer.
Definition: llcache.h:90
llcache_event_type type
Type of event.
Definition: llcache.h:86
const uint8_t * buf
Buffer of data.
Definition: llcache.h:89
Handle to low-level cache object.
Definition: llcache.c:76
struct gui_download_table * download
Download table.
Definition: gui_table.h:82
Interface to a number of general purpose functionality.
unsigned long long int strtoull(const char *nptr, char **endptr, int base)
string to unsigned long long
Definition: utils.c:293