diff options
author | Jorge Arellano Cid <jcid@dillo.org> | 2015-05-26 11:29:21 -0300 |
---|---|---|
committer | Jorge Arellano Cid <jcid@dillo.org> | 2015-05-26 11:29:21 -0300 |
commit | 24cff71d47c8b5cd15129a53295a4a27b93f89c0 (patch) | |
tree | 0771368441464f748ebf2f72f7f3090040c4c884 | |
parent | 37948ff867620850b921429c9b36886f40ce3843 (diff) |
Fix view-source dpi to handle null characters correctly
Although not allowed in text contexts, null characters should not
stop/halt/fail dpi protocol, thus the patch.
Test Example. Display a file with these contents:
null padding^@^@
(two trailing null characters)
and view source for it.
Note that dillo will not _display_ the file completely correct,
it will eat a char after each null, but this is not a problem in
dpi nor dpip but in rendering, the cache gets it right.
Adding code to correctly _display_ these anomalous pages is probably
not worth the effort though.
-rw-r--r-- | doc/Dpid.txt | 5 | ||||
-rw-r--r-- | dpi/vsource.c | 56 | ||||
-rw-r--r-- | dpip/dpip.c | 21 | ||||
-rw-r--r-- | dpip/dpip.h | 1 |
4 files changed, 53 insertions, 30 deletions
diff --git a/doc/Dpid.txt b/doc/Dpid.txt index 82b81311..6c418f57 100644 --- a/doc/Dpid.txt +++ b/doc/Dpid.txt @@ -285,9 +285,10 @@ commented code in hello.c and start making changes! Debugging a dpi --------------- - The simplest way is to add printf() feedback using the MSG* + The simplest way is to add printf-like feedback using the MSG* macros. You can start the dpid by hand on a terminal to force -messages to go there. +messages to go there. Filter dpis use sdterr and server dpis +stdout. Sometimes more complex dpis need more than MSG*. In this case you can use gdb like this. diff --git a/dpi/vsource.c b/dpi/vsource.c index 2f1129cb..c28e7b49 100644 --- a/dpi/vsource.c +++ b/dpi/vsource.c @@ -3,7 +3,7 @@ * * This server is an example. Play with it and modify to your taste. * - * Copyright 2010 Jorge Arellano Cid <jcid@dillo.org> + * Copyright 2010-2015 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ * Debugging macros */ #define _MSG(...) -#define MSG(...) printf("[vsource dpi]: " __VA_ARGS__) +#define MSG(...) fprintf(stderr, "[vsource dpi]: " __VA_ARGS__) /*---------------------------------------------------------------------------*/ @@ -42,38 +42,41 @@ void send_dpip_tag(Dsh *sh, char *dpip_tag) /* * Send source as plain text + * (handles embedded null chars correctly). */ void send_plain_text(Dsh *sh, int data_size) { - int bytes_read = 0; - char *src_str; + char *token; + int bytes_read = 0, token_size; /* Send HTTP header for plain text MIME type */ a_Dpip_dsh_write_str(sh, 0, "Content-type: text/plain\n\n"); while (bytes_read < data_size && - (src_str = a_Dpip_dsh_read_token(sh, 1))) { - bytes_read += strlen(src_str); - a_Dpip_dsh_write_str(sh, 1, src_str); - dFree(src_str); + (token = a_Dpip_dsh_read_token2(sh, 1, &token_size))) { + bytes_read += token_size; + _MSG("data_size=%d bytes_read=%d\n", data_size, bytes_read); + a_Dpip_dsh_write(sh, 1, token, token_size); + dFree(token); } } /* * Send source as plain text with line numbers + * (handles embedded null chars correctly). */ void send_numbered_text(Dsh *sh, int data_size) { - int bytes_read = 0, line = 1; - char *p, *q, *src_str, line_str[32]; + int bytes_read = 0, line = 1, token_size = 0; + char *p, *q, *token, line_str[32]; /* Send HTTP header for plain text MIME type */ a_Dpip_dsh_write_str(sh, 0, "Content-type: text/plain\n\n"); while (bytes_read < data_size && - (src_str = a_Dpip_dsh_read_token(sh, 1))) { - bytes_read += strlen(src_str); - p = q = src_str; + (token = a_Dpip_dsh_read_token2(sh, 1, &token_size))) { + bytes_read += token_size; + p = q = token; while (*p) { snprintf(line_str, 32, "%2d: ", line); @@ -84,28 +87,30 @@ void send_numbered_text(Dsh *sh, int data_size) ++p; ++line; } else { - a_Dpip_dsh_write_str(sh, 1, q); + /* send all the rest */ + a_Dpip_dsh_write(sh, 1, q, token_size - (q - token)); break; } q = ++p; } - dFree(src_str); + dFree(token); } } /* * Send source as html text with line numbers + * (handles embedded null chars correctly). */ void send_html_text(Dsh *sh, const char *url, int data_size) { - int bytes_read = 0, old_line = 0, line = 1; - char *p, *q, *src_str, line_str[128]; + int bytes_read = 0, old_line = 0, line = 1, token_size = 0; + char *p, *q, *token, line_str[128]; if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0 && strncmp(url+4, "/vsource/:", 10) == 0) url += 14; - /* Send HTTP header for plain text MIME type */ + /* Send HTTP header for html text MIME type */ a_Dpip_dsh_write_str(sh, 0, "Content-type: text/html\n\n"); a_Dpip_dsh_write_str(sh, 0, DOCTYPE); @@ -119,9 +124,9 @@ void send_html_text(Dsh *sh, const char *url, int data_size) "<body id=\"dillo_vs\">\n<table cellpadding='0'>\n", url); while (bytes_read < data_size && - (src_str = a_Dpip_dsh_read_token(sh, 1))) { - bytes_read += strlen(src_str); - p = q = src_str; + (token = a_Dpip_dsh_read_token2(sh, 1, &token_size))) { + bytes_read += token_size; + p = q = token; while (*p) { if (line > old_line) { @@ -143,13 +148,14 @@ void send_html_text(Dsh *sh, const char *url, int data_size) a_Dpip_dsh_write(sh, 0, q, p - q); a_Dpip_dsh_write_str(sh, 0, (*p == '<') ? "<" : "&"); } - } else { - a_Dpip_dsh_write_str(sh, 1, q); + } else { + /* send all the rest */ + a_Dpip_dsh_write(sh, 1, q, token_size - (q - token)); break; } q = ++p; } - dFree(src_str); + dFree(token); } if (data_size > 0) @@ -194,7 +200,7 @@ int main(void) * asking from us. a_Dpip_dsh_read_token() will block and return * a full dpip token or null on error (it's commented in dpip.c) */ dpip_tag = a_Dpip_dsh_read_token(sh, 1); - MSG("tag = [%s]\n", dpip_tag); + _MSG("tag = [%s]\n", dpip_tag); /* Now that we have the dpip_tag, let's isolate the command and url */ cmd = a_Dpip_get_attr(dpip_tag, "cmd"); diff --git a/dpip/dpip.c b/dpip/dpip.c index f4ce1bf0..2906ba2a 100644 --- a/dpip/dpip.c +++ b/dpip/dpip.c @@ -1,7 +1,7 @@ /* * File: dpip.c * - * Copyright 2005-2007 Jorge Arellano Cid <jcid@dillo.org> + * Copyright 2005-2015 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -427,11 +427,13 @@ static void Dpip_dsh_read(Dsh *dsh, int blocking) /* * Return a newlly allocated string with the next dpip token in the socket. - * Return value: token string on success, NULL otherwise + * Return value: token string and length on success, NULL otherwise. + * (useful for handling null characters in the data stream) */ -char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) +char *a_Dpip_dsh_read_token2(Dsh *dsh, int blocking, int *DataSize) { char *p, *ret = NULL; + *DataSize = 0; /* Read all available data without blocking */ Dpip_dsh_read(dsh, 0); @@ -462,6 +464,7 @@ char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) /* return a full tag */ if ((p = strstr(dsh->rdbuf->str, DPIP_TAG_END))) { ret = dStrndup(dsh->rdbuf->str, p - dsh->rdbuf->str + 3); + *DataSize = p - dsh->rdbuf->str + 3; dStr_erase(dsh->rdbuf, 0, p - dsh->rdbuf->str + 3); if (strstr(ret, DPIP_MODE_SWITCH_TAG)) dsh->mode |= DPIP_LAST_TAG; @@ -470,6 +473,7 @@ char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) /* raw mode, return what we have "as is" */ if (dsh->rdbuf->len > 0) { ret = dStrndup(dsh->rdbuf->str, dsh->rdbuf->len); + *DataSize = dsh->rdbuf->len; dStr_truncate(dsh->rdbuf, 0); } } @@ -478,6 +482,17 @@ char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) } /* + * Return a newlly allocated string with the next dpip token in the socket. + * Return value: token string on success, NULL otherwise + */ +char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) +{ + int token_size; + + return a_Dpip_dsh_read_token2(dsh, blocking, &token_size); +} + +/* * Close this socket for reading and writing. * (flush pending data) */ diff --git a/dpip/dpip.h b/dpip/dpip.h index 1a1846df..a63eb658 100644 --- a/dpip/dpip.h +++ b/dpip/dpip.h @@ -70,6 +70,7 @@ int a_Dpip_dsh_write_str(Dsh *dsh, int flush, const char *str); int a_Dpip_dsh_tryflush(Dsh *dsh); int a_Dpip_dsh_trywrite(Dsh *dsh, const char *Data, int DataSize); char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking); +char *a_Dpip_dsh_read_token2(Dsh *dsh, int blocking, int *DataSize); void a_Dpip_dsh_close(Dsh *dsh); void a_Dpip_dsh_free(Dsh *dsh); |