diff options
author | Michael Brown <mcb30@etherboot.org> | 2008-09-24 07:21:47 +0100 |
---|---|---|
committer | Michael Brown <mcb30@etherboot.org> | 2008-09-24 07:21:47 +0100 |
commit | b350b10b35760be54d216ef06f8608be05728033 (patch) | |
tree | ff82f3f82c93509c65950f21b70fdc261ce04a15 | |
parent | 9d44a061885cd81b58cc2d31edd16d60c5d8a3b2 (diff) | |
download | ipxe-b350b10b35760be54d216ef06f8608be05728033.tar.gz |
[uri] Add uri_encode() and uri_decode() functions for URI character encoding
-rw-r--r-- | src/core/uri.c | 78 | ||||
-rw-r--r-- | src/include/gpxe/uri.h | 2 |
2 files changed, 80 insertions, 0 deletions
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 <stdlib.h> #include <string.h> #include <libgen.h> +#include <ctype.h> #include <gpxe/vsprintf.h> #include <gpxe/uri.h> @@ -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 */ |