[gPXE-devel] [PATCH 1/2] [base64] Add decoding support.
Piotr Jaroszyński
p.jaroszynski at gmail.com
Fri Mar 26 23:35:22 EDT 2010
---
src/core/base64.c | 100 +++++++++++++++++++++++++++++++++++++++++++++
src/include/gpxe/base64.h | 12 +++++
2 files changed, 112 insertions(+), 0 deletions(-)
diff --git a/src/core/base64.c b/src/core/base64.c
index 5619ef7..8347c9c 100644
--- a/src/core/base64.c
+++ b/src/core/base64.c
@@ -66,3 +66,103 @@ void base64_encode ( const char *raw, char *encoded ) {
DBG ( "Base64-encoded \"%s\" as \"%s\"\n", raw, encoded );
assert ( strlen ( encoded ) == base64_encoded_len ( strlen ( raw ) ) );
}
+
+#define TABLE
+
+#ifdef TABLE
+static const char base64d[80] =
+ "\x3e\xff\xff\xff\x3f\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\xff"
+// + (,) (-) (.) / 0 1 2 3 4 5 6 7 8 9 (:)
+ "\xff\xff\x00\xff\xff\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
+// (;) (<) = (>) (?) (@) A B C D E F G H I J
+ "\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19"
+// K L M N O P Q R S T U V W X Y Z
+ "\xff\xff\xff\xff\xff\xff\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23"
+// ([) (\) (]) (^) (_) (`) a b c d e f g h i j
+ "\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33";
+// k l m n o p q r s t u v w x y z
+#endif
+
+/**
+ * Base64-decode a string
+ *
+ * @v encoded Encoded string
+ * @v raw Buffer for raw data
+ * @ret rc Return length of the decoded data or -1 to indicate an error
+ *
+ * The buffer must be the correct length for the raw data. Use
+ * something like
+ *
+ * char buf[ base64_decode_buf_len ( strlen ( encoded ) ) ];
+ *
+ * to provide a buffer of the correct size.
+ */
+int base64_decode ( const char *encoded, char *raw ) {
+ const uint8_t *encoded_bytes = ( ( const uint8_t * ) encoded );
+ uint8_t *raw_bytes = ( ( uint8_t * ) raw );
+ size_t encoded_len = strlen ( encoded );
+ size_t len = ( encoded_len / 4 ) * 3;
+ unsigned int byte;
+ unsigned int i;
+ unsigned char buf[4];
+
+ if ( encoded_len % 4 != 0 )
+ return -1;
+
+ if ( encoded_len != 0 ) {
+ for ( i = 1 ; i <= 2 ; ++i)
+ if ( encoded[ encoded_len - i ] == '=')
+ --len;
+ }
+
+ for ( byte = 0 ; byte < encoded_len ; byte += 4 ) {
+#ifdef TABLE
+ for ( i = 0 ; i < 4 ; ++i) {
+ if ( ( encoded_bytes[ byte + i ] < '+' ) || ( encoded_bytes[ byte + i ] > 'z' ) )
+ return -1;
+ buf[ i ] = base64d[ encoded_bytes[ byte + i ] - '+' ];
+ if ( buf[ i ] == 0xff )
+ return -1;
+ }
+#else
+ for ( i = 0 ; i < 4 ; ++i ) {
+ buf[ i ] = encoded_bytes[ byte + i ];
+ // ASCII order is + / 0..9 = A..Z a..z
+ if ( buf[ i ] >= 'A' ) {
+ if ( buf[ i ] <= 'Z' ) {
+ buf[ i ] += 0 - 'A';
+ } else if ( buf[ i ] >= 'a' && buf[ i ] <= 'z' ) {
+ buf[ i ] += 26 - 'a';
+ }
+ } else if ( buf[ i ] >= '0' ) {
+ if ( buf[ i ] <= '9' ) {
+ buf[ i ] += 52 - '0';
+ } else if ( buf[ i ] == '=' ) {
+ buf[ i ] = 0;
+ }
+ } else if ( buf[ i ] == '+' ) {
+ buf[ i ] = 62;
+ } else if ( buf[ i ] == '/' ) {
+ buf[ i ] = 63;
+ }
+ // didn't match any valid char
+ if ( buf[ i ] == encoded_bytes[ byte + i ] )
+ return -1;
+ }
+#endif
+ /*
+ * this loop does:
+ * *(raw_bytes++) = ( buf[ 0 ] << 2 ) | ( buf[ 1 ] >> 4 );
+ * *(raw_bytes++) = ( buf[ 1 ] << 4 ) | ( buf[ 2 ] >> 2 );
+ * *(raw_bytes++) = ( buf[ 2 ] << 6 ) | ( buf[ 3 ] >> 0 );
+ */
+ for ( i = 0 ; i < 3 ; ++i )
+ *(raw_bytes++) = ( buf[ i ] << ( i * 2 + 2 ) ) |
+ ( buf[ i + 1 ] >> ( 4 - i * 2 ) );
+
+ }
+
+ DBG ( "Base64-decoded \"%s\" to \"%s\"\n", encoded, raw );
+
+ return len;
+}
diff --git a/src/include/gpxe/base64.h b/src/include/gpxe/base64.h
index e38bef0..e4255a3 100644
--- a/src/include/gpxe/base64.h
+++ b/src/include/gpxe/base64.h
@@ -21,6 +21,18 @@ static inline size_t base64_encoded_len ( size_t raw_len ) {
return ( ( ( raw_len + 3 - 1 ) / 3 ) * 4 );
}
+/**
+ * Calculate length of the buffer needed to base64-decode string
+ *
+ * @v encoded_len Encoded string length (excluding NUL)
+ * @ret buf_len Buffer length
+ */
+static inline size_t base64_decode_buf_len ( size_t encoded_len ) {
+ return ( ( encoded_len / 4 ) * 3 );
+}
+
extern void base64_encode ( const char *raw, char *encoded );
+extern int base64_decode ( const char *encoded, char *raw );
+
#endif /* _GPXE_BASE64_H */
--
1.7.0.3
More information about the gPXE-devel
mailing list