NetSurf
download.c
Go to the documentation of this file.
1/*
2 * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
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
21 * windows frontend download implementation
22 *
23 * \todo The windows download functionality is very buggy this needs redoing
24 */
25
26#include <limits.h>
27#include "utils/inet.h" /* get correct winsock ordering */
28#include <shlobj.h>
29#include <windows.h>
30
31#include "utils/sys_time.h"
32#include "utils/log.h"
33#include "utils/messages.h"
34#include "utils/url.h"
35#include "utils/nsurl.h"
36#include "utils/utils.h"
37#include "utils/string.h"
38#include "content/fetch.h"
39#include "netsurf/download.h"
40#include "desktop/download.h"
41
42#include "windows/download.h"
43#include "windows/window.h"
44#include "windows/gui.h"
45#include "windows/resourceid.h"
46#include "windows/schedule.h"
47
49 HWND hwnd;
50 char *title;
51 char *filename;
52 char *domain;
53 char *time_left;
56 int size;
58 unsigned int progress;
60 struct timeval start_time;
61 int speed;
62 int error;
64 FILE *file;
66};
67
68static bool downloading = false;
70
71
72static void nsws_download_update_label(void *p)
73{
74 struct gui_download_window *w = p;
75 if (w->hwnd == NULL) {
77 return;
78 }
79 HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_LABEL);
80 char *size = human_friendly_bytesize(w->downloaded);
81 int i = 0, temp = w->time_remaining;
82 if (temp == -1) {
83 w->time_left = strdup(messages_get("UnknownSize"));
84 i = strlen(w->time_left);
85 } else {
86 do {
87 temp = temp / 10;
88 i++;
89 } while (temp > 2);
90 w->time_left = malloc(i + SLEN(" s") + 1);
91 if (w->time_left != NULL) {
92 if (w->time_remaining > 3600)
93 sprintf(w->time_left, "%d h",
94 w->time_remaining / 3600);
95 else if (w->time_remaining > 60)
96 sprintf(w->time_left, "%d m",
97 w->time_remaining / 60);
98 else
99 sprintf(w->time_left, "%d s",
100 w->time_remaining);
101 }
102 }
103 char label[strlen(w->title) + strlen(size) + strlen(w->total_size) +
104 + strlen(w->domain) + strlen(w->filename) +
105 SLEN("download from to \n[\t/\t]\n estimate of time"
106 " remaining ") + i + 1];
107 sprintf(label, "download %s from %s to %s\n[%s\t/\t%s] [%d%%]\n"
108 "estimate of time remaining %s", w->title, w->domain,
109 w->filename, size, w->total_size, w->progress / 100,
110 w->time_left);
111 if (w->time_left != NULL) {
112 free(w->time_left);
113 w->time_left = NULL;
114 }
115 SendMessage(sub, WM_SETTEXT, (WPARAM)0, (LPARAM)label);
116 if (w->progress < 10000) {
118 }
119}
120
121
123{
124 struct gui_download_window *w = p;
125 if (w->hwnd == NULL) {
127 return;
128 }
129 HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_PROGRESS);
130 SendMessage(sub, PBM_SETPOS, (WPARAM)(w->progress / 100), 0);
131 if (w->progress < 10000) {
133 }
134}
135
136
138{
139 if (w == NULL)
140 return;
141 if (w->title != NULL)
142 free(w->title);
143 if (w->filename != NULL)
144 free(w->filename);
145 if (w->domain != NULL)
146 free(w->domain);
147 if (w->time_left != NULL)
148 free(w->time_left);
149 if (w->total_size != NULL)
150 free(w->total_size);
151 if (w->file != NULL)
152 fclose(w->file);
155}
156
157
158static BOOL CALLBACK
159nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
160{
161 switch(msg) {
162 case WM_INITDIALOG:
165 return TRUE;
166
167 case WM_COMMAND:
168 switch(LOWORD(wparam)) {
169 case IDOK:
171 return TRUE;
173
174 case IDCANCEL:
176 download1 = NULL;
177 downloading = false;
178 EndDialog(hwnd, IDCANCEL);
179 return FALSE;
180 }
181 }
182 return FALSE;
183}
184
185
187{
188 w->hwnd = CreateDialog(hinst,
189 MAKEINTRESOURCE(IDD_DOWNLOAD),
190 gui_window_main_window(w->window),
192 if (w->hwnd == NULL) {
193 return false;
194 }
195 ShowWindow(w->hwnd, SW_SHOW);
196 return true;
197}
198
199
200static struct gui_download_window *
202{
203 if (downloading) {
204 /* initial implementation */
205 win32_warning("1 download at a time please", 0);
206 return NULL;
207 }
208 downloading = true;
209 struct gui_download_window *w =
210 malloc(sizeof(struct gui_download_window));
211 if (w == NULL) {
212 win32_warning(messages_get("NoMemory"), 0);
213 return NULL;
214 }
216 char *domain, *filename, *destination;
218 bool unknown_size = (total_size == 0);
219 const char *size = (unknown_size) ?
220 messages_get("UnknownSize") :
222
223 if (nsurl_nice(url, &filename, false) != NSERROR_OK) {
224 filename = strdup(messages_get("UnknownFile"));
225 }
226 if (filename == NULL) {
227 win32_warning(messages_get("NoMemory"), 0);
228 free(w);
229 return NULL;
230 }
231
233 domain = strdup(lwc_string_data(nsurl_get_component(url, NSURL_HOST)));
234 } else {
235 domain = strdup(messages_get("UnknownHost"));
236 }
237 if (domain == NULL) {
238 win32_warning(messages_get("NoMemory"), 0);
239 free(filename);
240 free(w);
241 return NULL;
242 }
243 destination = malloc(PATH_MAX);
244 if (destination == NULL) {
245 win32_warning(messages_get("NoMemory"), 0);
246 free(domain);
247 free(filename);
248 free(w);
249 return NULL;
250 }
251 SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT,
253 if (strlen(destination) < PATH_MAX - 2)
254 strcat(destination, "/");
255 if (strlen(destination) + strlen(filename) < PATH_MAX - 1)
256 strcat(destination, filename);
257 NSLOG(netsurf, INFO, "download %s [%s] from %s to %s", filename,
259 w->title = filename;
260 w->domain = domain;
261 w->size = total_size;
262 w->total_size = strdup(size);
263 if (w->total_size == NULL) {
264 win32_warning(messages_get("NoMemory"), 0);
265 free(destination);
266 free(domain);
267 free(filename);
268 free(w);
269 return NULL;
270 }
271 w->downloaded = 0;
272 w->speed = 0;
273 gettimeofday(&(w->start_time), NULL);
274 w->time_remaining = -1;
275 w->time_left = NULL;
276 w->status = DOWNLOAD_NONE;
277 w->filename = destination;
278 w->progress = 0;
279 w->error = 0;
280 w->window = gui;
281 w->file = fopen(destination, "wb");
282 if (w->file == NULL) {
283 win32_warning(messages_get("FileOpenWriteError"), destination);
284 free(destination);
285 free(domain);
286 free(filename);
287 free(w->total_size);
288 free(w->time_left);
289 free(w);
290 return NULL;
291 }
292 download1 = w;
293
294 if (nsws_download_window_up(w) == false) {
295 win32_warning(messages_get("NoMemory"), 0);
296 free(destination);
297 free(domain);
298 free(filename);
299 free(w->total_size);
300 free(w->time_left);
301 free(w);
302 return NULL;
303 }
304 return w;
305}
306
307
308static nserror
310 unsigned int size)
311{
312 if ((w == NULL) || (w->file == NULL))
313 return NSERROR_SAVE_FAILED;
314 size_t res;
315 struct timeval val;
316 res = fwrite((void *)data, 1, size, w->file);
317 if (res != size)
318 NSLOG(netsurf, INFO, "file write error %d of %d", size - res,
319 size);
320 w->downloaded += res;
321 w->progress = (unsigned int)(((long long)(w->downloaded) * 10000)
322 / w->size);
323 gettimeofday(&val, NULL);
324 w->time_remaining = (w->progress == 0) ? -1 :
325 (int)((val.tv_sec - w->start_time.tv_sec) *
326 (10000 - w->progress) / w->progress);
327 return NSERROR_OK;
328}
329
331 const char *error_msg)
332{
333 NSLOG(netsurf, INFO, "error %s", error_msg);
334}
335
337{
338 if (w == NULL)
339 return;
340 downloading = false;
341 if (w->hwnd != NULL)
342 EndDialog(w->hwnd, IDOK);
344}
345
351};
352
#define PATH_MAX
Definition: gui.h:31
Fetching of data from a URL (interface).
nsurl * download_context_get_url(const download_context *ctx)
Retrieve the URL for a download.
Definition: download.c:291
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)
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_SAVE_FAILED
Failed to save data.
Definition: errors.h:36
@ NSERROR_OK
No error.
Definition: errors.h:30
static BOOL CALLBACK nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: download.c:159
static struct gui_download_table download_table
Definition: download.c:346
static nserror gui_download_window_data(struct gui_download_window *w, const char *data, unsigned int size)
Definition: download.c:309
static bool downloading
Definition: download.c:68
struct gui_download_table * win32_download_table
Definition: download.c:353
static struct gui_download_window * gui_download_window_create(download_context *ctx, struct gui_window *gui)
Definition: download.c:201
static void nsws_download_update_progress(void *p)
Definition: download.c:122
static void gui_download_window_done(struct gui_download_window *w)
Definition: download.c:336
static void nsws_download_clear_data(struct gui_download_window *w)
Definition: download.c:137
static void gui_download_window_error(struct gui_download_window *w, const char *error_msg)
Definition: download.c:330
static void nsws_download_update_label(void *p)
Definition: download.c:72
static struct gui_download_window * download1
Definition: download.c:69
static bool nsws_download_window_up(struct gui_download_window *w)
Definition: download.c:186
download_status
Definition: download.h:24
@ DOWNLOAD_NONE
Definition: download.h:25
Interface to platform-specific download operations.
internet structures and defines
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
NetSurf URL handling (interface).
bool nsurl_has_component(const nsurl *url, nsurl_component part)
Enquire about the existence of componenets in a given URL.
nserror nsurl_nice(const nsurl *url, char **result, bool remove_extensions)
Attempt to find a nice filename for a URL.
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
@ NSURL_HOST
Definition: nsurl.h:49
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
#define ShowWindow(...)
Definition: os3support.h:172
#define IDC_DOWNLOAD_LABEL
Definition: resourceid.h:49
#define IDD_DOWNLOAD
Definition: resourceid.h:48
#define IDC_DOWNLOAD_PROGRESS
Definition: resourceid.h:50
Interface to utility string handling.
char * human_friendly_bytesize(unsigned long long int bytesize)
Create a human readable representation of a size in bytes.
Definition: utils.c:209
A context for a download.
Definition: download.c:40
function table for download windows.
Definition: download.h:34
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
char * original_total_size
Definition: download.c:55
struct ami_generic_window w
Definition: download.c:92
os_fw file
RISC OS file handle, of temporary file when !saved, and of destination when saved.
Definition: download.c:109
unsigned int progress
Definition: download.c:58
struct gui_window * window
Definition: download.c:63
unsigned int total_size
Size of resource, or 0 if unknown.
Definition: download.c:92
const char * url
Definition: download.c:102
char * destination
Definition: download.h:47
download_status status
Definition: download.c:65
struct download_context * ctx
Associated context, or 0 if the fetch has completed or aborted.
Definition: download.c:101
gfloat time_remaining
Definition: download.c:95
first entry in window list
Definition: gui.c:296
BSD style timeval macros.
Interface to URL parsing and joining operations.
Interface to a number of general purpose functionality.
#define fallthrough
switch fall through
Definition: utils.h:115
#define SLEN(x)
Calculate length of constant C string.
Definition: utils.h:84
nserror win32_warning(const char *warning, const char *detail)
Warn the user of an event.
Definition: gui.c:173
HINSTANCE hinst
win32 application instance handle.
Definition: gui.c:45
nserror win32_schedule(int ival, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: schedule.c:99
HWND gui_window_main_window(struct gui_window *w)
Get the main win32 window handle from a gui window.
Definition: window.c:2112