Leaked source code of windows server 2003
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.

337 lines
7.1 KiB

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