|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <e32base.h> |
|
17 #include <e32def.h> |
|
18 |
|
19 #include "BASE64.H" |
|
20 #include "BASE64DF.H" |
|
21 |
|
22 // |
|
23 // class CBase64CodecBase |
|
24 // |
|
25 // Provides 3 octet encoding and decoding alone |
|
26 // Returns an error code in the case of invalid source |
|
27 // |
|
28 |
|
29 void CBase64CodecBase::Reset() |
|
30 // |
|
31 // Reset the internal buffer |
|
32 { |
|
33 for (TInt i = 0; i < 4; i++) |
|
34 iQuart[i] = NULL; |
|
35 iQuartCount = 0; |
|
36 } |
|
37 |
|
38 |
|
39 TInt CBase64CodecBase::Encode(const TDesC8& aSource, TDes8& aResult) const |
|
40 // |
|
41 // Encode an arbitrary number of octets in aSource append the output to aResult. |
|
42 // If the number of octets in aSource is not a multiple of 3 |
|
43 // padding will be added terminating the encoding |
|
44 // |
|
45 { |
|
46 TInt sourceLength = aSource.Length(); |
|
47 if (sourceLength == 0) |
|
48 return KErrNone; |
|
49 __ASSERT_ALWAYS(((sourceLength * 4)/3 + sourceLength%3) <= (aResult.MaxLength()-aResult.Length()), Panic(EBase64Overflow)); |
|
50 |
|
51 sourceLength -= sourceLength%3; |
|
52 TUint8 sixBit=NULL; |
|
53 TText8 source; |
|
54 TInt i; |
|
55 |
|
56 for (i = 0; i < sourceLength; i++) |
|
57 { |
|
58 source=aSource[i]; |
|
59 sixBit = STATIC_CAST(TUint8,(source & 0xFC) >> 2); |
|
60 aResult.Append(KBase64Alphabet[sixBit]); |
|
61 sixBit = NULL; |
|
62 sixBit = STATIC_CAST(TUint8,(source & 0x03) << 4); |
|
63 source=aSource[++i]; |
|
64 sixBit |= STATIC_CAST(TUint8,(source & 0xF0) >> 4); |
|
65 aResult.Append(KBase64Alphabet[sixBit]); |
|
66 sixBit = NULL; |
|
67 sixBit = STATIC_CAST(TUint8,(source & 0x0F) << 2); |
|
68 source=aSource[++i]; |
|
69 sixBit |= STATIC_CAST(TUint8,(source & 0xC0) >> 6); |
|
70 aResult.Append(KBase64Alphabet[sixBit]); |
|
71 sixBit = NULL; |
|
72 sixBit = STATIC_CAST(TUint8,(source & 0x3F)); |
|
73 aResult.Append(KBase64Alphabet[sixBit]); |
|
74 } |
|
75 switch (aSource.Length() % 3) |
|
76 { |
|
77 case 2: |
|
78 source=aSource[i]; |
|
79 sixBit = STATIC_CAST(TUint8,(source & 0xFC) >> 2); |
|
80 aResult.Append(KBase64Alphabet[sixBit]); |
|
81 sixBit = NULL; |
|
82 sixBit = STATIC_CAST(TUint8,(source & 0x03) << 4); |
|
83 source=aSource[++i]; |
|
84 sixBit |= STATIC_CAST(TUint8,(source & 0xF0) >> 4); |
|
85 aResult.Append(KBase64Alphabet[sixBit]); |
|
86 sixBit = NULL; |
|
87 sixBit = STATIC_CAST(TUint8,(source & 0x0F) << 2); |
|
88 aResult.Append(KBase64Alphabet[sixBit]); |
|
89 aResult.Append(KBase64Alphabet[KBase64Pad]); |
|
90 break; |
|
91 case 1: |
|
92 source=aSource[i]; |
|
93 sixBit = STATIC_CAST(TUint8,(source & 0xFC) >> 2); |
|
94 aResult.Append(KBase64Alphabet[sixBit]); |
|
95 sixBit = NULL; |
|
96 sixBit = STATIC_CAST(TUint8,(source & 0x03) << 4); |
|
97 aResult.Append(KBase64Alphabet[sixBit]); |
|
98 aResult.Append(KBase64Alphabet[KBase64Pad]); |
|
99 aResult.Append(KBase64Alphabet[KBase64Pad]); |
|
100 break; |
|
101 default: |
|
102 break; |
|
103 } |
|
104 return KErrNone; |
|
105 } |
|
106 |
|
107 TInt CBase64CodecBase::Decode(const TDesC8& aSource, TDes8& aResult) |
|
108 // |
|
109 // Decode the base64 stream in aSource append the output to aResult. |
|
110 // Any non base64 chars are discarded while decoding |
|
111 // Returns if either an end of stream is found, or all aSource is exhausted |
|
112 // |
|
113 // Octets are only decoded when complete |
|
114 // |
|
115 { |
|
116 __ASSERT_ALWAYS((aSource.Length() * 3)/4 <= (aResult.MaxLength() - aResult.Length()), Panic(EBase64Overflow)); |
|
117 if (aSource.Length() == 0) |
|
118 return KErrNone; |
|
119 TText8* readPtr=CONST_CAST(TText8*,aSource.Ptr()); |
|
120 TText8* writePtr=CONST_CAST(TText8*,aResult.Ptr()); |
|
121 TText8* writeStart=writePtr; |
|
122 writePtr += aResult.Length(); |
|
123 TText8 result; |
|
124 TText8* readEnd=(readPtr + aSource.Length()); |
|
125 |
|
126 for (; readPtr < readEnd; readPtr++) |
|
127 { |
|
128 TUint8 base64code = Base64Char(*readPtr); |
|
129 switch (base64code) |
|
130 { |
|
131 case KBase64Pad: |
|
132 if (iQuartCount == 0) |
|
133 return KErrNone; |
|
134 result = STATIC_CAST(TText8,iQuart[0] << 2); |
|
135 result |= STATIC_CAST(TText8,((iQuart[1] & 0x30) >> 4)); |
|
136 *writePtr=result; |
|
137 writePtr++; |
|
138 if (iQuartCount == 3) |
|
139 { |
|
140 result = STATIC_CAST(TText8,(iQuart[1] & 0x0F) << 4); |
|
141 result |= STATIC_CAST(TText8,((iQuart[2] & 0x3C) >> 2)); |
|
142 *writePtr=result; |
|
143 writePtr++; |
|
144 } |
|
145 aResult.SetLength(writePtr-writeStart); |
|
146 iQuartCount = 0; |
|
147 return KErrNone; |
|
148 case KErrInvalidCharacter: |
|
149 // Do nothing |
|
150 break; |
|
151 default: |
|
152 { |
|
153 iQuart[iQuartCount++] = base64code; |
|
154 if (iQuartCount == 4) |
|
155 { |
|
156 result = STATIC_CAST(TText8,iQuart[0] << 2); |
|
157 result |= STATIC_CAST(TText8,((iQuart[1] & 0x30) >> 4)); |
|
158 *writePtr=result; |
|
159 writePtr++; |
|
160 result = STATIC_CAST(TText8,(iQuart[1] & 0x0F) << 4); |
|
161 result |= STATIC_CAST(TText8,((iQuart[2] & 0x3C) >> 2)); |
|
162 *writePtr=result; |
|
163 writePtr++; |
|
164 result = STATIC_CAST(TText8,((iQuart[2] & 0x03) << 6)); |
|
165 result |= STATIC_CAST(TText8,iQuart[3]); |
|
166 *writePtr=result; |
|
167 writePtr++; |
|
168 iQuartCount = 0; |
|
169 } |
|
170 } |
|
171 } |
|
172 } |
|
173 aResult.SetLength(writePtr-writeStart); |
|
174 return KErrNone; |
|
175 } |
|
176 |
|
177 TUint8 CBase64CodecBase::Base64Char(TText8 aChar) const |
|
178 // |
|
179 // Return the code or KErrInvalidCharacter |
|
180 { |
|
181 for (TUint8 i = 0; i < 65; i++) |
|
182 { |
|
183 if (aChar == KBase64Alphabet[i]) |
|
184 return i; |
|
185 } |
|
186 return KErrInvalidCharacter; |
|
187 } |
|
188 |
|
189 |
|
190 GLDEF_C void Panic(TBase64Panic aPanic) |
|
191 // Panic the process with Base64 codec as the category. |
|
192 // |
|
193 { |
|
194 _LIT(KPanicBase64Codec,"Base64 codec"); |
|
195 User::Panic(KPanicBase64Codec,aPanic); |
|
196 } |