source: subversion/applications/editors/osm-editor/qt3/qmdcodec.cpp @ 32040

Last change on this file since 32040 was 1158, checked in by nick, 14 years ago

moved current version to qt3 directory in preparation for qt4

File size: 31.5 KB
Line 
1/*
2   Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
3   Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU Lesser General Public License (LGPL)
7   version 2 as published by the Free Software Foundation.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU Library General Public
15   License along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18   RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
19   RSA Data Security, Inc. Created 1991. All rights reserved.
20
21   The QMD5 class is based on a C++ implementation of
22   "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
23   Mordechai T. Abzug,  Copyright (c) 1995.  This implementation
24   passes the test-suite as defined in RFC 1321.
25
26   The encoding and decoding utilities in QCodecs with the exception of
27   quoted-printable are based on the java implementation in HTTPClient
28   package by Ronald Tschalär Copyright (C) 1996-1999.
29
30   The quoted-printable codec as described in RFC 2045, section 6.7. is by
31   Rik Hemsley (C) 2001.
32*/
33
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37
38#include "qmdcodec.h"
39
40#define QMD5_S11 7
41#define QMD5_S12 12
42#define QMD5_S13 17
43#define QMD5_S14 22
44#define QMD5_S21 5
45#define QMD5_S22 9
46#define QMD5_S23 14
47#define QMD5_S24 20
48#define QMD5_S31 4
49#define QMD5_S32 11
50#define QMD5_S33 16
51#define QMD5_S34 23
52#define QMD5_S41 6
53#define QMD5_S42 10
54#define QMD5_S43 15
55#define QMD5_S44 21
56
57const char QCodecs::Base64EncMap[64] =
58{
59  0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
60  0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
61  0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
62  0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
63  0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
64  0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
65  0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
66  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
67};
68
69const char QCodecs::Base64DecMap[128] =
70{
71  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76  0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
77  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
78  0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79  0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
80  0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
81  0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
82  0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
83  0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
84  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
85  0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
86  0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
87};
88
89const char QCodecs::UUEncMap[64] =
90{
91  0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
92  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
93  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
94  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
95  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
96  0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
97  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
98  0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
99};
100
101const char QCodecs::UUDecMap[128] =
102{
103  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
108  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
109  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
110  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
111  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
112  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
113  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
114  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
115  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
119};
120
121const char QCodecs::hexChars[16] =
122{
123  '0', '1', '2', '3', '4', '5', '6', '7',
124  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
125};
126
127const unsigned int QCodecs::maxQPLineLength = 70;
128
129
130/******************************** QCodecs ********************************/
131// strchr(3) for broken systems.
132static int rikFindChar(register const char * _s, const char c)
133{
134  register const char * s = _s;
135
136  while (true)
137  {
138    if ((0 == *s) || (c == *s)) break; ++s;
139    if ((0 == *s) || (c == *s)) break; ++s;
140    if ((0 == *s) || (c == *s)) break; ++s;
141    if ((0 == *s) || (c == *s)) break; ++s;
142  }
143
144  return s - _s;
145}
146
147QCString QCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF)
148{
149  QByteArray out;
150  quotedPrintableEncode (in, out, useCRLF);
151  return QCString (out.data(), out.size()+1);
152}
153
154QCString QCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF)
155{
156  if (str.isEmpty())
157    return "";
158
159  QByteArray in (str.length());
160  memcpy (in.data(), str.data(), str.length());
161  return quotedPrintableEncode(in, useCRLF);
162}
163
164void QCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF)
165{
166  out.resize (0);
167  if (in.isEmpty())
168    return;
169
170  char *cursor;
171  const char *data;
172  unsigned int lineLength;
173  unsigned int pos;
174
175  const unsigned int length = in.size();
176  const unsigned int end = length - 1;
177
178
179  // Reasonable guess for output size when we're encoding
180  // mostly-ASCII data. It doesn't really matter, because
181  // the underlying allocation routines are quite efficient,
182  // but it's nice to have 0 allocations in many cases.
183  out.resize ((length*12)/10);
184  cursor = out.data();
185  data = in.data();
186  lineLength = 0;
187  pos = 0;
188
189  for (unsigned int i = 0; i < length; i++)
190  {
191    unsigned char c (data[i]);
192
193    // check if we have to enlarge the output buffer, use
194    // a safety margin of 16 byte
195    pos = cursor-out.data();
196    if (out.size()-pos < 16) {
197      out.resize(out.size()+4096);
198      cursor = out.data()+pos;
199    }
200
201    // Plain ASCII chars just go straight out.
202
203    if ((c >= 33) && (c <= 126) && ('=' != c))
204    {
205      *cursor++ = c;
206      ++lineLength;
207    }
208
209    // Spaces need some thought. We have to encode them at eol (or eof).
210
211    else if (' ' == c)
212    {
213      if
214        (
215         (i >= length)
216         ||
217         ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2]))
218                        ||
219                        (!useCRLF && ('\n' == data[i + 1]))))
220        )
221      {
222        *cursor++ = '=';
223        *cursor++ = '2';
224        *cursor++ = '0';
225
226        lineLength += 3;
227      }
228      else
229      {
230        *cursor++ = ' ';
231        ++lineLength;
232      }
233    }
234    // If we find a line break, just let it through.
235    else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) ||
236             (!useCRLF && ('\n' == c)))
237    {
238      lineLength = 0;
239
240      if (useCRLF) {
241        *cursor++ = '\r';
242        *cursor++ = '\n';
243        ++i;
244      } else {
245        *cursor++ = '\n';
246      }
247    }
248
249    // Anything else is converted to =XX.
250
251    else
252    {
253      *cursor++ = '=';
254      *cursor++ = hexChars[c / 16];
255      *cursor++ = hexChars[c % 16];
256
257      lineLength += 3;
258    }
259
260    // If we're approaching the maximum line length, do a soft line break.
261
262    if ((lineLength > maxQPLineLength) && (i < end))
263    {
264      if (useCRLF) {
265        *cursor++ = '=';
266        *cursor++ = '\r';
267        *cursor++ = '\n';
268      } else {
269        *cursor++ = '=';
270        *cursor++ = '\n';
271      }
272
273      lineLength = 0;
274    }
275  }
276
277  out.truncate(cursor - out.data());
278}
279
280QCString QCodecs::quotedPrintableDecode(const QByteArray & in)
281{
282  QByteArray out;
283  quotedPrintableDecode (in, out);
284  return QCString (out.data(), out.size()+1);
285}
286
287QCString QCodecs::quotedPrintableDecode(const QCString & str)
288{
289  if (str.isEmpty())
290    return "";
291
292  QByteArray in (str.length());
293  memcpy (in.data(), str.data(), str.length());
294  return quotedPrintableDecode (in);
295}
296
297void QCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out)
298{
299  // clear out the output buffer
300  out.resize (0);
301  if (in.isEmpty())
302      return;
303
304  char *cursor;
305  const char *data;
306  const unsigned int length = in.size();
307
308  data = in.data();
309  out.resize (length);
310  cursor = out.data();
311
312  for (unsigned int i = 0; i < length; i++)
313  {
314    char c(in.at(i));
315
316    if ('=' == c)
317    {
318      if (i < length - 2)
319      {
320        char c1 = in.at(i + 1);
321        char c2 = in.at(i + 2);
322
323        if (('\n' == c1) || ('\r' == c1 && '\n' == c2))
324        {
325          // Soft line break. No output.
326          if ('\r' == c1)
327            i += 2;        // CRLF line breaks
328          else
329            i += 1;
330        }
331        else
332        {
333          // =XX encoded byte.
334
335          int hexChar0 = rikFindChar(hexChars, c1);
336          int hexChar1 = rikFindChar(hexChars, c2);
337
338          if (hexChar0 < 16 && hexChar1 < 16)
339          {
340            *cursor++ = char((hexChar0 * 16) | hexChar1);
341            i += 2;
342          }
343        }
344      }
345    }
346    else
347    {
348      *cursor++ = c;
349    }
350  }
351
352  out.truncate(cursor - out.data());
353}
354
355QCString QCodecs::base64Encode( const QCString& str, bool insertLFs )
356{
357    if ( str.isEmpty() )
358        return "";
359
360    QByteArray in (str.length());
361    memcpy( in.data(), str.data(), str.length() );
362    return base64Encode( in, insertLFs );
363}
364
365QCString QCodecs::base64Encode( const QByteArray& in, bool insertLFs )
366{
367    QByteArray out;
368    base64Encode( in, out, insertLFs );
369    return QCString( out.data(), out.size()+1 );
370}
371
372void QCodecs::base64Encode( const QByteArray& in, QByteArray& out,
373                            bool insertLFs )
374{
375    // clear out the output buffer
376    out.resize (0);
377    if ( in.isEmpty() )
378        return;
379
380    unsigned int sidx = 0;
381    unsigned int didx = 0;
382    const char* data = in.data();
383    const unsigned int len = in.size();
384
385    unsigned int out_len = ((len+2)/3)*4;
386
387    // Deal with the 76 characters or less per
388    // line limit specified in RFC 2045 on a
389    // pre request basis.
390    insertLFs = (insertLFs && out_len > 76);
391    if ( insertLFs )
392      out_len += ((out_len-1)/76);
393
394    int count = 0;
395    out.resize( out_len );
396
397    // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
398    if ( len > 1 )
399    {
400        while (sidx < len-2)
401        {
402            if ( insertLFs )
403            {
404                if ( count && (count%76) == 0 )
405                    out.data()[didx++] = '\n';
406                count += 4;
407            }
408            out.data()[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
409            out.data()[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
410                                       (data[sidx] << 4) & 077];
411            out.data()[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 |
412                                       (data[sidx+1] << 2) & 077];
413            out.data()[didx++] = Base64EncMap[data[sidx+2] & 077];
414            sidx += 3;
415        }
416    }
417
418    if (sidx < len)
419    {
420        if ( insertLFs && (count > 0) && (count%76) == 0 )
421           out.data()[didx++] = '\n';
422
423        out.data()[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
424        if (sidx < len-1)
425        {
426            out.data()[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
427                                                                                                (data[sidx] << 4) & 077];
428            out.data()[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077];
429        }
430        else
431        {
432            out.data()[didx++] = Base64EncMap[(data[sidx] << 4) & 077];
433        }
434    }
435
436    // Add padding
437    while (didx < out.size())
438    {
439        out.data()[didx] = '=';
440        didx++;
441    }
442}
443
444QCString QCodecs::base64Decode( const QCString& str )
445{
446    if ( str.isEmpty() )
447        return "";
448
449    QByteArray in( str.length() );
450    memcpy( in.data(), str.data(), str.length() );
451    return base64Decode( in );
452}
453
454QCString QCodecs::base64Decode( const QByteArray& in )
455{
456    QByteArray out;
457    base64Decode( in, out );
458    return QCString( out.data(), out.size()+1 );
459}
460
461void QCodecs::base64Decode( const QByteArray& in, QByteArray& out )
462{
463    out.resize(0);
464    if ( in.isEmpty() )
465        return;
466
467    unsigned int count = 0;
468    unsigned int len = in.size(), tail = len;
469    const char* data = in.data();
470
471    // Deal with possible *nix "BEGIN" marker!!
472    while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
473            data[count] == '\t' || data[count] == ' ') )
474        count++;
475
476#ifdef _WIN32
477    if ( strnicmp(data+count, "begin", 5) == 0 )
478#else
479        if ( strncasecmp(data+count, "begin", 5) == 0 )
480#endif
481    {
482        count += 5;
483        while ( count < len && data[count] != '\n' && data[count] != '\r' )
484            count++;
485
486        while ( count < len && (data[count] == '\n' || data[count] == '\r') )
487            count ++;
488
489        data += count;
490        tail = (len -= count);
491    }
492
493    // Find the tail end of the actual encoded data even if
494    // there is/are trailing CR and/or LF.
495    while ( data[tail-1] == '=' || data[tail-1] == '\n' ||
496            data[tail-1] == '\r' )
497        if ( data[--tail] != '=' ) len = tail;
498
499    unsigned int outIdx = 0;
500    out.resize( (count=len) );
501    for (unsigned int idx = 0; idx < count; idx++)
502    {
503        // Adhere to RFC 2045 and ignore characters
504        // that are not part of the encoding table.
505        unsigned char ch = data[idx];
506        if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
507            (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
508        {
509            out.data()[outIdx++] = Base64DecMap[ch];
510        }
511        else
512        {
513            len--;
514            tail--;
515        }
516    }
517
518    // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl;
519
520    // 4-byte to 3-byte conversion
521    len = (tail>(len/4)) ? tail-(len/4) : 0;
522    unsigned int sidx = 0, didx = 0;
523    if ( len > 1 )
524    {
525      while (didx < len-2)
526      {
527          out.data()[didx] = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003));
528          out.data()[didx+1] = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017));
529          out.data()[didx+2] = (((out.at(sidx+2) << 6) & 255) | (out.at(sidx+3) & 077));
530          sidx += 4;
531          didx += 3;
532      }
533    }
534
535    if (didx < len)
536        out.data()[didx] = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003));
537
538    if (++didx < len )
539        out.data()[didx] = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017));
540
541    // Resize the output buffer
542    if ( len == 0 || len < out.size() )
543      out.resize(len);
544}
545
546QCString QCodecs::uuencode( const QCString& str )
547{
548    if ( str.isEmpty() )
549        return "";
550
551    QByteArray in;
552    in.resize( str.length() );
553    memcpy( in.data(), str.data(), str.length() );
554    return uuencode( in );
555}
556
557QCString QCodecs::uuencode( const QByteArray& in )
558{
559    QByteArray out;
560    uuencode( in, out );
561    return QCString( out.data(), out.size()+1 );
562}
563
564void QCodecs::uuencode( const QByteArray& in, QByteArray& out )
565{
566    out.resize( 0 );
567    if( in.isEmpty() )
568        return;
569
570    unsigned int sidx = 0;
571    unsigned int didx = 0;
572    unsigned int line_len = 45;
573
574    const char nl[] = "\n";
575    const char* data = in.data();
576    const unsigned int nl_len = strlen(nl);
577    const unsigned int len = in.size();
578
579    out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
580    // split into lines, adding line-length and line terminator
581    while (sidx+line_len < len)
582    {
583        // line length
584        out.data()[didx++] = UUEncMap[line_len];
585
586        // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
587        for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
588        {
589            out.data()[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
590            out.data()[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
591                                   (data[sidx] << 4) & 077];
592            out.data()[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
593                                (data[sidx+1] << 2) & 077];
594            out.data()[didx++] = UUEncMap[data[sidx+2] & 077];
595        }
596
597        // line terminator
598        //for (unsigned int idx=0; idx < nl_len; idx++)
599        //out[didx++] = nl[idx];
600        memcpy(out.data()+didx, nl, nl_len);
601        didx += nl_len;
602    }
603
604    // line length
605    out.data()[didx++] = UUEncMap[len-sidx];
606    // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
607    while (sidx+2 < len)
608    {
609        out.data()[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
610        out.data()[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
611                               (data[sidx] << 4) & 077];
612        out.data()[didx++] = UUEncMap[(data[sidx+2] >> 6) & 003 |
613                               (data[sidx+1] << 2) & 077];
614        out.data()[didx++] = UUEncMap[data[sidx+2] & 077];
615        sidx += 3;
616    }
617
618    if (sidx < len-1)
619    {
620        out.data()[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
621        out.data()[didx++] = UUEncMap[(data[sidx+1] >> 4) & 017 |
622                               (data[sidx] << 4) & 077];
623        out.data()[didx++] = UUEncMap[(data[sidx+1] << 2) & 077];
624        out.data()[didx++] = UUEncMap[0];
625    }
626    else if (sidx < len)
627    {
628        out.data()[didx++] = UUEncMap[(data[sidx] >> 2) & 077];
629        out.data()[didx++] = UUEncMap[(data[sidx] << 4) & 077];
630        out.data()[didx++] = UUEncMap[0];
631        out.data()[didx++] = UUEncMap[0];
632    }
633
634    // line terminator
635    memcpy(out.data()+didx, nl, nl_len);
636    didx += nl_len;
637
638    // sanity check
639    if ( didx != out.size() )
640        out.resize( 0 );
641}
642
643QCString QCodecs::uudecode( const QCString& str )
644{
645    if ( str.isEmpty() )
646        return "";
647
648    QByteArray in;
649    in.resize( str.length() );
650    memcpy( in.data(), str.data(), str.length() );
651    return uudecode( in );
652}
653
654QCString QCodecs::uudecode( const QByteArray& in )
655{
656    QByteArray out;
657    uudecode( in, out );
658    return QCString( out.data(), out.size()+1 );
659}
660
661void QCodecs::uudecode( const QByteArray& in, QByteArray& out )
662{
663    out.resize( 0 );
664    if( in.isEmpty() )
665        return;
666
667    unsigned int sidx = 0;
668    unsigned int didx = 0;
669    unsigned int len = in.size();
670    unsigned int line_len, end;
671    const char* data = in.data();
672
673    // Deal with *nix "BEGIN"/"END" separators!!
674    unsigned int count = 0;
675    while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
676            data[count] == '\t' || data[count] == ' ') )
677        count ++;
678
679    bool hasLF = false;
680
681#ifdef _WIN32
682    if ( strnicmp( data+count, "begin", 5) == 0 )
683#else
684        if ( strncasecmp( data+count, "begin", 5) == 0 )
685#endif
686    {
687        count += 5;
688        while ( count < len && data[count] != '\n' && data[count] != '\r' )
689            count ++;
690
691        while ( count < len && (data[count] == '\n' || data[count] == '\r') )
692            count ++;
693
694        data += count;
695        len -= count;
696        hasLF = true;
697    }
698
699    out.resize( len/4*3 );
700    while ( sidx < len )
701    {
702        // get line length (in number of encoded octets)
703        line_len = UUDecMap[ (unsigned char) data[sidx++]];
704        // ascii printable to 0-63 and 4-byte to 3-byte conversion
705        end = didx+line_len;
706        char A, B, C, D;
707        if (end > 2) {
708          while (didx < end-2)
709          {
710             A = UUDecMap[(unsigned char) data[sidx]];
711             B = UUDecMap[(unsigned char) data[sidx+1]];
712             C = UUDecMap[(unsigned char) data[sidx+2]];
713             D = UUDecMap[(unsigned char) data[sidx+3]];
714             out.data()[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
715             out.data()[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
716             out.data()[didx++] = ( ((C << 6) & 255) | (D & 077) );
717             sidx += 4;
718          }
719        }
720
721        if (didx < end)
722        {
723            A = UUDecMap[(unsigned char) data[sidx]];
724            B = UUDecMap[(unsigned char) data[sidx+1]];
725            out.data()[didx++] = ( ((A << 2) & 255) | ((B >> 4) & 003) );
726        }
727
728        if (didx < end)
729        {
730            B = UUDecMap[(unsigned char) data[sidx+1]];
731            C = UUDecMap[(unsigned char) data[sidx+2]];
732            out.data()[didx++] = ( ((B << 4) & 255) | ((C >> 2) & 017) );
733        }
734
735        // skip padding
736        while (sidx < len  && data[sidx] != '\n' && data[sidx] != '\r')
737            sidx++;
738
739        // skip end of line
740        while (sidx < len  && (data[sidx] == '\n' || data[sidx] == '\r'))
741            sidx++;
742
743        // skip the "END" separator when present.
744#ifdef _WIN32
745        if ( hasLF && strnicmp( data+sidx, "end", 3) == 0 )
746#else
747                if ( hasLF && strncasecmp( data+sidx, "end", 3) == 0 )
748#endif
749            break;
750    }
751
752    if ( didx < out.size()  )
753        out.resize( didx );
754}
755
756/******************************** QMD5 ********************************/
757QMD5::QMD5()
758{
759    init();
760}
761
762QMD5::QMD5(const char *in, int len)
763{
764    init();
765    update(in, len);
766}
767
768QMD5::QMD5(const QByteArray& in)
769{
770    init();
771    update( in );
772}
773
774QMD5::QMD5(const QCString& in)
775{
776    init();
777    update( in );
778}
779
780void QMD5::update(const QByteArray& in)
781{
782    update(in.data(), int(in.size()));
783}
784
785void QMD5::update(const QCString& in)
786{
787    update(in.data(), int(in.length()));
788}
789
790void QMD5::update(const unsigned char* in, int len)
791{
792    if (len < 0)
793        len = qstrlen(reinterpret_cast<const char*>(in));
794
795    if (!len)
796        return;
797
798    if (m_finalized) {
799        qWarning("QMD5::update called after state was finalized!");
800        return;
801    }
802
803    Q_UINT32 in_index;
804    Q_UINT32 buffer_index;
805    Q_UINT32 buffer_space;
806    Q_UINT32 in_length = static_cast<Q_UINT32>( len );
807
808    buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F);
809
810    if (  (m_count[0] += (in_length << 3))<(in_length << 3) )
811        m_count[1]++;
812
813    m_count[1] += (in_length >> 29);
814    buffer_space = 64 - buffer_index;
815
816    if (in_length >= buffer_space)
817    {
818        memcpy (m_buffer + buffer_index, in, buffer_space);
819        transform (m_buffer);
820
821        for (in_index = buffer_space; in_index + 63 < in_length;
822             in_index += 64)
823            transform (reinterpret_cast<const unsigned char*>(in+in_index));
824
825        buffer_index = 0;
826    }
827    else
828        in_index=0;
829
830    memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
831}
832
833bool QMD5::update(QIODevice& file)
834{
835    char buffer[1024];
836    int len;
837
838    while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
839        update(buffer, len);
840
841    return file.atEnd();
842}
843
844void QMD5::finalize ()
845{
846    if (m_finalized) return;
847
848    Q_UINT8 bits[8];
849    Q_UINT32 index, padLen;
850    static unsigned char PADDING[64]=
851    {
852        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
853        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
854        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
855        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
856    };
857
858    encode (bits, m_count, 8);
859    //memcpy( bits, m_count, 8 );
860
861    // Pad out to 56 mod 64.
862    index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f);
863    padLen = (index < 56) ? (56 - index) : (120 - index);
864    update (reinterpret_cast<const char*>(PADDING), padLen);
865
866    // Append length (before padding)
867    update (reinterpret_cast<const char*>(bits), 8);
868
869    // Store state in digest
870    encode (m_digest, m_state, 16);
871    //memcpy( m_digest, m_state, 16 );
872
873    // Fill sensitive information with zero's
874    memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
875
876    m_finalized = true;
877}
878
879
880bool QMD5::verify( const QMD5::Digest& digest)
881{
882    finalize();
883    return (0 == memcmp(rawDigest(), digest, sizeof(QMD5::Digest)));
884}
885
886bool QMD5::verify( const QCString& hexdigest)
887{
888    finalize();
889    return (0 == strcmp(hexDigest().data(), hexdigest));
890}
891
892const QMD5::Digest& QMD5::rawDigest()
893{
894    finalize();
895    return m_digest;
896}
897
898void QMD5::rawDigest( QMD5::Digest& bin )
899{
900    finalize();
901    memcpy( bin, m_digest, 16 );
902}
903
904
905QCString QMD5::hexDigest()
906{
907    QCString s(33);
908
909    finalize();
910    sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
911            m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
912            m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
913            m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
914
915    return s;
916}
917
918void QMD5::hexDigest(QCString& s)
919{
920    finalize();
921    s.resize(33);
922    sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
923            m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
924            m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
925            m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
926}
927
928QCString QMD5::base64Digest()
929{
930    QByteArray ba(16);
931
932    finalize();
933    memcpy(ba.data(), m_digest, 16);
934    return QCodecs::base64Encode(ba);
935}
936
937
938void QMD5::init()
939{
940    d = 0;
941    reset();
942}
943
944void QMD5::reset()
945{
946    m_finalized = false;
947
948    m_count[0] = 0;
949    m_count[1] = 0;
950
951    m_state[0] = 0x67452301;
952    m_state[1] = 0xefcdab89;
953    m_state[2] = 0x98badcfe;
954    m_state[3] = 0x10325476;
955
956    memset ( m_buffer, 0, sizeof(*m_buffer));
957    memset ( m_digest, 0, sizeof(*m_digest));
958}
959
960void QMD5::transform( const unsigned char block[64] )
961{
962
963    Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
964
965    decode (x, block, 64);
966    //memcpy( x, block, 64 );
967
968    Q_ASSERT(!m_finalized);  // not just a user error, since the method is private
969
970    /* Round 1 */
971    FF (a, b, c, d, x[ 0], QMD5_S11, 0xd76aa478); /* 1 */
972    FF (d, a, b, c, x[ 1], QMD5_S12, 0xe8c7b756); /* 2 */
973    FF (c, d, a, b, x[ 2], QMD5_S13, 0x242070db); /* 3 */
974    FF (b, c, d, a, x[ 3], QMD5_S14, 0xc1bdceee); /* 4 */
975    FF (a, b, c, d, x[ 4], QMD5_S11, 0xf57c0faf); /* 5 */
976    FF (d, a, b, c, x[ 5], QMD5_S12, 0x4787c62a); /* 6 */
977    FF (c, d, a, b, x[ 6], QMD5_S13, 0xa8304613); /* 7 */
978    FF (b, c, d, a, x[ 7], QMD5_S14, 0xfd469501); /* 8 */
979    FF (a, b, c, d, x[ 8], QMD5_S11, 0x698098d8); /* 9 */
980    FF (d, a, b, c, x[ 9], QMD5_S12, 0x8b44f7af); /* 10 */
981    FF (c, d, a, b, x[10], QMD5_S13, 0xffff5bb1); /* 11 */
982    FF (b, c, d, a, x[11], QMD5_S14, 0x895cd7be); /* 12 */
983    FF (a, b, c, d, x[12], QMD5_S11, 0x6b901122); /* 13 */
984    FF (d, a, b, c, x[13], QMD5_S12, 0xfd987193); /* 14 */
985    FF (c, d, a, b, x[14], QMD5_S13, 0xa679438e); /* 15 */
986    FF (b, c, d, a, x[15], QMD5_S14, 0x49b40821); /* 16 */
987
988    /* Round 2 */
989    GG (a, b, c, d, x[ 1], QMD5_S21, 0xf61e2562); /* 17 */
990    GG (d, a, b, c, x[ 6], QMD5_S22, 0xc040b340); /* 18 */
991    GG (c, d, a, b, x[11], QMD5_S23, 0x265e5a51); /* 19 */
992    GG (b, c, d, a, x[ 0], QMD5_S24, 0xe9b6c7aa); /* 20 */
993    GG (a, b, c, d, x[ 5], QMD5_S21, 0xd62f105d); /* 21 */
994    GG (d, a, b, c, x[10], QMD5_S22,  0x2441453); /* 22 */
995    GG (c, d, a, b, x[15], QMD5_S23, 0xd8a1e681); /* 23 */
996    GG (b, c, d, a, x[ 4], QMD5_S24, 0xe7d3fbc8); /* 24 */
997    GG (a, b, c, d, x[ 9], QMD5_S21, 0x21e1cde6); /* 25 */
998    GG (d, a, b, c, x[14], QMD5_S22, 0xc33707d6); /* 26 */
999    GG (c, d, a, b, x[ 3], QMD5_S23, 0xf4d50d87); /* 27 */
1000    GG (b, c, d, a, x[ 8], QMD5_S24, 0x455a14ed); /* 28 */
1001    GG (a, b, c, d, x[13], QMD5_S21, 0xa9e3e905); /* 29 */
1002    GG (d, a, b, c, x[ 2], QMD5_S22, 0xfcefa3f8); /* 30 */
1003    GG (c, d, a, b, x[ 7], QMD5_S23, 0x676f02d9); /* 31 */
1004    GG (b, c, d, a, x[12], QMD5_S24, 0x8d2a4c8a); /* 32 */
1005
1006    /* Round 3 */
1007    HH (a, b, c, d, x[ 5], QMD5_S31, 0xfffa3942); /* 33 */
1008    HH (d, a, b, c, x[ 8], QMD5_S32, 0x8771f681); /* 34 */
1009    HH (c, d, a, b, x[11], QMD5_S33, 0x6d9d6122); /* 35 */
1010    HH (b, c, d, a, x[14], QMD5_S34, 0xfde5380c); /* 36 */
1011    HH (a, b, c, d, x[ 1], QMD5_S31, 0xa4beea44); /* 37 */
1012    HH (d, a, b, c, x[ 4], QMD5_S32, 0x4bdecfa9); /* 38 */
1013    HH (c, d, a, b, x[ 7], QMD5_S33, 0xf6bb4b60); /* 39 */
1014    HH (b, c, d, a, x[10], QMD5_S34, 0xbebfbc70); /* 40 */
1015    HH (a, b, c, d, x[13], QMD5_S31, 0x289b7ec6); /* 41 */
1016    HH (d, a, b, c, x[ 0], QMD5_S32, 0xeaa127fa); /* 42 */
1017    HH (c, d, a, b, x[ 3], QMD5_S33, 0xd4ef3085); /* 43 */
1018    HH (b, c, d, a, x[ 6], QMD5_S34,  0x4881d05); /* 44 */
1019    HH (a, b, c, d, x[ 9], QMD5_S31, 0xd9d4d039); /* 45 */
1020    HH (d, a, b, c, x[12], QMD5_S32, 0xe6db99e5); /* 46 */
1021    HH (c, d, a, b, x[15], QMD5_S33, 0x1fa27cf8); /* 47 */
1022    HH (b, c, d, a, x[ 2], QMD5_S34, 0xc4ac5665); /* 48 */
1023
1024    /* Round 4 */
1025    II (a, b, c, d, x[ 0], QMD5_S41, 0xf4292244); /* 49 */
1026    II (d, a, b, c, x[ 7], QMD5_S42, 0x432aff97); /* 50 */
1027    II (c, d, a, b, x[14], QMD5_S43, 0xab9423a7); /* 51 */
1028    II (b, c, d, a, x[ 5], QMD5_S44, 0xfc93a039); /* 52 */
1029    II (a, b, c, d, x[12], QMD5_S41, 0x655b59c3); /* 53 */
1030    II (d, a, b, c, x[ 3], QMD5_S42, 0x8f0ccc92); /* 54 */
1031    II (c, d, a, b, x[10], QMD5_S43, 0xffeff47d); /* 55 */
1032    II (b, c, d, a, x[ 1], QMD5_S44, 0x85845dd1); /* 56 */
1033    II (a, b, c, d, x[ 8], QMD5_S41, 0x6fa87e4f); /* 57 */
1034    II (d, a, b, c, x[15], QMD5_S42, 0xfe2ce6e0); /* 58 */
1035    II (c, d, a, b, x[ 6], QMD5_S43, 0xa3014314); /* 59 */
1036    II (b, c, d, a, x[13], QMD5_S44, 0x4e0811a1); /* 60 */
1037    II (a, b, c, d, x[ 4], QMD5_S41, 0xf7537e82); /* 61 */
1038    II (d, a, b, c, x[11], QMD5_S42, 0xbd3af235); /* 62 */
1039    II (c, d, a, b, x[ 2], QMD5_S43, 0x2ad7d2bb); /* 63 */
1040    II (b, c, d, a, x[ 9], QMD5_S44, 0xeb86d391); /* 64 */
1041
1042    m_state[0] += a;
1043    m_state[1] += b;
1044    m_state[2] += c;
1045    m_state[3] += d;
1046
1047    memset ( static_cast<void *>(x), 0, sizeof(x) );
1048}
1049
1050inline Q_UINT32 QMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
1051{
1052    return (x << n) | (x >> (32-n))  ;
1053}
1054
1055inline Q_UINT32 QMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1056{
1057    return (x & y) | (~x & z);
1058}
1059
1060inline Q_UINT32 QMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1061{
1062    return (x & z) | (y & ~z);
1063}
1064
1065inline Q_UINT32 QMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1066{
1067    return x ^ y ^ z;
1068}
1069
1070inline Q_UINT32 QMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1071{
1072    return y ^ (x | ~z);
1073}
1074
1075void QMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1076                       Q_UINT32 x, Q_UINT32  s, Q_UINT32 ac )
1077{
1078    a += F(b, c, d) + x + ac;
1079    a = rotate_left (a, s) +b;
1080}
1081
1082void QMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1083                 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac)
1084{
1085    a += G(b, c, d) + x + ac;
1086    a = rotate_left (a, s) +b;
1087}
1088
1089void QMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1090                 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
1091{
1092    a += H(b, c, d) + x + ac;
1093    a = rotate_left (a, s) +b;
1094}
1095
1096void QMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1097                 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
1098{
1099    a += I(b, c, d) + x + ac;
1100    a = rotate_left (a, s) +b;
1101}
1102
1103
1104void QMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len )
1105{
1106#if !defined(WORDS_BIGENDIAN)
1107    memcpy(output, in, len);
1108
1109#else
1110    Q_UINT32 i, j;
1111    for (i = 0, j = 0; j < len; i++, j += 4)
1112    {
1113        output[j]   = static_cast<Q_UINT8>((in[i] & 0xff));
1114        output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff));
1115        output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff));
1116        output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff));
1117    }
1118#endif
1119}
1120
1121// Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a
1122// multiple of 4.
1123void QMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len)
1124{
1125#if !defined(WORDS_BIGENDIAN)
1126    memcpy(output, in, len);
1127
1128#else
1129    Q_UINT32 i, j;
1130    for (i = 0, j = 0; j < len; i++, j += 4)
1131        output[i] = static_cast<Q_UINT32>(in[j]) |
1132                    (static_cast<Q_UINT32>(in[j+1]) << 8)  |
1133                    (static_cast<Q_UINT32>(in[j+2]) << 16) |
1134                    (static_cast<Q_UINT32>(in[j+3]) << 24);
1135#endif
1136}
Note: See TracBrowser for help on using the repository browser.