00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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 }
00137
00138
00139
00140
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
00179
00180
00181
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
00193
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
00201
00202 if ((c >= 33) && (c <= 126) && ('=' != c))
00203 {
00204 *cursor++ = c;
00205 ++lineLength;
00206 }
00207
00208
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
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
00249
00250 else
00251 {
00252 *cursor++ = '=';
00253 *cursor++ = hexChars[c / 16];
00254 *cursor++ = hexChars[c % 16];
00255
00256 lineLength += 3;
00257 }
00258
00259
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
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
00314 if ('\r' == c1)
00315 i += 2;
00316 else
00317 i += 1;
00318 }
00319 else
00320 {
00321
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
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
00366
00367
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
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
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
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
00458
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
00468
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
00483
00484
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
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
00534 while (sidx+line_len < len)
00535 {
00536
00537 out[didx++] = UUEncMap[line_len];
00538
00539
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
00551
00552
00553 memcpy(out.data()+didx, nl, nl_len);
00554 didx += nl_len;
00555 }
00556
00557
00558 out[didx++] = UUEncMap[len-sidx];
00559
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
00588 memcpy(out.data()+didx, nl, nl_len);
00589 didx += nl_len;
00590
00591
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
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
00640 line_len = UUDecMap[ (unsigned char) data[sidx++]];
00641
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
00673 while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r')
00674 sidx++;
00675
00676
00677 while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r'))
00678 sidx++;
00679
00680
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
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
00791
00792
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
00798 update (reinterpret_cast<const char*>(bits), 8);
00799
00800
00801 encode (m_digest, m_state, 16);
00802
00803
00804
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
00894
00895 Q_ASSERT(!m_finalized);
00896
00897
00898 FF (a, b, c, d, x[ 0], QMD5_S11, 0xd76aa478);
00899 FF (d, a, b, c, x[ 1], QMD5_S12, 0xe8c7b756);
00900 FF (c, d, a, b, x[ 2], QMD5_S13, 0x242070db);
00901 FF (b, c, d, a, x[ 3], QMD5_S14, 0xc1bdceee);
00902 FF (a, b, c, d, x[ 4], QMD5_S11, 0xf57c0faf);
00903 FF (d, a, b, c, x[ 5], QMD5_S12, 0x4787c62a);
00904 FF (c, d, a, b, x[ 6], QMD5_S13, 0xa8304613);
00905 FF (b, c, d, a, x[ 7], QMD5_S14, 0xfd469501);
00906 FF (a, b, c, d, x[ 8], QMD5_S11, 0x698098d8);
00907 FF (d, a, b, c, x[ 9], QMD5_S12, 0x8b44f7af);
00908 FF (c, d, a, b, x[10], QMD5_S13, 0xffff5bb1);
00909 FF (b, c, d, a, x[11], QMD5_S14, 0x895cd7be);
00910 FF (a, b, c, d, x[12], QMD5_S11, 0x6b901122);
00911 FF (d, a, b, c, x[13], QMD5_S12, 0xfd987193);
00912 FF (c, d, a, b, x[14], QMD5_S13, 0xa679438e);
00913 FF (b, c, d, a, x[15], QMD5_S14, 0x49b40821);
00914
00915
00916 GG (a, b, c, d, x[ 1], QMD5_S21, 0xf61e2562);
00917 GG (d, a, b, c, x[ 6], QMD5_S22, 0xc040b340);
00918 GG (c, d, a, b, x[11], QMD5_S23, 0x265e5a51);
00919 GG (b, c, d, a, x[ 0], QMD5_S24, 0xe9b6c7aa);
00920 GG (a, b, c, d, x[ 5], QMD5_S21, 0xd62f105d);
00921 GG (d, a, b, c, x[10], QMD5_S22, 0x2441453);
00922 GG (c, d, a, b, x[15], QMD5_S23, 0xd8a1e681);
00923 GG (b, c, d, a, x[ 4], QMD5_S24, 0xe7d3fbc8);
00924 GG (a, b, c, d, x[ 9], QMD5_S21, 0x21e1cde6);
00925 GG (d, a, b, c, x[14], QMD5_S22, 0xc33707d6);
00926 GG (c, d, a, b, x[ 3], QMD5_S23, 0xf4d50d87);
00927 GG (b, c, d, a, x[ 8], QMD5_S24, 0x455a14ed);
00928 GG (a, b, c, d, x[13], QMD5_S21, 0xa9e3e905);
00929 GG (d, a, b, c, x[ 2], QMD5_S22, 0xfcefa3f8);
00930 GG (c, d, a, b, x[ 7], QMD5_S23, 0x676f02d9);
00931 GG (b, c, d, a, x[12], QMD5_S24, 0x8d2a4c8a);
00932
00933
00934 HH (a, b, c, d, x[ 5], QMD5_S31, 0xfffa3942);
00935 HH (d, a, b, c, x[ 8], QMD5_S32, 0x8771f681);
00936 HH (c, d, a, b, x[11], QMD5_S33, 0x6d9d6122);
00937 HH (b, c, d, a, x[14], QMD5_S34, 0xfde5380c);
00938 HH (a, b, c, d, x[ 1], QMD5_S31, 0xa4beea44);
00939 HH (d, a, b, c, x[ 4], QMD5_S32, 0x4bdecfa9);
00940 HH (c, d, a, b, x[ 7], QMD5_S33, 0xf6bb4b60);
00941 HH (b, c, d, a, x[10], QMD5_S34, 0xbebfbc70);
00942 HH (a, b, c, d, x[13], QMD5_S31, 0x289b7ec6);
00943 HH (d, a, b, c, x[ 0], QMD5_S32, 0xeaa127fa);
00944 HH (c, d, a, b, x[ 3], QMD5_S33, 0xd4ef3085);
00945 HH (b, c, d, a, x[ 6], QMD5_S34, 0x4881d05);
00946 HH (a, b, c, d, x[ 9], QMD5_S31, 0xd9d4d039);
00947 HH (d, a, b, c, x[12], QMD5_S32, 0xe6db99e5);
00948 HH (c, d, a, b, x[15], QMD5_S33, 0x1fa27cf8);
00949 HH (b, c, d, a, x[ 2], QMD5_S34, 0xc4ac5665);
00950
00951
00952 II (a, b, c, d, x[ 0], QMD5_S41, 0xf4292244);
00953 II (d, a, b, c, x[ 7], QMD5_S42, 0x432aff97);
00954 II (c, d, a, b, x[14], QMD5_S43, 0xab9423a7);
00955 II (b, c, d, a, x[ 5], QMD5_S44, 0xfc93a039);
00956 II (a, b, c, d, x[12], QMD5_S41, 0x655b59c3);
00957 II (d, a, b, c, x[ 3], QMD5_S42, 0x8f0ccc92);
00958 II (c, d, a, b, x[10], QMD5_S43, 0xffeff47d);
00959 II (b, c, d, a, x[ 1], QMD5_S44, 0x85845dd1);
00960 II (a, b, c, d, x[ 8], QMD5_S41, 0x6fa87e4f);
00961 II (d, a, b, c, x[15], QMD5_S42, 0xfe2ce6e0);
00962 II (c, d, a, b, x[ 6], QMD5_S43, 0xa3014314);
00963 II (b, c, d, a, x[13], QMD5_S44, 0x4e0811a1);
00964 II (a, b, c, d, x[ 4], QMD5_S41, 0xf7537e82);
00965 II (d, a, b, c, x[11], QMD5_S42, 0xbd3af235);
00966 II (c, d, a, b, x[ 2], QMD5_S43, 0x2ad7d2bb);
00967 II (b, c, d, a, x[ 9], QMD5_S44, 0xeb86d391);
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
01048
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