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

KDECore

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

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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