2005-09-15 09:58:31 -04:00
|
|
|
#ifndef EL__SESSION_DOWNLOAD_H
|
|
|
|
#define EL__SESSION_DOWNLOAD_H
|
|
|
|
|
|
|
|
#include "main/object.h"
|
|
|
|
#include "network/state.h"
|
|
|
|
#include "util/lists.h"
|
|
|
|
#include "util/time.h"
|
|
|
|
|
2020-10-05 14:14:55 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
/* Silly BFU stuff */
|
|
|
|
struct dialog_data;
|
|
|
|
struct listbox_item;
|
|
|
|
struct terminal;
|
|
|
|
|
|
|
|
struct cache_entry;
|
|
|
|
struct connection;
|
|
|
|
struct session;
|
|
|
|
struct uri;
|
|
|
|
|
|
|
|
struct download;
|
|
|
|
|
|
|
|
typedef void (download_callback_T)(struct download *, void *);
|
|
|
|
|
2009-07-24 11:09:59 -04:00
|
|
|
/** Flags controlling how to download a file. This is a bit mask.
|
2009-07-24 09:57:33 -04:00
|
|
|
* Unrecognized bits should be preserved and ignored. */
|
|
|
|
enum download_flags {
|
|
|
|
/** Downloading cannot be resumed; do not offer such an option
|
|
|
|
* to the user. All bits clear. */
|
|
|
|
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
|
2009-07-24 11:09:59 -04:00
|
|
|
* without #DOWNLOAD_RESUME_ALLOWED. */
|
|
|
|
DOWNLOAD_RESUME_SELECTED = 2,
|
|
|
|
|
|
|
|
/** The file will be opened in an external handler. */
|
2021-03-31 13:24:26 -04:00
|
|
|
DOWNLOAD_EXTERNAL = 4,
|
|
|
|
|
|
|
|
/** File overwriting is allowed. This is for temp names, since
|
|
|
|
* the file is created by the same function that chooses its
|
|
|
|
* name. */
|
|
|
|
DOWNLOAD_OVERWRITE = 8
|
2007-11-07 06:57:13 -05:00
|
|
|
};
|
|
|
|
|
2022-01-28 11:26:15 -05:00
|
|
|
typedef unsigned char download_flags_T;
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
struct download {
|
|
|
|
/* XXX: order matters there, there's some hard initialization in
|
|
|
|
* src/session/session.c and src/viewer/text/view.c */
|
|
|
|
LIST_HEAD(struct download);
|
|
|
|
|
|
|
|
struct connection *conn;
|
|
|
|
struct cache_entry *cached;
|
2007-07-26 20:07:39 -04:00
|
|
|
/** The callback is called when connection gets into a progress state,
|
2005-09-15 09:58:31 -04:00
|
|
|
* after it's over (in a result state), and also periodically after
|
|
|
|
* the download starts receiving some data. */
|
|
|
|
download_callback_T *callback;
|
|
|
|
void *data;
|
|
|
|
struct progress *progress;
|
|
|
|
|
2008-08-03 08:24:26 -04:00
|
|
|
struct connection_state state;
|
|
|
|
struct connection_state prev_error;
|
2022-01-28 10:22:03 -05:00
|
|
|
connection_priority_T pri;
|
2005-09-15 09:58:31 -04:00
|
|
|
};
|
|
|
|
|
2009-07-17 07:10:36 -04:00
|
|
|
/** The user has navigated to a resource that ELinks does not display
|
|
|
|
* automatically because of its MIME type, and ELinks is asking what
|
|
|
|
* to do.
|
|
|
|
*
|
|
|
|
* These structures are kept in the session.type_queries list, and
|
|
|
|
* destroy_session() calls done_type_query() to destroy them too. */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct type_query {
|
|
|
|
LIST_HEAD(struct type_query);
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** After ELinks has downloaded enough of the resource to see
|
|
|
|
* that a type query is needed, it moves the download here and
|
|
|
|
* continues it while the user decides what to do. */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct download download;
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** Cache entry loaded from #uri. Apparently used only for
|
|
|
|
* displaying the header. */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct cache_entry *cached;
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** The session in which the user navigated to #uri. The
|
|
|
|
* type_query is in the session.type_queries list of this
|
|
|
|
* session. */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct session *ses;
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** The URI of the resource about which ELinks is asking.
|
|
|
|
* This reference must be released with done_uri(). */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct uri *uri;
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** The name of the frame in which the user navigated to #uri.
|
|
|
|
* If the user chooses to display the resource, it goes into
|
|
|
|
* this frame. This string must be freed with mem_free(). */
|
2021-01-02 10:20:27 -05:00
|
|
|
char *target_frame;
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** Command line for an external handler, to be run when the
|
|
|
|
* download finishes. When ELinks displays the type query,
|
|
|
|
* it copies this from mime_handler.program of the default
|
|
|
|
* handler of the type. The user can then edit the string.
|
|
|
|
* This string must be freed with mem_free(). */
|
2021-01-02 10:20:27 -05:00
|
|
|
char *external_handler;
|
2009-07-23 15:57:11 -04:00
|
|
|
|
|
|
|
/** Whether the external handler is going to use the terminal.
|
|
|
|
* When ELinks displays the type query, it copies this from
|
|
|
|
* mime_handler.block of the default handler of the type.
|
|
|
|
* The user can then change the flag with a checkbox. */
|
2005-09-15 09:58:31 -04:00
|
|
|
int block;
|
2009-07-17 07:10:36 -04:00
|
|
|
|
|
|
|
/** Whether the resource was generated by ELinks running
|
|
|
|
* a local CGI program. If the user chooses to open the
|
|
|
|
* resource with an external handler, ELinks normally saves
|
|
|
|
* the resource to a temporary file and passes the name of
|
|
|
|
* that to the external handler. However, if the resource is
|
|
|
|
* from a "file" URI that does not refer to a local CGI, then
|
|
|
|
* Elinks need not copy the file. */
|
2008-03-09 07:50:09 -04:00
|
|
|
unsigned int cgi:1;
|
2009-07-17 07:10:36 -04:00
|
|
|
|
2010-07-24 11:07:18 -04:00
|
|
|
/** mailcap entry with copiousoutput */
|
|
|
|
unsigned int copiousoutput:1;
|
2005-09-15 09:58:31 -04:00
|
|
|
/* int frame; */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct file_download {
|
|
|
|
OBJECT_HEAD(struct file_download);
|
|
|
|
|
|
|
|
struct uri *uri;
|
2021-01-02 10:20:27 -05:00
|
|
|
char *file;
|
|
|
|
char *external_handler;
|
2005-09-15 09:58:31 -04:00
|
|
|
struct session *ses;
|
bug 1054: Don't abort downloads when closing a terminal.
Except if they have external handlers.
When ELinks receives an event from a terminal, move that terminal to
the beginning of the global "terminals" list, so that the terminals
are always sorted according to the time of the most recent use. Note,
this affects the numbering of bookmark folders in session snapshots.
Add get_default_terminal(), which returns the most recently used
terminal that is still open. Use that in various places that
previously used terminals.prev or terminals.next. Four functions
fetch the size of the terminal for User-Agent headers, and
get_default_terminal() is not really right, but neither was the
original code; add TODO comments in those functions.
When the user chooses "Background and Notify", associate the download
with the terminal where the dialog box is. So any later messages will
then appear in that terminal, if it is still open. However, don't
change the terminal if the download has an external handler.
When a download gets some data, don't immediately check the associated
terminal. Instead, wait for the download to end. Then, if the
terminal of the download has been closed, use get_default_terminal()
instead. If there is no default terminal either, just skip any
message boxes.
2008-10-15 04:05:43 -04:00
|
|
|
|
|
|
|
/** The terminal in which message boxes about the download
|
|
|
|
* should be displayed. If this terminal is closed, then
|
|
|
|
* detach_downloads_from_terminal() changes the pointer to
|
|
|
|
* NULL, and get_default_terminal() will be used if a
|
|
|
|
* terminal is needed later. However, if the download has
|
|
|
|
* an external handler, then detach_downloads_from_terminal()
|
|
|
|
* aborts it right away; external handlers always run in the
|
|
|
|
* original terminal, if anywhere. */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct terminal *term;
|
bug 1054: Don't abort downloads when closing a terminal.
Except if they have external handlers.
When ELinks receives an event from a terminal, move that terminal to
the beginning of the global "terminals" list, so that the terminals
are always sorted according to the time of the most recent use. Note,
this affects the numbering of bookmark folders in session snapshots.
Add get_default_terminal(), which returns the most recently used
terminal that is still open. Use that in various places that
previously used terminals.prev or terminals.next. Four functions
fetch the size of the terminal for User-Agent headers, and
get_default_terminal() is not really right, but neither was the
original code; add TODO comments in those functions.
When the user chooses "Background and Notify", associate the download
with the terminal where the dialog box is. So any later messages will
then appear in that terminal, if it is still open. However, don't
change the terminal if the download has an external handler.
When a download gets some data, don't immediately check the associated
terminal. Instead, wait for the download to end. Then, if the
terminal of the download has been closed, use get_default_terminal()
instead. If there is no default terminal either, just skip any
message boxes.
2008-10-15 04:05:43 -04:00
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
time_t remotetime;
|
|
|
|
off_t seek;
|
|
|
|
int handle;
|
|
|
|
int redirect_cnt;
|
|
|
|
int notify;
|
|
|
|
struct download download;
|
|
|
|
|
2007-07-26 20:07:39 -04:00
|
|
|
/** Should the file be deleted when destroying the structure */
|
2016-04-20 12:57:32 -04:00
|
|
|
unsigned int delete_:1;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2007-07-26 20:07:39 -04:00
|
|
|
/** Should the download be stopped/interrupted when destroying the structure */
|
2005-09-15 09:58:31 -04:00
|
|
|
unsigned int stop:1;
|
|
|
|
|
2007-07-26 20:07:39 -04:00
|
|
|
/** Whether to block the terminal when running the external handler. */
|
2005-09-15 09:58:31 -04:00
|
|
|
unsigned int block:1;
|
|
|
|
|
2010-07-24 11:07:18 -04:00
|
|
|
/** Mailcap entry with copiousoutput */
|
|
|
|
unsigned int copiousoutput:1;
|
|
|
|
|
2007-07-26 20:07:39 -04:00
|
|
|
/** The current dialog for this download. Can be NULL. */
|
2005-09-15 09:58:31 -04:00
|
|
|
struct dialog_data *dlg_data;
|
|
|
|
struct listbox_item *box_item;
|
|
|
|
};
|
|
|
|
|
2007-07-26 20:07:39 -04:00
|
|
|
/** Stack of all running downloads */
|
2007-07-26 15:39:08 -04:00
|
|
|
extern LIST_OF(struct file_download) downloads;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
static inline int
|
|
|
|
is_in_downloads_list(struct file_download *file_download)
|
|
|
|
{
|
|
|
|
struct file_download *down;
|
|
|
|
|
|
|
|
foreach (down, downloads)
|
|
|
|
if (file_download == down) return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int download_is_progressing(struct download *download);
|
|
|
|
|
|
|
|
int are_there_downloads(void);
|
|
|
|
|
2009-07-17 16:16:38 -04:00
|
|
|
/** Type of the callback function that will be called when the file
|
|
|
|
* has been opened, or when it is known that the file will not be
|
|
|
|
* opened.
|
|
|
|
*
|
|
|
|
* @param term
|
|
|
|
* The terminal on which the callback should display any windows.
|
|
|
|
* Comes directly from the @a term argument of create_download_file().
|
|
|
|
*
|
|
|
|
* @param fd
|
|
|
|
* A file descriptor to the opened file, or -1 if the file will not be
|
|
|
|
* opened. If the @a real_file argument of create_download_file()
|
|
|
|
* was not NULL, the callback may read the name of this file from
|
|
|
|
* *@a real_file.
|
|
|
|
*
|
|
|
|
* @param data
|
|
|
|
* A pointer to any data that the callback cares about.
|
|
|
|
* Comes directly from the @a data argument of create_download_file().
|
|
|
|
*
|
2009-07-24 09:57:33 -04:00
|
|
|
* @param flags
|
|
|
|
* The same as the @a flags argument of create_download_file(),
|
2009-07-17 16:16:38 -04:00
|
|
|
* except the ::DOWNLOAD_RESUME_SELECTED bit will be changed to match
|
|
|
|
* what the user chose.
|
|
|
|
*
|
|
|
|
* @relates cdf_hop */
|
|
|
|
typedef void cdf_callback_T(struct terminal *term, int fd,
|
2022-01-28 11:26:15 -05:00
|
|
|
void *data, download_flags_T flags);
|
2009-07-17 16:16:38 -04:00
|
|
|
|
2021-01-02 10:20:27 -05:00
|
|
|
void start_download(void *, char *);
|
|
|
|
void resume_download(void *, char *);
|
|
|
|
void create_download_file(struct terminal *, char *, char **,
|
2022-01-28 11:26:15 -05:00
|
|
|
download_flags_T, cdf_callback_T *, void *);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
void abort_all_downloads(void);
|
|
|
|
void destroy_downloads(struct session *);
|
2008-09-30 03:06:20 -04:00
|
|
|
void detach_downloads_from_terminal(struct terminal *);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
int setup_download_handler(struct session *, struct download *, struct cache_entry *, int);
|
|
|
|
|
|
|
|
void abort_download(struct file_download *file_download);
|
|
|
|
void done_type_query(struct type_query *type_query);
|
|
|
|
|
|
|
|
void tp_display(struct type_query *type_query);
|
|
|
|
void tp_save(struct type_query *type_query);
|
|
|
|
void tp_cancel(void *data);
|
2021-01-02 10:20:27 -05:00
|
|
|
struct file_download *init_file_download(struct uri *uri, struct session *ses, char *file, int fd);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-05 14:14:55 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
#endif
|