mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-28 06:49:41 +03:00
Merge branch 'master' of git://git.netsurf-browser.org/netsurf
This commit is contained in:
commit
d0665a1af6
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
382
utils/url.c
382
utils/url.c
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user