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., 675 Mass Ave, Cambridge, MA 02139, 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 
00034 #include <config.h>
00035 
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 
00040 #include <kdebug.h>
00041 #include "kmdcodec.h"
00042 
00043 #define KMD5_S11 7
00044 #define KMD5_S12 12
00045 #define KMD5_S13 17
00046 #define KMD5_S14 22
00047 #define KMD5_S21 5
00048 #define KMD5_S22 9
00049 #define KMD5_S23 14
00050 #define KMD5_S24 20
00051 #define KMD5_S31 4
00052 #define KMD5_S32 11
00053 #define KMD5_S33 16
00054 #define KMD5_S34 23
00055 #define KMD5_S41 6
00056 #define KMD5_S42 10
00057 #define KMD5_S43 15
00058 #define KMD5_S44 21
00059 
00060 const char KCodecs::Base64EncMap[64] =
00061 {
00062   0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
00063   0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
00064   0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
00065   0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
00066   0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
00067   0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
00068   0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
00069   0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
00070 };
00071 
00072 const char KCodecs::Base64DecMap[128] =
00073 {
00074   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00075   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00076   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00077   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00078   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00079   0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
00080   0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
00081   0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00082   0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
00083   0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
00084   0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
00085   0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
00086   0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
00087   0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
00088   0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
00089   0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
00090 };
00091 
00092 const char KCodecs::UUEncMap[64] =
00093 {
00094   0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
00095   0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
00096   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
00097   0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
00098   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
00099   0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
00100   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
00101   0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
00102 };
00103 
00104 const char KCodecs::UUDecMap[128] =
00105 {
00106   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00107   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00108   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00109   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00110   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
00111   0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
00112   0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
00113   0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
00114   0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
00115   0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
00116   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
00117   0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
00118   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00119   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00120   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00121   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00122 };
00123 
00124 const char KCodecs::hexChars[16] =
00125 {
00126   '0', '1', '2', '3', '4', '5', '6', '7',
00127   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
00128 };
00129 
00130 const unsigned int KCodecs::maxQPLineLength = 70;
00131 
00132 
00133 /******************************** KCodecs ********************************/
00134 // strchr(3) for broken systems.
00135 static int rikFindChar(register const char * _s, const char c)
00136 {
00137   register const char * s = _s;
00138 
00139   while (true)
00140   {
00141     if ((0 == *s) || (c == *s)) break; ++s;
00142     if ((0 == *s) || (c == *s)) break; ++s;
00143     if ((0 == *s) || (c == *s)) break; ++s;
00144     if ((0 == *s) || (c == *s)) break; ++s;
00145   }
00146 
00147   return s - _s;
00148 }
00149 
00150 QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF)
00151 {
00152   QByteArray out;
00153   quotedPrintableEncode (in, out, useCRLF);
00154   return QCString (out.data(), out.size()+1);
00155 }
00156 
00157 QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF)
00158 {
00159   if (str.isEmpty())
00160     return "";
00161 
00162   QByteArray in (str.length());
00163   memcpy (in.data(), str.data(), str.length());
00164   return quotedPrintableEncode(in, useCRLF);
00165 }
00166 
00167 void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF)
00168 {
00169   out.resize (0);
00170   if (in.isEmpty())
00171     return;
00172 
00173   char *cursor;
00174   const char *data;
00175   unsigned int lineLength;
00176   unsigned int pos;
00177 
00178   const unsigned int length = in.size();
00179   const unsigned int end = length - 1;
00180 
00181 
00182   // Reasonable guess for output size when we're encoding
00183   // mostly-ASCII data. It doesn't really matter, because
00184   // the underlying allocation routines are quite efficient,
00185   // but it's nice to have 0 allocations in many cases.
00186   out.resize ((length*12)/10);
00187   cursor = out.data();
00188   data = in.data();
00189   lineLength = 0;
00190   pos = 0;
00191 
00192   for (unsigned int i = 0; i < length; i++)
00193   {
00194     unsigned char c (data[i]);
00195 
00196     // check if we have to enlarge the output buffer, use
00197     // a safety margin of 16 byte
00198     pos = cursor-out.data();
00199     if (out.size()-pos < 16) {
00200       out.resize(out.size()+4096);
00201       cursor = out.data()+pos;
00202     }
00203 
00204     // Plain ASCII chars just go straight out.
00205 
00206     if ((c >= 33) && (c <= 126) && ('=' != c))
00207     {
00208       *cursor++ = c;
00209       ++lineLength;
00210     }
00211 
00212     // Spaces need some thought. We have to encode them at eol (or eof).
00213 
00214     else if (' ' == c)
00215     {
00216       if
00217         (
00218          (i >= length)
00219          ||
00220          ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2]))
00221                         ||
00222                         (!useCRLF && ('\n' == data[i + 1]))))
00223         )
00224       {
00225         *cursor++ = '=';
00226         *cursor++ = '2';
00227         *cursor++ = '0';
00228 
00229         lineLength += 3;
00230       }
00231       else
00232       {
00233         *cursor++ = ' ';
00234         ++lineLength;
00235       }
00236     }
00237     // If we find a line break, just let it through.
00238     else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) ||
00239              (!useCRLF && ('\n' == c)))
00240     {
00241       lineLength = 0;
00242 
00243       if (useCRLF) {
00244         *cursor++ = '\r';
00245         *cursor++ = '\n';
00246         ++i;
00247       } else {
00248         *cursor++ = '\n';
00249       }
00250     }
00251 
00252     // Anything else is converted to =XX.
00253 
00254     else
00255     {
00256       *cursor++ = '=';
00257       *cursor++ = hexChars[c / 16];
00258       *cursor++ = hexChars[c % 16];
00259 
00260       lineLength += 3;
00261     }
00262 
00263     // If we're approaching the maximum line length, do a soft line break.
00264 
00265     if ((lineLength > maxQPLineLength) && (i < end))
00266     {
00267       if (useCRLF) {
00268         *cursor++ = '=';
00269         *cursor++ = '\r';
00270         *cursor++ = '\n';
00271       } else {
00272         *cursor++ = '=';
00273         *cursor++ = '\n';
00274       }
00275 
00276       lineLength = 0;
00277     }
00278   }
00279 
00280   out.truncate(cursor - out.data());
00281 }
00282 
00283 QCString KCodecs::quotedPrintableDecode(const QByteArray & in)
00284 {
00285   QByteArray out;
00286   quotedPrintableDecode (in, out);
00287   return QCString (out.data(), out.size()+1);
00288 }
00289 
00290 QCString KCodecs::quotedPrintableDecode(const QCString & str)
00291 {
00292   if (str.isEmpty())
00293     return "";
00294 
00295   QByteArray in (str.length());
00296   memcpy (in.data(), str.data(), str.length());
00297   return quotedPrintableDecode (in);
00298 }
00299 
00300 void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out)
00301 {
00302   // clear out the output buffer
00303   out.resize (0);
00304   if (in.isEmpty())
00305       return;
00306 
00307   char *cursor;
00308   const char *data;
00309   const unsigned int length = in.size();
00310 
00311   data = in.data();
00312   out.resize (length);
00313   cursor = out.data();
00314 
00315   for (unsigned int i = 0; i < length; i++)
00316   {
00317     char c(in[i]);
00318 
00319     if ('=' == c)
00320     {
00321       if (i < length - 2)
00322       {
00323         char c1 = in[i + 1];
00324         char c2 = in[i + 2];
00325 
00326         if (('\n' == c1) || ('\r' == c1 && '\n' == c2))
00327         {
00328           // Soft line break. No output.
00329           if ('\r' == c1)
00330             i += 2;        // CRLF line breaks
00331           else
00332             i += 1;
00333         }
00334         else
00335         {
00336           // =XX encoded byte.
00337 
00338           int hexChar0 = rikFindChar(hexChars, c1);
00339           int hexChar1 = rikFindChar(hexChars, c2);
00340 
00341           if (hexChar0 < 16 && hexChar1 < 16)
00342           {
00343             *cursor++ = char((hexChar0 * 16) | hexChar1);
00344             i += 2;
00345           }
00346         }
00347       }
00348     }
00349     else
00350     {
00351       *cursor++ = c;
00352     }
00353   }
00354 
00355   out.truncate(cursor - out.data());
00356 }
00357 
00358 QCString KCodecs::base64Encode( const QCString& str, bool insertLFs )
00359 {
00360     if ( str.isEmpty() )
00361         return "";
00362 
00363     QByteArray in (str.length());
00364     memcpy( in.data(), str.data(), str.length() );
00365     return base64Encode( in, insertLFs );
00366 }
00367 
00368 QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs )
00369 {
00370     QByteArray out;
00371     base64Encode( in, out, insertLFs );
00372     return QCString( out.data(), out.size()+1 );
00373 }
00374 
00375 void KCodecs::base64Encode( const QByteArray& in, QByteArray& out,
00376                             bool insertLFs )
00377 {
00378     // clear out the output buffer
00379     out.resize (0);
00380     if ( in.isEmpty() )
00381         return;
00382 
00383     unsigned int sidx = 0;
00384     unsigned int didx = 0;
00385     const char* data = in.data();
00386     const unsigned int len = in.size();
00387 
00388     unsigned int out_len = ((len+2)/3)*4;
00389 
00390     // Deal with the 76 characters or less per
00391     // line limit specified in RFC 2045 on a
00392     // pre request basis.
00393     insertLFs = (insertLFs && out_len > 76);
00394     if ( insertLFs )
00395       out_len += ((out_len-1)/76);
00396 
00397     int count = 0;
00398     out.resize( out_len );
00399 
00400     // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00401     if ( len > 1 )
00402     {
00403         while (sidx < len-2)
00404         {
00405             if ( insertLFs )
00406             {
00407                 if ( count && (count%76) == 0 )
00408                     out[didx++] = '\n';
00409                 count += 4;
00410             }
00411             out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
00412             out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
00413                                        (data[sidx] << 4) & 077];
00414             out[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 |
00415                                        (data[sidx+1] << 2) & 077];
00416             out[didx++] = Base64EncMap[data[sidx+2] & 077];
00417             sidx += 3;
00418         }
00419     }
00420 
00421     if (sidx < len)
00422     {
00423         if ( insertLFs && (count > 0) && (count%76) == 0 )
00424            out[didx++] = '\n';
00425 
00426         out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
00427         if (sidx < len-1)
00428         {
00429             out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
00430                                        (data[sidx] << 4) & 077];
00431             out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077];
00432         }
00433         else
00434         {
00435             out[didx++] = Base64EncMap[(data[sidx] << 4) & 077];
00436         }
00437     }
00438 
00439     // Add padding
00440     while (didx < out.size())
00441     {
00442         out[didx] = '=';
00443         didx++;
00444     }
00445 }
00446 
00447 QCString KCodecs::base64Decode( const QCString& str )
00448 {
00449     if ( str.isEmpty() )
00450         return "";
00451 
00452     QByteArray in( str.length() );
00453     memcpy( in.data(), str.data(), str.length() );
00454     return base64Decode( in );
00455 }
00456 
00457 QCString KCodecs::base64Decode( const QByteArray& in )
00458 {
00459     QByteArray out;
00460     base64Decode( in, out );
00461     return QCString( out.data(), out.size()+1 );
00462 }
00463 
00464 void KCodecs::base64Decode( const QByteArray& in, QByteArray& out )
00465 {
00466     out.resize(0);
00467     if ( in.isEmpty() )
00468         return;
00469 
00470     unsigned int count = 0;
00471     unsigned int len = in.size(), tail = len;
00472     const char* data = in.data();
00473 
00474     // Deal with possible *nix "BEGIN" marker!!
00475     while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
00476             data[count] == '\t' || data[count] == ' ') )
00477         count++;
00478 
00479     if ( strncasecmp(data+count, "begin", 5) == 0 )
00480     {
00481         count += 5;
00482         while ( count < len && data[count] != '\n' && data[count] != '\r' )
00483             count++;
00484 
00485         while ( count < len && (data[count] == '\n' || data[count] == '\r') )
00486             count ++;
00487 
00488         data += count;
00489         tail = (len -= count);
00490     }
00491 
00492     // Find the tail end of the actual encoded data even if
00493     // there is/are trailing CR and/or LF.
00494     while ( data[tail-1] == '=' || data[tail-1] == '\n' ||
00495             data[tail-1] == '\r' )
00496         if ( data[--tail] != '=' ) len = tail;
00497 
00498     unsigned int outIdx = 0;
00499     out.resize( (count=len) );
00500     for (unsigned int idx = 0; idx < count; idx++)
00501     {
00502         // Adhere to RFC 2045 and ignore characters
00503         // that are not part of the encoding table.
00504         unsigned char ch = data[idx];
00505         if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
00506             (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
00507         {
00508             out[outIdx++] = Base64DecMap[ch];
00509         }
00510         else
00511         {
00512             len--;
00513             tail--;
00514         }
00515     }
00516 
00517     // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl;
00518 
00519     // 4-byte to 3-byte conversion
00520     len = (tail>(len/4)) ? tail-(len/4) : 0;
00521     unsigned int sidx = 0, didx = 0;
00522     if ( len > 1 )
00523     {
00524       while (didx < len-2)
00525       {
00526           out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
00527           out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
00528           out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077));
00529           sidx += 4;
00530           didx += 3;
00531       }
00532     }
00533 
00534     if (didx < len)
00535         out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
00536 
00537     if (++didx < len )
00538         out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
00539 
00540     // Resize the output buffer
00541     if ( len == 0 || len < out.size() )
00542       out.resize(len);
00543 }
00544 
00545 QCString KCodecs::uuencode( const QCString& str )
00546 {
00547     if ( str.isEmpty() )
00548         return "";
00549 
00550     QByteArray in;
00551     in.resize( str.length() );
00552     memcpy( in.data(), str.data(), str.length() );
00553     return uuencode( in );
00554 }
00555 
00556 QCString KCodecs::uuencode( const QByteArray& in )
00557 {
00558     QByteArray out;
00559     uuencode( in, out );
00560     return QCString( out.data(), out.size()+1 );
00561 }
00562 
00563 void KCodecs::uuencode( const QByteArray& in, QByteArray& out )
00564 {
00565     out.resize( 0 );
00566     if( in.isEmpty() )
00567         return;
00568 
00569     unsigned int sidx = 0;
00570     unsigned int didx = 0;
00571     unsigned int line_len = 45;
00572 
00573     const char nl[] = "\n";
00574     const char* data = in.data();
00575     const unsigned int nl_len = strlen(nl);
00576     const unsigned int len = in.size();
00577 
00578     out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
00579     // split into lines, adding line-length and line terminator
00580     while (sidx+line_len < len)
00581     {
00582         // line length
00583         out[didx++] = UUEncMap[line_len];
00584 
00585         // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00586         for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
00587         {
00588             out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00589             out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
00590                                    (data[sidx] << 4) & 077];
00591             out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
00592                                 (data[sidx+1] << 2) & 077];
00593             out[didx++] = UUEncMap[data[sidx+2] & 077];
00594         }
00595 
00596         // line terminator
00597         //for (unsigned int idx=0; idx < nl_len; idx++)
00598         //out[didx++] = nl[idx];
00599         memcpy(out.data()+didx, nl, nl_len);
00600         didx += nl_len;
00601     }
00602 
00603     // line length
00604     out[didx++] = UUEncMap[len-sidx];
00605     // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00606     while (sidx+2 < len)
00607     {
00608         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00609         out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
00610                                (data[sidx] << 4) & 077];
00611         out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
00612                                (data[sidx+1] << 2) & 077];
00613         out[didx++] = UUEncMap[data[sidx+2] & 077];
00614         sidx += 3;
00615     }
00616 
00617     if (sidx < len-1)
00618     {
00619         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00620         out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
00621                                (data[sidx] << 4) & 077];
00622         out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077];
00623         out[didx++] = UUEncMap[0];
00624     }
00625     else if (sidx < len)
00626     {
00627         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00628         out[didx++] = UUEncMap[(data[sidx] << 4) & 077];
00629         out[didx++] = UUEncMap[0];
00630         out[didx++] = UUEncMap[0];
00631     }
00632 
00633     // line terminator
00634     memcpy(out.data()+didx, nl, nl_len);
00635     didx += nl_len;
00636 
00637     // sanity check
00638     if ( didx != out.size() )
00639         out.resize( 0 );
00640 }
00641 
00642 QCString KCodecs::uudecode( const QCString& str )
00643 {
00644     if ( str.isEmpty() )
00645         return "";
00646 
00647     QByteArray in;
00648     in.resize( str.length() );
00649     memcpy( in.data(), str.data(), str.length() );
00650     return uudecode( in );
00651 }
00652 
00653 QCString KCodecs::uudecode( const QByteArray& in )
00654 {
00655     QByteArray out;
00656     uudecode( in, out );
00657     return QCString( out.data(), out.size()+1 );
00658 }
00659 
00660 void KCodecs::uudecode( const QByteArray& in, QByteArray& out )
00661 {
00662     out.resize( 0 );
00663     if( in.isEmpty() )
00664         return;
00665 
00666     unsigned int sidx = 0;
00667     unsigned int didx = 0;
00668     unsigned int len = in.size();
00669     unsigned int line_len, end;
00670     const char* data = in.data();
00671 
00672     // Deal with *nix "BEGIN"/"END" separators!!
00673     unsigned int count = 0;
00674     while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
00675             data[count] == '\t' || data[count] == ' ') )
00676         count ++;
00677 
00678     bool hasLF = false;
00679     if ( strncasecmp( data+count, "begin", 5) == 0 )
00680     {
00681         count += 5;
00682         while ( count < len && data[count] != '\n' && data[count] != '\r' )
00683             count ++;
00684 
00685         while ( count < len && (data[count] == '\n' || data[count] == '\r') )
00686             count ++;
00687 
00688         data += count;
00689         len -= count;
00690         hasLF = true;
00691     }
00692 
00693     out.resize( len/4*3 );
00694     while ( sidx < len )
00695     {
00696         // get line length (in number of encoded octets)
00697         line_len = UUDecMap[ (unsigned char) data[sidx++]];
00698         // ascii printable to 0-63 and 4-byte to 3-byte conversion
00699         end = didx+line_len;
00700         char A, B, C, D;
00701         if (end > 2) {
00702           while (didx < end-2)
00703           {
00704              A = UUDecMap[(unsigned char) data[sidx]];
00705              B = UUDecMap[(unsigned char) data[sidx+1]];
00706              C = UUDecMap[(unsigned char) data[sidx+2]];
00707              D = UUDecMap[(unsigned char) data[sidx+3]];
00708              out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
00709              out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
00710              out[didx++] = ( ((C << 6) & 255) | (D & 077) );
00711              sidx += 4;
00712           }
00713         }
00714 
00715         if (didx < end)
00716         {
00717             A = UUDecMap[(unsigned char) data[sidx]];
00718             B = UUDecMap[(unsigned char) data[sidx+1]];
00719             out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
00720         }
00721 
00722         if (didx < end)
00723         {
00724             B = UUDecMap[(unsigned char) data[sidx+1]];
00725             C = UUDecMap[(unsigned char) data[sidx+2]];
00726             out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
00727         }
00728 
00729         // skip padding
00730         while (sidx < len  && data[sidx] != '\n' && data[sidx] != '\r')
00731             sidx++;
00732 
00733         // skip end of line
00734         while (sidx < len  && (data[sidx] == '\n' || data[sidx] == '\r'))
00735             sidx++;
00736 
00737         // skip the "END" separator when present.
00738         if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 )
00739             break;
00740     }
00741 
00742     if ( didx < out.size()  )
00743         out.resize( didx );
00744 }
00745 
00746 /******************************** KMD5 ********************************/
00747 KMD5::KMD5()
00748 {
00749     init();
00750 }
00751 
00752 KMD5::KMD5(const char *in, int len)
00753 {
00754     init();
00755     update(in, len);
00756 }
00757 
00758 KMD5::KMD5(const QByteArray& in)
00759 {
00760     init();
00761     update( in );
00762 }
00763 
00764 KMD5::KMD5(const QCString& in)
00765 {
00766     init();
00767     update( in );
00768 }
00769 
00770 void KMD5::update(const QByteArray& in)
00771 {
00772     update(in.data(), int(in.size()));
00773 }
00774 
00775 void KMD5::update(const QCString& in)
00776 {
00777     update(in.data(), int(in.length()));
00778 }
00779 
00780 void KMD5::update(const unsigned char* in, int len)
00781 {
00782     if (len < 0)
00783         len = qstrlen(reinterpret_cast<const char*>(in));
00784 
00785     if (!len)
00786         return;
00787 
00788     if (m_finalized) {
00789         kdWarning() << "KMD5::update called after state was finalized!" << endl;
00790         return;
00791     }
00792 
00793     Q_UINT32 in_index;
00794     Q_UINT32 buffer_index;
00795     Q_UINT32 buffer_space;
00796     Q_UINT32 in_length = static_cast<Q_UINT32>( len );
00797 
00798     buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F);
00799 
00800     if (  (m_count[0] += (in_length << 3))<(in_length << 3) )
00801         m_count[1]++;
00802 
00803     m_count[1] += (in_length >> 29);
00804     buffer_space = 64 - buffer_index;
00805 
00806     if (in_length >= buffer_space)
00807     {
00808         memcpy (m_buffer + buffer_index, in, buffer_space);
00809         transform (m_buffer);
00810 
00811         for (in_index = buffer_space; in_index + 63 < in_length;
00812              in_index += 64)
00813             transform (reinterpret_cast<const unsigned char*>(in+in_index));
00814 
00815         buffer_index = 0;
00816     }
00817     else
00818         in_index=0;
00819 
00820     memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
00821 }
00822 
00823 bool KMD5::update(QIODevice& file)
00824 {
00825     char buffer[1024];
00826     int len;
00827 
00828     while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
00829         update(buffer, len);
00830 
00831     return file.atEnd();
00832 }
00833 
00834 void KMD5::finalize ()
00835 {
00836     if (m_finalized) return;
00837 
00838     Q_UINT8 bits[8];
00839     Q_UINT32 index, padLen;
00840     static unsigned char PADDING[64]=
00841     {
00842         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00843         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00844         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00845         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00846     };
00847 
00848     encode (bits, m_count, 8);
00849     //memcpy( bits, m_count, 8 );
00850 
00851     // Pad out to 56 mod 64.
00852     index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f);
00853     padLen = (index < 56) ? (56 - index) : (120 - index);
00854     update (reinterpret_cast<const char*>(PADDING), padLen);
00855 
00856     // Append length (before padding)
00857     update (reinterpret_cast<const char*>(bits), 8);
00858 
00859     // Store state in digest
00860     encode (m_digest, m_state, 16);
00861     //memcpy( m_digest, m_state, 16 );
00862 
00863     // Fill sensitive information with zero's
00864     memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
00865 
00866     m_finalized = true;
00867 }
00868 
00869 
00870 bool KMD5::verify( const KMD5::Digest& digest)
00871 {
00872     finalize();
00873     return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
00874 }
00875 
00876 bool KMD5::verify( const QCString& hexdigest)
00877 {
00878     finalize();
00879     return (0 == strcmp(hexDigest().data(), hexdigest));
00880 }
00881 
00882 const KMD5::Digest& KMD5::rawDigest()
00883 {
00884     finalize();
00885     return m_digest;
00886 }
00887 
00888 void KMD5::rawDigest( KMD5::Digest& bin )
00889 {
00890     finalize();
00891     memcpy( bin, m_digest, 16 );
00892 }
00893 
00894 
00895 QCString KMD5::hexDigest()
00896 {
00897     QCString s(33);
00898 
00899     finalize();
00900     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00901             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
00902             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
00903             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
00904 
00905     return s;
00906 }
00907 
00908 void KMD5::hexDigest(QCString& s)
00909 {
00910     finalize();
00911     s.resize(33);
00912     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00913             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
00914             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
00915             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
00916 }
00917 
00918 QCString KMD5::base64Digest()
00919 {
00920     QByteArray ba(16);
00921 
00922     finalize();
00923     memcpy(ba.data(), m_digest, 16);
00924     return KCodecs::base64Encode(ba);
00925 }
00926 
00927 
00928 void KMD5::init()
00929 {
00930     d = 0;
00931     reset();
00932 }
00933 
00934 void KMD5::reset()
00935 {
00936     m_finalized = false;
00937 
00938     m_count[0] = 0;
00939     m_count[1] = 0;
00940 
00941     m_state[0] = 0x67452301;
00942     m_state[1] = 0xefcdab89;
00943     m_state[2] = 0x98badcfe;
00944     m_state[3] = 0x10325476;
00945 
00946     memset ( m_buffer, 0, sizeof(*m_buffer));
00947     memset ( m_digest, 0, sizeof(*m_digest));
00948 }
00949 
00950 void KMD5::transform( const unsigned char block[64] )
00951 {
00952 
00953     Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
00954 
00955     decode (x, block, 64);
00956     //memcpy( x, block, 64 );
00957 
00958     Q_ASSERT(!m_finalized);  // not just a user error, since the method is private
00959 
00960     /* Round 1 */
00961     FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */
00962     FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */
00963     FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */
00964     FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */
00965     FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */
00966     FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */
00967     FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */
00968     FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */
00969     FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */
00970     FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */
00971     FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */
00972     FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */
00973     FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */
00974     FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */
00975     FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */
00976     FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */
00977 
00978     /* Round 2 */
00979     GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */
00980     GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */
00981     GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */
00982     GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */
00983     GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */
00984     GG (d, a, b, c, x[10], KMD5_S22,  0x2441453); /* 22 */
00985     GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */
00986     GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */
00987     GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */
00988     GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */
00989     GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */
00990     GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */
00991     GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */
00992     GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */
00993     GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */
00994     GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */
00995 
00996     /* Round 3 */
00997     HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */
00998     HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */
00999     HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */
01000     HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */
01001     HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */
01002     HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */
01003     HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */
01004     HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */
01005     HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */
01006     HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */
01007     HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */
01008     HH (b, c, d, a, x[ 6], KMD5_S34,  0x4881d05); /* 44 */
01009     HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */
01010     HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */
01011     HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */
01012     HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */
01013 
01014     /* Round 4 */
01015     II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */
01016     II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */
01017     II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */
01018     II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */
01019     II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */
01020     II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */
01021     II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */
01022     II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */
01023     II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */
01024     II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */
01025     II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */
01026     II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */
01027     II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */
01028     II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */
01029     II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */
01030     II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */
01031 
01032     m_state[0] += a;
01033     m_state[1] += b;
01034     m_state[2] += c;
01035     m_state[3] += d;
01036 
01037     memset ( static_cast<void *>(x), 0, sizeof(x) );
01038 }
01039 
01040 inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
01041 {
01042     return (x << n) | (x >> (32-n))  ;
01043 }
01044 
01045 inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01046 {
01047     return (x & y) | (~x & z);
01048 }
01049 
01050 inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01051 {
01052     return (x & z) | (y & ~z);
01053 }
01054 
01055 inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01056 {
01057     return x ^ y ^ z;
01058 }
01059 
01060 inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
01061 {
01062     return y ^ (x | ~z);
01063 }
01064 
01065 void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
01066                        Q_UINT32 x, Q_UINT32  s, Q_UINT32 ac )
01067 {
01068     a += F(b, c, d) + x + ac;
01069     a = rotate_left (a, s) +b;
01070 }
01071 
01072 void KMD5::GG ( 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 += G(b, c, d) + x + ac;
01076     a = rotate_left (a, s) +b;
01077 }
01078 
01079 void KMD5::HH ( 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 += H(b, c, d) + x + ac;
01083     a = rotate_left (a, s) +b;
01084 }
01085 
01086 void KMD5::II ( 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 += I(b, c, d) + x + ac;
01090     a = rotate_left (a, s) +b;
01091 }
01092 
01093 
01094 void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len )
01095 {
01096 #if !defined(WORDS_BIGENDIAN)
01097     memcpy(output, in, len);
01098 
01099 #else
01100     Q_UINT32 i, j;
01101     for (i = 0, j = 0; j < len; i++, j += 4)
01102     {
01103         output[j]   = static_cast<Q_UINT8>((in[i] & 0xff));
01104         output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff));
01105         output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff));
01106         output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff));
01107     }
01108 #endif
01109 }
01110 
01111 // Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a
01112 // multiple of 4.
01113 void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len)
01114 {
01115 #if !defined(WORDS_BIGENDIAN)
01116     memcpy(output, in, len);
01117 
01118 #else
01119     Q_UINT32 i, j;
01120     for (i = 0, j = 0; j < len; i++, j += 4)
01121         output[i] = static_cast<Q_UINT32>(in[j]) |
01122                     (static_cast<Q_UINT32>(in[j+1]) << 8)  |
01123                     (static_cast<Q_UINT32>(in[j+2]) << 16) |
01124                     (static_cast<Q_UINT32>(in[j+3]) << 24);
01125 #endif
01126 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:20:41 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001