Merge branch 'master' of git://git.netsurf-browser.org/netsurf

This commit is contained in:
Chris Young 2012-10-11 20:13:59 +01:00
commit d0665a1af6
4 changed files with 231 additions and 225 deletions

View File

@ -674,26 +674,41 @@ char *form_textarea_value(struct form_control *textarea)
*
* \param form form to which successful controls relate
* \param control linked list of fetch_multipart_data
* \param query_string iff true add '?' to the start of returned data
* \return URL-encoded form, or 0 on memory exhaustion
*/
char *form_url_encode(struct form *form,
struct fetch_multipart_data *control)
static char *form_url_encode(struct form *form,
struct fetch_multipart_data *control,
bool query_string)
{
char *name, *value;
char *s = malloc(1), *s2;
unsigned int len = 0, len1;
char *s, *s2;
unsigned int len, len1;
url_func_result url_err;
if (!s)
return 0;
s[0] = 0;
if (query_string)
s = malloc(2);
else
s = malloc(1);
if (s == NULL)
return NULL;
if (query_string) {
s[0] = '?';
s[1] = '\0';
len = 1;
} else {
s[0] = '\0';
len = 0;
}
for (; control; control = control->next) {
url_err = url_escape(control->name, 0, true, NULL, &name);
if (url_err == URL_FUNC_NOMEM) {
free(s);
return 0;
return NULL;
}
assert(url_err == URL_FUNC_OK);
@ -702,7 +717,7 @@ char *form_url_encode(struct form *form,
if (url_err == URL_FUNC_NOMEM) {
free(name);
free(s);
return 0;
return NULL;
}
assert(url_err == URL_FUNC_OK);
@ -713,7 +728,7 @@ char *form_url_encode(struct form *form,
free(value);
free(name);
free(s);
return 0;
return NULL;
}
s = s2;
sprintf(s + len, "%s=%s&", name, value);
@ -723,7 +738,7 @@ char *form_url_encode(struct form *form,
}
if (len)
s[len - 1] = 0;
s[len - 1] = '\0';
return s;
}
@ -1460,10 +1475,10 @@ void form_radio_set(html_content *html,
void form_submit(nsurl *page_url, struct browser_window *target,
struct form *form, struct form_control *submit_button)
{
char *data = NULL, *url = NULL;
char *data = NULL;
struct fetch_multipart_data *success;
struct url_components components;
url_func_result res;
nsurl *action;
nsurl *action_query;
assert(form != NULL);
@ -1474,7 +1489,7 @@ void form_submit(nsurl *page_url, struct browser_window *target,
switch (form->method) {
case method_GET:
data = form_url_encode(form, success);
data = form_url_encode(form, success, true);
if (data == NULL) {
fetch_multipart_data_destroy(success);
warn_user("NoMemory", 0);
@ -1482,8 +1497,7 @@ void form_submit(nsurl *page_url, struct browser_window *target,
}
/* Decompose action */
res = url_get_components(form->action, &components);
if (res != URL_FUNC_OK) {
if (nsurl_create(form->action, &action) != NSERROR_OK) {
free(data);
fetch_multipart_data_destroy(success);
warn_user("NoMemory", 0);
@ -1491,24 +1505,24 @@ void form_submit(nsurl *page_url, struct browser_window *target,
}
/* Replace query segment */
components.query = data;
/* Construct submit url */
url = url_reform_components(&components);
if (url == NULL) {
if (nsurl_replace_query(action, data, &action_query) !=
NSERROR_OK) {
nsurl_unref(action);
free(data);
fetch_multipart_data_destroy(success);
warn_user("NoMemory", 0);
return;
}
url_destroy_components(&components);
browser_window_go(target, url, nsurl_access(page_url), true);
/* Construct submit url */
browser_window_go(target, nsurl_access(action_query),
nsurl_access(page_url), true);
nsurl_unref(action);
nsurl_unref(action_query);
break;
case method_POST_URLENC:
data = form_url_encode(form, success);
data = form_url_encode(form, success, false);
if (data == NULL) {
fetch_multipart_data_destroy(success);
warn_user("NoMemory", 0);
@ -1527,5 +1541,4 @@ void form_submit(nsurl *page_url, struct browser_window *target,
fetch_multipart_data_destroy(success);
free(data);
free(url);
}

View File

@ -151,8 +151,6 @@ bool form_add_option(struct form_control *control, char *value, char *text,
bool form_successful_controls(struct form *form,
struct form_control *submit_button,
struct fetch_multipart_data **successful_controls);
char *form_url_encode(struct form *form,
struct fetch_multipart_data *control);
bool form_open_select_menu(void *client_data,
struct form_control *control,

View File

@ -167,6 +167,197 @@ out_true:
return true;
}
/**
* Split a URL into separate components
*
* URLs passed to this function are assumed to be valid and no error checking
* or recovery is attempted.
*
* See RFC 3986 for reference.
*
* \param url a valid absolute or relative URL
* \param result pointer to buffer to hold components
* \return URL_FUNC_OK on success
*/
static url_func_result url_get_components(const char *url,
struct url_components *result)
{
int storage_length;
char *storage_end;
const char *scheme;
const char *authority;
const char *path;
const char *query;
const char *fragment;
struct url_components_internal *internal;
assert(url);
/* clear our return value */
internal = (struct url_components_internal *)result;
memset(result, 0x00, sizeof(struct url_components));
/* get enough storage space for a URL with termination at each node */
storage_length = strlen(url) + 8;
internal->buffer = malloc(storage_length);
if (!internal->buffer)
return URL_FUNC_NOMEM;
storage_end = internal->buffer;
/* look for a valid scheme */
scheme = url;
if (isalpha(*scheme)) {
for (scheme = url + 1;
((*scheme != ':') && (*scheme != '\0'));
scheme++) {
if (!isalnum(*scheme) && (*scheme != '+') &&
(*scheme != '-') && (*scheme != '.'))
break;
}
if (*scheme == ':') {
memcpy(storage_end, url, scheme - url);
storage_end[scheme - url] = '\0';
result->scheme = storage_end;
storage_end += scheme - url + 1;
scheme++;
} else {
scheme = url;
}
}
/* look for an authority */
authority = scheme;
if ((authority[0] == '/') && (authority[1] == '/')) {
authority = strpbrk(scheme + 2, "/?#");
if (!authority)
authority = scheme + strlen(scheme);
memcpy(storage_end, scheme + 2, authority - scheme - 2);
storage_end[authority - scheme - 2] = '\0';
result->authority = storage_end;
storage_end += authority - scheme - 1;
}
/* look for a path */
path = authority;
if ((*path != '?') && (*path != '#') && (*path != '\0')) {
path = strpbrk(path, "?#");
if (!path)
path = authority + strlen(authority);
memcpy(storage_end, authority, path - authority);
storage_end[path - authority] = '\0';
result->path = storage_end;
storage_end += path - authority + 1;
}
/* look for a query */
query = path;
if (*query == '?') {
query = strchr(query, '#');
if (!query)
query = path + strlen(path);
memcpy(storage_end, path + 1, query - path - 1);
storage_end[query - path - 1] = '\0';
result->query = storage_end;
storage_end += query - path;
}
/* look for a fragment */
fragment = query;
if (*fragment == '#') {
fragment = query + strlen(query);
/* make a copy of the result for the caller */
memcpy(storage_end, query + 1, fragment - query - 1);
storage_end[fragment - query - 1] = '\0';
result->fragment = storage_end;
storage_end += fragment - query;
}
assert((result->buffer + storage_length) >= storage_end);
return URL_FUNC_OK;
}
/**
* Reform a URL from separate components
*
* See RFC 3986 for reference.
*
* \param components the components to reform into a URL
* \return a new URL allocated on the heap, or NULL on failure
*/
static char *url_reform_components(const struct url_components *components)
{
int scheme_len = 0, authority_len = 0, path_len = 0, query_len = 0,
fragment_len = 0;
char *result, *url;
/* 5.3 */
if (components->scheme)
scheme_len = strlen(components->scheme) + 1;
if (components->authority)
authority_len = strlen(components->authority) + 2;
if (components->path)
path_len = strlen(components->path);
if (components->query)
query_len = strlen(components->query) + 1;
if (components->fragment)
fragment_len = strlen(components->fragment) + 1;
/* claim memory */
url = result = malloc(scheme_len + authority_len + path_len +
query_len + fragment_len + 1);
if (!url) {
LOG(("malloc failed"));
return NULL;
}
/* rebuild URL */
if (components->scheme) {
sprintf(url, "%s:", components->scheme);
url += scheme_len;
}
if (components->authority) {
sprintf(url, "//%s", components->authority);
url += authority_len;
}
if (components->path) {
sprintf(url, "%s", components->path);
url += path_len;
}
if (components->query) {
sprintf(url, "?%s", components->query);
url += query_len;
}
if (components->fragment)
sprintf(url, "#%s", components->fragment);
return result;
}
/**
* Release some url components from memory
*
* \param result pointer to buffer containing components
*/
static void url_destroy_components(const struct url_components *components)
{
const struct url_components_internal *internal;
assert(components);
internal = (const struct url_components_internal *)components;
if (internal->buffer)
free(internal->buffer);
}
/**
* Resolve a relative URL to absolute form.
@ -685,197 +876,6 @@ url_func_result url_escape(const char *unescaped, size_t toskip,
return URL_FUNC_OK;
}
/**
* Split a URL into separate components
*
* URLs passed to this function are assumed to be valid and no error checking
* or recovery is attempted.
*
* See RFC 3986 for reference.
*
* \param url a valid absolute or relative URL
* \param result pointer to buffer to hold components
* \return URL_FUNC_OK on success
*/
url_func_result url_get_components(const char *url,
struct url_components *result)
{
int storage_length;
char *storage_end;
const char *scheme;
const char *authority;
const char *path;
const char *query;
const char *fragment;
struct url_components_internal *internal;
assert(url);
/* clear our return value */
internal = (struct url_components_internal *)result;
memset(result, 0x00, sizeof(struct url_components));
/* get enough storage space for a URL with termination at each node */
storage_length = strlen(url) + 8;
internal->buffer = malloc(storage_length);
if (!internal->buffer)
return URL_FUNC_NOMEM;
storage_end = internal->buffer;
/* look for a valid scheme */
scheme = url;
if (isalpha(*scheme)) {
for (scheme = url + 1;
((*scheme != ':') && (*scheme != '\0'));
scheme++) {
if (!isalnum(*scheme) && (*scheme != '+') &&
(*scheme != '-') && (*scheme != '.'))
break;
}
if (*scheme == ':') {
memcpy(storage_end, url, scheme - url);
storage_end[scheme - url] = '\0';
result->scheme = storage_end;
storage_end += scheme - url + 1;
scheme++;
} else {
scheme = url;
}
}
/* look for an authority */
authority = scheme;
if ((authority[0] == '/') && (authority[1] == '/')) {
authority = strpbrk(scheme + 2, "/?#");
if (!authority)
authority = scheme + strlen(scheme);
memcpy(storage_end, scheme + 2, authority - scheme - 2);
storage_end[authority - scheme - 2] = '\0';
result->authority = storage_end;
storage_end += authority - scheme - 1;
}
/* look for a path */
path = authority;
if ((*path != '?') && (*path != '#') && (*path != '\0')) {
path = strpbrk(path, "?#");
if (!path)
path = authority + strlen(authority);
memcpy(storage_end, authority, path - authority);
storage_end[path - authority] = '\0';
result->path = storage_end;
storage_end += path - authority + 1;
}
/* look for a query */
query = path;
if (*query == '?') {
query = strchr(query, '#');
if (!query)
query = path + strlen(path);
memcpy(storage_end, path + 1, query - path - 1);
storage_end[query - path - 1] = '\0';
result->query = storage_end;
storage_end += query - path;
}
/* look for a fragment */
fragment = query;
if (*fragment == '#') {
fragment = query + strlen(query);
/* make a copy of the result for the caller */
memcpy(storage_end, query + 1, fragment - query - 1);
storage_end[fragment - query - 1] = '\0';
result->fragment = storage_end;
storage_end += fragment - query;
}
assert((result->buffer + storage_length) >= storage_end);
return URL_FUNC_OK;
}
/**
* Reform a URL from separate components
*
* See RFC 3986 for reference.
*
* \param components the components to reform into a URL
* \return a new URL allocated on the heap, or NULL on failure
*/
char *url_reform_components(const struct url_components *components)
{
int scheme_len = 0, authority_len = 0, path_len = 0, query_len = 0,
fragment_len = 0;
char *result, *url;
/* 5.3 */
if (components->scheme)
scheme_len = strlen(components->scheme) + 1;
if (components->authority)
authority_len = strlen(components->authority) + 2;
if (components->path)
path_len = strlen(components->path);
if (components->query)
query_len = strlen(components->query) + 1;
if (components->fragment)
fragment_len = strlen(components->fragment) + 1;
/* claim memory */
url = result = malloc(scheme_len + authority_len + path_len +
query_len + fragment_len + 1);
if (!url) {
LOG(("malloc failed"));
return NULL;
}
/* rebuild URL */
if (components->scheme) {
sprintf(url, "%s:", components->scheme);
url += scheme_len;
}
if (components->authority) {
sprintf(url, "//%s", components->authority);
url += authority_len;
}
if (components->path) {
sprintf(url, "%s", components->path);
url += path_len;
}
if (components->query) {
sprintf(url, "?%s", components->query);
url += query_len;
}
if (components->fragment)
sprintf(url, "#%s", components->fragment);
return result;
}
/**
* Release some url components from memory
*
* \param result pointer to buffer containing components
*/
void url_destroy_components(const struct url_components *components)
{
const struct url_components_internal *internal;
assert(components);
internal = (const struct url_components_internal *)components;
if (internal->buffer)
free(internal->buffer);
}
#ifdef TEST

View File

@ -58,11 +58,6 @@ url_func_result url_escape(const char *unescaped, size_t toskip,
url_func_result url_unescape(const char *str, char **result);
url_func_result url_path(const char *url, char **result);
url_func_result url_get_components(const char *url,
struct url_components *result);
char *url_reform_components(const struct url_components *components);
void url_destroy_components(const struct url_components *components);
char *path_to_url(const char *path);
char *url_to_path(const char *url);