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

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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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