1 karl 1.1 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 karl 1.1 //==============================================================================
23 //
24 // Author: Karl Schopmeyer (k.schopmeyer@opengroup.org)
25 //
26 // Modified By:
27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30 #include "Base64.h"
31 #include <cassert>
32 #include <strstream>
|
33 kumpf 1.3 #include <string>
|
34 karl 1.1 #include <Pegasus/Common/String.h>
35 #include <Pegasus/Common/Base64.h>
36 #include <Pegasus/Common/Array.h>
37
38 PEGASUS_NAMESPACE_BEGIN
39 PEGASUS_USING_STD;
40
41 //*************************************************************
42 /* Encode static method takes an array of 8-bit values and
43 returns a base-64 stream.
|
44 karl 1.2 ATTN: KS feb 2002 - This is probably a very slow an inefficient
45 implementation and could be improved if it is required for
46 production. Today it is only for test programs.
|
47 karl 1.1 */
|
48 kumpf 1.4 Array<Sint8> Base64::encode(const Array<Uint8>& vby)
|
49 karl 1.1 {
|
50 karl 1.2 Array<Sint8> retArray;
|
51 karl 1.1 // If nothing in input string, return empty string
52 if (vby.size() == 0)
|
53 karl 1.2 return retArray;
|
54 karl 1.1 // for every character in the input array taken 3 bytes at a time
55
56 for (Uint32 i=0; i < vby.size(); i+=3)
57 {
58
59 // Create from 3 8 bit values to 4 6 bit values
60 Uint8 by1=0,by2=0,by3=0;
61 by1 = vby[i];
62 if (i+1<vby.size())
63 {
64 by2 = vby[i+1];
65 };
66 if (i+2<vby.size())
67 {
68 by3 = vby[i+2];
69 }
70
71 Uint8 by4=0,by5=0,by6=0,by7=0;
72 by4 = by1>>2;
73 by5 = ((by1&0x3)<<4)|(by2>>4);
74 by6 = ((by2&0xf)<<2)|(by3>>6);
75 karl 1.1 by7 = by3&0x3f;
76
|
77 karl 1.2 retArray.append(_Encode(by4));
78 retArray.append(_Encode(by5));
|
79 karl 1.1
80 if (i+1<vby.size())
|
81 karl 1.2 retArray.append( _Encode(by6));
|
82 karl 1.1 else
|
83 karl 1.2 retArray.append('=');
|
84 karl 1.1
85 if (i+2<vby.size())
|
86 karl 1.2 retArray.append( _Encode(by7));
|
87 karl 1.1 else
|
88 karl 1.2 retArray.append('=');
|
89 karl 1.1
90 if (i % (76/4*3) == 0)
91 {
|
92 karl 1.2 retArray.append( '\r');
93 retArray.append( '\n');
|
94 karl 1.1 }
95 };
96
|
97 karl 1.2 return retArray;
|
98 karl 1.1 };
99 /*I checked for the zero length. The algorithm would also work for zero length input stream, but I’m pretty adamant about handling border conditions. They are often the culprits of run-time production failures.
100 The algorithm goes thru each three bytes of data at a time. The first thing I do is to shift the bits around from three 8-bit values to four 6-bit values. Then I encode the 6-bit values and add then one at a time to the output stream. This is actually quite inefficient. The STL character array is being allocated one byte at a time. The algorithm would be much faster, if I pre-allocated that array. I’ll leave that as an optimization practical exercise for the reader.
101
102
103 /* The decode static method takes a base-64 stream and converts it
104 to an array of 8-bit values.
105 */
|
106 kumpf 1.4 Array<Uint8> Base64::decode(const Array<Sint8> strInput)
|
107 karl 1.1 {
108 //Strip any non-base64 characters from the input
|
109 kumpf 1.3 PEGASUS_STD(string) str;
|
110 karl 1.1 for (Uint32 j=0;j<strInput.size();j++)
111 {
112 if (_IsBase64(strInput[j]))
113 str += strInput[j];
114 }
|
115 karl 1.2
116 Array<Uint8> retArray;
|
117 karl 1.1
118 // Return if the input is zero length
119 if (str.length() == 0)
|
120 karl 1.2 return retArray;
|
121 karl 1.1
122 // comment
123 for (int i=0; i < str.length();i+=4)
124 {
125 char c1='A',c2='A',c3='A',c4='A';
126
127 c1 = str[i];
128 if (i+1<str.length())
129 c2 = str[i+1];
130 if (i+2<str.length())
131 c3 = str[i+2];
132 if (i+3<str.length())
133 c4 = str[i+3];
134
135 Uint8 by1=0,by2=0,by3=0,by4=0;
136 by1 = _Decode(c1);
137 by2 = _Decode(c2);
138 by3 = _Decode(c3);
139 by4 = _Decode(c4);
140 //cout << "base::64decode bytes" <<
141 // " 1 " << c1 << " " << by1 <<
142 karl 1.1 // " 2 " << c2 << " " << by2 <<
143 // " 3 " << c3 << " " << by3 <<
144 // " 4 " << c4 << " " << by4 << endl;
145
146 // append first byte by shifting
|
147 karl 1.2 retArray.append( (by1<<2)|(by2>>4) );
|
148 karl 1.1
149 // append second byte if not padding
150 if (c3 != '=')
|
151 karl 1.2 retArray.append( ((by2&0xf)<<4)|(by3>>2) );
|
152 karl 1.1
153 if (c4 != '=')
|
154 karl 1.2 retArray.append( ((by3&0x3)<<6)|by4 );
|
155 karl 1.1 }
156
|
157 karl 1.2 return retArray;
|
158 karl 1.1 };
159
160 //**********************************************************
161 /* Encode thanslates one six-bit pattern into a base-64 character.
162 Unsigned char is used to represent a six-bit stream of date.
163
164 */
165 inline PEGASUS_COMMON_LINKAGE char Base64::_Encode(Uint8 uc)
166 {
167 if (uc < 26)
168 return 'A'+uc;
169
170 if (uc < 52)
171 return 'a'+(uc-26);
172
173 if (uc < 62)
174 return '0'+(uc-52);
175
176 if (uc == 62)
177 return '+';
178
179 karl 1.1 return '/';
180 };
181
182 //Helper function returns true is a character is a valid base-64 character and false otherwise.
183
184 inline Boolean Base64::_IsBase64(char c)
185 {
186
187 if (c >= 'A' && c <= 'Z')
188 return true;
189
190 if (c >= 'a' && c <= 'z')
191 return true;
192
193 if (c >= '0' && c <= '9')
194 return true;
195
196 if (c == '+')
197 return true;
198
199 if (c == '/')
200 karl 1.1 return true;
201
202 if (c == '=')
203 return true;
204
205 return false;
206 };
207
208 // Translate one base-64 character into a six bit pattern
209 inline Uint8 Base64::_Decode(char c)
210 {
211 if (c >= 'A' && c <= 'Z')
212 return c - 'A';
213 if (c >= 'a' && c <= 'z')
214 return c - 'a' + 26;
215
216 if (c >= '0' && c <= '9')
217 return c - '0' + 52;
218
219 if (c == '+')
220 return 62;
221 karl 1.1
222 return 63;
223 };
224
225
226 PEGASUS_NAMESPACE_END
|