uri-util.c revision 639bb36b12b9f9bb54c8bb1be50eac623622f8a0
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * Generic URI parsing.
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * [URI-GEN] RFC3986 Appendix A:
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * host = IP-literal / IPv4address / reg-name
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * port = *DIGIT
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * reg-name = *( unreserved / pct-encoded / sub-delims )
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * pct-encoded = "%" HEXDIG HEXDIG
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / "*" / "+" / "," / ";" / "="
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * IP-literal = "[" ( IPv6address / IPvFuture ) "]"
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * IPv6address = 6( h16 ":" ) ls32
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / "::" 5( h16 ":" ) ls32
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / [ h16 ] "::" 4( h16 ":" ) ls32
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen * / [ *4( h16 ":" ) h16 ] "::" ls32
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen * / [ *5( h16 ":" ) h16 ] "::" h16
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / [ *6( h16 ":" ) h16 ] "::"
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * h16 = 1*4HEXDIG
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * ls32 = ( h16 ":" h16 ) / IPv4address
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * dec-octet = DIGIT ; 0-9
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / %x31-39 DIGIT ; 10-99
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / "1" 2DIGIT ; 100-199
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / "2" %x30-34 DIGIT ; 200-249
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * / "25" %x30-35 ; 250-255
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen/* Character lookup table
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" [bit0]
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen * / "*" / "+" / "," / ";" / "=" [bit1]
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" [bit2]
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * pchar = unreserved / sub-delims / ":" / "@" [bit0|bit1|bit3]
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * 'uchar' = unreserved / sub-delims / ":" [bit0|bit1|bit4]
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen * 'fchar' = pchar / "/" / "?" [bit0|bit1|bit3|bit5]
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenstatic unsigned const char _uri_char_lookup[256] = {
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen 0, 2, 0, 4, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 1, 36, // 20
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 2, 0, 2, 0, 36, // 30
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 4, 0, 1, // 50
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, // 70
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenstatic inline int _decode_hex_digit(const unsigned char digit)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen case '0': case '1': case '2': case '3': case '4':
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen case '5': case '6': case '7': case '8': case '9':
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainenuri_parse_pct_encoded(struct uri_parser *parser, const unsigned char **p,
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen const unsigned char *pend, unsigned char *ch_r)
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen if (**p == 0 || *(*p+1) == 0 || (pend != NULL && *p+1 >= pend)) {
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen parser->error = "Unexpected URI boundary after '%'";
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen "Expecting hex digit after '%%', but found '%c'", **p);
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen "Expecting hex digit after '%%%c', but found '%c'", *((*p)-1), **p);
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen "Percent encoding is not allowed to encode NUL character";
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenuri_parse_unreserved_char(struct uri_parser *parser, unsigned char *ch_r)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if (uri_parse_pct_encoded(parser, &parser->cur,
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenint uri_parse_unreserved(struct uri_parser *parser, string_t *part)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen unsigned char ch = 0;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if ((ret = uri_parse_unreserved_char(parser, &ch)) < 0)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenbool uri_data_decode(struct uri_parser *parser, const char *data,
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen const unsigned char *p = (const unsigned char *)data;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen const unsigned char *pend = (const unsigned char *)until;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen /* NULL means unlimited; solely rely on '\0' */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen unsigned char ch;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if (*p == '%') {
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen if (uri_parse_pct_encoded(parser, &p, NULL, &ch) <= 0)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenint uri_cut_scheme(const char **uri_p, const char **scheme_r)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen 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;
const char *segment;
unsigned int count;
int ret;
relative = 0;
if (ret > 0) {
if (count > 0) {
} else if ( relative > 0 ) {
relative++;