1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-12-27 02:29:52 +03:00

Merge pull request #1404 from davidebeatrici/base64-revamp

Refactor Base64 functions, encode/decode using OpenSSL's EVP interface
This commit is contained in:
Ilya Shipitsin 2021-07-02 13:23:10 +05:00 committed by GitHub
commit 08905e57a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 224 additions and 369 deletions

View File

@ -939,30 +939,26 @@ bool HttpParseBasicAuthHeader(HTTP_HEADER *h, char *username, UINT username_size
{
if (StrCmpi(key, "Basic") == 0 && IsEmptyStr(value) == false)
{
UINT b64_dest_size = StrSize(value) * 2 + 256;
char *b64_dest = ZeroMalloc(b64_dest_size);
Decode64(b64_dest, value);
if (IsEmptyStr(b64_dest) == false)
char *str = Base64ToBin(NULL, value, StrLen(value));
if (str != NULL)
{
if (b64_dest[0] == ':')
if (str[0] == ':')
{
// Empty username
StrCpy(username, username_size, "");
StrCpy(password, password_size, b64_dest + 1);
StrCpy(password, password_size, str + 1);
ret = true;
}
else
{
if (GetKeyAndValue(b64_dest, username, username_size, password, password_size, ":"))
if (GetKeyAndValue(str, username, username_size, password, password_size, ":"))
{
ret = true;
}
}
}
Free(b64_dest);
Free(str);
}
}
}
}

View File

