aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/IO/http.c33
-rw-r--r--src/html.cc95
-rw-r--r--src/url.h2
3 files changed, 106 insertions, 24 deletions
diff --git a/src/IO/http.c b/src/IO/http.c
index 41774dc8..bacf4397 100644
--- a/src/IO/http.c
+++ b/src/IO/http.c
@@ -171,6 +171,32 @@ static char *Http_get_referer(const DilloUrl *url)
}
/*
+ * Generate Content-Type header value for a POST query.
+ */
+Dstr *Http_get_content_type(const DilloUrl *url)
+{
+ Dstr *dstr;
+
+ if (URL_FLAGS(url) & URL_MultipartEnc) {
+ MSG("submitting multipart/form-data!\n");
+ dstr = dStr_new("multipart/form-data; boundary=\"");
+ if (strlen(URL_DATA(url)) > 2) {
+ /* boundary lines have "--" prepended. Skip that. */
+ const char *start = URL_DATA(url) + 2;
+ char *eol = strchr(start, '\n');
+ if (eol)
+ dStr_append_l(dstr, start, eol - start);
+ } else {
+ /* If there are zero parts, should a boundary be specified anyway? */
+ }
+ dStr_append_c(dstr,'"');
+ } else {
+ dstr = dStr_new("application/x-www-form-urlencoded");
+ }
+ return dstr;
+}
+
+/*
* Make the http query string
*/
char *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy)
@@ -205,6 +231,7 @@ char *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy)
cookies = a_Cookies_get_query(url);
referer = Http_get_referer(url);
if (URL_FLAGS(url) & URL_Post) {
+ Dstr *content_type = Http_get_content_type(url);
dStr_sprintfa(
query,
"POST %s HTTP/1.1\r\n"
@@ -215,16 +242,16 @@ char *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy)
"User-Agent: Dillo/%s\r\n"
"Accept-Encoding: gzip\r\n"
"%s"
- "Content-type: application/x-www-form-urlencoded\r\n"
+ "Content-type: %s\r\n"
"Content-length: %ld\r\n"
"Connection: close\r\n"
"\r\n"
"%s",
full_path->str, URL_HOST(url), s_port->str,
proxy_auth->str, referer, VERSION, cookies,
- (long)strlen(URL_DATA(url)),
+ content_type->str, (long)strlen(URL_DATA(url)),
URL_DATA(url));
-
+ dStr_free(content_type, TRUE);
} else {
dStr_sprintfa(
query,
diff --git a/src/html.cc b/src/html.cc
index 42b60ed0..af474307 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -145,7 +145,8 @@ typedef enum {
} DilloHtmlMethod;
typedef enum {
- DILLO_HTML_ENC_URLENCODING
+ DILLO_HTML_ENC_URLENCODING,
+ DILLO_HTML_ENC_MULTIPART
} DilloHtmlEnc;
typedef enum {
@@ -3514,8 +3515,10 @@ static void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
else
action = a_Url_dup(html->base_url);
enc = DILLO_HTML_ENC_URLENCODING;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "encoding"))) {
- /* todo: maybe deal with unknown encodings? */
+ if ((method == DILLO_HTML_METHOD_POST) &&
+ ((attrbuf = Html_get_attr(html, tag, tagsize, "enctype")))) {
+ if (!dStrcasecmp(attrbuf, "multipart/form-data"))
+ enc = DILLO_HTML_ENC_MULTIPART;
}
html->formNew(method, action, enc);
a_Url_free(action);
@@ -3808,16 +3811,39 @@ static void Html_urlencode_append(Dstr *str, const char *val)
/*
* Append a name-value pair to an existing url.
- * (name and value are urlencoded before appending them)
*/
static void
- Html_append_input(Dstr *url, const char *name, const char *value)
+ Html_append_input(DilloHtmlEnc encoding, Dstr *url, const char *name,
+ const char *value)
{
+ /*
+ * RFC2046: boundary := 0*69<bchars> bcharsnospace
+ * bchars := bcharsnospace / " "
+ * bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
+ * "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?"
+ */
+ const char *const boundary = "o_JOU,-LJU:ylnyp'Lyf0RUoh4P(8THlfd98?575p0";
+
if (name != NULL) {
- Html_urlencode_append(url, name);
- dStr_append_c(url, '=');
- Html_urlencode_append(url, value);
- dStr_append_c(url, '&');
+ if (encoding == DILLO_HTML_ENC_MULTIPART) {
+ if (url->len == 0) {
+ dStr_append(url, "--");
+ dStr_append(url, boundary);
+ }
+ dStr_sprintfa(url,
+ "\n"
+ "Content-Disposition: form-data; name=\"%s\"\n"
+ "\n"
+ "%s\n"
+ "--%s",
+ name, value, boundary);
+ } else {
+ // URL encoding
+ Html_urlencode_append(url, name);
+ dStr_append_c(url, '=');
+ Html_urlencode_append(url, value);
+ dStr_append_c(url, '&');
+ }
}
}
@@ -3863,24 +3889,28 @@ static void Html_submit_form2(DilloHtml *html, DilloHtmlForm *form,
case DILLO_HTML_INPUT_PASSWORD:
EntryResource *entryres;
entryres = (EntryResource*)((Embed*)input->widget)->getResource();
- Html_append_input(DataStr, input->name, entryres->getText());
+ Html_append_input(form->enc, DataStr, input->name,
+ entryres->getText());
break;
case DILLO_HTML_INPUT_TEXTAREA:
MultiLineTextResource *textres;
textres = (MultiLineTextResource*)((Embed*)input->widget)
->getResource();
- Html_append_input(DataStr, input->name, textres->getText());
+ Html_append_input(form->enc, DataStr, input->name,
+ textres->getText());
break;
case DILLO_HTML_INPUT_CHECKBOX:
case DILLO_HTML_INPUT_RADIO:
ToggleButtonResource *cb_r;
cb_r=(ToggleButtonResource*)((Embed*)input->widget)->getResource();
if (input->name && input->init_str && cb_r->isActivated()) {
- Html_append_input(DataStr, input->name, input->init_str);
+ Html_append_input(form->enc, DataStr, input->name,
+ input->init_str);
}
break;
case DILLO_HTML_INPUT_HIDDEN:
- Html_append_input(DataStr, input->name, input->init_str);
+ Html_append_input(form->enc, DataStr, input->name,
+ input->init_str);
break;
case DILLO_HTML_INPUT_SELECT:
case DILLO_HTML_INPUT_SEL_LIST:
@@ -3893,7 +3923,7 @@ static void Html_submit_form2(DilloHtml *html, DilloHtmlForm *form,
DilloHtmlOption *option =
input->select->options->get (i);
char *val = option->value ? option->value : option->content;
- Html_append_input(DataStr, input->name, val);
+ Html_append_input(form->enc, DataStr, input->name, val);
}
}
break;
@@ -3904,22 +3934,34 @@ static void Html_submit_form2(DilloHtml *html, DilloHtmlForm *form,
// break;
// case DILLO_HTML_INPUT_IMAGE:
// if (input->widget == submit) {
+// will have to be modified for handle enctype="multipart/form-data"
// Html_append_input(DataStr, input->name, input->init_str);
// Html_append_clickpos(DataStr, input->name, click_x, click_y);
// }
// break;
+ case DILLO_HTML_INPUT_FILE:
+ MSG("Data from file input not submitted\n");
+ // If multiple files are submitted, multipart/mixed should be used.
+ break;
case DILLO_HTML_INPUT_SUBMIT:
case DILLO_HTML_INPUT_BUTTON_SUBMIT:
if (input_idx == e_input_idx && form->num_submit_buttons > 0)
- Html_append_input(DataStr, input->name, input->init_str);
+ Html_append_input(form->enc, DataStr, input->name,
+ input->init_str);
break;
default:
break;
} /* switch */
} /* for (inputs) */
-
- if (DataStr->str[DataStr->len - 1] == '&')
- dStr_truncate(DataStr, DataStr->len - 1);
+
+ if (DataStr->len > 0) {
+ if (form->enc == DILLO_HTML_ENC_URLENCODING) {
+ if (DataStr->str[DataStr->len - 1] == '&')
+ dStr_truncate(DataStr, DataStr->len - 1);
+ } else if (form->enc == DILLO_HTML_ENC_MULTIPART) {
+ dStr_append(DataStr, "--");
+ }
+ }
/* form->action was previously resolved against base URL */
action_str = dStrdup(URL_STR(form->action));
@@ -3928,6 +3970,9 @@ static void Html_submit_form2(DilloHtml *html, DilloHtmlForm *form,
new_url = a_Url_new(action_str, NULL, 0, 0, 0);
a_Url_set_data(new_url, DataStr->str);
a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Post);
+ if (form->enc == DILLO_HTML_ENC_MULTIPART) {
+ a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_MultipartEnc);
+ }
} else {
/* remove <fragment> and <query> sections if present */
if ((p = strchr(action_str, '#')))
@@ -4166,9 +4211,17 @@ static void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
}
} else if (!dStrcasecmp(type, "file")) {
/* todo: implement it! */
-// inp_type = DILLO_HTML_INPUT_FILE;
-// init_str = (value) ? value : NULL;
- MSG("An input of the type \"file\" wasn't rendered!\n");
+ if (form->method != DILLO_HTML_METHOD_POST) {
+ /*
+ * The letter of the spec only states that file inputs "should" be
+ * used with enctype multipart/form-data (only meaningful with POST).
+ */
+ MSG("File input ignored in form not using HTTP POST method\n");
+ } else {
+// inp_type = DILLO_HTML_INPUT_FILE;
+// init_str = (value) ? value : NULL;
+ MSG("An input of the type \"file\" wasn't rendered!\n");
+ }
} else if (!dStrcasecmp(type, "button")) {
inp_type = DILLO_HTML_INPUT_BUTTON;
if (value) {
diff --git a/src/url.h b/src/url.h
index 1781c802..344ea15f 100644
--- a/src/url.h
+++ b/src/url.h
@@ -42,6 +42,8 @@
#define URL_ReloadIncomplete (1 << 9)
#define URL_SpamSafe (1 << 10)
+#define URL_MultipartEnc (1 << 11)
+
/*
* Access methods to fields inside DilloURL.
* (non '_'-ended macros MUST use these for initialization sake)