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