@ -806,9 +806,6 @@ static UINT SmDdnsGetKey(char *key, SM_DDNS *d){
void SmDDnsDlgInit(HWND hWnd, SM_DDNS *d)
{
char key[20];
char encodedkey[20 * 4 + 32];
// Validate arguments
if (hWnd == NULL || d == NULL)
{
@ -845,10 +842,15 @@ void SmDDnsDlgInit(HWND hWnd, SM_DDNS *d)
Hide(hWnd, B_PROXY);
if(SmDdnsGetKey(key, d) == ERR_NO_ERROR){
encodedkey[ B64_Encode(encodedkey, key, 20) ] = 0;
SetTextA(hWnd, E_KEY, encodedkey);
}else{
char key[20];
if (SmDdnsGetKey(key, d) == ERR_NO_ERROR)
{
char *encoded_key = Base64FromBin(NULL, key, sizeof(key));
SetTextA(hWnd, E_KEY, encoded_key);
Free(encoded_key);
}
else
{
SetText(hWnd, E_KEY, _UU("SM_DDNS_KEY_ERR"));
}

View File

@ -15,6 +15,7 @@
#include "Radius.h"
#include "Server.h"
#include "Mayaqua/Encoding.h"
#include "Mayaqua/Internat.h"
#include "Mayaqua/Memory.h"
#include "Mayaqua/Microsoft.h"
@ -31,11 +32,6 @@
#include <unistd.h>
#endif
int base64_enc_len(unsigned int plainLen) {
unsigned int n = plainLen;
return (n + 2 - ((n + 2) % 3)) / 3 * 4;
}
PID OpenChildProcess(const char* path, char* const parameter[], int fd[] )
{
#ifdef OS_WIN32
@ -134,7 +130,6 @@ bool SmbAuthenticate(char* name, char* password, char* domainname, char* groupna
int fds[2];
FILE* out, *in;
PID pid;
char buffer[255];
char ntlm_timeout[32];
char* proc_parameter[6];
@ -153,8 +148,6 @@ bool SmbAuthenticate(char* name, char* password, char* domainname, char* groupna
return false;
}
Zero(buffer, sizeof(buffer));
// Truncate string if unsafe char
EnSafeStr(domainname, '\0');
@ -218,64 +211,48 @@ bool SmbAuthenticate(char* name, char* password, char* domainname, char* groupna
return false;
}
if (base64_enc_len((unsigned int)strlen(name)) < sizeof(buffer)-1 &&
base64_enc_len((unsigned int)strlen(password)) < sizeof(buffer)-1 &&
base64_enc_len((unsigned int)strlen(domainname)) < sizeof(buffer)-1)
{
char answer[300];
unsigned int end = B64_Encode(buffer, name, (int)strlen(name));
buffer[end] = '\0';
char *base64 = Base64FromBin(NULL, name, StrLen(name));
fputs("Username:: ", out);
fputs(buffer, out);
fputs(base64, out);
fputs("\n", out);
Debug("Username: %s\n", buffer);
buffer[0] = 0;
Free(base64);
end = B64_Encode(buffer, domainname, (int)strlen(domainname));
buffer[end] = '\0';
base64 = Base64FromBin(NULL, domainname, StrLen(domainname));
fputs("NT-Domain:: ", out);
fputs(buffer, out);
fputs(base64, out);
fputs("\n", out);
Debug("NT-Domain: %s\n", buffer);
buffer[0] = 0;
Free(base64);
if (password[0] != '\0')
if (IsEmptyStr(password) == false)
{
Debug("Password authentication\n");
end = B64_Encode(buffer, password, (int)strlen(password));
buffer[end] = '\0';
Debug("SmbAuthenticate(): Using password authentication...\n");
base64 = Base64FromBin(NULL, password, StrLen(password));
fputs("Password:: ", out);
fputs(buffer, out);
fputs(base64, out);
fputs("\n", out);
Debug("Password: %s\n", buffer);
buffer[0] = 0;
Free(base64);
}
else
{
char* mschapv2_client_response;
char* base64_challenge8;
Debug("SmbAuthenticate(): Using MsChapV2 authentication...\n");
Debug("MsChapV2 authentication\n");
mschapv2_client_response = CopyBinToStr(MsChapV2_ClientResponse, 24);
end = B64_Encode(buffer, mschapv2_client_response, 48);
buffer[end] = '\0';
fputs("NT-Response:: ", out);
fputs(buffer, out);
fputs("\n", out);
Debug("NT-Response:: %s\n", buffer);
buffer[0] = 0;
char *mschapv2_client_response = CopyBinToStr(MsChapV2_ClientResponse, 24);
base64 = Base64FromBin(NULL, mschapv2_client_response, 48);
Free(mschapv2_client_response);
base64_challenge8 = CopyBinToStr(challenge8, 8);
end = B64_Encode(buffer, base64_challenge8 , 16);
buffer[end] = '\0';
fputs("LANMAN-Challenge:: ", out);
fputs(buffer, out);
fputs("NT-Response:: ", out);
fputs(base64, out);
fputs("\n", out);
Debug("LANMAN-Challenge:: %s\n", buffer);
buffer[0] = 0;
Free(base64);
char *base64_challenge8 = CopyBinToStr(challenge8, 8);
base64 = Base64FromBin(NULL, base64_challenge8, 16);
Free(base64_challenge8);
fputs("LANMAN-Challenge:: ", out);
fputs(base64, out);
fputs("\n", out);
Free(base64);
fputs("Request-User-Session-Key: Yes\n", out);
}
@ -285,6 +262,7 @@ bool SmbAuthenticate(char* name, char* password, char* domainname, char* groupna
fflush (out);
// Request send!
char answer[300];
Zero(answer, sizeof(answer));
while (fgets(answer, sizeof(answer)-1, in))
@ -323,7 +301,7 @@ bool SmbAuthenticate(char* name, char* password, char* domainname, char* groupna
response_parameter[0] ='\0';
response_parameter++;
end = Decode64(response_parameter, response_parameter);
const UINT end = Base64Decode(response_parameter, response_parameter, StrLen(response_parameter));
response_parameter[end] = '\0';
}

View File

@ -11,6 +11,7 @@
#include "Protocol.h"
#include "Mayaqua/DNS.h"
#include "Mayaqua/Encoding.h"
#include "Mayaqua/Memory.h"
#include "Mayaqua/Microsoft.h"
#include "Mayaqua/Pack.h"
@ -807,19 +808,14 @@ BUF *HttpRequestEx3(URL_DATA *data, INTERNET_SETTING *setting,
if (IsEmptyStr(setting->ProxyUsername) == false || IsEmptyStr(setting->ProxyPassword) == false)
{
char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
char basic_str[MAX_SIZE * 2];
char auth_str[MAX_SIZE * 2];
Format(auth_str, sizeof(auth_str), "%s:%s", setting->ProxyUsername, setting->ProxyPassword);
// Generate the authentication string
Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
setting->ProxyUsername, setting->ProxyPassword);
char *base64 = Base64FromBin(NULL, auth_str, StrLen(auth_str));
Format(auth_str, sizeof(auth_str), "Basic %s", base64);
Free(base64);
// Base64 encode
Zero(auth_b64_str, sizeof(auth_b64_str));
Encode64(auth_b64_str, auth_tmp_str);
Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
AddHttpValue(h, NewHttpValue("Proxy-Authorization", auth_str));
}
}
@ -1229,18 +1225,14 @@ bool ParseUrl(URL_DATA *data, char *str, bool is_post, char *referrer)
}
// String replacement
void Base64ToSafe64(char *str)
void Base64ToSafe64(char *str, const UINT size)
{
UINT i, len;
// Validate arguments
if (str == NULL)
if (str == NULL || size == 0)
{
return;
}
len = StrLen(str);
for (i = 0;i < len;i++)
for (UINT i = 0; i < size; ++i)
{
switch (str[i])
{
@ -1258,18 +1250,14 @@ void Base64ToSafe64(char *str)
}
}
}
void Safe64ToBase64(char *str)
void Safe64ToBase64(char *str, const UINT size)
{
UINT i, len;
// Validate arguments
if (str == NULL)
if (str == NULL || size == 0)
{
return;
}
len = StrLen(str);
for (i = 0;i < len;i++)
for (UINT i = 0; i < size; ++i)
{
switch (str[i])
{
@ -1288,44 +1276,39 @@ void Safe64ToBase64(char *str)
}
}
// Decode from Safe64
UINT DecodeSafe64(void *dst, char *src, UINT src_strlen)
// Decode from escaped Base64
UINT DecodeSafe64(void *dst, const char *src, UINT size)
{
char *tmp;
UINT ret;
if (dst == NULL || src == NULL)
{
return 0;
}
if (src_strlen == 0)
if (size == 0)
{
src_strlen = StrLen(src);
size = StrLen(src);
}
tmp = Malloc(src_strlen + 1);
Copy(tmp, src, src_strlen);
tmp[src_strlen] = 0;
Safe64ToBase64(tmp);
char *tmp = Malloc(size + 1);
Copy(tmp, src, size);
tmp[size] = '\0';
ret = B64_Decode(dst, tmp, src_strlen);
Safe64ToBase64(tmp, size);
const UINT ret = Base64Decode(dst, tmp, size);
Free(tmp);
return ret;
}
// Encode to Safe64
void EncodeSafe64(char *dst, void *src, UINT src_size)
// Encode to escaped Base64
void EncodeSafe64(char *dst, const void *src, const UINT size)
{
UINT size;
if (dst == NULL || src == NULL)
{
return;
}
size = B64_Encode(dst, src, src_size);
dst[size] = 0;
const UINT ret = Base64Encode(dst, src, size);
Base64ToSafe64(dst);
Base64ToSafe64(dst, ret);
}

View File

@ -84,10 +84,10 @@ struct WPC_PACKET
typedef bool (WPC_RECV_CALLBACK)(void *param, UINT total_size, UINT current_size, BUF *recv_buf);
// Function prototype
void EncodeSafe64(char *dst, void *src, UINT src_size);
UINT DecodeSafe64(void *dst, char *src, UINT src_strlen);
void Base64ToSafe64(char *str);
void Safe64ToBase64(char *str);
void Base64ToSafe64(char *str, const UINT size);
void Safe64ToBase64(char *str, const UINT size);
UINT DecodeSafe64(void *dst, const char *src, UINT size);
void EncodeSafe64(char *dst, const void *src, const UINT size);
bool ParseUrl(URL_DATA *data, char *str, bool is_post, char *referrer);
void CreateUrl(char *url, UINT url_size, URL_DATA *data);
void GetSystemInternetSetting(INTERNET_SETTING *setting);

View File

@ -57,9 +57,16 @@ if(UNIX)
# In some cases libiconv is not included in libc
find_library(LIB_ICONV iconv)
find_library(LIB_M m)
find_library(LIB_RT rt)
target_link_libraries(mayaqua PRIVATE Threads::Threads)
target_link_libraries(mayaqua
PRIVATE
Threads::Threads
$<$<BOOL:${LIB_ICONV}>:${LIB_ICONV}>
$<$<BOOL:${LIB_M}>:${LIB_M}>
$<$<BOOL:${LIB_RT}>:${LIB_RT}>
)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7l|aarch64|s390x)$" OR NOT HAVE_SYS_AUXV OR SKIP_CPU_FEATURES)
add_definitions(-DSKIP_CPU_FEATURES)
@ -69,14 +76,6 @@ if(UNIX)
target_link_libraries(mayaqua PRIVATE cpu_features)
endif()
if(LIB_RT)
target_link_libraries(mayaqua PRIVATE rt)
endif()
if(LIB_ICONV)
target_link_libraries(mayaqua PRIVATE ${LIB_ICONV})
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
target_link_libraries(mayaqua PRIVATE nsl socket)
endif()

View File

@ -7,6 +7,7 @@
#include "Cfg.h"
#include "Encoding.h"
#include "FileIO.h"
#include "Internat.h"
#include "Memory.h"
@ -746,12 +747,18 @@ bool CfgReadNextTextBUF(BUF *b, FOLDER *current)
if (!StrCmpi(token->Token[0], TAG_BYTE))
{
// byte
char *unescaped_b64 = CfgUnescape(data);
void *tmp = Malloc(StrLen(unescaped_b64) * 4 + 64);
int size = B64_Decode(tmp, unescaped_b64, StrLen(unescaped_b64));
CfgAddByte(current, name, tmp, size);
Free(tmp);
Free(unescaped_b64);
char *base64 = CfgUnescape(data);
const UINT base64_size = StrLen(base64);
UINT bin_size;
void *bin = Base64ToBin(&bin_size, base64, base64_size);
if (bin != NULL)
{
CfgAddByte(current, name, bin, bin_size);
Free(bin);
}
Free(base64);
}
Free(name);
@ -1162,9 +1169,7 @@ void CfgAddItemText(BUF *b, ITEM *t, UINT depth)
break;
case ITEM_TYPE_BYTE:
data = ZeroMalloc(t->size * 4 + 32);
len = B64_Encode(data, t->Buf, t->size);
data[len] = 0;
data = Base64FromBin(NULL, t->Buf, t->size);
break;
case ITEM_TYPE_STRING:

64
src/Mayaqua/Encoding.c Normal file
View File

@ -0,0 +1,64 @@
#include "Encoding.h"
#include <math.h>
#include <openssl/evp.h>
UINT Base64Decode(void *dst, const void *src, const UINT size)
{
if (dst == NULL)
{
// 4 input bytes = max. 3 output bytes.
//
// EVP_DecodeUpdate() ignores:
// - Leading/trailing whitespace.
// - Trailing newlines, carriage returns or EOF characters.
//
// EVP_DecodeFinal() fails if the input is not divisible by 4.
return size / 4 * 3;
}
// We don't use EVP_DecodeBlock() because it adds padding if the output is not divisible by 3.
EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
if (ctx == NULL)
{
return 0;
}
int ret = 0;
if (EVP_DecodeUpdate(ctx, dst, &ret, src, size) < 0)
{
goto FINAL;
}
int dummy;
if (EVP_DecodeFinal(ctx, dst, &dummy) < 0)
{
ret = 0;
}
FINAL:
EVP_ENCODE_CTX_free(ctx);
return ret;
}
UINT Base64Encode(void *dst, const void *src, const UINT size)
{
if (dst == NULL)
{
// 3 input bytes = 4 output bytes.
// +1 for the NUL terminator.
//
// EVP_EncodeBlock() adds padding when the input is not divisible by 3.
return ceilf((float)size / 3) * 4 + 1;
}
const int ret = EVP_EncodeBlock(dst, src, size);
if (ret > 0)
{
// EVP_EncodeBlock() returns the length of the string without the NUL terminator.
// We, instead, want to return the amount of bytes written into the output buffer.
return ret + 1;
}
return 0;
}

9
src/Mayaqua/Encoding.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef ENCODING_H
#define ENCODING_H
#include "MayaType.h"
UINT Base64Decode(void *dst, const void *src, const UINT size);
UINT Base64Encode(void *dst, const void *src, const UINT size);
#endif

View File

@ -7,6 +7,7 @@
#include "Memory.h"
#include "Encoding.h"
#include "Encrypt.h"
#include "FileIO.h"
#include "Internat.h"
@ -3407,232 +3408,62 @@ UINT64 Swap64(UINT64 value)
return r;
}
// Base64 encode
UINT Encode64(char *dst, char *src)
void *Base64ToBin(UINT *out_size, const void *src, const UINT size)
{
// Validate arguments
if (dst == NULL || src == NULL)
if (src == NULL || size == 0)
{
return 0;
return NULL;
}
return B64_Encode(dst, src, StrLen(src));
UINT bin_size = Base64Decode(NULL, src, size);
if (bin_size == 0)
{
return NULL;
}
void *bin = Malloc(bin_size);
bin_size = Base64Decode(bin, src, size);
if (bin_size == 0)
{
Free(bin);
return NULL;
}
if (out_size != NULL)
{
*out_size = bin_size;
}
return bin;
}
// Base64 decoding
UINT Decode64(char *dst, char *src)
void *Base64FromBin(UINT *out_size, const void *src, const UINT size)
{
// Validate arguments
if (dst == NULL || src == NULL)
if (src == NULL || size == 0)
{
return 0;
return NULL;
}
return B64_Decode(dst, src, StrLen(src));
}
UINT base64_size = Base64Encode(NULL, src, size);
if (base64_size == 0)
{
return NULL;
}
// Base64 encode
int B64_Encode(char *set, char *source, int len)
{
BYTE *src;
int i,j;
src = (BYTE *)source;
j = 0;
i = 0;
if (!len)
void *base64 = Malloc(base64_size);
base64_size = Base64Encode(base64, src, size);
if (base64_size == 0)
{
return 0;
Free(base64);
return NULL;
}
while (true)
{
if (i >= len)
{
return j;
}
if (set)
{
set[j] = B64_CodeToChar((src[i]) >> 2);
}
if (i + 1 >= len)
{
if (set)
{
set[j + 1] = B64_CodeToChar((src[i] & 0x03) << 4);
set[j + 2] = '=';
set[j + 3] = '=';
}
return j + 4;
}
if (set)
{
set[j + 1] = B64_CodeToChar(((src[i] & 0x03) << 4) + ((src[i + 1] >> 4)));
}
if (i + 2 >= len)
{
if (set)
{
set[j + 2] = B64_CodeToChar((src[i + 1] & 0x0f) << 2);
set[j + 3] = '=';
}
return j + 4;
}
if (set)
{
set[j + 2] = B64_CodeToChar(((src[i + 1] & 0x0f) << 2) + ((src[i + 2] >> 6)));
set[j + 3] = B64_CodeToChar(src[i + 2] & 0x3f);
}
i += 3;
j += 4;
}
}
// Base64 decode
int B64_Decode(char *set, char *source, int len)
{
int i,j;
char a1,a2,a3,a4;
char *src;
int f1,f2,f3,f4;
src = source;
i = 0;
j = 0;
while (true)
if (out_size != NULL)
{
f1 = f2 = f3 = f4 = 0;
if (i >= len)
{
break;
}
f1 = 1;
a1 = B64_CharToCode(src[i]);
if (a1 == -1)
{
f1 = 0;
}
if (i >= len + 1)
{
a2 = 0;
}
else
{
a2 = B64_CharToCode(src[i + 1]);
f2 = 1;
if (a2 == -1)
{
f2 = 0;
}
}
if (i >= len + 2)
{
a3 = 0;
}
else
{
a3 = B64_CharToCode(src[i + 2]);
f3 = 1;
if (a3 == -1)
{
f3 = 0;
}
}
if (i >= len + 3)
{
a4 = 0;
}
else
{
a4 = B64_CharToCode(src[i + 3]);
f4 = 1;
if (a4 == -1)
{
f4 = 0;
}
}
if (f1 && f2)
{
if (set)
{
set[j] = (a1 << 2) + (a2 >> 4);
}
j++;
}
if (f2 && f3)
{
if (set)
{
set[j] = (a2 << 4) + (a3 >> 2);
}
j++;
}
if (f3 && f4)
{
if (set)
{
set[j] = (a3 << 6) + a4;
}
j++;
}
i += 4;
*out_size = base64_size;
}
return j;
}
// Base64 : Convert a code to a character
char B64_CodeToChar(BYTE c)
{
BYTE r;
r = '=';
if (c <= 0x19)
{
r = c + 'A';
}
if (c >= 0x1a && c <= 0x33)
{
r = c - 0x1a + 'a';
}
if (c >= 0x34 && c <= 0x3d)
{
r = c - 0x34 + '0';
}
if (c == 0x3e)
{
r = '+';
}
if (c == 0x3f)
{
r = '/';
}
return r;
}
// Base64 : Convert a character to a code
char B64_CharToCode(char c)
{
if (c >= 'A' && c <= 'Z')
{
return c - 'A';
}
if (c >= 'a' && c <= 'z')
{
return c - 'a' + 0x1a;
}
if (c >= '0' && c <= '9')
{
return c - '0' + 0x34;
}
if (c == '+')
{
return 0x3e;
}
if (c == '/')
{
return 0x3f;
}
if (c == '=')
{
return -1;
}
return 0;
return base64;
}
// Malloc

View File

@ -190,12 +190,8 @@ void Zero(void *addr, UINT size);
void *Clone(void *addr, UINT size);
void *AddHead(void *src, UINT src_size, void *head, UINT head_size);
char B64_CodeToChar(BYTE c);
char B64_CharToCode(char c);
int B64_Encode(char *set, char *source, int len);
int B64_Decode(char *set, char *source, int len);
UINT Encode64(char *dst, char *src);
UINT Decode64(char *dst, char *src);
void *Base64FromBin(UINT *out_size, const void *src, const UINT size);
void *Base64ToBin(UINT *out_size, const void *src, const UINT size);
USHORT Swap16(USHORT value);
UINT Swap32(UINT value);

View File

@ -2239,10 +2239,9 @@ bool JsonTryParseValueAddToPack(PACK *p, JSON_VALUE *v, char *v_name, UINT index
{
if (v->type == JSON_TYPE_STRING)
{
UINT len = StrLen(v->value.string);
UCHAR *data = ZeroMalloc(len * 4 + 64);
UINT size = B64_Decode(data, v->value.string, len);
ElementNullSafe(PackAddDataEx(p, name, data, size, index, total))->JsonHint_IsArray = !is_single;
UINT data_size;
void *data = Base64ToBin(&data_size, v->value.string, StrLen(v->value.string));
ElementNullSafe(PackAddDataEx(p, name, data, data_size, index, total))->JsonHint_IsArray = !is_single;
Free(data);
ok = true;
}

View File

@ -129,17 +129,12 @@ UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *c
if (use_auth && GetHttpValue(h, "Proxy-Authorization") == NULL)
{
char auth_str[MAX_SIZE * 2], auth_b64_str[MAX_SIZE * 2];
// Generate the authentication string
char auth_str[MAX_SIZE * 2];
Format(auth_str, sizeof(auth_str), "%s:%s", in->Username, in->Password);
// Base64 encode
Zero(auth_b64_str, sizeof(auth_b64_str));
Encode64(auth_b64_str, auth_str);
// Generate final string
Format(auth_str, sizeof(auth_str), "Basic %s", auth_b64_str);
char *base64 = Base64FromBin(NULL, auth_str, StrLen(auth_str));
Format(auth_str, sizeof(auth_str), "Basic %s", base64);
Free(base64);
AddHttpValue(h, NewHttpValue("Proxy-Authorization", auth_str));
}

View File

@ -4667,12 +4667,11 @@ UINT JsonArrayAddNumber(JSON_ARRAY *array, UINT64 number) {
UINT JsonArrayAddData(JSON_ARRAY *array, void *data, UINT size)
{
UINT ret;
char *b64 = ZeroMalloc(size * 4 + 32);
B64_Encode(b64, data, size);
char *base64 = Base64FromBin(NULL, data, size);
ret = JsonArrayAddStr(array, b64);
ret = JsonArrayAddStr(array, base64);
Free(b64);
Free(base64);
return ret;
}
@ -4724,12 +4723,11 @@ UINT JsonSet(JSON_OBJECT *object, char *name, JSON_VALUE *value) {
UINT JsonSetData(JSON_OBJECT *object, char *name, void *data, UINT size)
{
UINT ret;
char *b64 = ZeroMalloc(size * 4 + 32);
B64_Encode(b64, data, size);
char *base64 = Base64FromBin(NULL, data, size);
ret = JsonSetStr(object, name, b64);
ret = JsonSetStr(object, name, base64);
Free(b64);
Free(base64);
return ret;
}