mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Disable resuming download of formatted document
If the user chose File -> Save formatted document and typed the name of an existing file, ELinks offered to resume downloading the file. There are a few problems with that: * save_formatted_finish does not actually support resuming. It would instead overwrite the beginning of the file and not truncate it. * When save_formatted calls create_download_file, cdf_hop->data ends up pointing to struct document. If the user then chooses to resume, lun_resume would read *(int *)cdf_hop->data, hoping to get cmdw_hop.magic or codw_hop.magic. struct document does not begin with any such magic value. * Because ELinks already has the formatted document in memory, resuming saves neither time nor I/O. So don't show the "Resume download of the original file" button in this situation.
This commit is contained in:
parent
6f9501346e
commit
6032bc730a
@ -446,13 +446,14 @@ download_data(struct download *download, struct file_download *file_download)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* XXX: We assume that resume is everytime zero in lun's callbacks. */
|
|
||||||
struct lun_hop {
|
struct lun_hop {
|
||||||
struct terminal *term;
|
struct terminal *term;
|
||||||
unsigned char *ofile, *file;
|
unsigned char *ofile, *file;
|
||||||
|
|
||||||
void (*callback)(struct terminal *, unsigned char *, void *, int);
|
void (*callback)(struct terminal *, unsigned char *, void *,
|
||||||
|
enum download_resume);
|
||||||
void *data;
|
void *data;
|
||||||
|
enum download_resume resume;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -477,7 +478,7 @@ struct cdf_hop {
|
|||||||
unsigned char **real_file;
|
unsigned char **real_file;
|
||||||
int safe;
|
int safe;
|
||||||
|
|
||||||
void (*callback)(struct terminal *, int, void *, int);
|
void (*callback)(struct terminal *, int, void *, enum download_resume);
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -486,7 +487,8 @@ lun_alternate(void *lun_hop_)
|
|||||||
{
|
{
|
||||||
struct lun_hop *lun_hop = lun_hop_;
|
struct lun_hop *lun_hop = lun_hop_;
|
||||||
|
|
||||||
lun_hop->callback(lun_hop->term, lun_hop->file, lun_hop->data, 0);
|
lun_hop->callback(lun_hop->term, lun_hop->file, lun_hop->data,
|
||||||
|
lun_hop->resume);
|
||||||
mem_free_if(lun_hop->ofile);
|
mem_free_if(lun_hop->ofile);
|
||||||
mem_free(lun_hop);
|
mem_free(lun_hop);
|
||||||
}
|
}
|
||||||
@ -496,7 +498,8 @@ lun_cancel(void *lun_hop_)
|
|||||||
{
|
{
|
||||||
struct lun_hop *lun_hop = lun_hop_;
|
struct lun_hop *lun_hop = lun_hop_;
|
||||||
|
|
||||||
lun_hop->callback(lun_hop->term, NULL, lun_hop->data, 0);
|
lun_hop->callback(lun_hop->term, NULL, lun_hop->data,
|
||||||
|
lun_hop->resume);
|
||||||
mem_free_if(lun_hop->ofile);
|
mem_free_if(lun_hop->ofile);
|
||||||
mem_free_if(lun_hop->file);
|
mem_free_if(lun_hop->file);
|
||||||
mem_free(lun_hop);
|
mem_free(lun_hop);
|
||||||
@ -507,12 +510,14 @@ lun_overwrite(void *lun_hop_)
|
|||||||
{
|
{
|
||||||
struct lun_hop *lun_hop = lun_hop_;
|
struct lun_hop *lun_hop = lun_hop_;
|
||||||
|
|
||||||
lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, 0);
|
lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data,
|
||||||
|
lun_hop->resume);
|
||||||
mem_free_if(lun_hop->file);
|
mem_free_if(lun_hop->file);
|
||||||
mem_free(lun_hop);
|
mem_free(lun_hop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void common_download_do(struct terminal *term, int fd, void *data, int resume);
|
static void common_download_do(struct terminal *term, int fd, void *data,
|
||||||
|
enum download_resume resume);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lun_resume(void *lun_hop_)
|
lun_resume(void *lun_hop_)
|
||||||
@ -546,15 +551,18 @@ lun_resume(void *lun_hop_)
|
|||||||
cdf_hop->callback = common_download_do;
|
cdf_hop->callback = common_download_do;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, 1);
|
lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data,
|
||||||
|
lun_hop->resume | DOWNLOAD_RESUME_SELECTED);
|
||||||
mem_free_if(lun_hop->file);
|
mem_free_if(lun_hop->file);
|
||||||
mem_free(lun_hop);
|
mem_free(lun_hop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
lookup_unique_name(struct terminal *term, unsigned char *ofile,
|
||||||
void (*callback)(struct terminal *, unsigned char *, void *, int),
|
enum download_resume resume,
|
||||||
|
void (*callback)(struct terminal *, unsigned char *,
|
||||||
|
void *, enum download_resume),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
/* [gettext_accelerator_context(.lookup_unique_name)] */
|
/* [gettext_accelerator_context(.lookup_unique_name)] */
|
||||||
@ -566,7 +574,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
|||||||
|
|
||||||
/* Minor code duplication to prevent useless call to get_opt_int()
|
/* Minor code duplication to prevent useless call to get_opt_int()
|
||||||
* if possible. --Zas */
|
* if possible. --Zas */
|
||||||
if (resume) {
|
if (resume & DOWNLOAD_RESUME_SELECTED) {
|
||||||
callback(term, ofile, data, resume);
|
callback(term, ofile, data, resume);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -588,7 +596,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
|||||||
msg_text(term, N_("'%s' is a directory."),
|
msg_text(term, N_("'%s' is a directory."),
|
||||||
ofile));
|
ofile));
|
||||||
mem_free(ofile);
|
mem_free(ofile);
|
||||||
callback(term, NULL, data, 0);
|
callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,7 +606,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
|||||||
if (!file || overwrite == 1 || file == ofile) {
|
if (!file || overwrite == 1 || file == ofile) {
|
||||||
/* Still nothing special to do... */
|
/* Still nothing special to do... */
|
||||||
if (file != ofile) mem_free(ofile);
|
if (file != ofile) mem_free(ofile);
|
||||||
callback(term, file, data, 0);
|
callback(term, file, data, resume & ~DOWNLOAD_RESUME_SELECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +617,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
|||||||
if (!lun_hop) {
|
if (!lun_hop) {
|
||||||
if (file != ofile) mem_free(file);
|
if (file != ofile) mem_free(file);
|
||||||
mem_free(ofile);
|
mem_free(ofile);
|
||||||
callback(term, NULL, data, 0);
|
callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lun_hop->term = term;
|
lun_hop->term = term;
|
||||||
@ -617,6 +625,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
|||||||
lun_hop->file = (file != ofile) ? file : stracpy(ofile);
|
lun_hop->file = (file != ofile) ? file : stracpy(ofile);
|
||||||
lun_hop->callback = callback;
|
lun_hop->callback = callback;
|
||||||
lun_hop->data = data;
|
lun_hop->data = data;
|
||||||
|
lun_hop->resume = resume;
|
||||||
|
|
||||||
msg_box(term, NULL, MSGBOX_FREE_TEXT,
|
msg_box(term, NULL, MSGBOX_FREE_TEXT,
|
||||||
N_("File exists"), ALIGN_CENTER,
|
N_("File exists"), ALIGN_CENTER,
|
||||||
@ -629,15 +638,18 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume,
|
|||||||
lun_hop, 4,
|
lun_hop, 4,
|
||||||
MSG_BOX_BUTTON(N_("Sa~ve under the alternative name"), lun_alternate, B_ENTER),
|
MSG_BOX_BUTTON(N_("Sa~ve under the alternative name"), lun_alternate, B_ENTER),
|
||||||
MSG_BOX_BUTTON(N_("~Overwrite the original file"), lun_overwrite, 0),
|
MSG_BOX_BUTTON(N_("~Overwrite the original file"), lun_overwrite, 0),
|
||||||
MSG_BOX_BUTTON(N_("~Resume download of the original file"), lun_resume, 0),
|
MSG_BOX_BUTTON((resume & DOWNLOAD_RESUME_ALLOWED
|
||||||
|
? N_("~Resume download of the original file")
|
||||||
|
: NULL),
|
||||||
|
lun_resume, 0),
|
||||||
MSG_BOX_BUTTON(N_("~Cancel"), lun_cancel, B_ESC));
|
MSG_BOX_BUTTON(N_("~Cancel"), lun_cancel, B_ESC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_download_file_do(struct terminal *term, unsigned char *file, void *data,
|
create_download_file_do(struct terminal *term, unsigned char *file,
|
||||||
int resume)
|
void *data, enum download_resume resume)
|
||||||
{
|
{
|
||||||
struct cdf_hop *cdf_hop = data;
|
struct cdf_hop *cdf_hop = data;
|
||||||
unsigned char *wd;
|
unsigned char *wd;
|
||||||
@ -660,8 +672,9 @@ create_download_file_do(struct terminal *term, unsigned char *file, void *data,
|
|||||||
/* O_APPEND means repositioning at the end of file before each write(),
|
/* O_APPEND means repositioning at the end of file before each write(),
|
||||||
* thus ignoring seek()s and that can hide mysterious bugs. IMHO.
|
* thus ignoring seek()s and that can hide mysterious bugs. IMHO.
|
||||||
* --pasky */
|
* --pasky */
|
||||||
h = open(file, O_CREAT | O_WRONLY | (resume ? 0 : O_TRUNC)
|
h = open(file, O_CREAT | O_WRONLY
|
||||||
| (sf && !resume ? O_EXCL : 0),
|
| (resume & DOWNLOAD_RESUME_SELECTED ? 0 : O_TRUNC)
|
||||||
|
| (sf && !(resume & DOWNLOAD_RESUME_SELECTED) ? O_EXCL : 0),
|
||||||
sf ? 0600 : 0666);
|
sf ? 0600 : 0666);
|
||||||
saved_errno = errno; /* Saved in case of ... --Zas */
|
saved_errno = errno; /* Saved in case of ... --Zas */
|
||||||
|
|
||||||
@ -708,15 +721,17 @@ finish:
|
|||||||
|
|
||||||
void
|
void
|
||||||
create_download_file(struct terminal *term, unsigned char *fi,
|
create_download_file(struct terminal *term, unsigned char *fi,
|
||||||
unsigned char **real_file, int safe, int resume,
|
unsigned char **real_file, int safe,
|
||||||
void (*callback)(struct terminal *, int, void *, int),
|
enum download_resume resume,
|
||||||
|
void (*callback)(struct terminal *, int,
|
||||||
|
void *, enum download_resume),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop));
|
struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop));
|
||||||
unsigned char *wd;
|
unsigned char *wd;
|
||||||
|
|
||||||
if (!cdf_hop) {
|
if (!cdf_hop) {
|
||||||
callback(term, -1, data, 0);
|
callback(term, -1, data, resume & ~DOWNLOAD_RESUME_SELECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -824,7 +839,8 @@ subst_file(unsigned char *prog, unsigned char *file)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
common_download_do(struct terminal *term, int fd, void *data, int resume)
|
common_download_do(struct terminal *term, int fd, void *data,
|
||||||
|
enum download_resume resume)
|
||||||
{
|
{
|
||||||
struct file_download *file_download;
|
struct file_download *file_download;
|
||||||
struct cmdw_hop *cmdw_hop = data;
|
struct cmdw_hop *cmdw_hop = data;
|
||||||
@ -839,7 +855,8 @@ common_download_do(struct terminal *term, int fd, void *data, int resume)
|
|||||||
file_download = init_file_download(ses->download_uri, ses, file, fd);
|
file_download = init_file_download(ses->download_uri, ses, file, fd);
|
||||||
if (!file_download) return;
|
if (!file_download) return;
|
||||||
|
|
||||||
if (resume) file_download->seek = buf.st_size;
|
if (resume & DOWNLOAD_RESUME_SELECTED)
|
||||||
|
file_download->seek = buf.st_size;
|
||||||
|
|
||||||
display_download(ses->tab->term, file_download, ses);
|
display_download(ses->tab->term, file_download, ses);
|
||||||
|
|
||||||
@ -848,7 +865,8 @@ common_download_do(struct terminal *term, int fd, void *data, int resume)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
common_download(struct session *ses, unsigned char *file, int resume)
|
common_download(struct session *ses, unsigned char *file,
|
||||||
|
enum download_resume resume)
|
||||||
{
|
{
|
||||||
struct cmdw_hop *cmdw_hop;
|
struct cmdw_hop *cmdw_hop;
|
||||||
|
|
||||||
@ -868,19 +886,22 @@ common_download(struct session *ses, unsigned char *file, int resume)
|
|||||||
void
|
void
|
||||||
start_download(void *ses, unsigned char *file)
|
start_download(void *ses, unsigned char *file)
|
||||||
{
|
{
|
||||||
common_download(ses, file, 0);
|
common_download(ses, file,
|
||||||
|
DOWNLOAD_RESUME_ALLOWED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
resume_download(void *ses, unsigned char *file)
|
resume_download(void *ses, unsigned char *file)
|
||||||
{
|
{
|
||||||
common_download(ses, file, 1);
|
common_download(ses, file,
|
||||||
|
DOWNLOAD_RESUME_ALLOWED | DOWNLOAD_RESUME_SELECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
continue_download_do(struct terminal *term, int fd, void *data, int resume)
|
continue_download_do(struct terminal *term, int fd, void *data,
|
||||||
|
enum download_resume resume)
|
||||||
{
|
{
|
||||||
struct codw_hop *codw_hop = data;
|
struct codw_hop *codw_hop = data;
|
||||||
struct file_download *file_download = NULL;
|
struct file_download *file_download = NULL;
|
||||||
@ -953,7 +974,8 @@ continue_download(void *data, unsigned char *file)
|
|||||||
|
|
||||||
create_download_file(type_query->ses->tab->term, file,
|
create_download_file(type_query->ses->tab->term, file,
|
||||||
&codw_hop->real_file,
|
&codw_hop->real_file,
|
||||||
!!type_query->external_handler, 0,
|
!!type_query->external_handler,
|
||||||
|
DOWNLOAD_RESUME_ALLOWED,
|
||||||
continue_download_do, codw_hop);
|
continue_download_do, codw_hop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,11 +99,27 @@ int download_is_progressing(struct download *download);
|
|||||||
|
|
||||||
int are_there_downloads(void);
|
int are_there_downloads(void);
|
||||||
|
|
||||||
|
/** Whether to resume downloading to a file. This is a bit mask.
|
||||||
|
* Unrecognized bits should be preserved and ignored. */
|
||||||
|
enum download_resume {
|
||||||
|
/** All bits clear. Downloading cannot be resumed; do not
|
||||||
|
* offer such an option to the user. */
|
||||||
|
DOWNLOAD_RESUME_DISABLED = 0,
|
||||||
|
|
||||||
|
/** Downloading can be resumed. This is the usual value. */
|
||||||
|
DOWNLOAD_RESUME_ALLOWED = 1,
|
||||||
|
|
||||||
|
/** The user wants to resume downloading. This must not occur
|
||||||
|
* without DOWNLOAD_RESUME_ALLOWED. */
|
||||||
|
DOWNLOAD_RESUME_SELECTED = 2
|
||||||
|
};
|
||||||
|
|
||||||
void start_download(void *, unsigned char *);
|
void start_download(void *, unsigned char *);
|
||||||
void resume_download(void *, unsigned char *);
|
void resume_download(void *, unsigned char *);
|
||||||
void create_download_file(struct terminal *, unsigned char *, unsigned char **,
|
void create_download_file(struct terminal *, unsigned char *, unsigned char **,
|
||||||
int, int,
|
int, enum download_resume,
|
||||||
void (*)(struct terminal *, int, void *, int),
|
void (*)(struct terminal *, int, void *,
|
||||||
|
enum download_resume),
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
void abort_all_downloads(void);
|
void abort_all_downloads(void);
|
||||||
|
@ -1616,7 +1616,8 @@ save_as(struct session *ses, struct document_view *doc_view, int magic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
save_formatted_finish(struct terminal *term, int h, void *data, int resume)
|
save_formatted_finish(struct terminal *term, int h,
|
||||||
|
void *data, enum download_resume resume)
|
||||||
{
|
{
|
||||||
struct document *document = data;
|
struct document *document = data;
|
||||||
|
|
||||||
@ -1643,7 +1644,8 @@ save_formatted(void *data, unsigned char *file)
|
|||||||
assert(doc_view && doc_view->document);
|
assert(doc_view && doc_view->document);
|
||||||
if_assert_failed return;
|
if_assert_failed return;
|
||||||
|
|
||||||
create_download_file(ses->tab->term, file, NULL, 0, 0,
|
create_download_file(ses->tab->term, file, NULL, 0,
|
||||||
|
DOWNLOAD_RESUME_DISABLED,
|
||||||
save_formatted_finish, doc_view->document);
|
save_formatted_finish, doc_view->document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user