1
0
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:
Kalle Olavi Niemitalo 2009-07-14 10:27:09 +03:00 committed by Kalle Olavi Niemitalo
parent 6f9501346e
commit 6032bc730a
3 changed files with 73 additions and 33 deletions

View File

@ -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);
} }

View File

@ -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);

View File

@ -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);
} }