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.

191 lines
5.5 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: base64.cxx
  7. //
  8. // Contents: Contains the implementation of base64 encoding.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include <ctype.h>
  12. #include "cadsxml.hxx"
  13. #define NL_STR "\r\n"
  14. #define NL_STR_LEN 2
  15. #define OCTETS_PER_GROUP 3
  16. #define SEXTETS_PER_GROUP 4
  17. #define BASE64_PAD_CHAR '='
  18. #define BASE64_PAD_INDEX 64
  19. /* NOTE: the pad character base64Alphabet[BASE64_PAD_INDEX] doesn't */
  20. /* really belong the strict definition of the Base64 character set */
  21. static
  22. char base64Alphabet[65] = {
  23. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  24. 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  25. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  26. 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  27. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='
  28. };
  29. //---------------------------------------------------------------------------
  30. // Function: encodeGroup
  31. //
  32. // Synopsis: Performs base64 encoding of a group of 3 bytes.
  33. //
  34. // Arguments:
  35. //
  36. // inBufPtr Pointer to data to encode
  37. // encodeBufPtr Encoded data
  38. // inBufLen Number of bytes in inBufPtr
  39. //
  40. // Returns: Number of encoded sextets
  41. //
  42. // Modifies: encodeBufPtr to store the encoded data.
  43. //
  44. //--------------------------------------------------------------------------
  45. static int encodeGroup (
  46. char *inBufPtr, /* input buffer to encode (3 8-bit octets) */
  47. char *encodeBufPtr, /* encode buffer (4 6-bit sextets) */
  48. int inBufLen )
  49. {
  50. int i;
  51. unsigned char octet;
  52. if (inBufLen > OCTETS_PER_GROUP)
  53. return(0);
  54. /* perform base64 encoding (convert 3 8-bit groups to 4 6-bit groups) */
  55. memset(encodeBufPtr, 0, SEXTETS_PER_GROUP);
  56. for (i=0; i<inBufLen; i++) {
  57. octet = *(inBufPtr + i);
  58. switch (i) {
  59. case 0:
  60. *encodeBufPtr = (char)(octet >> 2);
  61. *(encodeBufPtr+1) |= (char)((octet & 0x3) << 4);
  62. break;
  63. case 1:
  64. *(encodeBufPtr+1) |= (char)(octet >> 4);
  65. *(encodeBufPtr+2) |= (char)((octet & 0xf) << 2);
  66. break;
  67. case 2:
  68. *(encodeBufPtr+2) |= (char)(octet >> 6);
  69. *(encodeBufPtr+3) |= (char)(octet & 0x3f);
  70. break;
  71. }
  72. }
  73. /* perform padding for incomplete octet groups */
  74. switch (inBufLen) {
  75. case 1:
  76. *(encodeBufPtr+2) = BASE64_PAD_INDEX;
  77. /* the missing break is intentional! */
  78. case 2:
  79. *(encodeBufPtr+3) = BASE64_PAD_INDEX;
  80. break;
  81. default:
  82. break;
  83. }
  84. /* translate all base64 codes into characters from the base64 alphabet */
  85. for (i=0; i<SEXTETS_PER_GROUP; i++)
  86. *(encodeBufPtr+i) = base64Alphabet[ *(encodeBufPtr+i) ];
  87. return(SEXTETS_PER_GROUP); /* # of encoded sextets (incldg padding) */
  88. }
  89. //--------------------------------------------------------------------------
  90. // Function: encodeBase64Buffer
  91. //
  92. // Synopsis: Encodes a data buffer using the "Base64" method.
  93. //
  94. // Arguments:
  95. //
  96. // inBufPtr points to input data
  97. // inBytesPtr points to number of bytes in inBufPtr
  98. // outBufPtr points to output area for encoded data
  99. // outBytesPtr points to size of outBufPtr
  100. // outLineLen number of base64 characters to output per
  101. // line (each line is <CR><LF> terminated)
  102. //
  103. // Returns : 0 if successful, -1 otherwise.
  104. //
  105. // Modifies: *inBytesPtr to return the number of bytes encoded.
  106. // *outBytesPtr to return number of bytes placed in outBufPtr.
  107. // outBufPtr returns the encoded data.
  108. //
  109. //--------------------------------------------------------------------------
  110. int encodeBase64Buffer (
  111. char *inBufPtr,
  112. int *inBytesPtr,
  113. WCHAR *outBufPtr,
  114. int *outBytesPtr,
  115. int outLineLen
  116. )
  117. {
  118. int i, ret, bytesToEncode, outBufSize, startOffset, encodeLen;
  119. int octetCount, lineCount, outOfSpace;
  120. char inBuf[OCTETS_PER_GROUP], encodeBuf[SEXTETS_PER_GROUP+NL_STR_LEN];
  121. char *ptr;
  122. bytesToEncode = *inBytesPtr;
  123. outBufSize = *outBytesPtr;
  124. *inBytesPtr = 0;
  125. *outBytesPtr = 0;
  126. if (bytesToEncode <= 0 || outBufSize <= 0)
  127. return(-1);
  128. startOffset = -1;
  129. octetCount = lineCount = outOfSpace = 0;
  130. for (i=0; i < bytesToEncode && !outOfSpace; i++) {
  131. ptr = inBufPtr + i;
  132. if (startOffset < 0)
  133. startOffset = i;
  134. inBuf[octetCount++] = *ptr;
  135. /* encode the octet group if sufficient octets have been accumulated */
  136. /* or if we're on the last byte */
  137. if (octetCount == OCTETS_PER_GROUP
  138. || (i == bytesToEncode-1)) {
  139. /* encode the input octet group into an sextet group */
  140. encodeLen = encodeGroup(inBuf, encodeBuf, octetCount);
  141. lineCount += encodeLen;
  142. if (lineCount >= outLineLen) {
  143. memcpy(&encodeBuf[encodeLen], NL_STR, NL_STR_LEN);
  144. encodeLen += NL_STR_LEN;
  145. lineCount = 0;
  146. }
  147. if (*outBytesPtr + encodeLen > outBufSize)
  148. outOfSpace = 1;
  149. else {
  150. /* write decoded octets to output buffer */
  151. ret = mbstowcs(outBufPtr + *outBytesPtr, encodeBuf, encodeLen);
  152. *outBytesPtr += encodeLen;
  153. *inBytesPtr += i - startOffset + 1;
  154. startOffset = -1;
  155. octetCount = 0;
  156. }
  157. }
  158. }
  159. // Null terminate output
  160. if(*outBytesPtr < outBufSize) {
  161. *(outBufPtr + *outBytesPtr) = L'\0';
  162. (*outBytesPtr)++;
  163. }
  164. return(0);
  165. }