http-url.c revision d82ad7143c057c565e1fd5f3580645556ed0bcc9
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "strfuncs.h"
#include "net.h"
#include "uri-util.h"
#include "http-url.h"
#include "http-request.h"
/*
* HTTP URL parser
*/
struct http_url_parser {
struct uri_parser parser;
enum http_url_parse_flags flags;
unsigned int relative:1;
unsigned int request_target:1;
};
{
struct uri_authority auth;
int ret;
return FALSE;
if (ret > 0) {
const char *p;
Section 2.8.1:
{...} Senders MUST NOT include a userinfo subcomponent (and its "@"
delimiter) when transmitting an "http" URI in a message. Recipients
of HTTP messages that contain a URI reference SHOULD parse for the
existence of userinfo and treat its presence as an error, likely
indicating that the deprecated subcomponent is being used to
obscure the authority for the sake of phishing attacks.
*/
return FALSE;
}
if (p == NULL) {
return FALSE;
} else {
return FALSE;
return FALSE;
}
}
}
}
return TRUE;
}
{
return FALSE;
return FALSE;
return TRUE;
}
{
const char *const *path;
int path_relative;
const char *part;
int ret;
/*
Appendix C:
http-URI = "http://" authority path-abempty [ "?" query ]
[ "#" fragment ]
https-URI = "https://" authority path-abempty [ "?" query ]
[ "#" fragment ]
partial-URI = relative-part [ "?" query ]
request-target = origin-form / absolute-form / authority-form /
asterisk-form
origin-form = absolute-path [ "?" query ]
absolute-form = absolute-URI
authority-form = authority
asterisk-form = "*"
; Not parsed here
absolute-path = 1*( "/" segment )
Appendix A: (implemented in uri-util.h)
absolute-URI = scheme ":" hier-part [ "?" query ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
relative-part = "//" authority path-abempty
/ path-absolute
/ path-noscheme
/ path-empty
authority = [ userinfo "@" ] host [ ":" port ]
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-noscheme = segment-nz-nc *( "/" segment )
path-rootless = segment-nz *( "/" segment )
path-empty = 0<pchar>
segment = *pchar
segment-nz = 1*pchar
segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
; non-zero-length segment without any colon ":"
query = *( pchar / "/" / "?" )
fragment = *( pchar / "/" / "?" )
*/
/* "http:" / "https:" */
const char *scheme;
return FALSE;
else if (ret > 0) {
if (url_parser->request_target) {
/* valid as non-HTTP scheme, but also try to parse as authority */
if (!http_url_parse_authority_form(url_parser)) {
}
return TRUE;
}
return FALSE;
}
have_scheme = TRUE;
}
} else {
have_scheme = TRUE;
}
/* "//" authority ; or
* ["//"] authority ; when parsing a request target
*/
} else {
/* start of absolute-path */
}
if (!http_url_parse_authority_form(url_parser)) {
/* not non-HTTP scheme and invalid as authority-form */
return FALSE;
}
return TRUE;
}
if (have_scheme && !have_authority) {
return FALSE;
}
if (have_authority) {
return FALSE;
}
/* path-abempty / path-absolute / path-noscheme / path-empty */
return FALSE;
/* Relative URLs are only valid when we have a base URL */
if (relative) {
return FALSE;
}
}
/* Resolve path */
if (ret > 0) {
const char *p = pend - 1;
/* discard trailing segments of base path based on how many effective
leading '..' segments were found in the relative path.
*/
while (path_relative > 0 && p > pbegin) {
while (p > pbegin && *p != '/') p--;
if (p >= pbegin) {
pend = p;
}
if (p > pbegin) p--;
}
}
/* append relative path */
return FALSE;
}
path++;
}
}
/* [ "?" query ] */
return FALSE;
if (ret > 0) {
return FALSE;
}
/* [ "#" fragment ] */
return FALSE;
if (ret > 0) {
return FALSE;
}
return FALSE;
}
return FALSE;
}
if (have_scheme)
return TRUE;
}
/* Public API */
{
struct http_url_parser url_parser;
/* base != NULL indicates whether relative URLs are allowed. However, certain
if (!http_url_do_parse(&url_parser)) {
return -1;
}
return 0;
}
int http_url_request_target_parse(const char *request_target,
const char **error_r)
{
struct http_url_parser url_parser;
struct uri_parser *parser;
struct uri_authority host;
return -1;
}
*error_r = "Invalid Host header: Contains invalid character";
return -1;
}
return 0;
}
url_parser.flags = 0;
if (!http_url_do_parse(&url_parser)) {
return -1;
}
return 0;
}
/*
* HTTP URL manipulation
*/
{
if (src->have_host_ip) {
}
}
}
{
}
{
return new_url;
}
/*
* HTTP URL construction
*/
static void
{
/* scheme */
else
}
static void
{
/* host:port */
/* assume IPv6 literal if starts with '['; avoid encoding */
else
} else if (url->have_host_ip) {
} else
i_unreached();
}
static void
{
/* Older syntax of RFC 2616 requires this slash at all times for an
absolute URL
*/
} else {
}
/* query (pre-encoded) */
}
}
{
/* fragment */
}
}
{
}
{
}
{
}
{
}