Refactor http utilities

svn path=/trunk/netsurf/; revision=12595
This commit is contained in:
John Mark Bell 2011-07-08 08:38:17 +00:00
parent c54b6aabaa
commit b34502af82
27 changed files with 1380 additions and 580 deletions

View File

@ -16,9 +16,12 @@ S_RENDER := box.c box_construct.c box_normalise.c \
hubbub_binding.c imagemap.c layout.c list.c table.c textinput.c \
textplain.c
S_UTILS := base64.c filename.c hashtable.c http.c locale.c messages.c \
S_UTILS := base64.c filename.c hashtable.c locale.c messages.c \
talloc.c url.c utf8.c utils.c useragent.c filepath.c log.c
S_HTTP := challenge.c generics.c primitives.c parameter.c \
content-disposition.c content-type.c www-authenticate.c
S_DESKTOP := cookies.c history_global_core.c hotlist.c knockout.c \
mouse.c options.c plot_style.c print.c search.c searchweb.c \
scrollbar.c sslcert.c textarea.c thumbnail.c tree.c \
@ -30,6 +33,7 @@ S_COMMON := $(addprefix content/,$(S_CONTENT)) \
$(addprefix css/,$(S_CSS)) \
$(addprefix render/,$(S_RENDER)) \
$(addprefix utils/,$(S_UTILS)) \
$(addprefix utils/http/,$(S_HTTP)) \
$(addprefix desktop/,$(S_DESKTOP))
# S_IMAGE are sources related to image management

View File

