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