kdecore Library API Documentation

kmdcodec.cpp

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