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