fixed the ContextMenuStash.png screenshot
[TortoiseGit.git] / src / Utils / CBase64.cpp
blob9bdcb9df95dbbacc33ce82e76781d9f960e84597
1 // Base64.cpp: implementation of the CBase64 class.
2 //
3 //////////////////////////////////////////////////////////////////////
5 #include "stdafx.h"
6 #include "CBase64.h"
8 #ifdef _DEBUG
9 #undef THIS_FILE
10 static char THIS_FILE[]=__FILE__;
11 #define new DEBUG_NEW
12 #endif
14 //////////////////////////////////////////////////////////////////////
15 // CBase64
16 //////////////////////////////////////////////////////////////////////
17 // Static Member Initializers
20 // The 7-bit alphabet used to encode binary information
21 const char m_sBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
23 const int f_nMask[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
25 CBase64::CBase64()
27 m_lBitStorage = 0;
28 m_nBitsRemaining = 0;
29 m_nInputSize = 0;
30 m_szInput = NULL;
33 CBase64::~CBase64()
37 CStringA CBase64::Encode( IN const char* szEncoding, IN int nSize )
39 CStringA sOutput = "";
40 int nNumBits = 6;
41 UINT nDigit;
42 int lp = 0;
43 int count = 0;
45 ASSERT( szEncoding != NULL );
46 if( szEncoding == NULL )
47 return sOutput;
48 m_szInput = szEncoding;
49 m_nInputSize = nSize;
51 m_nBitsRemaining = 0;
52 nDigit = read_bits( nNumBits, &nNumBits, lp );
53 while( nNumBits > 0 )
55 sOutput += m_sBase64Alphabet[ (int)nDigit ];
56 nDigit = read_bits( nNumBits, &nNumBits, lp );
57 count++;
59 if(count % 80 == 0)
60 sOutput += '\n';
62 // Pad with '=' as per RFC 1521
63 while( sOutput.GetLength() % 4 != 0 )
65 sOutput += '=';
67 return sOutput;
70 // The size of the output buffer must not be less than
71 // 3/4 the size of the input buffer. For simplicity,
72 // make them the same size.
73 // return : ½âÂëºóÊý¾Ý³¤¶È
74 int CBase64::Decode ( IN const char* szDecoding, char* szOutput )
76 CString sInput;
77 int c, lp =0;
78 int nDigit;
79 int nDecode[ 256 ];
81 ASSERT( szDecoding != NULL );
82 ASSERT( szOutput != NULL );
83 if( szOutput == NULL )
84 return 0;
85 if( szDecoding == NULL )
86 return 0;
87 sInput = szDecoding;
88 if( sInput.GetLength() == 0 )
89 return 0;
91 // Build Decode Table
93 int i;
94 for( i = 0; i < 256; i++ )
95 nDecode[i] = -2; // Illegal digit
96 for( i=0; i < 64; i++ )
98 nDecode[ m_sBase64Alphabet[ i ] ] = i;
99 nDecode[ m_sBase64Alphabet[ i ] | 0x80 ] = i; // Ignore 8th bit
100 nDecode[ '\r' ] = -1;
101 nDecode[ '\n' ] = -1;
102 nDecode[ '=' ] = -1;
103 nDecode[ '=' | 0x80 ] = -1; // Ignore MIME padding char
106 // Clear the output buffer
107 memset( szOutput, 0, sInput.GetLength() + 1 );
109 // Decode the Input
111 for( lp = 0, i = 0; lp < sInput.GetLength(); lp++ )
113 c = sInput[ lp ];
114 nDigit = nDecode[ c & 0x7F ];
115 if( nDigit < -1 )
117 return 0;
119 else if( nDigit >= 0 )
120 // i (index into output) is incremented by write_bits()
121 write_bits( nDigit & 0x3F, 6, szOutput, i );
123 return i;
126 UINT CBase64::read_bits(int nNumBits, int * pBitsRead, int& lp)
128 ULONG lScratch;
129 while( ( m_nBitsRemaining < nNumBits ) &&
130 ( lp < m_nInputSize ) )
132 int c = m_szInput[ lp++ ];
133 m_lBitStorage <<= 8;
134 m_lBitStorage |= (c & 0xff);
135 m_nBitsRemaining += 8;
137 if( m_nBitsRemaining < nNumBits )
139 lScratch = m_lBitStorage << ( nNumBits - m_nBitsRemaining );
140 *pBitsRead = m_nBitsRemaining;
141 m_nBitsRemaining = 0;
143 else
145 lScratch = m_lBitStorage >> ( m_nBitsRemaining - nNumBits );
146 *pBitsRead = nNumBits;
147 m_nBitsRemaining -= nNumBits;
149 return (UINT)lScratch & f_nMask[nNumBits];
153 void CBase64::write_bits(UINT nBits,
154 int nNumBits,
155 LPSTR szOutput,
156 int& i)
158 UINT nScratch;
160 m_lBitStorage = (m_lBitStorage << nNumBits) | nBits;
161 m_nBitsRemaining += nNumBits;
162 while( m_nBitsRemaining > 7 )
164 nScratch = m_lBitStorage >> (m_nBitsRemaining - 8);
165 szOutput[ i++ ] = nScratch & 0xFF;
166 m_nBitsRemaining -= 8;