MythTV  0.26-pre
mcodecs.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 QMD5 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 QCodecs 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 <stdio.h>
00035 #include <string.h>
00036 #include <stdlib.h>
00037 
00038 #include <QtCore/QIODevice>
00039 #include <QtDebug>
00040 
00041 #include "compat.h"
00042 #include "mcodecs.h"
00043 
00044 #define QMD5_S11 7
00045 #define QMD5_S12 12
00046 #define QMD5_S13 17
00047 #define QMD5_S14 22
00048 #define QMD5_S21 5
00049 #define QMD5_S22 9
00050 #define QMD5_S23 14
00051 #define QMD5_S24 20
00052 #define QMD5_S31 4
00053 #define QMD5_S32 11
00054 #define QMD5_S33 16
00055 #define QMD5_S34 23
00056 #define QMD5_S41 6
00057 #define QMD5_S42 10
00058 #define QMD5_S43 15
00059 #define QMD5_S44 21
00060 
00061 namespace QCodecs
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 QCodecs
00137 
00138 
00139 /******************************** QCodecs ********************************/
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 QCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF)
00157 {
00158   QByteArray out;
00159   quotedPrintableEncode (in, out, useCRLF);
00160   return out;
00161 }
00162 
00163 void QCodecs::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 QCodecs::quotedPrintableDecode(const QByteArray & in)
00280 {
00281   QByteArray out;
00282   quotedPrintableDecode (in, out);
00283   return out;
00284 }
00285 
00286 
00287 void QCodecs::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 unsigned int length = in.size();
00296 
00297   out.resize (length);
00298   cursor = out.data();
00299 
00300   for (unsigned int i = 0; i < length; i++)
00301   {
00302     char c(in[i]);
00303 
00304     if ('=' == c)
00305     {
00306       if (i < length - 2)
00307       {
00308         char c1 = in[i + 1];
00309         char c2 = in[i + 2];
00310 
00311         if (('\n' == c1) || ('\r' == c1 && '\n' == c2))
00312         {
00313           // Soft line break. No output.
00314           if ('\r' == c1)
00315             i += 2;        // CRLF line breaks
00316           else
00317             i += 1;
00318         }
00319         else
00320         {
00321           // =XX encoded byte.
00322 
00323           int hexChar0 = rikFindChar(hexChars, c1);
00324           int hexChar1 = rikFindChar(hexChars, c2);
00325 
00326           if (hexChar0 < 16 && hexChar1 < 16)
00327           {
00328             *cursor++ = char((hexChar0 * 16) | hexChar1);
00329             i += 2;
00330           }
00331         }
00332       }
00333     }
00334     else
00335     {
00336       *cursor++ = c;
00337     }
00338   }
00339 
00340   out.truncate(cursor - out.data());
00341 }
00342 
00343 QByteArray QCodecs::base64Encode( const QByteArray& in, bool insertLFs )
00344 {
00345     QByteArray out;
00346     base64Encode( in, out, insertLFs );
00347     return out;
00348 }
00349 
00350 void QCodecs::base64Encode( const QByteArray& in, QByteArray& out,
00351                             bool insertLFs )
00352 {
00353     // clear out the output buffer
00354     out.resize (0);
00355     if ( in.isEmpty() )
00356         return;
00357 
00358     unsigned int sidx = 0;
00359     int didx = 0;
00360     const char* data = in.data();
00361     const unsigned int len = in.size();
00362 
00363     unsigned int out_len = ((len+2)/3)*4;
00364 
00365     // Deal with the 76 characters or less per
00366     // line limit specified in RFC 2045 on a
00367     // pre request basis.
00368     insertLFs = (insertLFs && out_len > 76);
00369     if ( insertLFs )
00370       out_len += ((out_len-1)/76);
00371 
00372     int count = 0;
00373     out.resize( out_len );
00374 
00375     // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00376     if ( len > 1 )
00377     {
00378         while (sidx < len-2)
00379         {
00380             if ( insertLFs )
00381             {
00382                 if ( count && (count%76) == 0 )
00383                     out[didx++] = '\n';
00384                 count += 4;
00385             }
00386             out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
00387             out[didx++] = Base64EncMap[((data[sidx+1] >> 4) & 017) |
00388                                        ((data[sidx] << 4) & 077)];
00389             out[didx++] = Base64EncMap[((data[sidx+2] >> 6) & 003) |
00390                                        ((data[sidx+1] << 2) & 077)];
00391             out[didx++] = Base64EncMap[data[sidx+2] & 077];
00392             sidx += 3;
00393         }
00394     }
00395 
00396     if (sidx < len)
00397     {
00398         if ( insertLFs && (count > 0) && (count%76) == 0 )
00399            out[didx++] = '\n';
00400 
00401         out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
00402         if (sidx < len-1)
00403         {
00404             out[didx++] = Base64EncMap[((data[sidx+1] >> 4) & 017) |
00405                                        ((data[sidx] << 4) & 077)];
00406             out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077];
00407         }
00408         else
00409         {
00410             out[didx++] = Base64EncMap[(data[sidx] << 4) & 077];
00411         }
00412     }
00413 
00414     // Add padding
00415     while (didx < out.size())
00416     {
00417         out[didx] = '=';
00418         didx++;
00419     }
00420 }
00421 
00422 QByteArray QCodecs::base64Decode( const QByteArray& in )
00423 {
00424     QByteArray out;
00425     base64Decode( in, out );
00426     return out;
00427 }
00428 
00429 void QCodecs::base64Decode( const QByteArray& in, QByteArray& out )
00430 {
00431     out.resize(0);
00432     if ( in.isEmpty() )
00433         return;
00434 
00435     int count = 0;
00436     int len = in.size(), tail = len;
00437     const char* data = in.data();
00438 
00439     // Deal with possible *nix "BEGIN" marker!!
00440     while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
00441             data[count] == '\t' || data[count] == ' ') )
00442         count++;
00443 
00444     if ( strncasecmp(data+count, "begin", 5) == 0 )
00445     {
00446         count += 5;
00447         while ( count < len && data[count] != '\n' && data[count] != '\r' )
00448             count++;
00449 
00450         while ( count < len && (data[count] == '\n' || data[count] == '\r') )
00451             count ++;
00452 
00453         data += count;
00454         tail = (len -= count);
00455     }
00456 
00457     // Find the tail end of the actual encoded data even if
00458     // there is/are trailing CR and/or LF.
00459     while ( data[tail-1] == '=' || data[tail-1] == '\n' ||
00460             data[tail-1] == '\r' )
00461         if ( data[--tail] != '=' ) len = tail;
00462 
00463     unsigned int outIdx = 0;
00464     out.resize( (count=len) );
00465     for (int idx = 0; idx < count; idx++)
00466     {
00467         // Adhere to RFC 2045 and ignore characters
00468         // that are not part of the encoding table.
00469         unsigned char ch = data[idx];
00470         if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
00471             (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
00472         {
00473             out[outIdx++] = Base64DecMap[ch];
00474         }
00475         else
00476         {
00477             len--;
00478             tail--;
00479         }
00480     }
00481 
00482     // kDebug() << "Tail size = " << tail << ", Length size = " << len;
00483 
00484     // 4-byte to 3-byte conversion
00485     len = (tail>(len/4)) ? tail-(len/4) : 0;
00486     int sidx = 0, didx = 0;
00487     if ( len > 1 )
00488     {
00489       while (didx < len-2)
00490       {
00491           out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
00492           out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
00493           out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077));
00494           sidx += 4;
00495           didx += 3;
00496       }
00497     }
00498 
00499     if (didx < len)
00500         out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
00501 
00502     if (++didx < len )
00503         out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
00504 
00505     // Resize the output buffer
00506     if ( len == 0 || len < out.size() )
00507       out.resize(len);
00508 }
00509 
00510 QByteArray QCodecs::uuencode( const QByteArray& in )
00511 {
00512     QByteArray out;
00513     uuencode( in, out );
00514     return QByteArray( out.data(), out.size()+1 );
00515 }
00516 
00517 void QCodecs::uuencode( const QByteArray& in, QByteArray& out )
00518 {
00519     out.resize( 0 );
00520     if( in.isEmpty() )
00521         return;
00522 
00523     unsigned int sidx = 0;
00524     int didx = 0;
00525     unsigned int line_len = 45;
00526 
00527     const char nl[] = "\n";
00528     const char* data = in.data();
00529     const unsigned int nl_len = strlen(nl);
00530     const unsigned int len = in.size();
00531 
00532     out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
00533     // split into lines, adding line-length and line terminator
00534     while (sidx+line_len < len)
00535     {
00536         // line length
00537         out[didx++] = UUEncMap[line_len];
00538 
00539         // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00540         for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
00541         {
00542             out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00543             out[didx++] = UUEncMap[((data[sidx+1] >> 4) & 017) |
00544                                    ((data[sidx] << 4) & 077)];
00545             out[didx++] = UUEncMap[((data[sidx+2] >> 6) & 003) |
00546                                    ((data[sidx+1] << 2) & 077)];
00547             out[didx++] = UUEncMap[data[sidx+2] & 077];
00548         }
00549 
00550         // line terminator
00551         //for (unsigned int idx=0; idx < nl_len; idx++)
00552         //out[didx++] = nl[idx];
00553         memcpy(out.data()+didx, nl, nl_len);
00554         didx += nl_len;
00555     }
00556 
00557     // line length
00558     out[didx++] = UUEncMap[len-sidx];
00559     // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
00560     while (sidx+2 < len)
00561     {
00562         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00563         out[didx++] = UUEncMap[((data[sidx+1] >> 4) & 017) |
00564                                ((data[sidx] << 4) & 077)];
00565         out[didx++] = UUEncMap[((data[sidx+2] >> 6) & 003) |
00566                                ((data[sidx+1] << 2) & 077)];
00567         out[didx++] = UUEncMap[data[sidx+2] & 077];
00568         sidx += 3;
00569     }
00570 
00571     if (sidx < len-1)
00572     {
00573         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00574         out[didx++] = UUEncMap[((data[sidx+1] >> 4) & 017) |
00575                                ((data[sidx] << 4) & 077)];
00576         out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077];
00577         out[didx++] = UUEncMap[0];
00578     }
00579     else if (sidx < len)
00580     {
00581         out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
00582         out[didx++] = UUEncMap[(data[sidx] << 4) & 077];
00583         out[didx++] = UUEncMap[0];
00584         out[didx++] = UUEncMap[0];
00585     }
00586 
00587     // line terminator
00588     memcpy(out.data()+didx, nl, nl_len);
00589     didx += nl_len;
00590 
00591     // sanity check
00592     if ( didx != out.size() )
00593         out.resize( 0 );
00594 }
00595 
00596 QByteArray QCodecs::uudecode( const QByteArray& in )
00597 {
00598     QByteArray out;
00599     uudecode( in, out );
00600     return out;
00601 }
00602 
00603 void QCodecs::uudecode( const QByteArray& in, QByteArray& out )
00604 {
00605     out.resize( 0 );
00606     if( in.isEmpty() )
00607         return;
00608 
00609     int sidx = 0;
00610     int didx = 0;
00611     int len = in.size();
00612     int line_len, end;
00613     const char* data = in.data();
00614 
00615     // Deal with *nix "BEGIN"/"END" separators!!
00616     int count = 0;
00617     while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
00618             data[count] == '\t' || data[count] == ' ') )
00619         count ++;
00620 
00621     bool hasLF = false;
00622     if ( strncasecmp( data+count, "begin", 5) == 0 )
00623     {
00624         count += 5;
00625         while ( count < len && data[count] != '\n' && data[count] != '\r' )
00626             count ++;
00627 
00628         while ( count < len && (data[count] == '\n' || data[count] == '\r') )
00629             count ++;
00630 
00631         data += count;
00632         len -= count;
00633         hasLF = true;
00634     }
00635 
00636     out.resize( len/4*3 );
00637     while ( sidx < len )
00638     {
00639         // get line length (in number of encoded octets)
00640         line_len = UUDecMap[ (unsigned char) data[sidx++]];
00641         // ascii printable to 0-63 and 4-byte to 3-byte conversion
00642         end = didx+line_len;
00643         char A, B, C, D;
00644         if (end > 2) {
00645           while (didx < end-2)
00646           {
00647              A = UUDecMap[(unsigned char) data[sidx]];
00648              B = UUDecMap[(unsigned char) data[sidx+1]];
00649              C = UUDecMap[(unsigned char) data[sidx+2]];
00650              D = UUDecMap[(unsigned char) data[sidx+3]];
00651              out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
00652              out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
00653              out[didx++] = ( ((C << 6) & 255) | (D & 077) );
00654              sidx += 4;
00655           }
00656         }
00657 
00658         if (didx < end)
00659         {
00660             A = UUDecMap[(unsigned char) data[sidx]];
00661             B = UUDecMap[(unsigned char) data[sidx+1]];
00662             out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
00663         }
00664 
00665         if (didx < end)
00666         {
00667             B = UUDecMap[(unsigned char) data[sidx+1]];
00668             C = UUDecMap[(unsigned char) data[sidx+2]];
00669             out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
00670         }
00671 
00672         // skip padding
00673         while (sidx < len  && data[sidx] != '\n' && data[sidx] != '\r')
00674             sidx++;
00675 
00676         // skip end of line
00677         while (sidx < len  && (data[sidx] == '\n' || data[sidx] == '\r'))
00678             sidx++;
00679 
00680         // skip the "END" separator when present.
00681         if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 )
00682             break;
00683     }
00684 
00685     if ( didx < out.size()  )
00686         out.resize( didx );
00687 }
00688 
00689 /******************************** QMD5 ********************************/
00690 QMD5::QMD5()
00691 {
00692     init();
00693 }
00694 
00695 QMD5::QMD5(const char *in, int len)
00696 {
00697     init();
00698     update(in, len);
00699 }
00700 
00701 QMD5::QMD5(const QByteArray& in)
00702 {
00703     init();
00704     update( in );
00705 }
00706 
00707 QMD5::~QMD5()
00708 {
00709 }
00710 
00711 void QMD5::update(const QByteArray& in)
00712 {
00713     update(in.data(), int(in.size()));
00714 }
00715 
00716 void QMD5::update(const char* in, int len)
00717 {
00718     update(reinterpret_cast<const unsigned char*>(in), len);
00719 }
00720 
00721 void QMD5::update(const unsigned char* in, int len)
00722 {
00723     if (len < 0)
00724         len = qstrlen(reinterpret_cast<const char*>(in));
00725 
00726     if (!len)
00727         return;
00728 
00729     if (m_finalized) {
00730         qDebug() << "QMD5::update called after state was finalized!";
00731         return;
00732     }
00733 
00734     quint32 in_index;
00735     quint32 buffer_index;
00736     quint32 buffer_space;
00737     quint32 in_length = static_cast<quint32>( len );
00738 
00739     buffer_index = static_cast<quint32>((m_count[0] >> 3) & 0x3F);
00740 
00741     if (  (m_count[0] += (in_length << 3))<(in_length << 3) )
00742         m_count[1]++;
00743 
00744     m_count[1] += (in_length >> 29);
00745     buffer_space = 64 - buffer_index;
00746 
00747     if (in_length >= buffer_space)
00748     {
00749         memcpy (m_buffer + buffer_index, in, buffer_space);
00750         transform (m_buffer);
00751 
00752         for (in_index = buffer_space; in_index + 63 < in_length;
00753              in_index += 64)
00754             transform (reinterpret_cast<const unsigned char*>(in+in_index));
00755 
00756         buffer_index = 0;
00757     }
00758     else
00759         in_index=0;
00760 
00761     memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
00762 }
00763 
00764 bool QMD5::update(QIODevice& file)
00765 {
00766     char buffer[1024];
00767     int len;
00768 
00769     while ((len=file.read(buffer, sizeof(buffer))) > 0)
00770         update(buffer, len);
00771 
00772     return file.atEnd();
00773 }
00774 
00775 void QMD5::finalize ()
00776 {
00777     if (m_finalized) return;
00778 
00779     quint8 bits[8];
00780     quint32 index, padLen;
00781     static const unsigned char PADDING[64]=
00782     {
00783         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00784         0, 0, 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
00787     };
00788 
00789     encode (bits, m_count, 8);
00790     //memcpy( bits, m_count, 8 );
00791 
00792     // Pad out to 56 mod 64.
00793     index = static_cast<quint32>((m_count[0] >> 3) & 0x3f);
00794     padLen = (index < 56) ? (56 - index) : (120 - index);
00795     update (reinterpret_cast<const char*>(PADDING), padLen);
00796 
00797     // Append length (before padding)
00798     update (reinterpret_cast<const char*>(bits), 8);
00799 
00800     // Store state in digest
00801     encode (m_digest, m_state, 16);
00802     //memcpy( m_digest, m_state, 16 );
00803 
00804     // Fill sensitive information with zero's
00805     memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
00806 
00807     m_finalized = true;
00808 }
00809 
00810 
00811 bool QMD5::verify( const QMD5::Digest& digest)
00812 {
00813     finalize();
00814     return (0 == memcmp(rawDigest(), digest, sizeof(QMD5::Digest)));
00815 }
00816 
00817 bool QMD5::verify( const QByteArray& hexdigest)
00818 {
00819     finalize();
00820     return (0 == strcmp(hexDigest().data(), hexdigest));
00821 }
00822 
00823 const QMD5::Digest& QMD5::rawDigest()
00824 {
00825     finalize();
00826     return m_digest;
00827 }
00828 
00829 void QMD5::rawDigest( QMD5::Digest& bin )
00830 {
00831     finalize();
00832     memcpy( bin, m_digest, 16 );
00833 }
00834 
00835 
00836 QByteArray QMD5::hexDigest()
00837 {
00838     QByteArray s(32, 0);
00839 
00840     finalize();
00841     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00842             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
00843             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
00844             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
00845 
00846     return s;
00847 }
00848 
00849 void QMD5::hexDigest(QByteArray& s)
00850 {
00851     finalize();
00852     s.resize(32);
00853     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00854             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
00855             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
00856             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
00857 }
00858 
00859 QByteArray QMD5::base64Digest()
00860 {
00861     finalize();
00862     return QByteArray::fromRawData(reinterpret_cast<const char*>(m_digest),16).toBase64();
00863 }
00864 
00865 void QMD5::init()
00866 {
00867     d = 0;
00868     reset();
00869 }
00870 
00871 void QMD5::reset()
00872 {
00873     m_finalized = false;
00874 
00875     m_count[0] = 0;
00876     m_count[1] = 0;
00877 
00878     m_state[0] = 0x67452301;
00879     m_state[1] = 0xefcdab89;
00880     m_state[2] = 0x98badcfe;
00881     m_state[3] = 0x10325476;
00882 
00883     memset ( m_buffer, 0, sizeof(*m_buffer));
00884     memset ( m_digest, 0, sizeof(*m_digest));
00885 }
00886 
00887 void QMD5::transform( const unsigned char block[64] )
00888 {
00889 
00890     quint32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
00891 
00892     decode (x, block, 64);
00893     //memcpy( x, block, 64 );
00894 
00895     Q_ASSERT(!m_finalized);  // not just a user error, since the method is private
00896 
00897     /* Round 1 */
00898     FF (a, b, c, d, x[ 0], QMD5_S11, 0xd76aa478); /* 1 */
00899     FF (d, a, b, c, x[ 1], QMD5_S12, 0xe8c7b756); /* 2 */
00900     FF (c, d, a, b, x[ 2], QMD5_S13, 0x242070db); /* 3 */
00901     FF (b, c, d, a, x[ 3], QMD5_S14, 0xc1bdceee); /* 4 */
00902     FF (a, b, c, d, x[ 4], QMD5_S11, 0xf57c0faf); /* 5 */
00903     FF (d, a, b, c, x[ 5], QMD5_S12, 0x4787c62a); /* 6 */
00904     FF (c, d, a, b, x[ 6], QMD5_S13, 0xa8304613); /* 7 */
00905     FF (b, c, d, a, x[ 7], QMD5_S14, 0xfd469501); /* 8 */
00906     FF (a, b, c, d, x[ 8], QMD5_S11, 0x698098d8); /* 9 */
00907     FF (d, a, b, c, x[ 9], QMD5_S12, 0x8b44f7af); /* 10 */
00908     FF (c, d, a, b, x[10], QMD5_S13, 0xffff5bb1); /* 11 */
00909     FF (b, c, d, a, x[11], QMD5_S14, 0x895cd7be); /* 12 */
00910     FF (a, b, c, d, x[12], QMD5_S11, 0x6b901122); /* 13 */
00911     FF (d, a, b, c, x[13], QMD5_S12, 0xfd987193); /* 14 */
00912     FF (c, d, a, b, x[14], QMD5_S13, 0xa679438e); /* 15 */
00913     FF (b, c, d, a, x[15], QMD5_S14, 0x49b40821); /* 16 */
00914 
00915     /* Round 2 */
00916     GG (a, b, c, d, x[ 1], QMD5_S21, 0xf61e2562); /* 17 */
00917     GG (d, a, b, c, x[ 6], QMD5_S22, 0xc040b340); /* 18 */
00918     GG (c, d, a, b, x[11], QMD5_S23, 0x265e5a51); /* 19 */
00919     GG (b, c, d, a, x[ 0], QMD5_S24, 0xe9b6c7aa); /* 20 */
00920     GG (a, b, c, d, x[ 5], QMD5_S21, 0xd62f105d); /* 21 */
00921     GG (d, a, b, c, x[10], QMD5_S22,  0x2441453); /* 22 */
00922     GG (c, d, a, b, x[15], QMD5_S23, 0xd8a1e681); /* 23 */
00923     GG (b, c, d, a, x[ 4], QMD5_S24, 0xe7d3fbc8); /* 24 */
00924     GG (a, b, c, d, x[ 9], QMD5_S21, 0x21e1cde6); /* 25 */
00925     GG (d, a, b, c, x[14], QMD5_S22, 0xc33707d6); /* 26 */
00926     GG (c, d, a, b, x[ 3], QMD5_S23, 0xf4d50d87); /* 27 */
00927     GG (b, c, d, a, x[ 8], QMD5_S24, 0x455a14ed); /* 28 */
00928     GG (a, b, c, d, x[13], QMD5_S21, 0xa9e3e905); /* 29 */
00929     GG (d, a, b, c, x[ 2], QMD5_S22, 0xfcefa3f8); /* 30 */
00930     GG (c, d, a, b, x[ 7], QMD5_S23, 0x676f02d9); /* 31 */
00931     GG (b, c, d, a, x[12], QMD5_S24, 0x8d2a4c8a); /* 32 */
00932 
00933     /* Round 3 */
00934     HH (a, b, c, d, x[ 5], QMD5_S31, 0xfffa3942); /* 33 */
00935     HH (d, a, b, c, x[ 8], QMD5_S32, 0x8771f681); /* 34 */
00936     HH (c, d, a, b, x[11], QMD5_S33, 0x6d9d6122); /* 35 */
00937     HH (b, c, d, a, x[14], QMD5_S34, 0xfde5380c); /* 36 */
00938     HH (a, b, c, d, x[ 1], QMD5_S31, 0xa4beea44); /* 37 */
00939     HH (d, a, b, c, x[ 4], QMD5_S32, 0x4bdecfa9); /* 38 */
00940     HH (c, d, a, b, x[ 7], QMD5_S33, 0xf6bb4b60); /* 39 */
00941     HH (b, c, d, a, x[10], QMD5_S34, 0xbebfbc70); /* 40 */
00942     HH (a, b, c, d, x[13], QMD5_S31, 0x289b7ec6); /* 41 */
00943     HH (d, a, b, c, x[ 0], QMD5_S32, 0xeaa127fa); /* 42 */
00944     HH (c, d, a, b, x[ 3], QMD5_S33, 0xd4ef3085); /* 43 */
00945     HH (b, c, d, a, x[ 6], QMD5_S34,  0x4881d05); /* 44 */
00946     HH (a, b, c, d, x[ 9], QMD5_S31, 0xd9d4d039); /* 45 */
00947     HH (d, a, b, c, x[12], QMD5_S32, 0xe6db99e5); /* 46 */
00948     HH (c, d, a, b, x[15], QMD5_S33, 0x1fa27cf8); /* 47 */
00949     HH (b, c, d, a, x[ 2], QMD5_S34, 0xc4ac5665); /* 48 */
00950 
00951     /* Round 4 */
00952     II (a, b, c, d, x[ 0], QMD5_S41, 0xf4292244); /* 49 */
00953     II (d, a, b, c, x[ 7], QMD5_S42, 0x432aff97); /* 50 */
00954     II (c, d, a, b, x[14], QMD5_S43, 0xab9423a7); /* 51 */
00955     II (b, c, d, a, x[ 5], QMD5_S44, 0xfc93a039); /* 52 */
00956     II (a, b, c, d, x[12], QMD5_S41, 0x655b59c3); /* 53 */
00957     II (d, a, b, c, x[ 3], QMD5_S42, 0x8f0ccc92); /* 54 */
00958     II (c, d, a, b, x[10], QMD5_S43, 0xffeff47d); /* 55 */
00959     II (b, c, d, a, x[ 1], QMD5_S44, 0x85845dd1); /* 56 */
00960     II (a, b, c, d, x[ 8], QMD5_S41, 0x6fa87e4f); /* 57 */
00961     II (d, a, b, c, x[15], QMD5_S42, 0xfe2ce6e0); /* 58 */
00962     II (c, d, a, b, x[ 6], QMD5_S43, 0xa3014314); /* 59 */
00963     II (b, c, d, a, x[13], QMD5_S44, 0x4e0811a1); /* 60 */
00964     II (a, b, c, d, x[ 4], QMD5_S41, 0xf7537e82); /* 61 */
00965     II (d, a, b, c, x[11], QMD5_S42, 0xbd3af235); /* 62 */
00966     II (c, d, a, b, x[ 2], QMD5_S43, 0x2ad7d2bb); /* 63 */
00967     II (b, c, d, a, x[ 9], QMD5_S44, 0xeb86d391); /* 64 */
00968 
00969     m_state[0] += a;
00970     m_state[1] += b;
00971     m_state[2] += c;
00972     m_state[3] += d;
00973 
00974     memset ( static_cast<void *>(x), 0, sizeof(x) );
00975 }
00976 
00977 inline quint32 QMD5::rotate_left (quint32 x, quint32 n)
00978 {
00979     return (x << n) | (x >> (32-n))  ;
00980 }
00981 
00982 inline quint32 QMD5::F (quint32 x, quint32 y, quint32 z)
00983 {
00984     return (x & y) | (~x & z);
00985 }
00986 
00987 inline quint32 QMD5::G (quint32 x, quint32 y, quint32 z)
00988 {
00989     return (x & z) | (y & ~z);
00990 }
00991 
00992 inline quint32 QMD5::H (quint32 x, quint32 y, quint32 z)
00993 {
00994     return x ^ y ^ z;
00995 }
00996 
00997 inline quint32 QMD5::I (quint32 x, quint32 y, quint32 z)
00998 {
00999     return y ^ (x | ~z);
01000 }
01001 
01002 void QMD5::FF ( quint32& a, quint32 b, quint32 c, quint32 d,
01003                        quint32 x, quint32  s, quint32 ac )
01004 {
01005     a += F(b, c, d) + x + ac;
01006     a = rotate_left (a, s) +b;
01007 }
01008 
01009 void QMD5::GG ( quint32& a, quint32 b, quint32 c, quint32 d,
01010                  quint32 x, quint32 s, quint32 ac)
01011 {
01012     a += G(b, c, d) + x + ac;
01013     a = rotate_left (a, s) +b;
01014 }
01015 
01016 void QMD5::HH ( quint32& a, quint32 b, quint32 c, quint32 d,
01017                  quint32 x, quint32 s, quint32 ac )
01018 {
01019     a += H(b, c, d) + x + ac;
01020     a = rotate_left (a, s) +b;
01021 }
01022 
01023 void QMD5::II ( quint32& a, quint32 b, quint32 c, quint32 d,
01024                  quint32 x, quint32 s, quint32 ac )
01025 {
01026     a += I(b, c, d) + x + ac;
01027     a = rotate_left (a, s) +b;
01028 }
01029 
01030 
01031 void QMD5::encode ( unsigned char* output, quint32 *in, quint32 len )
01032 {
01033 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
01034     memcpy(output, in, len);
01035 #else
01036     quint32 i, j;
01037     for (i = 0, j = 0; j < len; i++, j += 4)
01038     {
01039         output[j]   = static_cast<quint8>((in[i] & 0xff));
01040         output[j+1] = static_cast<quint8>(((in[i] >> 8) & 0xff));
01041         output[j+2] = static_cast<quint8>(((in[i] >> 16) & 0xff));
01042         output[j+3] = static_cast<quint8>(((in[i] >> 24) & 0xff));
01043     }
01044 #endif
01045 }
01046 
01047 // Decodes in (quint8) into output (quint32). Assumes len is a
01048 // multiple of 4.
01049 void QMD5::decode (quint32 *output, const unsigned char* in, quint32 len)
01050 {
01051 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
01052     memcpy(output, in, len);
01053 
01054 #else
01055     quint32 i, j;
01056     for (i = 0, j = 0; j < len; i++, j += 4)
01057         output[i] = static_cast<quint32>(in[j]) |
01058                     (static_cast<quint32>(in[j+1]) << 8)  |
01059                     (static_cast<quint32>(in[j+2]) << 16) |
01060                     (static_cast<quint32>(in[j+3]) << 24);
01061 #endif
01062 }
01063 
01064 
01065 
01066 /**************************************************************/
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends