summaryrefslogtreecommitdiffabout
path: root/microkde/kdecore/kmdcodec.cpp
Unidiff
Diffstat (limited to 'microkde/kdecore/kmdcodec.cpp') (more/less context) (show whitespace changes)
-rw-r--r--microkde/kdecore/kmdcodec.cpp1127
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
60const 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
72const 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
92const 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
104const 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
124const 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
130const unsigned int KCodecs::maxQPLineLength = 70;
131
132
133/******************************** KCodecs ********************************/
134// strchr(3) for broken systems.
135static 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
150QCString 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
157QCString 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
167void 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
283QCString KCodecs::quotedPrintableDecode(const QByteArray & in)
284{
285 QByteArray out;
286 quotedPrintableDecode (in, out);
287 return QCString (out.data(), out.size()+1);
288}
289
290QCString 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
300void 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
358QCString 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
368QCString 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
375void 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
447QCString 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
457QCString KCodecs::base64Decode( const QByteArray& in )
458{
459 QByteArray out;
460 base64Decode( in, out );
461 return QCString( out.data(), out.size()+1 );
462}
463
464void 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
545QCString 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
556QCString KCodecs::uuencode( const QByteArray& in )
557{
558 QByteArray out;
559 uuencode( in, out );
560 return QCString( out.data(), out.size()+1 );
561}
562
563void 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
642QCString 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
653QCString KCodecs::uudecode( const QByteArray& in )
654{
655 QByteArray out;
656 uudecode( in, out );
657 return QCString( out.data(), out.size()+1 );
658}
659
660void 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 ********************************/
747KMD5::KMD5()
748{
749 init();
750}
751
752KMD5::KMD5(const char *in, int len)
753{
754 init();
755 update(in, len);
756}
757
758KMD5::KMD5(const QByteArray& in)
759{
760 init();
761 update( in );
762}
763
764KMD5::KMD5(const QCString& in)
765{
766 init();
767 update( in );
768}
769
770void KMD5::update(const QByteArray& in)
771{
772 update(in.data(), int(in.size()));
773}
774
775void KMD5::update(const QCString& in)
776{
777 update(in.data(), int(in.length()));
778}
779
780void 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
823bool 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
834void 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
870bool KMD5::verify( const KMD5::Digest& digest)
871{
872 finalize();
873 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
874}
875
876bool KMD5::verify( const QCString& hexdigest)
877{
878 finalize();
879 return (0 == strcmp(hexDigest().data(), hexdigest));
880}
881
882const KMD5::Digest& KMD5::rawDigest()
883{
884 finalize();
885 return m_digest;
886}
887
888void KMD5::rawDigest( KMD5::Digest& bin )
889{
890 finalize();
891 memcpy( bin, m_digest, 16 );
892}
893
894
895QCString 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
908void 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
918QCString 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
928void KMD5::init()
929{
930 d = 0;
931 reset();
932}
933
934void 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
950void 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
1041inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
1042{
1043 return (x << n) | (x >> (32-n)) ;
1044}
1045
1046inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1047{
1048 return (x & y) | (~x & z);
1049}
1050
1051inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1052{
1053 return (x & z) | (y & ~z);
1054}
1055
1056inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1057{
1058 return x ^ y ^ z;
1059}
1060
1061inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1062{
1063 return y ^ (x | ~z);
1064}
1065
1066void 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
1073void 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
1080void 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
1087void 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
1095void 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.
1114void 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}