aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Arellano Cid <jcid@dillo.org>2009-11-01 16:32:00 -0300
committerJorge Arellano Cid <jcid@dillo.org>2009-11-01 16:32:00 -0300
commitd8458319fcfeb7567e32f576f939c62554dedae6 (patch)
tree3dd1a56a51bc0fc703e31d6635376d5c24ed1ce8
parent252144effc180451e16e58a09de22685dd572ce4 (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--ChangeLog2
-rw-r--r--dpi/ftp.c90
-rw-r--r--src/cache.c9
-rw-r--r--src/cache.h1
-rw-r--r--src/capi.c16
5 files changed, 69 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 46323fb6..3c6e805b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/dpi/ftp.c b/dpi/ftp.c
index 0d7bc23a..6b1e2f31 100644
--- a/dpi/ftp.c
+++ b/dpi/ftp.c
@@ -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);
diff --git a/src/capi.c b/src/capi.c
index 1339054b..54e199aa 100644
--- a/src/capi.c
+++ b/src/capi.c
@@ -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)) {