Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 | } |
