summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2003-10-25 14:13:49 +0000
committerJames Bursa <james@netsurf-browser.org>2003-10-25 14:13:49 +0000
commit28f974f00f43d3a04c0bcae32e7cfc85ee66df20 (patch)
tree9ab73b22014e6da29c851698b0f7c0262260cc8e
parentf1375fe19db064fcebf00433ce73eab99be038ef (diff)
downloadnetsurf-28f974f00f43d3a04c0bcae32e7cfc85ee66df20.tar.gz
netsurf-28f974f00f43d3a04c0bcae32e7cfc85ee66df20.tar.bz2
[project @ 2003-10-25 14:13:49 by bursa]
URL encoded POST support. svn path=/import/netsurf/; revision=375
-rw-r--r--content/fetch.c31
-rw-r--r--content/fetch.h4
-rw-r--r--content/fetchcache.c6
-rw-r--r--content/fetchcache.h5
-rw-r--r--css/css.c8
-rw-r--r--debug/netsurfd.c2
-rw-r--r--desktop/browser.c74
-rw-r--r--desktop/browser.h4
-rw-r--r--render/box.c36
-rw-r--r--render/form.c2
-rw-r--r--render/form.h10
-rw-r--r--render/html.c14
-rw-r--r--riscos/401login.c2
-rw-r--r--riscos/gui.c3
-rw-r--r--riscos/mouseactions.c2
15 files changed, 135 insertions, 68 deletions
diff --git a/content/fetch.c b/content/fetch.c
index 88b451523..f95d7138b 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -29,6 +29,7 @@
#endif
#include "netsurf/desktop/options.h"
#include "netsurf/desktop/401login.h"
+#include "netsurf/render/form.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"
@@ -52,6 +53,7 @@ struct fetch {
char *location; /**< Response Location header, or 0. */
unsigned long content_length; /**< Response Content-Length, or 0. */
char *realm; /**< HTTP Auth Realm */
+ char *post_urlenc; /**< Url encoded POST string, or 0. */
struct fetch *queue; /**< Next fetch for this host. */
struct fetch *prev; /**< Previous active fetch in ::fetch_list. */
struct fetch *next; /**< Next active fetch in ::fetch_list. */
@@ -138,8 +140,9 @@ void fetch_quit(void)
*/
struct fetch * fetch_start(char *url, char *referer,
- void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size),
- void *p, bool only_2xx)
+ void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size),
+ void *p, bool only_2xx, char *post_urlenc,
+ struct form_successful_control *post_multipart)
{
struct fetch *fetch = xcalloc(1, sizeof(*fetch)), *host_fetch;
CURLcode code;
@@ -170,6 +173,9 @@ struct fetch * fetch_start(char *url, char *referer,
if (uri->server != 0)
fetch->host = xstrdup(uri->server);
fetch->content_length = 0;
+ fetch->post_urlenc = 0;
+ if (post_urlenc)
+ fetch->post_urlenc = xstrdup(post_urlenc);
fetch->queue = 0;
fetch->prev = 0;
fetch->next = 0;
@@ -257,10 +263,19 @@ struct fetch * fetch_start(char *url, char *referer,
code = curl_easy_setopt(fetch->curl_handle, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
assert(code == CURLE_OK);
+#ifdef riscos
if (LOGIN.string != NULL) {
code = curl_easy_setopt(fetch->curl_handle, CURLOPT_USERPWD, LOGIN.string);
assert(code == CURLE_OK);
}
+#endif
+
+ /* POST */
+ if (fetch->post_urlenc) {
+ code = curl_easy_setopt(fetch->curl_handle,
+ CURLOPT_POSTFIELDS, fetch->post_urlenc);
+ assert(code == CURLE_OK);
+ }
/* add to the global curl multi handle */
codem = curl_multi_add_handle(curl_multi, fetch->curl_handle);
@@ -327,11 +342,18 @@ void fetch_abort(struct fetch *f)
code = curl_easy_setopt(fetch->curl_handle, CURLOPT_WRITEHEADER, fetch);
assert(code == CURLE_OK);
/* TODO: remove referer header if fetch->referer == 0 */
- if (fetch->referer != 0) {
+ /*if (fetch->referer != 0)*/ {
code = curl_easy_setopt(fetch->curl_handle, CURLOPT_REFERER, fetch->referer);
assert(code == CURLE_OK);
}
+ /* POST */
+ if (fetch->post_urlenc) {
+ code = curl_easy_setopt(fetch->curl_handle,
+ CURLOPT_POSTFIELDS, fetch->post_urlenc);
+ assert(code == CURLE_OK);
+ }
+
/* add to the global curl multi handle */
codem = curl_multi_add_handle(curl_multi, fetch->curl_handle);
assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
@@ -346,6 +368,7 @@ void fetch_abort(struct fetch *f)
free(f->referer);
free(f->location);
free(f->realm);
+ free(f->post_urlenc);
xfree(f);
}
@@ -502,6 +525,7 @@ bool fetch_process_headers(struct fetch *f)
return true;
}
+#ifdef riscos
/* handle HTTP 401 (Authentication errors) */
if (http_code == 401) {
/* this shouldn't be here... */
@@ -510,6 +534,7 @@ bool fetch_process_headers(struct fetch *f)
f->callback(FETCH_ERROR, f->p, "",0);
return true;
}
+#endif
/* handle HTTP errors (non 2xx response codes) */
if (f->only_2xx && strncmp(f->url, "http", 4) == 0 &&
diff --git a/content/fetch.h b/content/fetch.h
index ed469de04..762664923 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -18,11 +18,13 @@ typedef enum {FETCH_TYPE, FETCH_DATA, FETCH_FINISHED, FETCH_ERROR, FETCH_REDIREC
struct content;
struct fetch;
+struct form_successful_control;
void fetch_init(void);
struct fetch * fetch_start(char *url, char *referer,
void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size),
- void *p, bool only_2xx);
+ void *p, bool only_2xx, char *post_urlenc,
+ struct form_successful_control *post_multipart);
void fetch_abort(struct fetch *f);
void fetch_poll(void);
void fetch_quit(void);
diff --git a/content/fetchcache.c b/content/fetchcache.c
index cf5bccf47..942f38773 100644
--- a/content/fetchcache.c
+++ b/content/fetchcache.c
@@ -42,7 +42,8 @@ struct content * fetchcache(const char *url0, char *referer,
void (*callback)(content_msg msg, struct content *c, void *p1,
void *p2, const char *error),
void *p1, void *p2, unsigned long width, unsigned long height,
- bool only_2xx)
+ bool only_2xx, char *post_urlenc,
+ struct form_successful_control *post_multipart)
{
struct content *c;
char *url = xstrdup(url0);
@@ -67,7 +68,8 @@ struct content * fetchcache(const char *url0, char *referer,
c->fetch_size = 0;
c->width = width;
c->height = height;
- c->fetch = fetch_start(url, referer, fetchcache_callback, c, only_2xx);
+ c->fetch = fetch_start(url, referer, fetchcache_callback, c, only_2xx,
+ post_urlenc, post_multipart);
free(url);
if (c->fetch == 0) {
LOG(("warning: fetch_start failed"));
diff --git a/content/fetchcache.h b/content/fetchcache.h
index bd7c09933..a0a25c2f8 100644
--- a/content/fetchcache.h
+++ b/content/fetchcache.h
@@ -18,10 +18,13 @@
#include <stdbool.h>
#include "netsurf/content/content.h"
+struct form_successful_control;
+
struct content * fetchcache(const char *url, char *referer,
void (*callback)(content_msg msg, struct content *c, void *p1,
void *p2, const char *error),
void *p1, void *p2, unsigned long width, unsigned long height,
- bool only_2xx);
+ bool only_2xx, char *post_urlenc,
+ struct form_successful_control *post_multipart);
#endif
diff --git a/css/css.c b/css/css.c
index c5c5c7780..3dfcdd632 100644
--- a/css/css.c
+++ b/css/css.c
@@ -173,7 +173,7 @@ void css_revive(struct content *c, unsigned int width, unsigned int height)
c->data.css.import_content[i] = fetchcache(
c->data.css.import_url[i], c->url,
css_atimport_callback, c, i,
- c->width, c->height, true);
+ c->width, c->height, true, 0, 0);
if (c->data.css.import_content[i] == 0)
continue;
if (c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
@@ -333,7 +333,7 @@ void css_atimport(struct content *c, struct css_node *node)
c->data.css.import_url[i] = url_join(url, c->url);
c->data.css.import_content[i] = fetchcache(
c->data.css.import_url[i], c->url, css_atimport_callback,
- c, i, c->width, c->height, true);
+ c, i, c->width, c->height, true, 0, 0);
if (c->data.css.import_content[i] &&
c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
c->active++;
@@ -381,7 +381,7 @@ void css_atimport_callback(content_msg msg, struct content *css,
c->data.css.import_url[i] = xstrdup(error);
c->data.css.import_content[i] = fetchcache(
c->data.css.import_url[i], c->url, css_atimport_callback,
- c, i, css->width, css->height, true);
+ c, i, css->width, css->height, true, 0, 0);
if (c->data.css.import_content[i] &&
c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
c->active++;
@@ -568,7 +568,7 @@ void css_parse_property_list(struct css_style * style, char * str)
void *parser;
YY_BUFFER_STATE buffer;
int token;
- struct parse_params param = {1, 0, 0};
+ struct parse_params param = {1, 0, 0, false};
css_lex_init(&lexer);
parser = css_parser_Alloc(malloc);
diff --git a/debug/netsurfd.c b/debug/netsurfd.c
index 3d4c1cb5b..c09dd3f2f 100644
--- a/debug/netsurfd.c
+++ b/debug/netsurfd.c
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
return 0;
url[strlen(url) - 1] = 0;
destroyed = 0;
- c = fetchcache(url, 0, callback, 0, 0, 100, 1000, false);
+ c = fetchcache(url, 0, callback, 0, 0, 100, 1000, false, 0, 0);
if (c) {
done = c->status == CONTENT_STATUS_DONE;
while (!done)
diff --git a/desktop/browser.c b/desktop/browser.c
index 67a4670dc..16fc03126 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -38,6 +38,9 @@ static int redraw_box_list(struct browser_window* bw, struct box* current,
static void browser_window_redraw_boxes(struct browser_window* bw, struct box_position* start, struct box_position* end);
static void browser_window_follow_link(struct browser_window* bw,
unsigned long click_x, unsigned long click_y, int click_type);
+static void browser_window_open_location_post(struct browser_window* bw,
+ const char* url0, char *post_urlenc,
+ struct form_successful_control *post_multipart);
static void browser_window_callback(content_msg msg, struct content *c,
void *p1, void *p2, const char *error);
static void download_window_callback(content_msg msg, struct content *c,
@@ -117,7 +120,7 @@ void browser_window_back(struct browser_window* bw)
if (bw->history->earlier != NULL)
{
bw->history = bw->history->earlier;
- browser_window_open_location_historical(bw, bw->history->url);
+ browser_window_open_location_historical(bw, bw->history->url, 0, 0);
}
}
}
@@ -129,7 +132,7 @@ void browser_window_forward(struct browser_window* bw)
if (bw->history->later != NULL)
{
bw->history = bw->history->later;
- browser_window_open_location_historical(bw, bw->history->url);
+ browser_window_open_location_historical(bw, bw->history->url, 0, 0);
}
}
}
@@ -241,7 +244,9 @@ void browser_window_destroy(struct browser_window* bw)
LOG(("end"));
}
-void browser_window_open_location_historical(struct browser_window* bw, const char* url)
+void browser_window_open_location_historical(struct browser_window* bw,
+ const char* url, char *post_urlenc,
+ struct form_successful_control *post_multipart)
{
LOG(("bw = %p, url = %s", bw, url));
@@ -251,7 +256,8 @@ void browser_window_open_location_historical(struct browser_window* bw, const ch
browser_window_start_throbber(bw);
bw->time0 = clock();
bw->loading_content = fetchcache(url, 0, browser_window_callback, bw, 0,
- gui_window_get_width(bw->window), 0, false);
+ gui_window_get_width(bw->window), 0, false,
+ post_urlenc, post_multipart);
if (bw->loading_content == 0) {
browser_window_set_status(bw, "Unable to fetch document");
return;
@@ -266,11 +272,18 @@ void browser_window_open_location_historical(struct browser_window* bw, const ch
void browser_window_open_location(struct browser_window* bw, const char* url0)
{
+ browser_window_open_location_post(bw, url0, 0, 0);
+}
+
+void browser_window_open_location_post(struct browser_window* bw,
+ const char* url0, char *post_urlenc,
+ struct form_successful_control *post_multipart)
+{
char *url;
LOG(("bw = %p, url0 = %s", bw, url0));
assert(bw != 0 && url0 != 0);
url = url_join(url0, bw->url);
- browser_window_open_location_historical(bw, url);
+ browser_window_open_location_historical(bw, url, post_urlenc, post_multipart);
/* TODO: move this to somewhere below CONTENT_MSG_READY below */
if (bw->history == NULL)
bw->history = history_create(NULL, url);
@@ -1569,36 +1582,41 @@ void browser_window_redraw_boxes(struct browser_window* bw, struct box_position*
}
+/**
+ * Collect controls and submit a form.
+ */
+
void browser_form_submit(struct browser_window *bw, struct form *form,
struct form_control *submit_button)
{
+ char *data, *url;
struct form_successful_control *success;
success = form_successful_controls(form, submit_button);
- if (form->method == method_GET) {
- /*GET request*/
- /*GET basically munges the entire form data
- into one URL. */
-
- char *data = form_url_encode(success);
- char *url = xcalloc(1, strlen(form->action) + strlen(data) + 2);
- sprintf(url, "%s?%s", form->action, data);
- free(data);
- browser_window_open_location(bw, url);
- xfree(url);
-
- } else {
- /*POST request*/
- assert(form->method == method_POST);
-
- LOG(("POST request - not implemented yet"));
-
- /*POST is a standard HTTP method.
- Basically, it creates a new request
- and sends the form data as the request
- body.*/
- }
+ switch (form->method) {
+ case method_GET:
+ data = form_url_encode(success);
+ url = xcalloc(1, strlen(form->action) + strlen(data) + 2);
+ sprintf(url, "%s?%s", form->action, data);
+ free(data);
+ browser_window_open_location(bw, url);
+ free(url);
+ break;
+
+ case method_POST_URLENC:
+ data = form_url_encode(success);
+ browser_window_open_location_post(bw, form->action, data, 0);
+ free(data);
+ break;
+
+ case method_POST_MULTIPART:
+ browser_window_open_location_post(bw, form->action, 0, success);
+ break;
+
+ default:
+ assert(0);
+ }
form_free_successful(success);
}
diff --git a/desktop/browser.h b/desktop/browser.h
index 38dc3628b..2afbd83bb 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -99,7 +99,9 @@ struct box_selection
struct browser_window* create_browser_window(int flags, int width, int height);
void browser_window_destroy(struct browser_window* bw);
void browser_window_open_location(struct browser_window* bw, const char* url);
-void browser_window_open_location_historical(struct browser_window* bw, const char* url);
+void browser_window_open_location_historical(struct browser_window* bw,
+ const char* url, char *post_urlenc,
+ struct form_successful_control *post_multipart);
int browser_window_action(struct browser_window* bw, struct browser_action* act);
void browser_window_set_status(struct browser_window* bw, const char* text);
diff --git a/render/box.c b/render/box.c
index 3ad80ffad..6e9518931 100644
--- a/render/box.c
+++ b/render/box.c
@@ -14,7 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include "libxml/HTMLparser.h"
-#include "netsurf/content/fetchcache.h"
+#include "netsurf/content/content.h"
#include "netsurf/css/css.h"
#include "netsurf/render/box.h"
#include "netsurf/render/font.h"
@@ -737,22 +737,31 @@ struct result box_image(xmlNode *n, struct status *status,
struct result box_form(xmlNode *n, struct status *status,
struct css_style *style)
{
- char* s;
+ char *s, *s2;
struct box *box;
struct form *form;
box = box_create(style, status->href, status->title);
- status->current_form = form = xcalloc(1, sizeof(*form));
-
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "action"))) {
- form->action = s;
+ s = (char *) xmlGetProp(n, (const xmlChar *) "action");
+ if (!s) {
+ /* the action attribute is required */
+ return (struct result) {box, 1};
}
+ status->current_form = form = xcalloc(1, sizeof(*form));
+ form->action = s;
+
form->method = method_GET;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "method"))) {
- if (stricmp(s, "post") == 0)
- form->method = method_POST;
+ if (strcasecmp(s, "post") == 0) {
+ form->method = method_POST_URLENC;
+ if ((s2 = (char *) xmlGetProp(n, (const xmlChar *) "enctype"))) {
+ if (strcasecmp(s2, "multipart/form-data") == 0)
+ form->method = method_POST_MULTIPART;
+ xmlFree(s2);
+ }
+ }
xmlFree(s);
}
@@ -913,13 +922,18 @@ void add_option(xmlNode* n, struct form_control* current_select, char *text)
current_select->data.select.last_item->next = option;
current_select->data.select.last_item = option;
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) {
+ option->value = s;
+ } else {
+ option->value = xstrdup(text);
+ }
+
for (c = text; *c; c++)
if (*c == ' ')
*c = 160;
option->selected = option->initial_selected = false;
option->text = text;
- option->value = 0;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "selected"))) {
xmlFree(s);
@@ -930,10 +944,6 @@ void add_option(xmlNode* n, struct form_control* current_select, char *text)
current_select->data.select.current = option;
}
}
-
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) {
- option->value = s;
- }
}
struct result box_input(xmlNode *n, struct status *status,
diff --git a/render/form.c b/render/form.c
index f4ed0a9f8..eade477ba 100644
--- a/render/form.c
+++ b/render/form.c
@@ -74,7 +74,7 @@ struct form_successful_control *form_successful_controls(struct form *form,
if (control->type == GADGET_SELECT) {
for (option = control->data.select.items; option;
option = option->next) {
- if (option->selected && option->value) {
+ if (option->selected) {
success_new = xcalloc(1, sizeof(*success_new));
success_new->name = xstrdup(control->name);
success_new->value = xstrdup(option->value);
diff --git a/render/form.h b/render/form.h
index b81abf01a..10e357ec7 100644
--- a/render/form.h
+++ b/render/form.h
@@ -14,15 +14,19 @@
#define _NETSURF_RENDER_FORM_H_
#include <stdbool.h>
-#include "netsurf/render/box.h"
+struct box;
struct form_control;
struct form_option;
/** HTML form. */
struct form {
- char *action; /* url */
- enum {method_GET, method_POST} method;
+ char *action; /**< Url to submit to. */
+ enum {
+ method_GET, /**< GET, always url encoded. */
+ method_POST_URLENC, /**< POST, url encoded. */
+ method_POST_MULTIPART /**< POST, multipart/form-data. */
+ } method; /**< Method and enctype. */
struct form_control *controls; /**< Linked list of controls. */
struct form_control *last_control; /**< Last control in list. */
};
diff --git a/render/html.c b/render/html.c
index 0d868f996..e023de9e8 100644
--- a/render/html.c
+++ b/render/html.c
@@ -185,7 +185,7 @@ void html_convert_css_callback(content_msg msg, struct content *css,
c->active--;
c->data.html.stylesheet_content[i] = fetchcache(
error, c->url, html_convert_css_callback,
- c, i, css->width, css->height, true);
+ c, i, css->width, css->height, true, 0, 0);
if (c->data.html.stylesheet_content[i] != 0 &&
c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE)
c->active++;
@@ -238,7 +238,7 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
#endif
c->url,
html_convert_css_callback,
- c, 0, c->width, c->height, true);
+ c, 0, c->width, c->height, true, 0, 0);
assert(c->data.html.stylesheet_content[0] != 0);
if (c->data.html.stylesheet_content[0]->status != CONTENT_STATUS_DONE)
c->active++;
@@ -289,7 +289,7 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
(i + 1) * sizeof(*c->data.html.stylesheet_content));
c->data.html.stylesheet_content[i] = fetchcache(url, c->url,
html_convert_css_callback, c, i,
- c->width, c->height, true);
+ c->width, c->height, true, 0, 0);
if (c->data.html.stylesheet_content[i] &&
c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE)
c->active++;
@@ -376,8 +376,8 @@ void html_fetch_object(struct content *c, char *url, struct box *box)
/* start fetch */
c->data.html.object[i].content = fetchcache(url, c->url,
html_object_callback,
- c, i,
- c->width, c->height, true); /* we don't know the object's
+ c, i, c->width, c->height,
+ true, 0, 0); /* we don't know the object's
dimensions yet; use
parent's as an estimate */
if (c->data.html.object[i].content) {
@@ -467,7 +467,7 @@ void html_object_callback(content_msg msg, struct content *object,
c->data.html.object[i].url = xstrdup(error);
c->data.html.object[i].content = fetchcache(
error, c->url, html_object_callback,
- c, i, 0, 0, true);
+ c, i, 0, 0, true, 0, 0);
if (c->data.html.object[i].content) {
c->active++;
if (c->data.html.object[i].content->status == CONTENT_STATUS_DONE)
@@ -556,7 +556,7 @@ void html_revive(struct content *c, unsigned int width, unsigned int height)
c->data.html.object[i].content = fetchcache(
c->data.html.object[i].url, c->url,
html_object_callback,
- c, i, 0, 0, true);
+ c, i, 0, 0, true, 0, 0);
if (c->data.html.object[i].content &&
c->data.html.object[i].content->status != CONTENT_STATUS_DONE)
c->active++;
diff --git a/riscos/401login.c b/riscos/401login.c
index 0ab0ffbea..edd081cc0 100644
--- a/riscos/401login.c
+++ b/riscos/401login.c
@@ -136,5 +136,5 @@ void do_thing() {
break;
}
if (gw != NULL)
- browser_window_open_location_historical(gw->data.browser.bw, url);
+ browser_window_open_location_historical(gw->data.browser.bw, url, 0, 0);
}
diff --git a/riscos/gui.c b/riscos/gui.c
index 328d40691..3979fd691 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -732,7 +732,8 @@ void ro_gui_toolbar_click(gui_window* g, wimp_pointer* pointer)
}
else if (pointer->i == ro_theme_icon(current_theme, THEME_TOOLBAR, "TOOLBAR_RELOAD"))
{
- browser_window_open_location_historical(g->data.browser.bw, g->data.browser.bw->url);
+ browser_window_open_location_historical(g->data.browser.bw,
+ g->data.browser.bw->url, 0, 0);
}
}
diff --git a/riscos/mouseactions.c b/riscos/mouseactions.c
index 265465b5b..6c0bd6289 100644
--- a/riscos/mouseactions.c
+++ b/riscos/mouseactions.c
@@ -56,7 +56,7 @@ void ro_gui_mouse_action(gui_window *g) {
case mouseaction_RELOAD:
browser_window_open_location_historical(g->data.browser.bw,
- g->data.browser.bw->url);
+ g->data.browser.bw->url, 0, 0);
break;
}
}