base64.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:13k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  *****************************************************************************
  3.  *
  4.  *
  5.  * Base64 conversion.
  6.  *
  7.  * Written by Alex Fedotov, posted at CodeGuru
  8.  * (http://codeguru.earthweb.com) with no copyright or restrictions on
  9.  * its use.  
  10.  *
  11.  *****************************************************************************
  12.  ****************************************************************************/
  13. #include "base64.h"
  14. #define _ASSERTE(exp) if ( !(exp) ) return -1
  15. #define _CrtIsValidPointer(ptr, len, x) (((ptr) != 0) && ((len) > 0))
  16. const char _b64_etbl[64] = {
  17.     'A','B','C','D',  'E','F','G','H', 'I','J','K','L',  'M','N','O','P',
  18.     'Q','R','S','T',  'U','V','W','X', 'Y','Z','a','b',  'c','d','e','f',
  19.     'g','h','i','j',  'k','l','m','n', 'o','p','q','r',  's','t','u','v',
  20.     'w','x','y','z',  '0','1','2','3', '4','5','6','7',  '8','9','+','/'
  21. };
  22. const char _b64_dtbl[128] = { 
  23.     0x40,0x40,0x40,0x40,  0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40,  0x40,0x40,0x40,0x40,
  24.     0x40,0x40,0x40,0x40,  0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40,  0x40,0x40,0x40,0x40,
  25.     0x40,0x40,0x40,0x40,  0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x3E,  0x40,0x40,0x40,0x3F,
  26.     0x34,0x35,0x36,0x37,  0x38,0x39,0x3A,0x3B, 0x3C,0x3D,0x40,0x40,  0x40,0x00,0x40,0x40,
  27.     
  28.     0x40,0x00,0x01,0x02,  0x03,0x04,0x05,0x06, 0x07,0x08,0x09,0x0A,  0x0B,0x0C,0x0D,0x0E,
  29.     0x0F,0x10,0x11,0x12,  0x13,0x14,0x15,0x16, 0x17,0x18,0x19,0x40,  0x40,0x40,0x40,0x40,
  30.     0x40,0x1A,0x1B,0x1C,  0x1D,0x1E,0x1F,0x20, 0x21,0x22,0x23,0x24,  0x25,0x26,0x27,0x28,
  31.     0x29,0x2A,0x2B,0x2C,  0x2D,0x2E,0x2F,0x30, 0x31,0x32,0x33,0x40,  0x40,0x40,0x40,0x40
  32. };
  33. //---------------------------------------------------------------------------
  34. // b64elen
  35. //
  36. //  Calculates length of base64-encoded string given size of binary data.
  37. //
  38. //  Parameters:
  39. //    cb - number of bytes of binary data
  40. //
  41. //  Returns:
  42. //    the length of base64-encoded string not including the terminating null
  43. //    character.
  44. //
  45. extern "C" long
  46. b64elen(
  47.     size_t cb
  48.     )
  49. {
  50.     return (cb + 2) / 3 * 4;
  51. }
  52. //---------------------------------------------------------------------------
  53. // b64dlen
  54. //
  55. //  Calculates size of binary data which will be produced after decoding of 
  56. //  base64-encoded string with specified length.
  57. //
  58. //  Parameters:
  59. //    cch - length of the string, not including terminating null character
  60. //
  61. //  Returns:
  62. //    the number of bytes of binary data.
  63. //
  64. extern "C" long
  65. b64dlen(
  66.     size_t cch
  67.     )
  68. {
  69.     return cch * 3 / 4 + (cch % 4); 
  70. }
  71. //---------------------------------------------------------------------------
  72. // strb64e
  73. //
  74. //  Converts a buffer with binary data into a base64-encoded string. The
  75. //  function does not store a null character at the end of the string.
  76. //
  77. //  Parameters:
  78. //    p   - pointer to a buffer with binary data
  79. //    cb  - size of the buffer in bytes
  80. //    psz - pointer to a buffer that receives encoded string
  81. //
  82. //  Returns:
  83. //    number of characters written into the output buffer.
  84. //
  85. //  Note:
  86. //    Required size of the output buffer can be determined as b64elen(cb).
  87. //
  88. extern "C" long
  89. strb64e(
  90.     const void * p, 
  91.     size_t cb, 
  92.     char * psz
  93.     )
  94. {
  95.     _ASSERTE(_CrtIsValidPointer(p, cb, 0));
  96.     _ASSERTE(_CrtIsValidPointer(psz, b64elen(cb), 1));
  97.     int i;
  98.     int rem = cb % 3;
  99.     int cbr = cb - rem;
  100.     _ASSERTE((cbr % 3) == 0);
  101.     char * qsz = psz;
  102.     const char * pb = (const char *)p;
  103.     register int dw;
  104.     // convert each three consequent bytes into four base64 characters
  105.     for (i = 0; i < cbr; i += 3, psz += 4)
  106.     {
  107. dw = ((unsigned char)pb[i]) << 16;
  108. dw |= ((unsigned char)pb[i + 1]) << 8;
  109. dw |= ((unsigned char)pb[i + 2]);
  110. psz[3] = _b64_etbl[dw & 0x3F]; dw >>= 6;
  111. psz[2] = _b64_etbl[dw & 0x3F]; dw >>= 6;
  112. psz[1] = _b64_etbl[dw & 0x3F]; dw >>= 6;
  113. psz[0] = _b64_etbl[dw & 0x3F];
  114.     }
  115.     // 0, 1, or 2 bytes can remain at the end of the input buffer; deal
  116.     // with each of these cases separately
  117.     switch (rem)
  118.     {
  119. case 2:
  120.     dw = ((unsigned char)pb[i]) << 8;
  121.     dw |= ((unsigned char)pb[i + 1]);
  122.     psz[3] = '=';
  123.     psz[2] = _b64_etbl[dw & 0x3F];  dw >>= 6;
  124.     psz[1] = _b64_etbl[dw & 0x3F];  dw >>= 6;
  125.     psz[0] = _b64_etbl[dw & 0x3F];
  126.     return qsz - psz + 4;
  127. case 1:
  128.     dw = ((unsigned char)pb[i]);
  129.     psz[3] = '=';
  130.     psz[2] = '=';
  131.     psz[1] = _b64_etbl[dw & 0x3F];  dw >>= 6;
  132.     psz[0] = _b64_etbl[dw & 0x3F];
  133.     return qsz - psz + 4;
  134. case 0:
  135.     return qsz - psz;
  136. default:
  137.     _ASSERTE(0);
  138.     // __assume(0);
  139.     }
  140. }
  141. //---------------------------------------------------------------------------
  142. // wcsb64e
  143. //
  144. //  Converts a buffer with binary data into a base64-encoded string. The
  145. //  function does not store a null character at the end of the string.
  146. //
  147. //  Parameters:
  148. //    p   - pointer to a buffer with binary data
  149. //    cb  - size of the buffer in bytes
  150. //    psz - pointer to a buffer that receives encoded string
  151. //
  152. //  Returns:
  153. //    number of characters written into the output buffer.
  154. //
  155. //  Note:
  156. //    Required size of the output buffer can be determined as b64elen(cb).
  157. //
  158. extern "C" long
  159. wcsb64e(
  160.     const void * p, 
  161.     size_t cb, 
  162.     wchar_t * psz
  163.     )
  164. {
  165.     _ASSERTE(_CrtIsValidPointer(p, cb, 0));
  166.     _ASSERTE(_CrtIsValidPointer(psz, b64elen(cb) * sizeof(wchar_t), 1));
  167.     int i;
  168.     int rem = cb % 3;
  169.     int cbr = cb - rem;
  170.     _ASSERTE((cbr % 3) == 0);
  171.     wchar_t * qsz = psz;
  172.     const char * pb = (const char *)p;
  173.     register int dw;
  174.     // convert each three consequent bytes into four base64 characters
  175.     for (i = 0; i < cbr; i += 3, psz += 4)
  176.     {
  177. dw = ((unsigned char)pb[i]) << 16;
  178. dw |= ((unsigned char)pb[i + 1]) << 8;
  179. dw |= ((unsigned char)pb[i + 2]);
  180. psz[3] = (wchar_t)_b64_etbl[dw & 0x3F]; dw >>= 6;
  181. psz[2] = (wchar_t)_b64_etbl[dw & 0x3F]; dw >>= 6;
  182. psz[1] = (wchar_t)_b64_etbl[dw & 0x3F]; dw >>= 6;
  183. psz[0] = (wchar_t)_b64_etbl[dw & 0x3F];
  184.     }
  185.     // 0, 1, or 2 bytes can remain at the end of the input buffer; deal
  186.     // with each of these cases separately
  187.     switch (rem)
  188.     {
  189. case 2:
  190.     dw = ((unsigned char)pb[i]) << 8;
  191.     dw |= ((unsigned char)pb[i + 1]);
  192.     psz[3] = L'=';
  193.     psz[2] = (wchar_t)_b64_etbl[dw & 0x3F]; dw >>= 6;
  194.     psz[1] = (wchar_t)_b64_etbl[dw & 0x3F]; dw >>= 6;
  195.     psz[0] = (wchar_t)_b64_etbl[dw & 0x3F];
  196.     return qsz - psz + 4;
  197. case 1:
  198.     dw = ((unsigned char)pb[i]);
  199.     psz[3] = L'=';
  200.     psz[2] = L'=';
  201.     psz[1] = (wchar_t)_b64_etbl[dw & 0x3F]; dw >>= 6;
  202.     psz[0] = (wchar_t)_b64_etbl[dw & 0x3F];
  203.     return qsz - psz + 4;
  204. case 0:
  205.     return qsz - psz;
  206. default:
  207.     _ASSERTE(0);
  208.     // __assume(0);
  209.     }
  210. }
  211. //---------------------------------------------------------------------------
  212. // strb64d
  213. //
  214. //  Converts a base64-encoded string into binary data. If the input string
  215. //  contains characters that are not allowed for base64, the contents of the
  216. //  output buffer is unpredictable.
  217. //
  218. //  Parameters:
  219. //    psz - pointer to a base64-encoded sting
  220. //    cch - number of characters in the string
  221. //    p   - pointer to a buffer that receives binary data
  222. //
  223. //  Returns:
  224. //    number of bytes stored into the output buffer.
  225. //
  226. //  Note:
  227. //    Required size of the output buffer can be determined as b64dlen(cch).
  228. //
  229. extern "C" long
  230. strb64d(
  231.     const char * psz, 
  232.     size_t cch, 
  233.     void * p
  234.     )
  235. {
  236.     _ASSERTE(_CrtIsValidPointer(psz, cch, 0));
  237.     _ASSERTE(_CrtIsValidPointer(p, b64dlen(cch), 1));
  238.     int i;
  239.     // ignore '=' characters that might appear at the end of the string
  240.     while (cch > 0 && psz[cch - 1] == '=')
  241. cch--;
  242.     int rem = cch & 3;
  243.     int cch4 = cch - rem;
  244.     char * pb = (char *)p;  
  245.     register int dw;
  246.     // convert each four consequtive base64 characters into three bytes
  247.     // of binary data
  248.     for (i = 0; i < cch4; i += 4, pb += 3)
  249.     {
  250. dw = _b64_dtbl[0x7F & psz[i]] << 18;
  251. dw |= _b64_dtbl[0x7F & psz[i + 1]] << 12;
  252. dw |= _b64_dtbl[0x7F & psz[i + 2]] << 6;
  253. dw |= _b64_dtbl[0x7F & psz[i + 3]];
  254. pb[2] = (unsigned char)dw;  dw >>= 8;
  255. pb[1] = (unsigned char)dw;  dw >>= 8;
  256. pb[0] = (unsigned char)dw;
  257.     }
  258.     // a few characters might remain at the end of the string
  259.     switch (rem)
  260.     {
  261. case 3:
  262.     dw = _b64_dtbl[0x7F & psz[i]] << 12;
  263.     dw |= _b64_dtbl[0x7F & psz[i + 1]] << 6;
  264.     dw |= _b64_dtbl[0x7F & psz[i + 2]];
  265.     //pb[2] = (unsigned char)dw;    dw >>= 8;
  266.     pb[1] = (unsigned char)dw; dw >>= 8;
  267.     pb[0] = (unsigned char)dw;
  268.     return pb - (char *)p + 2;
  269. case 2:
  270.     dw = _b64_dtbl[0x7F & psz[i]] << 6;
  271.     dw |= _b64_dtbl[0x7F & psz[i + 1]];
  272.     //pb[1] = (unsigned char)dw;    dw >>= 8;
  273.     pb[0] = (unsigned char)dw;
  274.     return pb - (char *)p + 1;
  275. case 1:
  276.     //pb[0] = _b64_dtbl[0x7F & psz[i]];
  277.     return pb - (char *)p;
  278. case 0:
  279.     return pb - (char *)p;
  280. default:
  281.     _ASSERTE(0);
  282.     // __assume(0);
  283.     }
  284. }
  285. //---------------------------------------------------------------------------
  286. // wcsb64d
  287. //
  288. //  Converts a base64-encoded string into binary data. If the input string
  289. //  contains characters that are not allowed for base64, the contents of the
  290. //  output buffer is unpredictable.
  291. //
  292. //  Parameters:
  293. //    psz - pointer to a base64-encoded sting
  294. //    cch - number of characters in the string
  295. //    p   - pointer to a buffer that receives binary data
  296. //
  297. //  Returns:
  298. //    number of bytes written into the output buffer.
  299. //
  300. //  Note:
  301. //    Required size of the output buffer can be determined as b64dlen(cch).
  302. //
  303. extern "C" long
  304. wcsb64d(
  305.     const wchar_t * psz, 
  306.     size_t cch, 
  307.     void * p
  308.     )
  309. {
  310.     _ASSERTE(_CrtIsValidPointer(psz, cch * sizeof(wchar_t), 0));
  311.     _ASSERTE(_CrtIsValidPointer(p, b64dlen(cch), 1));
  312.     int i;
  313.     // ignore '=' characters that might appear at the end of the string
  314.     while (cch > 0 && psz[cch - 1] == L'=')
  315. cch--;
  316.     int rem = cch & 3;
  317.     int cch4 = cch - rem;
  318.     char * pb = (char *)p;  
  319.     register int dw;
  320.     // convert each four consequtive base64 characters into three bytes
  321.     // of binary data
  322.     for (i = 0; i < cch4; i += 4, pb += 3)
  323.     {
  324. dw = _b64_dtbl[0x7F & psz[i]] << 18;
  325. dw |= _b64_dtbl[0x7F & psz[i + 1]] << 12;
  326. dw |= _b64_dtbl[0x7F & psz[i + 2]] << 6;
  327. dw |= _b64_dtbl[0x7F & psz[i + 3]];
  328. pb[2] = (unsigned char)dw;  dw >>= 8;
  329. pb[1] = (unsigned char)dw;  dw >>= 8;
  330. pb[0] = (unsigned char)dw;
  331.     }
  332.     // a few characters might remain at the end of the string
  333.     switch (rem)
  334.     {
  335. case 3:
  336.     dw = _b64_dtbl[0x7F & psz[i]] << 12;
  337.     dw |= _b64_dtbl[0x7F & psz[i + 1]] << 6;
  338.     dw |= _b64_dtbl[0x7F & psz[i + 2]];
  339.     //pb[2] = (unsigned char)dw;    dw >>= 8;
  340.     pb[1] = (unsigned char)dw; dw >>= 8;
  341.     pb[0] = (unsigned char)dw;
  342.     return pb - (char *)p + 2;
  343. case 2:
  344.     dw = _b64_dtbl[0x7F & psz[i]] << 6;
  345.     dw |= _b64_dtbl[0x7F & psz[i + 1]];
  346.     //pb[1] = (unsigned char)dw;    dw >>= 8;
  347.     pb[0] = (unsigned char)dw;
  348.     return pb - (char *)p + 1;
  349. case 1:
  350.     //pb[0] = _b64_dtbl[0x7F & psz[i]];
  351.     return pb - (char *)p;
  352. case 0:
  353.     return pb - (char *)p;
  354. default:
  355.     _ASSERTE(0);
  356.     // __assume(0);
  357.     }
  358. }
  359. //---------------------------------------------------------------------------
  360. // strisb64
  361. //
  362. //  Determines whether a string is a valid base64-encoded string.
  363. //
  364. //  Parameters:
  365. //    psz - pointer to a string
  366. //    cch - number of characters in the string
  367. //
  368. //  Returns:
  369. //    nonzero, if the string entirely consists of valid base64 characters,
  370. //    zero - otherwise.
  371. //
  372. extern "C" int
  373. strisb64(
  374.     const char * psz,
  375.     size_t cch
  376.     )
  377. {
  378.     _ASSERTE(_CrtIsValidPointer(psz, cch * sizeof(char), 0));
  379.     size_t i;
  380.     for (i = 0; (i < cch) && (psz[i] != '='); i++)
  381.     {
  382. if ((psz[i] & 0x80) != 0)
  383.     return 0;
  384. if (_b64_dtbl[psz[i]] == 0x40)
  385.     return 0;
  386.     }
  387.     if (i == cch)
  388. return 1;
  389.     if ((cch % 4) != 0)
  390. return 0;
  391.     switch (cch - i)
  392.     {
  393. case 2:
  394.     if (psz[i + 1] != '=')
  395. return 0;
  396. case 1:
  397. case 0:
  398.     break;
  399. default:
  400.     return 0;
  401.     }
  402.     return 1;
  403. }
  404. //---------------------------------------------------------------------------
  405. // wcsisb64
  406. //
  407. //  Determines whether a string is a valid base64-encoded string.
  408. //
  409. //  Parameters:
  410. //    psz - pointer to a string
  411. //    cch - number of characters in the string
  412. //
  413. //  Returns:
  414. //    nonzero, if the string entirely consists of valid base64 characters,
  415. //    zero - otherwise.
  416. //
  417. extern "C" int
  418. wcsisb64(
  419.     const wchar_t * psz,
  420.     size_t cch
  421.     )
  422. {
  423.     _ASSERTE(_CrtIsValidPointer(psz, cch * sizeof(wchar_t), 0));
  424.     size_t i;
  425.     for (i = 0; (i < cch) && (psz[i] != L'='); i++)
  426.     {
  427. if ((psz[i] & 0xFF80) != 0)
  428.     return 0;
  429. if (_b64_dtbl[psz[i]] == 0x40)
  430.     return 0;
  431.     }
  432.     if (i == cch)
  433. return 1;
  434.     if ((cch % 4) != 0)
  435. return 0;
  436.     switch (cch - i)
  437.     {
  438. case 2:
  439.     if (psz[i + 1] != L'=')
  440. return 0;
  441. case 1:
  442. case 0:
  443.     break;
  444. default:
  445.     return 0;
  446.     }
  447.     return 1;
  448. }