diff options
author | Jorge Arellano Cid <jcid@dillo.org> | 2009-11-01 16:32:00 -0300 |
---|---|---|
committer | Jorge Arellano Cid <jcid@dillo.org> | 2009-11-01 16:32:00 -0300 |
commit | d8458319fcfeb7567e32f576f939c62554dedae6 (patch) | |
tree | 3dd1a56a51bc0fc703e31d6635376d5c24ed1ce8 | |
parent | 252144effc180451e16e58a09de22685dd572ce4 (diff) |
ftp dpi: fixed download offer, streamed transfer, added HTML feedback.
Now it behaves as HTTP. Also fixed a bug in dillo with lingering cache
entries (when the file transfer was already done at abort time).
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | dpi/ftp.c | 90 | ||||
-rw-r--r-- | src/cache.c | 9 | ||||
-rw-r--r-- | src/cache.h | 1 | ||||
-rw-r--r-- | src/capi.c | 16 |
5 files changed, 69 insertions, 49 deletions
@@ -21,6 +21,8 @@ dillo-2.2 [??] - Switched capi to use dlib's Dlist instead of a_List_* methods. - Remove empty cache entries on Stop-button press and new link request! - Fixed URL unescaping in the datauri DPI. + - Fixed the FTP dpi: download dialog works, empty cache-entry removal, + feedback page when file doesn't exist and streamed transfer of files. Patches: Jorge Arellano Cid +- Fix segfault from AREA when MAP is missing name attribute. - Fix image map coordinates when margin/border/padding present. @@ -171,17 +171,18 @@ static void make_wget_argv(char *url) /* * Fork, exec command, get its output and send via stdout. - * Return: Number of bytes transfered. + * Return: Number of bytes transfered, -1 if file-not_found, -2 if aborted. */ static int try_ftp_transfer(char *url) { -#define MinSZ 256 +#define MIN_SZ 256 +#define READ_SZ 16*1024 ssize_t n; - int nb, has_mime_type, has_html_header; + int nb, has_mime_type, has_html_header, no_such_file, offer_download; const char *mime_type = "application/octet-stream"; - char buf[4096], *d_cmd; - Dstr *dbuf = dStr_sized_new(4096); + char buf[READ_SZ], *d_cmd; + Dstr *dbuf = dStr_sized_new(READ_SZ); pid_t ch_pid; int aborted = 0; int DataPipe[2]; @@ -214,18 +215,24 @@ static int try_ftp_transfer(char *url) nb = 0; has_mime_type = 0; has_html_header = 0; + no_such_file = 0; + offer_download = 0; do { - while ((n = read(DataPipe[0], buf, 4096)) < 0 && errno == EINTR); + while ((n = read(DataPipe[0], buf, READ_SZ)) < 0 && errno == EINTR); if (n > 0) { dStr_append_l(dbuf, buf, n); - if (!has_mime_type && dbuf->len < MinSZ) + if (!has_mime_type && dbuf->len < MIN_SZ) continue; } else if (n < 0) break; if (!has_mime_type) { - if (dbuf->len > 0) - a_Misc_get_content_type_from_data2(dbuf->str,dbuf->len,&mime_type); + if (dbuf->len == 0) { + /* When the file doesn't exist, the transfer size is zero */ + no_such_file = 1; + break; + } + a_Misc_get_content_type_from_data2(dbuf->str, dbuf->len, &mime_type); has_mime_type = 1; if (strcmp(mime_type, "application/octet-stream") == 0) { @@ -233,11 +240,12 @@ static int try_ftp_transfer(char *url) kill(ch_pid, SIGTERM); /* The "application/octet-stream" MIME type will be sent and * Dillo will offer a download dialog */ + offer_download = 1; aborted = 1; } } - if (!has_html_header && dbuf->len) { + if (offer_download || (!aborted && !has_html_header && dbuf->len)) { /* Send dpip tag */ d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url); a_Dpip_dsh_write_str(sh, 1, d_cmd); @@ -246,18 +254,19 @@ static int try_ftp_transfer(char *url) /* Send HTTP header. */ a_Dpip_dsh_write_str(sh, 0, "Content-type: "); a_Dpip_dsh_write_str(sh, 0, mime_type); - a_Dpip_dsh_write_str(sh, 1, "\n\n"); + a_Dpip_dsh_write_str(sh, 1, "\r\n\r\n"); has_html_header = 1; } if (!aborted && dbuf->len) { - a_Dpip_dsh_write(sh, 0, dbuf->str, dbuf->len); + a_Dpip_dsh_write(sh, 1, dbuf->str, dbuf->len); nb += dbuf->len; dStr_truncate(dbuf, 0); } } while (n > 0 && !aborted); - return nb; + dStr_free(dbuf, 1); + return (no_such_file ? -1 : (aborted ? -2 : nb)); } /* @@ -265,17 +274,11 @@ static int try_ftp_transfer(char *url) */ int main(int argc, char **argv) { + const char *err_msg = "404 Not Found\nNo such file or directory"; char *dpip_tag = NULL, *cmd = NULL, *url = NULL, *url2 = NULL; - int nb, rc; + int st, rc; char *p, *d_cmd; - /* Debugging with a command line argument */ - if (argc == 2) - dpip_tag = dStrdup(argv[1]); - - /* Initialize the SockHandler */ - sh = a_Dpip_dsh_new(STDIN_FILENO, STDOUT_FILENO, 8*1024); - /* wget may need to write a temporary file... */ rc = chdir("/tmp"); if (rc == -1) { @@ -283,17 +286,24 @@ int main(int argc, char **argv) dStrerror(errno)); } - /* Authenticate our client... */ - if (!(dpip_tag = a_Dpip_dsh_read_token(sh, 1)) || - a_Dpip_check_auth(dpip_tag) < 0) { - MSG("can't authenticate request: %s\n", dStrerror(errno)); - a_Dpip_dsh_close(sh); - return 1; - } - dFree(dpip_tag); + /* Initialize the SockHandler */ + sh = a_Dpip_dsh_new(STDIN_FILENO, STDOUT_FILENO, 8*1024); - /* Read the dpi command from STDIN */ - dpip_tag = a_Dpip_dsh_read_token(sh, 1); + if (argc == 2) { + /* Debugging with a command line argument */ + dpip_tag = dStrdup(argv[1]); + } else { + /* Authenticate our client... */ + if (!(dpip_tag = a_Dpip_dsh_read_token(sh, 1)) || + a_Dpip_check_auth(dpip_tag) < 0) { + MSG("can't authenticate request: %s\n", dStrerror(errno)); + a_Dpip_dsh_close(sh); + return 1; + } + dFree(dpip_tag); + /* Read the dpi command from STDIN */ + dpip_tag = a_Dpip_dsh_read_token(sh, 1); + } MSG("tag=[%s]\n", dpip_tag); cmd = a_Dpip_get_attr(dpip_tag, "cmd"); @@ -303,21 +313,27 @@ int main(int argc, char **argv) exit (EXIT_FAILURE); } - if ((nb = try_ftp_transfer(url)) == 0) { + if ((st = try_ftp_transfer(url)) == -1) { /* Transfer failed, the requested file may not exist or be a symlink * to a directory. Try again... */ if ((p = strrchr(url, '/')) && p[1]) { url2 = dStrconcat(url, "/", NULL); - nb = try_ftp_transfer(url2); + st = try_ftp_transfer(url2); } } - if (nb == 0) { + if (st == -1) { /* The transfer failed, let dillo know... */ - d_cmd = a_Dpip_build_cmd("cmd=%s to_cmd=%s msg=%s", - "answer", "open_url", "not a directory"); - a_Dpip_dsh_write_str(sh, 1, d_cmd); + d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url); + a_Dpip_dsh_write_str(sh, 0, d_cmd); dFree(d_cmd); + a_Dpip_dsh_printf(sh, 1, + "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n" + "\r\n" + "%s", + strlen(err_msg), err_msg); } dFree(cmd); diff --git a/src/cache.c b/src/cache.c index 302e9bda..fe2511d1 100644 --- a/src/cache.c +++ b/src/cache.c @@ -999,7 +999,7 @@ static void Cache_auth_entry(CacheEntry_t *entry, BrowserWindow *bw) * Check whether a URL scheme is downloadable. * Return: 1 enabled, 0 disabled. */ -static int Cache_download_enabled(const DilloUrl *url) +int a_Cache_download_enabled(const DilloUrl *url) { if (!dStrcasecmp(URL_SCHEME(url), "http") || !dStrcasecmp(URL_SCHEME(url), "https") || @@ -1035,7 +1035,8 @@ typedef struct { DilloUrl *url; } Cache_savelink_t; -/* Save link from behind a timeout so that Cache_process_queue() can +/* + * Save link from behind a timeout so that Cache_process_queue() can * get on with its work. */ static void Cache_savelink_cb(void *vdata) @@ -1198,8 +1199,10 @@ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) /* Abort the entry, remove it from cache, and maybe offer download. */ DilloUrl *url = a_Url_dup(entry->Url); a_Capi_conn_abort_by_url(url); + /* Necessary when 'conn' is already done */ + Cache_entry_remove(NULL, url); entry = NULL; - if (OfferDownload && Cache_download_enabled(url)) { + if (OfferDownload && a_Cache_download_enabled(url)) { Cache_savelink_t *data = dNew(Cache_savelink_t, 1); data->bw = Client_bw; data->url = url; diff --git a/src/cache.h b/src/cache.h index ff286a0e..cdea361b 100644 --- a/src/cache.h +++ b/src/cache.h @@ -68,6 +68,7 @@ uint_t a_Cache_get_flags(const DilloUrl *url); uint_t a_Cache_get_flags_with_redirection(const DilloUrl *url); void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, const DilloUrl *Url); +int a_Cache_download_enabled(const DilloUrl *url); void a_Cache_entry_inject(const DilloUrl *Url, Dstr *data_ds); void a_Cache_entry_remove_by_url(DilloUrl *url); void a_Cache_freeall(void); @@ -187,6 +187,8 @@ static void Capi_conn_resume(void) /* * Abort the connection for a given url, using its CCC. * (OpAbort 2,BCK removes the cache entry) + * TODO: when conn is already done, the cache entry isn't removed. + * This may be wrong and needs a revision. */ void a_Capi_conn_abort_by_url(const DilloUrl *url) { @@ -341,15 +343,11 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData) MSG_WARN("Cannot open \"%s\" for writing.\n", web->filename); } } - } else { - if (!dStrcasecmp(scheme, "https") || - !dStrcasecmp(scheme, "http") || - !dStrcasecmp(scheme, "ftp")) { - server = "downloads"; - cmd = Capi_dpi_build_cmd(web, server); - a_Capi_dpi_send_cmd(web->url, web->bw, cmd, server, 1); - dFree(cmd); - } + } else if (a_Cache_download_enabled(web->url)) { + server = "downloads"; + cmd = Capi_dpi_build_cmd(web, server); + a_Capi_dpi_send_cmd(web->url, web->bw, cmd, server, 1); + dFree(cmd); } } else if (Capi_url_uses_dpi(web->url, &server)) { |