|
1 /* |
|
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Base64 encoding and decoding functions. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 /** |
|
23 @file |
|
24 */ |
|
25 |
|
26 #include "base64.h" |
|
27 |
|
28 // Constants used by the Base64 algorithm |
|
29 const TUint8 TBase64::iAlphabet[] = |
|
30 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; |
|
31 const TInt8 KImcvLookUpStartOffset = 43; |
|
32 const TUint8 KImcvConvEquals = '='; |
|
33 const TInt8 AsciiToBase64[80]= |
|
34 { |
|
35 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, |
|
36 57, 58, 59, 60, 61, -1, -1, -1, 64, -1, |
|
37 -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, |
|
38 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, |
|
39 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, |
|
40 -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, |
|
41 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, |
|
42 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 |
|
43 }; |
|
44 const TInt8 Base64ToAscii[65]= |
|
45 { |
|
46 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, |
|
47 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, |
|
48 85, 86, 87, 88, 89, 90, 97, 98, 99,100, |
|
49 101,102,103,104,105,106,107,108,109,110, |
|
50 111,112,113,114,115,116,117,118,119,120, |
|
51 121,122, 48, 49, 50, 51, 52, 53, 54, 55, |
|
52 56, 57, 43, 47, 61 |
|
53 }; |
|
54 |
|
55 EXPORT_C TBase64::TBase64() : |
|
56 iShiftStored(0), |
|
57 iMaskShiftStored(ESix) |
|
58 { |
|
59 } |
|
60 |
|
61 EXPORT_C void TBase64::Initialize() |
|
62 { |
|
63 iMaskShiftStored = ESix; |
|
64 } |
|
65 |
|
66 //Encodes data to Base64. |
|
67 EXPORT_C HBufC8* TBase64::EncodeLC(const TDesC8& aSrcString) |
|
68 { |
|
69 // Allocate and clear destination string |
|
70 TInt destLen = ((aSrcString.Length() - 1) / 3 + 1) * 4; |
|
71 HBufC8* destString = HBufC8::NewMaxLC(destLen); |
|
72 TPtr8 destPtr = destString->Des(); |
|
73 |
|
74 // Initialise variables |
|
75 const TUint8* srcStringPtr = aSrcString.Ptr(); |
|
76 const TUint8* srcStringEnd = aSrcString.Length() + srcStringPtr; |
|
77 TUint8* destStringPtr = (TUint8*)destString->Ptr(); |
|
78 TUint8* destStringPtrBase = destStringPtr; |
|
79 |
|
80 TInt character = 0; |
|
81 TUint8 encodedChar = 0; |
|
82 TInt charStorage = 0; |
|
83 TInt maskShift = EZero; |
|
84 |
|
85 while (srcStringPtr <= srcStringEnd) |
|
86 { |
|
87 // maskShift is used as a char read counter |
|
88 if(maskShift == ESix) |
|
89 { |
|
90 // If the 3rd char read is also the last char then the while loop |
|
91 // is broken on the next check. |
|
92 if(srcStringPtr == srcStringEnd) |
|
93 srcStringPtr++; |
|
94 maskShift = EZero; |
|
95 character = 0; |
|
96 } |
|
97 else |
|
98 { |
|
99 if (srcStringPtr == srcStringEnd) |
|
100 character=0; |
|
101 else |
|
102 character = *srcStringPtr; |
|
103 |
|
104 srcStringPtr++; |
|
105 // Shifts charStorage ready for the next char |
|
106 charStorage = charStorage << 8; |
|
107 maskShift += ETwo; |
|
108 } |
|
109 charStorage = charStorage | character; |
|
110 // Shifts the mask to the correct bit location |
|
111 // Masks (AND's) the valid bits from charStorage |
|
112 // Shifts the valid bits into the low order 8bits |
|
113 // Converts to BASE64 char, Casts the result to an unsigned |
|
114 // char (which it should be ?....I hope) |
|
115 encodedChar = (TUint8)Base64ToAscii[((charStorage >> maskShift) & ESixBitMask)]; |
|
116 *destStringPtr++ = encodedChar; |
|
117 } |
|
118 |
|
119 // Check for not enough chars and pad if required |
|
120 if (maskShift == EFour) |
|
121 { |
|
122 *destStringPtr++ = KImcvConvEquals; |
|
123 *destStringPtr++ = KImcvConvEquals; |
|
124 } |
|
125 else |
|
126 if (maskShift == ESix) |
|
127 *destStringPtr++ = KImcvConvEquals; |
|
128 |
|
129 destPtr.SetLength((TInt)(destStringPtr - destStringPtrBase)); |
|
130 return destString; |
|
131 } |
|
132 |
|
133 //Decodes Base64-encoded data. |
|
134 EXPORT_C HBufC8* TBase64::DecodeLC(const TDesC8& aSrcString, TBool& aNeedMoreData) |
|
135 { |
|
136 // The source string must be a multiple of 4 bytes long |
|
137 if (aSrcString.Length() & 0x3) |
|
138 { |
|
139 User::Leave(KErrCorrupt); |
|
140 } |
|
141 |
|
142 TInt decodedInt = 0; |
|
143 TInt8 offsetChar = 0; |
|
144 TUint8 decodedChar = 0; |
|
145 |
|
146 // Find out how long the decoded string will be. |
|
147 TInt outLen = aSrcString.Length() / 4 * 3; |
|
148 if (aSrcString[aSrcString.Length() - 1] == '=') |
|
149 outLen--; |
|
150 if (aSrcString[aSrcString.Length() - 2] == '=') |
|
151 outLen--; |
|
152 |
|
153 // Construct output buffer. |
|
154 HBufC8* destString = HBufC8::NewMaxLC(outLen); |
|
155 TPtr8 destPtr = destString->Des(); |
|
156 destPtr.Zero(); |
|
157 |
|
158 // Initialise variables |
|
159 const TUint8* srcStringPtr = aSrcString.Ptr(); |
|
160 const TUint8* srcStringEnd = aSrcString.Length() + srcStringPtr; |
|
161 TUint8* destStringPtr = (TUint8*)destString->Ptr(); |
|
162 TUint8* destStringPtrBase = destStringPtr; |
|
163 TInt maskShift = iMaskShiftStored; |
|
164 TInt shiftStorage = iShiftStored; |
|
165 |
|
166 // Main character process loop |
|
167 while (srcStringPtr<srcStringEnd) |
|
168 { |
|
169 offsetChar = (TInt8)(*srcStringPtr - KImcvLookUpStartOffset); |
|
170 srcStringPtr++; |
|
171 |
|
172 // Check for valid B64 character |
|
173 if ((offsetChar >= 0) && (offsetChar < 80)) |
|
174 { |
|
175 // Read in next character and B64 decode |
|
176 decodedInt = AsciiToBase64[offsetChar]; |
|
177 |
|
178 // Exits when a PAD char is reached |
|
179 if(decodedInt == EPadChar) |
|
180 { |
|
181 destPtr.SetLength((TInt)(destStringPtr - destStringPtrBase)); |
|
182 aNeedMoreData = EFalse; |
|
183 return destString; |
|
184 } |
|
185 |
|
186 // Ensures the first 2 chars of 4 are received before processing |
|
187 if(maskShift == ESix) |
|
188 maskShift = EFour; |
|
189 else |
|
190 { |
|
191 shiftStorage = shiftStorage << ESix; |
|
192 shiftStorage = shiftStorage | decodedInt; |
|
193 decodedChar = (TUint8)((shiftStorage >> maskShift) & EEightBitMask); |
|
194 |
|
195 if((maskShift -= ETwo) < EZero) |
|
196 maskShift = ESix; |
|
197 |
|
198 *destStringPtr++ = decodedChar; |
|
199 } |
|
200 shiftStorage = decodedInt; |
|
201 } |
|
202 } |
|
203 iShiftStored = shiftStorage; |
|
204 iMaskShiftStored = maskShift; |
|
205 |
|
206 destPtr.SetLength((TInt)(destStringPtr - destStringPtrBase)); |
|
207 aNeedMoreData = maskShift < ESix; |
|
208 return destString; |
|
209 } |
|
210 |