[project @ 2003-10-25 14:13:49 by bursa]

URL encoded POST support.

svn path=/import/netsurf/; revision=375
This commit is contained in:
James Bursa 2003-10-25 14:13:49 +00:00
parent f1375fe19d
commit 28f974f00f
15 changed files with 132 additions and 65 deletions

View File

@ -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 &&

View File

@ -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);

View File

@ -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"));

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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;
@ -265,12 +271,19 @@ 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. */
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;
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);
case method_POST_URLENC:
data = form_url_encode(success);
browser_window_open_location_post(bw, form->action, data, 0);
free(data);
break;
} else {
/*POST request*/
assert(form->method == method_POST);
case method_POST_MULTIPART:
browser_window_open_location_post(bw, form->action, 0, success);
break;
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.*/
}
default:
assert(0);
}
form_free_successful(success);
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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. */
};

View File

@ -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++;

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}