author | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
commit | b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (unidiff) | |
tree | 2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /microkde/kdecore/kmdcodec.cpp | |
download | kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2 |
Initial revision
-rw-r--r-- | microkde/kdecore/kmdcodec.cpp | 1127 |
1 files changed, 1127 insertions, 0 deletions
diff --git a/microkde/kdecore/kmdcodec.cpp b/microkde/kdecore/kmdcodec.cpp new file mode 100644 index 0000000..bc03569 --- a/dev/null +++ b/microkde/kdecore/kmdcodec.cpp | |||
@@ -0,0 +1,1127 @@ | |||
1 | /* | ||
2 | Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> | ||
3 | Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU Lesser General Public License (LGPL) | ||
7 | version 2 as published by the Free Software Foundation. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public | ||
15 | License along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | |||
18 | RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. | ||
19 | RSA Data Security, Inc. Created 1991. All rights reserved. | ||
20 | |||
21 | The KMD5 class is based on a C++ implementation of | ||
22 | "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by | ||
23 | Mordechai T. Abzug,Copyright (c) 1995. This implementation | ||
24 | passes the test-suite as defined in RFC 1321. | ||
25 | |||
26 | The encoding and decoding utilities in KCodecs with the exception of | ||
27 | quoted-printable are based on the java implementation in HTTPClient | ||
28 | package by Ronald Tschal� Copyright (C) 1996-1999. | ||
29 | |||
30 | The quoted-printable codec as described in RFC 2045, section 6.7. is by | ||
31 | Rik Hemsley (C) 2001. | ||
32 | */ | ||
33 | |||
34 | //US #include <config.h> | ||
35 | |||
36 | #include <stdio.h> | ||
37 | #include <string.h> | ||
38 | #include <stdlib.h> | ||
39 | |||
40 | #include <kdebug.h> | ||
41 | #include "kmdcodec.h" | ||
42 | |||
43 | #define KMD5_S11 7 | ||
44 | #define KMD5_S12 12 | ||
45 | #define KMD5_S13 17 | ||
46 | #define KMD5_S14 22 | ||
47 | #define KMD5_S21 5 | ||
48 | #define KMD5_S22 9 | ||
49 | #define KMD5_S23 14 | ||
50 | #define KMD5_S24 20 | ||
51 | #define KMD5_S31 4 | ||
52 | #define KMD5_S32 11 | ||
53 | #define KMD5_S33 16 | ||
54 | #define KMD5_S34 23 | ||
55 | #define KMD5_S41 6 | ||
56 | #define KMD5_S42 10 | ||
57 | #define KMD5_S43 15 | ||
58 | #define KMD5_S44 21 | ||
59 | |||
60 | const char KCodecs::Base64EncMap[64] = | ||
61 | { | ||
62 | 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, | ||
63 | 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, | ||
64 | 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | ||
65 | 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, | ||
66 | 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, | ||
67 | 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, | ||
68 | 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, | ||
69 | 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F | ||
70 | }; | ||
71 | |||
72 | const char KCodecs::Base64DecMap[128] = | ||
73 | { | ||
74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
79 | 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, | ||
80 | 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, | ||
81 | 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
82 | 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, | ||
83 | 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, | ||
84 | 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, | ||
85 | 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
86 | 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, | ||
87 | 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, | ||
88 | 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, | ||
89 | 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
90 | }; | ||
91 | |||
92 | const char KCodecs::UUEncMap[64] = | ||
93 | { | ||
94 | 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | ||
95 | 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, | ||
96 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | ||
97 | 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, | ||
98 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, | ||
99 | 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, | ||
100 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, | ||
101 | 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F | ||
102 | }; | ||
103 | |||
104 | const char KCodecs::UUDecMap[128] = | ||
105 | { | ||
106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
108 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
110 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
111 | 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | ||
112 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | ||
113 | 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, | ||
114 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | ||
115 | 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, | ||
116 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | ||
117 | 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, | ||
118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
121 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
122 | }; | ||
123 | |||
124 | const char KCodecs::hexChars[16] = | ||
125 | { | ||
126 | '0', '1', '2', '3', '4', '5', '6', '7', | ||
127 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
128 | }; | ||
129 | |||
130 | const unsigned int KCodecs::maxQPLineLength = 70; | ||
131 | |||
132 | |||
133 | /******************************** KCodecs ********************************/ | ||
134 | // strchr(3) for broken systems. | ||
135 | static int rikFindChar(register const char * _s, const char c) | ||
136 | { | ||
137 | register const char * s = _s; | ||
138 | |||
139 | while (true) | ||
140 | { | ||
141 | if ((0 == *s) || (c == *s)) break; ++s; | ||
142 | if ((0 == *s) || (c == *s)) break; ++s; | ||
143 | if ((0 == *s) || (c == *s)) break; ++s; | ||
144 | if ((0 == *s) || (c == *s)) break; ++s; | ||
145 | } | ||
146 | |||
147 | return s - _s; | ||
148 | } | ||
149 | |||
150 | QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF) | ||
151 | { | ||
152 | QByteArray out; | ||
153 | quotedPrintableEncode (in, out, useCRLF); | ||
154 | return QCString (out.data(), out.size()+1); | ||
155 | } | ||
156 | |||
157 | QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF) | ||
158 | { | ||
159 | if (str.isEmpty()) | ||
160 | return ""; | ||
161 | |||
162 | QByteArray in (str.length()); | ||
163 | memcpy (in.data(), str.data(), str.length()); | ||
164 | return quotedPrintableEncode(in, useCRLF); | ||
165 | } | ||
166 | |||
167 | void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF) | ||
168 | { | ||
169 | out.resize (0); | ||
170 | if (in.isEmpty()) | ||
171 | return; | ||
172 | |||
173 | char *cursor; | ||
174 | const char *data; | ||
175 | unsigned int lineLength; | ||
176 | unsigned int pos; | ||
177 | |||
178 | const unsigned int length = in.size(); | ||
179 | const unsigned int end = length - 1; | ||
180 | |||
181 | |||
182 | // Reasonable guess for output size when we're encoding | ||
183 | // mostly-ASCII data. It doesn't really matter, because | ||
184 | // the underlying allocation routines are quite efficient, | ||
185 | // but it's nice to have 0 allocations in many cases. | ||
186 | out.resize ((length*12)/10); | ||
187 | cursor = out.data(); | ||
188 | data = in.data(); | ||
189 | lineLength = 0; | ||
190 | pos = 0; | ||
191 | |||
192 | for (unsigned int i = 0; i < length; i++) | ||
193 | { | ||
194 | unsigned char c (data[i]); | ||
195 | |||
196 | // check if we have to enlarge the output buffer, use | ||
197 | // a safety margin of 16 byte | ||
198 | pos = cursor-out.data(); | ||
199 | if (out.size()-pos < 16) { | ||
200 | out.resize(out.size()+4096); | ||
201 | cursor = out.data()+pos; | ||
202 | } | ||
203 | |||
204 | // Plain ASCII chars just go straight out. | ||
205 | |||
206 | if ((c >= 33) && (c <= 126) && ('=' != c)) | ||
207 | { | ||
208 | *cursor++ = c; | ||
209 | ++lineLength; | ||
210 | } | ||
211 | |||
212 | // Spaces need some thought. We have to encode them at eol (or eof). | ||
213 | |||
214 | else if (' ' == c) | ||
215 | { | ||
216 | if | ||
217 | ( | ||
218 | (i >= length) | ||
219 | || | ||
220 | ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2])) | ||
221 | || | ||
222 | (!useCRLF && ('\n' == data[i + 1])))) | ||
223 | ) | ||
224 | { | ||
225 | *cursor++ = '='; | ||
226 | *cursor++ = '2'; | ||
227 | *cursor++ = '0'; | ||
228 | |||
229 | lineLength += 3; | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | *cursor++ = ' '; | ||
234 | ++lineLength; | ||
235 | } | ||
236 | } | ||
237 | // If we find a line break, just let it through. | ||
238 | else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) || | ||
239 | (!useCRLF && ('\n' == c))) | ||
240 | { | ||
241 | lineLength = 0; | ||
242 | |||
243 | if (useCRLF) { | ||
244 | *cursor++ = '\r'; | ||
245 | *cursor++ = '\n'; | ||
246 | ++i; | ||
247 | } else { | ||
248 | *cursor++ = '\n'; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | // Anything else is converted to =XX. | ||
253 | |||
254 | else | ||
255 | { | ||
256 | *cursor++ = '='; | ||
257 | *cursor++ = hexChars[c / 16]; | ||
258 | *cursor++ = hexChars[c % 16]; | ||
259 | |||
260 | lineLength += 3; | ||
261 | } | ||
262 | |||
263 | // If we're approaching the maximum line length, do a soft line break. | ||
264 | |||
265 | if ((lineLength > maxQPLineLength) && (i < end)) | ||
266 | { | ||
267 | if (useCRLF) { | ||
268 | *cursor++ = '='; | ||
269 | *cursor++ = '\r'; | ||
270 | *cursor++ = '\n'; | ||
271 | } else { | ||
272 | *cursor++ = '='; | ||
273 | *cursor++ = '\n'; | ||
274 | } | ||
275 | |||
276 | lineLength = 0; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | out.truncate(cursor - out.data()); | ||
281 | } | ||
282 | |||
283 | QCString KCodecs::quotedPrintableDecode(const QByteArray & in) | ||
284 | { | ||
285 | QByteArray out; | ||
286 | quotedPrintableDecode (in, out); | ||
287 | return QCString (out.data(), out.size()+1); | ||
288 | } | ||
289 | |||
290 | QCString KCodecs::quotedPrintableDecode(const QCString & str) | ||
291 | { | ||
292 | if (str.isEmpty()) | ||
293 | return ""; | ||
294 | |||
295 | QByteArray in (str.length()); | ||
296 | memcpy (in.data(), str.data(), str.length()); | ||
297 | return quotedPrintableDecode (in); | ||
298 | } | ||
299 | |||
300 | void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out) | ||
301 | { | ||
302 | // clear out the output buffer | ||
303 | out.resize (0); | ||
304 | if (in.isEmpty()) | ||
305 | return; | ||
306 | |||
307 | char *cursor; | ||
308 | const char *data; | ||
309 | const unsigned int length = in.size(); | ||
310 | |||
311 | data = in.data(); | ||
312 | out.resize (length); | ||
313 | cursor = out.data(); | ||
314 | |||
315 | for (unsigned int i = 0; i < length; i++) | ||
316 | { | ||
317 | char c(in.at(i)); | ||
318 | |||
319 | if ('=' == c) | ||
320 | { | ||
321 | if (i < length - 2) | ||
322 | { | ||
323 | char c1 = in.at(i + 1); | ||
324 | char c2 = in.at(i + 2); | ||
325 | |||
326 | if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) | ||
327 | { | ||
328 | // Soft line break. No output. | ||
329 | if ('\r' == c1) | ||
330 | i += 2; // CRLF line breaks | ||
331 | else | ||
332 | i += 1; | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | // =XX encoded byte. | ||
337 | |||
338 | int hexChar0 = rikFindChar(hexChars, c1); | ||
339 | int hexChar1 = rikFindChar(hexChars, c2); | ||
340 | |||
341 | if (hexChar0 < 16 && hexChar1 < 16) | ||
342 | { | ||
343 | *cursor++ = char((hexChar0 * 16) | hexChar1); | ||
344 | i += 2; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | else | ||
350 | { | ||
351 | *cursor++ = c; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | out.truncate(cursor - out.data()); | ||
356 | } | ||
357 | |||
358 | QCString KCodecs::base64Encode( const QCString& str, bool insertLFs ) | ||
359 | { | ||
360 | if ( str.isEmpty() ) | ||
361 | return ""; | ||
362 | |||
363 | QByteArray in (str.length()); | ||
364 | memcpy( in.data(), str.data(), str.length() ); | ||
365 | return base64Encode( in, insertLFs ); | ||
366 | } | ||
367 | |||
368 | QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs ) | ||
369 | { | ||
370 | QByteArray out; | ||
371 | base64Encode( in, out, insertLFs ); | ||
372 | return QCString( out.data(), out.size()+1 ); | ||
373 | } | ||
374 | |||
375 | void KCodecs::base64Encode( const QByteArray& in, QByteArray& out, | ||
376 | bool insertLFs ) | ||
377 | { | ||
378 | // clear out the output buffer | ||
379 | out.resize (0); | ||
380 | if ( in.isEmpty() ) | ||
381 | return; | ||
382 | |||
383 | unsigned int sidx = 0; | ||
384 | unsigned int didx = 0; | ||
385 | const char* data = in.data(); | ||
386 | const unsigned int len = in.size(); | ||
387 | |||
388 | unsigned int out_len = ((len+2)/3)*4; | ||
389 | |||
390 | // Deal with the 76 characters or less per | ||
391 | // line limit specified in RFC 2045 on a | ||
392 | // pre request basis. | ||
393 | insertLFs = (insertLFs && out_len > 76); | ||
394 | if ( insertLFs ) | ||
395 | out_len += ((out_len-1)/76); | ||
396 | |||
397 | int count = 0; | ||
398 | out.resize( out_len ); | ||
399 | |||
400 | // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion | ||
401 | if ( len > 1 ) | ||
402 | { | ||
403 | while (sidx < len-2) | ||
404 | { | ||
405 | if ( insertLFs ) | ||
406 | { | ||
407 | if ( count && (count%76) == 0 ) | ||
408 | out.at(didx++) = '\n'; | ||
409 | count += 4; | ||
410 | } | ||
411 | out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077]; | ||
412 | out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 | | ||
413 | (data[sidx] << 4) & 077]; | ||
414 | out.at(didx++) = Base64EncMap[(data[sidx+2] >> 6) & 003 | | ||
415 | (data[sidx+1] << 2) & 077]; | ||
416 | out.at(didx++) = Base64EncMap[data[sidx+2] & 077]; | ||
417 | sidx += 3; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | if (sidx < len) | ||
422 | { | ||
423 | if ( insertLFs && (count > 0) && (count%76) == 0 ) | ||
424 | out.at(didx++) = '\n'; | ||
425 | |||
426 | out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077]; | ||
427 | if (sidx < len-1) | ||
428 | { | ||
429 | out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 | | ||
430 | (data[sidx] << 4) & 077]; | ||
431 | out.at(didx++) = Base64EncMap[(data[sidx+1] << 2) & 077]; | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | out.at(didx++) = Base64EncMap[(data[sidx] << 4) & 077]; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | // Add padding | ||
440 | while (didx < out.size()) | ||
441 | { | ||
442 | out.at(didx) = '='; | ||
443 | didx++; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | QCString KCodecs::base64Decode( const QCString& str ) | ||
448 | { | ||
449 | if ( str.isEmpty() ) | ||
450 | return ""; | ||
451 | |||
452 | QByteArray in( str.length() ); | ||
453 | memcpy( in.data(), str.data(), str.length() ); | ||
454 | return base64Decode( in ); | ||
455 | } | ||
456 | |||
457 | QCString KCodecs::base64Decode( const QByteArray& in ) | ||
458 | { | ||
459 | QByteArray out; | ||
460 | base64Decode( in, out ); | ||
461 | return QCString( out.data(), out.size()+1 ); | ||
462 | } | ||
463 | |||
464 | void KCodecs::base64Decode( const QByteArray& in, QByteArray& out ) | ||
465 | { | ||
466 | out.resize(0); | ||
467 | if ( in.isEmpty() ) | ||
468 | return; | ||
469 | |||
470 | unsigned int count = 0; | ||
471 | unsigned int len = in.size(), tail = len; | ||
472 | const char* data = in.data(); | ||
473 | |||
474 | // Deal with possible *nix "BEGIN" marker!! | ||
475 | while ( count < len && (data[count] == '\n' || data[count] == '\r' || | ||
476 | data[count] == '\t' || data[count] == ' ') ) | ||
477 | count++; | ||
478 | |||
479 | if ( QString(data+count).left(5).lower() == "begin" ) | ||
480 | { | ||
481 | count += 5; | ||
482 | while ( count < len && data[count] != '\n' && data[count] != '\r' ) | ||
483 | count++; | ||
484 | |||
485 | while ( count < len && (data[count] == '\n' || data[count] == '\r') ) | ||
486 | count ++; | ||
487 | |||
488 | data += count; | ||
489 | tail = (len -= count); | ||
490 | } | ||
491 | |||
492 | // Find the tail end of the actual encoded data even if | ||
493 | // there is/are trailing CR and/or LF. | ||
494 | while ( data[tail-1] == '=' || data[tail-1] == '\n' || | ||
495 | data[tail-1] == '\r' ) | ||
496 | if ( data[--tail] != '=' ) len = tail; | ||
497 | |||
498 | unsigned int outIdx = 0; | ||
499 | out.resize( (count=len) ); | ||
500 | for (unsigned int idx = 0; idx < count; idx++) | ||
501 | { | ||
502 | // Adhere to RFC 2045 and ignore characters | ||
503 | // that are not part of the encoding table. | ||
504 | unsigned char ch = data[idx]; | ||
505 | if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || | ||
506 | (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') | ||
507 | { | ||
508 | out.at(outIdx++) = Base64DecMap[ch]; | ||
509 | } | ||
510 | else | ||
511 | { | ||
512 | len--; | ||
513 | tail--; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl; | ||
518 | |||
519 | // 4-byte to 3-byte conversion | ||
520 | len = (tail>(len/4)) ? tail-(len/4) : 0; | ||
521 | unsigned int sidx = 0, didx = 0; | ||
522 | if ( len > 1 ) | ||
523 | { | ||
524 | while (didx < len-2) | ||
525 | { | ||
526 | out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003)); | ||
527 | out.at(didx+1) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017)); | ||
528 | out.at(didx+2) = (((out.at(sidx+2) << 6) & 255) | (out.at(sidx+3) & 077)); | ||
529 | sidx += 4; | ||
530 | didx += 3; | ||
531 | } | ||
532 | } | ||
533 | |||
534 | if (didx < len) | ||
535 | out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003)); | ||
536 | |||
537 | if (++didx < len ) | ||
538 | out.at(didx) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017)); | ||
539 | |||
540 | // Resize the output buffer | ||
541 | if ( len == 0 || len < out.size() ) | ||
542 | out.resize(len); | ||
543 | } | ||
544 | |||
545 | QCString KCodecs::uuencode( const QCString& str ) | ||
546 | { | ||
547 | if ( str.isEmpty() ) | ||
548 | return ""; | ||
549 | |||
550 | QByteArray in; | ||
551 | in.resize( str.length() ); | ||
552 | memcpy( in.data(), str.data(), str.length() ); | ||
553 | return uuencode( in ); | ||
554 | } | ||
555 | |||
556 | QCString KCodecs::uuencode( const QByteArray& in ) | ||
557 | { | ||
558 | QByteArray out; | ||
559 | uuencode( in, out ); | ||
560 | return QCString( out.data(), out.size()+1 ); | ||
561 | } | ||
562 | |||
563 | void KCodecs::uuencode( const QByteArray& in, QByteArray& out ) | ||
564 | { | ||
565 | out.resize( 0 ); | ||
566 | if( in.isEmpty() ) | ||
567 | return; | ||
568 | |||
569 | unsigned int sidx = 0; | ||
570 | unsigned int didx = 0; | ||
571 | unsigned int line_len = 45; | ||
572 | |||
573 | const char nl[] = "\n"; | ||
574 | const char* data = in.data(); | ||
575 | const unsigned int nl_len = strlen(nl); | ||
576 | const unsigned int len = in.size(); | ||
577 | |||
578 | out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); | ||
579 | // split into lines, adding line-length and line terminator | ||
580 | while (sidx+line_len < len) | ||
581 | { | ||
582 | // line length | ||
583 | out.at(didx++) = UUEncMap[line_len]; | ||
584 | |||
585 | // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion | ||
586 | for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) | ||
587 | { | ||
588 | out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; | ||
589 | out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | | ||
590 | (data[sidx] << 4) & 077]; | ||
591 | out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 | | ||
592 | (data[sidx+1] << 2) & 077]; | ||
593 | out.at(didx++) = UUEncMap[data[sidx+2] & 077]; | ||
594 | } | ||
595 | |||
596 | // line terminator | ||
597 | //for (unsigned int idx=0; idx < nl_len; idx++) | ||
598 | //out.at(didx++) = nl[idx]; | ||
599 | memcpy(out.data()+didx, nl, nl_len); | ||
600 | didx += nl_len; | ||
601 | } | ||
602 | |||
603 | // line length | ||
604 | out.at(didx++) = UUEncMap[len-sidx]; | ||
605 | // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion | ||
606 | while (sidx+2 < len) | ||
607 | { | ||
608 | out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; | ||
609 | out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | | ||
610 | (data[sidx] << 4) & 077]; | ||
611 | out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 | | ||
612 | (data[sidx+1] << 2) & 077]; | ||
613 | out.at(didx++) = UUEncMap[data[sidx+2] & 077]; | ||
614 | sidx += 3; | ||
615 | } | ||
616 | |||
617 | if (sidx < len-1) | ||
618 | { | ||
619 | out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; | ||
620 | out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | | ||
621 | (data[sidx] << 4) & 077]; | ||
622 | out.at(didx++) = UUEncMap[(data[sidx+1] << 2) & 077]; | ||
623 | out.at(didx++) = UUEncMap[0]; | ||
624 | } | ||
625 | else if (sidx < len) | ||
626 | { | ||
627 | out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; | ||
628 | out.at(didx++) = UUEncMap[(data[sidx] << 4) & 077]; | ||
629 | out.at(didx++) = UUEncMap[0]; | ||
630 | out.at(didx++) = UUEncMap[0]; | ||
631 | } | ||
632 | |||
633 | // line terminator | ||
634 | memcpy(out.data()+didx, nl, nl_len); | ||
635 | didx += nl_len; | ||
636 | |||
637 | // sanity check | ||
638 | if ( didx != out.size() ) | ||
639 | out.resize( 0 ); | ||
640 | } | ||
641 | |||
642 | QCString KCodecs::uudecode( const QCString& str ) | ||
643 | { | ||
644 | if ( str.isEmpty() ) | ||
645 | return ""; | ||
646 | |||
647 | QByteArray in; | ||
648 | in.resize( str.length() ); | ||
649 | memcpy( in.data(), str.data(), str.length() ); | ||
650 | return uudecode( in ); | ||
651 | } | ||
652 | |||
653 | QCString KCodecs::uudecode( const QByteArray& in ) | ||
654 | { | ||
655 | QByteArray out; | ||
656 | uudecode( in, out ); | ||
657 | return QCString( out.data(), out.size()+1 ); | ||
658 | } | ||
659 | |||
660 | void KCodecs::uudecode( const QByteArray& in, QByteArray& out ) | ||
661 | { | ||
662 | out.resize( 0 ); | ||
663 | if( in.isEmpty() ) | ||
664 | return; | ||
665 | |||
666 | unsigned int sidx = 0; | ||
667 | unsigned int didx = 0; | ||
668 | unsigned int len = in.size(); | ||
669 | unsigned int line_len, end; | ||
670 | const char* data = in.data(); | ||
671 | |||
672 | // Deal with *nix "BEGIN"/"END" separators!! | ||
673 | unsigned int count = 0; | ||
674 | while ( count < len && (data[count] == '\n' || data[count] == '\r' || | ||
675 | data[count] == '\t' || data[count] == ' ') ) | ||
676 | count ++; | ||
677 | |||
678 | bool hasLF = false; | ||
679 | if ( QString( data+count).left(5).lower() == "begin" ) | ||
680 | { | ||
681 | count += 5; | ||
682 | while ( count < len && data[count] != '\n' && data[count] != '\r' ) | ||
683 | count ++; | ||
684 | |||
685 | while ( count < len && (data[count] == '\n' || data[count] == '\r') ) | ||
686 | count ++; | ||
687 | |||
688 | data += count; | ||
689 | len -= count; | ||
690 | hasLF = true; | ||
691 | } | ||
692 | |||
693 | out.resize( len/4*3 ); | ||
694 | while ( sidx < len ) | ||
695 | { | ||
696 | // get line length (in number of encoded octets) | ||
697 | line_len = UUDecMap[ (unsigned char) data[sidx++]]; | ||
698 | // ascii printable to 0-63 and 4-byte to 3-byte conversion | ||
699 | end = didx+line_len; | ||
700 | char A, B, C, D; | ||
701 | if (end > 2) { | ||
702 | while (didx < end-2) | ||
703 | { | ||
704 | A = UUDecMap[(unsigned char) data[sidx]]; | ||
705 | B = UUDecMap[(unsigned char) data[sidx+1]]; | ||
706 | C = UUDecMap[(unsigned char) data[sidx+2]]; | ||
707 | D = UUDecMap[(unsigned char) data[sidx+3]]; | ||
708 | out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) ); | ||
709 | out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) ); | ||
710 | out.at(didx++) = ( ((C << 6) & 255) | (D & 077) ); | ||
711 | sidx += 4; | ||
712 | } | ||
713 | } | ||
714 | |||
715 | if (didx < end) | ||
716 | { | ||
717 | A = UUDecMap[(unsigned char) data[sidx]]; | ||
718 | B = UUDecMap[(unsigned char) data[sidx+1]]; | ||
719 | out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) ); | ||
720 | } | ||
721 | |||
722 | if (didx < end) | ||
723 | { | ||
724 | B = UUDecMap[(unsigned char) data[sidx+1]]; | ||
725 | C = UUDecMap[(unsigned char) data[sidx+2]]; | ||
726 | out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) ); | ||
727 | } | ||
728 | |||
729 | // skip padding | ||
730 | while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') | ||
731 | sidx++; | ||
732 | |||
733 | // skip end of line | ||
734 | while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) | ||
735 | sidx++; | ||
736 | |||
737 | // skip the "END" separator when present. | ||
738 | if ( hasLF && QString( data+sidx).left(3).lower() == "end" ) | ||
739 | break; | ||
740 | } | ||
741 | |||
742 | if ( didx < out.size() ) | ||
743 | out.resize( didx ); | ||
744 | } | ||
745 | |||
746 | /******************************** KMD5 ********************************/ | ||
747 | KMD5::KMD5() | ||
748 | { | ||
749 | init(); | ||
750 | } | ||
751 | |||
752 | KMD5::KMD5(const char *in, int len) | ||
753 | { | ||
754 | init(); | ||
755 | update(in, len); | ||
756 | } | ||
757 | |||
758 | KMD5::KMD5(const QByteArray& in) | ||
759 | { | ||
760 | init(); | ||
761 | update( in ); | ||
762 | } | ||
763 | |||
764 | KMD5::KMD5(const QCString& in) | ||
765 | { | ||
766 | init(); | ||
767 | update( in ); | ||
768 | } | ||
769 | |||
770 | void KMD5::update(const QByteArray& in) | ||
771 | { | ||
772 | update(in.data(), int(in.size())); | ||
773 | } | ||
774 | |||
775 | void KMD5::update(const QCString& in) | ||
776 | { | ||
777 | update(in.data(), int(in.length())); | ||
778 | } | ||
779 | |||
780 | void KMD5::update(const unsigned char* in, int len) | ||
781 | { | ||
782 | if (len < 0) | ||
783 | len = qstrlen(reinterpret_cast<const char*>(in)); | ||
784 | |||
785 | if (!len) | ||
786 | return; | ||
787 | |||
788 | if (m_finalized) { | ||
789 | kdWarning() << "KMD5::update called after state was finalized!" << endl; | ||
790 | return; | ||
791 | } | ||
792 | |||
793 | Q_UINT32 in_index; | ||
794 | Q_UINT32 buffer_index; | ||
795 | Q_UINT32 buffer_space; | ||
796 | Q_UINT32 in_length = static_cast<Q_UINT32>( len ); | ||
797 | |||
798 | buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F); | ||
799 | |||
800 | if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) | ||
801 | m_count[1]++; | ||
802 | |||
803 | m_count[1] += (in_length >> 29); | ||
804 | buffer_space = 64 - buffer_index; | ||
805 | |||
806 | if (in_length >= buffer_space) | ||
807 | { | ||
808 | memcpy (m_buffer + buffer_index, in, buffer_space); | ||
809 | transform (m_buffer); | ||
810 | |||
811 | for (in_index = buffer_space; in_index + 63 < in_length; | ||
812 | in_index += 64) | ||
813 | transform (reinterpret_cast<const unsigned char*>(in+in_index)); | ||
814 | |||
815 | buffer_index = 0; | ||
816 | } | ||
817 | else | ||
818 | in_index=0; | ||
819 | |||
820 | memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); | ||
821 | } | ||
822 | |||
823 | bool KMD5::update(QIODevice& file) | ||
824 | { | ||
825 | char buffer[1024]; | ||
826 | int len; | ||
827 | |||
828 | while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) | ||
829 | update(buffer, len); | ||
830 | |||
831 | return file.atEnd(); | ||
832 | } | ||
833 | |||
834 | void KMD5::finalize () | ||
835 | { | ||
836 | if (m_finalized) return; | ||
837 | |||
838 | Q_UINT8 bits[8]; | ||
839 | Q_UINT32 index, padLen; | ||
840 | static unsigned char PADDING[64]= | ||
841 | { | ||
842 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
843 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
844 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
845 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
846 | }; | ||
847 | |||
848 | encode (bits, m_count, 8); | ||
849 | //memcpy( bits, m_count, 8 ); | ||
850 | |||
851 | // Pad out to 56 mod 64. | ||
852 | index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f); | ||
853 | padLen = (index < 56) ? (56 - index) : (120 - index); | ||
854 | update (reinterpret_cast<const char*>(PADDING), padLen); | ||
855 | |||
856 | // Append length (before padding) | ||
857 | update (reinterpret_cast<const char*>(bits), 8); | ||
858 | |||
859 | // Store state in digest | ||
860 | encode (m_digest, m_state, 16); | ||
861 | //memcpy( m_digest, m_state, 16 ); | ||
862 | |||
863 | // Fill sensitive information with zero's | ||
864 | memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); | ||
865 | |||
866 | m_finalized = true; | ||
867 | } | ||
868 | |||
869 | |||
870 | bool KMD5::verify( const KMD5::Digest& digest) | ||
871 | { | ||
872 | finalize(); | ||
873 | return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); | ||
874 | } | ||
875 | |||
876 | bool KMD5::verify( const QCString& hexdigest) | ||
877 | { | ||
878 | finalize(); | ||
879 | return (0 == strcmp(hexDigest().data(), hexdigest)); | ||
880 | } | ||
881 | |||
882 | const KMD5::Digest& KMD5::rawDigest() | ||
883 | { | ||
884 | finalize(); | ||
885 | return m_digest; | ||
886 | } | ||
887 | |||
888 | void KMD5::rawDigest( KMD5::Digest& bin ) | ||
889 | { | ||
890 | finalize(); | ||
891 | memcpy( bin, m_digest, 16 ); | ||
892 | } | ||
893 | |||
894 | |||
895 | QCString KMD5::hexDigest() | ||
896 | { | ||
897 | QCString s(33); | ||
898 | |||
899 | finalize(); | ||
900 | sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", | ||
901 | m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], | ||
902 | m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], | ||
903 | m_digest[12], m_digest[13], m_digest[14], m_digest[15]); | ||
904 | |||
905 | return s; | ||
906 | } | ||
907 | |||
908 | void KMD5::hexDigest(QCString& s) | ||
909 | { | ||
910 | finalize(); | ||
911 | s.resize(33); | ||
912 | sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", | ||
913 | m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], | ||
914 | m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], | ||
915 | m_digest[12], m_digest[13], m_digest[14], m_digest[15]); | ||
916 | } | ||
917 | |||
918 | QCString KMD5::base64Digest() | ||
919 | { | ||
920 | QByteArray ba(16); | ||
921 | |||
922 | finalize(); | ||
923 | memcpy(ba.data(), m_digest, 16); | ||
924 | return KCodecs::base64Encode(ba); | ||
925 | } | ||
926 | |||
927 | |||
928 | void KMD5::init() | ||
929 | { | ||
930 | d = 0; | ||
931 | reset(); | ||
932 | } | ||
933 | |||
934 | void KMD5::reset() | ||
935 | { | ||
936 | m_finalized = false; | ||
937 | |||
938 | m_count[0] = 0; | ||
939 | m_count[1] = 0; | ||
940 | |||
941 | m_state[0] = 0x67452301; | ||
942 | m_state[1] = 0xefcdab89; | ||
943 | m_state[2] = 0x98badcfe; | ||
944 | m_state[3] = 0x10325476; | ||
945 | |||
946 | memset ( m_buffer, 0, sizeof(*m_buffer)); | ||
947 | memset ( m_digest, 0, sizeof(*m_digest)); | ||
948 | } | ||
949 | |||
950 | void KMD5::transform( const unsigned char block[64] ) | ||
951 | { | ||
952 | |||
953 | Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; | ||
954 | |||
955 | decode (x, block, 64); | ||
956 | //memcpy( x, block, 64 ); | ||
957 | |||
958 | //US Q_ASSERT(!m_finalized); // not just a user error, since the method is private | ||
959 | ASSERT(!m_finalized); // not just a user error, since the method is private | ||
960 | |||
961 | /* Round 1 */ | ||
962 | FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ | ||
963 | FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ | ||
964 | FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ | ||
965 | FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ | ||
966 | FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ | ||
967 | FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ | ||
968 | FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ | ||
969 | FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ | ||
970 | FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ | ||
971 | FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ | ||
972 | FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ | ||
973 | FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ | ||
974 | FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ | ||
975 | FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ | ||
976 | FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ | ||
977 | FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ | ||
978 | |||
979 | /* Round 2 */ | ||
980 | GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ | ||
981 | GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ | ||
982 | GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ | ||
983 | GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ | ||
984 | GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ | ||
985 | GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ | ||
986 | GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ | ||
987 | GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ | ||
988 | GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ | ||
989 | GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ | ||
990 | GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ | ||
991 | GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ | ||
992 | GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ | ||
993 | GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ | ||
994 | GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ | ||
995 | GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ | ||
996 | |||
997 | /* Round 3 */ | ||
998 | HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ | ||
999 | HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ | ||
1000 | HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ | ||
1001 | HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ | ||
1002 | HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ | ||
1003 | HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ | ||
1004 | HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ | ||
1005 | HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ | ||
1006 | HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ | ||
1007 | HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ | ||
1008 | HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ | ||
1009 | HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ | ||
1010 | HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ | ||
1011 | HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ | ||
1012 | HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ | ||
1013 | HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ | ||
1014 | |||
1015 | /* Round 4 */ | ||
1016 | II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ | ||
1017 | II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ | ||
1018 | II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ | ||
1019 | II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ | ||
1020 | II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ | ||
1021 | II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ | ||
1022 | II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ | ||
1023 | II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ | ||
1024 | II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ | ||
1025 | II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ | ||
1026 | II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ | ||
1027 | II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ | ||
1028 | II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ | ||
1029 | II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ | ||
1030 | II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ | ||
1031 | II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ | ||
1032 | |||
1033 | m_state[0] += a; | ||
1034 | m_state[1] += b; | ||
1035 | m_state[2] += c; | ||
1036 | m_state[3] += d; | ||
1037 | |||
1038 | memset ( static_cast<void *>(x), 0, sizeof(x) ); | ||
1039 | } | ||
1040 | |||
1041 | inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n) | ||
1042 | { | ||
1043 | return (x << n) | (x >> (32-n)) ; | ||
1044 | } | ||
1045 | |||
1046 | inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1047 | { | ||
1048 | return (x & y) | (~x & z); | ||
1049 | } | ||
1050 | |||
1051 | inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1052 | { | ||
1053 | return (x & z) | (y & ~z); | ||
1054 | } | ||
1055 | |||
1056 | inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1057 | { | ||
1058 | return x ^ y ^ z; | ||
1059 | } | ||
1060 | |||
1061 | inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1062 | { | ||
1063 | return y ^ (x | ~z); | ||
1064 | } | ||
1065 | |||
1066 | void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, | ||
1067 | Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) | ||
1068 | { | ||
1069 | a += F(b, c, d) + x + ac; | ||
1070 | a = rotate_left (a, s) +b; | ||
1071 | } | ||
1072 | |||
1073 | void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, | ||
1074 | Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac) | ||
1075 | { | ||
1076 | a += G(b, c, d) + x + ac; | ||
1077 | a = rotate_left (a, s) +b; | ||
1078 | } | ||
1079 | |||
1080 | void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, | ||
1081 | Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) | ||
1082 | { | ||
1083 | a += H(b, c, d) + x + ac; | ||
1084 | a = rotate_left (a, s) +b; | ||
1085 | } | ||
1086 | |||
1087 | void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, | ||
1088 | Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) | ||
1089 | { | ||
1090 | a += I(b, c, d) + x + ac; | ||
1091 | a = rotate_left (a, s) +b; | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ) | ||
1096 | { | ||
1097 | #if !defined(WORDS_BIGENDIAN) | ||
1098 | memcpy(output, in, len); | ||
1099 | |||
1100 | #else | ||
1101 | Q_UINT32 i, j; | ||
1102 | for (i = 0, j = 0; j < len; i++, j += 4) | ||
1103 | { | ||
1104 | output[j] = static_cast<Q_UINT8>((in[i] & 0xff)); | ||
1105 | output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff)); | ||
1106 | output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff)); | ||
1107 | output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff)); | ||
1108 | } | ||
1109 | #endif | ||
1110 | } | ||
1111 | |||
1112 | // Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a | ||
1113 | // multiple of 4. | ||
1114 | void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len) | ||
1115 | { | ||
1116 | #if !defined(WORDS_BIGENDIAN) | ||
1117 | memcpy(output, in, len); | ||
1118 | |||
1119 | #else | ||
1120 | Q_UINT32 i, j; | ||
1121 | for (i = 0, j = 0; j < len; i++, j += 4) | ||
1122 | output[i] = static_cast<Q_UINT32>(in[j]) | | ||
1123 | (static_cast<Q_UINT32>(in[j+1]) << 8) | | ||
1124 | (static_cast<Q_UINT32>(in[j+2]) << 16) | | ||
1125 | (static_cast<Q_UINT32>(in[j+3]) << 24); | ||
1126 | #endif | ||
1127 | } | ||