diff options
Diffstat (limited to 'riscos/download.c')
-rw-r--r-- | riscos/download.c | 319 |
1 files changed, 177 insertions, 142 deletions
diff --git a/riscos/download.c b/riscos/download.c index ebd981dca..a03ff474b 100644 --- a/riscos/download.c +++ b/riscos/download.c @@ -33,6 +33,8 @@ #include <sys/time.h> #include <time.h> #include <curl/curl.h> +#include <libwapcaplet/libwapcaplet.h> + #include "oslib/mimemap.h" #include "oslib/osargs.h" #include "oslib/osfile.h" @@ -41,21 +43,27 @@ #include "oslib/osgbpb.h" #include "oslib/wimp.h" #include "oslib/wimpspriteop.h" + #include "desktop/gui.h" #include "desktop/netsurf.h" -#include "riscos/dialog.h" +#include "desktop/download.h" #include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/nsurl.h" +#include "utils/utf8.h" +#include "utils/utils.h" +#include "utils/corestrings.h" + +#include "riscos/gui.h" +#include "riscos/dialog.h" #include "riscos/mouse.h" #include "riscos/save.h" #include "riscos/query.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" -#include "utils/log.h" -#include "utils/messages.h" -#include "utils/schedule.h" -#include "utils/url.h" -#include "utils/utf8.h" -#include "utils/utils.h" +#include "riscos/ucstables.h" +#include "riscos/filetype.h" #define ICON_DOWNLOAD_ICON 0 #define ICON_DOWNLOAD_URL 1 @@ -206,6 +214,60 @@ const char *ro_gui_download_temp_name(struct gui_download_window *dw) return temp_name; } +/** + * Try and find the correct RISC OS filetype from a download context. + */ +static nserror download_ro_filetype(download_context *ctx, bits *ftype_out) +{ + nsurl *url = download_context_get_url(ctx); + bits ftype = 0; + lwc_string *scheme; + + /* If the file is local try and read its filetype */ + scheme = nsurl_get_component(url, NSURL_SCHEME); + if (scheme != NULL) { + bool filescheme; + if (lwc_string_isequal(scheme, + corestring_lwc_file, + &filescheme) != lwc_error_ok) { + filescheme = false; + } + + if (filescheme) { + lwc_string *path = nsurl_get_component(url, NSURL_PATH); + if (path != NULL && lwc_string_length(path) != 0) { + char *raw_path; + raw_path = curl_unescape(lwc_string_data(path), + lwc_string_length(path)); + if (raw_path != NULL) { + ftype = ro_filetype_from_unix_path(raw_path); + curl_free(raw_path); + } + } + } + } + + /* If we still don't have a filetype (i.e. failed reading local + * one or fetching a remote object), then use the MIME type. + */ + if (ftype == 0) { + /* convert MIME type to RISC OS file type */ + os_error *error; + const char *mime_type; + + mime_type = download_context_get_mime_type(ctx); + error = xmimemaptranslate_mime_type_to_filetype(mime_type, &ftype); + if (error) { + LOG(("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); + ftype = 0xffd; + } + } + + *ftype_out = ftype; + return NSERROR_OK; +} /** * Create and open a download progress window. @@ -215,20 +277,17 @@ const char *ro_gui_download_temp_name(struct gui_download_window *dw) * reported */ -struct gui_download_window *gui_download_window_create(download_context *ctx, - struct gui_window *gui) +static struct gui_download_window * +gui_download_window_create(download_context *ctx, struct gui_window *gui) { - const char *url = download_context_get_url(ctx); - const char *mime_type = download_context_get_mime_type(ctx); + nsurl *url = download_context_get_url(ctx); const char *temp_name; - char *scheme = NULL; char *filename = NULL; struct gui_download_window *dw; bool space_warning = false; os_error *error; - url_func_result res; char *local_path; - utf8_convert_ret err; + nserror err; size_t i, last_dot; dw = malloc(sizeof *dw); @@ -244,8 +303,13 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, dw->query = QUERY_INVALID; dw->received = 0; dw->total_size = download_context_get_total_length(ctx); - strncpy(dw->url, url, sizeof dw->url); + + /** @todo change this to take a reference to the nsurl and use + * that value directly rather than using a fixed buffer. + */ + strncpy(dw->url, nsurl_access(url), sizeof dw->url); dw->url[sizeof dw->url - 1] = 0; + dw->status[0] = 0; gettimeofday(&dw->start_time, 0); dw->last_time = dw->start_time; @@ -254,55 +318,12 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, dw->average_rate = 0; dw->average_points = 0; - /* Get scheme from URL */ - res = url_scheme(url, &scheme); - if (res == URL_FUNC_NOMEM) { - warn_user("NoMemory", 0); + /* get filetype */ + err = download_ro_filetype(ctx, &dw->file_type); + if (err != NSERROR_OK) { + warn_user(messages_get_errorcode(err), 0); free(dw); return 0; - } else if (res == URL_FUNC_OK) { - /* If we have a scheme and it's "file", then - * attempt to use the local filetype directly */ - if (strcasecmp(scheme, "file") == 0) { - char *path = NULL; - res = url_path(url, &path); - if (res == URL_FUNC_NOMEM) { - warn_user("NoMemory", 0); - free(scheme); - free(dw); - return 0; - } else if (res == URL_FUNC_OK) { - char *raw_path = curl_unescape(path, - strlen(path)); - if (raw_path == NULL) { - warn_user("NoMemory", 0); - free(path); - free(scheme); - free(dw); - return 0; - } - dw->file_type = - ro_filetype_from_unix_path(raw_path); - curl_free(raw_path); - free(path); - } - } - - free(scheme); - } - - /* If we still don't have a filetype (i.e. failed reading local - * one or fetching a remote object), then use the MIME type */ - if (dw->file_type == 0) { - /* convert MIME type to RISC OS file type */ - error = xmimemaptranslate_mime_type_to_filetype(mime_type, - &(dw->file_type)); - if (error) { - LOG(("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - dw->file_type = 0xffd; - } } /* open temporary output file */ @@ -375,10 +396,12 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s", filename); + free(filename); + err = utf8_to_local_encoding(dw->path, 0, &local_path); - if (err != UTF8_CONVERT_OK) { + if (err != NSERROR_OK) { /* badenc should never happen */ - assert(err != UTF8_CONVERT_BADENC); + assert(err !=NSERROR_BAD_ENCODING); LOG(("utf8_to_local_encoding failed")); warn_user("NoMemory", 0); free(dw); @@ -435,6 +458,57 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, return dw; } +/** + * Handle failed downloads. + * + * \param dw download window + * \param error_msg error message + */ + +static void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) +{ + os_error *error; + + if (dw->ctx != NULL) + download_context_destroy(dw->ctx); + dw->ctx = NULL; + dw->error = true; + + riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw); + + /* place error message in status icon in red */ + strncpy(dw->status, error_msg, sizeof dw->status); + error = xwimp_set_icon_state(dw->window, + ICON_DOWNLOAD_STATUS, + wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT, + wimp_ICON_FG_COLOUR); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + /* grey out pathname icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH, + wimp_ICON_SHADED, 0); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + /* grey out file icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON, + wimp_ICON_SHADED, wimp_ICON_SHADED); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + ro_gui_download_window_hide_caret(dw); +} /** * Handle received download data. @@ -445,7 +519,7 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, * \return NSERROR_OK on success, appropriate error otherwise */ -nserror gui_download_window_data(struct gui_download_window *dw, +static nserror gui_download_window_data(struct gui_download_window *dw, const char *data, unsigned int size) { while (true) { @@ -526,7 +600,6 @@ nserror gui_download_window_data(struct gui_download_window *dw, void ro_gui_download_update_status(struct gui_download_window *dw) { - char *received; char *total_size; char *speed; char time[20] = "?"; @@ -537,7 +610,7 @@ void ro_gui_download_update_status(struct gui_download_window *dw) os_error *error; int width; char *local_status; - utf8_convert_ret err; + nserror err; gettimeofday(&t, 0); dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->last_time.tv_sec + @@ -548,6 +621,7 @@ void ro_gui_download_update_status(struct gui_download_window *dw) total_size = human_friendly_bytesize(max(dw->received, dw->total_size)); if (dw->ctx) { + char *received; rate = (dw->received - dw->last_received) / dt; received = human_friendly_bytesize(dw->received); /* A simple 'modified moving average' download rate calculation @@ -571,9 +645,9 @@ void ro_gui_download_update_status(struct gui_download_window *dw) /* convert to local encoding */ err = utf8_to_local_encoding( messages_get("Download"), 0, &local_status); - if (err != UTF8_CONVERT_OK) { + if (err != NSERROR_OK) { /* badenc should never happen */ - assert(err != UTF8_CONVERT_BADENC); + assert(err != NSERROR_BAD_ENCODING); /* hide nomem error */ snprintf(dw->status, sizeof dw->status, messages_get("Download"), @@ -594,9 +668,9 @@ void ro_gui_download_update_status(struct gui_download_window *dw) err = utf8_to_local_encoding( messages_get("DownloadU"), 0, &local_status); - if (err != UTF8_CONVERT_OK) { + if (err != NSERROR_OK) { /* badenc should never happen */ - assert(err != UTF8_CONVERT_BADENC); + assert(err != NSERROR_BAD_ENCODING); /* hide nomem error */ snprintf(dw->status, sizeof dw->status, messages_get("DownloadU"), @@ -622,9 +696,9 @@ void ro_gui_download_update_status(struct gui_download_window *dw) err = utf8_to_local_encoding(messages_get("Downloaded"), 0, &local_status); - if (err != UTF8_CONVERT_OK) { + if (err != NSERROR_OK) { /* badenc should never happen */ - assert(err != UTF8_CONVERT_BADENC); + assert(err != NSERROR_BAD_ENCODING); /* hide nomem error */ snprintf(dw->status, sizeof dw->status, messages_get("Downloaded"), @@ -661,15 +735,16 @@ void ro_gui_download_update_status(struct gui_download_window *dw) warn_user("WimpError", error->errmess); } - if (dw->ctx) - schedule(100, ro_gui_download_update_status_wrapper, dw); - else - schedule_remove(ro_gui_download_update_status_wrapper, dw); + if (dw->ctx) { + riscos_schedule(1000, ro_gui_download_update_status_wrapper, dw); + } else { + riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw); + } } /** - * Wrapper for ro_gui_download_update_status(), suitable for schedule(). + * Wrapper for ro_gui_download_update_status(), suitable for riscos_schedule(). */ void ro_gui_download_update_status_wrapper(void *p) @@ -707,57 +782,6 @@ void ro_gui_download_window_hide_caret(struct gui_download_window *dw) } -/** - * Handle failed downloads. - * - * \param dw download window - * \param error_msg error message - */ - -void gui_download_window_error(struct gui_download_window *dw, - const char *error_msg) -{ - os_error *error; - - if (dw->ctx != NULL) - download_context_destroy(dw->ctx); - dw->ctx = NULL; - dw->error = true; - - schedule_remove(ro_gui_download_update_status_wrapper, dw); - - /* place error message in status icon in red */ - strncpy(dw->status, error_msg, sizeof dw->status); - error = xwimp_set_icon_state(dw->window, - ICON_DOWNLOAD_STATUS, - wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT, - wimp_ICON_FG_COLOUR); - if (error) { - LOG(("xwimp_set_icon_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - - /* grey out pathname icon */ - error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH, - wimp_ICON_SHADED, 0); - if (error) { - LOG(("xwimp_set_icon_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - - /* grey out file icon */ - error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON, - wimp_ICON_SHADED, wimp_ICON_SHADED); - if (error) { - LOG(("xwimp_set_icon_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - - ro_gui_download_window_hide_caret(dw); -} /** @@ -766,7 +790,7 @@ void gui_download_window_error(struct gui_download_window *dw, * \param dw download window */ -void gui_download_window_done(struct gui_download_window *dw) +static void gui_download_window_done(struct gui_download_window *dw) { os_error *error; @@ -792,10 +816,11 @@ void gui_download_window_done(struct gui_download_window *dw) warn_user("SaveError", error->errmess); } - if (dw->send_dataload) + if (dw->send_dataload) { ro_gui_download_send_dataload(dw); + } - schedule(200, ro_gui_download_window_destroy_wrapper, dw); + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); } } @@ -810,9 +835,6 @@ void gui_download_window_done(struct gui_download_window *dw) bool ro_gui_download_click(wimp_pointer *pointer) { struct gui_download_window *dw; - char command[256] = "Filer_OpenDir "; - char *dot; - os_error *error; dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(pointer->w); if ((pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) && @@ -836,10 +858,14 @@ bool ro_gui_download_click(wimp_pointer *pointer) ro_gui_drag_icon(x, y, sprite); } else if (pointer->i == ICON_DOWNLOAD_DESTINATION) { + char command[256] = "Filer_OpenDir "; + char *dot; + strncpy(command + 14, dw->path, 242); command[255] = 0; dot = strrchr(command, '.'); if (dot) { + os_error *error; *dot = 0; error = xos_cli(command); if (error) { @@ -886,7 +912,7 @@ bool ro_gui_download_keypress(wimp_key *key) !nsoption_bool(confirm_overwrite)) && !dw->ctx) { /* finished already */ - schedule(200, ro_gui_download_window_destroy_wrapper, dw); + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); } return true; } @@ -982,7 +1008,7 @@ void ro_gui_download_datasave_ack(wimp_message *message) ro_gui_download_send_dataload(dw); - schedule(200, ro_gui_download_window_destroy_wrapper, dw); + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); } } @@ -1414,7 +1440,7 @@ void ro_gui_download_send_dataload(struct gui_download_window *dw) warn_user("WimpError", error->errmess); } - schedule(200, ro_gui_download_window_destroy_wrapper, dw); + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); } @@ -1477,8 +1503,8 @@ bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit) return false; } - schedule_remove(ro_gui_download_update_status_wrapper, dw); - schedule_remove(ro_gui_download_window_destroy_wrapper, dw); + riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw); + riscos_schedule(-1, ro_gui_download_window_destroy_wrapper, dw); /* remove from list */ if (dw->prev) @@ -1531,7 +1557,7 @@ bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit) /** - * Wrapper for ro_gui_download_window_destroy(), suitable for schedule(). + * Wrapper for ro_gui_download_window_destroy(), suitable for riscos_schedule(). */ void ro_gui_download_window_destroy_wrapper(void *p) @@ -1610,7 +1636,7 @@ void ro_gui_download_overwrite_confirmed(query_id id, enum query_response res, v ro_gui_download_send_dataload(dw); - schedule(200, ro_gui_download_window_destroy_wrapper, dw); + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); } } @@ -1631,3 +1657,12 @@ bool ro_gui_download_prequit(void) } return true; } + +static struct gui_download_table download_table = { + .create = gui_download_window_create, + .data = gui_download_window_data, + .error = gui_download_window_error, + .done = gui_download_window_done, +}; + +struct gui_download_table *riscos_download_table = &download_table; |