@ -128,24 +128,16 @@ static const content_handler *content_lookup(lwc_string *mime_type)
* \param mime_type MIME type to consider
* \return Generic content type
*/
content_type content_factory_type_from_mime_type(const char *mime_type)
content_type content_factory_type_from_mime_type(lwc_string *mime_type)
{
const content_handler *handler;
lwc_string *imime_type;
lwc_error lerror;
content_type type = CONTENT_NONE;
lerror = lwc_intern_string(mime_type, strlen(mime_type), &imime_type);
if (lerror != lwc_error_ok)
return CONTENT_NONE;
handler = content_lookup(imime_type);
handler = content_lookup(mime_type);
if (handler != NULL) {
type = handler->type(imime_type);
type = handler->type(mime_type);
}
lwc_string_unref(imime_type);
return type;
}
@ -163,10 +155,7 @@ struct content *content_factory_create_content(llcache_handle *llcache,
struct content *c;
const char *content_type_header;
const content_handler *handler;
char *mime_type;
http_parameter *params;
lwc_string *imime_type;
lwc_error lerr;
http_content_type *ct;
nserror error;
content_type_header =
@ -174,39 +163,26 @@ struct content *content_factory_create_content(llcache_handle *llcache,
if (content_type_header == NULL)
content_type_header = "text/plain";
error = http_parse_content_type(content_type_header, &mime_type,
&params);
error = http_parse_content_type(content_type_header, &ct);
if (error != NSERROR_OK)
return NULL;
lerr = lwc_intern_string(mime_type, strlen(mime_type), &imime_type);
if (lerr != lwc_error_ok) {
http_parameter_list_destroy(params);
free(mime_type);
return NULL;
}
free(mime_type);
handler = content_lookup(imime_type);
handler = content_lookup(ct->media_type);
if (handler == NULL) {
lwc_string_unref(imime_type);
http_parameter_list_destroy(params);
http_content_type_destroy(ct);
return NULL;
}
assert(handler->create != NULL);
error = handler->create(handler, imime_type, params, llcache,
fallback_charset, quirks, &c);
error = handler->create(handler, ct->media_type, ct->parameters,
llcache, fallback_charset, quirks, &c);
if (error != NSERROR_OK) {
lwc_string_unref(imime_type);
http_parameter_list_destroy(params);
http_content_type_destroy(ct);
return NULL;
}
lwc_string_unref(imime_type);
http_parameter_list_destroy(params);
http_content_type_destroy(ct);
return c;
}

View File

@ -39,6 +39,6 @@ nserror content_factory_register_handler(lwc_string *mime_type,
struct content *content_factory_create_content(struct llcache_handle *llcache,
const char *fallback_charset, bool quirks);
content_type content_factory_type_from_mime_type(const char *mime_type);
content_type content_factory_type_from_mime_type(lwc_string *mime_type);
#endif

View File

@ -541,8 +541,7 @@ bool hlcache_type_is_acceptable(llcache_handle *llcache,
content_type accepted_types, content_type *computed_type)
{
const char *content_type_header;
char *mime_type;
http_parameter *params;
http_content_type *ct;
content_type type;
nserror error;
@ -551,15 +550,13 @@ bool hlcache_type_is_acceptable(llcache_handle *llcache,
if (content_type_header == NULL)
content_type_header = "text/plain";
error = http_parse_content_type(content_type_header, &mime_type,
&params);
error = http_parse_content_type(content_type_header, &ct);
if (error != NSERROR_OK)
return false;
type = content_factory_type_from_mime_type(mime_type);
type = content_factory_type_from_mime_type(ct->media_type);
free(mime_type);
http_parameter_list_destroy(params);
http_content_type_destroy(ct);
*computed_type = type;

View File

@ -90,6 +90,7 @@ static const content_handler css_content_handler = {
};
static lwc_string *css_mime_type;
static lwc_string *css_charset;
static css_stylesheet *blank_import;
/**
@ -105,10 +106,18 @@ nserror css_init(void)
if (lerror != lwc_error_ok)
return NSERROR_NOMEM;
lerror = lwc_intern_string("charset", SLEN("charset"), &css_charset);
if (lerror != lwc_error_ok) {
lwc_string_unref(css_mime_type);
return NSERROR_NOMEM;
}
error = content_factory_register_handler(css_mime_type,
&css_content_handler);
if (error != NSERROR_OK)
if (error != NSERROR_OK) {
lwc_string_unref(css_charset);
lwc_string_unref(css_mime_type);
}
return error;
}
@ -118,6 +127,8 @@ nserror css_init(void)
*/
void css_fini(void)
{
lwc_string_unref(css_charset);
lwc_string_unref(css_mime_type);
if (blank_import != NULL)
@ -138,6 +149,7 @@ nserror nscss_create(const content_handler *handler,
{
nscss_content *result;
const char *charset = NULL;
lwc_string *charset_value = NULL;
union content_msg_data msg_data;
nserror error;
@ -153,11 +165,14 @@ nserror nscss_create(const content_handler *handler,
}
/* Find charset specified on HTTP layer, if any */
error = http_parameter_list_find_item(params, "charset", &charset);
if (error != NSERROR_OK || *charset == '\0') {
error = http_parameter_list_find_item(params, css_charset,
&charset_value);
if (error != NSERROR_OK || lwc_string_length(charset_value) == 0) {
/* No charset specified, use fallback, if any */
/** \todo libcss will take this as gospel, which is wrong */
charset = fallback_charset;
} else {
charset = lwc_string_data(charset_value);
}
error = nscss_create_css_data(&result->data,
@ -167,10 +182,15 @@ nserror nscss_create(const content_handler *handler,
if (error != NSERROR_OK) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&result->base, CONTENT_MSG_ERROR, msg_data);
if (charset_value != NULL)
lwc_string_unref(charset_value);
talloc_free(result);
return error;
}
if (charset_value != NULL)
lwc_string_unref(charset_value);
*c = (struct content *) result;
return NSERROR_OK;

View File

@ -28,6 +28,7 @@
#include "desktop/gui.h"
#include "utils/http.h"
#include "utils/url.h"
#include "utils/utils.h"
/**
* A context for a download
@ -36,7 +37,7 @@ struct download_context {
llcache_handle *llcache; /**< Low-level cache handle */
struct gui_window *parent; /**< Parent window */
char *mime_type; /**< MIME type of download */
lwc_string *mime_type; /**< MIME type of download */
unsigned long total_length; /**< Length of data, in bytes */
char *filename; /**< Suggested filename */
@ -87,8 +88,7 @@ static char *download_default_filename(const char *url)
static nserror download_context_process_headers(download_context *ctx)
{
const char *http_header;
char *mime_type;
http_parameter *params;
http_content_type *content_type;
unsigned long length;
nserror error;
@ -97,13 +97,10 @@ static nserror download_context_process_headers(download_context *ctx)
if (http_header == NULL)
http_header = "text/plain";
error = http_parse_content_type(http_header, &mime_type, &params);
error = http_parse_content_type(http_header, &content_type);
if (error != NSERROR_OK)
return error;
/* Don't care about parameters */
http_parameter_list_destroy(params);
/* Retrieve and parse Content-Length */
http_header = llcache_handle_get_header(ctx->llcache, "Content-Length");
if (http_header == NULL)
@ -115,35 +112,46 @@ static nserror download_context_process_headers(download_context *ctx)
http_header = llcache_handle_get_header(ctx->llcache,
"Content-Disposition");
if (http_header != NULL) {
const char *filename;
char *disposition;
lwc_string *filename;
lwc_string *filename_value;
http_content_disposition *disposition;
if (lwc_intern_string("filename", SLEN("filename"),
&filename) != lwc_error_ok) {
http_content_type_destroy(content_type);
return NSERROR_NOMEM;
}
error = http_parse_content_disposition(http_header,
&disposition, &params);
&disposition);
if (error != NSERROR_OK) {
free(mime_type);
lwc_string_unref(filename);
http_content_type_destroy(content_type);
return error;
}
free(disposition);
error = http_parameter_list_find_item(params,
"filename", &filename);
error = http_parameter_list_find_item(disposition->parameters,
filename, &filename_value);
if (error == NSERROR_OK)
ctx->filename = download_parse_filename(filename);
ctx->filename = download_parse_filename(
lwc_string_data(filename_value));
http_parameter_list_destroy(params);
http_content_disposition_destroy(disposition);
lwc_string_unref(filename_value);
lwc_string_unref(filename);
}
ctx->mime_type = mime_type;
ctx->mime_type = lwc_string_ref(content_type->media_type);
ctx->total_length = length;
if (ctx->filename == NULL) {
ctx->filename = download_default_filename(
llcache_handle_get_url(ctx->llcache));
}
http_content_type_destroy(content_type);
if (ctx->filename == NULL) {
free(ctx->mime_type);
lwc_string_unref(ctx->mime_type);
ctx->mime_type = NULL;
return NSERROR_NOMEM;
}
@ -152,9 +160,7 @@ static nserror download_context_process_headers(download_context *ctx)
ctx->window = gui_download_window_create(ctx, ctx->parent);
if (ctx->window == NULL) {
free(ctx->filename);
ctx->filename = NULL;
free(ctx->mime_type);
ctx->mime_type = NULL;
lwc_string_unref(ctx->mime_type);
return NSERROR_NOMEM;
}
@ -259,7 +265,7 @@ void download_context_destroy(download_context *ctx)
{
llcache_handle_release(ctx->llcache);
free(ctx->mime_type);
lwc_string_unref(ctx->mime_type);
free(ctx->filename);
@ -283,7 +289,7 @@ const char *download_context_get_url(const download_context *ctx)
/* See download.h for documentation */
const char *download_context_get_mime_type(const download_context *ctx)
{
return ctx->mime_type;
return lwc_string_data(ctx->mime_type);
}
/* See download.h for documentation */

View File

@ -1257,17 +1257,44 @@ bool box_object(BOX_SPECIAL_PARAMS)
* (classid || !classid) && data => data is used (consult type)
* !classid && !data => invalid; ignored */
if (params->classid && !params->data && params->codetype &&
content_factory_type_from_mime_type(params->codetype) ==
CONTENT_NONE)
/* can't handle this MIME type */
return true;
if (params->classid != NULL && params->data == NULL &&
params->codetype != NULL) {
lwc_string *icodetype;
lwc_error lerror;
if (params->data && params->type &&
content_factory_type_from_mime_type(params->type) ==
CONTENT_NONE)
lerror = lwc_intern_string(params->codetype,
strlen(params->codetype), &icodetype);
if (lerror != lwc_error_ok)
return false;
if (content_factory_type_from_mime_type(icodetype) ==
CONTENT_NONE) {
/* can't handle this MIME type */
lwc_string_unref(icodetype);
return true;
}
lwc_string_unref(icodetype);
}
if (params->data != NULL && params->type != NULL) {
lwc_string *itype;
lwc_error lerror;
lerror = lwc_intern_string(params->type, strlen(params->type),
&itype);
if (lerror != lwc_error_ok)
return false;
if (content_factory_type_from_mime_type(itype) ==
CONTENT_NONE) {
/* can't handle this MIME type */
lwc_string_unref(itype);
return true;
}
lwc_string_unref(itype);
}
/* add parameters to linked list */
for (c = n->children; c; c = c->next) {

View File

@ -138,6 +138,7 @@ static const char *html_types[] = {
};
static lwc_string *html_mime_types[NOF_ELEMENTS(html_types)];
static lwc_string *html_charset;
nserror html_init(void)
{
@ -145,6 +146,12 @@ nserror html_init(void)
lwc_error lerror;
nserror error;
lerror = lwc_intern_string("charset", SLEN("charset"), &html_charset);
if (lerror != lwc_error_ok) {
error = NSERROR_NOMEM;
goto error;
}
for (i = 0; i < NOF_ELEMENTS(html_mime_types); i++) {
lerror = lwc_intern_string(html_types[i],
strlen(html_types[i]),
@ -176,6 +183,9 @@ void html_fini(void)
if (html_mime_types[i] != NULL)
lwc_string_unref(html_mime_types[i]);
}
if (html_charset != NULL)
lwc_string_unref(html_charset);
}
/**
@ -217,7 +227,7 @@ nserror html_create(const content_handler *handler,
nserror html_create_html_data(html_content *c, const http_parameter *params)
{
const char *charset;
lwc_string *charset;
union content_msg_data msg_data;
binding_error error;
nserror nerror;
@ -245,10 +255,13 @@ nserror html_create_html_data(html_content *c, const http_parameter *params)
c->font_func = &nsfont;
c->scrollbar = NULL;
nerror = http_parameter_list_find_item(params, "charset", &charset);
nerror = http_parameter_list_find_item(params, html_charset, &charset);
if (nerror == NSERROR_OK) {
c->encoding = talloc_strdup(c, charset);
if (!c->encoding) {
c->encoding = talloc_strdup(c, lwc_string_data(charset));
lwc_string_unref(charset);
if (c->encoding == NULL) {
error = BINDING_NOMEM;
goto error;
}

View File

@ -58,7 +58,7 @@ struct textplain_line {
typedef struct textplain_content {
struct content base;
char *encoding;
lwc_string *encoding;
void *inputstream;
char *utf8_data;
size_t utf8_data_size;
@ -93,7 +93,7 @@ static nserror textplain_create(const content_handler *handler,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c);
static nserror textplain_create_internal(textplain_content *c,
const char *charset);
lwc_string *charset);
static bool textplain_process_data(struct content *c,
const char *data, unsigned int size);
static bool textplain_convert(struct content *c);
@ -140,6 +140,8 @@ static const content_handler textplain_content_handler = {
};
static lwc_string *textplain_mime_type;
static lwc_string *textplain_charset;
static lwc_string *textplain_default_charset;
/**
* Initialise the text content handler
@ -154,10 +156,28 @@ nserror textplain_init(void)
if (lerror != lwc_error_ok)
return NSERROR_NOMEM;
lerror = lwc_intern_string("charset", SLEN("charset"),
&textplain_charset);
if (lerror != lwc_error_ok) {
lwc_string_unref(textplain_mime_type);
return NSERROR_NOMEM;
}
lerror = lwc_intern_string("Windows-1252", SLEN("Windows-1252"),
&textplain_default_charset);
if (lerror != lwc_error_ok) {
lwc_string_unref(textplain_charset);
lwc_string_unref(textplain_mime_type);
return NSERROR_NOMEM;
}
error = content_factory_register_handler(textplain_mime_type,
&textplain_content_handler);
if (error != NSERROR_OK)
if (error != NSERROR_OK) {
lwc_string_unref(textplain_default_charset);
lwc_string_unref(textplain_charset);
lwc_string_unref(textplain_mime_type);
}
return error;
}
@ -167,6 +187,8 @@ nserror textplain_init(void)
*/
void textplain_fini(void)
{
lwc_string_unref(textplain_default_charset);
lwc_string_unref(textplain_charset);
lwc_string_unref(textplain_mime_type);
}
@ -181,7 +203,7 @@ nserror textplain_create(const content_handler *handler,
{
textplain_content *text;
nserror error;
const char *encoding;
lwc_string *encoding;
text = talloc_zero(0, textplain_content);
if (text == NULL)
@ -194,17 +216,21 @@ nserror textplain_create(const content_handler *handler,
return error;
}
error = http_parameter_list_find_item(params, "charset", &encoding);
error = http_parameter_list_find_item(params, textplain_charset,
&encoding);
if (error != NSERROR_OK) {
encoding = "Windows-1252";
encoding = lwc_string_ref(textplain_default_charset);
}
error = textplain_create_internal(text, encoding);
if (error != NSERROR_OK) {
lwc_string_unref(encoding);
talloc_free(text);
return error;
}
lwc_string_unref(encoding);
*c = (struct content *) text;
return NSERROR_OK;
@ -226,7 +252,7 @@ parserutils_error textplain_charset_hack(const uint8_t *data, size_t len,
return PARSERUTILS_OK;
}
nserror textplain_create_internal(textplain_content *c, const char *encoding)
nserror textplain_create_internal(textplain_content *c, lwc_string *encoding)
{
char *utf8_data;
parserutils_inputstream *stream;
@ -239,7 +265,7 @@ nserror textplain_create_internal(textplain_content *c, const char *encoding)
if (utf8_data == NULL)
goto no_memory;
error = parserutils_inputstream_create(encoding, 0,
error = parserutils_inputstream_create(lwc_string_data(encoding), 0,
textplain_charset_hack, ns_realloc, NULL, &stream);
if (error == PARSERUTILS_BADENCODING) {
/* Fall back to Windows-1252 */
@ -252,13 +278,7 @@ nserror textplain_create_internal(textplain_content *c, const char *encoding)
goto no_memory;
}
c->encoding = strdup(encoding);
if (c->encoding == NULL) {
talloc_free(utf8_data);
parserutils_inputstream_destroy(stream);
goto no_memory;
}
c->encoding = lwc_string_ref(encoding);
c->inputstream = stream;
c->utf8_data = utf8_data;
c->utf8_data_size = 0;
@ -527,8 +547,7 @@ void textplain_destroy(struct content *c)
{
textplain_content *text = (textplain_content *) c;
if (text->encoding != NULL)
free(text->encoding);
lwc_string_unref(text->encoding);
if (text->inputstream != NULL)
parserutils_inputstream_destroy(text->inputstream);

View File

@ -1,423 +0,0 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* HTTP header parsing functions
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils/http.h"
/**
* Representation of an HTTP parameter
*/
struct http_parameter {
struct http_parameter *next; /**< Next parameter in list, or NULL */
char *name; /**< Parameter name */
char *value; /**< Parameter value */
};
/**
* Determine if a character is valid for an HTTP token
*
* \param c Character to consider
* \return True if character is valid, false otherwise
*/
static bool http_is_token_char(uint8_t c)
{
/* [ 32 - 126 ] except ()<>@,;:\"/[]?={} SP HT */
if (c <= ' ' || 126 < c)
return false;
return (strchr("()<>@,;:\\\"/[]?={}", c) == NULL);
}
/**
* Parse an HTTP token
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap token value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned value is owned by the caller
*/
static nserror http_parse_token(const char **input, char **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
char *token;
end = start;
while (http_is_token_char(*end))
end++;
token = malloc(end - start + 1);
if (token == NULL)
return NSERROR_NOMEM;
memcpy(token, start, end - start);
token[end - start] = '\0';
*value = token;
*input = (const char *) end;
return NSERROR_OK;
}
/**
* Parse an HTTP quoted-string
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap string value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned value is owned by the caller
*/
static nserror http_parse_quoted_string(const char **input, char **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
uint8_t c;
char *string_value;
/* <"> *( qdtext | quoted-pair ) <">
* qdtext = any TEXT except <">
* quoted-pair = "\" CHAR
* TEXT = [ HT, CR, LF, 32-126, 128-255 ]
* CHAR = [ 0 - 127 ]
*
* \todo TEXT may contain non 8859-1 chars encoded per RFC 2047
* \todo Support quoted-pairs
*/
if (*start == '"') {
end = start = start + 1;
c = *end;
while (c == '\t' || c == '\r' || c == '\n' ||
c == ' ' || c == '!' ||
('#' <= c && c <= 126) || c > 127) {
end++;
c = *end;
}
if (*end != '"') {
start--;
end = start;
}
} else {
end = start;
}
string_value = malloc(end - start + 1);
if (string_value == NULL)
return NSERROR_NOMEM;
memcpy(string_value, start, end - start);
string_value[end - start] = '\0';
*value = string_value;
if (end != start)
*input = (const char *) end + 1;
return NSERROR_OK;
}
/**
* Parse an HTTP parameter
*
* \param input Pointer to current input byte. Updated on exit.
* \param parameter Pointer to location to receive on-heap parameter.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned parameter is owned by the caller.
*/
static nserror http_parse_parameter(const char **input,
http_parameter **parameter)
{
const char *pos = *input;
char *name;
char *value;
http_parameter *param;
nserror error;
/* token "=" ( token | quoted-string ) */
error = http_parse_token(&pos, &name);
if (error != NSERROR_OK)
return error;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos != '=') {
value = strdup("");
if (value == NULL) {
free(name);
return NSERROR_NOMEM;
}
} else {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == '"')
error = http_parse_quoted_string(&pos, &value);
else
error = http_parse_token(&pos, &value);
if (error != NSERROR_OK) {
free(name);
return error;
}
}
param = malloc(sizeof(*param));
if (param == NULL) {
free(value);
free(name);
return NSERROR_NOMEM;
}
param->next = NULL;
param->name = name;
param->value = value;
*parameter = param;
*input = pos;
return NSERROR_OK;
}
/**
* Parse an HTTP parameter list
*
* \param input Pointer to current input byte. Updated on exit.
* \param parameters Pointer to location to receive on-heap parameter list.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned parameter list is owned by the caller
*/
static nserror http_parse_parameter_list(const char **input,
http_parameter **parameters)
{
const char *pos = *input;
http_parameter *param;
http_parameter *list = NULL;
nserror error;
/* 1*( ";" parameter ) */
while (*pos == ';') {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_parameter(&pos, &param);
if (error != NSERROR_OK) {
while (list != NULL) {
param = list;
list = param->next;
free(param->name);
free(param->value);
free(param);
}
return error;
}
if (list != NULL)
param->next = list;
list = param;
while (*pos == ' ' || *pos == '\t')
pos++;
}
*parameters = list;
*input = pos;
return NSERROR_OK;
}
/* See http.h for documentation */
nserror http_parse_content_type(const char *header_value, char **media_type,
http_parameter **parameters)
{
const char *pos = header_value;
char *type;
char *subtype = NULL;
http_parameter *params = NULL;
char *mime;
size_t mime_len;
nserror error;
/* type "/" subtype *( ";" parameter ) */
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_token(&pos, &type);
if (error != NSERROR_OK)
return error;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == '/') {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_token(&pos, &subtype);
if (error != NSERROR_OK) {
free(type);
return error;
}
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == ';') {
error = http_parse_parameter_list(&pos, &params);
if (error != NSERROR_OK) {
free(subtype);
free(type);
return error;
}
}
}
/* <type> + <subtype> + '/' */
mime_len = strlen(type) + (subtype != NULL ? strlen(subtype) : 0) + 1;
mime = malloc(mime_len + 1);
if (mime == NULL) {
http_parameter_list_destroy(params);
free(subtype);
free(type);
return NSERROR_OK;
}
sprintf(mime, "%s/%s", type, subtype != NULL ? subtype : "");
free(subtype);
free(type);
*media_type = mime;
*parameters = params;
return NSERROR_OK;
}
/* See http.h for documentation */
nserror http_parse_content_disposition(const char *header_value,
char **disposition_type, http_parameter **parameters)
{
const char *pos = header_value;
char *type;
http_parameter *params = NULL;
nserror error;
/* disposition-type *( ";" parameter ) */
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_token(&pos, &type);
if (error != NSERROR_OK)
return error;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == ';') {
error = http_parse_parameter_list(&pos, &params);
if (error != NSERROR_OK) {
free(type);
return error;
}
}
*disposition_type = type;
*parameters = params;
return NSERROR_OK;
}
/* See http.h for documentation */
nserror http_parameter_list_find_item(const http_parameter *list,
const char *name, const char **value)
{
while (list != NULL && strcasecmp(name, list->name) != 0)
list = list->next;
if (list == NULL)
return NSERROR_NOT_FOUND;
*value = list->value;
return NSERROR_OK;
}
/* See http.h for documentation */
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
const char **name, const char **value)
{
if (cur == NULL)
return NULL;
*name = cur->name;
*value = cur->value;
return cur->next;
}
/* See http.h for documentation */
void http_parameter_list_destroy(http_parameter *list)
{
while (list != NULL) {
http_parameter *victim = list;
list = victim->next;
free(victim->name);
free(victim->value);
free(victim);
}
}

View File

@ -23,63 +23,13 @@
#ifndef NETSURF_UTILS_HTTP_H_
#define NETSURF_UTILS_HTTP_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/errors.h"
typedef struct http_parameter http_parameter;
/**
* Parse an HTTP Content-Type header value
*
* \param header_value Header value to parse
* \param media_type Pointer to location to receive media type
* \param parameters Pointer to location to receive parameter list
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_content_type(const char *header_value, char **media_type,
http_parameter **parameters);
/**
* Parse an HTTP Content-Disposition header value
*
* \param header_value Header value to parse
* \param disposition_type Pointer to location to receive disposition type
* \param parameters Pointer to location to receive parameter list
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_content_disposition(const char *header_value,
char **disposition_type, http_parameter **parameters);
/**
* Find a named item in an HTTP parameter list
*
* \param list List to search
* \param name Name of item to search for
* \param value Pointer to location to receive value
* \return NSERROR_OK on success,
* NSERROR_NOT_FOUND if requested item does not exist
*/
nserror http_parameter_list_find_item(const http_parameter *list,
const char *name, const char **value);
/**
* Iterate over a parameter list
*
* \param cur Pointer to current iteration position, list head to start
* \param name Pointer to location to receive item name
* \param value Pointer to location to receive item value
* \return Pointer to next iteration position, or NULL for end of iteration
*/
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
const char **name, const char **value);
/**
* Destroy a list of HTTP parameters
*
* \param list List to destroy
*/
void http_parameter_list_destroy(http_parameter *list);
#include "utils/http/content-disposition.h"
#include "utils/http/content-type.h"
#include "utils/http/www-authenticate.h"
#endif

140
utils/http/challenge.c Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "utils/http.h"
#include "utils/http/challenge_internal.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
/**
* Representation of an HTTP challenge
*/
struct http_challenge {
http__item base;
lwc_string *scheme; /**< Challenge scheme */
http_parameter *params; /**< Challenge parameters */
};
/**
* Destroy an HTTP challenge
*
* \param self Challenge to destroy
*/
static void http_destroy_challenge(http_challenge *self)
{
lwc_string_unref(self->scheme);
http_parameter_list_destroy(self->params);
free(self);
}
/**
* Parse an HTTP challenge
*
* \param input Pointer to current input byte. Updated on exit.
* \param challenge Pointer to location to receive challenge
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no parameter could be parsed
*
* The returned challenge is owned by the caller.
*/
nserror http__parse_challenge(const char **input, http_challenge **challenge)
{
const char *pos = *input;
http_challenge *result;
lwc_string *scheme;
http_parameter *first = NULL;
http_parameter *params = NULL;
nserror error;
/* challenge = auth-scheme 1*SP 1#auth-param
* auth-scheme = token
* auth-param = parameter
*/
error = http__parse_token(&pos, &scheme);
if (error != NSERROR_OK)
return error;
if (*pos != ' ' && *pos != '\t') {
lwc_string_unref(scheme);
return NSERROR_NOT_FOUND;
}
http__skip_LWS(&pos);
error = http__parse_parameter(&pos, &first);
if (error != NSERROR_OK) {
lwc_string_unref(scheme);
return error;
}
http__skip_LWS(&pos);
if (*pos == ',') {
error = http__item_list_parse(&pos,
http__parse_parameter, first, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(scheme);
return error;
}
} else {
params = first;
}
result = malloc(sizeof(*result));
if (result == NULL) {
http_parameter_list_destroy(params);
lwc_string_unref(scheme);
return NSERROR_NOMEM;
}
HTTP__ITEM_INIT(result, NULL, http_destroy_challenge);
result->scheme = scheme;
result->params = params;
*challenge = result;
*input = pos;
return NSERROR_OK;
}
/* See challenge.h for documentation */
const http_challenge *http_challenge_list_iterate(const http_challenge *cur,
lwc_string **scheme, http_parameter **parameters)
{
if (cur == NULL)
return NULL;
*scheme = lwc_string_ref(cur->scheme);
*parameters = cur->params;
return (http_challenge *) cur->base.next;
}
/* See challenge.h for documentation */
void http_challenge_list_destroy(http_challenge *list)
{
http__item_list_destroy(list);
}

47
utils/http/challenge.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_CHALLENGE_H_
#define NETSURF_UTILS_HTTP_CHALLENGE_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/http/parameter.h"
typedef struct http_challenge http_challenge;
/**
* Iterate over a challenge list
*
* \param cur Pointer to current iteration position, list head to start
* \param scheme Pointer to location to receive challenge scheme
* \param parameters Pointer to location to receive challenge parameters
* \return Pointer to next iteration position, or NULL for end of iteration
*/
const http_challenge *http_challenge_list_iterate(const http_challenge *cur,
lwc_string **scheme, http_parameter **parameters);
/**
* Destroy a list of HTTP challenges
*
* \param list List to destroy
*/
void http_challenge_list_destroy(http_challenge *list);
#endif

View File

@ -0,0 +1,27 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_CHALLENGE_INTERNAL_H_
#define NETSURF_UTILS_HTTP_CHALLENGE_INTERNAL_H_
#include "utils/errors.h"
#include "utils/http/challenge.h"
nserror http__parse_challenge(const char **input, http_challenge **parameter);
#endif

View File

@ -0,0 +1,78 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "utils/http.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
/* See content-disposition.h for documentation */
nserror http_parse_content_disposition(const char *header_value,
http_content_disposition **result)
{
const char *pos = header_value;
lwc_string *mtype;
http_parameter *params = NULL;
http_content_disposition *cd;
nserror error;
/* disposition-type *( ";" parameter ) */
http__skip_LWS(&pos);
error = http__parse_token(&pos, &mtype);
if (error != NSERROR_OK)
return error;
http__skip_LWS(&pos);
if (*pos == ';') {
error = http__item_list_parse(&pos,
http__parse_parameter, NULL, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(mtype);
return error;
}
}
cd = malloc(sizeof(*cd));
if (cd == NULL) {
http_parameter_list_destroy(params);
lwc_string_unref(mtype);
return NSERROR_NOMEM;
}
cd->disposition_type = mtype;
cd->parameters = params;
*result = cd;
return NSERROR_OK;
}
/* See content-disposition.h for documentation */
void http_content_disposition_destroy(http_content_disposition *victim)
{
lwc_string_unref(victim->disposition_type);
http_parameter_list_destroy(victim->parameters);
free(victim);
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_CONTENT_DISPOSITION_H_
#define NETSURF_UTILS_HTTP_CONTENT_DISPOSITION_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/http/parameter.h"
typedef struct http_content_disposition {
lwc_string *disposition_type;
http_parameter *parameters;
} http_content_disposition;
/**
* Parse an HTTP Content-Disposition header value
*
* \param header_value Header value to parse
* \param result Pointer to location to receive result
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_content_disposition(const char *header_value,
http_content_disposition **result);
/**
* Destroy a content disposition object
*
* \param victim Object to destroy
*/
void http_content_disposition_destroy(http_content_disposition *victim);
#endif

128
utils/http/content-type.c Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils/http.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
/* See content-type.h for documentation */
nserror http_parse_content_type(const char *header_value,
http_content_type **result)
{
const char *pos = header_value;
lwc_string *type;
lwc_string *subtype = NULL;
http_parameter *params = NULL;
char *mime;
size_t mime_len;
lwc_string *imime;
http_content_type *ct;
nserror error;
/* type "/" subtype *( ";" parameter ) */
http__skip_LWS(&pos);
error = http__parse_token(&pos, &type);
if (error != NSERROR_OK)
return error;
http__skip_LWS(&pos);
if (*pos != '/') {
lwc_string_unref(type);
return NSERROR_NOT_FOUND;
}
pos++;
http__skip_LWS(&pos);
error = http__parse_token(&pos, &subtype);
if (error != NSERROR_OK) {
lwc_string_unref(type);
return error;
}
http__skip_LWS(&pos);
if (*pos == ';') {
error = http__item_list_parse(&pos,
http__parse_parameter, NULL, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(subtype);
lwc_string_unref(type);
return error;
}
}
/* <type> + <subtype> + '/' */
mime_len = lwc_string_length(type) + lwc_string_length(subtype) + 1;
mime = malloc(mime_len + 1);
if (mime == NULL) {
http_parameter_list_destroy(params);
lwc_string_unref(subtype);
lwc_string_unref(type);
return NSERROR_NOMEM;
}
sprintf(mime, "%.*s/%.*s",
(int) lwc_string_length(type), lwc_string_data(type),
(int) lwc_string_length(subtype), lwc_string_data(subtype));
lwc_string_unref(subtype);
lwc_string_unref(type);
if (lwc_intern_string(mime, mime_len, &imime) != lwc_error_ok) {
http_parameter_list_destroy(params);
free(mime);
return NSERROR_NOMEM;
}
free(mime);
ct = malloc(sizeof(*ct));
if (ct == NULL) {
lwc_string_unref(imime);
http_parameter_list_destroy(params);
return NSERROR_NOMEM;
}
ct->media_type = imime;
ct->parameters = params;
*result = ct;
return NSERROR_OK;
}
/* See content-type.h for documentation */
void http_content_type_destroy(http_content_type *victim)
{
lwc_string_unref(victim->media_type);
http_parameter_list_destroy(victim->parameters);
free(victim);
}

49
utils/http/content-type.h Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_CONTENT_TYPE_H_
#define NETSURF_UTILS_HTTP_CONTENT_TYPE_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/http/parameter.h"
typedef struct http_content_type {
lwc_string *media_type;
http_parameter *parameters;
} http_content_type;
/**
* Parse an HTTP Content-Type header value
*
* \param header_value Header value to parse
* \param result Pointer to location to receive result
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_content_type(const char *header_value,
http_content_type **result);
/**
* Destroy a content type object
*
* \param victim Object to destroy
*/
void http_content_type_destroy(http_content_type *victim);
#endif

99
utils/http/generics.c Normal file
View File

@ -0,0 +1,99 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "utils/http/generics.h"
#include "utils/http/primitives.h"
/**
* Destructor for an item list
*
* \param list List to destroy
*/
void http___item_list_destroy(http__item *list)
{
while (list != NULL) {
http__item *victim = list;
list = victim->next;
victim->free(victim);
}
}
/**
* Parse a list of items
*
* \param input Pointer to current input byte. Updated on exit.
* \param itemparser Pointer to function to parse list items
* \param first Pointer to first item, or NULL.
* \param parameters Pointer to location to receive on-heap parameter list.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no items could be parsed
*
* The returned list is owned by the caller
*
* \note Ownership of the \a first item is passed to this function.
*/
nserror http___item_list_parse(const char **input,
http__itemparser itemparser, http__item *first,
http__item **items)
{
const char *pos = *input;
const char separator = *pos;
http__item *item;
http__item *list = first;
nserror error = NSERROR_OK;
/* 1*( <separator> <item> ) */
while (*pos == separator) {
pos++;
http__skip_LWS(&pos);
error = itemparser(&pos, &item);
if (error == NSERROR_OK) {
if (list != NULL)
item->next = list;
list = item;
http__skip_LWS(&pos);
} else if (error != NSERROR_NOT_FOUND) {
/* Permit <separator> LWS <separator> */
break;
}
}
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
http__item_list_destroy(list);
} else if (list == NULL) {
error = NSERROR_NOT_FOUND;
} else {
error = NSERROR_OK;
*items = list;
*input = pos;
}
return error;
}

54
utils/http/generics.h Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_GENERICS_H_
#define NETSURF_UTILS_HTTP_GENERICS_H_
#include "utils/errors.h"
/**
* Representation of an item
*/
typedef struct http__item {
struct http__item *next; /**< Next item in list, or NULL */
void (*free)(struct http__item *self); /**< Item destructor */
} http__item;
#define HTTP__ITEM_INIT(item, n, f) \
((http__item *) (item))->next = (http__item *) (n); \
((http__item *) (item))->free = (void (*)(http__item *)) (f)
/**
* Type of an item parser
*/
typedef nserror (*http__itemparser)(const char **input, http__item **item);
void http___item_list_destroy(http__item *list);
#define http__item_list_destroy(l) \
http___item_list_destroy((http__item *) (l))
nserror http___item_list_parse(const char **input,
http__itemparser itemparser, http__item *first,
http__item **items);
#define http__item_list_parse(i, p, f, r) \
http___item_list_parse((i), (http__itemparser) (p), \
(http__item *) (f), (http__item **) (r))
#endif

153
utils/http/parameter.c Normal file
View File

@ -0,0 +1,153 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include "utils/http.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
/**
* Representation of an HTTP parameter
*/
struct http_parameter {
http__item base;
lwc_string *name; /**< Parameter name */
lwc_string *value; /**< Parameter value */
};
/**
* Destructor for an HTTP parameter
*
* \param self Parameter to destroy
*/
static void http_destroy_parameter(http_parameter *self)
{
lwc_string_unref(self->name);
lwc_string_unref(self->value);
free(self);
}
/**
* Parse an HTTP parameter
*
* \param input Pointer to current input byte. Updated on exit.
* \param parameter Pointer to location to receive on-heap parameter.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no parameter could be parsed
*
* The returned parameter is owned by the caller.
*/
nserror http__parse_parameter(const char **input, http_parameter **parameter)
{
const char *pos = *input;
lwc_string *name;
lwc_string *value;
http_parameter *param;
nserror error;
/* token "=" ( token | quoted-string ) */
error = http__parse_token(&pos, &name);
if (error != NSERROR_OK)
return error;
http__skip_LWS(&pos);
if (*pos != '=') {
lwc_string_unref(name);
return NSERROR_NOT_FOUND;
}
pos++;
http__skip_LWS(&pos);
if (*pos == '"')
error = http__parse_quoted_string(&pos, &value);
else
error = http__parse_token(&pos, &value);
if (error != NSERROR_OK) {
lwc_string_unref(name);
return error;
}
param = malloc(sizeof(*param));
if (param == NULL) {
lwc_string_unref(value);
lwc_string_unref(name);
return NSERROR_NOMEM;
}
HTTP__ITEM_INIT(param, NULL, http_destroy_parameter);
param->name = name;
param->value = value;
*parameter = param;
*input = pos;
return NSERROR_OK;
}
/* See parameter.h for documentation */
nserror http_parameter_list_find_item(const http_parameter *list,
lwc_string *name, lwc_string **value)
{
bool match;
while (list != NULL) {
if (lwc_string_caseless_isequal(name, list->name,
&match) == lwc_error_ok && match)
break;
list = (http_parameter *) list->base.next;
}
if (list == NULL)
return NSERROR_NOT_FOUND;
*value = lwc_string_ref(list->value);
return NSERROR_OK;
}
/* See parameter.h for documentation */
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
lwc_string **name, lwc_string **value)
{
if (cur == NULL)
return NULL;
*name = lwc_string_ref(cur->name);
*value = lwc_string_ref(cur->value);
return (http_parameter *) cur->base.next;
}
/* See parameter.h for documentation */
void http_parameter_list_destroy(http_parameter *list)
{
http__item_list_destroy(list);
}

59
utils/http/parameter.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_PARAMETER_H_
#define NETSURF_UTILS_HTTP_PARAMETER_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/errors.h"
typedef struct http_parameter http_parameter;
/**
* Find a named item in an HTTP parameter list
*
* \param list List to search
* \param name Name of item to search for
* \param value Pointer to location to receive value
* \return NSERROR_OK on success,
* NSERROR_NOT_FOUND if requested item does not exist
*/
nserror http_parameter_list_find_item(const http_parameter *list,
lwc_string *name, lwc_string **value);
/**
* Iterate over a parameter list
*
* \param cur Pointer to current iteration position, list head to start
* \param name Pointer to location to receive item name
* \param value Pointer to location to receive item value
* \return Pointer to next iteration position, or NULL for end of iteration
*/
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
lwc_string **name, lwc_string **value);
/**
* Destroy a list of HTTP parameters
*
* \param list List to destroy
*/
void http_parameter_list_destroy(http_parameter *list);
#endif

View File

@ -0,0 +1,27 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_PARAMETER_INTERNAL_H_
#define NETSURF_UTILS_HTTP_PARAMETER_INTERNAL_H_
#include "utils/errors.h"
#include "utils/http/parameter.h"
nserror http__parse_parameter(const char **input, http_parameter **parameter);
#endif

146
utils/http/primitives.c Normal file
View File

@ -0,0 +1,146 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "utils/http/primitives.h"
/**
* Skip past linear whitespace in input
*
* \param input Pointer to current input byte. Updated on exit.
*/
void http__skip_LWS(const char **input)
{
const char *pos = *input;
while (*pos == ' ' || *pos == '\t')
pos++;
*input = pos;
}
/**
* Determine if a character is valid for an HTTP token
*
* \param c Character to consider
* \return True if character is valid, false otherwise
*/
static bool http_is_token_char(uint8_t c)
{
/* [ 32 - 126 ] except ()<>@,;:\"/[]?={} SP HT */
if (c <= ' ' || 126 < c)
return false;
return (strchr("()<>@,;:\\\"/[]?={}", c) == NULL);
}
/**
* Parse an HTTP token
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap token value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no token could be parsed
*
* The returned value is owned by the caller
*/
nserror http__parse_token(const char **input, lwc_string **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
lwc_string *token;
end = start;
while (http_is_token_char(*end))
end++;
if (end == start)
return NSERROR_NOT_FOUND;
if (lwc_intern_string((const char *) start,
end - start, &token) != lwc_error_ok)
return NSERROR_NOMEM;
*value = token;
*input = (const char *) end;
return NSERROR_OK;
}
/**
* Parse an HTTP quoted-string
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap string value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion,
* NSERROR_NOT_FOUND if no string could be parsed
*
* The returned value is owned by the caller
*/
nserror http__parse_quoted_string(const char **input, lwc_string **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
uint8_t c;
lwc_string *string_value;
/* <"> *( qdtext | quoted-pair ) <">
* qdtext = any TEXT except <">
* quoted-pair = "\" CHAR
* TEXT = [ HT, CR, LF, 32-126, 128-255 ]
* CHAR = [ 0 - 127 ]
*
* \todo TEXT may contain non 8859-1 chars encoded per RFC 2047
* \todo Support quoted-pairs
*/
if (*start != '"')
return NSERROR_NOT_FOUND;
end = start = start + 1;
c = *end;
while (c == '\t' || c == '\r' || c == '\n' ||
c == ' ' || c == '!' ||
('#' <= c && c <= 126) || c > 127) {
end++;
c = *end;
}
if (*end != '"')
return NSERROR_NOT_FOUND;
if (lwc_intern_string((const char *) start, end - start,
&string_value) != lwc_error_ok)
return NSERROR_NOMEM;
*value = string_value;
*input = (const char *) end + 1;
return NSERROR_OK;
}

32
utils/http/primitives.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_PRIMITIVES_H_
#define NETSURF_UTILS_HTTP_PRIMITIVES_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/errors.h"
void http__skip_LWS(const char **input);
nserror http__parse_token(const char **input, lwc_string **value);
nserror http__parse_quoted_string(const char **input, lwc_string **value);
#endif

View File

@ -0,0 +1,75 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "utils/http/challenge_internal.h"
#include "utils/http/generics.h"
#include "utils/http/parameter_internal.h"
#include "utils/http/primitives.h"
#include "utils/http/www-authenticate.h"
/* See www-authenticate.h for documentation */
nserror http_parse_www_authenticate(const char *header_value,
http_www_authenticate **result)
{
const char *pos = header_value;
http_challenge *first = NULL;
http_challenge *list = NULL;
http_www_authenticate *wa;
nserror error;
/* 1#challenge */
http__skip_LWS(&pos);
error = http__parse_challenge(&pos, &first);
if (error != NSERROR_OK)
return error;
http__skip_LWS(&pos);
if (*pos == ',') {
error = http__item_list_parse(&pos,
http__parse_challenge, first, &list);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND)
return error;
} else {
list = first;
}
wa = malloc(sizeof(*wa));
if (wa == NULL) {
http_challenge_list_destroy(list);
return NSERROR_NOMEM;
}
wa->challenges = list;
*result = wa;
return NSERROR_OK;
}
/* See www-authenticate.h for documentation */
void http_www_authenticate_destroy(http_www_authenticate *victim)
{
http_challenge_list_destroy(victim->challenges);
free(victim);
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETSURF_UTILS_HTTP_WWW_AUTHENTICATE_H_
#define NETSURF_UTILS_HTTP_WWW_AUTHENTICATE_H_
#include <libwapcaplet/libwapcaplet.h>
#include "utils/http/challenge.h"
typedef struct http_www_authenticate {
http_challenge *challenges;
} http_www_authenticate;
/**
* Parse an HTTP WWW-Authenticate header value
*
* \param header_value Header value to parse
* \param result Pointer to location to receive result
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*/
nserror http_parse_www_authenticate(const char *header_value,
http_www_authenticate **result);
/**
* Destroy a www authenticate object
*
* \param victim Object to destroy
*/
void http_www_authenticate_destroy(http_www_authenticate *victim);
#endif