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 00034 #include <config.h> 00035 00036 #include <stdio.h> 00037 #include <string.h> 00038 #include <stdlib.h> 00039 00040 #include <kdebug.h> 00041 #include "kmdcodec.h" 00042 00043 #define KMD5_S11 7 00044 #define KMD5_S12 12 00045 #define KMD5_S13 17 00046 #define KMD5_S14 22 00047 #define KMD5_S21 5 00048 #define KMD5_S22 9 00049 #define KMD5_S23 14 00050 #define KMD5_S24 20 00051 #define KMD5_S31 4 00052 #define KMD5_S32 11 00053 #define KMD5_S33 16 00054 #define KMD5_S34 23 00055 #define KMD5_S41 6 00056 #define KMD5_S42 10 00057 #define KMD5_S43 15 00058 #define KMD5_S44 21 00059 00060 const char KCodecs::Base64EncMap[64] = 00061 { 00062 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 00063 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 00064 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 00065 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 00066 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 00067 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 00068 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 00069 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F 00070 }; 00071 00072 const char KCodecs::Base64DecMap[128] = 00073 { 00074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00079 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, 00080 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 00081 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00082 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 00083 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 00084 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 00085 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 00086 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 00087 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 00088 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 00089 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 00090 }; 00091 00092 const char KCodecs::UUEncMap[64] = 00093 { 00094 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 00095 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 00096 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 00097 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 00098 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 00099 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 00100 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 00101 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F 00102 }; 00103 00104 const char KCodecs::UUDecMap[128] = 00105 { 00106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00110 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 00111 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 00112 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 00113 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 00114 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 00115 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 00116 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 00117 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 00118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00122 }; 00123 00124 const char KCodecs::hexChars[16] = 00125 { 00126 '0', '1', '2', '3', '4', '5', '6', '7', 00127 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 00128 }; 00129 00130 const unsigned int KCodecs::maxQPLineLength = 70; 00131 00132 00133 /******************************** KCodecs ********************************/ 00134 // strchr(3) for broken systems. 00135 static int rikFindChar(register const char * _s, const char c) 00136 { 00137 register const char * s = _s; 00138 00139 while (true) 00140 { 00141 if ((0 == *s) || (c == *s)) break; ++s; 00142 if ((0 == *s) || (c == *s)) break; ++s; 00143 if ((0 == *s) || (c == *s)) break; ++s; 00144 if ((0 == *s) || (c == *s)) break; ++s; 00145 } 00146 00147 return s - _s; 00148 } 00149 00150 QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF) 00151 { 00152 QByteArray out; 00153 quotedPrintableEncode (in, out, useCRLF); 00154 return QCString (out.data(), out.size()+1); 00155 } 00156 00157 QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF) 00158 { 00159 if (str.isEmpty()) 00160 return ""; 00161 00162 QByteArray in (str.length()); 00163 memcpy (in.data(), str.data(), str.length()); 00164 return quotedPrintableEncode(in, useCRLF); 00165 } 00166 00167 void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF) 00168 { 00169 out.resize (0); 00170 if (in.isEmpty()) 00171 return; 00172 00173 char *cursor; 00174 const char *data; 00175 unsigned int lineLength; 00176 unsigned int pos; 00177 00178 const unsigned int length = in.size(); 00179 const unsigned int end = length - 1; 00180 00181 00182 // Reasonable guess for output size when we're encoding 00183 // mostly-ASCII data. It doesn't really matter, because 00184 // the underlying allocation routines are quite efficient, 00185 // but it's nice to have 0 allocations in many cases. 00186 out.resize ((length*12)/10); 00187 cursor = out.data(); 00188 data = in.data(); 00189 lineLength = 0; 00190 pos = 0; 00191 00192 for (unsigned int i = 0; i < length; i++) 00193 { 00194 unsigned char c (data[i]); 00195 00196 // check if we have to enlarge the output buffer, use 00197 // a safety margin of 16 byte 00198 pos = cursor-out.data(); 00199 if (out.size()-pos < 16) { 00200 out.resize(out.size()+4096); 00201 cursor = out.data()+pos; 00202 } 00203 00204 // Plain ASCII chars just go straight out. 00205 00206 if ((c >= 33) && (c <= 126) && ('=' != c)) 00207 { 00208 *cursor++ = c; 00209 ++lineLength; 00210 } 00211 00212 // Spaces need some thought. We have to encode them at eol (or eof). 00213 00214 else if (' ' == c) 00215 { 00216 if 00217 ( 00218 (i >= length) 00219 || 00220 ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2])) 00221 || 00222 (!useCRLF && ('\n' == data[i + 1])))) 00223 ) 00224 { 00225 *cursor++ = '='; 00226 *cursor++ = '2'; 00227 *cursor++ = '0'; 00228 00229 lineLength += 3; 00230 } 00231 else 00232 { 00233 *cursor++ = ' '; 00234 ++lineLength; 00235 } 00236 } 00237 // If we find a line break, just let it through. 00238 else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) || 00239 (!useCRLF && ('\n' == c))) 00240 { 00241 lineLength = 0; 00242 00243 if (useCRLF) { 00244 *cursor++ = '\r'; 00245 *cursor++ = '\n'; 00246 ++i; 00247 } else { 00248 *cursor++ = '\n'; 00249 } 00250 } 00251 00252 // Anything else is converted to =XX. 00253 00254 else 00255 { 00256 *cursor++ = '='; 00257 *cursor++ = hexChars[c / 16]; 00258 *cursor++ = hexChars[c % 16]; 00259 00260 lineLength += 3; 00261 } 00262 00263 // If we're approaching the maximum line length, do a soft line break. 00264 00265 if ((lineLength > maxQPLineLength) && (i < end)) 00266 { 00267 if (useCRLF) { 00268 *cursor++ = '='; 00269 *cursor++ = '\r'; 00270 *cursor++ = '\n'; 00271 } else { 00272 *cursor++ = '='; 00273 *cursor++ = '\n'; 00274 } 00275 00276 lineLength = 0; 00277 } 00278 } 00279 00280 out.truncate(cursor - out.data()); 00281 } 00282 00283 QCString KCodecs::quotedPrintableDecode(const QByteArray & in) 00284 { 00285 QByteArray out; 00286 quotedPrintableDecode (in, out); 00287 return QCString (out.data(), out.size()+1); 00288 } 00289 00290 QCString KCodecs::quotedPrintableDecode(const QCString & str) 00291 { 00292 if (str.isEmpty()) 00293 return ""; 00294 00295 QByteArray in (str.length()); 00296 memcpy (in.data(), str.data(), str.length()); 00297 return quotedPrintableDecode (in); 00298 } 00299 00300 void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out) 00301 { 00302 // clear out the output buffer 00303 out.resize (0); 00304 if (in.isEmpty()) 00305 return; 00306 00307 char *cursor; 00308 const char *data; 00309 const unsigned int length = in.size(); 00310 00311 data = in.data(); 00312 out.resize (length); 00313 cursor = out.data(); 00314 00315 for (unsigned int i = 0; i < length; i++) 00316 { 00317 char c(in[i]); 00318 00319 if ('=' == c) 00320 { 00321 if (i < length - 2) 00322 { 00323 char c1 = in[i + 1]; 00324 char c2 = in[i + 2]; 00325 00326 if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) 00327 { 00328 // Soft line break. No output. 00329 if ('\r' == c1) 00330 i += 2; // CRLF line breaks 00331 else 00332 i += 1; 00333 } 00334 else 00335 { 00336 // =XX encoded byte. 00337 00338 int hexChar0 = rikFindChar(hexChars, c1); 00339 int hexChar1 = rikFindChar(hexChars, c2); 00340 00341 if (hexChar0 < 16 && hexChar1 < 16) 00342 { 00343 *cursor++ = char((hexChar0 * 16) | hexChar1); 00344 i += 2; 00345 } 00346 } 00347 } 00348 } 00349 else 00350 { 00351 *cursor++ = c; 00352 } 00353 } 00354 00355 out.truncate(cursor - out.data()); 00356 } 00357 00358 QCString KCodecs::base64Encode( const QCString& str, bool insertLFs ) 00359 { 00360 if ( str.isEmpty() ) 00361 return ""; 00362 00363 QByteArray in (str.length()); 00364 memcpy( in.data(), str.data(), str.length() ); 00365 return base64Encode( in, insertLFs ); 00366 } 00367 00368 QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs ) 00369 { 00370 QByteArray out; 00371 base64Encode( in, out, insertLFs ); 00372 return QCString( out.data(), out.size()+1 ); 00373 } 00374 00375 void KCodecs::base64Encode( const QByteArray& in, QByteArray& out, 00376 bool insertLFs ) 00377 { 00378 // clear out the output buffer 00379 out.resize (0); 00380 if ( in.isEmpty() ) 00381 return; 00382 00383 unsigned int sidx = 0; 00384 unsigned int didx = 0; 00385 const char* data = in.data(); 00386 const unsigned int len = in.size(); 00387 00388 unsigned int out_len = ((len+2)/3)*4; 00389 00390 // Deal with the 76 characters or less per 00391 // line limit specified in RFC 2045 on a 00392 // pre request basis. 00393 insertLFs = (insertLFs && out_len > 76); 00394 if ( insertLFs ) 00395 out_len += ((out_len-1)/76); 00396 00397 int count = 0; 00398 out.resize( out_len ); 00399 00400 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00401 if ( len > 1 ) 00402 { 00403 while (sidx < len-2) 00404 { 00405 if ( insertLFs ) 00406 { 00407 if ( count && (count%76) == 0 ) 00408 out[didx++] = '\n'; 00409 count += 4; 00410 } 00411 out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; 00412 out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 | 00413 (data[sidx] << 4) & 077]; 00414 out[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 | 00415 (data[sidx+1] << 2) & 077]; 00416 out[didx++] = Base64EncMap[data[sidx+2] & 077]; 00417 sidx += 3; 00418 } 00419 } 00420 00421 if (sidx < len) 00422 { 00423 if ( insertLFs && (count > 0) && (count%76) == 0 ) 00424 out[didx++] = '\n'; 00425 00426 out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; 00427 if (sidx < len-1) 00428 { 00429 out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 | 00430 (data[sidx] << 4) & 077]; 00431 out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077]; 00432 } 00433 else 00434 { 00435 out[didx++] = Base64EncMap[(data[sidx] << 4) & 077]; 00436 } 00437 } 00438 00439 // Add padding 00440 while (didx < out.size()) 00441 { 00442 out[didx] = '='; 00443 didx++; 00444 } 00445 } 00446 00447 QCString KCodecs::base64Decode( const QCString& str ) 00448 { 00449 if ( str.isEmpty() ) 00450 return ""; 00451 00452 QByteArray in( str.length() ); 00453 memcpy( in.data(), str.data(), str.length() ); 00454 return base64Decode( in ); 00455 } 00456 00457 QCString KCodecs::base64Decode( const QByteArray& in ) 00458 { 00459 QByteArray out; 00460 base64Decode( in, out ); 00461 return QCString( out.data(), out.size()+1 ); 00462 } 00463 00464 void KCodecs::base64Decode( const QByteArray& in, QByteArray& out ) 00465 { 00466 out.resize(0); 00467 if ( in.isEmpty() ) 00468 return; 00469 00470 unsigned int count = 0; 00471 unsigned int len = in.size(), tail = len; 00472 const char* data = in.data(); 00473 00474 // Deal with possible *nix "BEGIN" marker!! 00475 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00476 data[count] == '\t' || data[count] == ' ') ) 00477 count++; 00478 00479 if ( strncasecmp(data+count, "begin", 5) == 0 ) 00480 { 00481 count += 5; 00482 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00483 count++; 00484 00485 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00486 count ++; 00487 00488 data += count; 00489 tail = (len -= count); 00490 } 00491 00492 // Find the tail end of the actual encoded data even if 00493 // there is/are trailing CR and/or LF. 00494 while ( data[tail-1] == '=' || data[tail-1] == '\n' || 00495 data[tail-1] == '\r' ) 00496 if ( data[--tail] != '=' ) len = tail; 00497 00498 unsigned int outIdx = 0; 00499 out.resize( (count=len) ); 00500 for (unsigned int idx = 0; idx < count; idx++) 00501 { 00502 // Adhere to RFC 2045 and ignore characters 00503 // that are not part of the encoding table. 00504 unsigned char ch = data[idx]; 00505 if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || 00506 (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') 00507 { 00508 out[outIdx++] = Base64DecMap[ch]; 00509 } 00510 else 00511 { 00512 len--; 00513 tail--; 00514 } 00515 } 00516 00517 // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl; 00518 00519 // 4-byte to 3-byte conversion 00520 len = (tail>(len/4)) ? tail-(len/4) : 0; 00521 unsigned int sidx = 0, didx = 0; 00522 if ( len > 1 ) 00523 { 00524 while (didx < len-2) 00525 { 00526 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00527 out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00528 out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077)); 00529 sidx += 4; 00530 didx += 3; 00531 } 00532 } 00533 00534 if (didx < len) 00535 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00536 00537 if (++didx < len ) 00538 out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00539 00540 // Resize the output buffer 00541 if ( len == 0 || len < out.size() ) 00542 out.resize(len); 00543 } 00544 00545 QCString KCodecs::uuencode( const QCString& str ) 00546 { 00547 if ( str.isEmpty() ) 00548 return ""; 00549 00550 QByteArray in; 00551 in.resize( str.length() ); 00552 memcpy( in.data(), str.data(), str.length() ); 00553 return uuencode( in ); 00554 } 00555 00556 QCString KCodecs::uuencode( const QByteArray& in ) 00557 { 00558 QByteArray out; 00559 uuencode( in, out ); 00560 return QCString( out.data(), out.size()+1 ); 00561 } 00562 00563 void KCodecs::uuencode( const QByteArray& in, QByteArray& out ) 00564 { 00565 out.resize( 0 ); 00566 if( in.isEmpty() ) 00567 return; 00568 00569 unsigned int sidx = 0; 00570 unsigned int didx = 0; 00571 unsigned int line_len = 45; 00572 00573 const char nl[] = "\n"; 00574 const char* data = in.data(); 00575 const unsigned int nl_len = strlen(nl); 00576 const unsigned int len = in.size(); 00577 00578 out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); 00579 // split into lines, adding line-length and line terminator 00580 while (sidx+line_len < len) 00581 { 00582 // line length 00583 out[didx++] = UUEncMap[line_len]; 00584 00585 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00586 for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) 00587 { 00588 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00589 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00590 (data[sidx] << 4) & 077]; 00591 out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 | 00592 (data[sidx+1] << 2) & 077]; 00593 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00594 } 00595 00596 // line terminator 00597 //for (unsigned int idx=0; idx < nl_len; idx++) 00598 //out[didx++] = nl[idx]; 00599 memcpy(out.data()+didx, nl, nl_len); 00600 didx += nl_len; 00601 } 00602 00603 // line length 00604 out[didx++] = UUEncMap[len-sidx]; 00605 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00606 while (sidx+2 < len) 00607 { 00608 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00609 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00610 (data[sidx] << 4) & 077]; 00611 out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 | 00612 (data[sidx+1] << 2) & 077]; 00613 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00614 sidx += 3; 00615 } 00616 00617 if (sidx < len-1) 00618 { 00619 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00620 out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 | 00621 (data[sidx] << 4) & 077]; 00622 out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077]; 00623 out[didx++] = UUEncMap[0]; 00624 } 00625 else if (sidx < len) 00626 { 00627 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00628 out[didx++] = UUEncMap[(data[sidx] << 4) & 077]; 00629 out[didx++] = UUEncMap[0]; 00630 out[didx++] = UUEncMap[0]; 00631 } 00632 00633 // line terminator 00634 memcpy(out.data()+didx, nl, nl_len); 00635 didx += nl_len; 00636 00637 // sanity check 00638 if ( didx != out.size() ) 00639 out.resize( 0 ); 00640 } 00641 00642 QCString KCodecs::uudecode( const QCString& str ) 00643 { 00644 if ( str.isEmpty() ) 00645 return ""; 00646 00647 QByteArray in; 00648 in.resize( str.length() ); 00649 memcpy( in.data(), str.data(), str.length() ); 00650 return uudecode( in ); 00651 } 00652 00653 QCString KCodecs::uudecode( const QByteArray& in ) 00654 { 00655 QByteArray out; 00656 uudecode( in, out ); 00657 return QCString( out.data(), out.size()+1 ); 00658 } 00659 00660 void KCodecs::uudecode( const QByteArray& in, QByteArray& out ) 00661 { 00662 out.resize( 0 ); 00663 if( in.isEmpty() ) 00664 return; 00665 00666 unsigned int sidx = 0; 00667 unsigned int didx = 0; 00668 unsigned int len = in.size(); 00669 unsigned int line_len, end; 00670 const char* data = in.data(); 00671 00672 // Deal with *nix "BEGIN"/"END" separators!! 00673 unsigned int count = 0; 00674 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00675 data[count] == '\t' || data[count] == ' ') ) 00676 count ++; 00677 00678 bool hasLF = false; 00679 if ( strncasecmp( data+count, "begin", 5) == 0 ) 00680 { 00681 count += 5; 00682 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00683 count ++; 00684 00685 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00686 count ++; 00687 00688 data += count; 00689 len -= count; 00690 hasLF = true; 00691 } 00692 00693 out.resize( len/4*3 ); 00694 while ( sidx < len ) 00695 { 00696 // get line length (in number of encoded octets) 00697 line_len = UUDecMap[ (unsigned char) data[sidx++]]; 00698 // ascii printable to 0-63 and 4-byte to 3-byte conversion 00699 end = didx+line_len; 00700 char A, B, C, D; 00701 if (end > 2) { 00702 while (didx < end-2) 00703 { 00704 A = UUDecMap[(unsigned char) data[sidx]]; 00705 B = UUDecMap[(unsigned char) data[sidx+1]]; 00706 C = UUDecMap[(unsigned char) data[sidx+2]]; 00707 D = UUDecMap[(unsigned char) data[sidx+3]]; 00708 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00709 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00710 out[didx++] = ( ((C << 6) & 255) | (D & 077) ); 00711 sidx += 4; 00712 } 00713 } 00714 00715 if (didx < end) 00716 { 00717 A = UUDecMap[(unsigned char) data[sidx]]; 00718 B = UUDecMap[(unsigned char) data[sidx+1]]; 00719 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00720 } 00721 00722 if (didx < end) 00723 { 00724 B = UUDecMap[(unsigned char) data[sidx+1]]; 00725 C = UUDecMap[(unsigned char) data[sidx+2]]; 00726 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00727 } 00728 00729 // skip padding 00730 while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') 00731 sidx++; 00732 00733 // skip end of line 00734 while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) 00735 sidx++; 00736 00737 // skip the "END" separator when present. 00738 if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 ) 00739 break; 00740 } 00741 00742 if ( didx < out.size() ) 00743 out.resize( didx ); 00744 } 00745 00746 /******************************** KMD5 ********************************/ 00747 KMD5::KMD5() 00748 { 00749 init(); 00750 } 00751 00752 KMD5::KMD5(const char *in, int len) 00753 { 00754 init(); 00755 update(in, len); 00756 } 00757 00758 KMD5::KMD5(const QByteArray& in) 00759 { 00760 init(); 00761 update( in ); 00762 } 00763 00764 KMD5::KMD5(const QCString& in) 00765 { 00766 init(); 00767 update( in ); 00768 } 00769 00770 void KMD5::update(const QByteArray& in) 00771 { 00772 update(in.data(), int(in.size())); 00773 } 00774 00775 void KMD5::update(const QCString& in) 00776 { 00777 update(in.data(), int(in.length())); 00778 } 00779 00780 void KMD5::update(const unsigned char* in, int len) 00781 { 00782 if (len < 0) 00783 len = qstrlen(reinterpret_cast<const char*>(in)); 00784 00785 if (!len) 00786 return; 00787 00788 if (m_finalized) { 00789 kdWarning() << "KMD5::update called after state was finalized!" << endl; 00790 return; 00791 } 00792 00793 Q_UINT32 in_index; 00794 Q_UINT32 buffer_index; 00795 Q_UINT32 buffer_space; 00796 Q_UINT32 in_length = static_cast<Q_UINT32>( len ); 00797 00798 buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F); 00799 00800 if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) 00801 m_count[1]++; 00802 00803 m_count[1] += (in_length >> 29); 00804 buffer_space = 64 - buffer_index; 00805 00806 if (in_length >= buffer_space) 00807 { 00808 memcpy (m_buffer + buffer_index, in, buffer_space); 00809 transform (m_buffer); 00810 00811 for (in_index = buffer_space; in_index + 63 < in_length; 00812 in_index += 64) 00813 transform (reinterpret_cast<const unsigned char*>(in+in_index)); 00814 00815 buffer_index = 0; 00816 } 00817 else 00818 in_index=0; 00819 00820 memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); 00821 } 00822 00823 bool KMD5::update(QIODevice& file) 00824 { 00825 char buffer[1024]; 00826 int len; 00827 00828 while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) 00829 update(buffer, len); 00830 00831 return file.atEnd(); 00832 } 00833 00834 void KMD5::finalize () 00835 { 00836 if (m_finalized) return; 00837 00838 Q_UINT8 bits[8]; 00839 Q_UINT32 index, padLen; 00840 static unsigned char PADDING[64]= 00841 { 00842 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00846 }; 00847 00848 encode (bits, m_count, 8); 00849 //memcpy( bits, m_count, 8 ); 00850 00851 // Pad out to 56 mod 64. 00852 index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f); 00853 padLen = (index < 56) ? (56 - index) : (120 - index); 00854 update (reinterpret_cast<const char*>(PADDING), padLen); 00855 00856 // Append length (before padding) 00857 update (reinterpret_cast<const char*>(bits), 8); 00858 00859 // Store state in digest 00860 encode (m_digest, m_state, 16); 00861 //memcpy( m_digest, m_state, 16 ); 00862 00863 // Fill sensitive information with zero's 00864 memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); 00865 00866 m_finalized = true; 00867 } 00868 00869 00870 bool KMD5::verify( const KMD5::Digest& digest) 00871 { 00872 finalize(); 00873 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); 00874 } 00875 00876 bool KMD5::verify( const QCString& hexdigest) 00877 { 00878 finalize(); 00879 return (0 == strcmp(hexDigest().data(), hexdigest)); 00880 } 00881 00882 const KMD5::Digest& KMD5::rawDigest() 00883 { 00884 finalize(); 00885 return m_digest; 00886 } 00887 00888 void KMD5::rawDigest( KMD5::Digest& bin ) 00889 { 00890 finalize(); 00891 memcpy( bin, m_digest, 16 ); 00892 } 00893 00894 00895 QCString KMD5::hexDigest() 00896 { 00897 QCString s(33); 00898 00899 finalize(); 00900 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00901 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00902 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00903 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00904 00905 return s; 00906 } 00907 00908 void KMD5::hexDigest(QCString& s) 00909 { 00910 finalize(); 00911 s.resize(33); 00912 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00913 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00914 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00915 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00916 } 00917 00918 QCString KMD5::base64Digest() 00919 { 00920 QByteArray ba(16); 00921 00922 finalize(); 00923 memcpy(ba.data(), m_digest, 16); 00924 return KCodecs::base64Encode(ba); 00925 } 00926 00927 00928 void KMD5::init() 00929 { 00930 d = 0; 00931 reset(); 00932 } 00933 00934 void KMD5::reset() 00935 { 00936 m_finalized = false; 00937 00938 m_count[0] = 0; 00939 m_count[1] = 0; 00940 00941 m_state[0] = 0x67452301; 00942 m_state[1] = 0xefcdab89; 00943 m_state[2] = 0x98badcfe; 00944 m_state[3] = 0x10325476; 00945 00946 memset ( m_buffer, 0, sizeof(*m_buffer)); 00947 memset ( m_digest, 0, sizeof(*m_digest)); 00948 } 00949 00950 void KMD5::transform( const unsigned char block[64] ) 00951 { 00952 00953 Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; 00954 00955 decode (x, block, 64); 00956 //memcpy( x, block, 64 ); 00957 00958 Q_ASSERT(!m_finalized); // not just a user error, since the method is private 00959 00960 /* Round 1 */ 00961 FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ 00962 FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ 00963 FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ 00964 FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ 00965 FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ 00966 FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ 00967 FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ 00968 FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ 00969 FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ 00970 FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ 00971 FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ 00972 FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ 00973 FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ 00974 FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ 00975 FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ 00976 FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ 00977 00978 /* Round 2 */ 00979 GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ 00980 GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ 00981 GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ 00982 GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ 00983 GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ 00984 GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ 00985 GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ 00986 GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ 00987 GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ 00988 GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ 00989 GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ 00990 GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ 00991 GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ 00992 GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ 00993 GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ 00994 GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ 00995 00996 /* Round 3 */ 00997 HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ 00998 HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ 00999 HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ 01000 HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ 01001 HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ 01002 HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ 01003 HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ 01004 HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ 01005 HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ 01006 HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ 01007 HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ 01008 HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ 01009 HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ 01010 HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ 01011 HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ 01012 HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ 01013 01014 /* Round 4 */ 01015 II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ 01016 II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ 01017 II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ 01018 II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ 01019 II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ 01020 II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ 01021 II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ 01022 II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ 01023 II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ 01024 II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ 01025 II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ 01026 II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ 01027 II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ 01028 II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ 01029 II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ 01030 II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ 01031 01032 m_state[0] += a; 01033 m_state[1] += b; 01034 m_state[2] += c; 01035 m_state[3] += d; 01036 01037 memset ( static_cast<void *>(x), 0, sizeof(x) ); 01038 } 01039 01040 inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n) 01041 { 01042 return (x << n) | (x >> (32-n)) ; 01043 } 01044 01045 inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01046 { 01047 return (x & y) | (~x & z); 01048 } 01049 01050 inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01051 { 01052 return (x & z) | (y & ~z); 01053 } 01054 01055 inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01056 { 01057 return x ^ y ^ z; 01058 } 01059 01060 inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) 01061 { 01062 return y ^ (x | ~z); 01063 } 01064 01065 void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, 01066 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) 01067 { 01068 a += F(b, c, d) + x + ac; 01069 a = rotate_left (a, s) +b; 01070 } 01071 01072 void KMD5::GG ( 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 += G(b, c, d) + x + ac; 01076 a = rotate_left (a, s) +b; 01077 } 01078 01079 void KMD5::HH ( 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 += H(b, c, d) + x + ac; 01083 a = rotate_left (a, s) +b; 01084 } 01085 01086 void KMD5::II ( 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 += I(b, c, d) + x + ac; 01090 a = rotate_left (a, s) +b; 01091 } 01092 01093 01094 void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ) 01095 { 01096 #if !defined(WORDS_BIGENDIAN) 01097 memcpy(output, in, len); 01098 01099 #else 01100 Q_UINT32 i, j; 01101 for (i = 0, j = 0; j < len; i++, j += 4) 01102 { 01103 output[j] = static_cast<Q_UINT8>((in[i] & 0xff)); 01104 output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff)); 01105 output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff)); 01106 output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff)); 01107 } 01108 #endif 01109 } 01110 01111 // Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a 01112 // multiple of 4. 01113 void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len) 01114 { 01115 #if !defined(WORDS_BIGENDIAN) 01116 memcpy(output, in, len); 01117 01118 #else 01119 Q_UINT32 i, j; 01120 for (i = 0, j = 0; j < len; i++, j += 4) 01121 output[i] = static_cast<Q_UINT32>(in[j]) | 01122 (static_cast<Q_UINT32>(in[j+1]) << 8) | 01123 (static_cast<Q_UINT32>(in[j+2]) << 16) | 01124 (static_cast<Q_UINT32>(in[j+3]) << 24); 01125 #endif 01126 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:14:01 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003