summaryrefslogtreecommitdiffstats
path: root/kdecore/kmdcodec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/kmdcodec.cpp')
-rw-r--r--kdecore/kmdcodec.cpp1510
1 files changed, 1510 insertions, 0 deletions
diff --git a/kdecore/kmdcodec.cpp b/kdecore/kmdcodec.cpp
new file mode 100644
index 000000000..10fca9307
--- /dev/null
+++ b/kdecore/kmdcodec.cpp
@@ -0,0 +1,1510 @@
+/*
+ Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
+ Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License (LGPL)
+ version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
+ RSA Data Security, Inc. Created 1991. All rights reserved.
+
+ The KMD5 class is based on a C++ implementation of
+ "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
+ Mordechai T. Abzug, Copyright (c) 1995. This implementation
+ passes the test-suite as defined in RFC 1321.
+
+ The encoding and decoding utilities in KCodecs with the exception of
+ quoted-printable are based on the java implementation in HTTPClient
+ package by Ronald Tschalär Copyright (C) 1996-1999.
+
+ The quoted-printable codec as described in RFC 2045, section 6.7. is by
+ Rik Hemsley (C) 2001.
+
+ KMD4 class based on the LGPL code of Copyright (C) 2001 Nikos Mavroyanopoulos
+ The algorithm is due to Ron Rivest. This code is based on code
+ written by Colin Plumb in 1993.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <kdebug.h>
+#include "kmdcodec.h"
+
+#define KMD5_S11 7
+#define KMD5_S12 12
+#define KMD5_S13 17
+#define KMD5_S14 22
+#define KMD5_S21 5
+#define KMD5_S22 9
+#define KMD5_S23 14
+#define KMD5_S24 20
+#define KMD5_S31 4
+#define KMD5_S32 11
+#define KMD5_S33 16
+#define KMD5_S34 23
+#define KMD5_S41 6
+#define KMD5_S42 10
+#define KMD5_S43 15
+#define KMD5_S44 21
+
+const char KCodecs::Base64EncMap[64] =
+{
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
+};
+
+const char KCodecs::Base64DecMap[128] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+ 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const char KCodecs::UUEncMap[64] =
+{
+ 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
+};
+
+const char KCodecs::UUDecMap[128] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const char KCodecs::hexChars[16] =
+{
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+const unsigned int KCodecs::maxQPLineLength = 70;
+
+
+/******************************** KCodecs ********************************/
+// strchr(3) for broken systems.
+static int rikFindChar(register const char * _s, const char c)
+{
+ register const char * s = _s;
+
+ while (true)
+ {
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ }
+
+ return s - _s;
+}
+
+QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF)
+{
+ QByteArray out;
+ quotedPrintableEncode (in, out, useCRLF);
+ return QCString (out.data(), out.size()+1);
+}
+
+QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF)
+{
+ if (str.isEmpty())
+ return "";
+
+ QByteArray in (str.length());
+ memcpy (in.data(), str.data(), str.length());
+ return quotedPrintableEncode(in, useCRLF);
+}
+
+void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF)
+{
+ out.resize (0);
+ if (in.isEmpty())
+ return;
+
+ char *cursor;
+ const char *data;
+ unsigned int lineLength;
+ unsigned int pos;
+
+ const unsigned int length = in.size();
+ const unsigned int end = length - 1;
+
+
+ // Reasonable guess for output size when we're encoding
+ // mostly-ASCII data. It doesn't really matter, because
+ // the underlying allocation routines are quite efficient,
+ // but it's nice to have 0 allocations in many cases.
+ out.resize ((length*12)/10);
+ cursor = out.data();
+ data = in.data();
+ lineLength = 0;
+ pos = 0;
+
+ for (unsigned int i = 0; i < length; i++)
+ {
+ unsigned char c (data[i]);
+
+ // check if we have to enlarge the output buffer, use
+ // a safety margin of 16 byte
+ pos = cursor-out.data();
+ if (out.size()-pos < 16) {
+ out.resize(out.size()+4096);
+ cursor = out.data()+pos;
+ }
+
+ // Plain ASCII chars just go straight out.
+
+ if ((c >= 33) && (c <= 126) && ('=' != c))
+ {
+ *cursor++ = c;
+ ++lineLength;
+ }
+
+ // Spaces need some thought. We have to encode them at eol (or eof).
+
+ else if (' ' == c)
+ {
+ if
+ (
+ (i >= length)
+ ||
+ ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2]))
+ ||
+ (!useCRLF && ('\n' == data[i + 1]))))
+ )
+ {
+ *cursor++ = '=';
+ *cursor++ = '2';
+ *cursor++ = '0';
+
+ lineLength += 3;
+ }
+ else
+ {
+ *cursor++ = ' ';
+ ++lineLength;
+ }
+ }
+ // If we find a line break, just let it through.
+ else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) ||
+ (!useCRLF && ('\n' == c)))
+ {
+ lineLength = 0;
+
+ if (useCRLF) {
+ *cursor++ = '\r';
+ *cursor++ = '\n';
+ ++i;
+ } else {
+ *cursor++ = '\n';
+ }
+ }
+
+ // Anything else is converted to =XX.
+
+ else
+ {
+ *cursor++ = '=';
+ *cursor++ = hexChars[c / 16];
+ *cursor++ = hexChars[c % 16];
+
+ lineLength += 3;
+ }
+
+ // If we're approaching the maximum line length, do a soft line break.
+
+ if ((lineLength > maxQPLineLength) && (i < end))
+ {
+ if (useCRLF) {
+ *cursor++ = '=';
+ *cursor++ = '\r';
+ *cursor++ = '\n';
+ } else {
+ *cursor++ = '=';
+ *cursor++ = '\n';
+ }
+
+ lineLength = 0;
+ }
+ }
+
+ out.truncate(cursor - out.data());
+}
+
+QCString KCodecs::quotedPrintableDecode(const QByteArray & in)
+{
+ QByteArray out;
+ quotedPrintableDecode (in, out);
+ return QCString (out.data(), out.size()+1);
+}
+
+QCString KCodecs::quotedPrintableDecode(const QCString & str)
+{
+ if (str.isEmpty())
+ return "";
+
+ QByteArray in (str.length());
+ memcpy (in.data(), str.data(), str.length());
+ return quotedPrintableDecode (in);
+}
+
+void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out)
+{
+ // clear out the output buffer
+ out.resize (0);
+ if (in.isEmpty())
+ return;
+
+ char *cursor;
+ const char *data;
+ const unsigned int length = in.size();
+
+ data = in.data();
+ out.resize (length);
+ cursor = out.data();
+
+ for (unsigned int i = 0; i < length; i++)
+ {
+ char c(in[i]);
+
+ if ('=' == c)
+ {
+ if (i < length - 2)
+ {
+ char c1 = in[i + 1];
+ char c2 = in[i + 2];
+
+ if (('\n' == c1) || ('\r' == c1 && '\n' == c2))
+ {
+ // Soft line break. No output.
+ if ('\r' == c1)
+ i += 2; // CRLF line breaks
+ else
+ i += 1;
+ }
+ else
+ {
+ // =XX encoded byte.
+
+ int hexChar0 = rikFindChar(hexChars, c1);
+ int hexChar1 = rikFindChar(hexChars, c2);
+
+ if (hexChar0 < 16 && hexChar1 < 16)
+ {
+ *cursor++ = char((hexChar0 * 16) | hexChar1);
+ i += 2;
+ }
+ }
+ }
+ }
+ else
+ {
+ *cursor++ = c;
+ }
+ }
+
+ out.truncate(cursor - out.data());
+}
+
+QCString KCodecs::base64Encode( const QCString& str, bool insertLFs )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in (str.length());
+ memcpy( in.data(), str.data(), str.length() );
+ return base64Encode( in, insertLFs );
+}
+
+QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs )
+{
+ QByteArray out;
+ base64Encode( in, out, insertLFs );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::base64Encode( const QByteArray& in, QByteArray& out,
+ bool insertLFs )
+{
+ // clear out the output buffer
+ out.resize (0);
+ if ( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ const char* data = in.data();
+ const unsigned int len = in.size();
+
+ unsigned int out_len = ((len+2)/3)*4;
+
+ // Deal with the 76 characters or less per
+ // line limit specified in RFC 2045 on a
+ // pre request basis.
+ insertLFs = (insertLFs && out_len > 76);
+ if ( insertLFs )
+ out_len += ((out_len-1)/76);
+
+ int count = 0;
+ out.resize( out_len );
+
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ if ( len > 1 )
+ {
+ while (sidx < len-2)
+ {
+ if ( insertLFs )
+ {
+ if ( count && (count%76) == 0 )
+ out[didx++] = '\n';
+ count += 4;
+ }
+ out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
+ out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out[didx++] = Base64EncMap[data[sidx+2] & 077];
+ sidx += 3;
+ }
+ }
+
+ if (sidx < len)
+ {
+ if ( insertLFs && (count > 0) && (count%76) == 0 )
+ out[didx++] = '\n';
+
+ out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
+ if (sidx < len-1)
+ {
+ out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077];
+ }
+ else
+ {
+ out[didx++] = Base64EncMap[(data[sidx] << 4) & 077];
+ }
+ }
+
+ // Add padding
+ while (didx < out.size())
+ {
+ out[didx] = '=';
+ didx++;
+ }
+}
+
+QCString KCodecs::base64Decode( const QCString& str )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in( str.length() );
+ memcpy( in.data(), str.data(), str.length() );
+ return base64Decode( in );
+}
+
+QCString KCodecs::base64Decode( const QByteArray& in )
+{
+ QByteArray out;
+ base64Decode( in, out );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::base64Decode( const QByteArray& in, QByteArray& out )
+{
+ out.resize(0);
+ if ( in.isEmpty() )
+ return;
+
+ unsigned int count = 0;
+ unsigned int len = in.size(), tail = len;
+ const char* data = in.data();
+
+ // Deal with possible *nix "BEGIN" marker!!
+ while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
+ data[count] == '\t' || data[count] == ' ') )
+ count++;
+
+ if ( count == len )
+ return;
+
+ if ( strncasecmp(data+count, "begin", 5) == 0 )
+ {
+ count += 5;
+ while ( count < len && data[count] != '\n' && data[count] != '\r' )
+ count++;
+
+ while ( count < len && (data[count] == '\n' || data[count] == '\r') )
+ count ++;
+
+ data += count;
+ tail = (len -= count);
+ }
+
+ // Find the tail end of the actual encoded data even if
+ // there is/are trailing CR and/or LF.
+ while ( tail > 0
+ && ( data[tail-1] == '=' || data[tail-1] == '\n' || data[tail-1] == '\r' ) )
+ if ( data[--tail] != '=' ) len = tail;
+
+ unsigned int outIdx = 0;
+ out.resize( (count=len) );
+ for (unsigned int idx = 0; idx < count; idx++)
+ {
+ // Adhere to RFC 2045 and ignore characters
+ // that are not part of the encoding table.
+ unsigned char ch = data[idx];
+ if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
+ (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
+ {
+ out[outIdx++] = Base64DecMap[ch];
+ }
+ else
+ {
+ len--;
+ tail--;
+ }
+ }
+
+ // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl;
+
+ // 4-byte to 3-byte conversion
+ len = (tail>(len/4)) ? tail-(len/4) : 0;
+ unsigned int sidx = 0, didx = 0;
+ if ( len > 1 )
+ {
+ while (didx < len-2)
+ {
+ out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
+ out[didx+1] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
+ out[didx+2] = (((out[sidx+2] << 6) & 255) | (out[sidx+3] & 077));
+ sidx += 4;
+ didx += 3;
+ }
+ }
+
+ if (didx < len)
+ out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx+1] >> 4) & 003));
+
+ if (++didx < len )
+ out[didx] = (((out[sidx+1] << 4) & 255) | ((out[sidx+2] >> 2) & 017));
+
+ // Resize the output buffer
+ if ( len == 0 || len < out.size() )
+ out.resize(len);
+}
+
+QCString KCodecs::uuencode( const QCString& str )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in;
+ in.resize( str.length() );
+ memcpy( in.data(), str.data(), str.length() );
+ return uuencode( in );
+}
+
+QCString KCodecs::uuencode( const QByteArray& in )
+{
+ QByteArray out;
+ uuencode( in, out );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::uuencode( const QByteArray& in, QByteArray& out )
+{
+ out.resize( 0 );
+ if( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ unsigned int line_len = 45;
+
+ const char nl[] = "\n";
+ const char* data = in.data();
+ const unsigned int nl_len = strlen(nl);
+ const unsigned int len = in.size();
+
+ out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
+ // split into lines, adding line-length and line terminator
+ while (sidx+line_len < len)
+ {
+ // line length
+ out[didx++] = UUEncMap[line_len];
+
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
+ {
+ out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
+ out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out[didx++] = UUEncMap[data[sidx+2] & 077];
+ }
+
+ // line terminator
+ //for (unsigned int idx=0; idx < nl_len; idx++)
+ //out[didx++] = nl[idx];
+ memcpy(out.data()+didx, nl, nl_len);
+ didx += nl_len;
+ }
+
+ // line length
+ out[didx++] = UUEncMap[len-sidx];
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ while (sidx+2 < len)
+ {
+ out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
+ out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out[didx++] = UUEncMap[data[sidx+2] & 077];
+ sidx += 3;
+ }
+
+ if (sidx < len-1)
+ {
+ out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
+ out[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = UUEncMap[(data[sidx+1] << 2) & 077];
+ out[didx++] = UUEncMap[0];
+ }
+ else if (sidx < len)
+ {
+ out[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
+ out[didx++] = UUEncMap[(data[sidx] << 4) & 077];
+ out[didx++] = UUEncMap[0];
+ out[didx++] = UUEncMap[0];
+ }
+
+ // line terminator
+ memcpy(out.data()+didx, nl, nl_len);
+ didx += nl_len;
+
+ // sanity check
+ if ( didx != out.size() )
+ out.resize( 0 );
+}
+
+QCString KCodecs::uudecode( const QCString& str )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in;
+ in.resize( str.length() );
+ memcpy( in.data(), str.data(), str.length() );
+ return uudecode( in );
+}
+
+QCString KCodecs::uudecode( const QByteArray& in )
+{
+ QByteArray out;
+ uudecode( in, out );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::uudecode( const QByteArray& in, QByteArray& out )
+{
+ out.resize( 0 );
+ if( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ unsigned int len = in.size();
+ unsigned int line_len, end;
+ const char* data = in.data();
+
+ // Deal with *nix "BEGIN"/"END" separators!!
+ unsigned int count = 0;
+ while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
+ data[count] == '\t' || data[count] == ' ') )
+ count ++;
+
+ bool hasLF = false;
+ if ( strncasecmp( data+count, "begin", 5) == 0 )
+ {
+ count += 5;
+ while ( count < len && data[count] != '\n' && data[count] != '\r' )
+ count ++;
+
+ while ( count < len && (data[count] == '\n' || data[count] == '\r') )
+ count ++;
+
+ data += count;
+ len -= count;
+ hasLF = true;
+ }
+
+ out.resize( len/4*3 );
+ while ( sidx < len )
+ {
+ // get line length (in number of encoded octets)
+ line_len = UUDecMap[ (unsigned char) data[sidx++]];
+ // ascii printable to 0-63 and 4-byte to 3-byte conversion
+ end = didx+line_len;
+ char A, B, C, D;
+ if (end > 2) {
+ while (didx < end-2)
+ {
+ A = UUDecMap[(unsigned char) data[sidx]];
+ B = UUDecMap[(unsigned char) data[sidx+1]];
+ C = UUDecMap[(unsigned char) data[sidx+2]];
+ D = UUDecMap[(unsigned char) data[sidx+3]];
+ out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
+ out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
+ out[didx++] = ( ((C << 6) & 255) | (D & 077) );
+ sidx += 4;
+ }
+ }
+
+ if (didx < end)
+ {
+ A = UUDecMap[(unsigned char) data[sidx]];
+ B = UUDecMap[(unsigned char) data[sidx+1]];
+ out[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
+ }
+
+ if (didx < end)
+ {
+ B = UUDecMap[(unsigned char) data[sidx+1]];
+ C = UUDecMap[(unsigned char) data[sidx+2]];
+ out[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
+ }
+
+ // skip padding
+ while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r')
+ sidx++;
+
+ // skip end of line
+ while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r'))
+ sidx++;
+
+ // skip the "END" separator when present.
+ if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 )
+ break;
+ }
+
+ if ( didx < out.size() )
+ out.resize( didx );
+}
+
+/******************************** KMD5 ********************************/
+KMD5::KMD5()
+{
+ init();
+}
+
+KMD5::KMD5(const char *in, int len)
+{
+ init();
+ update(in, len);
+}
+
+KMD5::KMD5(const QByteArray& in)
+{
+ init();
+ update( in );
+}
+
+KMD5::KMD5(const QCString& in)
+{
+ init();
+ update( in );
+}
+
+void KMD5::update(const QByteArray& in)
+{
+ update(in.data(), int(in.size()));
+}
+
+void KMD5::update(const QCString& in)
+{
+ update(in.data(), int(in.length()));
+}
+
+void KMD5::update(const unsigned char* in, int len)
+{
+ if (len < 0)
+ len = qstrlen(reinterpret_cast<const char*>(in));
+
+ if (!len)
+ return;
+
+ if (m_finalized) {
+ kdWarning() << "KMD5::update called after state was finalized!" << endl;
+ return;
+ }
+
+ Q_UINT32 in_index;
+ Q_UINT32 buffer_index;
+ Q_UINT32 buffer_space;
+ Q_UINT32 in_length = static_cast<Q_UINT32>( len );
+
+ buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F);
+
+ if ( (m_count[0] += (in_length << 3))<(in_length << 3) )
+ m_count[1]++;
+
+ m_count[1] += (in_length >> 29);
+ buffer_space = 64 - buffer_index;
+
+ if (in_length >= buffer_space)
+ {
+ memcpy (m_buffer + buffer_index, in, buffer_space);
+ transform (m_buffer);
+
+ for (in_index = buffer_space; in_index + 63 < in_length;
+ in_index += 64)
+ transform (reinterpret_cast<const unsigned char*>(in+in_index));
+
+ buffer_index = 0;
+ }
+ else
+ in_index=0;
+
+ memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
+}
+
+bool KMD5::update(QIODevice& file)
+{
+ char buffer[1024];
+ int len;
+
+ while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
+ update(buffer, len);
+
+ return file.atEnd();
+}
+
+void KMD5::finalize ()
+{
+ if (m_finalized) return;
+
+ Q_UINT8 bits[8];
+ Q_UINT32 index, padLen;
+ static const unsigned char PADDING[64]=
+ {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ encode (bits, m_count, 8);
+ //memcpy( bits, m_count, 8 );
+
+ // Pad out to 56 mod 64.
+ index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ update (reinterpret_cast<const char*>(PADDING), padLen);
+
+ // Append length (before padding)
+ update (reinterpret_cast<const char*>(bits), 8);
+
+ // Store state in digest
+ encode (m_digest, m_state, 16);
+ //memcpy( m_digest, m_state, 16 );
+
+ // Fill sensitive information with zero's
+ memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
+
+ m_finalized = true;
+}
+
+
+bool KMD5::verify( const KMD5::Digest& digest)
+{
+ finalize();
+ return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
+}
+
+bool KMD5::verify( const QCString& hexdigest)
+{
+ finalize();
+ return (0 == strcmp(hexDigest().data(), hexdigest));
+}
+
+const KMD5::Digest& KMD5::rawDigest()
+{
+ finalize();
+ return m_digest;
+}
+
+void KMD5::rawDigest( KMD5::Digest& bin )
+{
+ finalize();
+ memcpy( bin, m_digest, 16 );
+}
+
+
+QCString KMD5::hexDigest()
+{
+ QCString s(33);
+
+ finalize();
+ sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
+ m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
+ m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
+
+ return s;
+}
+
+void KMD5::hexDigest(QCString& s)
+{
+ finalize();
+ s.resize(33);
+ sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
+ m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
+ m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
+}
+
+QCString KMD5::base64Digest()
+{
+ QByteArray ba(16);
+
+ finalize();
+ memcpy(ba.data(), m_digest, 16);
+ return KCodecs::base64Encode(ba);
+}
+
+
+void KMD5::init()
+{
+ d = 0;
+ reset();
+}
+
+void KMD5::reset()
+{
+ m_finalized = false;
+
+ m_count[0] = 0;
+ m_count[1] = 0;
+
+ m_state[0] = 0x67452301;
+ m_state[1] = 0xefcdab89;
+ m_state[2] = 0x98badcfe;
+ m_state[3] = 0x10325476;
+
+ memset ( m_buffer, 0, sizeof(*m_buffer));
+ memset ( m_digest, 0, sizeof(*m_digest));
+}
+
+void KMD5::transform( const unsigned char block[64] )
+{
+
+ Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
+
+ decode (x, block, 64);
+ //memcpy( x, block, 64 );
+
+ Q_ASSERT(!m_finalized); // not just a user error, since the method is private
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */
+
+ m_state[0] += a;
+ m_state[1] += b;
+ m_state[2] += c;
+ m_state[3] += d;
+
+ memset ( static_cast<void *>(x), 0, sizeof(x) );
+}
+
+inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
+{
+ return (x << n) | (x >> (32-n)) ;
+}
+
+inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return (x & y) | (~x & z);
+}
+
+inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return (x & z) | (y & ~z);
+}
+
+inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return x ^ y ^ z;
+}
+
+inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return y ^ (x | ~z);
+}
+
+void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
+{
+ a += F(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac)
+{
+ a += G(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
+{
+ a += H(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
+{
+ a += I(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+
+void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len )
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(output, in, len);
+
+#else
+ Q_UINT32 i, j;
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ {
+ output[j] = static_cast<Q_UINT8>((in[i] & 0xff));
+ output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff));
+ output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff));
+ output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff));
+ }
+#endif
+}
+
+// Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a
+// multiple of 4.
+void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(output, in, len);
+
+#else
+ Q_UINT32 i, j;
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = static_cast<Q_UINT32>(in[j]) |
+ (static_cast<Q_UINT32>(in[j+1]) << 8) |
+ (static_cast<Q_UINT32>(in[j+2]) << 16) |
+ (static_cast<Q_UINT32>(in[j+3]) << 24);
+#endif
+}
+
+
+
+/**************************************************************/
+
+
+
+/***********************************************************/
+
+KMD4::KMD4()
+{
+ init();
+}
+
+KMD4::KMD4(const char *in, int len)
+{
+ init();
+ update(in, len);
+}
+
+KMD4::KMD4(const QByteArray& in)
+{
+ init();
+ update( in );
+}
+
+KMD4::KMD4(const QCString& in)
+{
+ init();
+ update( in );
+}
+
+void KMD4::update(const QByteArray& in)
+{
+ update(in.data(), int(in.size()));
+}
+
+void KMD4::update(const QCString& in)
+{
+ update(in.data(), int(in.length()));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void KMD4::update(const unsigned char *in, int len)
+{
+ if (len < 0)
+ len = qstrlen(reinterpret_cast<const char*>(in));
+
+ if (!len)
+ return;
+
+ if (m_finalized) {
+ kdWarning() << "KMD4::update called after state was finalized!" << endl;
+ return;
+ }
+
+ Q_UINT32 t;
+
+ /* Update bitcount */
+
+ t = m_count[0];
+ if ((m_count[0] = t + ((Q_UINT32) len << 3)) < t)
+ m_count[1]++; /* Carry from low to high */
+ m_count[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t)
+ {
+ Q_UINT8 *p = &m_buffer[ t ];
+
+ t = 64 - t;
+ if ((Q_UINT32)len < t)
+ {
+ memcpy (p, in, len);
+ return;
+ }
+ memcpy (p, in, t);
+ byteReverse (m_buffer, 16);
+ transform (m_state, (Q_UINT32*) m_buffer);
+ in += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64)
+ {
+ memcpy (m_buffer, in, 64);
+ byteReverse (m_buffer, 16);
+ transform (m_state, (Q_UINT32 *) m_buffer);
+ in += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy (m_buffer, in, len);
+}
+
+bool KMD4::update(QIODevice& file)
+{
+ char buffer[1024];
+ int len;
+
+ while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
+ update(buffer, len);
+
+ return file.atEnd();
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void KMD4::finalize()
+{
+ unsigned int count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (m_count[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = m_buffer + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8)
+ {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset (p, 0, count);
+ byteReverse (m_buffer, 16);
+ transform (m_state, (Q_UINT32*) m_buffer);
+
+ /* Now fill the next block with 56 bytes */
+ memset (m_buffer, 0, 56);
+ }
+ else
+ {
+ /* Pad block to 56 bytes */
+ memset (p, 0, count - 8);
+ }
+ byteReverse (m_buffer, 14);
+
+ /* Append length in bits and transform */
+ ((Q_UINT32 *) m_buffer)[14] = m_count[0];
+ ((Q_UINT32 *) m_buffer)[15] = m_count[1];
+
+ transform (m_state, (Q_UINT32 *) m_buffer);
+ byteReverse ((unsigned char *) m_state, 4);
+
+ memcpy (m_digest, m_state, 16);
+ memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
+
+ m_finalized = true;
+}
+
+bool KMD4::verify( const KMD4::Digest& digest)
+{
+ finalize();
+ return (0 == memcmp(rawDigest(), digest, sizeof(KMD4::Digest)));
+}
+
+bool KMD4::verify( const QCString& hexdigest)
+{
+ finalize();
+ return (0 == strcmp(hexDigest().data(), hexdigest));
+}
+
+const KMD4::Digest& KMD4::rawDigest()
+{
+ finalize();
+ return m_digest;
+}
+
+void KMD4::rawDigest( KMD4::Digest& bin )
+{
+ finalize();
+ memcpy( bin, m_digest, 16 );
+}
+
+QCString KMD4::hexDigest()
+{
+ QCString s(33);
+
+ finalize();
+ sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
+ m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
+ m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
+// kdDebug() << "KMD4::hexDigest() " << s << endl;
+ return s;
+}
+
+void KMD4::hexDigest(QCString& s)
+{
+ finalize();
+ s.resize(33);
+ sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
+ m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
+ m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
+}
+
+QCString KMD4::base64Digest()
+{
+ QByteArray ba(16);
+
+ finalize();
+ memcpy(ba.data(), m_digest, 16);
+ return KCodecs::base64Encode(ba);
+}
+
+
+void KMD4::init()
+{
+ d = 0;
+ reset();
+}
+
+/*
+ * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void KMD4::reset()
+{
+ m_finalized = false;
+
+ m_state[0] = 0x67452301;
+ m_state[1] = 0xefcdab89;
+ m_state[2] = 0x98badcfe;
+ m_state[3] = 0x10325476;
+
+ m_count[0] = 0;
+ m_count[1] = 0;
+
+ memset ( m_buffer, 0, sizeof(*m_buffer));
+ memset ( m_digest, 0, sizeof(*m_digest));
+}
+
+//#define rotl32(x,n) (((x) << ((Q_UINT32)(n))) | ((x) >> (32 - (Q_UINT32)(n))))
+
+inline Q_UINT32 KMD4::rotate_left (Q_UINT32 x, Q_UINT32 n)
+{
+ return (x << n) | (x >> (32-n)) ;
+}
+
+inline Q_UINT32 KMD4::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return (x & y) | (~x & z);
+}
+
+inline Q_UINT32 KMD4::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return ((x) & (y)) | ((x) & (z)) | ((y) & (z));
+}
+
+inline Q_UINT32 KMD4::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return x ^ y ^ z;
+}
+
+inline void KMD4::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s )
+{
+ a += F(b, c, d) + x;
+ a = rotate_left (a, s);
+}
+
+inline void KMD4::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s)
+{
+ a += G(b, c, d) + x + (Q_UINT32)0x5a827999;
+ a = rotate_left (a, s);
+}
+
+inline void KMD4::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s )
+{
+ a += H(b, c, d) + x + (Q_UINT32)0x6ed9eba1;
+ a = rotate_left (a, s);
+}
+
+void KMD4::byteReverse( unsigned char *buf, Q_UINT32 len )
+{
+#ifdef WORDS_BIGENDIAN
+ Q_UINT32 *b = (Q_UINT32*) buf;
+ while ( len > 0 ) {
+ *b = ((((*b) & 0xff000000) >> 24) | (((*b) & 0x00ff0000) >> 8) |
+ (((*b) & 0x0000ff00) << 8) | (((*b) & 0x000000ff) << 24));
+ len--;
+ b++;
+ }
+#else
+ Q_UNUSED(buf)
+ Q_UNUSED(len)
+#endif
+}
+
+/*
+ * The core of the MD4 algorithm
+ */
+void KMD4::transform( Q_UINT32 buf[4], Q_UINT32 const in[16] )
+{
+ Q_UINT32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ FF (a, b, c, d, in[0], 3); /* 1 */
+ FF (d, a, b, c, in[1], 7); /* 2 */
+ FF (c, d, a, b, in[2], 11); /* 3 */
+ FF (b, c, d, a, in[3], 19); /* 4 */
+ FF (a, b, c, d, in[4], 3); /* 5 */
+ FF (d, a, b, c, in[5], 7); /* 6 */
+ FF (c, d, a, b, in[6], 11); /* 7 */
+ FF (b, c, d, a, in[7], 19); /* 8 */
+ FF (a, b, c, d, in[8], 3); /* 9 */
+ FF (d, a, b, c, in[9], 7); /* 10 */
+ FF (c, d, a, b, in[10], 11); /* 11 */
+ FF (b, c, d, a, in[11], 19); /* 12 */
+ FF (a, b, c, d, in[12], 3); /* 13 */
+ FF (d, a, b, c, in[13], 7); /* 14 */
+ FF (c, d, a, b, in[14], 11); /* 15 */
+ FF (b, c, d, a, in[15], 19); /* 16 */
+
+ GG (a, b, c, d, in[0], 3); /* 17 */
+ GG (d, a, b, c, in[4], 5); /* 18 */
+ GG (c, d, a, b, in[8], 9); /* 19 */
+ GG (b, c, d, a, in[12], 13); /* 20 */
+ GG (a, b, c, d, in[1], 3); /* 21 */
+ GG (d, a, b, c, in[5], 5); /* 22 */
+ GG (c, d, a, b, in[9], 9); /* 23 */
+ GG (b, c, d, a, in[13], 13); /* 24 */
+ GG (a, b, c, d, in[2], 3); /* 25 */
+ GG (d, a, b, c, in[6], 5); /* 26 */
+ GG (c, d, a, b, in[10], 9); /* 27 */
+ GG (b, c, d, a, in[14], 13); /* 28 */
+ GG (a, b, c, d, in[3], 3); /* 29 */
+ GG (d, a, b, c, in[7], 5); /* 30 */
+ GG (c, d, a, b, in[11], 9); /* 31 */
+ GG (b, c, d, a, in[15], 13); /* 32 */
+
+ HH (a, b, c, d, in[0], 3); /* 33 */
+ HH (d, a, b, c, in[8], 9); /* 34 */
+ HH (c, d, a, b, in[4], 11); /* 35 */
+ HH (b, c, d, a, in[12], 15); /* 36 */
+ HH (a, b, c, d, in[2], 3); /* 37 */
+ HH (d, a, b, c, in[10], 9); /* 38 */
+ HH (c, d, a, b, in[6], 11); /* 39 */
+ HH (b, c, d, a, in[14], 15); /* 40 */
+ HH (a, b, c, d, in[1], 3); /* 41 */
+ HH (d, a, b, c, in[9], 9); /* 42 */
+ HH (c, d, a, b, in[5], 11); /* 43 */
+ HH (b, c, d, a, in[13], 15); /* 44 */
+ HH (a, b, c, d, in[3], 3); /* 45 */
+ HH (d, a, b, c, in[11], 9); /* 46 */
+ HH (c, d, a, b, in[7], 11); /* 47 */
+ HH (b, c, d, a, in[15], 15); /* 48 */
+
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}