uri-util.c revision 05262e3132642bbdc4a8087c17b0903cf2ff22d2
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen * Generic URI parsing.
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen * [URI-GEN] RFC3986 Appendix A:
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen * host = IP-literal / IPv4address / reg-name
8b2cf1c1bd8ddcea0525b62fd35ba76e136828a1Timo Sirainen * port = *DIGIT
8b2cf1c1bd8ddcea0525b62fd35ba76e136828a1Timo Sirainen * reg-name = *( unreserved / pct-encoded / sub-delims )
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen * pct-encoded = "%" HEXDIG HEXDIG
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen * / "*" / "+" / "," / ";" / "="
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen * IP-literal = "[" ( IPv6address / IPvFuture ) "]"
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen * IPv6address = 6( h16 ":" ) ls32
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen * / "::" 5( h16 ":" ) ls32
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen * / [ h16 ] "::" 4( h16 ":" ) ls32
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
9b7eeffb5752b500ac62ba1fd01c4a8c4ada14e9Timo Sirainen * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
9b7eeffb5752b500ac62ba1fd01c4a8c4ada14e9Timo Sirainen * / [ *4( h16 ":" ) h16 ] "::" ls32
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen * / [ *5( h16 ":" ) h16 ] "::" h16
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen * / [ *6( h16 ":" ) h16 ] "::"
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen * h16 = 1*4HEXDIG
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen * ls32 = ( h16 ":" h16 ) / IPv4address
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen * dec-octet = DIGIT ; 0-9
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen * / %x31-39 DIGIT ; 10-99
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen * / "1" 2DIGIT ; 100-199
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen * / "2" %x30-34 DIGIT ; 200-249
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen * / "25" %x30-35 ; 250-255
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen/* Character lookup table
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" [bit0]
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen * / "*" / "+" / "," / ";" / "=" [bit1]
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" [bit2]
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen * pchar = unreserved / sub-delims / ":" / "@" [bit0|bit1|bit3]
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen * 'pfchar' = unreserved / sub-delims / ":" / "@" / "/"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen * [bit0|bit1|bit3|bit5]
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen * 'uchar' = unreserved / sub-delims / ":" [bit0|bit1|bit4]
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen * 'qchar' = pchar / "/" / "?" [bit0|bit1|bit3|bit5|bit6]
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#define CHAR_MASK_PFCHAR ((1<<0)|(1<<1)|(1<<3)|(1<<5))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define CHAR_MASK_QCHAR ((1<<0)|(1<<1)|(1<<3)|(1<<5)|(1<<6))
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic unsigned const char _uri_char_lookup[256] = {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 0, 2, 0, 4, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 1, 36, // 20
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 2, 0, 2, 0, 68, // 30
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 4, 0, 1, // 50
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, // 70
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainenstatic inline int _decode_hex_digit(const unsigned char digit)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen case '0': case '1': case '2': case '3': case '4':
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen case '5': case '6': case '7': case '8': case '9':
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenuri_parse_pct_encoded(struct uri_parser *parser, const unsigned char **p,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const unsigned char *pend, unsigned char *ch_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (**p == 0 || *(*p+1) == 0 || (pend != NULL && *p+1 >= pend)) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen parser->error = "Unexpected URI boundary after '%'";
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "Expecting hex digit after '%%', but found '%c'", **p);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Expecting hex digit after '%%%c', but found '%c'", *((*p)-1), **p);
ceb43cc04edb94445fab8f914bc4da6d740403d1Timo Sirainen "Percent encoding is not allowed to encode NUL character";
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenuri_parse_unreserved_char(struct uri_parser *parser, unsigned char *ch_r)
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (uri_parse_pct_encoded(parser, &parser->cur,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if ((_uri_char_lookup[*parser->cur] & CHAR_MASK_UNRESERVED) != 0) {
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainenint uri_parse_unreserved(struct uri_parser *parser, string_t *part)
d7e72877b7a5085c3addf9729d0bfbe1b5357853Timo Sirainen unsigned char ch = 0;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if ((ret = uri_parse_unreserved_char(parser, &ch)) < 0)
const unsigned char *p = (const unsigned char *)data;
return TRUE;
unsigned char ch;
return FALSE;
return TRUE;
const char *p = *uri_p;
if (!i_isalpha(*p))
len++;
int count = 0;
count++;
if (count > 0) {
int ret;
return ret;
int len = 0;
int ret;
if (ret > 0) {
len++;
len++;
#ifdef HAVE_IPV6
const char *address;
int ret;
const unsigned char *preserve;
int ret;
#ifdef HAVE_IPV6
return ret;
return ret;
int count = 0;
count++;
if (count > 0) {
int ret;
if (ret == 0) {
return ret;
return ret;
unsigned int count;
int ret;
relative = 0;
if (ret > 0) {
if (count > 0) {
} else if ( relative > 0 ) {
relative++;
const unsigned char *p = (const unsigned char *)data;
const char *data)
const char *data)
const char *data)
const char *data)
const char *data)