www.pudn.com > BTSERVER.rar > base64.cpp
/*---------------------------------------------------------------------------*/ /* base64 */ /* ====== */ /* */ /* Base64 is a stand-alone C program to encode 7-Bit ASCII strings into */ /* base64 encoded strings and decode base64 encoded strings back into 7 bit */ /* ASCII strings. */ /* */ /* Base64 encoding is sometimes used for simple HTTP authentication. That is */ /* when strong encryption isn't necessary, Base64 encryption is used to */ /* authenticate User-ID's and Passwords. */ /* */ /* Base64 processes a string by octets (3 Byte blocks). For every octet in */ /* the decoded string, four byte blocks are generated in the encoded string. */ /* If the decoded string length is not a multiple of 3, the Base64 algorithm */ /* pads the end of the encoded string with equal signs '='. */ /* */ /* An example taken from RFC 2617 (HTTP Authentication): */ /* */ /* Resource (URL) requires basic authentication (Authorization: Basic) for */ /* access, otherwise a HTTP 401 Unauthorized response is returned. */ /* */ /* User-ID:Password string = "Aladdin:open sesame" */ /* Base64 encoded string = "QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */ /* */ /* Usage: base64 OPTION [STRING] */ /* ------ */ /* OPTION: -h Displays a brief messages. */ /* -e Base64 encode the 7-Bit ASCII STRING. */ /* -d Decode the Base64 STRING to 7-Bit ASCII. */ /* */ /* STRING: Either a 7-Bit ASCII text string for encoding or a Base64 */ /* encoded string for decoding back to 7-Bit ASCII. */ /* */ /* Note: For EBCDIC and other collating sequences, the STRING must first */ /* be converted to 7-Bit ASCII before passing it to this module and */ /* the return string must be converted back to the appropriate */ /* collating sequence. */ /* */ /* Student Exercises: */ /* ------------------ */ /* 1. Modify base64 to accept an additional parameter "Quiet Mode" (-q) to */ /* optionally supress the ending statistics and only display the encoded */ /* or decoded string. */ /* */ /* 2. Make base64 callable from another program as follows: */ /* a. Add an externally callable function to determine and return the */ /* size of the buffer required for encoding or decoding. */ /* b. Make base64 accept three parameters; input and output buffer point- */ /* ers and a flag for indicate encoding or decoding. */ /* c. Modify base64 so that a calling program can: */ /* i. Request the size of a buffer required either for encoding or */ /* decoding. */ /* ii. Allocate a buffer based on the result from the previous */ /* call. */ /* iii. Call base64 with the appropriate pointers and flag to encode */ /* or decode a string into the callers buffer. */ /* */ /* Copyright (c) 1994 - 2001 */ /* Marc Niegowski */ /* Connectivity, Inc. */ /* All rights reserved. */ /*---------------------------------------------------------------------------*/ #include// calloc and free prototypes. #include // printf prototype. #include // str* and memset prototypes. #include "base64.h" typedef unsigned char uchar; // Define unsigned char as uchar. typedef unsigned int uint; // Define unsigned int as uint. char *b64decode(const char *); // Decodes a string to ASCII. bool b64valid(uchar *); // Tests for a valid Base64 char. char *b64isnot(char *); // Displays an invalid message. char *b64buffer(const char *, bool); // Alloc. encoding/decoding buffer. // Macro definitions: #define b64is7bit(c) ((c) > 0x7f ? 0 : 1) // Valid 7-Bit ASCII character? #define b64blocks(l) (((l) + 2) / 3 * 4 + 1)// Length rounded to 4 byte block. #define b64octets(l) ((l) / 4 * 3 + 1) // Length rounded to 3 byte octet. // Note: Tables are in hex to support different collating sequences static const // Base64 encoding and decoding uchar pBase64[] = { // table. 0x3e, 0x7f, 0x7f, 0x7f, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 }; /*---------------------------------------------------------------------------*/ /* b64decode - Decode a Base64 string to a 7-Bit ASCII string. */ /* =========================================================== */ /* */ /* Call with: char * - The Base64 string to decode. */ /* */ /* Returns: bool - True (!0) if the operation was successful. */ /* False (0) if the operation was unsuccessful. */ /*---------------------------------------------------------------------------*/ char *b64decode(const char *s) { int l = strlen(s); // Get length of Base64 string. char *b; // Decoding buffer pointers. uchar c = 0; // Character to decode. int x = 0; // General purpose integers. int y = 0; static // Collating sequence... const // ...independant "===". char pPad[] = {0x3d, 0x3d, 0x3d, 0x00}; if (l % 4) // If it's not modulo 4, then it... return b64isnot(NULL); // ...can't be a Base64 string. if (b = strchr(s, pPad[0])) // Only one, two or three equal... { // ...'=' signs are allowed at... if ((b - s) < (l - 3)) // ...the end of the Base64 string. return b64isnot(NULL); // Any other equal '=' signs are... else // ...invalid. if (strncmp(b, (char *) pPad + 3 - (s + l - b), s + l - b)) return b64isnot(NULL); } if (!(b = b64buffer(s, false))) // Allocate a decoding buffer. return NULL; // Can't allocate decoding buffer. x = 0; // Initialize index. while ((c = *s++)) // Decode every byte of the... { // Base64 string. if (c == pPad[0]) // Ignore "=". break; if (!b64valid(&c)) // Valid Base64 Index? return b64isnot(b); // No, return false. switch(x % 4) // Decode 4 byte words into... { // ...3 byte octets. case 0: // Byte 0 of word. b[y] = c << 2; break; case 1: // Byte 1 of word. b[y] |= c >> 4; if (!b64is7bit((uchar) b[y++])) // Is 1st byte of octet valid? return b64isnot(b); // No, return false. b[y] = (c & 0x0f) << 4; break; case 2: // Byte 2 of word. b[y] |= c >> 2; if (!b64is7bit((uchar) b[y++])) // Is 2nd byte of octet valid? return b64isnot(b); // No, return false. b[y] = (c & 0x03) << 6; break; case 3: // Byte 3 of word. b[y] |= c; if (!b64is7bit((uchar) b[y++])) // Is 3rd byte of octet valid? return b64isnot(b); // No, return false. } x++; // Increment word byte. } return b; } /*---------------------------------------------------------------------------*/ /* b64valid - validate the character to decode. */ /* ============================================ */ /* */ /* Checks whether the character to decode falls within the boundaries of the */ /* Base64 decoding table. */ /* */ /* Call with: char - The Base64 character to decode. */ /* */ /* Returns: bool - True (!0) if the character is valid. */ /* False (0) if the character is not valid. */ /*---------------------------------------------------------------------------*/ bool b64valid(uchar *c) { if ((*c < 0x2b) || (*c > 0x7a)) // If not within the range of... return false; // ...the table, return false. if ((*c = pBase64[*c - 0x2b]) == 0x7f) // If it falls within one of... return false; // ...the gaps, return false. return true; // Otherwise, return true. } /*---------------------------------------------------------------------------*/ /* b64isnot - Display an error message and clean up. */ /* ================================================= */ /* */ /* Call this routine to display a message indicating that the string being */ /* decoded is an invalid Base64 string and de-allocate the decoding buffer. */ /* */ /* Call with: char * - Pointer to the Base64 string being decoded. */ /* char * - Pointer to the decoding buffer or NULL if it isn't */ /* allocated and doesn't need to be de-allocated. */ /* */ /* Returns: bool - True (!0) if the character is valid. */ /* False (0) if the character is not valid. */ /*---------------------------------------------------------------------------*/ char *b64isnot(char *b) { if (b) // If the buffer pointer is not... free(b); // ...NULL, de-allocate it. return NULL; } /*---------------------------------------------------------------------------*/ /* b64buffer - Allocate the decoding or encoding buffer. */ /* ===================================================== */ /* */ /* Call this routine to allocate an encoding buffer in 4 byte blocks or a */ /* decoding buffer in 3 byte octets. We use "calloc" to initialize the */ /* buffer to 0x00's for strings. */ /* */ /* Call with: char * - Pointer to the string to be encoded or decoded. */ /* bool - True (!0) to allocate an encoding buffer. */ /* False (0) to allocate a decoding buffer. */ /* */ /* Returns: char * - Pointer to the buffer or NULL if the buffer */ /* could not be allocated. */ /*---------------------------------------------------------------------------*/ char *b64buffer(const char *s, bool f) { int l = strlen(s); // String size to encode or decode. if (!l) // If the string size is 0... return NULL; // ...return null. return (char *)calloc((f ? b64blocks(l) : b64octets(l)),sizeof(char)); }