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