kmdcodec.cpp
00001 /* 00002 Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> 00003 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU Lesser General Public License (LGPL) 00007 version 2 as published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this program; if not, write to the Free Software 00016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 00018 RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. 00019 RSA Data Security, Inc. Created 1991. All rights reserved. 00020 00021 The KMD5 class is based on a C++ implementation of 00022 "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by 00023 Mordechai T. Abzug, Copyright (c) 1995. This implementation 00024 passes the test-suite as defined in RFC 1321. 00025 00026 The encoding and decoding utilities in KCodecs with the exception of 00027 quoted-printable are based on the java implementation in HTTPClient 00028 package by Ronald Tschal�r Copyright (C) 1996-1999. 00029 00030 The quoted-printable codec as described in RFC 2045, section 6.7. is by 00031 Rik Hemsley (C) 2001. 00032 00033 KMD4 class based on the LGPL code of Copyright (C) 2001 Nikos Mavroyanopoulos 00034 The algorithm is due to Ron Rivest. This code is based on code 00035 written by Colin Plumb in 1993. 00036 */ 00037 00038 #include <config.h> 00039 00040 #include <ctype.h> 00041 #include <stdio.h> 00042 #include <string.h> 00043 #include <stdlib.h> 00044 00045 #include <kdebug.h> 00046 #include "kmdcodec.h" 00047 00048 #define KMD5_S11 7 00049 #define KMD5_S12 12 00050 #define KMD5_S13 17 00051 #define KMD5_S14 22 00052 #define KMD5_S21 5 00053 #define KMD5_S22 9 00054 #define KMD5_S23 14 00055 #define KMD5_S24 20 00056 #define KMD5_S31 4 00057 #define KMD5_S32 11 00058 #define KMD5_S33 16 00059 #define KMD5_S34 23 00060 #define KMD5_S41 6 00061 #define KMD5_S42 10 00062 #define KMD5_S43 15 00063 #define KMD5_S44 21 00064 00065 const char KCodecs::Base64EncMap[64] = 00066 { 00067 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 00068 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 00069 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 00070 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 00071 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 00072 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 00073 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 00074 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F 00075 }; 00076 00077 const char KCodecs::Base64DecMap[128] = 00078 { 00079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00080 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00084 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, 00085 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 00086 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00087 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 00088 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 00089 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 00090 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 00091 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 00092 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 00093 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 00094 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 00095 }; 00096 00097 const char KCodecs::UUEncMap[64] = 00098 { 00099 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 00100 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 00101 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 00102 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 00103 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 00104 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 00105 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 00106 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F 00107 }; 00108 00109 const char KCodecs::UUDecMap[128] = 00110 { 00111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00115 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 00116 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 00117 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 00118 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 00119 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 00120 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 00121 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 00122 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 00123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00127 }; 00128 00129 const char KCodecs::hexChars[16] = 00130 { 00131 '0', '1', '2', '3', '4', '5', '6', '7', 00132 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 00133 }; 00134 00135 const unsigned int KCodecs::maxQPLineLength = 70; 00136 00137 00138 /******************************** KCodecs ********************************/ 00139 // strchr(3) for broken systems. 00140 static int rikFindChar(const char * _s, const char c) 00141 { 00142 const char * s = _s; 00143 00144 while (true) 00145 { 00146 if ((0 == *s) || (c == *s)) break; ++s; 00147 if ((0 == *s) || (c == *s)) break; ++s; 00148 if ((0 == *s) || (c == *s)) break; ++s; 00149 if ((0 == *s) || (c == *s)) break; ++s; 00150 } 00151 00152 return s - _s; 00153 } 00154 00155 TQCString KCodecs::quotedPrintableEncode(const TQByteArray& in, bool useCRLF) 00156 { 00157 TQByteArray out; 00158 quotedPrintableEncode (in, out, useCRLF); 00159 return TQCString (out.data(), out.size()+1); 00160 } 00161 00162 TQCString KCodecs::quotedPrintableEncode(const TQCString& str, bool useCRLF) 00163 { 00164 if (str.isEmpty()) 00165 return ""; 00166 00167 TQByteArray in (str.length()); 00168 memcpy (in.data(), str.data(), str.length()); 00169 return quotedPrintableEncode(in, useCRLF); 00170 } 00171 00172 void KCodecs::quotedPrintableEncode(const TQByteArray& in, TQByteArray& out, bool useCRLF) 00173 { 00174 out.resize (0); 00175 if (in.isEmpty()) 00176 return; 00177 00178 char *cursor; 00179 const char *data; 00180 unsigned int lineLength; 00181 unsigned int pos; 00182 00183 const unsigned int length = in.size(); 00184 const unsigned int end = length - 1; 00185 00186 00187 // Reasonable guess for output size when we're encoding 00188 // mostly-ASCII data. It doesn't really matter, because 00189 // the underlying allocation routines are quite efficient, 00190 // but it's nice to have 0 allocations in many cases. 00191 out.resize ((length*12)/10); 00192 cursor = out.data(); 00193 data = in.data(); 00194 lineLength = 0; 00195 pos = 0; 00196 00197 for (unsigned int i = 0; i < length; i++) 00198 { 00199 unsigned char c (data[i]); 00200 00201 // check if we have to enlarge the output buffer, use 00202 // a safety margin of 16 byte 00203 pos = cursor-out.data(); 00204 if (out.size()-pos < 16) { 00205 out.resize(out.size()+4096); 00206 cursor = out.data()+pos; 00207 } 00208 00209 // Plain ASCII chars just go straight out. 00210 00211 if ((c >= 33) && (c <= 126) && ('=' != c)) 00212 { 00213 *cursor++ = c; 00214 ++lineLength; 00215 } 00216 00217 // Spaces need some thought. We have to encode them at eol (or eof). 00218 00219 else if (' ' == c) 00220 { 00221 if 00222 ( 00223 (i >= length) 00224 || 00225 ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2])) 00226 || 00227 (!useCRLF && ('\n' == data[i + 1])))) 00228 ) 00229 { 00230 *cursor++ = '='; 00231 *cursor++ = '2'; 00232 *cursor++ = '0'; 00233 00234 lineLength += 3; 00235 } 00236 else 00237 { 00238 *cursor++ = ' '; 00239 ++lineLength; 00240 } 00241 } 00242 // If we find a line break, just let it through. 00243 else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) || 00244 (!useCRLF && ('\n' == c))) 00245 { 00246 lineLength = 0; 00247 00248 if (useCRLF) { 00249 *cursor++ = '\r'; 00250 *cursor++ = '\n'; 00251 ++i; 00252 } else { 00253 *cursor++ = '\n'; 00254 } 00255 } 00256 00257 // Anything else is converted to =XX. 00258 00259 else 00260 { 00261 *cursor++ = '='; 00262 *cursor++ = hexChars[c / 16]; 00263 *cursor++ = hexChars[c % 16]; 00264 00265 lineLength += 3; 00266 } 00267 00268 // If we're approaching the maximum line length, do a soft line break. 00269 00270 if ((lineLength > maxQPLineLength) && (i < end)) 00271 { 00272 if (useCRLF) { 00273 *cursor++ = '='; 00274 *cursor++ = '\r'; 00275 *cursor++ = '\n'; 00276 } else { 00277 *cursor++ = '='; 00278 *cursor++ = '\n'; 00279 } 00280 00281 lineLength = 0; 00282 } 00283 } 00284 00285 out.truncate(cursor - out.data()); 00286 } 00287 00288 TQCString KCodecs::quotedPrintableDecode(const TQByteArray & in) 00289 { 00290 TQByteArray out; 00291 quotedPrintableDecode (in, out); 00292 return TQCString (out.data(), out.size()+1); 00293 } 00294 00295 TQCString KCodecs::quotedPrintableDecode(const TQCString & str) 00296 { 00297 if (str.isEmpty()) 00298 return ""; 00299 00300 TQByteArray in (str.length()); 00301 memcpy (in.data(), str.data(), str.length()); 00302 return quotedPrintableDecode (in); 00303 } 00304 00305 void KCodecs::quotedPrintableDecode(const TQByteArray& in, TQByteArray& out) 00306 { 00307 // clear out the output buffer 00308 out.resize (0); 00309 if (in.isEmpty()) 00310 return; 00311 00312 char *cursor; 00313 const char *data; 00314 const unsigned int length = in.size(); 00315 00316 data = in.data(); 00317 out.resize (length); 00318 cursor = out.data(); 00319 00320 for (unsigned int i = 0; i < length; i++) 00321 { 00322 char c(in[i]); 00323 00324 if ('=' == c) 00325 { 00326 if (i < length - 2) 00327 { 00328 char c1 = toupper(in[i + 1]); 00329 char c2 = toupper(in[i + 2]); 00330 00331 if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) 00332 { 00333 // Soft line break. No output. 00334 if ('\r' == c1) 00335 i += 2; // CRLF line breaks 00336 else 00337 i += 1; 00338 } 00339 else 00340 { 00341 // =XX encoded byte. 00342 00343 int hexChar0 = rikFindChar(hexChars, c1); 00344 int hexChar1 = rikFindChar(hexChars, c2); 00345 00346 if (hexChar0 < 16 && hexChar1 < 16) 00347 { 00348 *cursor++ = char((hexChar0 * 16) | hexChar1); 00349 i += 2; 00350 } 00351 } 00352 } 00353 } 00354 else 00355 { 00356 *cursor++ = c; 00357 } 00358 } 00359 00360 out.truncate(cursor - out.data()); 00361 } 00362 00363 TQCString KCodecs::base64Encode( const TQCString& str, bool insertLFs ) 00364 { 00365 if ( str.isEmpty() ) 00366 return ""; 00367 00368 TQByteArray in (str.length()); 00369 memcpy( in.data(), str.data(), str.length() ); 00370 return base64Encode( in, insertLFs ); 00371 } 00372 00373 TQCString KCodecs::base64Encode( const TQByteArray& in, bool insertLFs ) 00374 { 00375 TQByteArray out; 00376 base64Encode( in, out, insertLFs ); 00377 return TQCString( out.data(), out.size()+1 ); 00378 } 00379 00380 void KCodecs::base64Encode( const TQByteArray& in, TQByteArray& out, 00381 bool insertLFs ) 00382 { 00383 // clear out the output buffer 00384 out.resize (0); 00385 if ( in.isEmpty() ) 00386 return; 00387 00388 unsigned int sidx = 0; 00389 unsigned int didx = 0; 00390 const char* data = in.data(); 00391 const unsigned int len = in.size(); 00392 00393 unsigned int out_len = ((len+2)/3)*4; 00394 00395 // Deal with the 76 characters or less per 00396 // line limit specified in RFC 2045 on a 00397 // pre request basis. 00398 insertLFs = (insertLFs && out_len > 76); 00399 if ( insertLFs ) 00400 out_len += ((out_len-1)/76); 00401 00402 int count = 0; 00403 out.resize( out_len ); 00404 00405 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00406 if ( len > 1 ) 00407 { 00408 while (sidx < len-2) 00409 { 00410 if ( insertLFs ) 00411 { 00412 if ( count && (count%76) == 0 ) 00413 out[didx++] = '\n'; 00414 count += 4; 00415 } 00416 out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; 00417 out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 | 00418 (data[sidx] << 4) & 077]; 00419 out[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 | 00420 (data[sidx+1] << 2) & 077]; 00421 out[didx++] = Base64EncMap[data[sidx+2] & 077]; 00422 sidx += 3; 00423 } 00424 } 00425 00426 if (sidx < len) 00427 { 00428 if ( insertLFs && (count > 0) && (count%76) == 0 ) 00429 out[didx++] = '\n'; 00430 00431 out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; 00432 if (sidx < len-1) 00433 { 00434 out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 | 00435 (data[sidx] << 4) & 077]; 00436 out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077]; 00437 } 00438 else 00439 { 00440 out[didx++] = Base64EncMap[(data[sidx] << 4) & 077]; 00441 } 00442 } 00443 00444 // Add padding 00445 while (didx < out.size()) 00446 { 00447 out[didx] = '='; 00448 didx++; 00449 } 00450 } 00451 00452 TQCString KCodecs::base64Decode( const TQCString& str ) 00453 { 00454 if ( str.isEmpty() ) 00455 return ""; 00456 00457 TQByteArray in( str.length() ); 00458 memcpy( in.data(), str.data(), str.length() ); 00459 return base64Decode( in ); 00460 } 00461 00462 TQCString KCodecs::base64Decode( const TQByteArray& in ) 00463 { 00464 TQByteArray out; 00465 base64Decode( in, out ); 00466 return TQCString( out.data(), out.size()+1 ); 00467 } 00468 00469 void KCodecs::base64Decode( const TQByteArray& in, TQByteArray& out ) 00470 { 00471 out.resize(0); 00472 if ( in.isEmpty() ) 00473 return; 00474 00475 unsigned int count = 0; 00476 unsigned int len = in.size(), tail = len; 00477 const char* data = in.data(); 00478 00479 // Deal with possible *nix "BEGIN" marker!! 00480 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00481 data[count] == '\t' || data[count] == ' ') ) 00482 count++; 00483 00484 if ( count == len ) 00485 return; 00486 00487 if ( strncasecmp(data+count, "begin", 5) == 0 ) 00488 { 00489 count += 5; 00490 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00491 count++; 00492 00493 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00494 count ++; 00495 00496 data += count; 00497 tail = (len -= count); 00498 } 00499 00500 // Find the tail end of the actual encoded data even if 00501 // there is/are trailing CR and/or LF. 00502 while ( tail > 0 00503 && ( data[tail-1] == '=' || data[tail-1] == '\n' || data[tail-1] == '\r' ) ) 00504 if ( data[--tail] != '=' ) len = tail; 00505 00506 unsigned int outIdx = 0; 00507 out.resize( (count=len) ); 00508 for (unsigned int idx = 0; idx < count; idx++) 00509 { 00510 // Adhere to RFC 2045 and ignore characters 00511 // that are not part of the encoding table. 00512 unsigned char ch = data[idx]; 00513 if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || 00514 (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') 00515 { 00516 out[outIdx++] = Base64DecMap[ch]; 00517 } 00518 else 00519 { 00520 len--; 00521 tail--; 00522 } 00523 } 00524 00525 // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl; 00526 00527 // 4-byte to 3-byte conversion 00528 len = (tail>(len/4)) ? tail-(len/4) : 0; 00529 unsigned int sidx = 0, didx = 0; 00530 if ( len > 1 ) 00531 { 00532 while (didx < len-2) 00533 { 00534 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00535 out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00536 out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077)); 00537 sidx += 4; 00538 didx += 3; 00539 } 00540 } 00541 00542 if (didx < len) 00543 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00544 00545 if (++didx < len ) 00546 out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00547 00548 // Resize the output buffer 00549 if ( len == 0 || len < out.size() ) 00550 out.resize(len); 00551 } 00552 00553 TQCString KCodecs::uuencode( const TQCString& str ) 00554 { 00555 if ( str.isEmpty() ) 00556 return ""; 00557 00558 TQByteArray in; 00559 in.resize( str.length() ); 00560 memcpy( in.data(), str.data(), str.length() ); 00561 return uuencode( in ); 00562 } 00563 00564 TQCString KCodecs::uuencode( const TQByteArray& in ) 00565 { 00566 TQByteArray out; 00567 uuencode( in, out ); 00568 return TQCString( out.data(), out.size()+1 ); 00569 } 00570 00571 void KCodecs::uuencode( const TQByteArray& in, TQByteArray& out ) 00572 { 00573 out.resize( 0 ); 00574 if( in.isEmpty() ) 00575 return; 00576 00577 unsigned int sidx = 0; 00578 unsigned int didx = 0; 00579 unsigned int line_len = 45; 00580 00581 const char nl[] = "\n"; 00582 const char* data = in.data(); 00583 const unsigned int nl_len = strlen(nl); 00584 const unsigned int len = in.size(); 00585 00586 out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); 00587 // split into lines, adding line-length and line terminator 00588 while (sidx+line_len < len) 00589 { 00590 // line length 00591 out[didx++] = UUEncMap[line_len]; 00592 00593 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00594 for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) 00595 { 00596 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00597 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00598 (data[sidx] << 4) & 077]; 00599 out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 | 00600 (data[sidx+1] << 2) & 077]; 00601 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00602 } 00603 00604 // line terminator 00605 //for (unsigned int idx=0; idx < nl_len; idx++) 00606 //out[didx++] = nl[idx]; 00607 memcpy(out.data()+didx, nl, nl_len); 00608 didx += nl_len; 00609 } 00610 00611 // line length 00612 out[didx++] = UUEncMap[len-sidx]; 00613 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00614 while (sidx+2 < len) 00615 { 00616 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00617 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00618 (data[sidx] << 4) & 077]; 00619 out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 | 00620 (data[sidx+1] << 2) & 077]; 00621 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00622 sidx += 3; 00623 } 00624 00625 if (sidx < len-1) 00626 { 00627 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00628 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00629 (data[sidx] << 4) & 077]; 00630 out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077]; 00631 out[didx++] = UUEncMap[0]; 00632 } 00633 else if (sidx < len) 00634 { 00635 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00636 out[didx++] = UUEncMap[(data[sidx] << 4) & 077]; 00637 out[didx++] = UUEncMap[0]; 00638 out[didx++] = UUEncMap[0]; 00639 } 00640 00641 // line terminator 00642 memcpy(out.data()+didx, nl, nl_len); 00643 didx += nl_len; 00644 00645 // sanity check 00646 if ( didx != out.size() ) 00647 out.resize( 0 ); 00648 } 00649 00650 TQCString KCodecs::uudecode( const TQCString& str ) 00651 { 00652 if ( str.isEmpty() ) 00653 return ""; 00654 00655 TQByteArray in; 00656 in.resize( str.length() ); 00657 memcpy( in.data(), str.data(), str.length() ); 00658 return uudecode( in ); 00659 } 00660 00661 TQCString KCodecs::uudecode( const TQByteArray& in ) 00662 { 00663 TQByteArray out; 00664 uudecode( in, out ); 00665 return TQCString( out.data(), out.size()+1 ); 00666 } 00667 00668 void KCodecs::uudecode( const TQByteArray& in, TQByteArray& out ) 00669 { 00670 out.resize( 0 ); 00671 if( in.isEmpty() ) 00672 return; 00673 00674 unsigned int sidx = 0; 00675 unsigned int didx = 0; 00676 unsigned int len = in.size(); 00677 unsigned int line_len, end; 00678 const char* data = in.data(); 00679 00680 // Deal with *nix "BEGIN"/"END" separators!! 00681 unsigned int count = 0; 00682 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00683 data[count] == '\t' || data[count] == ' ') ) 00684 count ++; 00685 00686 bool hasLF = false; 00687 if ( strncasecmp( data+count, "begin", 5) == 0 ) 00688 { 00689 count += 5; 00690 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00691 count ++; 00692 00693 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00694 count ++; 00695 00696 data += count; 00697 len -= count; 00698 hasLF = true; 00699 } 00700 00701 out.resize( len/4*3 ); 00702 while ( sidx < len ) 00703 { 00704 // get line length (in number of encoded octets) 00705 line_len = UUDecMap[ (unsigned char) data[sidx++]]; 00706 // ascii printable to 0-63 and 4-byte to 3-byte conversion 00707 end = didx+line_len; 00708 char A, B, C, D; 00709 if (end > 2) { 00710 while (didx < end-2) 00711 { 00712 A = UUDecMap[(unsigned char) data[sidx]]; 00713 B = UUDecMap[(unsigned char) data[sidx+1]]; 00714 C = UUDecMap[(unsigned char) data[sidx+2]]; 00715 D = UUDecMap[(unsigned char) data[sidx+3]]; 00716 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00717 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00718 out[didx++] = ( ((C << 6) & 255) | (D & 077) ); 00719 sidx += 4; 00720 } 00721 } 00722 00723 if (didx < end) 00724 { 00725 A = UUDecMap[(unsigned char) data[sidx]]; 00726 B = UUDecMap[(unsigned char) data[sidx+1]]; 00727 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00728 } 00729 00730 if (didx < end) 00731 { 00732 B = UUDecMap[(unsigned char) data[sidx+1]]; 00733 C = UUDecMap[(unsigned char) data[sidx+2]]; 00734 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00735 } 00736 00737 // skip padding 00738 while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') 00739 sidx++; 00740 00741 // skip end of line 00742 while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) 00743 sidx++; 00744 00745 // skip the "END" separator when present. 00746 if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 ) 00747 break; 00748 } 00749 00750 if ( didx < out.size() ) 00751 out.resize( didx ); 00752 } 00753 00754 /******************************** KMD5 ********************************/ 00755 KMD5::KMD5() 00756 { 00757 init(); 00758 } 00759 00760 KMD5::KMD5(const char *in, int len) 00761 { 00762 init(); 00763 update(in, len); 00764 } 00765 00766 KMD5::KMD5(const TQByteArray& in) 00767 { 00768 init(); 00769 update( in ); 00770 } 00771 00772 KMD5::KMD5(const TQCString& in) 00773 { 00774 init(); 00775 update( in ); 00776 } 00777 00778 void KMD5::update(const TQByteArray& in) 00779 { 00780 update(in.data(), int(in.size())); 00781 } 00782 00783 void KMD5::update(const TQCString& in) 00784 { 00785 update(in.data(), int(in.length())); 00786 } 00787 00788 void KMD5::update(const unsigned char* in, int len) 00789 { 00790 if (len < 0) 00791 len = tqstrlen(reinterpret_cast<const char*>(in)); 00792 00793 if (!len) 00794 return; 00795 00796 if (m_finalized) { 00797 kdWarning() << "KMD5::update called after state was finalized!" << endl; 00798 return; 00799 } 00800 00801 TQ_UINT32 in_index; 00802 TQ_UINT32 buffer_index; 00803 TQ_UINT32 buffer_space; 00804 TQ_UINT32 in_length = static_cast<TQ_UINT32>( len ); 00805 00806 buffer_index = static_cast<TQ_UINT32>((m_count[0] >> 3) & 0x3F); 00807 00808 if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) 00809 m_count[1]++; 00810 00811 m_count[1] += (in_length >> 29); 00812 buffer_space = 64 - buffer_index; 00813 00814 if (in_length >= buffer_space) 00815 { 00816 memcpy (m_buffer + buffer_index, in, buffer_space); 00817 transform (m_buffer); 00818 00819 for (in_index = buffer_space; in_index + 63 < in_length; 00820 in_index += 64) 00821 transform (reinterpret_cast<const unsigned char*>(in+in_index)); 00822 00823 buffer_index = 0; 00824 } 00825 else 00826 in_index=0; 00827 00828 memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); 00829 } 00830 00831 bool KMD5::update(TQIODevice& file) 00832 { 00833 char buffer[1024]; 00834 int len; 00835 00836 while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) 00837 update(buffer, len); 00838 00839 return file.atEnd(); 00840 } 00841 00842 void KMD5::finalize () 00843 { 00844 if (m_finalized) return; 00845 00846 TQ_UINT8 bits[8]; 00847 TQ_UINT32 index, padLen; 00848 static const unsigned char PADDING[64]= 00849 { 00850 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00852 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00853 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00854 }; 00855 00856 encode (bits, m_count, 8); 00857 //memcpy( bits, m_count, 8 ); 00858 00859 // Pad out to 56 mod 64. 00860 index = static_cast<TQ_UINT32>((m_count[0] >> 3) & 0x3f); 00861 padLen = (index < 56) ? (56 - index) : (120 - index); 00862 update (reinterpret_cast<const char*>(PADDING), padLen); 00863 00864 // Append length (before padding) 00865 update (reinterpret_cast<const char*>(bits), 8); 00866 00867 // Store state in digest 00868 encode (m_digest, m_state, 16); 00869 //memcpy( m_digest, m_state, 16 ); 00870 00871 // Fill sensitive information with zero's 00872 memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); 00873 00874 m_finalized = true; 00875 } 00876 00877 00878 bool KMD5::verify( const KMD5::Digest& digest) 00879 { 00880 finalize(); 00881 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); 00882 } 00883 00884 bool KMD5::verify( const TQCString& hexdigest) 00885 { 00886 finalize(); 00887 return (0 == strcmp(hexDigest().data(), hexdigest)); 00888 } 00889 00890 const KMD5::Digest& KMD5::rawDigest() 00891 { 00892 finalize(); 00893 return m_digest; 00894 } 00895 00896 void KMD5::rawDigest( KMD5::Digest& bin ) 00897 { 00898 finalize(); 00899 memcpy( bin, m_digest, 16 ); 00900 } 00901 00902 00903 TQCString KMD5::hexDigest() 00904 { 00905 TQCString s(33); 00906 00907 finalize(); 00908 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00909 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00910 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00911 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00912 00913 return s; 00914 } 00915 00916 void KMD5::hexDigest(TQCString& s) 00917 { 00918 finalize(); 00919 s.resize(33); 00920 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00921 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00922 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00923 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00924 } 00925 00926 TQCString KMD5::base64Digest() 00927 { 00928 TQByteArray ba(16); 00929 00930 finalize(); 00931 memcpy(ba.data(), m_digest, 16); 00932 return KCodecs::base64Encode(ba); 00933 } 00934 00935 00936 void KMD5::init() 00937 { 00938 d = 0; 00939 reset(); 00940 } 00941 00942 void KMD5::reset() 00943 { 00944 m_finalized = false; 00945 00946 m_count[0] = 0; 00947 m_count[1] = 0; 00948 00949 m_state[0] = 0x67452301; 00950 m_state[1] = 0xefcdab89; 00951 m_state[2] = 0x98badcfe; 00952 m_state[3] = 0x10325476; 00953 00954 memset ( m_buffer, 0, sizeof(*m_buffer)); 00955 memset ( m_digest, 0, sizeof(*m_digest)); 00956 } 00957 00958 void KMD5::transform( const unsigned char block[64] ) 00959 { 00960 00961 TQ_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; 00962 00963 decode (x, block, 64); 00964 //memcpy( x, block, 64 ); 00965 00966 Q_ASSERT(!m_finalized); // not just a user error, since the method is private 00967 00968 /* Round 1 */ 00969 FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ 00970 FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ 00971 FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ 00972 FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ 00973 FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ 00974 FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ 00975 FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ 00976 FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ 00977 FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ 00978 FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ 00979 FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ 00980 FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ 00981 FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ 00982 FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ 00983 FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ 00984 FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ 00985 00986 /* Round 2 */ 00987 GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ 00988 GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ 00989 GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ 00990 GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ 00991 GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ 00992 GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ 00993 GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ 00994 GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ 00995 GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ 00996 GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ 00997 GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ 00998 GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ 00999 GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ 01000 GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ 01001 GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ 01002 GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ 01003 01004 /* Round 3 */ 01005 HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ 01006 HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ 01007 HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ 01008 HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ 01009 HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ 01010 HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ 01011 HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ 01012 HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ 01013 HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ 01014 HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ 01015 HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ 01016 HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ 01017 HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ 01018 HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ 01019 HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ 01020 HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ 01021 01022 /* Round 4 */ 01023 II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ 01024 II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ 01025 II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ 01026 II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ 01027 II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ 01028 II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ 01029 II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ 01030 II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ 01031 II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ 01032 II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ 01033 II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ 01034 II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ 01035 II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ 01036 II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ 01037 II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ 01038 II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ 01039 01040 m_state[0] += a; 01041 m_state[1] += b; 01042 m_state[2] += c; 01043 m_state[3] += d; 01044 01045 memset ( static_cast<void *>(x), 0, sizeof(x) ); 01046 } 01047 01048 inline TQ_UINT32 KMD5::rotate_left (TQ_UINT32 x, TQ_UINT32 n) 01049 { 01050 return (x << n) | (x >> (32-n)) ; 01051 } 01052 01053 inline TQ_UINT32 KMD5::F (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01054 { 01055 return (x & y) | (~x & z); 01056 } 01057 01058 inline TQ_UINT32 KMD5::G (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01059 { 01060 return (x & z) | (y & ~z); 01061 } 01062 01063 inline TQ_UINT32 KMD5::H (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01064 { 01065 return x ^ y ^ z; 01066 } 01067 01068 inline TQ_UINT32 KMD5::I (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01069 { 01070 return y ^ (x | ~z); 01071 } 01072 01073 void KMD5::FF ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01074 TQ_UINT32 x, TQ_UINT32 s, TQ_UINT32 ac ) 01075 { 01076 a += F(b, c, d) + x + ac; 01077 a = rotate_left (a, s) +b; 01078 } 01079 01080 void KMD5::GG ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01081 TQ_UINT32 x, TQ_UINT32 s, TQ_UINT32 ac) 01082 { 01083 a += G(b, c, d) + x + ac; 01084 a = rotate_left (a, s) +b; 01085 } 01086 01087 void KMD5::HH ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01088 TQ_UINT32 x, TQ_UINT32 s, TQ_UINT32 ac ) 01089 { 01090 a += H(b, c, d) + x + ac; 01091 a = rotate_left (a, s) +b; 01092 } 01093 01094 void KMD5::II ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01095 TQ_UINT32 x, TQ_UINT32 s, TQ_UINT32 ac ) 01096 { 01097 a += I(b, c, d) + x + ac; 01098 a = rotate_left (a, s) +b; 01099 } 01100 01101 01102 void KMD5::encode ( unsigned char* output, TQ_UINT32 *in, TQ_UINT32 len ) 01103 { 01104 #if !defined(WORDS_BIGENDIAN) 01105 memcpy(output, in, len); 01106 01107 #else 01108 TQ_UINT32 i, j; 01109 for (i = 0, j = 0; j < len; i++, j += 4) 01110 { 01111 output[j] = static_cast<TQ_UINT8>((in[i] & 0xff)); 01112 output[j+1] = static_cast<TQ_UINT8>(((in[i] >> 8) & 0xff)); 01113 output[j+2] = static_cast<TQ_UINT8>(((in[i] >> 16) & 0xff)); 01114 output[j+3] = static_cast<TQ_UINT8>(((in[i] >> 24) & 0xff)); 01115 } 01116 #endif 01117 } 01118 01119 // Decodes in (TQ_UINT8) into output (TQ_UINT32). Assumes len is a 01120 // multiple of 4. 01121 void KMD5::decode (TQ_UINT32 *output, const unsigned char* in, TQ_UINT32 len) 01122 { 01123 #if !defined(WORDS_BIGENDIAN) 01124 memcpy(output, in, len); 01125 01126 #else 01127 TQ_UINT32 i, j; 01128 for (i = 0, j = 0; j < len; i++, j += 4) 01129 output[i] = static_cast<TQ_UINT32>(in[j]) | 01130 (static_cast<TQ_UINT32>(in[j+1]) << 8) | 01131 (static_cast<TQ_UINT32>(in[j+2]) << 16) | 01132 (static_cast<TQ_UINT32>(in[j+3]) << 24); 01133 #endif 01134 } 01135 01136 01137 01138 /**************************************************************/ 01139 01140 01141 01142 /***********************************************************/ 01143 01144 KMD4::KMD4() 01145 { 01146 init(); 01147 } 01148 01149 KMD4::KMD4(const char *in, int len) 01150 { 01151 init(); 01152 update(in, len); 01153 } 01154 01155 KMD4::KMD4(const TQByteArray& in) 01156 { 01157 init(); 01158 update( in ); 01159 } 01160 01161 KMD4::KMD4(const TQCString& in) 01162 { 01163 init(); 01164 update( in ); 01165 } 01166 01167 void KMD4::update(const TQByteArray& in) 01168 { 01169 update(in.data(), int(in.size())); 01170 } 01171 01172 void KMD4::update(const TQCString& in) 01173 { 01174 update(in.data(), int(in.length())); 01175 } 01176 01177 /* 01178 * Update context to reflect the concatenation of another buffer full 01179 * of bytes. 01180 */ 01181 void KMD4::update(const unsigned char *in, int len) 01182 { 01183 if (len < 0) 01184 len = tqstrlen(reinterpret_cast<const char*>(in)); 01185 01186 if (!len) 01187 return; 01188 01189 if (m_finalized) { 01190 kdWarning() << "KMD4::update called after state was finalized!" << endl; 01191 return; 01192 } 01193 01194 TQ_UINT32 t; 01195 01196 /* Update bitcount */ 01197 01198 t = m_count[0]; 01199 if ((m_count[0] = t + ((TQ_UINT32) len << 3)) < t) 01200 m_count[1]++; /* Carry from low to high */ 01201 m_count[1] += len >> 29; 01202 01203 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ 01204 01205 /* Handle any leading odd-sized chunks */ 01206 01207 if (t) 01208 { 01209 TQ_UINT8 *p = &m_buffer[ t ]; 01210 01211 t = 64 - t; 01212 if ((TQ_UINT32)len < t) 01213 { 01214 memcpy (p, in, len); 01215 return; 01216 } 01217 memcpy (p, in, t); 01218 byteReverse (m_buffer, 16); 01219 transform (m_state, (TQ_UINT32*) m_buffer); 01220 in += t; 01221 len -= t; 01222 } 01223 /* Process data in 64-byte chunks */ 01224 01225 while (len >= 64) 01226 { 01227 memcpy (m_buffer, in, 64); 01228 byteReverse (m_buffer, 16); 01229 transform (m_state, (TQ_UINT32 *) m_buffer); 01230 in += 64; 01231 len -= 64; 01232 } 01233 01234 /* Handle any remaining bytes of data. */ 01235 01236 memcpy (m_buffer, in, len); 01237 } 01238 01239 bool KMD4::update(TQIODevice& file) 01240 { 01241 char buffer[1024]; 01242 int len; 01243 01244 while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) 01245 update(buffer, len); 01246 01247 return file.atEnd(); 01248 } 01249 01250 /* 01251 * Final wrapup - pad to 64-byte boundary with the bit pattern 01252 * 1 0* (64-bit count of bits processed, MSB-first) 01253 */ 01254 void KMD4::finalize() 01255 { 01256 unsigned int count; 01257 unsigned char *p; 01258 01259 /* Compute number of bytes mod 64 */ 01260 count = (m_count[0] >> 3) & 0x3F; 01261 01262 /* Set the first char of padding to 0x80. This is safe since there is 01263 always at least one byte free */ 01264 p = m_buffer + count; 01265 *p++ = 0x80; 01266 01267 /* Bytes of padding needed to make 64 bytes */ 01268 count = 64 - 1 - count; 01269 01270 /* Pad out to 56 mod 64 */ 01271 if (count < 8) 01272 { 01273 /* Two lots of padding: Pad the first block to 64 bytes */ 01274 memset (p, 0, count); 01275 byteReverse (m_buffer, 16); 01276 transform (m_state, (TQ_UINT32*) m_buffer); 01277 01278 /* Now fill the next block with 56 bytes */ 01279 memset (m_buffer, 0, 56); 01280 } 01281 else 01282 { 01283 /* Pad block to 56 bytes */ 01284 memset (p, 0, count - 8); 01285 } 01286 byteReverse (m_buffer, 14); 01287 01288 /* Append length in bits and transform */ 01289 ((TQ_UINT32 *) m_buffer)[14] = m_count[0]; 01290 ((TQ_UINT32 *) m_buffer)[15] = m_count[1]; 01291 01292 transform (m_state, (TQ_UINT32 *) m_buffer); 01293 byteReverse ((unsigned char *) m_state, 4); 01294 01295 memcpy (m_digest, m_state, 16); 01296 memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); 01297 01298 m_finalized = true; 01299 } 01300 01301 bool KMD4::verify( const KMD4::Digest& digest) 01302 { 01303 finalize(); 01304 return (0 == memcmp(rawDigest(), digest, sizeof(KMD4::Digest))); 01305 } 01306 01307 bool KMD4::verify( const TQCString& hexdigest) 01308 { 01309 finalize(); 01310 return (0 == strcmp(hexDigest().data(), hexdigest)); 01311 } 01312 01313 const KMD4::Digest& KMD4::rawDigest() 01314 { 01315 finalize(); 01316 return m_digest; 01317 } 01318 01319 void KMD4::rawDigest( KMD4::Digest& bin ) 01320 { 01321 finalize(); 01322 memcpy( bin, m_digest, 16 ); 01323 } 01324 01325 TQCString KMD4::hexDigest() 01326 { 01327 TQCString s(33); 01328 01329 finalize(); 01330 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 01331 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 01332 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 01333 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 01334 // kdDebug() << "KMD4::hexDigest() " << s << endl; 01335 return s; 01336 } 01337 01338 void KMD4::hexDigest(TQCString& s) 01339 { 01340 finalize(); 01341 s.resize(33); 01342 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 01343 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 01344 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 01345 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 01346 } 01347 01348 TQCString KMD4::base64Digest() 01349 { 01350 TQByteArray ba(16); 01351 01352 finalize(); 01353 memcpy(ba.data(), m_digest, 16); 01354 return KCodecs::base64Encode(ba); 01355 } 01356 01357 01358 void KMD4::init() 01359 { 01360 d = 0; 01361 reset(); 01362 } 01363 01364 /* 01365 * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious 01366 * initialization constants. 01367 */ 01368 void KMD4::reset() 01369 { 01370 m_finalized = false; 01371 01372 m_state[0] = 0x67452301; 01373 m_state[1] = 0xefcdab89; 01374 m_state[2] = 0x98badcfe; 01375 m_state[3] = 0x10325476; 01376 01377 m_count[0] = 0; 01378 m_count[1] = 0; 01379 01380 memset ( m_buffer, 0, sizeof(*m_buffer)); 01381 memset ( m_digest, 0, sizeof(*m_digest)); 01382 } 01383 01384 //#define rotl32(x,n) (((x) << ((TQ_UINT32)(n))) | ((x) >> (32 - (TQ_UINT32)(n)))) 01385 01386 inline TQ_UINT32 KMD4::rotate_left (TQ_UINT32 x, TQ_UINT32 n) 01387 { 01388 return (x << n) | (x >> (32-n)) ; 01389 } 01390 01391 inline TQ_UINT32 KMD4::F (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01392 { 01393 return (x & y) | (~x & z); 01394 } 01395 01396 inline TQ_UINT32 KMD4::G (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01397 { 01398 return ((x) & (y)) | ((x) & (z)) | ((y) & (z)); 01399 } 01400 01401 inline TQ_UINT32 KMD4::H (TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 z) 01402 { 01403 return x ^ y ^ z; 01404 } 01405 01406 inline void KMD4::FF ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01407 TQ_UINT32 x, TQ_UINT32 s ) 01408 { 01409 a += F(b, c, d) + x; 01410 a = rotate_left (a, s); 01411 } 01412 01413 inline void KMD4::GG ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01414 TQ_UINT32 x, TQ_UINT32 s) 01415 { 01416 a += G(b, c, d) + x + (TQ_UINT32)0x5a827999; 01417 a = rotate_left (a, s); 01418 } 01419 01420 inline void KMD4::HH ( TQ_UINT32& a, TQ_UINT32 b, TQ_UINT32 c, TQ_UINT32 d, 01421 TQ_UINT32 x, TQ_UINT32 s ) 01422 { 01423 a += H(b, c, d) + x + (TQ_UINT32)0x6ed9eba1; 01424 a = rotate_left (a, s); 01425 } 01426 01427 void KMD4::byteReverse( unsigned char *buf, TQ_UINT32 len ) 01428 { 01429 #ifdef WORDS_BIGENDIAN 01430 TQ_UINT32 *b = (TQ_UINT32*) buf; 01431 while ( len > 0 ) { 01432 *b = ((((*b) & 0xff000000) >> 24) | (((*b) & 0x00ff0000) >> 8) | 01433 (((*b) & 0x0000ff00) << 8) | (((*b) & 0x000000ff) << 24)); 01434 len--; 01435 b++; 01436 } 01437 #else 01438 Q_UNUSED(buf) 01439 Q_UNUSED(len) 01440 #endif 01441 } 01442 01443 /* 01444 * The core of the MD4 algorithm 01445 */ 01446 void KMD4::transform( TQ_UINT32 buf[4], TQ_UINT32 const in[16] ) 01447 { 01448 TQ_UINT32 a, b, c, d; 01449 01450 a = buf[0]; 01451 b = buf[1]; 01452 c = buf[2]; 01453 d = buf[3]; 01454 01455 FF (a, b, c, d, in[0], 3); /* 1 */ 01456 FF (d, a, b, c, in[1], 7); /* 2 */ 01457 FF (c, d, a, b, in[2], 11); /* 3 */ 01458 FF (b, c, d, a, in[3], 19); /* 4 */ 01459 FF (a, b, c, d, in[4], 3); /* 5 */ 01460 FF (d, a, b, c, in[5], 7); /* 6 */ 01461 FF (c, d, a, b, in[6], 11); /* 7 */ 01462 FF (b, c, d, a, in[7], 19); /* 8 */ 01463 FF (a, b, c, d, in[8], 3); /* 9 */ 01464 FF (d, a, b, c, in[9], 7); /* 10 */ 01465 FF (c, d, a, b, in[10], 11); /* 11 */ 01466 FF (b, c, d, a, in[11], 19); /* 12 */ 01467 FF (a, b, c, d, in[12], 3); /* 13 */ 01468 FF (d, a, b, c, in[13], 7); /* 14 */ 01469 FF (c, d, a, b, in[14], 11); /* 15 */ 01470 FF (b, c, d, a, in[15], 19); /* 16 */ 01471 01472 GG (a, b, c, d, in[0], 3); /* 17 */ 01473 GG (d, a, b, c, in[4], 5); /* 18 */ 01474 GG (c, d, a, b, in[8], 9); /* 19 */ 01475 GG (b, c, d, a, in[12], 13); /* 20 */ 01476 GG (a, b, c, d, in[1], 3); /* 21 */ 01477 GG (d, a, b, c, in[5], 5); /* 22 */ 01478 GG (c, d, a, b, in[9], 9); /* 23 */ 01479 GG (b, c, d, a, in[13], 13); /* 24 */ 01480 GG (a, b, c, d, in[2], 3); /* 25 */ 01481 GG (d, a, b, c, in[6], 5); /* 26 */ 01482 GG (c, d, a, b, in[10], 9); /* 27 */ 01483 GG (b, c, d, a, in[14], 13); /* 28 */ 01484 GG (a, b, c, d, in[3], 3); /* 29 */ 01485 GG (d, a, b, c, in[7], 5); /* 30 */ 01486 GG (c, d, a, b, in[11], 9); /* 31 */ 01487 GG (b, c, d, a, in[15], 13); /* 32 */ 01488 01489 HH (a, b, c, d, in[0], 3); /* 33 */ 01490 HH (d, a, b, c, in[8], 9); /* 34 */ 01491 HH (c, d, a, b, in[4], 11); /* 35 */ 01492 HH (b, c, d, a, in[12], 15); /* 36 */ 01493 HH (a, b, c, d, in[2], 3); /* 37 */ 01494 HH (d, a, b, c, in[10], 9); /* 38 */ 01495 HH (c, d, a, b, in[6], 11); /* 39 */ 01496 HH (b, c, d, a, in[14], 15); /* 40 */ 01497 HH (a, b, c, d, in[1], 3); /* 41 */ 01498 HH (d, a, b, c, in[9], 9); /* 42 */ 01499 HH (c, d, a, b, in[5], 11); /* 43 */ 01500 HH (b, c, d, a, in[13], 15); /* 44 */ 01501 HH (a, b, c, d, in[3], 3); /* 45 */ 01502 HH (d, a, b, c, in[11], 9); /* 46 */ 01503 HH (c, d, a, b, in[7], 11); /* 47 */ 01504 HH (b, c, d, a, in[15], 15); /* 48 */ 01505 01506 01507 buf[0] += a; 01508 buf[1] += b; 01509 buf[2] += c; 01510 buf[3] += d; 01511 }