kdecore Library API Documentation

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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <stdio.h> 00041 #include <string.h> 00042 #include <stdlib.h> 00043 00044 #include <kswap.h> 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(register const char * _s, const char c) 00141 { 00142 register 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 QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF) 00156 { 00157 QByteArray out; 00158 quotedPrintableEncode (in, out, useCRLF); 00159 return QCString (out.data(), out.size()+1); 00160 } 00161 00162 QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF) 00163 { 00164 if (str.isEmpty()) 00165 return ""; 00166 00167 QByteArray in (str.length()); 00168 memcpy (in.data(), str.data(), str.length()); 00169 return quotedPrintableEncode(in, useCRLF); 00170 } 00171 00172 void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& 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 QCString KCodecs::quotedPrintableDecode(const QByteArray & in) 00289 { 00290 QByteArray out; 00291 quotedPrintableDecode (in, out); 00292 return QCString (out.data(), out.size()+1); 00293 } 00294 00295 QCString KCodecs::quotedPrintableDecode(const QCString & str) 00296 { 00297 if (str.isEmpty()) 00298 return ""; 00299 00300 QByteArray in (str.length()); 00301 memcpy (in.data(), str.data(), str.length()); 00302 return quotedPrintableDecode (in); 00303 } 00304 00305 void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& 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 = in[i + 1]; 00329 char c2 = 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 QCString KCodecs::base64Encode( const QCString& str, bool insertLFs ) 00364 { 00365 if ( str.isEmpty() ) 00366 return ""; 00367 00368 QByteArray in (str.length()); 00369 memcpy( in.data(), str.data(), str.length() ); 00370 return base64Encode( in, insertLFs ); 00371 } 00372 00373 QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs ) 00374 { 00375 QByteArray out; 00376 base64Encode( in, out, insertLFs ); 00377 return QCString( out.data(), out.size()+1 ); 00378 } 00379 00380 void KCodecs::base64Encode( const QByteArray& in, QByteArray& 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 QCString KCodecs::base64Decode( const QCString& str ) 00453 { 00454 if ( str.isEmpty() ) 00455 return ""; 00456 00457 QByteArray in( str.length() ); 00458 memcpy( in.data(), str.data(), str.length() ); 00459 return base64Decode( in ); 00460 } 00461 00462 QCString KCodecs::base64Decode( const QByteArray& in ) 00463 { 00464 QByteArray out; 00465 base64Decode( in, out ); 00466 return QCString( out.data(), out.size()+1 ); 00467 } 00468 00469 void KCodecs::base64Decode( const QByteArray& in, QByteArray& 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 ( strncasecmp(data+count, "begin", 5) == 0 ) 00485 { 00486 count += 5; 00487 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00488 count++; 00489 00490 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00491 count ++; 00492 00493 data += count; 00494 tail = (len -= count); 00495 } 00496 00497 // Find the tail end of the actual encoded data even if 00498 // there is/are trailing CR and/or LF. 00499 while ( data[tail-1] == '=' || data[tail-1] == '\n' || 00500 data[tail-1] == '\r' ) 00501 if ( data[--tail] != '=' ) len = tail; 00502 00503 unsigned int outIdx = 0; 00504 out.resize( (count=len) ); 00505 for (unsigned int idx = 0; idx < count; idx++) 00506 { 00507 // Adhere to RFC 2045 and ignore characters 00508 // that are not part of the encoding table. 00509 unsigned char ch = data[idx]; 00510 if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || 00511 (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') 00512 { 00513 out[outIdx++] = Base64DecMap[ch]; 00514 } 00515 else 00516 { 00517 len--; 00518 tail--; 00519 } 00520 } 00521 00522 // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl; 00523 00524 // 4-byte to 3-byte conversion 00525 len = (tail>(len/4)) ? tail-(len/4) : 0; 00526 unsigned int sidx = 0, didx = 0; 00527 if ( len > 1 ) 00528 { 00529 while (didx < len-2) 00530 { 00531 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00532 out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00533 out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077)); 00534 sidx += 4; 00535 didx += 3; 00536 } 00537 } 00538 00539 if (didx < len) 00540 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00541 00542 if (++didx < len ) 00543 out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00544 00545 // Resize the output buffer 00546 if ( len == 0 || len < out.size() ) 00547 out.resize(len); 00548 } 00549 00550 QCString KCodecs::uuencode( const QCString& str ) 00551 { 00552 if ( str.isEmpty() ) 00553 return ""; 00554 00555 QByteArray in; 00556 in.resize( str.length() ); 00557 memcpy( in.data(), str.data(), str.length() ); 00558 return uuencode( in ); 00559 } 00560 00561 QCString KCodecs::uuencode( const QByteArray& in ) 00562 { 00563 QByteArray out; 00564 uuencode( in, out ); 00565 return QCString( out.data(), out.size()+1 ); 00566 } 00567 00568 void KCodecs::uuencode( const QByteArray& in, QByteArray& out ) 00569 { 00570 out.resize( 0 ); 00571 if( in.isEmpty() ) 00572 return; 00573 00574 unsigned int sidx = 0; 00575 unsigned int didx = 0; 00576 unsigned int line_len = 45; 00577 00578 const char nl[] = "\n"; 00579 const char* data = in.data(); 00580 const unsigned int nl_len = strlen(nl); 00581 const unsigned int len = in.size(); 00582 00583 out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); 00584 // split into lines, adding line-length and line terminator 00585 while (sidx+line_len < len) 00586 { 00587 // line length 00588 out[didx++] = UUEncMap[line_len]; 00589 00590 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00591 for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) 00592 { 00593 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00594 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00595 (data[sidx] << 4) & 077]; 00596 out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 | 00597 (data[sidx+1] << 2) & 077]; 00598 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00599 } 00600 00601 // line terminator 00602 //for (unsigned int idx=0; idx < nl_len; idx++) 00603 //out[didx++] = nl[idx]; 00604 memcpy(out.data()+didx, nl, nl_len); 00605 didx += nl_len; 00606 } 00607 00608 // line length 00609 out[didx++] = UUEncMap[len-sidx]; 00610 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00611 while (sidx+2 < len) 00612 { 00613 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00614 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00615 (data[sidx] << 4) & 077]; 00616 out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 | 00617 (data[sidx+1] << 2) & 077]; 00618 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00619 sidx += 3; 00620 } 00621 00622 if (sidx < len-1) 00623 { 00624 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00625 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00626 (data[sidx] << 4) & 077]; 00627 out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077]; 00628 out[didx++] = UUEncMap[0]; 00629 } 00630 else if (sidx < len) 00631 { 00632 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00633 out[didx++] = UUEncMap[(data[sidx] << 4) & 077]; 00634 out[didx++] = UUEncMap[0]; 00635 out[didx++] = UUEncMap[0]; 00636 } 00637 00638 // line terminator 00639 memcpy(out.data()+didx, nl, nl_len); 00640 didx += nl_len; 00641 00642 // sanity check 00643 if ( didx != out.size() ) 00644 out.resize( 0 ); 00645 } 00646 00647 QCString KCodecs::uudecode( const QCString& str ) 00648 { 00649 if ( str.isEmpty() ) 00650 return ""; 00651 00652 QByteArray in; 00653 in.resize( str.length() ); 00654 memcpy( in.data(), str.data(), str.length() ); 00655 return uudecode( in ); 00656 } 00657 00658 QCString KCodecs::uudecode( const QByteArray& in ) 00659 { 00660 QByteArray out; 00661 uudecode( in, out ); 00662 return QCString( out.data(), out.size()+1 ); 00663 } 00664 00665 void KCodecs::uudecode( const QByteArray& in, QByteArray& out ) 00666 { 00667 out.resize( 0 ); 00668 if( in.isEmpty() ) 00669 return; 00670 00671 unsigned int sidx = 0; 00672 unsigned int didx = 0; 00673 unsigned int len = in.size(); 00674 unsigned int line_len, end; 00675 const char* data = in.data(); 00676 00677 // Deal with *nix "BEGIN"/"END" separators!! 00678 unsigned int count = 0; 00679 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00680 data[count] == '\t' || data[count] == ' ') ) 00681 count ++; 00682 00683 bool hasLF = false; 00684 if ( strncasecmp( data+count, "begin", 5) == 0 ) 00685 { 00686 count += 5; 00687 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00688 count ++; 00689 00690 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00691 count ++; 00692 00693 data += count; 00694 len -= count; 00695 hasLF = true; 00696 } 00697 00698 out.resize( len/4*3 ); 00699 while ( sidx < len ) 00700 { 00701 // get line length (in number of encoded octets) 00702 line_len = UUDecMap[ (unsigned char) data[sidx++]]; 00703 // ascii printable to 0-63 and 4-byte to 3-byte conversion 00704 end = didx+line_len; 00705 char A, B, C, D; 00706 if (end > 2) { 00707 while (didx < end-2) 00708 { 00709 A = UUDecMap[(unsigned char) data[sidx]]; 00710 B = UUDecMap[(unsigned char) data[sidx+1]]; 00711 C = UUDecMap[(unsigned char) data[sidx+2]]; 00712 D = UUDecMap[(unsigned char) data[sidx+3]]; 00713 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00714 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00715 out[didx++] = ( ((C << 6) & 255) | (D & 077) ); 00716 sidx += 4; 00717 } 00718 } 00719 00720 if (didx < end) 00721 { 00722 A = UUDecMap[(unsigned char) data[sidx]]; 00723 B = UUDecMap[(unsigned char) data[sidx+1]]; 00724 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00725 } 00726 00727 if (didx < end) 00728 { 00729 B = UUDecMap[(unsigned char) data[sidx+1]]; 00730 C = UUDecMap[(unsigned char) data[sidx+2]]; 00731 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00732 } 00733 00734 // skip padding 00735 while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') 00736 sidx++; 00737 00738 // skip end of line 00739 while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) 00740 sidx++; 00741 00742 // skip the "END" separator when present. 00743 if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 ) 00744 break; 00745 } 00746 00747 if ( didx < out.size() ) 00748 out.resize( didx ); 00749 } 00750 00751 /******************************** KMD5 ********************************/ 00752 KMD5::KMD5() 00753 { 00754 init(); 00755 } 00756 00757 KMD5::KMD5(const char *in, int len) 00758 { 00759 init(); 00760 update(in, len); 00761 } 00762 00763 KMD5::KMD5(const QByteArray& in) 00764 { 00765 init(); 00766 update( in ); 00767 } 00768 00769 KMD5::KMD5(const QCString& in) 00770 { 00771 init(); 00772 update( in ); 00773 } 00774 00775 void KMD5::update(const QByteArray& in) 00776 { 00777 update(in.data(), int(in.size())); 00778 } 00779 00780 void KMD5::update(const QCString& in) 00781 { 00782 update(in.data(), int(in.length())); 00783 } 00784 00785 void KMD5::update(const unsigned char* in, int len) 00786 { 00787 if (len < 0) 00788 len = qstrlen(reinterpret_cast<const char*>(in)); 00789 00790 if (!len) 00791 return; 00792 00793 if (m_finalized) { 00794 kdWarning() << "KMD5::update called after state was finalized!" << endl; 00795 return; 00796 } 00797 00798 Q_UINT32 in_index; 00799 Q_UINT32 buffer_index; 00800 Q_UINT32 buffer_space; 00801 Q_UINT32 in_length = static_cast<Q_UINT32>( len ); 00802 00803 buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F); 00804 00805 if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) 00806 m_count[1]++; 00807 00808 m_count[1] += (in_length >> 29); 00809 buffer_space = 64 - buffer_index; 00810 00811 if (in_length >= buffer_space) 00812 { 00813 memcpy (m_buffer + buffer_index, in, buffer_space); 00814 transform (m_buffer); 00815 00816 for (in_index = buffer_space; in_index + 63 < in_length; 00817 in_index += 64) 00818 transform (reinterpret_cast<const unsigned char*>(in+in_index)); 00819 00820 buffer_index = 0; 00821 } 00822 else 00823 in_index=0; 00824 00825 memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); 00826 } 00827 00828 bool KMD5::update(QIODevice& file) 00829 { 00830 char buffer[1024]; 00831 int len; 00832 00833 while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) 00834 update(buffer, len); 00835 00836 return file.atEnd(); 00837 } 00838 00839 void KMD5::finalize () 00840 { 00841 if (m_finalized) return; 00842 00843 Q_UINT8 bits[8]; 00844 Q_UINT32 index, padLen; 00845 static const unsigned char PADDING[64]= 00846 { 00847 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00850 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00851 }; 00852 00853 encode (bits, m_count, 8); 00854 //memcpy( bits, m_count, 8 ); 00855 00856 // Pad out to 56 mod 64. 00857 index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f); 00858 padLen = (index < 56) ? (56 - index) : (120 - index); 00859 update (reinterpret_cast<const char*>(PADDING), padLen); 00860 00861 // Append length (before padding) 00862 update (reinterpret_cast<const char*>(bits), 8); 00863 00864 // Store state in digest 00865 encode (m_digest, m_state, 16); 00866 //memcpy( m_digest, m_state, 16 ); 00867 00868 // Fill sensitive information with zero's 00869 memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); 00870 00871 m_finalized = true; 00872 } 00873 00874 00875 bool KMD5::verify( const KMD5::Digest& digest) 00876 { 00877 finalize(); 00878 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); 00879 } 00880 00881 bool KMD5::verify( const QCString& hexdigest) 00882 { 00883 finalize(); 00884 return (0 == strcmp(hexDigest().data(), hexdigest)); 00885 } 00886 00887 const KMD5::Digest& KMD5::rawDigest() 00888 { 00889 finalize(); 00890 return m_digest; 00891 } 00892 00893 void KMD5::rawDigest( KMD5::Digest& bin ) 00894 { 00895 finalize(); 00896 memcpy( bin, m_digest, 16 ); 00897 } 00898 00899 00900 QCString KMD5::hexDigest() 00901 { 00902 QCString s(33); 00903 00904 finalize(); 00905 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00906 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00907 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00908 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00909 00910 return s; 00911 } 00912 00913 void KMD5::hexDigest(QCString& s) 00914 { 00915 finalize(); 00916 s.resize(33); 00917 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00918 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00919 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00920 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00921 } 00922 00923 QCString KMD5::base64Digest() 00924 { 00925 QByteArray ba(16); 00926 00927 finalize(); 00928 memcpy(ba.data(), m_digest, 16); 00929 return KCodecs::base64Encode(ba); 00930 } 00931 00932 00933 void KMD5::init() 00934 { 00935 d = 0; 00936 reset(); 00937 } 00938 00939 void KMD5::reset() 00940 { 00941 m_finalized = false; 00942 00943 m_count[0] = 0; 00944 m_count[1] = 0; 00945 00946 m_state[0] = 0x67452301; 00947 m_state[1] = 0xefcdab89; 00948 m_state[2] = 0x98badcfe; 00949 m_state[3] = 0x10325476; 00950 00951 memset ( m_buffer, 0, sizeof(*m_buffer)); 00952 memset ( m_digest, 0, sizeof(*m_digest)); 00953 } 00954 00955 void KMD5::transform( const unsigned char block[64] ) 00956 { 00957 00958 Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; 00959 00960 decode (x, block, 64); 00961 //memcpy( x, block, 64 ); 00962 00963 Q_ASSERT(!m_finalized); // not just a user error, since the method is private 00964 00965 /* Round 1 */ 00966 FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ 00967 FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ 00968 FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ 00969 FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ 00970 FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ 00971 FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ 00972 FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ 00973 FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ 00974 FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ 00975 FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ 00976 FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ 00977 FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ 00978 FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ 00979 FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ 00980 FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ 00981 FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ 00982 00983 /* Round 2 */ 00984 GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ 00985 GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ 00986 GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ 00987 GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ 00988 GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ 00989 GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ 00990 GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ 00991 GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ 00992 GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ 00993 GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ 00994 GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ 00995 GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ 00996 GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ 00997 GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ 00998 GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ 00999 GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ 01000 01001 /* Round 3 */ 01002 HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ 01003 HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ 01004 HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ 01005 HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ 01006 HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ 01007 HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ 01008 HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ 01009 HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ 01010 HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ 01011 HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ 01012 HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ 01013 HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ 01014 HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ 01015 HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ 01016 HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ 01017 HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ 01018 01019 /* Round 4 */ 01020 II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ 01021 II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ 01022 II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ 01023 II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ 01024 II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ 01025 II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ 01026 II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ 01027 II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ 01028 II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ 01029 II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ 01030 II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ 01031 II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ 01032 II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ 01033 II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ 01034 II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ 01035 II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ 01036 01037 m_state[0] += a; 01038 m_state[1] += b; 01039 m_state[2] += c; 01040 m_state[3] += d; 01041 01042 memset ( static_cast<void *>(x), 0, sizeof(x) ); 01043 } 01044 01045 inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n) 01046 { 01047 return (x << n) | (x >> (32-n)) ; 01048 } 01049 01050 inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01051 { 01052 return (x & y) | (~x & z); 01053 } 01054 01055 inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01056 { 01057 return (x & z) | (y & ~z); 01058 } 01059 01060 inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01061 { 01062 return x ^ y ^ z; 01063 } 01064 01065 inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01066 { 01067 return y ^ (x | ~z); 01068 } 01069 01070 void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01071 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) 01072 { 01073 a += F(b, c, d) + x + ac; 01074 a = rotate_left (a, s) +b; 01075 } 01076 01077 void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01078 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac) 01079 { 01080 a += G(b, c, d) + x + ac; 01081 a = rotate_left (a, s) +b; 01082 } 01083 01084 void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01085 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) 01086 { 01087 a += H(b, c, d) + x + ac; 01088 a = rotate_left (a, s) +b; 01089 } 01090 01091 void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01092 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) 01093 { 01094 a += I(b, c, d) + x + ac; 01095 a = rotate_left (a, s) +b; 01096 } 01097 01098 01099 void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ) 01100 { 01101 #if !defined(WORDS_BIGENDIAN) 01102 memcpy(output, in, len); 01103 01104 #else 01105 Q_UINT32 i, j; 01106 for (i = 0, j = 0; j < len; i++, j += 4) 01107 { 01108 output[j] = static_cast<Q_UINT8>((in[i] & 0xff)); 01109 output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff)); 01110 output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff)); 01111 output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff)); 01112 } 01113 #endif 01114 } 01115 01116 // Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a 01117 // multiple of 4. 01118 void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len) 01119 { 01120 #if !defined(WORDS_BIGENDIAN) 01121 memcpy(output, in, len); 01122 01123 #else 01124 Q_UINT32 i, j; 01125 for (i = 0, j = 0; j < len; i++, j += 4) 01126 output[i] = static_cast<Q_UINT32>(in[j]) | 01127 (static_cast<Q_UINT32>(in[j+1]) << 8) | 01128 (static_cast<Q_UINT32>(in[j+2]) << 16) | 01129 (static_cast<Q_UINT32>(in[j+3]) << 24); 01130 #endif 01131 } 01132 01133 01134 01135 /**************************************************************/ 01136 01137 01138 01139 /***********************************************************/ 01140 01141 KMD4::KMD4() 01142 { 01143 init(); 01144 } 01145 01146 KMD4::KMD4(const char *in, int len) 01147 { 01148 init(); 01149 update(in, len); 01150 } 01151 01152 KMD4::KMD4(const QByteArray& in) 01153 { 01154 init(); 01155 update( in ); 01156 } 01157 01158 KMD4::KMD4(const QCString& in) 01159 { 01160 init(); 01161 update( in ); 01162 } 01163 01164 void KMD4::update(const QByteArray& in) 01165 { 01166 update(in.data(), int(in.size())); 01167 } 01168 01169 void KMD4::update(const QCString& in) 01170 { 01171 update(in.data(), int(in.length())); 01172 } 01173 01174 /* 01175 * Update context to reflect the concatenation of another buffer full 01176 * of bytes. 01177 */ 01178 void KMD4::update(const unsigned char *in, int len) 01179 { 01180 if (len < 0) 01181 len = qstrlen(reinterpret_cast<const char*>(in)); 01182 01183 if (!len) 01184 return; 01185 01186 if (m_finalized) { 01187 kdWarning() << "KMD4::update called after state was finalized!" << endl; 01188 return; 01189 } 01190 01191 Q_UINT32 t; 01192 01193 /* Update bitcount */ 01194 01195 t = m_count[0]; 01196 if ((m_count[0] = t + ((Q_UINT32) len << 3)) < t) 01197 m_count[1]++; /* Carry from low to high */ 01198 m_count[1] += len >> 29; 01199 01200 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ 01201 01202 /* Handle any leading odd-sized chunks */ 01203 01204 if (t) 01205 { 01206 Q_UINT8 *p = &m_buffer[ t ]; 01207 01208 t = 64 - t; 01209 if ((Q_UINT32)len < t) 01210 { 01211 memcpy (p, in, len); 01212 return; 01213 } 01214 memcpy (p, in, t); 01215 byteReverse (m_buffer, 16); 01216 transform (m_state, (Q_UINT32*) m_buffer); 01217 in += t; 01218 len -= t; 01219 } 01220 /* Process data in 64-byte chunks */ 01221 01222 while (len >= 64) 01223 { 01224 memcpy (m_buffer, in, 64); 01225 byteReverse (m_buffer, 16); 01226 transform (m_state, (Q_UINT32 *) m_buffer); 01227 in += 64; 01228 len -= 64; 01229 } 01230 01231 /* Handle any remaining bytes of data. */ 01232 01233 memcpy (m_buffer, in, len); 01234 } 01235 01236 bool KMD4::update(QIODevice& file) 01237 { 01238 char buffer[1024]; 01239 int len; 01240 01241 while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) 01242 update(buffer, len); 01243 01244 return file.atEnd(); 01245 } 01246 01247 /* 01248 * Final wrapup - pad to 64-byte boundary with the bit pattern 01249 * 1 0* (64-bit count of bits processed, MSB-first) 01250 */ 01251 void KMD4::finalize() 01252 { 01253 unsigned int count; 01254 unsigned char *p; 01255 01256 /* Compute number of bytes mod 64 */ 01257 count = (m_count[0] >> 3) & 0x3F; 01258 01259 /* Set the first char of padding to 0x80. This is safe since there is 01260 always at least one byte free */ 01261 p = m_buffer + count; 01262 *p++ = 0x80; 01263 01264 /* Bytes of padding needed to make 64 bytes */ 01265 count = 64 - 1 - count; 01266 01267 /* Pad out to 56 mod 64 */ 01268 if (count < 8) 01269 { 01270 /* Two lots of padding: Pad the first block to 64 bytes */ 01271 memset (p, 0, count); 01272 byteReverse (m_buffer, 16); 01273 transform (m_state, (Q_UINT32*) m_buffer); 01274 01275 /* Now fill the next block with 56 bytes */ 01276 memset (m_buffer, 0, 56); 01277 } 01278 else 01279 { 01280 /* Pad block to 56 bytes */ 01281 memset (p, 0, count - 8); 01282 } 01283 byteReverse (m_buffer, 14); 01284 01285 /* Append length in bits and transform */ 01286 ((Q_UINT32 *) m_buffer)[14] = m_count[0]; 01287 ((Q_UINT32 *) m_buffer)[15] = m_count[1]; 01288 01289 transform (m_state, (Q_UINT32 *) m_buffer); 01290 byteReverse ((unsigned char *) m_state, 4); 01291 01292 memcpy (m_digest, m_state, 16); 01293 memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); 01294 01295 m_finalized = true; 01296 } 01297 01298 bool KMD4::verify( const KMD4::Digest& digest) 01299 { 01300 finalize(); 01301 return (0 == memcmp(rawDigest(), digest, sizeof(KMD4::Digest))); 01302 } 01303 01304 bool KMD4::verify( const QCString& hexdigest) 01305 { 01306 finalize(); 01307 return (0 == strcmp(hexDigest().data(), hexdigest)); 01308 } 01309 01310 const KMD4::Digest& KMD4::rawDigest() 01311 { 01312 finalize(); 01313 return m_digest; 01314 } 01315 01316 void KMD4::rawDigest( KMD4::Digest& bin ) 01317 { 01318 finalize(); 01319 memcpy( bin, m_digest, 16 ); 01320 } 01321 01322 QCString KMD4::hexDigest() 01323 { 01324 QCString s(33); 01325 01326 finalize(); 01327 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 01328 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 01329 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 01330 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 01331 // kdDebug() << "KMD4::hexDigest() " << s << endl; 01332 return s; 01333 } 01334 01335 void KMD4::hexDigest(QCString& s) 01336 { 01337 finalize(); 01338 s.resize(33); 01339 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 01340 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 01341 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 01342 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 01343 } 01344 01345 QCString KMD4::base64Digest() 01346 { 01347 QByteArray ba(16); 01348 01349 finalize(); 01350 memcpy(ba.data(), m_digest, 16); 01351 return KCodecs::base64Encode(ba); 01352 } 01353 01354 01355 void KMD4::init() 01356 { 01357 d = 0; 01358 reset(); 01359 } 01360 01361 /* 01362 * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious 01363 * initialization constants. 01364 */ 01365 void KMD4::reset() 01366 { 01367 m_finalized = false; 01368 01369 m_state[0] = 0x67452301; 01370 m_state[1] = 0xefcdab89; 01371 m_state[2] = 0x98badcfe; 01372 m_state[3] = 0x10325476; 01373 01374 m_count[0] = 0; 01375 m_count[1] = 0; 01376 01377 memset ( m_buffer, 0, sizeof(*m_buffer)); 01378 memset ( m_digest, 0, sizeof(*m_digest)); 01379 } 01380 01381 //#define rotl32(x,n) (((x) << ((Q_UINT32)(n))) | ((x) >> (32 - (Q_UINT32)(n)))) 01382 01383 inline Q_UINT32 KMD4::rotate_left (Q_UINT32 x, Q_UINT32 n) 01384 { 01385 return (x << n) | (x >> (32-n)) ; 01386 } 01387 01388 inline Q_UINT32 KMD4::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01389 { 01390 return (x & y) | (~x & z); 01391 } 01392 01393 inline Q_UINT32 KMD4::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01394 { 01395 return ((x) & (y)) | ((x) & (z)) | ((y) & (z)); 01396 } 01397 01398 inline Q_UINT32 KMD4::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01399 { 01400 return x ^ y ^ z; 01401 } 01402 01403 inline void KMD4::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01404 Q_UINT32 x, Q_UINT32 s ) 01405 { 01406 a += F(b, c, d) + x; 01407 a = rotate_left (a, s); 01408 } 01409 01410 inline void KMD4::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01411 Q_UINT32 x, Q_UINT32 s) 01412 { 01413 a += G(b, c, d) + x + (Q_UINT32)0x5a827999; 01414 a = rotate_left (a, s); 01415 } 01416 01417 inline void KMD4::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01418 Q_UINT32 x, Q_UINT32 s ) 01419 { 01420 a += H(b, c, d) + x + (Q_UINT32)0x6ed9eba1; 01421 a = rotate_left (a, s); 01422 } 01423 01424 void KMD4::byteReverse( unsigned char *buf, Q_UINT32 len ) 01425 { 01426 Q_UINT32 *b = (Q_UINT32*) buf; 01427 while ( len > 0 ) { 01428 *b = KFromToLittleEndian( *b ); 01429 len--; 01430 b++; 01431 } 01432 } 01433 01434 /* 01435 * The core of the MD4 algorithm 01436 */ 01437 void KMD4::transform( Q_UINT32 buf[4], Q_UINT32 const in[16] ) 01438 { 01439 Q_UINT32 a, b, c, d; 01440 01441 a = buf[0]; 01442 b = buf[1]; 01443 c = buf[2]; 01444 d = buf[3]; 01445 01446 FF (a, b, c, d, in[0], 3); /* 1 */ 01447 FF (d, a, b, c, in[1], 7); /* 2 */ 01448 FF (c, d, a, b, in[2], 11); /* 3 */ 01449 FF (b, c, d, a, in[3], 19); /* 4 */ 01450 FF (a, b, c, d, in[4], 3); /* 5 */ 01451 FF (d, a, b, c, in[5], 7); /* 6 */ 01452 FF (c, d, a, b, in[6], 11); /* 7 */ 01453 FF (b, c, d, a, in[7], 19); /* 8 */ 01454 FF (a, b, c, d, in[8], 3); /* 9 */ 01455 FF (d, a, b, c, in[9], 7); /* 10 */ 01456 FF (c, d, a, b, in[10], 11); /* 11 */ 01457 FF (b, c, d, a, in[11], 19); /* 12 */ 01458 FF (a, b, c, d, in[12], 3); /* 13 */ 01459 FF (d, a, b, c, in[13], 7); /* 14 */ 01460 FF (c, d, a, b, in[14], 11); /* 15 */ 01461 FF (b, c, d, a, in[15], 19); /* 16 */ 01462 01463 GG (a, b, c, d, in[0], 3); /* 17 */ 01464 GG (d, a, b, c, in[4], 5); /* 18 */ 01465 GG (c, d, a, b, in[8], 9); /* 19 */ 01466 GG (b, c, d, a, in[12], 13); /* 20 */ 01467 GG (a, b, c, d, in[1], 3); /* 21 */ 01468 GG (d, a, b, c, in[5], 5); /* 22 */ 01469 GG (c, d, a, b, in[9], 9); /* 23 */ 01470 GG (b, c, d, a, in[13], 13); /* 24 */ 01471 GG (a, b, c, d, in[2], 3); /* 25 */ 01472 GG (d, a, b, c, in[6], 5); /* 26 */ 01473 GG (c, d, a, b, in[10], 9); /* 27 */ 01474 GG (b, c, d, a, in[14], 13); /* 28 */ 01475 GG (a, b, c, d, in[3], 3); /* 29 */ 01476 GG (d, a, b, c, in[7], 5); /* 30 */ 01477 GG (c, d, a, b, in[11], 9); /* 31 */ 01478 GG (b, c, d, a, in[15], 13); /* 32 */ 01479 01480 HH (a, b, c, d, in[0], 3); /* 33 */ 01481 HH (d, a, b, c, in[8], 9); /* 34 */ 01482 HH (c, d, a, b, in[4], 11); /* 35 */ 01483 HH (b, c, d, a, in[12], 15); /* 36 */ 01484 HH (a, b, c, d, in[2], 3); /* 37 */ 01485 HH (d, a, b, c, in[10], 9); /* 38 */ 01486 HH (c, d, a, b, in[6], 11); /* 39 */ 01487 HH (b, c, d, a, in[14], 15); /* 40 */ 01488 HH (a, b, c, d, in[1], 3); /* 41 */ 01489 HH (d, a, b, c, in[9], 9); /* 42 */ 01490 HH (c, d, a, b, in[5], 11); /* 43 */ 01491 HH (b, c, d, a, in[13], 15); /* 44 */ 01492 HH (a, b, c, d, in[3], 3); /* 45 */ 01493 HH (d, a, b, c, in[11], 9); /* 46 */ 01494 HH (c, d, a, b, in[7], 11); /* 47 */ 01495 HH (b, c, d, a, in[15], 15); /* 48 */ 01496 01497 01498 buf[0] += a; 01499 buf[1] += b; 01500 buf[2] += c; 01501 buf[3] += d; 01502 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:47:37 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003