summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2008-09-24 08:21:47 +0200
committerMichael Brown2008-09-24 08:21:47 +0200
commitb350b10b35760be54d216ef06f8608be05728033 (patch)
treeff82f3f82c93509c65950f21b70fdc261ce04a15
parent[romprefix] If we hook INT 19, prompt before attempting boot (diff)
downloadipxe-b350b10b35760be54d216ef06f8608be05728033.tar.gz
ipxe-b350b10b35760be54d216ef06f8608be05728033.tar.xz
ipxe-b350b10b35760be54d216ef06f8608be05728033.zip
[uri] Add uri_encode() and uri_decode() functions for URI character encoding
-rw-r--r--src/core/uri.c78
-rw-r--r--src/include/gpxe/uri.h2
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 */