Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

379 lines
9.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StdAfx.h"
#include "Base64.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif
namespace
{
char code[65] = {
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/','=' };
string encode(const char *pBuff, const ULONGLONG &len)
{
int textSize = len; //明文长度
int resultSize = (textSize + 2) / 3 * 4; //密文长度
char* pText = new char[textSize + 1]; //多开辟一个内存空间用于存储'\0'
char* pResult = new char[resultSize + 1]; //多开辟一个内存空间用于存储'\0'
::memset(pText, 0, sizeof(char) * (textSize + 1));
::memset(pResult, 0, sizeof(char) * (resultSize + 1));
::memcpy(pText, pBuff, sizeof(char) * (textSize + 1));
pText[textSize] = '\0';
pResult[resultSize] = '\0';
int textIndex = 0;//pText的下标
int resultIndex;//pResult的下标
//加密明文,但不包括密文的最后四个字符,因为明文长度可能不是 3 的整数倍,密文会以‘=’结尾
for (resultIndex = 0; resultIndex < resultSize - 4; resultIndex += 4, textIndex += 3)
{
char a, b, c;
a = pText[textIndex];
b = pText[textIndex + 1];
c = pText[textIndex + 2];
for (int i = 0; i < 4; i++)
{
int index;
switch (i)
{
case 0:index = (a >> 2 & 0x3F); break;
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
case 2:index = (b << 2 & 0x3C) | (c >> 6 & 0x03); break;
case 3:index = (c & 0x3F); break;
}
pResult[resultIndex + i] = code[index];
}
}
//判断明文剩余几个字符,并加密
if (textIndex == textSize - 1)//余一个字符,密文末尾有两个‘=’
{
char a, b;
a = pText[textIndex];
b = 0;
for (int j = 0; j < 4; j++)
{
int index;
switch (j)
{
case 0:index = (a >> 2 & 0x3F); break;
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
case 2:index = 64; break;
case 3:index = 64; break;
}
pResult[resultIndex + j] = code[index];
}
}
else if ((textIndex + 1) == textSize - 1)//余两个字符,密文末尾有一个‘=’
{
char a, b, c;
a = pText[textIndex];
b = pText[textIndex + 1];
c = 0;
for (int j = 0; j < 4; j++)
{
int index;
switch (j)
{
case 0:index = (a >> 2 & 0x3F); break;
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
case 2:index = (b << 2 & 0x3C) | (c >> 6 & 0x03); break;
case 3:index = 64; break;
}
pResult[resultIndex + j] = code[index];
}
}
else//是三的整数倍,密文末尾没有‘=’
{
char a, b, c;
a = pText[textIndex];
b = pText[textIndex + 1];
c = pText[textIndex + 2];
for (int j = 0; j < 4; j++)
{
int index;
switch (j)
{
case 0:index = (a >> 2 & 0x3F); break;
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
case 2:index = (b << 2 & 0x3C) | (c >> 6 & 0x03); break;
case 3:index = (c & 0x3F); break;
}
pResult[resultIndex + j] = code[index];
}
}
string strOut(pResult);
delete[] pText;
delete[] pResult;
pText = NULL;
pResult = NULL;
return strOut;
}
ULONGLONG decode(const string &ciphertext, char *&pResult)
{
int textSize = ciphertext.size();
if (textSize % 4 != 0)//Base64密文的长度应该是4的倍数
return 0;
int resultSize = textSize / 4 * 3;//明文的长度
char* pText = new char[textSize + 1];
pResult = new char[resultSize + 1];
ciphertext.copy(pText, textSize, 0);
pText[textSize] = '\0';
pResult[resultSize] = '\0';
int textIndex = 0;//pText的下标
int resultIndex;//pResult的下标
int index[4];//存储字符在code种的位置
//解密密文,但不解密最后四个字符,因为密文最后四位可能包括‘=’
for (resultIndex = 0; resultIndex < resultSize - 3; resultIndex += 3, textIndex += 4)
{
for (int m = 0; m < 4; m++)
{
if (pText[textIndex + m] >= 'A' && pText[textIndex + m] <= 'Z')
{
index[m] = pText[textIndex + m] - 65;
}
else if (pText[textIndex + m] >= 'a' && pText[textIndex + m] <= 'z')
{
index[m] = pText[textIndex + m] - 71;
}
else if (pText[textIndex + m] >= '0' && pText[textIndex + m] <= '9')
{
index[m] = pText[textIndex + m] + 4;
}
else if (pText[textIndex + m] == '+')
{
index[m] = 62;
}
else if (pText[textIndex + m] == '/')
{
index[m] = 63;
}
else //如果密文包括其他字符则不是正确的Base64编码
{
delete[] pText;
delete[] pResult;
pText = pResult = NULL;
return 0;
}
}
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
pResult[resultIndex + 1] = (index[1] << 4 & 0xF0) | (index[2] >> 2 & 0x0F);
pResult[resultIndex + 2] = (index[2] << 6 & 0xC0) | index[3];
}
//处理密文的最后四位
for (int m = 0; m < 4; m++)
{
if (pText[textIndex + m] >= 'A' && pText[textIndex + m] <= 'Z')
{
index[m] = pText[textIndex + m] - 65;
}
else if (pText[textIndex + m] >= 'a' && pText[textIndex + m] <= 'z')
{
index[m] = pText[textIndex + m] - 71;
}
else if (pText[textIndex + m] >= '0' && pText[textIndex + m] <= '9')
{
index[m] = pText[textIndex + m] + 4;
}
else if (pText[textIndex + m] == '+')
{
index[m] = 62;
}
else if (pText[textIndex + m] == '/')
{
index[m] = 63;
}
else if (pText[textIndex + m] == '=')
{
index[m] = 64;
}
else
{
delete[] pText;
delete[] pResult;
pText = pResult = NULL;
return 0;
}
}
if (index[2] == 64)//密文末尾有两个 =
{
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
pResult[resultIndex + 1] = '\0';
pResult[resultIndex + 2] = '\0';
}
else if (index[3] == 64)//密文末尾有一个 =
{
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
pResult[resultIndex + 1] = (index[1] << 4 & 0xF0) | (index[2] >> 2 & 0x0F);
pResult[resultIndex + 2] = '\0';
}
else//密文末尾没有 =
{
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
pResult[resultIndex + 1] = (index[1] << 4 & 0xF0) | (index[2] >> 2 & 0x0F);
pResult[resultIndex + 2] = (index[2] << 6 & 0xC0) | index[3];
}
delete[] pText;
pText = NULL;
return resultSize + 1;
}
}
string Base64::Encode(const char * pBuffer, const ULONGLONG & length)
{
return encode(pBuffer, length);
}
ULONGLONG Base64::Decode(const string & ciphertext, char *& pBuffer)
{
return decode(ciphertext, pBuffer);
}
std::string Base64::Encode(const std::string& plaintext)
{
int textSize=plaintext.size() * sizeof(char);
char* pText=new char[textSize];
::memcpy(pText, plaintext.data(), sizeof(char) * textSize);
string str = encode(pText, textSize);
delete[] pText;
pText = NULL;
return str;
}
std::string Base64::Decode(const std::string& ciphertext)
{
char *pBuff(NULL);
ULONGLONG len = decode(ciphertext, pBuff);
if (!pBuff) return "";
string str(pBuff);
delete[] pBuff;
return str;
}
string Base64::EncodeF2S(CFile * pFile)
{
pFile->SeekToBegin();
ULONGLONG len = pFile->GetLength();
char *psz = new char[len];
::memset(psz, 0, sizeof(char) * len);
pFile->Read(psz, len);
string str = encode(psz, len);
delete[] psz;
return str;
}
ULONGLONG Base64::DecodeS2F(const string& ciphertext, CFile * pFile)
{
char *pBuff(NULL);
ULONGLONG len = decode(ciphertext, pBuff);
if (!len || !pBuff) return 0L;
pFile->SetLength(0L);
pFile->SeekToBegin();
pFile->Write(pBuff, len);
delete[] pBuff;
pBuff = NULL;
return len;
}
wstring Base64::Encode(const wstring & plaintext)
{
// 先将 plaintext 转为 utf8
string plain = unicode2Ansii(plaintext.c_str(), CP_UTF8);
// 得到的 ss 为 ansii 编码,将其转为unicode
return ansii2Unicode(plain.c_str(), CP_ACP);
}
wstring Base64::EncodeF2W(CFile * pFile)
{
string cipher = EncodeF2S(pFile);
return ansii2Unicode(cipher.c_str(), CP_ACP);
}
wstring Base64::Decode(const wstring & ciphertext)
{
// 先将 ciphertext 转为 ansii
string cipher = unicode2Ansii(ciphertext.c_str(), CP_ACP);
string plain = Decode(cipher);
// 得到 plain 为utf8编码,将 plain 转为 unicode
return ansii2Unicode(plain.c_str(), CP_UTF8);
}
ULONGLONG Base64::DecodeW2F(const wstring & ciphertext, CFile * pFile)
{
// cipher 转为 ansii
string cipher = unicode2Ansii(ciphertext.c_str(), CP_ACP);
return DecodeS2F(cipher, pFile);
}
std::string Base64::unicode2Ansii(LPCTSTR psz, const DWORD & codePage)
{
if (!psz) return std::string("");
char *pBuffer;
int nLength;
int nLen;
nLen = (int)wcslen(psz);
nLength = ::WideCharToMultiByte(codePage, 0, psz, nLen, NULL, 0, 0, 0);
int rc = ::GetLastError();
pBuffer = new char[nLength + 1];
memset(pBuffer, 0, (nLength + 1) * sizeof(char));
::WideCharToMultiByte(codePage, 0, psz, nLen, pBuffer, nLength, 0, 0);
std::string str(pBuffer);
delete[] pBuffer;
return str;
}
std::wstring Base64::ansii2Unicode(LPCSTR psz, const DWORD & codePage)
{
if (!psz) return std::wstring(L"");
int nLength, nLen;
wchar_t *pBuffer;
nLen = (int)strlen(psz);
nLength = ::MultiByteToWideChar(codePage, 0, psz, nLen, NULL, 0);
pBuffer = new wchar_t[nLength + 1];
memset(pBuffer, 0, (nLength + 1) * sizeof(wchar_t));
::MultiByteToWideChar(codePage, 0, psz, nLen, (LPWSTR)pBuffer, nLength);
std::wstring wstr(pBuffer);
delete[] pBuffer;
return wstr;
}