|
@@ -0,0 +1,336 @@
|
|
|
+/************************************************
|
|
|
+* *
|
|
|
+* CBase64.cpp *
|
|
|
+* Base 64 de- and encoding class *
|
|
|
+* *
|
|
|
+* ============================================ *
|
|
|
+* *
|
|
|
+* This class was written on 28.05.2003 *
|
|
|
+* by Jan Raddatz [jan-raddatz@web.de] *
|
|
|
+* *
|
|
|
+* ============================================ *
|
|
|
+* *
|
|
|
+* Copyright (c) by Jan Raddatz *
|
|
|
+* This class was published @ codeguru.com *
|
|
|
+* 28.05.2003 *
|
|
|
+* *
|
|
|
+************************************************/
|
|
|
+#include "pch.h"
|
|
|
+#include "Base64.h"
|
|
|
+
|
|
|
+char CBase64Coder::ch64[] = {
|
|
|
+ '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', '+', '/', '='
|
|
|
+};
|
|
|
+
|
|
|
+CBase64Coder::CBase64Coder()
|
|
|
+{
|
|
|
+ buf = NULL;
|
|
|
+ size = 0;
|
|
|
+}
|
|
|
+
|
|
|
+CBase64Coder::~CBase64Coder()
|
|
|
+{
|
|
|
+ if (buf)
|
|
|
+ {
|
|
|
+ free(buf);
|
|
|
+ buf = NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void CBase64Coder::allocMem(int NewSize)
|
|
|
+{
|
|
|
+ if (buf)
|
|
|
+ buf = (char*)realloc(buf, NewSize);
|
|
|
+ else
|
|
|
+ buf = (char*)malloc(NewSize);
|
|
|
+ memset(buf, 0, NewSize);
|
|
|
+}
|
|
|
+
|
|
|
+const char* CBase64Coder::encode(const string& buffer)
|
|
|
+{
|
|
|
+ return encode(buffer.c_str(), buffer.length());
|
|
|
+}
|
|
|
+
|
|
|
+const char* CBase64Coder::encode(const char* buffer, int buflen)
|
|
|
+{
|
|
|
+#ifdef _DEBUG
|
|
|
+ DWORD start, finish;
|
|
|
+ start = GetTickCount();
|
|
|
+#endif
|
|
|
+ int nLeft = 3 - buflen % 3;
|
|
|
+ //根据BASE64算法,总长度会变成原来的4/3倍
|
|
|
+ //所以内存分配=length*4/3并加1位作为结束符号(0)
|
|
|
+ size = calc_base64_len(buflen);
|
|
|
+ allocMem(size + 1);
|
|
|
+ //临时变量,
|
|
|
+ int index = 0;
|
|
|
+ char *pOut = buf;
|
|
|
+ while (buflen - index >= 3)
|
|
|
+ {
|
|
|
+ const char * p1 = buffer + index;
|
|
|
+ const char * p2 = p1 + 1;
|
|
|
+ const char * p3 = p2 + 1;
|
|
|
+
|
|
|
+ char c1 = ((*p1) & (0xFC)) >> 2;
|
|
|
+ char c2 = ((*p1) & (0x03)) << 4 | ((*p2) & 0xF0) >> 4;
|
|
|
+ char c3 = ((*p2) & (0x0F)) << 2 | ((*p3) & 0xC0) >> 6;
|
|
|
+ char c4 = (*p3) & (0x3F);
|
|
|
+
|
|
|
+ *(pOut++) = _getBase64Char(c1);
|
|
|
+ *(pOut++) = _getBase64Char(c2);
|
|
|
+ *(pOut++) = _getBase64Char(c3);
|
|
|
+ *(pOut++) = _getBase64Char(c4);
|
|
|
+
|
|
|
+ index += 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ int last = buflen - index;
|
|
|
+ if (last == 1)
|
|
|
+ {
|
|
|
+ const char * p1 = buffer + index;
|
|
|
+ char c1 = ((*p1) & (0xFC)) >> 2;
|
|
|
+ char c2 = ((*p1) & (0x03)) << 4;
|
|
|
+ *(pOut++) = _getBase64Char(c1);
|
|
|
+ *(pOut++) = _getBase64Char(c2);
|
|
|
+ *(pOut++) = '=';
|
|
|
+ *(pOut++) = '=';
|
|
|
+
|
|
|
+ }
|
|
|
+ else if (last == 2)
|
|
|
+ {
|
|
|
+ const char * p1 = buffer + index;
|
|
|
+ const char * p2 = p1 + 1;
|
|
|
+ char c1 = ((*p1) & (0xFC)) >> 2;
|
|
|
+ char c2 = ((*p1) & (0x03)) << 4 | ((*p2) & 0xF0) >> 4;
|
|
|
+ char c3 = ((*p2) & (0x0F)) << 2;
|
|
|
+
|
|
|
+ *(pOut++) = _getBase64Char(c1);
|
|
|
+ *(pOut++) = _getBase64Char(c2);
|
|
|
+ *(pOut++) = _getBase64Char(c3);
|
|
|
+ *(pOut++) = '=';
|
|
|
+ //*(pOut++)='=';
|
|
|
+ }
|
|
|
+#ifdef _DEBUG
|
|
|
+ finish = GetTickCount();
|
|
|
+ //TRACE("func Base64Encode spend %d ms\n", finish - start);
|
|
|
+#endif
|
|
|
+ return buf;
|
|
|
+}
|
|
|
+
|
|
|
+const char* CBase64Coder::decode(const char* buffer, int Length)
|
|
|
+{
|
|
|
+#ifdef _DEBUG
|
|
|
+ DWORD start, finish;
|
|
|
+ start = GetTickCount();
|
|
|
+#endif
|
|
|
+ int length = Length;
|
|
|
+ if (length % 4 != 0)
|
|
|
+ return NULL;
|
|
|
+ int nLen = calc_data_len(buffer,Length);
|
|
|
+ size = nLen;
|
|
|
+ allocMem(size + 1);
|
|
|
+
|
|
|
+ int dec = 0;
|
|
|
+ while (buffer[Length - 1 - dec] == '=')
|
|
|
+ {
|
|
|
+ dec++;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ int real_len = length - dec;
|
|
|
+ int index = 0;
|
|
|
+ char *pOut = buf;
|
|
|
+ while (real_len - index >= 4)
|
|
|
+ {
|
|
|
+ const char * p1 = buffer + index;
|
|
|
+ const char * p2 = p1 + 1;
|
|
|
+ const char * p3 = p2 + 1;
|
|
|
+ const char * p4 = p3 + 1;
|
|
|
+
|
|
|
+ char c1 = BinSearch(*p1);
|
|
|
+ if (c1 == -1)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ char c2 = BinSearch(*p2);
|
|
|
+ if (c2 == -1)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ char c3 = BinSearch(*p3);
|
|
|
+ if (c3 == -1)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ char c4 = BinSearch(*p4);
|
|
|
+ if (c4 == -1)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ *(pOut++) = (c1) << 2 | ((c2)&(0x30)) >> 4;
|
|
|
+ *(pOut++) = ((c2)&(0xF)) << 4 | ((c3)&(0x3C)) >> 2;
|
|
|
+ *(pOut++) = ((c3)&(0x03)) << 6 | (c4)&(0x3F);
|
|
|
+ index += 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ int last = real_len - index;
|
|
|
+ if (last == 2)
|
|
|
+ {
|
|
|
+ const char * p1 = buffer + index;
|
|
|
+ const char * p2 = p1 + 1;
|
|
|
+
|
|
|
+ char c1 = BinSearch(*p1);
|
|
|
+ char c2 = BinSearch(*p2);
|
|
|
+
|
|
|
+ *(pOut++) = (c1) << 2 | ((c2)&(0x30)) >> 4;
|
|
|
+
|
|
|
+ }
|
|
|
+ else if (last == 3)
|
|
|
+ {
|
|
|
+ const char * p1 = buffer + index;
|
|
|
+ const char * p2 = p1 + 1;
|
|
|
+ const char * p3 = p2 + 1;
|
|
|
+
|
|
|
+ char c1 = BinSearch(*p1);
|
|
|
+ char c2 = BinSearch(*p2);
|
|
|
+ char c3 = BinSearch(*p3);
|
|
|
+
|
|
|
+ *(pOut++) = (c1) << 2 | ((c2)&(0x30)) >> 4;
|
|
|
+ *(pOut++) = ((c2)&(0x0F)) << 4 | ((c3)&(0x30)) >> 2;
|
|
|
+ }
|
|
|
+#ifdef _DEBUG
|
|
|
+ finish = GetTickCount();
|
|
|
+ TRACE("func Base64Decode spend %d ms\n", finish - start);
|
|
|
+#endif
|
|
|
+ return buf;
|
|
|
+}
|
|
|
+
|
|
|
+//采用二分法查找p在ch64数组中的位置,并返回。如果找不到则返回-1
|
|
|
+int CBase64Coder::BinSearch(char p)
|
|
|
+{
|
|
|
+ /*if (p >= 'A' && p <= 'Z')
|
|
|
+ return (p - 'A');
|
|
|
+ else if (p >= 'a' && p <= 'z')
|
|
|
+ return (p - 'a' + 26);
|
|
|
+ else if (p >= '0' && p <= '9')
|
|
|
+ return (p - '0' + 26 + 26);
|
|
|
+ else if (p == '+')
|
|
|
+ return 62;
|
|
|
+ else if (p == '/')
|
|
|
+ return 63;
|
|
|
+ else if (p == '=')
|
|
|
+ return 64;*/
|
|
|
+ switch (p)
|
|
|
+ {
|
|
|
+ case 'A':
|
|
|
+ case 'B':
|
|
|
+ case 'C':
|
|
|
+ case 'D':
|
|
|
+ case 'E':
|
|
|
+ case 'F':
|
|
|
+ case 'G':
|
|
|
+ case 'H':
|
|
|
+ case 'I':
|
|
|
+ case 'J':
|
|
|
+ case 'K':
|
|
|
+ case 'L':
|
|
|
+ case 'M':
|
|
|
+ case 'N':
|
|
|
+ case 'O':
|
|
|
+ case 'P':
|
|
|
+ case 'Q':
|
|
|
+ case 'R':
|
|
|
+ case 'S':
|
|
|
+ case 'T':
|
|
|
+ case 'U':
|
|
|
+ case 'V':
|
|
|
+ case 'W':
|
|
|
+ case 'X':
|
|
|
+ case 'Y':
|
|
|
+ case 'Z':
|
|
|
+ return p - 'A';
|
|
|
+ case 'a':
|
|
|
+ case 'b':
|
|
|
+ case 'c':
|
|
|
+ case 'd':
|
|
|
+ case 'e':
|
|
|
+ case 'f':
|
|
|
+ case 'g':
|
|
|
+ case 'h':
|
|
|
+ case 'i':
|
|
|
+ case 'j':
|
|
|
+ case 'k':
|
|
|
+ case 'l':
|
|
|
+ case 'm':
|
|
|
+ case 'n':
|
|
|
+ case 'o':
|
|
|
+ case 'p':
|
|
|
+ case 'q':
|
|
|
+ case 'r':
|
|
|
+ case 's':
|
|
|
+ case 't':
|
|
|
+ case 'u':
|
|
|
+ case 'v':
|
|
|
+ case 'w':
|
|
|
+ case 'x':
|
|
|
+ case 'y':
|
|
|
+ case 'z':
|
|
|
+ return p - 'a' + 26;
|
|
|
+ case '0':
|
|
|
+ case '1':
|
|
|
+ case '2':
|
|
|
+ case '3':
|
|
|
+ case '4':
|
|
|
+ case '5':
|
|
|
+ case '6':
|
|
|
+ case '7':
|
|
|
+ case '8':
|
|
|
+ case '9':
|
|
|
+ return p - '0' + 52;
|
|
|
+ case '+':
|
|
|
+ return 62;
|
|
|
+ case '/':
|
|
|
+ return 63;
|
|
|
+ case '=':
|
|
|
+ return 64;
|
|
|
+
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+int CBase64Coder::calc_base64_len(int data_len)
|
|
|
+{
|
|
|
+ int last = data_len * 8 % 6;
|
|
|
+ if (last == 0)
|
|
|
+ {
|
|
|
+ return data_len * 8 / 6;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int base64_len = data_len * 8 / 6 + 1;
|
|
|
+ base64_len += (last == 2 ? 2 : 1);
|
|
|
+ return base64_len;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int CBase64Coder::calc_data_len(const char * base64, int base64_len)
|
|
|
+{
|
|
|
+ int dec = 0;
|
|
|
+ while (base64[base64_len - 1 - dec] == '=')
|
|
|
+ {
|
|
|
+ dec++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ((base64_len - dec) * 6) / 8;
|
|
|
+}
|
|
|
+
|
|
|
+char CBase64Coder::_getBase64Char(char c)
|
|
|
+{
|
|
|
+ return ch64[c];
|
|
|
+}
|