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 <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 ( strncasecmp(data+count, "begin", 5) == 0 )
00484     {
00485         count += 5;
00486         while ( count < len && data[count] != '\n' && data[count] != '\r' )
00487             count++;
00488 
00489         while ( count < len && (data[count] == '\n' || data[count] == '\r') )
00490             count ++;
00491 
00492         data += count;
00493         tail = (len -= count);
00494     }
00495 
00496     // Find the tail end of the actual encoded data even if
00497     // there is/are trailing CR and/or LF.
00498     while ( data[tail-1] == '=' || data[tail-1] == '\n' ||
00499             data[tail-1] == '\r' )
00500         if ( data[--tail] != '=' ) len = tail;
00501 
00502     unsigned int outIdx = 0;
00503     out.resize( (count=len) );
00504     for (unsigned int idx = 0; idx < count; idx++)
00505     {
00506         // Adhere to RFC 2045 and ignore characters
00507         // that are not part of the encoding table.
00508         unsigned char ch = data[idx];
00509         if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
00510             (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
00511         {
00512             out[outIdx++] = Base64DecMap[ch];
00513         }
00514         else
00515         {
00516             len--;
00517             tail--;
00518         }
00519     }
00520 
00521     // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl;
00522 
00523     // 4-byte to 3-byte conversion
00524     len = (tail>(len/4)) ? tail-(len/4) : 0;
00525     unsigned int sidx = 0, didx = 0;
00526     if ( len > 1 )
00527     {
00528       while (didx < len-2)
00529       {
00530           out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
00531           out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
00532           out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077));
00533           sidx += 4;
00534           didx += 3;
00535       }
00536     }
00537 
00538     if (didx < len)
00539         out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
00540 
00541     if (++didx < len )
00542         out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
00543 
00544     // Resize the output buffer
00545     if ( len == 0 || len < out.size() )
00546       out.resize(len);
00547 }
00548 
00549 QCString KCodecs::uuencode( const QCString& str )
00550 {
00551     if ( str.isEmpty() )
00552         return "";
00553 
00554     QByteArray in;
00555     in.resize( str.length() );
00556     memcpy( in.data(), str.data(), str.length() );
00557     return uuencode( in );
00558 }
00559 
00560 QCString KCodecs::uuencode( const QByteArray& in )
00561 {
00562     QByteArray out;
00563     uuencode( in, out );
00564     return QCString( out.data(), out.size()+1 );
00565 }
00566 
00567 void KCodecs::uuencode( const QByteArray& in, QByteArray& out )
00568 {
00569     out.resize( 0 );
00570     if( in.isEmpty() )
00571         return;
00572 
00573     unsigned int sidx = 0;
00574     unsigned int didx = 0;
00575     unsigned int line_len = 45;
00576 
00577     const char nl[] = "\n";
00578     const char* data = in.data();
00579     const unsigned int nl_len = strlen(nl);
00580     const unsigned int len = in.size();
00581 
00582     out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
00583     // split into lines, adding line-length and line terminator
00584     while (sidx+line_len < len)
00585     {
00586         // line length
00587         out[didx++] = UUEncMap[line_len];
00588 
00589         // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00590         for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
00591         {
00592             out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00593             out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
00594                                    (data[sidx] << 4) & 077];
00595             out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
00596                                 (data[sidx+1] << 2) & 077];
00597             out[didx++] = UUEncMap[data[sidx+2] & 077];
00598         }
00599 
00600         // line terminator
00601         //for (unsigned int idx=0; idx < nl_len; idx++)
00602         //out[didx++] = nl[idx];
00603         memcpy(out.data()+didx, nl, nl_len);
00604         didx += nl_len;
00605     }
00606 
00607     // line length
00608     out[didx++] = UUEncMap[len-sidx];
00609     // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00610     while (sidx+2 < len)
00611     {
00612         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00613         out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
00614                                (data[sidx] << 4) & 077];
00615         out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
00616                                (data[sidx+1] << 2) & 077];
00617         out[didx++] = UUEncMap[data[sidx+2] & 077];
00618         sidx += 3;
00619     }
00620 
00621     if (sidx < len-1)
00622     {
00623         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00624         out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
00625                                (data[sidx] << 4) & 077];
00626         out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077];
00627         out[didx++] = UUEncMap[0];
00628     }
00629     else if (sidx < len)
00630     {
00631         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00632         out[didx++] = UUEncMap[(data[sidx] << 4) & 077];
00633         out[didx++] = UUEncMap[0];
00634         out[didx++] = UUEncMap[0];
00635     }
00636 
00637     // line terminator
00638     memcpy(out.data()+didx, nl, nl_len);
00639     didx += nl_len;
00640 
00641     // sanity check
00642     if ( didx != out.size() )
00643         out.resize( 0 );
00644 }
00645 
00646 QCString KCodecs::uudecode( const QCString& str )
00647 {
00648     if ( str.isEmpty() )
00649         return "";
00650 
00651     QByteArray in;
00652     in.resize( str.length() );
00653     memcpy( in.data(), str.data(), str.length() );
00654     return uudecode( in );
00655 }
00656 
00657 QCString KCodecs::uudecode( const QByteArray& in )
00658 {
00659     QByteArray out;
00660     uudecode( in, out );
00661     return QCString( out.data(), out.size()+1 );
00662 }
00663 
00664 void KCodecs::uudecode( const QByteArray& in, QByteArray& out )
00665 {
00666     out.resize( 0 );
00667     if( in.isEmpty() )
00668         return;
00669 
00670     unsigned int sidx = 0;
00671     unsigned int didx = 0;
00672     unsigned int len = in.size();
00673     unsigned int line_len, end;
00674     const char* data = in.data();
00675 
00676     // Deal with *nix "BEGIN"/"END" separators!!
00677     unsigned int count = 0;
00678     while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
00679             data[count] == '\t' || data[count] == ' ') )
00680         count ++;
00681 
00682     bool hasLF = false;
00683     if ( strncasecmp( data+count, "begin", 5) == 0 )
00684     {
00685         count += 5;
00686         while ( count < len && data[count] != '\n' && data[count] != '\r' )
00687             count ++;
00688 
00689         while ( count < len && (data[count] == '\n' || data[count] == '\r') )
00690             count ++;
00691 
00692         data += count;
00693         len -= count;
00694         hasLF = true;
00695     }
00696 
00697     out.resize( len/4*3 );
00698     while ( sidx < len )
00699     {
00700         // get line length (in number of encoded octets)
00701         line_len = UUDecMap[ (unsigned char) data[sidx++]];
00702         // ascii printable to 0-63 and 4-byte to 3-byte conversion
00703         end = didx+line_len;
00704         char A, B, C, D;
00705         if (end > 2) {
00706           while (didx < end-2)
00707           {
00708              A = UUDecMap[(unsigned char) data[sidx]];
00709              B = UUDecMap[(unsigned char) data[sidx+1]];
00710              C = UUDecMap[(unsigned char) data[sidx+2]];
00711              D = UUDecMap[(unsigned char) data[sidx+3]];
00712              out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
00713              out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
00714              out[didx++] = ( ((C << 6) & 255) | (D & 077) );
00715              sidx += 4;
00716           }
00717         }
00718 
00719         if (didx < end)
00720         {
00721             A = UUDecMap[(unsigned char) data[sidx]];
00722             B = UUDecMap[(unsigned char) data[sidx+1]];
00723             out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
00724         }
00725 
00726         if (didx < end)
00727         {
00728             B = UUDecMap[(unsigned char) data[sidx+1]];
00729             C = UUDecMap[(unsigned char) data[sidx+2]];
00730             out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
00731         }
00732 
00733         // skip padding
00734         while (sidx < len  && data[sidx] != '\n' && data[sidx] != '\r')
00735             sidx++;
00736 
00737         // skip end of line
00738         while (sidx < len  && (data[sidx] == '\n' || data[sidx] == '\r'))
00739             sidx++;
00740 
00741         // skip the "END" separator when present.
00742         if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 )
00743             break;
00744     }
00745 
00746     if ( didx < out.size()  )
00747         out.resize( didx );
00748 }
00749 
00750 /******************************** KMD5 ********************************/
00751 KMD5::KMD5()
00752 {
00753     init();
00754 }
00755 
00756 KMD5::KMD5(const char *in, int len)
00757 {
00758     init();
00759     update(in, len);
00760 }
00761 
00762 KMD5::KMD5(const QByteArray& in)
00763 {
00764     init();
00765     update( in );
00766 }
00767 
00768 KMD5::KMD5(const QCString& in)
00769 {
00770     init();
00771     update( in );
00772 }
00773 
00774 void KMD5::update(const QByteArray& in)
00775 {
00776     update(in.data(), int(in.size()));
00777 }
00778 
00779 void KMD5::update(const QCString& in)
00780 {
00781     update(in.data(), int(in.length()));
00782 }
00783 
00784 void KMD5::update(const unsigned char* in, int len)
00785 {
00786     if (len < 0)
00787         len = qstrlen(reinterpret_cast<const char*>(in));
00788 
00789     if (!len)
00790         return;
00791 
00792     if (m_finalized) {
00793         kdWarning() << "KMD5::update called after state was finalized!" << endl;
00794         return;
00795     }
00796 
00797     Q_UINT32 in_index;
00798     Q_UINT32 buffer_index;
00799     Q_UINT32 buffer_space;
00800     Q_UINT32 in_length = static_cast<Q_UINT32>( len );
00801 
00802     buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F);
00803 
00804     if (  (m_count[0] += (in_length << 3))<(in_length << 3) )
00805         m_count[1]++;
00806 
00807     m_count[1] += (in_length >> 29);
00808     buffer_space = 64 - buffer_index;
00809 
00810     if (in_length >= buffer_space)
00811     {
00812         memcpy (m_buffer + buffer_index, in, buffer_space);
00813         transform (m_buffer);
00814 
00815         for (in_index = buffer_space; in_index + 63 < in_length;
00816              in_index += 64)
00817             transform (reinterpret_cast<const unsigned char*>(in+in_index));
00818 
00819         buffer_index = 0;
00820     }
00821     else
00822         in_index=0;
00823 
00824     memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
00825 }
00826 
00827 bool KMD5::update(QIODevice& file)
00828 {
00829     char buffer[1024];
00830     int len;
00831 
00832     while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
00833         update(buffer, len);
00834 
00835     return file.atEnd();
00836 }
00837 
00838 void KMD5::finalize ()
00839 {
00840     if (m_finalized) return;
00841 
00842     Q_UINT8 bits[8];
00843     Q_UINT32 index, padLen;
00844     static const unsigned char PADDING[64]=
00845     {
00846         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00847         0, 0, 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
00850     };
00851 
00852     encode (bits, m_count, 8);
00853     //memcpy( bits, m_count, 8 );
00854 
00855     // Pad out to 56 mod 64.
00856     index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f);
00857     padLen = (index < 56) ? (56 - index) : (120 - index);
00858     update (reinterpret_cast<const char*>(PADDING), padLen);
00859 
00860     // Append length (before padding)
00861     update (reinterpret_cast<const char*>(bits), 8);
00862 
00863     // Store state in digest
00864     encode (m_digest, m_state, 16);
00865     //memcpy( m_digest, m_state, 16 );
00866 
00867     // Fill sensitive information with zero's
00868     memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
00869 
00870     m_finalized = true;
00871 }
00872 
00873 
00874 bool KMD5::verify( const KMD5::Digest& digest)
00875 {
00876     finalize();
00877     return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
00878 }
00879 
00880 bool KMD5::verify( const QCString& hexdigest)
00881 {
00882     finalize();
00883     return (0 == strcmp(hexDigest().data(), hexdigest));
00884 }
00885 
00886 const KMD5::Digest& KMD5::rawDigest()
00887 {
00888     finalize();
00889     return m_digest;
00890 }
00891 
00892 void KMD5::rawDigest( KMD5::Digest& bin )
00893 {
00894     finalize();
00895     memcpy( bin, m_digest, 16 );
00896 }
00897 
00898 
00899 QCString KMD5::hexDigest()
00900 {
00901     QCString s(33);
00902 
00903     finalize();
00904     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00905             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
00906             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
00907             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
00908 
00909     return s;
00910 }
00911 
00912 void KMD5::hexDigest(QCString& s)
00913 {
00914     finalize();
00915     s.resize(33);
00916     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00917             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
00918             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
00919             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
00920 }
00921 
00922 QCString KMD5::base64Digest()
00923 {
00924     QByteArray ba(16);
00925 
00926     finalize();
00927     memcpy(ba.data(), m_digest, 16);
00928     return KCodecs::base64Encode(ba);
00929 }
00930 
00931 
00932 void KMD5::init()
00933 {
00934     d = 0;
00935     reset();
00936 }
00937 
00938 void KMD5::reset()
00939 {
00940     m_finalized = false;
00941 
00942     m_count[0] = 0;
00943     m_count[1] = 0;
00944 
00945     m_state[0] = 0x67452301;
00946     m_state[1] = 0xefcdab89;
00947     m_state[2] = 0x98badcfe;
00948     m_state[3] = 0x10325476;
00949 
00950     memset ( m_buffer, 0, sizeof(*m_buffer));
00951     memset ( m_digest, 0, sizeof(*m_digest));
00952 }
00953 
00954 void KMD5::transform( const unsigned char block[64] )
00955 {
00956 
00957     Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
00958 
00959     decode (x, block, 64);
00960     //memcpy( x, block, 64 );
00961 
00962     Q_ASSERT(!m_finalized);  // not just a user error, since the method is private
00963 
00964     /* Round 1 */
00965     FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */
00966     FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */
00967     FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */
00968     FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */
00969     FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */
00970     FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */
00971     FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */
00972     FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */
00973     FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */
00974     FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */
00975     FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */
00976     FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */
00977     FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */
00978     FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */
00979     FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */
00980     FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */
00981 
00982     /* Round 2 */
00983     GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */
00984     GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */
00985     GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */
00986     GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */
00987     GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */
00988     GG (d, a, b, c, x[10], KMD5_S22,  0x2441453); /* 22 */
00989     GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */
00990     GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */
00991     GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */
00992     GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */
00993     GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */
00994     GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */
00995     GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */
00996     GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */
00997     GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */
00998     GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */
00999 
01000     /* Round 3 */
01001     HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */
01002     HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */
01003     HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */
01004     HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */
01005     HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */
01006     HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */
01007     HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */
01008     HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */
01009     HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */
01010     HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */
01011     HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */
01012     HH (b, c, d, a, x[ 6], KMD5_S34,  0x4881d05); /* 44 */
01013     HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */
01014     HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */
01015     HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */
01016     HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */
01017 
01018     /* Round 4 */
01019     II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */
01020     II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */
01021     II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */
01022     II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */
01023     II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */
01024     II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */
01025     II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */
01026     II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */
01027     II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */
01028     II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */
01029     II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */
01030     II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */
01031     II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */
01032     II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */
01033     II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */
01034     II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */
01035 
01036     m_state[0] += a;
01037     m_state[1] += b;
01038     m_state[2] += c;
01039     m_state[3] += d;
01040 
01041     memset ( static_cast<void *>(x), 0, sizeof(x) );
01042 }
01043 
01044 inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
01045 {
01046     return (x << n) | (x >> (32-n))  ;
01047 }
01048 
01049 inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01050 {
01051     return (x & y) | (~x & z);
01052 }
01053 
01054 inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01055 {
01056     return (x & z) | (y & ~z);
01057 }
01058 
01059 inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01060 {
01061     return x ^ y ^ z;
01062 }
01063 
01064 inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01065 {
01066     return y ^ (x | ~z);
01067 }
01068 
01069 void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01070                        Q_UINT32 x, Q_UINT32  s, Q_UINT32 ac )
01071 {
01072     a += F(b, c, d) + x + ac;
01073     a = rotate_left (a, s) +b;
01074 }
01075 
01076 void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01077                  Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac)
01078 {
01079     a += G(b, c, d) + x + ac;
01080     a = rotate_left (a, s) +b;
01081 }
01082 
01083 void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01084                  Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
01085 {
01086     a += H(b, c, d) + x + ac;
01087     a = rotate_left (a, s) +b;
01088 }
01089 
01090 void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01091                  Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
01092 {
01093     a += I(b, c, d) + x + ac;
01094     a = rotate_left (a, s) +b;
01095 }
01096 
01097 
01098 void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len )
01099 {
01100 #if !defined(WORDS_BIGENDIAN)
01101     memcpy(output, in, len);
01102 
01103 #else
01104     Q_UINT32 i, j;
01105     for (i = 0, j = 0; j < len; i++, j += 4)
01106     {
01107         output[j]   = static_cast<Q_UINT8>((in[i] & 0xff));
01108         output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff));
01109         output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff));
01110         output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff));
01111     }
01112 #endif
01113 }
01114 
01115 // Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a
01116 // multiple of 4.
01117 void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len)
01118 {
01119 #if !defined(WORDS_BIGENDIAN)
01120     memcpy(output, in, len);
01121 
01122 #else
01123     Q_UINT32 i, j;
01124     for (i = 0, j = 0; j < len; i++, j += 4)
01125         output[i] = static_cast<Q_UINT32>(in[j]) |
01126                     (static_cast<Q_UINT32>(in[j+1]) << 8)  |
01127                     (static_cast<Q_UINT32>(in[j+2]) << 16) |
01128                     (static_cast<Q_UINT32>(in[j+3]) << 24);
01129 #endif
01130 }
01131 
01132 
01133 
01134 /**************************************************************/
01135 
01136 
01137 
01138 /***********************************************************/
01139 
01140 KMD4::KMD4()
01141 {
01142     init();
01143 }
01144 
01145 KMD4::KMD4(const char *in, int len)
01146 {
01147     init();
01148     update(in, len);
01149 }
01150 
01151 KMD4::KMD4(const QByteArray& in)
01152 {
01153     init();
01154     update( in );
01155 }
01156 
01157 KMD4::KMD4(const QCString& in)
01158 {
01159     init();
01160     update( in );
01161 }
01162 
01163 void KMD4::update(const QByteArray& in)
01164 {
01165     update(in.data(), int(in.size()));
01166 }
01167 
01168 void KMD4::update(const QCString& in)
01169 {
01170     update(in.data(), int(in.length()));
01171 }
01172 
01173 /*
01174  * Update context to reflect the concatenation of another buffer full
01175  * of bytes.
01176  */
01177 void KMD4::update(const unsigned char *in, int len)
01178 {
01179   if (len < 0)
01180       len = qstrlen(reinterpret_cast<const char*>(in));
01181 
01182   if (!len)
01183       return;
01184 
01185   if (m_finalized) {
01186       kdWarning() << "KMD4::update called after state was finalized!" << endl;
01187       return;
01188   }
01189 
01190   Q_UINT32 t;
01191 
01192   /* Update bitcount */
01193 
01194   t = m_count[0];
01195   if ((m_count[0] = t + ((Q_UINT32) len << 3)) < t)
01196     m_count[1]++;       /* Carry from low to high */
01197   m_count[1] += len >> 29;
01198 
01199   t = (t >> 3) & 0x3f;      /* Bytes already in shsInfo->data */
01200 
01201   /* Handle any leading odd-sized chunks */
01202 
01203   if (t)
01204     {
01205       Q_UINT8 *p = &m_buffer[ t ];
01206 
01207       t = 64 - t;
01208       if ((Q_UINT32)len < t)
01209     {
01210       memcpy (p, in, len);
01211       return;
01212     }
01213       memcpy (p, in, t);
01214       byteReverse (m_buffer, 16);
01215       transform (m_state, (Q_UINT32*) m_buffer);
01216       in += t;
01217       len -= t;
01218     }
01219   /* Process data in 64-byte chunks */
01220 
01221   while (len >= 64)
01222     {
01223       memcpy (m_buffer, in, 64);
01224       byteReverse (m_buffer, 16);
01225       transform (m_state, (Q_UINT32 *) m_buffer);
01226       in += 64;
01227       len -= 64;
01228     }
01229 
01230   /* Handle any remaining bytes of data. */
01231 
01232   memcpy (m_buffer, in, len);
01233 }
01234 
01235 bool KMD4::update(QIODevice& file)
01236 {
01237     char buffer[1024];
01238     int len;
01239 
01240     while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
01241         update(buffer, len);
01242 
01243     return file.atEnd();
01244 }
01245 
01246 /*
01247  * Final wrapup - pad to 64-byte boundary with the bit pattern 
01248  * 1 0* (64-bit count of bits processed, MSB-first)
01249  */
01250 void KMD4::finalize()
01251 {
01252   unsigned int count;
01253   unsigned char *p;
01254 
01255   /* Compute number of bytes mod 64 */
01256   count = (m_count[0] >> 3) & 0x3F;
01257 
01258   /* Set the first char of padding to 0x80.  This is safe since there is
01259      always at least one byte free */
01260   p = m_buffer + count;
01261   *p++ = 0x80;
01262 
01263   /* Bytes of padding needed to make 64 bytes */
01264   count = 64 - 1 - count;
01265 
01266   /* Pad out to 56 mod 64 */
01267   if (count < 8)
01268     {
01269       /* Two lots of padding:  Pad the first block to 64 bytes */
01270       memset (p, 0, count);
01271       byteReverse (m_buffer, 16);
01272       transform (m_state, (Q_UINT32*) m_buffer);
01273 
01274       /* Now fill the next block with 56 bytes */
01275       memset (m_buffer, 0, 56);
01276     }
01277   else
01278     {
01279       /* Pad block to 56 bytes */
01280       memset (p, 0, count - 8);
01281     }
01282   byteReverse (m_buffer, 14);
01283 
01284   /* Append length in bits and transform */
01285   ((Q_UINT32 *) m_buffer)[14] = m_count[0];
01286   ((Q_UINT32 *) m_buffer)[15] = m_count[1];
01287 
01288   transform (m_state, (Q_UINT32 *) m_buffer);
01289   byteReverse ((unsigned char *) m_state, 4);
01290 
01291   memcpy (m_digest, m_state, 16);
01292   memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
01293 
01294   m_finalized = true;
01295 }
01296 
01297 bool KMD4::verify( const KMD4::Digest& digest)
01298 {
01299     finalize();
01300     return (0 == memcmp(rawDigest(), digest, sizeof(KMD4::Digest)));
01301 }
01302 
01303 bool KMD4::verify( const QCString& hexdigest)
01304 {
01305     finalize();
01306     return (0 == strcmp(hexDigest().data(), hexdigest));
01307 }
01308 
01309 const KMD4::Digest& KMD4::rawDigest()
01310 {
01311     finalize();
01312     return m_digest;
01313 }
01314 
01315 void KMD4::rawDigest( KMD4::Digest& bin )
01316 {
01317     finalize();
01318     memcpy( bin, m_digest, 16 );
01319 }
01320 
01321 QCString KMD4::hexDigest()
01322 {
01323     QCString s(33);
01324 
01325     finalize();
01326     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
01327             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
01328             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
01329             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
01330 //    kdDebug() << "KMD4::hexDigest() " << s << endl;
01331     return s;
01332 }
01333 
01334 void KMD4::hexDigest(QCString& s)
01335 {
01336     finalize();
01337     s.resize(33);
01338     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
01339             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
01340             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
01341             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
01342 }
01343 
01344 QCString KMD4::base64Digest()
01345 {
01346     QByteArray ba(16);
01347 
01348     finalize();
01349     memcpy(ba.data(), m_digest, 16);
01350     return KCodecs::base64Encode(ba);
01351 }
01352 
01353 
01354 void KMD4::init()
01355 {
01356     d = 0;
01357     reset();
01358 }
01359 
01360 /*
01361  * Start MD4 accumulation.  Set bit count to 0 and buffer to mysterious
01362  * initialization constants.
01363  */
01364 void KMD4::reset()
01365 {
01366   m_finalized = false;
01367 
01368   m_state[0] = 0x67452301;
01369   m_state[1] = 0xefcdab89;
01370   m_state[2] = 0x98badcfe;
01371   m_state[3] = 0x10325476;
01372 
01373   m_count[0] = 0;
01374   m_count[1] = 0;
01375 
01376   memset ( m_buffer, 0, sizeof(*m_buffer));
01377   memset ( m_digest, 0, sizeof(*m_digest));
01378 }
01379 
01380 //#define rotl32(x,n)   (((x) << ((Q_UINT32)(n))) | ((x) >> (32 - (Q_UINT32)(n))))
01381 
01382 inline Q_UINT32 KMD4::rotate_left (Q_UINT32 x, Q_UINT32 n)
01383 {
01384     return (x << n) | (x >> (32-n))  ;
01385 }
01386 
01387 inline Q_UINT32 KMD4::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01388 {
01389     return (x & y) | (~x & z);
01390 }
01391 
01392 inline Q_UINT32 KMD4::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01393 {
01394     return ((x) & (y)) | ((x) & (z)) | ((y) & (z));
01395 }
01396 
01397 inline Q_UINT32 KMD4::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01398 {
01399     return x ^ y ^ z;
01400 }
01401 
01402 inline void KMD4::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01403                        Q_UINT32 x, Q_UINT32  s )
01404 {
01405     a += F(b, c, d) + x;
01406     a = rotate_left (a, s);
01407 }
01408 
01409 inline void KMD4::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01410                  Q_UINT32 x, Q_UINT32 s)
01411 {
01412     a += G(b, c, d) + x + (Q_UINT32)0x5a827999;
01413     a = rotate_left (a, s);
01414 }
01415 
01416 inline void KMD4::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01417                  Q_UINT32 x, Q_UINT32 s )
01418 {
01419     a += H(b, c, d) + x + (Q_UINT32)0x6ed9eba1;
01420     a = rotate_left (a, s);
01421 }
01422 
01423 void KMD4::byteReverse( unsigned char *buf, Q_UINT32 len )
01424 {
01425   Q_UINT32 *b = (Q_UINT32*) buf;
01426 #ifdef WORDS_BIGENDIAN
01427   while ( len > 0 ) {
01428     *b = ((((*b) & 0xff000000) >> 24) | (((*b) & 0x00ff0000) >>  8) |
01429          (((*b) & 0x0000ff00) <<  8) | (((*b) & 0x000000ff) << 24));
01430     len--;
01431     b++;
01432   }
01433 #endif
01434 }
01435 
01436 /*
01437  * The core of the MD4 algorithm
01438  */
01439 void KMD4::transform( Q_UINT32 buf[4], Q_UINT32 const in[16] )
01440 {
01441   Q_UINT32 a, b, c, d;
01442 
01443   a = buf[0];
01444   b = buf[1];
01445   c = buf[2];
01446   d = buf[3];
01447 
01448   FF (a, b, c, d, in[0], 3);    /* 1 */
01449   FF (d, a, b, c, in[1], 7);    /* 2 */
01450   FF (c, d, a, b, in[2], 11);   /* 3 */
01451   FF (b, c, d, a, in[3], 19);   /* 4 */
01452   FF (a, b, c, d, in[4], 3);    /* 5 */
01453   FF (d, a, b, c, in[5], 7);    /* 6 */
01454   FF (c, d, a, b, in[6], 11);   /* 7 */
01455   FF (b, c, d, a, in[7], 19);   /* 8 */
01456   FF (a, b, c, d, in[8], 3);    /* 9 */
01457   FF (d, a, b, c, in[9], 7);    /* 10 */
01458   FF (c, d, a, b, in[10], 11);  /* 11 */
01459   FF (b, c, d, a, in[11], 19);  /* 12 */
01460   FF (a, b, c, d, in[12], 3);   /* 13 */
01461   FF (d, a, b, c, in[13], 7);   /* 14 */
01462   FF (c, d, a, b, in[14], 11);  /* 15 */
01463   FF (b, c, d, a, in[15], 19);  /* 16 */
01464 
01465   GG (a, b, c, d, in[0], 3);    /* 17 */
01466   GG (d, a, b, c, in[4], 5);    /* 18 */
01467   GG (c, d, a, b, in[8], 9);    /* 19 */
01468   GG (b, c, d, a, in[12], 13);  /* 20 */
01469   GG (a, b, c, d, in[1], 3);    /* 21 */
01470   GG (d, a, b, c, in[5], 5);    /* 22 */
01471   GG (c, d, a, b, in[9], 9);    /* 23 */
01472   GG (b, c, d, a, in[13], 13);  /* 24 */
01473   GG (a, b, c, d, in[2], 3);    /* 25 */
01474   GG (d, a, b, c, in[6], 5);    /* 26 */
01475   GG (c, d, a, b, in[10], 9);   /* 27 */
01476   GG (b, c, d, a, in[14], 13);  /* 28 */
01477   GG (a, b, c, d, in[3], 3);    /* 29 */
01478   GG (d, a, b, c, in[7], 5);    /* 30 */
01479   GG (c, d, a, b, in[11], 9);   /* 31 */
01480   GG (b, c, d, a, in[15], 13);  /* 32 */
01481 
01482   HH (a, b, c, d, in[0], 3);    /* 33 */
01483   HH (d, a, b, c, in[8], 9);    /* 34 */
01484   HH (c, d, a, b, in[4], 11);   /* 35 */
01485   HH (b, c, d, a, in[12], 15);  /* 36 */
01486   HH (a, b, c, d, in[2], 3);    /* 37 */
01487   HH (d, a, b, c, in[10], 9);   /* 38 */
01488   HH (c, d, a, b, in[6], 11);   /* 39 */
01489   HH (b, c, d, a, in[14], 15);  /* 40 */
01490   HH (a, b, c, d, in[1], 3);    /* 41 */
01491   HH (d, a, b, c, in[9], 9);    /* 42 */
01492   HH (c, d, a, b, in[5], 11);   /* 43 */
01493   HH (b, c, d, a, in[13], 15);  /* 44 */
01494   HH (a, b, c, d, in[3], 3);    /* 45 */
01495   HH (d, a, b, c, in[11], 9);   /* 46 */
01496   HH (c, d, a, b, in[7], 11);   /* 47 */
01497   HH (b, c, d, a, in[15], 15);  /* 48 */
01498 
01499 
01500   buf[0] += a;
01501   buf[1] += b;
01502   buf[2] += c;
01503   buf[3] += d;
01504 }
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 Wed May 4 07:11:21 2005 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003