/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include"sdp_base64.h"
/* * Local definitions for Base64 to Raw table entries.
*/ #define INVALID_CHAR 0xFF /* Character not in supported Base64 set */ #define WHITE_SPACE 0xFE /* Space, tab, newline, etc character */ #define PADDING 0xFD /* The character '=' */
#define PAD_CHAR '='/* The character '=' */
/* Maximum length of a base64 encoded line */ #define MAX_BASE64_LINE_LENGTH 76
/* * base64_result_table * String table for translating base64 error codes into human * understanable strings.
*/ char *base64_result_table[BASE64_RESULT_MAX] =
{ "Base64 successful", "Base64 Buffer Overrun", "Base64 Bad Data", "Base64 Bad Padding", "Base64 Bad Block Size"
};
/* * base64_encode_size_bytes * * DESCRIPTION * Estimates the size of buffer required for holding the result of * encoding data of size raw_size_bytes. * * PARAMETERS * raw_size_bytes = Estimated size of the un-encoded data in bytes. * * RETURN VALUE * The size of destination buffer to use for encoding in bytes.
*/ int base64_est_encode_size_bytes (int raw_size_bytes)
{ int length;
/* * Find the number of bytes needed to represent the data * using a 4/3 expansion ratio. That result must be * rounded to the next higher multiple of four to account * for padding. Then add in a term to account for any '\n's * added.
*/
length = ((((raw_size_bytes * 4 + 2)/ 3) + 3) & ~(0x3)) +
raw_size_bytes / MAX_BASE64_LINE_LENGTH;
return length;
}
/* * base64_decode_size_bytes * * DESCRIPTION * Estimates the size of buffer required for holding the result of * decoding data of size base64_size_bytes. * * PARAMETERS * base64_size_bytes = Estimated size of the Base64 data in bytes. * * RETURN VALUE * The size of destination buffer to use for decoding in bytes.
*/ int base64_est_decode_size_bytes (int base64_size_bytes)
{ int length;
/* * base64_encode * * DESCRIPTION * Encode data pointed to by src into the buffer pointer to by dest * using the Base64 algorithm. * * NOTE: No trailing '\n' character will be added. * * NOTE: As per specification, '\n' will be placed every 76 chars. * * PARAMETERS * src = Pointer to the raw data to base64 encode. * src_bytes = The number of bytes in the src buffer to encode. * dest = Pointer to the destination buffer where the converted data * will reside when complete. * dest_bytes = Initially holds the size of the destination buffer * but at completion holds the number of bytes converted. * * RETURN VALUE * base64_success if the buffer was successfully converted, the * appropriate error code otherwise. * * The dest parameter holds the converted data. * * The dest_bytes parameter holds the actual number of bytes converted.
*/
base64_result_t base64_encode(unsignedchar *src, int src_bytes, unsignedchar *dest, int*dest_bytes)
{ int i, j=0; int line_count = 0; unsignedchar index; /* index into base64 lookup table */ int smax = src_bytes-2; /* only do full multiples of 3 */ int dmax = *dest_bytes; /* destination maximum */
*dest_bytes = 0;
/* Do full groups. Base64 must be done in blocks of 3 src bytes */ for (i=0; i<smax; i+=3) { /* Check to see if newline should be injected */ if (line_count>=MAX_BASE64_LINE_LENGTH) { if (j<dmax){
dest[j++] = '\n';
} else { return BASE64_BUFFER_OVERRUN;
}
line_count = 0;
}
line_count += 4;
if ((j+3) < dmax) {
/* Find mapping of upper 6 bits */
index = (src[i] >> 2) & 0x3F;
dest[j++] = raw_to_base64_table[index];
/* bottom 2 bits of first word, high 4 bits of second word */
index = ((src[i] << 4) & 0x30) | ((src[i+1] >> 4) & 0x0F);
dest[j++] = raw_to_base64_table[index];
/* bottom 4 bits of second word, high 2 bits of third word */
index = ((src[i+1] << 2) & 0x3C) | ((src[i+2] >> 6) & 0x03);
dest[j++] = raw_to_base64_table[index];
/* bottom 6 bits of third word */
index = src[i+2] & 0x3F;
dest[j++] = raw_to_base64_table[index];
} else { return BASE64_BUFFER_OVERRUN;
}
}
/* Check to see if any more work must be done */ if (i<src_bytes) {
/* Check to see if a newline should be output */ if (line_count>=MAX_BASE64_LINE_LENGTH) { if (j<dmax){
dest[j++] = '\n';
} else { return BASE64_BUFFER_OVERRUN;
}
line_count = 0;
}
line_count += 4;
/* Must fill another quantum */ if (j+4>dmax) { /* No room left in output buffer! */ return BASE64_BUFFER_OVERRUN;
}
/* Find mapping of upper 6 bits */
index = (src[i] >> 2) & 0x3F;
dest[j++] = raw_to_base64_table[index];
/* check for another stragler */ if ((i+1)<src_bytes) { /* bottom 2 bits of first word, high 4 bits of second word */
index = ((src[i] << 4) & 0x30) | ((src[i+1] >> 4) & 0x0F);
dest[j++] = raw_to_base64_table[index];
/* bottom 4 bits of second word */
index = (src[i+1] << 2) & 0x3C;
dest[j++] = raw_to_base64_table[index];
dest[j++] = PAD_CHAR;
} else { /* bottom 2 bits of first word */
index = (src[i] << 4) & 0x30;
dest[j++] = raw_to_base64_table[index];
dest[j++] = PAD_CHAR;
dest[j++] = PAD_CHAR;
}
}
*dest_bytes = j;
return BASE64_SUCCESS;
}
unsignedchar base64_decode_get_raw(unsignedchar index)
{ /* only have 128 values, MSB must not be set! */ if (index >= 128) { return INVALID_CHAR;
} return base64_to_raw_table[index];
}
/* * base64_decode * * DESCRIPTION * Decode data pointed to by src into the buffer pointer to by dest * using the Base64 algorithm. * * PARAMETERS * src = Pointer to the Base64 data to decode. * src_bytes = The number of bytes in the src buffer to decode. * dest = Pointer to the destination buffer where the converted data * will reside when complete. * dest_bytes = Initially holds the size of the destination buffer * but at completion holds the number of bytes converted. * * RETURN VALUE * base64_success if the buffer was successfully converted, the * appropriate error code otherwise. * * The dest parameter holds the converted data. * * The dest_bytes parameter holds the actual number of bytes converted.
*/
base64_result_t base64_decode(unsignedchar *src, int src_bytes, unsignedchar *dest, int*dest_bytes)
{ int i, j = 0; int sindex = 0; /* Current NON-whitespace source
* index */ int pad_count=0; /* Number of padding characters
* encountered */ int dest_size_bytes = *dest_bytes; /* Save size of destination buffer */ unsignedchar cindex; /* The current Base64 character to
* process */ unsignedchar val; /* The value of the current Base64
* character */
*dest_bytes = 0;
for (i=0; i<src_bytes; i++) {
cindex = src[i];
val = base64_decode_get_raw(cindex); if (val == INVALID_CHAR) { /* Invalid base64 character */ return BASE64_BAD_DATA;
}
if (val == WHITE_SPACE) { /* Ignore white space */ continue;
}
if (val == PADDING) { /* we must be at the end-finish up */
pad_count++; if (++i<src_bytes) { /* can have up to 2 pad chars */ if (base64_decode_get_raw(src[i]) != PADDING) { return BASE64_BAD_PADDING;
}
if (++i<src_bytes) { /* should not have any more padding! */ return BASE64_BAD_PADDING;
}
pad_count++;
}
/* DONE! */ break;
}
/* Determine which portion of the 3 bytes this data will fill */ switch (sindex & 0x3) { case 0: /* Fill upper 6 bits */ if (j<dest_size_bytes) {
dest[j] = val << 2;
} else { return BASE64_BUFFER_OVERRUN;
} break; case 1: /* Fill Bottom 2 bits */
dest[j++] |= val >> 4;
if (j<dest_size_bytes) { /* Fill Top 4 bits */
dest[j] = (val << 4) & 0xF0;
} else { /* * Check to see if there is any more data present. * Next base64 character MUST be a pad character and * the rest of this data MUST be zero. * * If this is not the end of data then a buffer overrun * has occurred
*/ if ((val & 0x0F) ||
(i+1>=src_bytes) ||
(base64_decode_get_raw(src[i+1]) != PADDING)) { return BASE64_BUFFER_OVERRUN;
}
} break; case 2: /* Fill Bottom 4 bits */
dest[j++] |= val >> 2;
if (j<dest_size_bytes) { /* Fill Top 2 bits */
dest[j] = (val << 6) & 0xC0;
} else { /* * Check to see if there is any more data present. * Next base64 character MUST be a pad character and * the rest of this data MUST be zero. * * If this is not the end of data then a buffer overrun * has occurred
*/ if ((val & 0x03) ||
(i+1>=src_bytes) ||
(base64_decode_get_raw(src[i+1]) != PADDING)) { return BASE64_BUFFER_OVERRUN;
}
} break; case 3: /* * No need to check for overrun here since the * previous case was already checked. If another * group is present then case 0 will check again.
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.