base 64 编解码
1. base64的编码都是按字符串长度,以每3个8bit的字符为一组,
2. 然后针对每组,首先获取每个字符的ASCII编码,
3. 然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节
4. 然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节
5. 然后将这4个8bit的字节转换成10进制,对照Base64编码表 (下表),得到对应编码后的字符。
实现:
////////////////////////////////////////////////////////////////////// // // base64 Encoding/Decoding: // Encoding: String2Base64: unsigned char * to base64; // Decoding: Base642TString: base64 to unsigned char * . // // xuhh // Dec 11, 2014 // ////////////////////////////////////////////////////////////////////// #if !defined(_MIME_CODING_H) #define _MIME_CODING_H #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <utility> #include <string> #include <list> using namespace std; #if !defined(ASSERT) #if defined(_DEBUG) #include <assert.h> #define ASSERT(exp) assert(exp) #else #define ASSERT(exp) ((void)0) #endif #endif #if defined(_DEBUG) && !defined(DEBUG_NEW) #define DEBUG_NEW new #endif // maximum length of an encoded line (RFC 2045) #define MAX_MIME_LINE_LEN 76 #define MAX_ENCODEDWORD_LEN 75 ////////////////////////////////////////////////////////////////////// // string to base64 extern unsigned char * String2Base64(const char* str); ////////////////////////////////////////////////////////////////////// // base64 to string extern unsigned char * Base642TString(const char* str); ////////////////////////////////////////////////////////////////////// // CMimeEnvironment - global environment to manage encoding/decoding class CMimeCodeBase; #define DECLARE_MIMECODER(class_name) public: static CMimeCodeBase* CreateObject() { return new class_name; } ////////////////////////////////////////////////////////////////////// // CMimeCodeBase class CMimeCodeBase { public: CMimeCodeBase() : m_pbInput(NULL), m_nInputSize(0), m_bIsEncoding(false) {} public: void SetInput(const char* pbInput, int nInputSize, bool bEncoding) { m_pbInput = (const unsigned char*) pbInput; m_nInputSize = nInputSize; m_bIsEncoding = bEncoding; } int GetOutputLength() const { return m_bIsEncoding ? GetEncodeLength() : GetDecodeLength(); } int GetOutput(unsigned char* pbOutput, int nMaxSize) { return m_bIsEncoding ? Encode(pbOutput, nMaxSize) : Decode(pbOutput, nMaxSize); } protected: // overrides virtual int GetEncodeLength() const { return m_nInputSize; } virtual int GetDecodeLength() const { return m_nInputSize; } virtual int Encode(unsigned char* pbOutput, int nMaxSize) const { int nSize = min(nMaxSize, m_nInputSize); ::memcpy(pbOutput, m_pbInput, nSize); return nSize; } virtual int Decode(unsigned char* pbOutput, int nMaxSize) { return CMimeCodeBase::Encode(pbOutput, nMaxSize); } protected: const unsigned char* m_pbInput; int m_nInputSize; bool m_bIsEncoding; }; ////////////////////////////////////////////////////////////////////// // CMimeCodeBase64 - for base64 encoding mechanism class CMimeCodeBase64 : public CMimeCodeBase { public: CMimeCodeBase64() : m_bAddLineBreak(true) {} public: DECLARE_MIMECODER(CMimeCodeBase64) void AddLineBreak(bool bAdd=true) { m_bAddLineBreak = bAdd; } protected: virtual int GetEncodeLength() const; virtual int GetDecodeLength() const; virtual int Encode(unsigned char* pbOutput, int nMaxSize) const; virtual int Decode(unsigned char* pbOutput, int nMaxSize); private: bool m_bAddLineBreak; private: static inline int DecodeBase64Char(unsigned int nCode) { if (nCode >= 'A' && nCode <= 'Z') return nCode - 'A'; if (nCode >= 'a' && nCode <= 'z') return nCode - 'a' + 26; if (nCode >= '0' && nCode <= '9') return nCode - '0' + 52; if (nCode == '+') return 62; if (nCode == '/') return 63; return 64; } }; #endif // !defined(_MIME_CODING_H)
实现文件:
////////////////////////////////////////////////////////////////////// // // base64 Encoding/Decoding: // Encoding: String2Base64: unsigned char * to base64; // Decoding: Base642TString: base64 to unsigned char * . // // xuhh // Dec 11, 2014 // ////////////////////////////////////////////////////////////////////// #include "MimeCode.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////////// // string to base64 unsigned char* String2Base64(const char * szStr) { CMimeCodeBase64 base64; base64.SetInput(szStr, strlen(szStr), true); int nLen = base64.GetOutputLength()+1; unsigned char* pOutput = new unsigned char[nLen]; nLen = base64.GetOutput(pOutput, nLen); pOutput[nLen] = 0; return pOutput; } ////////////////////////////////////////////////////////////////////////// // base64 to string unsigned char * Base642TString(const char* str) { CMimeCodeBase64 base64; base64.SetInput(str, strlen(str), false); int len = base64.GetOutputLength()+1; unsigned char* pOutput = new unsigned char[len]; len = base64.GetOutput(pOutput, len); pOutput[len] = 0; return pOutput; } ////////////////////////////////////////////////////////////////////// // CMimeCodeBase64 int CMimeCodeBase64::GetEncodeLength() const { int nLength = (m_nInputSize + 2) / 3 * 4; if (m_bAddLineBreak) nLength += (nLength / MAX_MIME_LINE_LEN + 1) * 2; return nLength; } int CMimeCodeBase64::GetDecodeLength() const { return m_nInputSize * 3 / 4 + 2; } int CMimeCodeBase64::Encode(unsigned char* pbOutput, int nMaxSize) const { static const char* s_Base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned char* pbOutStart = pbOutput; unsigned char* pbOutEnd = pbOutput + nMaxSize; int nFrom, nLineLen = 0; unsigned char chHigh4bits = 0; for (nFrom=0; nFrom<m_nInputSize; nFrom++) { if (pbOutput >= pbOutEnd) break; unsigned char ch = m_pbInput[nFrom]; switch (nFrom % 3) { case 0: *pbOutput++ = s_Base64Table[ch >> 2]; chHigh4bits = (ch << 4) & 0x30; break; case 1: *pbOutput++ = s_Base64Table[chHigh4bits | (ch >> 4)]; chHigh4bits = (ch << 2) & 0x3c; break; default: *pbOutput++ = s_Base64Table[chHigh4bits | (ch >> 6)]; if (pbOutput < pbOutEnd) { *pbOutput++ = s_Base64Table[ch & 0x3f]; nLineLen++; } } nLineLen++; if (m_bAddLineBreak && nLineLen >= MAX_MIME_LINE_LEN && pbOutput+2 <= pbOutEnd) { *pbOutput++ = '\r'; *pbOutput++ = '\n'; nLineLen = 0; } } if (nFrom % 3 != 0 && pbOutput < pbOutEnd) // 不足三位,= 补足 { *pbOutput++ = s_Base64Table[chHigh4bits]; int nPad = 4 - (nFrom % 3) - 1; if (pbOutput+nPad <= pbOutEnd) { ::memset(pbOutput, '=', nPad); pbOutput += nPad; } } if (m_bAddLineBreak && nLineLen != 0 && pbOutput+2 <= pbOutEnd) { *pbOutput++ = '\r'; *pbOutput++ = '\n'; } return (int)(pbOutput - pbOutStart); } int CMimeCodeBase64::Decode(unsigned char* pbOutput, int nMaxSize) { const unsigned char* pbData = m_pbInput; const unsigned char* pbEnd = m_pbInput + m_nInputSize; unsigned char* pbOutStart = pbOutput; unsigned char* pbOutEnd = pbOutput + nMaxSize; int nFrom = 0; unsigned char chHighBits = 0; while (pbData < pbEnd) { if (pbOutput >= pbOutEnd) break; unsigned char ch = *pbData++; if (ch == '\r' || ch == '\n') continue; ch = (unsigned char) DecodeBase64Char(ch); if (ch >= 64) // invalid encoding, or trailing pad '=' break; switch ((nFrom++) % 4) { case 0: chHighBits = ch << 2; break; case 1: *pbOutput++ = chHighBits | (ch >> 4); chHighBits = ch << 4; break; case 2: *pbOutput++ = chHighBits | (ch >> 2); chHighBits = ch << 6; break; default: *pbOutput++ = chHighBits | ch; } } return (int)(pbOutput - pbOutStart); }
时间: 2024-10-25 03:22:58