From b350b10b35760be54d216ef06f8608be05728033 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Sep 2008 07:21:47 +0100 Subject: [uri] Add uri_encode() and uri_decode() functions for URI character encoding --- src/core/uri.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/include/gpxe/uri.h | 2 ++ 2 files changed, 80 insertions(+) diff --git a/src/core/uri.c b/src/core/uri.c index 3b3cf85b..cf2b071d 100644 --- a/src/core/uri.c +++ b/src/core/uri.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -381,3 +382,80 @@ struct uri * resolve_uri ( struct uri *base_uri, free ( tmp_path ); return new_uri; } + +/** + * Test for unreserved URI characters + * + * @v c Character to test + * @ret is_unreserved Character is an unreserved character + */ +static int is_unreserved_uri_char ( int c ) { + /* According to RFC3986, the unreserved character set is + * + * A-Z a-z 0-9 - _ . ~ + */ + return ( isupper ( c ) || islower ( c ) || isdigit ( c ) || + ( c == '-' ) || ( c == '_' ) || + ( c == '.' ) || ( c == '~' ) ); +} + +/** + * URI-encode string + * + * @v raw_string String to be URI-encoded + * @v buf Buffer to contain encoded string + * @v len Length of buffer + * @ret len Length of encoded string (excluding NUL) + */ +size_t uri_encode ( const char *raw_string, char *buf, size_t len ) { + ssize_t remaining = len; + size_t used; + unsigned char c; + + if ( len ) + buf[0] = '\0'; + + while ( ( c = *(raw_string++) ) ) { + if ( is_unreserved_uri_char ( c ) ) { + used = ssnprintf ( buf, remaining, "%c", c ); + } else { + used = ssnprintf ( buf, remaining, "%%%02X", c ); + } + buf += used; + remaining -= used; + } + + return ( len - remaining ); +} + +/** + * Decode URI-encoded string + * + * @v encoded_string URI-encoded string + * @v buf Buffer to contain decoded string + * @v len Length of buffer + * @ret len Length of decoded string (excluding NUL) + */ +size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) { + ssize_t remaining = len; + char hexbuf[3]; + char *hexbuf_end; + unsigned char c; + + if ( len ) + buf[0] = '\0'; + + while ( *encoded_string ) { + if ( *encoded_string == '%' ) { + encoded_string++; + snprintf ( hexbuf, sizeof ( hexbuf ), "%s", + encoded_string ); + c = strtoul ( hexbuf, &hexbuf_end, 16 ); + encoded_string += ( hexbuf_end - hexbuf ); + } else { + c = *(encoded_string++); + } + ssnprintf ( buf++, remaining--, "%c", c ); + } + return ( len - remaining ); +} diff --git a/src/include/gpxe/uri.h b/src/include/gpxe/uri.h index 514bc479..37f3aac9 100644 --- a/src/include/gpxe/uri.h +++ b/src/include/gpxe/uri.h @@ -135,5 +135,7 @@ extern char * resolve_path ( const char *base_path, extern struct uri * resolve_uri ( struct uri *base_uri, struct uri *relative_uri ); extern void churi ( struct uri *uri ); +extern size_t uri_encode ( const char *raw_string, char *buf, size_t len ); +extern size_t uri_decode ( const char *encoded_string, char *buf, size_t len ); #endif /* _GPXE_URI_H */ -- cgit v1.2.3-55-g7522