Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

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