|
MythTV
0.26-pre
|
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 QMD5 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 QCodecs 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 <stdio.h> 00035 #include <string.h> 00036 #include <stdlib.h> 00037 00038 #include <QtCore/QIODevice> 00039 #include <QtDebug> 00040 00041 #include "compat.h" 00042 #include "mcodecs.h" 00043 00044 #define QMD5_S11 7 00045 #define QMD5_S12 12 00046 #define QMD5_S13 17 00047 #define QMD5_S14 22 00048 #define QMD5_S21 5 00049 #define QMD5_S22 9 00050 #define QMD5_S23 14 00051 #define QMD5_S24 20 00052 #define QMD5_S31 4 00053 #define QMD5_S32 11 00054 #define QMD5_S33 16 00055 #define QMD5_S34 23 00056 #define QMD5_S41 6 00057 #define QMD5_S42 10 00058 #define QMD5_S43 15 00059 #define QMD5_S44 21 00060 00061 namespace QCodecs 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 QCodecs 00137 00138 00139 /******************************** QCodecs ********************************/ 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 QCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF) 00157 { 00158 QByteArray out; 00159 quotedPrintableEncode (in, out, useCRLF); 00160 return out; 00161 } 00162 00163 void QCodecs::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 QCodecs::quotedPrintableDecode(const QByteArray & in) 00280 { 00281 QByteArray out; 00282 quotedPrintableDecode (in, out); 00283 return out; 00284 } 00285 00286 00287 void QCodecs::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 unsigned int length = in.size(); 00296 00297 out.resize (length); 00298 cursor = out.data(); 00299 00300 for (unsigned int i = 0; i < length; i++) 00301 { 00302 char c(in[i]); 00303 00304 if ('=' == c) 00305 { 00306 if (i < length - 2) 00307 { 00308 char c1 = in[i + 1]; 00309 char c2 = in[i + 2]; 00310 00311 if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) 00312 { 00313 // Soft line break. No output. 00314 if ('\r' == c1) 00315 i += 2; // CRLF line breaks 00316 else 00317 i += 1; 00318 } 00319 else 00320 { 00321 // =XX encoded byte. 00322 00323 int hexChar0 = rikFindChar(hexChars, c1); 00324 int hexChar1 = rikFindChar(hexChars, c2); 00325 00326 if (hexChar0 < 16 && hexChar1 < 16) 00327 { 00328 *cursor++ = char((hexChar0 * 16) | hexChar1); 00329 i += 2; 00330 } 00331 } 00332 } 00333 } 00334 else 00335 { 00336 *cursor++ = c; 00337 } 00338 } 00339 00340 out.truncate(cursor - out.data()); 00341 } 00342 00343 QByteArray QCodecs::base64Encode( const QByteArray& in, bool insertLFs ) 00344 { 00345 QByteArray out; 00346 base64Encode( in, out, insertLFs ); 00347 return out; 00348 } 00349 00350 void QCodecs::base64Encode( const QByteArray& in, QByteArray& out, 00351 bool insertLFs ) 00352 { 00353 // clear out the output buffer 00354 out.resize (0); 00355 if ( in.isEmpty() ) 00356 return; 00357 00358 unsigned int sidx = 0; 00359 int didx = 0; 00360 const char* data = in.data(); 00361 const unsigned int len = in.size(); 00362 00363 unsigned int out_len = ((len+2)/3)*4; 00364 00365 // Deal with the 76 characters or less per 00366 // line limit specified in RFC 2045 on a 00367 // pre request basis. 00368 insertLFs = (insertLFs && out_len > 76); 00369 if ( insertLFs ) 00370 out_len += ((out_len-1)/76); 00371 00372 int count = 0; 00373 out.resize( out_len ); 00374 00375 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00376 if ( len > 1 ) 00377 { 00378 while (sidx < len-2) 00379 { 00380 if ( insertLFs ) 00381 { 00382 if ( count && (count%76) == 0 ) 00383 out[didx++] = '\n'; 00384 count += 4; 00385 } 00386 out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; 00387 out[didx++] = Base64EncMap[((data[sidx+1] >> 4) & 017) | 00388 ((data[sidx] << 4) & 077)]; 00389 out[didx++] = Base64EncMap[((data[sidx+2] >> 6) & 003) | 00390 ((data[sidx+1] << 2) & 077)]; 00391 out[didx++] = Base64EncMap[data[sidx+2] & 077]; 00392 sidx += 3; 00393 } 00394 } 00395 00396 if (sidx < len) 00397 { 00398 if ( insertLFs && (count > 0) && (count%76) == 0 ) 00399 out[didx++] = '\n'; 00400 00401 out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077]; 00402 if (sidx < len-1) 00403 { 00404 out[didx++] = Base64EncMap[((data[sidx+1] >> 4) & 017) | 00405 ((data[sidx] << 4) & 077)]; 00406 out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077]; 00407 } 00408 else 00409 { 00410 out[didx++] = Base64EncMap[(data[sidx] << 4) & 077]; 00411 } 00412 } 00413 00414 // Add padding 00415 while (didx < out.size()) 00416 { 00417 out[didx] = '='; 00418 didx++; 00419 } 00420 } 00421 00422 QByteArray QCodecs::base64Decode( const QByteArray& in ) 00423 { 00424 QByteArray out; 00425 base64Decode( in, out ); 00426 return out; 00427 } 00428 00429 void QCodecs::base64Decode( const QByteArray& in, QByteArray& out ) 00430 { 00431 out.resize(0); 00432 if ( in.isEmpty() ) 00433 return; 00434 00435 int count = 0; 00436 int len = in.size(), tail = len; 00437 const char* data = in.data(); 00438 00439 // Deal with possible *nix "BEGIN" marker!! 00440 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00441 data[count] == '\t' || data[count] == ' ') ) 00442 count++; 00443 00444 if ( strncasecmp(data+count, "begin", 5) == 0 ) 00445 { 00446 count += 5; 00447 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00448 count++; 00449 00450 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00451 count ++; 00452 00453 data += count; 00454 tail = (len -= count); 00455 } 00456 00457 // Find the tail end of the actual encoded data even if 00458 // there is/are trailing CR and/or LF. 00459 while ( data[tail-1] == '=' || data[tail-1] == '\n' || 00460 data[tail-1] == '\r' ) 00461 if ( data[--tail] != '=' ) len = tail; 00462 00463 unsigned int outIdx = 0; 00464 out.resize( (count=len) ); 00465 for (int idx = 0; idx < count; idx++) 00466 { 00467 // Adhere to RFC 2045 and ignore characters 00468 // that are not part of the encoding table. 00469 unsigned char ch = data[idx]; 00470 if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || 00471 (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') 00472 { 00473 out[outIdx++] = Base64DecMap[ch]; 00474 } 00475 else 00476 { 00477 len--; 00478 tail--; 00479 } 00480 } 00481 00482 // kDebug() << "Tail size = " << tail << ", Length size = " << len; 00483 00484 // 4-byte to 3-byte conversion 00485 len = (tail>(len/4)) ? tail-(len/4) : 0; 00486 int sidx = 0, didx = 0; 00487 if ( len > 1 ) 00488 { 00489 while (didx < len-2) 00490 { 00491 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00492 out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00493 out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077)); 00494 sidx += 4; 00495 didx += 3; 00496 } 00497 } 00498 00499 if (didx < len) 00500 out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003)); 00501 00502 if (++didx < len ) 00503 out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017)); 00504 00505 // Resize the output buffer 00506 if ( len == 0 || len < out.size() ) 00507 out.resize(len); 00508 } 00509 00510 QByteArray QCodecs::uuencode( const QByteArray& in ) 00511 { 00512 QByteArray out; 00513 uuencode( in, out ); 00514 return QByteArray( out.data(), out.size()+1 ); 00515 } 00516 00517 void QCodecs::uuencode( const QByteArray& in, QByteArray& out ) 00518 { 00519 out.resize( 0 ); 00520 if( in.isEmpty() ) 00521 return; 00522 00523 unsigned int sidx = 0; 00524 int didx = 0; 00525 unsigned int line_len = 45; 00526 00527 const char nl[] = "\n"; 00528 const char* data = in.data(); 00529 const unsigned int nl_len = strlen(nl); 00530 const unsigned int len = in.size(); 00531 00532 out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); 00533 // split into lines, adding line-length and line terminator 00534 while (sidx+line_len < len) 00535 { 00536 // line length 00537 out[didx++] = UUEncMap[line_len]; 00538 00539 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00540 for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) 00541 { 00542 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00543 out[didx++] = UUEncMap[((data[sidx+1] >> 4) & 017) | 00544 ((data[sidx] << 4) & 077)]; 00545 out[didx++] = UUEncMap[((data[sidx+2] >> 6) & 003) | 00546 ((data[sidx+1] << 2) & 077)]; 00547 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00548 } 00549 00550 // line terminator 00551 //for (unsigned int idx=0; idx < nl_len; idx++) 00552 //out[didx++] = nl[idx]; 00553 memcpy(out.data()+didx, nl, nl_len); 00554 didx += nl_len; 00555 } 00556 00557 // line length 00558 out[didx++] = UUEncMap[len-sidx]; 00559 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion 00560 while (sidx+2 < len) 00561 { 00562 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00563 out[didx++] = UUEncMap[((data[sidx+1] >> 4) & 017) | 00564 ((data[sidx] << 4) & 077)]; 00565 out[didx++] = UUEncMap[((data[sidx+2] >> 6) & 003) | 00566 ((data[sidx+1] << 2) & 077)]; 00567 out[didx++] = UUEncMap[data[sidx+2] & 077]; 00568 sidx += 3; 00569 } 00570 00571 if (sidx < len-1) 00572 { 00573 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00574 out[didx++] = UUEncMap[((data[sidx+1] >> 4) & 017) | 00575 ((data[sidx] << 4) & 077)]; 00576 out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077]; 00577 out[didx++] = UUEncMap[0]; 00578 } 00579 else if (sidx < len) 00580 { 00581 out[didx++] = UUEncMap[(data[sidx] >> 2) & 077]; 00582 out[didx++] = UUEncMap[(data[sidx] << 4) & 077]; 00583 out[didx++] = UUEncMap[0]; 00584 out[didx++] = UUEncMap[0]; 00585 } 00586 00587 // line terminator 00588 memcpy(out.data()+didx, nl, nl_len); 00589 didx += nl_len; 00590 00591 // sanity check 00592 if ( didx != out.size() ) 00593 out.resize( 0 ); 00594 } 00595 00596 QByteArray QCodecs::uudecode( const QByteArray& in ) 00597 { 00598 QByteArray out; 00599 uudecode( in, out ); 00600 return out; 00601 } 00602 00603 void QCodecs::uudecode( const QByteArray& in, QByteArray& out ) 00604 { 00605 out.resize( 0 ); 00606 if( in.isEmpty() ) 00607 return; 00608 00609 int sidx = 0; 00610 int didx = 0; 00611 int len = in.size(); 00612 int line_len, end; 00613 const char* data = in.data(); 00614 00615 // Deal with *nix "BEGIN"/"END" separators!! 00616 int count = 0; 00617 while ( count < len && (data[count] == '\n' || data[count] == '\r' || 00618 data[count] == '\t' || data[count] == ' ') ) 00619 count ++; 00620 00621 bool hasLF = false; 00622 if ( strncasecmp( data+count, "begin", 5) == 0 ) 00623 { 00624 count += 5; 00625 while ( count < len && data[count] != '\n' && data[count] != '\r' ) 00626 count ++; 00627 00628 while ( count < len && (data[count] == '\n' || data[count] == '\r') ) 00629 count ++; 00630 00631 data += count; 00632 len -= count; 00633 hasLF = true; 00634 } 00635 00636 out.resize( len/4*3 ); 00637 while ( sidx < len ) 00638 { 00639 // get line length (in number of encoded octets) 00640 line_len = UUDecMap[ (unsigned char) data[sidx++]]; 00641 // ascii printable to 0-63 and 4-byte to 3-byte conversion 00642 end = didx+line_len; 00643 char A, B, C, D; 00644 if (end > 2) { 00645 while (didx < end-2) 00646 { 00647 A = UUDecMap[(unsigned char) data[sidx]]; 00648 B = UUDecMap[(unsigned char) data[sidx+1]]; 00649 C = UUDecMap[(unsigned char) data[sidx+2]]; 00650 D = UUDecMap[(unsigned char) data[sidx+3]]; 00651 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00652 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00653 out[didx++] = ( ((C << 6) & 255) | (D & 077) ); 00654 sidx += 4; 00655 } 00656 } 00657 00658 if (didx < end) 00659 { 00660 A = UUDecMap[(unsigned char) data[sidx]]; 00661 B = UUDecMap[(unsigned char) data[sidx+1]]; 00662 out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) ); 00663 } 00664 00665 if (didx < end) 00666 { 00667 B = UUDecMap[(unsigned char) data[sidx+1]]; 00668 C = UUDecMap[(unsigned char) data[sidx+2]]; 00669 out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) ); 00670 } 00671 00672 // skip padding 00673 while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') 00674 sidx++; 00675 00676 // skip end of line 00677 while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) 00678 sidx++; 00679 00680 // skip the "END" separator when present. 00681 if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 ) 00682 break; 00683 } 00684 00685 if ( didx < out.size() ) 00686 out.resize( didx ); 00687 } 00688 00689 /******************************** QMD5 ********************************/ 00690 QMD5::QMD5() 00691 { 00692 init(); 00693 } 00694 00695 QMD5::QMD5(const char *in, int len) 00696 { 00697 init(); 00698 update(in, len); 00699 } 00700 00701 QMD5::QMD5(const QByteArray& in) 00702 { 00703 init(); 00704 update( in ); 00705 } 00706 00707 QMD5::~QMD5() 00708 { 00709 } 00710 00711 void QMD5::update(const QByteArray& in) 00712 { 00713 update(in.data(), int(in.size())); 00714 } 00715 00716 void QMD5::update(const char* in, int len) 00717 { 00718 update(reinterpret_cast<const unsigned char*>(in), len); 00719 } 00720 00721 void QMD5::update(const unsigned char* in, int len) 00722 { 00723 if (len < 0) 00724 len = qstrlen(reinterpret_cast<const char*>(in)); 00725 00726 if (!len) 00727 return; 00728 00729 if (m_finalized) { 00730 qDebug() << "QMD5::update called after state was finalized!"; 00731 return; 00732 } 00733 00734 quint32 in_index; 00735 quint32 buffer_index; 00736 quint32 buffer_space; 00737 quint32 in_length = static_cast<quint32>( len ); 00738 00739 buffer_index = static_cast<quint32>((m_count[0] >> 3) & 0x3F); 00740 00741 if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) 00742 m_count[1]++; 00743 00744 m_count[1] += (in_length >> 29); 00745 buffer_space = 64 - buffer_index; 00746 00747 if (in_length >= buffer_space) 00748 { 00749 memcpy (m_buffer + buffer_index, in, buffer_space); 00750 transform (m_buffer); 00751 00752 for (in_index = buffer_space; in_index + 63 < in_length; 00753 in_index += 64) 00754 transform (reinterpret_cast<const unsigned char*>(in+in_index)); 00755 00756 buffer_index = 0; 00757 } 00758 else 00759 in_index=0; 00760 00761 memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); 00762 } 00763 00764 bool QMD5::update(QIODevice& file) 00765 { 00766 char buffer[1024]; 00767 int len; 00768 00769 while ((len=file.read(buffer, sizeof(buffer))) > 0) 00770 update(buffer, len); 00771 00772 return file.atEnd(); 00773 } 00774 00775 void QMD5::finalize () 00776 { 00777 if (m_finalized) return; 00778 00779 quint8 bits[8]; 00780 quint32 index, padLen; 00781 static const unsigned char PADDING[64]= 00782 { 00783 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00784 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00785 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00787 }; 00788 00789 encode (bits, m_count, 8); 00790 //memcpy( bits, m_count, 8 ); 00791 00792 // Pad out to 56 mod 64. 00793 index = static_cast<quint32>((m_count[0] >> 3) & 0x3f); 00794 padLen = (index < 56) ? (56 - index) : (120 - index); 00795 update (reinterpret_cast<const char*>(PADDING), padLen); 00796 00797 // Append length (before padding) 00798 update (reinterpret_cast<const char*>(bits), 8); 00799 00800 // Store state in digest 00801 encode (m_digest, m_state, 16); 00802 //memcpy( m_digest, m_state, 16 ); 00803 00804 // Fill sensitive information with zero's 00805 memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); 00806 00807 m_finalized = true; 00808 } 00809 00810 00811 bool QMD5::verify( const QMD5::Digest& digest) 00812 { 00813 finalize(); 00814 return (0 == memcmp(rawDigest(), digest, sizeof(QMD5::Digest))); 00815 } 00816 00817 bool QMD5::verify( const QByteArray& hexdigest) 00818 { 00819 finalize(); 00820 return (0 == strcmp(hexDigest().data(), hexdigest)); 00821 } 00822 00823 const QMD5::Digest& QMD5::rawDigest() 00824 { 00825 finalize(); 00826 return m_digest; 00827 } 00828 00829 void QMD5::rawDigest( QMD5::Digest& bin ) 00830 { 00831 finalize(); 00832 memcpy( bin, m_digest, 16 ); 00833 } 00834 00835 00836 QByteArray QMD5::hexDigest() 00837 { 00838 QByteArray s(32, 0); 00839 00840 finalize(); 00841 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00842 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00843 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00844 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00845 00846 return s; 00847 } 00848 00849 void QMD5::hexDigest(QByteArray& s) 00850 { 00851 finalize(); 00852 s.resize(32); 00853 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 00854 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 00855 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 00856 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 00857 } 00858 00859 QByteArray QMD5::base64Digest() 00860 { 00861 finalize(); 00862 return QByteArray::fromRawData(reinterpret_cast<const char*>(m_digest),16).toBase64(); 00863 } 00864 00865 void QMD5::init() 00866 { 00867 d = 0; 00868 reset(); 00869 } 00870 00871 void QMD5::reset() 00872 { 00873 m_finalized = false; 00874 00875 m_count[0] = 0; 00876 m_count[1] = 0; 00877 00878 m_state[0] = 0x67452301; 00879 m_state[1] = 0xefcdab89; 00880 m_state[2] = 0x98badcfe; 00881 m_state[3] = 0x10325476; 00882 00883 memset ( m_buffer, 0, sizeof(*m_buffer)); 00884 memset ( m_digest, 0, sizeof(*m_digest)); 00885 } 00886 00887 void QMD5::transform( const unsigned char block[64] ) 00888 { 00889 00890 quint32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; 00891 00892 decode (x, block, 64); 00893 //memcpy( x, block, 64 ); 00894 00895 Q_ASSERT(!m_finalized); // not just a user error, since the method is private 00896 00897 /* Round 1 */ 00898 FF (a, b, c, d, x[ 0], QMD5_S11, 0xd76aa478); /* 1 */ 00899 FF (d, a, b, c, x[ 1], QMD5_S12, 0xe8c7b756); /* 2 */ 00900 FF (c, d, a, b, x[ 2], QMD5_S13, 0x242070db); /* 3 */ 00901 FF (b, c, d, a, x[ 3], QMD5_S14, 0xc1bdceee); /* 4 */ 00902 FF (a, b, c, d, x[ 4], QMD5_S11, 0xf57c0faf); /* 5 */ 00903 FF (d, a, b, c, x[ 5], QMD5_S12, 0x4787c62a); /* 6 */ 00904 FF (c, d, a, b, x[ 6], QMD5_S13, 0xa8304613); /* 7 */ 00905 FF (b, c, d, a, x[ 7], QMD5_S14, 0xfd469501); /* 8 */ 00906 FF (a, b, c, d, x[ 8], QMD5_S11, 0x698098d8); /* 9 */ 00907 FF (d, a, b, c, x[ 9], QMD5_S12, 0x8b44f7af); /* 10 */ 00908 FF (c, d, a, b, x[10], QMD5_S13, 0xffff5bb1); /* 11 */ 00909 FF (b, c, d, a, x[11], QMD5_S14, 0x895cd7be); /* 12 */ 00910 FF (a, b, c, d, x[12], QMD5_S11, 0x6b901122); /* 13 */ 00911 FF (d, a, b, c, x[13], QMD5_S12, 0xfd987193); /* 14 */ 00912 FF (c, d, a, b, x[14], QMD5_S13, 0xa679438e); /* 15 */ 00913 FF (b, c, d, a, x[15], QMD5_S14, 0x49b40821); /* 16 */ 00914 00915 /* Round 2 */ 00916 GG (a, b, c, d, x[ 1], QMD5_S21, 0xf61e2562); /* 17 */ 00917 GG (d, a, b, c, x[ 6], QMD5_S22, 0xc040b340); /* 18 */ 00918 GG (c, d, a, b, x[11], QMD5_S23, 0x265e5a51); /* 19 */ 00919 GG (b, c, d, a, x[ 0], QMD5_S24, 0xe9b6c7aa); /* 20 */ 00920 GG (a, b, c, d, x[ 5], QMD5_S21, 0xd62f105d); /* 21 */ 00921 GG (d, a, b, c, x[10], QMD5_S22, 0x2441453); /* 22 */ 00922 GG (c, d, a, b, x[15], QMD5_S23, 0xd8a1e681); /* 23 */ 00923 GG (b, c, d, a, x[ 4], QMD5_S24, 0xe7d3fbc8); /* 24 */ 00924 GG (a, b, c, d, x[ 9], QMD5_S21, 0x21e1cde6); /* 25 */ 00925 GG (d, a, b, c, x[14], QMD5_S22, 0xc33707d6); /* 26 */ 00926 GG (c, d, a, b, x[ 3], QMD5_S23, 0xf4d50d87); /* 27 */ 00927 GG (b, c, d, a, x[ 8], QMD5_S24, 0x455a14ed); /* 28 */ 00928 GG (a, b, c, d, x[13], QMD5_S21, 0xa9e3e905); /* 29 */ 00929 GG (d, a, b, c, x[ 2], QMD5_S22, 0xfcefa3f8); /* 30 */ 00930 GG (c, d, a, b, x[ 7], QMD5_S23, 0x676f02d9); /* 31 */ 00931 GG (b, c, d, a, x[12], QMD5_S24, 0x8d2a4c8a); /* 32 */ 00932 00933 /* Round 3 */ 00934 HH (a, b, c, d, x[ 5], QMD5_S31, 0xfffa3942); /* 33 */ 00935 HH (d, a, b, c, x[ 8], QMD5_S32, 0x8771f681); /* 34 */ 00936 HH (c, d, a, b, x[11], QMD5_S33, 0x6d9d6122); /* 35 */ 00937 HH (b, c, d, a, x[14], QMD5_S34, 0xfde5380c); /* 36 */ 00938 HH (a, b, c, d, x[ 1], QMD5_S31, 0xa4beea44); /* 37 */ 00939 HH (d, a, b, c, x[ 4], QMD5_S32, 0x4bdecfa9); /* 38 */ 00940 HH (c, d, a, b, x[ 7], QMD5_S33, 0xf6bb4b60); /* 39 */ 00941 HH (b, c, d, a, x[10], QMD5_S34, 0xbebfbc70); /* 40 */ 00942 HH (a, b, c, d, x[13], QMD5_S31, 0x289b7ec6); /* 41 */ 00943 HH (d, a, b, c, x[ 0], QMD5_S32, 0xeaa127fa); /* 42 */ 00944 HH (c, d, a, b, x[ 3], QMD5_S33, 0xd4ef3085); /* 43 */ 00945 HH (b, c, d, a, x[ 6], QMD5_S34, 0x4881d05); /* 44 */ 00946 HH (a, b, c, d, x[ 9], QMD5_S31, 0xd9d4d039); /* 45 */ 00947 HH (d, a, b, c, x[12], QMD5_S32, 0xe6db99e5); /* 46 */ 00948 HH (c, d, a, b, x[15], QMD5_S33, 0x1fa27cf8); /* 47 */ 00949 HH (b, c, d, a, x[ 2], QMD5_S34, 0xc4ac5665); /* 48 */ 00950 00951 /* Round 4 */ 00952 II (a, b, c, d, x[ 0], QMD5_S41, 0xf4292244); /* 49 */ 00953 II (d, a, b, c, x[ 7], QMD5_S42, 0x432aff97); /* 50 */ 00954 II (c, d, a, b, x[14], QMD5_S43, 0xab9423a7); /* 51 */ 00955 II (b, c, d, a, x[ 5], QMD5_S44, 0xfc93a039); /* 52 */ 00956 II (a, b, c, d, x[12], QMD5_S41, 0x655b59c3); /* 53 */ 00957 II (d, a, b, c, x[ 3], QMD5_S42, 0x8f0ccc92); /* 54 */ 00958 II (c, d, a, b, x[10], QMD5_S43, 0xffeff47d); /* 55 */ 00959 II (b, c, d, a, x[ 1], QMD5_S44, 0x85845dd1); /* 56 */ 00960 II (a, b, c, d, x[ 8], QMD5_S41, 0x6fa87e4f); /* 57 */ 00961 II (d, a, b, c, x[15], QMD5_S42, 0xfe2ce6e0); /* 58 */ 00962 II (c, d, a, b, x[ 6], QMD5_S43, 0xa3014314); /* 59 */ 00963 II (b, c, d, a, x[13], QMD5_S44, 0x4e0811a1); /* 60 */ 00964 II (a, b, c, d, x[ 4], QMD5_S41, 0xf7537e82); /* 61 */ 00965 II (d, a, b, c, x[11], QMD5_S42, 0xbd3af235); /* 62 */ 00966 II (c, d, a, b, x[ 2], QMD5_S43, 0x2ad7d2bb); /* 63 */ 00967 II (b, c, d, a, x[ 9], QMD5_S44, 0xeb86d391); /* 64 */ 00968 00969 m_state[0] += a; 00970 m_state[1] += b; 00971 m_state[2] += c; 00972 m_state[3] += d; 00973 00974 memset ( static_cast<void *>(x), 0, sizeof(x) ); 00975 } 00976 00977 inline quint32 QMD5::rotate_left (quint32 x, quint32 n) 00978 { 00979 return (x << n) | (x >> (32-n)) ; 00980 } 00981 00982 inline quint32 QMD5::F (quint32 x, quint32 y, quint32 z) 00983 { 00984 return (x & y) | (~x & z); 00985 } 00986 00987 inline quint32 QMD5::G (quint32 x, quint32 y, quint32 z) 00988 { 00989 return (x & z) | (y & ~z); 00990 } 00991 00992 inline quint32 QMD5::H (quint32 x, quint32 y, quint32 z) 00993 { 00994 return x ^ y ^ z; 00995 } 00996 00997 inline quint32 QMD5::I (quint32 x, quint32 y, quint32 z) 00998 { 00999 return y ^ (x | ~z); 01000 } 01001 01002 void QMD5::FF ( quint32& a, quint32 b, quint32 c, quint32 d, 01003 quint32 x, quint32 s, quint32 ac ) 01004 { 01005 a += F(b, c, d) + x + ac; 01006 a = rotate_left (a, s) +b; 01007 } 01008 01009 void QMD5::GG ( quint32& a, quint32 b, quint32 c, quint32 d, 01010 quint32 x, quint32 s, quint32 ac) 01011 { 01012 a += G(b, c, d) + x + ac; 01013 a = rotate_left (a, s) +b; 01014 } 01015 01016 void QMD5::HH ( quint32& a, quint32 b, quint32 c, quint32 d, 01017 quint32 x, quint32 s, quint32 ac ) 01018 { 01019 a += H(b, c, d) + x + ac; 01020 a = rotate_left (a, s) +b; 01021 } 01022 01023 void QMD5::II ( quint32& a, quint32 b, quint32 c, quint32 d, 01024 quint32 x, quint32 s, quint32 ac ) 01025 { 01026 a += I(b, c, d) + x + ac; 01027 a = rotate_left (a, s) +b; 01028 } 01029 01030 01031 void QMD5::encode ( unsigned char* output, quint32 *in, quint32 len ) 01032 { 01033 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN 01034 memcpy(output, in, len); 01035 #else 01036 quint32 i, j; 01037 for (i = 0, j = 0; j < len; i++, j += 4) 01038 { 01039 output[j] = static_cast<quint8>((in[i] & 0xff)); 01040 output[j+1] = static_cast<quint8>(((in[i] >> 8) & 0xff)); 01041 output[j+2] = static_cast<quint8>(((in[i] >> 16) & 0xff)); 01042 output[j+3] = static_cast<quint8>(((in[i] >> 24) & 0xff)); 01043 } 01044 #endif 01045 } 01046 01047 // Decodes in (quint8) into output (quint32). Assumes len is a 01048 // multiple of 4. 01049 void QMD5::decode (quint32 *output, const unsigned char* in, quint32 len) 01050 { 01051 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN 01052 memcpy(output, in, len); 01053 01054 #else 01055 quint32 i, j; 01056 for (i = 0, j = 0; j < len; i++, j += 4) 01057 output[i] = static_cast<quint32>(in[j]) | 01058 (static_cast<quint32>(in[j+1]) << 8) | 01059 (static_cast<quint32>(in[j+2]) << 16) | 01060 (static_cast<quint32>(in[j+3]) << 24); 01061 #endif 01062 } 01063 01064 01065 01066 /**************************************************************/
1.7.6.1