Demo using MBED TLS
Dependencies: EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed
Fork of iothub_client_sample_amqp by
azure_c_shared_utility/base64.c@58:f50b97b08851, 2017-01-05 (annotated)
- Committer:
- markrad
- Date:
- Thu Jan 05 00:20:03 2017 +0000
- Revision:
- 58:f50b97b08851
Sample using MBED TLS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
markrad | 58:f50b97b08851 | 1 | // Copyright (c) Microsoft. All rights reserved. |
markrad | 58:f50b97b08851 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
markrad | 58:f50b97b08851 | 3 | |
markrad | 58:f50b97b08851 | 4 | // |
markrad | 58:f50b97b08851 | 5 | // PUT NO INCLUDES BEFORE HERE !!!! |
markrad | 58:f50b97b08851 | 6 | // |
markrad | 58:f50b97b08851 | 7 | #include <stdlib.h> |
markrad | 58:f50b97b08851 | 8 | #ifdef _CRTDBG_MAP_ALLOC |
markrad | 58:f50b97b08851 | 9 | #include <crtdbg.h> |
markrad | 58:f50b97b08851 | 10 | #endif |
markrad | 58:f50b97b08851 | 11 | #include "azure_c_shared_utility/gballoc.h" |
markrad | 58:f50b97b08851 | 12 | |
markrad | 58:f50b97b08851 | 13 | #include <stddef.h> |
markrad | 58:f50b97b08851 | 14 | #include <string.h> |
markrad | 58:f50b97b08851 | 15 | #include <stdint.h> |
markrad | 58:f50b97b08851 | 16 | // |
markrad | 58:f50b97b08851 | 17 | // PUT NO CLIENT LIBRARY INCLUDES BEFORE HERE !!!! |
markrad | 58:f50b97b08851 | 18 | // |
markrad | 58:f50b97b08851 | 19 | #include "azure_c_shared_utility/base64.h" |
markrad | 58:f50b97b08851 | 20 | #include "azure_c_shared_utility/xlogging.h" |
markrad | 58:f50b97b08851 | 21 | |
markrad | 58:f50b97b08851 | 22 | |
markrad | 58:f50b97b08851 | 23 | #define splitInt(intVal, bytePos) (char)((intVal >> (bytePos << 3)) & 0xFF) |
markrad | 58:f50b97b08851 | 24 | #define joinChars(a, b, c, d) (uint32_t)((uint32_t)a + ((uint32_t)b << 8) + ((uint32_t)c << 16) + ((uint32_t)d << 24)) |
markrad | 58:f50b97b08851 | 25 | |
markrad | 58:f50b97b08851 | 26 | static char base64char(unsigned char val) |
markrad | 58:f50b97b08851 | 27 | { |
markrad | 58:f50b97b08851 | 28 | char result; |
markrad | 58:f50b97b08851 | 29 | |
markrad | 58:f50b97b08851 | 30 | if (val < 26) |
markrad | 58:f50b97b08851 | 31 | { |
markrad | 58:f50b97b08851 | 32 | result = 'A' + (char)val; |
markrad | 58:f50b97b08851 | 33 | } |
markrad | 58:f50b97b08851 | 34 | else if (val < 52) |
markrad | 58:f50b97b08851 | 35 | { |
markrad | 58:f50b97b08851 | 36 | result = 'a' + ((char)val - 26); |
markrad | 58:f50b97b08851 | 37 | } |
markrad | 58:f50b97b08851 | 38 | else if (val < 62) |
markrad | 58:f50b97b08851 | 39 | { |
markrad | 58:f50b97b08851 | 40 | result = '0' + ((char)val - 52); |
markrad | 58:f50b97b08851 | 41 | } |
markrad | 58:f50b97b08851 | 42 | else if (val == 62) |
markrad | 58:f50b97b08851 | 43 | { |
markrad | 58:f50b97b08851 | 44 | result = '+'; |
markrad | 58:f50b97b08851 | 45 | } |
markrad | 58:f50b97b08851 | 46 | else |
markrad | 58:f50b97b08851 | 47 | { |
markrad | 58:f50b97b08851 | 48 | result = '/'; |
markrad | 58:f50b97b08851 | 49 | } |
markrad | 58:f50b97b08851 | 50 | |
markrad | 58:f50b97b08851 | 51 | return result; |
markrad | 58:f50b97b08851 | 52 | } |
markrad | 58:f50b97b08851 | 53 | |
markrad | 58:f50b97b08851 | 54 | static char base64b16(unsigned char val) |
markrad | 58:f50b97b08851 | 55 | { |
markrad | 58:f50b97b08851 | 56 | const uint32_t base64b16values[4] = { |
markrad | 58:f50b97b08851 | 57 | joinChars('A', 'E', 'I', 'M'), |
markrad | 58:f50b97b08851 | 58 | joinChars('Q', 'U', 'Y', 'c'), |
markrad | 58:f50b97b08851 | 59 | joinChars('g', 'k', 'o', 's'), |
markrad | 58:f50b97b08851 | 60 | joinChars('w', '0', '4', '8') |
markrad | 58:f50b97b08851 | 61 | }; |
markrad | 58:f50b97b08851 | 62 | return splitInt(base64b16values[val >> 2], (val & 0x03)); |
markrad | 58:f50b97b08851 | 63 | } |
markrad | 58:f50b97b08851 | 64 | |
markrad | 58:f50b97b08851 | 65 | static char base64b8(unsigned char val) |
markrad | 58:f50b97b08851 | 66 | { |
markrad | 58:f50b97b08851 | 67 | const uint32_t base64b8values = joinChars('A', 'Q', 'g', 'w'); |
markrad | 58:f50b97b08851 | 68 | return splitInt(base64b8values, val); |
markrad | 58:f50b97b08851 | 69 | } |
markrad | 58:f50b97b08851 | 70 | |
markrad | 58:f50b97b08851 | 71 | static int base64toValue(char base64character, unsigned char* value) |
markrad | 58:f50b97b08851 | 72 | { |
markrad | 58:f50b97b08851 | 73 | int result = 0; |
markrad | 58:f50b97b08851 | 74 | if (('A' <= base64character) && (base64character <= 'Z')) |
markrad | 58:f50b97b08851 | 75 | { |
markrad | 58:f50b97b08851 | 76 | *value = base64character - 'A'; |
markrad | 58:f50b97b08851 | 77 | } |
markrad | 58:f50b97b08851 | 78 | else if (('a' <= base64character) && (base64character <= 'z')) |
markrad | 58:f50b97b08851 | 79 | { |
markrad | 58:f50b97b08851 | 80 | *value = ('Z' - 'A') + 1 + (base64character - 'a'); |
markrad | 58:f50b97b08851 | 81 | } |
markrad | 58:f50b97b08851 | 82 | else if (('0' <= base64character) && (base64character <= '9')) |
markrad | 58:f50b97b08851 | 83 | { |
markrad | 58:f50b97b08851 | 84 | *value = ('Z' - 'A') + 1 + ('z' - 'a') + 1 + (base64character - '0'); |
markrad | 58:f50b97b08851 | 85 | } |
markrad | 58:f50b97b08851 | 86 | else if ('+' == base64character) |
markrad | 58:f50b97b08851 | 87 | { |
markrad | 58:f50b97b08851 | 88 | *value = 62; |
markrad | 58:f50b97b08851 | 89 | } |
markrad | 58:f50b97b08851 | 90 | else if ('/' == base64character) |
markrad | 58:f50b97b08851 | 91 | { |
markrad | 58:f50b97b08851 | 92 | *value = 63; |
markrad | 58:f50b97b08851 | 93 | } |
markrad | 58:f50b97b08851 | 94 | else |
markrad | 58:f50b97b08851 | 95 | { |
markrad | 58:f50b97b08851 | 96 | *value = 0; |
markrad | 58:f50b97b08851 | 97 | result = -1; |
markrad | 58:f50b97b08851 | 98 | } |
markrad | 58:f50b97b08851 | 99 | return result; |
markrad | 58:f50b97b08851 | 100 | } |
markrad | 58:f50b97b08851 | 101 | |
markrad | 58:f50b97b08851 | 102 | static size_t numberOfBase64Characters(const char* encodedString) |
markrad | 58:f50b97b08851 | 103 | { |
markrad | 58:f50b97b08851 | 104 | size_t length = 0; |
markrad | 58:f50b97b08851 | 105 | unsigned char junkChar; |
markrad | 58:f50b97b08851 | 106 | while (base64toValue(encodedString[length],&junkChar) != -1) |
markrad | 58:f50b97b08851 | 107 | { |
markrad | 58:f50b97b08851 | 108 | length++; |
markrad | 58:f50b97b08851 | 109 | } |
markrad | 58:f50b97b08851 | 110 | return length; |
markrad | 58:f50b97b08851 | 111 | } |
markrad | 58:f50b97b08851 | 112 | |
markrad | 58:f50b97b08851 | 113 | /*returns the count of original bytes before being base64 encoded*/ |
markrad | 58:f50b97b08851 | 114 | /*notice NO validation of the content of encodedString. Its length is validated to be a multiple of 4.*/ |
markrad | 58:f50b97b08851 | 115 | static size_t Base64decode_len(const char *encodedString) |
markrad | 58:f50b97b08851 | 116 | { |
markrad | 58:f50b97b08851 | 117 | size_t result; |
markrad | 58:f50b97b08851 | 118 | size_t sourceLength = strlen(encodedString); |
markrad | 58:f50b97b08851 | 119 | |
markrad | 58:f50b97b08851 | 120 | if (sourceLength == 0) |
markrad | 58:f50b97b08851 | 121 | { |
markrad | 58:f50b97b08851 | 122 | result = 0; |
markrad | 58:f50b97b08851 | 123 | } |
markrad | 58:f50b97b08851 | 124 | else |
markrad | 58:f50b97b08851 | 125 | { |
markrad | 58:f50b97b08851 | 126 | result = sourceLength / 4 * 3; |
markrad | 58:f50b97b08851 | 127 | if (encodedString[sourceLength - 1] == '=') |
markrad | 58:f50b97b08851 | 128 | { |
markrad | 58:f50b97b08851 | 129 | if (encodedString[sourceLength - 2] == '=') |
markrad | 58:f50b97b08851 | 130 | { |
markrad | 58:f50b97b08851 | 131 | result --; |
markrad | 58:f50b97b08851 | 132 | } |
markrad | 58:f50b97b08851 | 133 | result--; |
markrad | 58:f50b97b08851 | 134 | } |
markrad | 58:f50b97b08851 | 135 | } |
markrad | 58:f50b97b08851 | 136 | return result; |
markrad | 58:f50b97b08851 | 137 | } |
markrad | 58:f50b97b08851 | 138 | |
markrad | 58:f50b97b08851 | 139 | static void Base64decode(unsigned char *decodedString, const char *base64String) |
markrad | 58:f50b97b08851 | 140 | { |
markrad | 58:f50b97b08851 | 141 | |
markrad | 58:f50b97b08851 | 142 | size_t numberOfEncodedChars; |
markrad | 58:f50b97b08851 | 143 | size_t indexOfFirstEncodedChar; |
markrad | 58:f50b97b08851 | 144 | size_t decodedIndex; |
markrad | 58:f50b97b08851 | 145 | |
markrad | 58:f50b97b08851 | 146 | // |
markrad | 58:f50b97b08851 | 147 | // We can only operate on individual bytes. If we attempt to work |
markrad | 58:f50b97b08851 | 148 | // on anything larger we could get an alignment fault on some |
markrad | 58:f50b97b08851 | 149 | // architectures |
markrad | 58:f50b97b08851 | 150 | // |
markrad | 58:f50b97b08851 | 151 | |
markrad | 58:f50b97b08851 | 152 | numberOfEncodedChars = numberOfBase64Characters(base64String); |
markrad | 58:f50b97b08851 | 153 | indexOfFirstEncodedChar = 0; |
markrad | 58:f50b97b08851 | 154 | decodedIndex = 0; |
markrad | 58:f50b97b08851 | 155 | while (numberOfEncodedChars >= 4) |
markrad | 58:f50b97b08851 | 156 | { |
markrad | 58:f50b97b08851 | 157 | unsigned char c1; |
markrad | 58:f50b97b08851 | 158 | unsigned char c2; |
markrad | 58:f50b97b08851 | 159 | unsigned char c3; |
markrad | 58:f50b97b08851 | 160 | unsigned char c4; |
markrad | 58:f50b97b08851 | 161 | (void)base64toValue(base64String[indexOfFirstEncodedChar], &c1); |
markrad | 58:f50b97b08851 | 162 | (void)base64toValue(base64String[indexOfFirstEncodedChar + 1], &c2); |
markrad | 58:f50b97b08851 | 163 | (void)base64toValue(base64String[indexOfFirstEncodedChar + 2], &c3); |
markrad | 58:f50b97b08851 | 164 | (void)base64toValue(base64String[indexOfFirstEncodedChar + 3], &c4); |
markrad | 58:f50b97b08851 | 165 | decodedString[decodedIndex] = (c1 << 2) | (c2 >> 4); |
markrad | 58:f50b97b08851 | 166 | decodedIndex++; |
markrad | 58:f50b97b08851 | 167 | decodedString[decodedIndex] = ((c2 & 0x0f) << 4) | (c3 >> 2); |
markrad | 58:f50b97b08851 | 168 | decodedIndex++; |
markrad | 58:f50b97b08851 | 169 | decodedString[decodedIndex] = ((c3 & 0x03) << 6) | c4; |
markrad | 58:f50b97b08851 | 170 | decodedIndex++; |
markrad | 58:f50b97b08851 | 171 | numberOfEncodedChars -= 4; |
markrad | 58:f50b97b08851 | 172 | indexOfFirstEncodedChar += 4; |
markrad | 58:f50b97b08851 | 173 | |
markrad | 58:f50b97b08851 | 174 | } |
markrad | 58:f50b97b08851 | 175 | |
markrad | 58:f50b97b08851 | 176 | if (numberOfEncodedChars == 2) |
markrad | 58:f50b97b08851 | 177 | { |
markrad | 58:f50b97b08851 | 178 | unsigned char c1; |
markrad | 58:f50b97b08851 | 179 | unsigned char c2; |
markrad | 58:f50b97b08851 | 180 | (void)base64toValue(base64String[indexOfFirstEncodedChar], &c1); |
markrad | 58:f50b97b08851 | 181 | (void)base64toValue(base64String[indexOfFirstEncodedChar + 1], &c2); |
markrad | 58:f50b97b08851 | 182 | decodedString[decodedIndex] = (c1 << 2) | (c2 >> 4); |
markrad | 58:f50b97b08851 | 183 | } |
markrad | 58:f50b97b08851 | 184 | else if (numberOfEncodedChars == 3) |
markrad | 58:f50b97b08851 | 185 | { |
markrad | 58:f50b97b08851 | 186 | unsigned char c1; |
markrad | 58:f50b97b08851 | 187 | unsigned char c2; |
markrad | 58:f50b97b08851 | 188 | unsigned char c3; |
markrad | 58:f50b97b08851 | 189 | (void)base64toValue(base64String[indexOfFirstEncodedChar], &c1); |
markrad | 58:f50b97b08851 | 190 | (void)base64toValue(base64String[indexOfFirstEncodedChar + 1], &c2); |
markrad | 58:f50b97b08851 | 191 | (void)base64toValue(base64String[indexOfFirstEncodedChar + 2], &c3); |
markrad | 58:f50b97b08851 | 192 | decodedString[decodedIndex] = (c1 << 2) | (c2 >> 4); |
markrad | 58:f50b97b08851 | 193 | decodedIndex++; |
markrad | 58:f50b97b08851 | 194 | decodedString[decodedIndex] = ((c2 & 0x0f) << 4) | (c3 >> 2); |
markrad | 58:f50b97b08851 | 195 | } |
markrad | 58:f50b97b08851 | 196 | } |
markrad | 58:f50b97b08851 | 197 | |
markrad | 58:f50b97b08851 | 198 | BUFFER_HANDLE Base64_Decoder(const char* source) |
markrad | 58:f50b97b08851 | 199 | { |
markrad | 58:f50b97b08851 | 200 | BUFFER_HANDLE result; |
markrad | 58:f50b97b08851 | 201 | /*Codes_SRS_BASE64_06_008: [If source is NULL then Base64_Decode shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 202 | if (source == NULL) |
markrad | 58:f50b97b08851 | 203 | { |
markrad | 58:f50b97b08851 | 204 | LogError("invalid parameter const char* source=%p", source); |
markrad | 58:f50b97b08851 | 205 | result = NULL; |
markrad | 58:f50b97b08851 | 206 | } |
markrad | 58:f50b97b08851 | 207 | else |
markrad | 58:f50b97b08851 | 208 | { |
markrad | 58:f50b97b08851 | 209 | if ((strlen(source) % 4) != 0) |
markrad | 58:f50b97b08851 | 210 | { |
markrad | 58:f50b97b08851 | 211 | /*Codes_SRS_BASE64_06_011: [If the source string has an invalid length for a base 64 encoded string then Base64_Decode shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 212 | LogError("Invalid length Base64 string!"); |
markrad | 58:f50b97b08851 | 213 | result = NULL; |
markrad | 58:f50b97b08851 | 214 | } |
markrad | 58:f50b97b08851 | 215 | else |
markrad | 58:f50b97b08851 | 216 | { |
markrad | 58:f50b97b08851 | 217 | if ((result = BUFFER_new()) == NULL) |
markrad | 58:f50b97b08851 | 218 | { |
markrad | 58:f50b97b08851 | 219 | /*Codes_SRS_BASE64_06_010: [If there is any memory allocation failure during the decode then Base64_Decode shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 220 | LogError("Could not create a buffer to decoding."); |
markrad | 58:f50b97b08851 | 221 | } |
markrad | 58:f50b97b08851 | 222 | else |
markrad | 58:f50b97b08851 | 223 | { |
markrad | 58:f50b97b08851 | 224 | size_t sizeOfOutputBuffer = Base64decode_len(source); |
markrad | 58:f50b97b08851 | 225 | /*Codes_SRS_BASE64_06_009: [If the string pointed to by source is zero length then the handle returned shall refer to a zero length buffer.]*/ |
markrad | 58:f50b97b08851 | 226 | if (sizeOfOutputBuffer > 0) |
markrad | 58:f50b97b08851 | 227 | { |
markrad | 58:f50b97b08851 | 228 | if (BUFFER_pre_build(result, sizeOfOutputBuffer) != 0) |
markrad | 58:f50b97b08851 | 229 | { |
markrad | 58:f50b97b08851 | 230 | /*Codes_SRS_BASE64_06_010: [If there is any memory allocation failure during the decode then Base64_Decode shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 231 | LogError("Could not prebuild a buffer for base 64 decoding."); |
markrad | 58:f50b97b08851 | 232 | BUFFER_delete(result); |
markrad | 58:f50b97b08851 | 233 | result = NULL; |
markrad | 58:f50b97b08851 | 234 | } |
markrad | 58:f50b97b08851 | 235 | else |
markrad | 58:f50b97b08851 | 236 | { |
markrad | 58:f50b97b08851 | 237 | Base64decode(BUFFER_u_char(result), source); |
markrad | 58:f50b97b08851 | 238 | } |
markrad | 58:f50b97b08851 | 239 | } |
markrad | 58:f50b97b08851 | 240 | } |
markrad | 58:f50b97b08851 | 241 | } |
markrad | 58:f50b97b08851 | 242 | } |
markrad | 58:f50b97b08851 | 243 | return result; |
markrad | 58:f50b97b08851 | 244 | } |
markrad | 58:f50b97b08851 | 245 | |
markrad | 58:f50b97b08851 | 246 | |
markrad | 58:f50b97b08851 | 247 | static STRING_HANDLE Base64_Encode_Internal(const unsigned char* source, size_t size) |
markrad | 58:f50b97b08851 | 248 | { |
markrad | 58:f50b97b08851 | 249 | STRING_HANDLE result; |
markrad | 58:f50b97b08851 | 250 | size_t neededSize = 0; |
markrad | 58:f50b97b08851 | 251 | char* encoded; |
markrad | 58:f50b97b08851 | 252 | size_t currentPosition = 0; |
markrad | 58:f50b97b08851 | 253 | neededSize += (size == 0) ? (0) : ((((size - 1) / 3) + 1) * 4); |
markrad | 58:f50b97b08851 | 254 | neededSize += 1; /*+1 because \0 at the end of the string*/ |
markrad | 58:f50b97b08851 | 255 | /*Codes_SRS_BASE64_06_006: [If when allocating memory to produce the encoding a failure occurs then Base64_Encode shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 256 | encoded = (char*)malloc(neededSize); |
markrad | 58:f50b97b08851 | 257 | if (encoded == NULL) |
markrad | 58:f50b97b08851 | 258 | { |
markrad | 58:f50b97b08851 | 259 | result = NULL; |
markrad | 58:f50b97b08851 | 260 | LogError("Base64_Encode:: Allocation failed."); |
markrad | 58:f50b97b08851 | 261 | } |
markrad | 58:f50b97b08851 | 262 | else |
markrad | 58:f50b97b08851 | 263 | { |
markrad | 58:f50b97b08851 | 264 | /*b0 b1(+1) b2(+2) |
markrad | 58:f50b97b08851 | 265 | 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 |
markrad | 58:f50b97b08851 | 266 | |----c1---| |----c2---| |----c3---| |----c4---| |
markrad | 58:f50b97b08851 | 267 | */ |
markrad | 58:f50b97b08851 | 268 | |
markrad | 58:f50b97b08851 | 269 | size_t destinationPosition = 0; |
markrad | 58:f50b97b08851 | 270 | while (size - currentPosition >= 3) |
markrad | 58:f50b97b08851 | 271 | { |
markrad | 58:f50b97b08851 | 272 | char c1 = base64char(source[currentPosition] >> 2); |
markrad | 58:f50b97b08851 | 273 | char c2 = base64char( |
markrad | 58:f50b97b08851 | 274 | ((source[currentPosition] & 3) << 4) | |
markrad | 58:f50b97b08851 | 275 | (source[currentPosition + 1] >> 4) |
markrad | 58:f50b97b08851 | 276 | ); |
markrad | 58:f50b97b08851 | 277 | char c3 = base64char( |
markrad | 58:f50b97b08851 | 278 | ((source[currentPosition + 1] & 0x0F) << 2) | |
markrad | 58:f50b97b08851 | 279 | ((source[currentPosition + 2] >> 6) & 3) |
markrad | 58:f50b97b08851 | 280 | ); |
markrad | 58:f50b97b08851 | 281 | char c4 = base64char( |
markrad | 58:f50b97b08851 | 282 | source[currentPosition + 2] & 0x3F |
markrad | 58:f50b97b08851 | 283 | ); |
markrad | 58:f50b97b08851 | 284 | currentPosition += 3; |
markrad | 58:f50b97b08851 | 285 | encoded[destinationPosition++] = c1; |
markrad | 58:f50b97b08851 | 286 | encoded[destinationPosition++] = c2; |
markrad | 58:f50b97b08851 | 287 | encoded[destinationPosition++] = c3; |
markrad | 58:f50b97b08851 | 288 | encoded[destinationPosition++] = c4; |
markrad | 58:f50b97b08851 | 289 | |
markrad | 58:f50b97b08851 | 290 | } |
markrad | 58:f50b97b08851 | 291 | if (size - currentPosition == 2) |
markrad | 58:f50b97b08851 | 292 | { |
markrad | 58:f50b97b08851 | 293 | char c1 = base64char(source[currentPosition] >> 2); |
markrad | 58:f50b97b08851 | 294 | char c2 = base64char( |
markrad | 58:f50b97b08851 | 295 | ((source[currentPosition] & 0x03) << 4) | |
markrad | 58:f50b97b08851 | 296 | (source[currentPosition + 1] >> 4) |
markrad | 58:f50b97b08851 | 297 | ); |
markrad | 58:f50b97b08851 | 298 | char c3 = base64b16(source[currentPosition + 1] & 0x0F); |
markrad | 58:f50b97b08851 | 299 | encoded[destinationPosition++] = c1; |
markrad | 58:f50b97b08851 | 300 | encoded[destinationPosition++] = c2; |
markrad | 58:f50b97b08851 | 301 | encoded[destinationPosition++] = c3; |
markrad | 58:f50b97b08851 | 302 | encoded[destinationPosition++] = '='; |
markrad | 58:f50b97b08851 | 303 | } |
markrad | 58:f50b97b08851 | 304 | else if (size - currentPosition == 1) |
markrad | 58:f50b97b08851 | 305 | { |
markrad | 58:f50b97b08851 | 306 | char c1 = base64char(source[currentPosition] >> 2); |
markrad | 58:f50b97b08851 | 307 | char c2 = base64b8(source[currentPosition] & 0x03); |
markrad | 58:f50b97b08851 | 308 | encoded[destinationPosition++] = c1; |
markrad | 58:f50b97b08851 | 309 | encoded[destinationPosition++] = c2; |
markrad | 58:f50b97b08851 | 310 | encoded[destinationPosition++] = '='; |
markrad | 58:f50b97b08851 | 311 | encoded[destinationPosition++] = '='; |
markrad | 58:f50b97b08851 | 312 | } |
markrad | 58:f50b97b08851 | 313 | |
markrad | 58:f50b97b08851 | 314 | /*null terminating the string*/ |
markrad | 58:f50b97b08851 | 315 | encoded[destinationPosition] = '\0'; |
markrad | 58:f50b97b08851 | 316 | /*Codes_SRS_BASE64_06_007: [Otherwise Base64_Encode shall return a pointer to STRING, that string contains the base 64 encoding of input.]*/ |
markrad | 58:f50b97b08851 | 317 | result = STRING_new_with_memory(encoded); |
markrad | 58:f50b97b08851 | 318 | if (result == NULL) |
markrad | 58:f50b97b08851 | 319 | { |
markrad | 58:f50b97b08851 | 320 | free(encoded); |
markrad | 58:f50b97b08851 | 321 | LogError("Base64_Encode:: Allocation failed for return value."); |
markrad | 58:f50b97b08851 | 322 | } |
markrad | 58:f50b97b08851 | 323 | } |
markrad | 58:f50b97b08851 | 324 | return result; |
markrad | 58:f50b97b08851 | 325 | } |
markrad | 58:f50b97b08851 | 326 | |
markrad | 58:f50b97b08851 | 327 | STRING_HANDLE Base64_Encode_Bytes(const unsigned char* source, size_t size) |
markrad | 58:f50b97b08851 | 328 | { |
markrad | 58:f50b97b08851 | 329 | STRING_HANDLE result; |
markrad | 58:f50b97b08851 | 330 | /*Codes_SRS_BASE64_02_001: [If source is NULL then Base64_Encode_Bytes shall return NULL.] */ |
markrad | 58:f50b97b08851 | 331 | if (source == NULL) |
markrad | 58:f50b97b08851 | 332 | { |
markrad | 58:f50b97b08851 | 333 | result = NULL; |
markrad | 58:f50b97b08851 | 334 | } |
markrad | 58:f50b97b08851 | 335 | /*Codes_SRS_BASE64_02_002: [If source is not NULL and size is zero, then Base64_Encode_Bytes shall produce an empty STRING_HANDLE.] */ |
markrad | 58:f50b97b08851 | 336 | else if (size == 0) |
markrad | 58:f50b97b08851 | 337 | { |
markrad | 58:f50b97b08851 | 338 | result = STRING_new(); /*empty string*/ |
markrad | 58:f50b97b08851 | 339 | } |
markrad | 58:f50b97b08851 | 340 | else |
markrad | 58:f50b97b08851 | 341 | { |
markrad | 58:f50b97b08851 | 342 | result = Base64_Encode_Internal(source, size); |
markrad | 58:f50b97b08851 | 343 | } |
markrad | 58:f50b97b08851 | 344 | return result; |
markrad | 58:f50b97b08851 | 345 | } |
markrad | 58:f50b97b08851 | 346 | |
markrad | 58:f50b97b08851 | 347 | STRING_HANDLE Base64_Encode(BUFFER_HANDLE input) |
markrad | 58:f50b97b08851 | 348 | { |
markrad | 58:f50b97b08851 | 349 | STRING_HANDLE result; |
markrad | 58:f50b97b08851 | 350 | /*the following will happen*/ |
markrad | 58:f50b97b08851 | 351 | /*1. the "data" of the binary shall be "eaten" 3 characters at a time and produce 4 base64 encoded characters for as long as there are more than 3 characters still to process*/ |
markrad | 58:f50b97b08851 | 352 | /*2. the remaining characters (1 or 2) shall be encoded.*/ |
markrad | 58:f50b97b08851 | 353 | /*there's a level of assumption that 'a' corresponds to 0b000000 and that '_' corresponds to 0b111111*/ |
markrad | 58:f50b97b08851 | 354 | /*the encoding will use the optional [=] or [==] at the end of the encoded string, so that other less standard aware libraries can do their work*/ |
markrad | 58:f50b97b08851 | 355 | /*these are the bits of the 3 normal bytes to be encoded*/ |
markrad | 58:f50b97b08851 | 356 | |
markrad | 58:f50b97b08851 | 357 | /*Codes_SRS_BASE64_06_001: [If input is NULL then Base64_Encode shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 358 | if (input == NULL) |
markrad | 58:f50b97b08851 | 359 | { |
markrad | 58:f50b97b08851 | 360 | result = NULL; |
markrad | 58:f50b97b08851 | 361 | LogError("Base64_Encode:: NULL input"); |
markrad | 58:f50b97b08851 | 362 | } |
markrad | 58:f50b97b08851 | 363 | else |
markrad | 58:f50b97b08851 | 364 | { |
markrad | 58:f50b97b08851 | 365 | size_t inputSize; |
markrad | 58:f50b97b08851 | 366 | const unsigned char* inputBinary; |
markrad | 58:f50b97b08851 | 367 | if ((BUFFER_content(input, &inputBinary) != 0) || |
markrad | 58:f50b97b08851 | 368 | (BUFFER_size(input, &inputSize) != 0)) |
markrad | 58:f50b97b08851 | 369 | { |
markrad | 58:f50b97b08851 | 370 | result = NULL; |
markrad | 58:f50b97b08851 | 371 | LogError("Base64_Encode:: BUFFER_routines failure."); |
markrad | 58:f50b97b08851 | 372 | } |
markrad | 58:f50b97b08851 | 373 | else |
markrad | 58:f50b97b08851 | 374 | { |
markrad | 58:f50b97b08851 | 375 | result = Base64_Encode_Internal(inputBinary, inputSize); |
markrad | 58:f50b97b08851 | 376 | } |
markrad | 58:f50b97b08851 | 377 | } |
markrad | 58:f50b97b08851 | 378 | return result; |
markrad | 58:f50b97b08851 | 379 | } |