base 64 编解码


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);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值