Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
6.4 KiB

  1. // Base64Coder.cpp: implementation of the Base64Coder class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Base64.h"
  6. // Digits...
  7. static char Base64Digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  8. BOOL Base64Coder::m_Init = FALSE;
  9. char Base64Coder::m_DecodeTable[256];
  10. #ifndef PAGESIZE
  11. #define PAGESIZE 4096
  12. #endif
  13. #ifndef ROUNDTOPAGE
  14. #define ROUNDTOPAGE(a) (((a/4096)+1)*4096)
  15. #endif
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. Base64Coder::Base64Coder()
  20. : m_pDBuffer(NULL),
  21. m_pEBuffer(NULL),
  22. m_nDBufLen(0),
  23. m_nEBufLen(0)
  24. {
  25. }
  26. Base64Coder::~Base64Coder()
  27. {
  28. if(m_pDBuffer != NULL)
  29. delete [] m_pDBuffer;
  30. if(m_pEBuffer != NULL)
  31. delete [] m_pEBuffer;
  32. }
  33. LPCSTR Base64Coder::DecodedMessage() const
  34. {
  35. return (LPCSTR) m_pDBuffer;
  36. }
  37. LPCSTR Base64Coder::EncodedMessage() const
  38. {
  39. return (LPCSTR) m_pEBuffer;
  40. }
  41. void Base64Coder::DecodedMessage(PBYTE* ppBuffer, DWORD* nBufLen) const
  42. {
  43. *ppBuffer = m_pDBuffer;
  44. *nBufLen = m_nDDataLen;
  45. }
  46. void Base64Coder::AllocEncode(DWORD nSize)
  47. {
  48. if(m_nEBufLen < nSize)
  49. {
  50. if(m_pEBuffer != NULL)
  51. delete [] m_pEBuffer;
  52. m_nEBufLen = ROUNDTOPAGE(nSize);
  53. m_pEBuffer = new BYTE[m_nEBufLen];
  54. }
  55. if (m_pEBuffer != NULL)
  56. ::ZeroMemory(m_pEBuffer, m_nEBufLen);
  57. m_nEDataLen = 0;
  58. }
  59. void Base64Coder::AllocDecode(DWORD nSize)
  60. {
  61. if(m_nDBufLen < nSize)
  62. {
  63. if(m_pDBuffer != NULL)
  64. delete [] m_pDBuffer;
  65. m_nDBufLen = ROUNDTOPAGE(nSize);
  66. m_pDBuffer = new BYTE[m_nDBufLen];
  67. }
  68. if (m_pDBuffer != NULL)
  69. ::ZeroMemory(m_pDBuffer, m_nDBufLen);
  70. m_nDDataLen = 0;
  71. }
  72. void Base64Coder::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen)
  73. {
  74. DWORD i = 0;
  75. AllocEncode(nBufLen);
  76. while(i < nBufLen)
  77. {
  78. if(!_IsBadMimeChar(pBuffer[i]))
  79. {
  80. m_pEBuffer[m_nEDataLen] = pBuffer[i];
  81. m_nEDataLen++;
  82. }
  83. i++;
  84. }
  85. }
  86. void Base64Coder::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen)
  87. {
  88. AllocDecode(nBufLen);
  89. ::CopyMemory(m_pDBuffer, pBuffer, nBufLen);
  90. m_nDDataLen = nBufLen;
  91. }
  92. void Base64Coder::Encode(const PBYTE pBuffer, DWORD nBufLen)
  93. {
  94. SetDecodeBuffer(pBuffer, nBufLen);
  95. AllocEncode(nBufLen * 2);
  96. TempBucket Raw;
  97. DWORD nIndex = 0;
  98. while((nIndex + 3) <= nBufLen)
  99. {
  100. Raw.Clear();
  101. ::CopyMemory(&Raw, m_pDBuffer + nIndex, 3);
  102. Raw.nSize = 3;
  103. _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen);
  104. nIndex += 3;
  105. m_nEDataLen += 4;
  106. }
  107. if(nBufLen > nIndex)
  108. {
  109. Raw.Clear();
  110. Raw.nSize = (BYTE) (nBufLen - nIndex);
  111. ::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex);
  112. _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen);
  113. m_nEDataLen += 4;
  114. }
  115. }
  116. void Base64Coder::Encode(LPCSTR szMessage)
  117. {
  118. if(szMessage != NULL)
  119. Base64Coder::Encode((const PBYTE)szMessage, lstrlenA(szMessage));
  120. }
  121. void Base64Coder::Decode(const PBYTE pBuffer, DWORD dwBufLen)
  122. {
  123. if(!Base64Coder::m_Init)
  124. _Init();
  125. SetEncodeBuffer(pBuffer, dwBufLen);
  126. AllocDecode(dwBufLen);
  127. TempBucket Raw;
  128. DWORD nIndex = 0;
  129. while((nIndex + 4) <= m_nEDataLen)
  130. {
  131. Raw.Clear();
  132. Raw.nData[0] = Base64Coder::m_DecodeTable[m_pEBuffer[nIndex]];
  133. Raw.nData[1] = Base64Coder::m_DecodeTable[m_pEBuffer[nIndex + 1]];
  134. Raw.nData[2] = Base64Coder::m_DecodeTable[m_pEBuffer[nIndex + 2]];
  135. Raw.nData[3] = Base64Coder::m_DecodeTable[m_pEBuffer[nIndex + 3]];
  136. if(Raw.nData[2] == 255)
  137. Raw.nData[2] = 0;
  138. if(Raw.nData[3] == 255)
  139. Raw.nData[3] = 0;
  140. Raw.nSize = 4;
  141. _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen);
  142. nIndex += 4;
  143. m_nDDataLen += 3;
  144. }
  145. // If nIndex < m_nEDataLen, then we got a decode message without padding.
  146. // We may want to throw some kind of warning here, but we are still required
  147. // to handle the decoding as if it was properly padded.
  148. if(nIndex < m_nEDataLen)
  149. {
  150. Raw.Clear();
  151. for(DWORD i = nIndex; i < m_nEDataLen; i++)
  152. {
  153. Raw.nData[i - nIndex] = Base64Coder::m_DecodeTable[m_pEBuffer[i]];
  154. Raw.nSize++;
  155. if(Raw.nData[i - nIndex] == 255)
  156. Raw.nData[i - nIndex] = 0;
  157. }
  158. _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen);
  159. m_nDDataLen += (m_nEDataLen - nIndex);
  160. }
  161. }
  162. void Base64Coder::Decode(LPCSTR szMessage)
  163. {
  164. if(szMessage != NULL)
  165. Base64Coder::Decode((const PBYTE)szMessage, lstrlenA(szMessage));
  166. }
  167. DWORD Base64Coder::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer)
  168. {
  169. TempBucket Data;
  170. DWORD nCount = 0;
  171. _DecodeRaw(Data, Decode);
  172. for(int i = 0; i < 3; i++)
  173. {
  174. pBuffer[i] = Data.nData[i];
  175. if(pBuffer[i] != 255)
  176. nCount++;
  177. }
  178. return nCount;
  179. }
  180. void Base64Coder::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer)
  181. {
  182. TempBucket Data;
  183. _EncodeRaw(Data, Decode);
  184. for(int i = 0; i < 4; i++)
  185. pBuffer[i] = Base64Digits[Data.nData[i]];
  186. switch(Decode.nSize)
  187. {
  188. case 1:
  189. pBuffer[2] = '=';
  190. case 2:
  191. pBuffer[3] = '=';
  192. }
  193. }
  194. void Base64Coder::_DecodeRaw(TempBucket &Data, const TempBucket &Decode)
  195. {
  196. BYTE nTemp;
  197. Data.nData[0] = Decode.nData[0];
  198. Data.nData[0] <<= 2;
  199. nTemp = Decode.nData[1];
  200. nTemp >>= 4;
  201. nTemp &= 0x03;
  202. Data.nData[0] |= nTemp;
  203. Data.nData[1] = Decode.nData[1];
  204. Data.nData[1] <<= 4;
  205. nTemp = Decode.nData[2];
  206. nTemp >>= 2;
  207. nTemp &= 0x0F;
  208. Data.nData[1] |= nTemp;
  209. Data.nData[2] = Decode.nData[2];
  210. Data.nData[2] <<= 6;
  211. nTemp = Decode.nData[3];
  212. nTemp &= 0x3F;
  213. Data.nData[2] |= nTemp;
  214. }
  215. void Base64Coder::_EncodeRaw(TempBucket &Data, const TempBucket &Decode)
  216. {
  217. BYTE nTemp;
  218. Data.nData[0] = Decode.nData[0];
  219. Data.nData[0] >>= 2;
  220. Data.nData[1] = Decode.nData[0];
  221. Data.nData[1] <<= 4;
  222. nTemp = Decode.nData[1];
  223. nTemp >>= 4;
  224. Data.nData[1] |= nTemp;
  225. Data.nData[1] &= 0x3F;
  226. Data.nData[2] = Decode.nData[1];
  227. Data.nData[2] <<= 2;
  228. nTemp = Decode.nData[2];
  229. nTemp >>= 6;
  230. Data.nData[2] |= nTemp;
  231. Data.nData[2] &= 0x3F;
  232. Data.nData[3] = Decode.nData[2];
  233. Data.nData[3] &= 0x3F;
  234. }
  235. BOOL Base64Coder::_IsBadMimeChar(BYTE nData)
  236. {
  237. switch(nData)
  238. {
  239. case '\r': case '\n': case '\t': case ' ' :
  240. case '\b': case '\a': case '\f': case '\v':
  241. return TRUE;
  242. default:
  243. return FALSE;
  244. }
  245. }
  246. void Base64Coder::_Init()
  247. { // Initialize Decoding table.
  248. int i;
  249. for(i = 0; i < 256; i++)
  250. Base64Coder::m_DecodeTable[i] = -2;
  251. for(i = 0; i < 64; i++)
  252. {
  253. Base64Coder::m_DecodeTable[Base64Digits[i]] = (char)i;
  254. Base64Coder::m_DecodeTable[Base64Digits[i]|0x80] = (char)i;
  255. }
  256. Base64Coder::m_DecodeTable['='] = -1;
  257. Base64Coder::m_DecodeTable['='|0x80] = -1;
  258. Base64Coder::m_Init = TRUE;
  259. }