Click here to Skip to main content
16,018,904 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
Hi all

I need to write a C function receive as input a string and outputs Base64 but with charset UTF16BE.

Below Base64_code function produce UTF8.

I really hope somebody can help me

Thanks all

Giovanni

What I have tried:

void Base64_code(IN const CHAR* strIn, OUT CString& strOut)
{
    const static CHAR base64ABC[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    strOut.Empty();
    const size_t len = strlen(strIn);
    for (size_t i = 0; i < len; i += 3) 
    {
        LONG l = (((LONG)strIn[i]) << 16) | (((i + 1) < len) ? (((LONG)strIn[i + 1]) << 8) : 0) | (((i + 2) < len) ? ((LONG)strIn[i + 2]) : 0);

        strOut += base64ABC[(l >> 18) & 0x3F];
        strOut += base64ABC[(l >> 12) & 0x3F];
        if (i + 1 < len) strOut += base64ABC[(l >> 6) & 0x3F];
        if (i + 2 < len) strOut += base64ABC[(l) & 0x3F];
    }
    switch (len % 3) 
    {
    case 1:
        strOut += '=';
    case 2:
        strOut += '=';
    }
}
Posted
Updated 17-May-23 4:37am
Comments
CPallini 16-May-23 6:08am    
But...
Why?

The issue is about encoding either an ASCCI or UTF16 string. The following code shows examples of both types, and will print the results.
C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* base64_encode(const unsigned char* strIn, int strLen)
{
    const static char* base64ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    size_t outlen = ((strLen + 3) / 3 * 4 + 1) * 2;
    char* strOut = (char*)malloc(outlen + 2);
    char* pOut = strOut;
    for (size_t i = 0; i < strLen; i += 3)
    {
        long l = (((long)strIn[i]) << 16) | (((i + 1) < strLen) ? (((long)strIn[i + 1]) << 8) : 0) | (((i + 2) < strLen) ? ((long)strIn[i + 2]) : 0);

        *pOut++ = base64ABC[(l >> 18) & 0x3F];
        *pOut++ = base64ABC[(l >> 12) & 0x3F];
        if (i + 1 < strLen) *pOut++ = base64ABC[(l >> 6) & 0x3F];
        if (i + 2 < strLen) *pOut++ = base64ABC[l & 0x3F];
    }
    switch (strLen % 3)
    {
    case 1:
        *pOut++ = '=';
    case 2:
        *pOut++ = '=';
    }
    *pOut = L'\0';

    return strOut;
}

int main() {
    const char* ascii = "Hello, world!";    // ASCII source
    char* encodedA = base64_encode((const unsigned char*)ascii, strlen(ascii));
    if (encodedA != NULL) {
        printf("Base64 ASCII: %s\n", encodedA);
        free(encodedA);
    }
    const wchar_t* utf16 = L"Hello, world!";
    int len = wcslen(utf16) * 2;
    char* encodedU = base64_encode((const unsigned char*)utf16, len);
    if (encodedU != NULL) {
        printf("Base64 UTF16: %s\n", encodedU);
        free(encodedU);
    }
    return 0;
}
 
Share this answer
 
v3
Comments
Drakesal 16-May-23 8:41am    
Hi and excuse me for late response

I tried this solution but return me always the same chars
Richard MacCutchan 16-May-23 8:57am    
Yes, but they are UTF16 characters. Is that not what you are asking for?
Drakesal 16-May-23 9:06am    
powershell [convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes(string)

i need this in C where Unicode = UTF16BE
Drakesal 16-May-23 9:09am    
if you go to the site https://the-x.cn/en-US/base64

and put Hello, World! you obtain -> SABlAGwAbABvACwAIABXAG8AcgBsAGQAIQA=
Richard MacCutchan 16-May-23 9:10am    
Sorry, you need to explain exactly how that value is generated.
Please try with the below code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

char* utf16be_base64_encode(const char* input) {
size_t input_len = strlen(input);
size_t output_len = ((input_len * 2 + 1) / 3) * 4 + 1;
char* output = (char*)malloc(output_len);
if (output == NULL) {
printf("Memory allocation failed.\n");
return NULL;
}

size_t i, j;
uint32_t val = 0;
uint8_t bytes[3];
size_t output_pos = 0;

for (i = 0; i < input_len; i += 2) {
bytes[0] = (uint8_t)input[i];
bytes[1] = (uint8_t)input[i + 1];
val = (bytes[0] << 8) | bytes[1];

for (j = 0; j < 4; ++j) {
output[output_pos++] = base64_table[(val >> 18) & 0x3F];
val <<= 6;
}
}

if (input_len % 2 != 0) {
bytes[0] = (uint8_t)input[input_len - 1];
bytes[1] = 0;
val = (bytes[0] << 8) | bytes[1];
for (j = 0; j < 3; ++j) {
output[output_pos++] = base64_table[(val >> 18) & 0x3F];
val <<= 6;
}
output[output_pos++] = '=';
}

output[output_pos] = '\0';
return output;
}

int main() {
const char* input = "Hello, world!";
char* encoded = utf16be_base64_encode(input);
if (encoded != NULL) {
printf("Base64 (UTF-16BE): %s\n", encoded);
free(encoded);
}

return 0;
}
 
Share this answer
 
Comments
Drakesal 16-May-23 5:52am    
For the moment thanks for the fast response :)

I tried your code and compared with site https://dencode.com/string/base64

so result for "Hello, World!" is:
site: SABlAGwAbABvACwAIABXAG8AcgBsAGQAIQA=
code: AEhlAGxsAG8sACBXAG9yAGxkACEAACE=

there is something to tune
Richard MacCutchan 16-May-23 5:54am    
This code does not produce UTF16 characters.
Hi I have the complete solution:

bool CrypttoBase64Encode(BYTE* pbSource, DWORD dwSourceLength, CString& sBase64)
{
    bool bResult = false;
    DWORD dwDestLength = 0;
    LPTSTR psDest = NULL;
    if (CryptBinaryToString(pbSource, dwSourceLength, CRYPT_STRING_BASE64, NULL, &dwDestLength) == TRUE)
    {
        psDest = new TCHAR[dwDestLength + 1];
        if (CryptBinaryToString(pbSource, dwSourceLength, CRYPT_STRING_BASE64, psDest, &dwDestLength) == TRUE)
        {
            sBase64 = CString(psDest);
            sBase64 = sBase64.Left(sBase64.GetLength() - 2);
            bResult = true;
        }
        delete[] psDest;
    }
    return bResult;
}

int main()
{
    CString s = _T("Hello, world!");

    LPBYTE pByte = new BYTE[(s.GetLength()) * 2];
    memcpy(pByte, s, (s.GetLength()) * 2);

    CrypttoBase64Encode(pByte, (s.GetLength()) * 2, s);

    delete[] pByte;

    return 0;
}


With this you obtain a complete string encoding in UTF16 LE (unicode)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900