diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/IO/http.c | 33 | ||||
-rw-r--r-- | src/html.cc | 95 | ||||
-rw-r--r-- | src/url.h | 2 |
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) { @@ -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) |