• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kmdcodec.cpp

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

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal