source: sources/src/toolsCode.cc @ 1492:3ae5908ffbf9

Revision 1492:3ae5908ffbf9, 55.4 KB checked in by niam, 16 months ago (diff)

branch merge

Line 
1/***************************************************************************
2 *            toolsCode.cc
3 *
4 *  Thu Jul 24 2008
5 *  Copyright  2008  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <errno.h>
33#ifdef ICONV_EXT
34#include <iconv.h>
35#endif
36#ifdef ZLIB_EXT
37#include <zlib.h>
38#endif
39#ifdef BZIP2_EXT
40#include <bzlib.h>
41#endif
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/socket.h>
45#include <netinet/in.h>
46#include <arpa/inet.h>
47#include <netdb.h>
48#include <sys/un.h>
49#include <net/if.h>
50#include <sys/ioctl.h>
51#include <fcntl.h>
52#include <stdlib.h>
53
54#include <libdodo/toolsCode.h>
55#include <libdodo/types.h>
56#include <libdodo/toolsString.h>
57#include <libdodo/toolsCodeEx.h>
58
59using namespace dodo::tools;
60
61/**
62 * for MD5
63 */
64
65/**
66 * MD5 magic numbers
67 */
68#define S11    7
69#define S12    12
70#define S13    17
71#define S14    22
72#define S21    5
73#define S22    9
74#define S23    14
75#define S24    20
76#define S31    4
77#define S32    11
78#define S33    16
79#define S34    23
80#define S41    6
81#define S42    10
82#define S43    15
83#define S44    21
84
85//-------------------------------------------------------------------
86
87const unsigned char code::MD5Padding[] = {
88    0x80, 0,    0,        0,    0,        0,        0,    0,        0,    0,        0,    0,        0,    0,        0,    0,        0, 0, 0, 0, 0, 0,
89    0,    0,    0,        0,    0,        0,        0,    0,        0,    0,        0,    0,        0,    0,        0,    0,        0, 0, 0, 0, 0, 0, 0,
90    0,    0,    0,        0,    0,        0,        0,    0,        0,    0,        0,    0,        0,    0,        0,    0,        0, 0, 0
91};
92
93/**
94 * F, G, H and I are basic MD5 functions.
95 */
96#define F(x, y, z)           (((x) & (y)) | ((~x) & (z)))
97
98//-------------------------------------------------------------------
99
100#define G(x, y, z)           (((x) & (z)) | ((y) & (~z)))
101
102//-------------------------------------------------------------------
103
104#define H(x, y, z)           ((x) ^ (y) ^ (z))
105
106//-------------------------------------------------------------------
107
108#define I(x, y, z)           ((y) ^ ((x) | (~z)))
109
110/**
111 * ROTATE_LEFT rotates x left n bits.
112 */
113#define ROTATE_LEFT(x, n)    (((x) << (n)) | ((x) >> (32 - (n))))
114
115/**
116 * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
117 * Rotation is separate from addition to prevent recomputation.
118 */
119#define FF(a, b, c, d, x, s, ac)                            \
120    {                                                       \
121        (a) += F((b), (c), (d)) + (x) + (unsigned int)(ac); \
122        (a) = ROTATE_LEFT((a), (s));                        \
123        (a) += (b);                                         \
124    }
125
126//-------------------------------------------------------------------
127
128#define GG(a, b, c, d, x, s, ac)                            \
129    {                                                       \
130        (a) += G((b), (c), (d)) + (x) + (unsigned int)(ac); \
131        (a) = ROTATE_LEFT((a), (s));                        \
132        (a) += (b);                                         \
133    }
134
135//-------------------------------------------------------------------
136
137#define HH(a, b, c, d, x, s, ac)                            \
138    {                                                       \
139        (a) += H((b), (c), (d)) + (x) + (unsigned int)(ac); \
140        (a) = ROTATE_LEFT((a), (s));                        \
141        (a) += (b);                                         \
142    }
143
144//-------------------------------------------------------------------
145
146#define II(a, b, c, d, x, s, ac)                            \
147    {                                                       \
148        (a) += I((b), (c), (d)) + (x) + (unsigned int)(ac); \
149        (a) = ROTATE_LEFT((a), (s));                        \
150        (a) += (b);                                         \
151    }
152
153//-------------------------------------------------------------------
154
155/**
156 * for ASCII85 decode
157 */
158const unsigned long code::powASCII85[] = {
159    85 * 85 * 85 * 85,
160    85 * 85 * 85,
161    85 * 85,
162    85,
163    1
164};
165
166//-------------------------------------------------------------------
167
168/**
169 * for base64 decode
170 */
171const char code::base64EncodeChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
172
173//-------------------------------------------------------------------
174
175const char code::base64DecodeChars[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
176
177//-------------------------------------------------------------------
178
179/**
180 * for SHA
181 */
182
183#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
184#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
185#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
186
187//-------------------------------------------------------------------
188
189/**
190 * for SHA-1
191 */
192
193/**
194 *  SHA-1 circular left shift macro
195 */
196#define SHA1_ROTL(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))
197
198//-------------------------------------------------------------------
199
200/**
201 * for SHA-256
202 */
203
204/**
205 * SHA-256 rotate left and rotate right macro
206 */
207#define SHA256_ROTL(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))
208#define SHA256_ROTR(bits, word) (((word) >> (bits)) | ((word) << (32 - (bits))))
209
210//-------------------------------------------------------------------
211
212/**
213 * SHA-256 SIGMA and sigma macros
214 */
215#define SHA256_SIGMA0(word) (SHA256_ROTR( 2, word) ^ SHA256_ROTR(13, word) ^ SHA256_ROTR(22, word))
216#define SHA256_SIGMA1(word) (SHA256_ROTR( 6, word) ^ SHA256_ROTR(11, word) ^ SHA256_ROTR(25, word))
217#define SHA256_sigma0(word) (SHA256_ROTR( 7, word) ^ SHA256_ROTR(18, word) ^ ((word) >> 3))
218#define SHA256_sigma1(word) (SHA256_ROTR(17, word) ^ SHA256_ROTR(19, word) ^ ((word) >> 10))
219
220//-------------------------------------------------------------------
221
222/**
223 * for SHA-512
224 */
225
226/**
227 * SHA-512 rotate left and rotate right macro
228 */
229#define SHA512_ROTL(bits, word) (((word) << (bits)) | ((word) >> (64 - (bits))))
230#define SHA512_ROTR(bits, word) (((word) >> (bits)) | ((word) << (64 - (bits))))
231
232/**
233 * SHA-512 SIGMA and sigma macros
234 */
235#define SHA512_SIGMA0(word) (SHA512_ROTR(28, (word)) ^ SHA512_ROTR(34, (word)) ^ SHA512_ROTR(39, (word)))
236#define SHA512_SIGMA1(word) (SHA512_ROTR(14, (word)) ^ SHA512_ROTR(18, (word)) ^ SHA512_ROTR(41, (word)))
237#define SHA512_sigma0(word) (SHA512_ROTR( 1, (word)) ^ SHA512_ROTR( 8, (word)) ^ ((word) >> 7))
238#define SHA512_sigma1(word) (SHA512_ROTR(19, (word)) ^ SHA512_ROTR(61, (word)) ^ ((word) >> 6))
239
240/*
241 * These definitions are potentially faster equivalents for the ones
242 * used in FIPS-180-2, section 4.1.3.
243 *   ((x & y) ^ (~x & z)) becomes
244 *   ((x & (y ^ z)) ^ z)
245 */
246#define SHA512_Ch(x, y, z) ((x & (y ^ z)) ^ z)
247
248//-------------------------------------------------------------------
249
250/*
251 * These definitions are potentially faster equivalents for the ones
252 * used in FIPS-180-2, section 4.1.3.
253 *   ((x & y) ^ (x & z) ^ (y & z)) becomes
254 *   ((x & (y | z)) | (y & z))
255 */
256#define SHA512_Maj(x, y, z) ((x & (y | z)) | (y & z))
257
258//-------------------------------------------------------------------
259
260/**
261 * for HEX convertions
262 */
263const char code::hexEncodeChars[] = "0123456789abcdef";
264
265//-------------------------------------------------------------------
266
267#ifdef ICONV_EXT
268dodo::string
269code::codesetConversion(const dodo::string &buffer,
270                        const dodo::string &toCode,
271                        const dodo::string &fromCode)
272{
273    iconv_t conv = iconv_open(toCode.data(), fromCode.data());
274    if (conv == (iconv_t)(-1))
275        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_CODESETCONVERSION, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
276
277    size_t in, out, outBefore;
278    char *inFake, *outFake;
279
280    in = buffer.size();
281    outBefore = out = (in + 1) * 4;
282    char *outBuffer = new char[out];
283
284    inFake = (char *)buffer.data();
285    outFake = outBuffer;
286
287#ifdef __FreeBSD__
288    if (iconv(conv, (const char **)&inFake, &in, &outFake, &out) == (size_t)(-1))
289#else
290    if (iconv(conv, &inFake, &in, &outFake, &out) == (size_t)(-1))
291#endif
292    {
293        delete [] outBuffer;
294
295        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_CODESETCONVERSION, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
296    }
297
298    dodo::string result;
299    result = dodo::string(outBuffer, outBefore - out);
300
301    delete [] outBuffer;
302
303    return result;
304}
305#endif
306
307//-------------------------------------------------------------------
308
309#ifdef ZLIB_EXT
310dodo::string
311code::zCompress(const dodo::string &buffer,
312                unsigned short   level,
313                short            type)
314{
315    z_stream zs;
316    int ret;
317
318    dodo::string strBuf;
319    Bytef *byteBuf;
320
321    zs.zalloc = Z_NULL;
322    zs.zfree = Z_NULL;
323    zs.opaque = Z_NULL;
324
325    if ((ret = deflateInit2(&zs, level, Z_DEFLATED, 16+MAX_WBITS, level, type)) < 0)
326        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_ZCOMPRESS, exception::ERRNO_ZLIB, ret, zs.msg == NULL ? "" : zs.msg, __LINE__, __FILE__);
327
328    zs.avail_in =  buffer.size();
329    zs.next_in = (Bytef *)buffer.data();
330
331    byteBuf = new Bytef[ZLIB_CHUNK];
332
333    strBuf.clear();
334
335    do {
336        zs.avail_out = ZLIB_CHUNK;
337        zs.next_out = byteBuf;
338
339        if ((ret = deflate(&zs, Z_FINISH)) < 0) {
340            delete [] byteBuf;
341
342            dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_ZCOMPRESS, exception::ERRNO_ZLIB, ret, zs.msg == NULL ? "" : zs.msg, __LINE__, __FILE__);
343        }
344
345        strBuf += dodo::string((char *)byteBuf, ZLIB_CHUNK - zs.avail_out);
346    } while (zs.avail_out == 0);
347
348    deflateEnd(&zs);
349    delete [] byteBuf;
350
351    return strBuf;
352}
353
354//-------------------------------------------------------------------
355
356dodo::string
357code::zDecompress(const dodo::string &buffer)
358{
359    z_stream zs;
360    int ret;
361
362    dodo::string strBuf;
363    Bytef *byteBuf;
364
365    zs.zalloc = Z_NULL;
366    zs.zfree = Z_NULL;
367    zs.opaque = Z_NULL;
368
369    if ((ret = inflateInit2(&zs, 16+MAX_WBITS)) < 0)
370        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_ZDECOMPRESS, exception::ERRNO_ZLIB, ret, zs.msg == NULL ? "" : zs.msg, __LINE__, __FILE__);
371
372    byteBuf = new Bytef[ZLIB_CHUNK];
373
374    zs.avail_in = buffer.size();
375    zs.next_in = (Bytef *)buffer.data();
376
377    strBuf.clear();
378
379    do {
380        zs.avail_out = ZLIB_CHUNK;
381        zs.next_out = byteBuf;
382
383        if ((ret = inflate(&zs, Z_NO_FLUSH)) < 0) {
384            delete [] byteBuf;
385
386            dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_ZDECOMPRESS, exception::ERRNO_ZLIB, ret, zs.msg == NULL ? "" : zs.msg, __LINE__, __FILE__);
387        }
388
389        strBuf += dodo::string((char *)byteBuf, ZLIB_CHUNK - zs.avail_out);
390    } while (zs.avail_out == 0);
391
392    inflateEnd(&zs);
393    delete [] byteBuf;
394
395    return strBuf;
396}
397#endif
398
399//-------------------------------------------------------------------
400
401char
402code::hexToChar(char first,
403                char second)
404{
405    int val = 0;
406
407    switch (first) {
408        case '0':
409        case '1':
410        case '2':
411        case '3':
412        case '4':
413        case '5':
414        case '6':
415        case '7':
416        case '8':
417        case '9':
418
419            val = 16 * (int(first) - 48);
420
421            break;
422
423        default:
424
425            if (first > 90)
426                first -= 32;
427
428            val = 16 * int(first) - 55;
429    }
430
431    switch (second) {
432        case '0':
433        case '1':
434        case '2':
435        case '3':
436        case '4':
437        case '5':
438        case '6':
439        case '7':
440        case '8':
441        case '9':
442
443            val += int(second) - 48;
444
445            break;
446
447        default:
448
449            if (second > 90)
450                second -= 32;
451
452            val += int(second) - 55;
453    }
454
455    return char(val);
456}
457
458//-------------------------------------------------------------------
459
460unsigned long
461code::hexToLong(const dodo::string &string)
462{
463    long i = string.size() - 1;
464    if (i < 0)
465        return 0;
466
467    unsigned long val = 0;
468
469    char first = string[i];
470    switch (first) {
471        case '0':
472        case '1':
473        case '2':
474        case '3':
475        case '4':
476        case '5':
477        case '6':
478        case '7':
479        case '8':
480        case '9':
481
482            val = int(first) - 48;
483
484            break;
485
486        case '\0':
487            return 0;
488
489        default:
490
491            if (first > 90)
492                first -= 32;
493
494            val = int(first) - 55;
495    }
496    --i;
497
498    for (long j = 1; i >= 0; --i, ++j) {
499        first = string[i];
500        switch (first) {
501            case '0':
502            case '1':
503            case '2':
504            case '3':
505            case '4':
506            case '5':
507            case '6':
508            case '7':
509            case '8':
510            case '9':
511
512                val += (2 << ((4 * j) - 1)) * (int(first) - 48);
513
514                break;
515
516            case '\0':
517                return val;
518
519            default:
520
521                if (first > 90)
522                    first -= 32;
523
524                val += (2 << ((4 * j) - 1)) * (int(first) - 55);
525        }
526    }
527
528    return val;
529}
530
531//-------------------------------------------------------------------
532
533void
534code::charToHex(char result[3],
535                char first)
536{
537    result[0] = hexEncodeChars[(first >> 4) & 0xf];
538    result[1] = hexEncodeChars[first & 0xf];
539
540    result[2] = '\0';
541}
542
543//-------------------------------------------------------------------
544
545dodo::string
546code::longToHex(unsigned long numeric)
547{
548    dodo::string hex;
549
550    for (long i = 2 * sizeof(unsigned long) - 1; i >= 0; --i)
551        hex += hexEncodeChars[(numeric >> i * 4) & 0xf];
552
553    return hex;
554}
555
556//-------------------------------------------------------------------
557
558dodo::string
559code::decodeUrl(const dodo::string &string)
560{
561    dodo::string result;
562    unsigned long o(0), k(string.size());
563
564    for (; o < k; ++o) {
565        switch (string[o]) {
566            case '+':
567                result += ' ';
568                break;
569
570            case '%':
571                if ((k - o) >= 2) {
572                    result += code::hexToChar(string[o + 1], string[o + 2]);
573                    o += 2;
574                } else {
575                    result += '%';
576                }
577                break;
578
579            default:
580                result += string[o];
581        }
582    }
583
584    return result;
585}
586
587//-------------------------------------------------------------------
588
589dodo::string
590code::encodeUrl(const dodo::string &string)
591{
592    dodo::string result;
593
594    unsigned long i(0), j(string.size());
595    char temp[3];
596
597    for (; i != j; ++i) {
598        switch (string[i]) {
599            case ' ':
600
601                result += '+';
602
603                break;
604
605            case 'A':
606            case 'B':
607            case 'C':
608            case 'D':
609            case 'E':
610            case 'F':
611            case 'G':
612            case 'H':
613            case 'I':
614            case 'J':
615            case 'K':
616            case 'L':
617            case 'M':
618            case 'N':
619            case 'O':
620            case 'P':
621            case 'Q':
622            case 'R':
623            case 'S':
624            case 'T':
625            case 'U':
626            case 'V':
627            case 'W':
628            case 'X':
629            case 'Y':
630            case 'Z':
631            case 'a':
632            case 'b':
633            case 'c':
634            case 'd':
635            case 'e':
636            case 'f':
637            case 'g':
638            case 'h':
639            case 'i':
640            case 'j':
641            case 'k':
642            case 'l':
643            case 'm':
644            case 'n':
645            case 'o':
646            case 'p':
647            case 'q':
648            case 'r':
649            case 's':
650            case 't':
651            case 'u':
652            case 'v':
653            case 'w':
654            case 'x':
655            case 'y':
656            case 'z':
657            case '0':
658            case '1':
659            case '2':
660            case '3':
661            case '4':
662            case '5':
663            case '6':
664            case '7':
665            case '8':
666            case '9':
667            case '-':
668            case '_':
669            case '.':
670            case '~':
671
672                result += string[i];
673
674                break;
675
676            default:
677
678                result += '%';
679                charToHex(temp, string[i]);
680                result += temp;
681        }
682    }
683
684    return result;
685}
686
687//-------------------------------------------------------------------
688
689void
690code::_encodeASCII85(dodo::string    &result,
691                     unsigned long tuple,
692                     int           count)
693{
694    short i(5);
695    char buf[5], *s = buf;
696
697    do {
698        *s++ = tuple % 85;
699        tuple /= 85;
700    } while (--i > 0);
701
702    i = count;
703    do
704        result += (char)(*--s + '!');
705    while (i-- > 0);
706}
707
708//-------------------------------------------------------------------
709
710dodo::string
711code::encodeASCII85(const dodo::string &string)
712{
713    dodo::string result("<~");
714    unsigned long tuple = 0;
715
716    unsigned short count(0);
717    int j = string.size();
718
719    for (int k(0); k < j; ++k) {
720        switch (count++) {
721            case 0:
722
723                tuple |= (string[k] << 24);
724
725                break;
726
727            case 1:
728
729                tuple |= (string[k] << 16);
730
731                break;
732
733            case 2:
734
735                tuple |= (string[k] <<  8);
736
737                break;
738
739            case 3:
740
741                tuple |= string[k];
742
743                if (tuple == 0)
744                    result += 'z';
745                else
746                    code::_encodeASCII85(result, tuple, count);
747
748                tuple = 0;
749                count = 0;
750
751                break;
752        }
753    }
754
755    if (count > 0)
756        code::_encodeASCII85(result, tuple, count);
757
758    result += "~>";
759
760    return result;
761}
762
763//-------------------------------------------------------------------
764
765void
766code::_decodeASCII85(dodo::string    &result,
767                     unsigned long tuple,
768                     int           count)
769{
770    switch (count) {
771        case 4:
772            result += (char)(tuple >> 24);
773            result += (char)(tuple >> 16);
774            result += (char)(tuple >>  8);
775            result += (char)(tuple);
776            break;
777
778        case 3:
779            result += (char)(tuple >> 24);
780            result += (char)(tuple >> 16);
781            result += (char)(tuple >>  8);
782            break;
783
784        case 2:
785            result += (char)(tuple >> 24);
786            result += (char)(tuple >> 16);
787            break;
788
789        case 1:
790            result += (char)(tuple >> 24);
791            break;
792    }
793}
794
795//-------------------------------------------------------------------
796
797dodo::string
798code::decodeASCII85(const dodo::string &string)
799{
800    unsigned long j = string.size(), count = 0, tuple = 0;
801    bool _break = false;
802    dodo::string result;
803
804    for (unsigned long k(0); k < j; ++k) {
805        if (string[k] == '<') {
806            if ((j - k) >= 1 && string[++k] == '~') {
807                _break = false;
808                while (!_break && k < j) {
809                    switch (string[++k]) {
810                        case 'z':
811
812                            if (count != 0)
813                                dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_DECODEASCII85, exception::ERRNO_LIBDODO, CODEEX_BADASCII85, TOOLSCODEEX_BADASCII85_STR, __LINE__, __FILE__);
814
815                            result += dodo::string('\0', 4);
816
817                            break;
818
819                        case '~':
820
821                            if ((k - j) >= 1 && string[++k] == '>') {
822                                if (count > 0) {
823                                    count--;
824                                    tuple += powASCII85[count];
825                                    _decodeASCII85(result, tuple, count);
826                                }
827                                ++k;
828                                _break = true;
829
830                                break;
831                            }
832
833                            dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_DECODEASCII85, exception::ERRNO_LIBDODO, CODEEX_BADASCII85, TOOLSCODEEX_BADASCII85_STR, __LINE__, __FILE__);
834
835                        case '\n':
836                        case '\r':
837                        case '\t':
838                        case ' ':
839                        case '\0':
840                        case '\f':
841                        case '\b':
842                        case 0177:
843
844                            break;
845
846                        default:
847
848                            if (string[k] < '!' || string[k] > 'u')
849                                dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_DECODEASCII85, exception::ERRNO_LIBDODO, CODEEX_BADASCII85, TOOLSCODEEX_BADASCII85_STR, __LINE__, __FILE__);
850
851                            tuple += (string[k] - '!') * powASCII85[count++];
852                            if (count == 5) {
853                                _decodeASCII85(result, tuple, 4);
854                                count = 0;
855                                tuple = 0;
856                            }
857                    }
858                }
859            } else {
860                result += '<';
861                result += string[k];
862            }
863        } else
864            result += string[k];
865    }
866
867    return result;
868}
869
870//-------------------------------------------------------------------
871
872void
873code::_encodeBase64(unsigned char in[3],
874                    unsigned char out[4],
875                    int           len)
876{
877    out[0] = base64EncodeChars[in[0] >> 2];
878    out[1] = base64EncodeChars[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
879    out[2] = (unsigned char)(len > 1 ? base64EncodeChars[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
880    out[3] = (unsigned char)(len > 2 ? base64EncodeChars[in[2] & 0x3f ] : '=');
881}
882
883//-------------------------------------------------------------------
884
885dodo::string
886code::encodeBase64(const dodo::string &string)
887{
888    unsigned long j = string.size();
889    unsigned char in[3], out[4];
890    unsigned short i, len;
891    dodo::string result;
892
893    for (unsigned long k(0); k < j;) {
894        len = 0;
895        for (i = 0; i < 3; ++i) {
896            ++k;
897            if (k <= j) {
898                in[i] = string[k - 1];
899                ++len;
900            } else
901                in[i] = 0;
902        }
903
904        if (len > 0) {
905            _encodeBase64(in, out, len);
906            for (i = 0; i < 4; ++i)
907                result += out[i];
908        }
909    }
910
911    return result;
912}
913
914//-------------------------------------------------------------------
915
916void
917code::_decodeBase64(unsigned char in[4],
918                    unsigned char out[3])
919{
920    out[0] = (unsigned char )(in[0] << 2 | in[1] >> 4);
921    out[1] = (unsigned char )(in[1] << 4 | in[2] >> 2);
922    out[2] = (unsigned char )(((in[2] << 6) & 0xc0) | in[3]);
923}
924
925//-------------------------------------------------------------------
926
927dodo::string
928code::decodeBase64(const dodo::string &string)
929{
930    unsigned long j = string.size() + 1;
931    unsigned char in[4], out[3], v;
932    unsigned short i, len;
933    dodo::string result;
934
935    for (unsigned long k(0); k < j;) {
936        len = 0;
937        for (len = 0, i = 0; i < 4 && k < j; ++i) {
938            v = 0;
939            while (k < j && v == 0) {
940                v = string[k++];
941                v = (unsigned char)((v < 43 || v > 122) ? 0 : base64DecodeChars[v - 43]);
942                if (v)
943                    v = (unsigned char)(v == '$' ? 0 : v - 61);
944            }
945
946            if (k < j) {
947                ++len;
948                if (v)
949                    in[i] = (unsigned char)(v - 1);
950            } else
951                in[i] = 0;
952        }
953
954        if (len > 0) {
955            _decodeBase64(in, out);
956            for (i = 0; i < len - 1; ++i)
957                result += out[i];
958        }
959    }
960
961    return result;
962}
963
964//-------------------------------------------------------------------
965
966dodo::__url__
967code::parseUrl(const dodo::string &url)
968{
969    unsigned long begin(0), pos, pos1;
970
971    __url__ temp;
972
973    if ((pos = url.find("://", 0)) != dodo::string::POSITION_END) {
974        temp.protocol = dodo::string(url.data(), pos);
975
976        begin = pos + 3;
977    }
978
979    if ((pos = url.find('@', begin)) != dodo::string::POSITION_END) {
980        if ((pos1 = url.find(':', begin)) < pos) {
981            temp.login = dodo::string(url.data() + begin, pos1 - begin);
982
983            ++pos1;
984
985            temp.password = dodo::string(url.data() + pos1, pos - pos1);
986        } else
987            temp.login = dodo::string(url.data() + begin, pos - begin);
988
989        begin = pos + 1;
990    }
991
992    if ((pos = url.find('/', begin)) != dodo::string::POSITION_END) {
993        if ((pos1 = url.find(':', begin)) < pos) {
994            temp.host = dodo::string(url.data() + begin, pos1 - begin);
995
996            ++pos1;
997
998            temp.port = dodo::string(url.data() + pos1, pos - pos1);
999        } else
1000            temp.host = dodo::string(url.data() + begin, pos - begin);
1001
1002        begin = pos + 1;
1003
1004        if ((pos = url.find('?', begin)) != dodo::string::POSITION_END) {
1005            temp.path = dodo::string(url.data() + begin, pos - begin);
1006            temp.request = dodo::string(url.data() + pos + 1, url.size() - pos - 1);
1007        } else
1008            temp.path = dodo::string(url.data() + begin, url.size() - begin);
1009    } else {
1010        if ((pos1 = url.find(':', begin)) != dodo::string::POSITION_END) {
1011            temp.host = dodo::string(url.data() + begin, pos1 - begin);
1012
1013            ++pos1;
1014
1015            temp.port = dodo::string(url.data() + pos1, url.size() - pos1);
1016        } else
1017            temp.host = dodo::string(url.data() + begin, url.size() - begin);
1018    }
1019
1020    return temp;
1021}
1022
1023//-------------------------------------------------------------------
1024
1025dodo::string
1026code::makeUrl(const __url__ &url)
1027{
1028    dodo::string stringUrl;
1029
1030    unsigned long logbs = url.login.size();
1031
1032    if (url.protocol.size() > 0) {
1033        stringUrl += dodo::string(url.protocol);
1034        stringUrl += dodo::string("://" );
1035    }
1036    if (logbs > 0)
1037        stringUrl += dodo::string(url.login);
1038    if (url.password.size() > 0) {
1039        stringUrl += dodo::string(":");
1040        stringUrl += dodo::string(url.password);
1041    }
1042    if (logbs > 0)
1043        stringUrl += dodo::string("@");
1044    stringUrl += dodo::string(url.host);
1045    if (url.port.size() > 0) {
1046        stringUrl += dodo::string(":");
1047        stringUrl += dodo::string(url.port);
1048    }
1049    stringUrl += dodo::string("/");
1050    stringUrl += dodo::string(url.path);
1051    if (url.request.size() > 0) {
1052        stringUrl += dodo::string("?");
1053        stringUrl += dodo::string(url.request);
1054    }
1055
1056    return stringUrl;
1057}
1058
1059//-------------------------------------------------------------------
1060
1061#ifdef BZIP2_EXT
1062dodo::string
1063code::bzCompress(const dodo::string &buffer,
1064                 unsigned short   level,
1065                 unsigned short   type)
1066{
1067    bz_stream bzs;
1068    int ret;
1069
1070    dodo::string strBuf;
1071    char *byteBuf;
1072
1073    bzs.bzalloc = NULL;
1074    bzs.bzfree = NULL;
1075    bzs.opaque = NULL;
1076
1077    ret = BZ2_bzCompressInit(&bzs, level, 0, type);
1078    if (ret != BZ_OK)
1079        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_BZCOMPRESS, exception::ERRNO_BZIP, CODEEX_BADBZCOMPRESSIONINIT, TOOLSCODEEX_BADBZCOMPRESSIONINIT_STR, __LINE__, __FILE__);
1080
1081    bzs.avail_in =  buffer.size();
1082    bzs.next_in = (char *)buffer.data();
1083
1084    byteBuf = new char[BZIP_CHUNK];
1085
1086    strBuf.clear();
1087
1088    do {
1089        bzs.avail_out = BZIP_CHUNK;
1090        bzs.next_out = byteBuf;
1091
1092        if ((ret = BZ2_bzCompress(&bzs, BZ_FINISH)) < 0) {
1093            delete [] byteBuf;
1094
1095            dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_BZCOMPRESS, exception::ERRNO_BZIP, CODEEX_BADBZCOMPRESSION, TOOLSCODEEX_BADBZCOMPRESSION_STR, __LINE__, __FILE__);
1096        }
1097
1098        strBuf += dodo::string((char *)byteBuf, BZIP_CHUNK - bzs.avail_out);
1099    } while (bzs.avail_out == 0);
1100
1101    delete [] byteBuf;
1102
1103    ret = BZ2_bzCompressEnd(&bzs);
1104    if (ret != BZ_OK)
1105        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_BZCOMPRESS, exception::ERRNO_BZIP, CODEEX_BADBZCOMPRESSIONFINISH, TOOLSCODEEX_BADBZCOMPRESSIONFINISH_STR, __LINE__, __FILE__);
1106
1107    return strBuf;
1108}
1109
1110//-------------------------------------------------------------------
1111
1112dodo::string
1113code::bzDecompress(const dodo::string &buffer)
1114{
1115    bz_stream bzs;
1116    int ret;
1117
1118    dodo::string strBuf;
1119    char *byteBuf;
1120
1121    bzs.bzalloc = NULL;
1122    bzs.bzfree = NULL;
1123    bzs.opaque = NULL;
1124
1125    ret = BZ2_bzDecompressInit(&bzs, 0, 0);
1126    if (ret != BZ_OK)
1127        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_BZDECOMPRESS, exception::ERRNO_BZIP, CODEEX_BADBZDECOMPRESSIONINIT, TOOLSCODEEX_BADBZDECOMPRESSIONINIT_STR, __LINE__, __FILE__);
1128
1129    byteBuf = new char[BZIP_CHUNK];
1130
1131    bzs.avail_in = buffer.size();
1132    bzs.next_in = (char *)buffer.data();
1133
1134    strBuf.clear();
1135
1136    do {
1137        bzs.avail_out = BZIP_CHUNK;
1138        bzs.next_out = byteBuf;
1139
1140        if ((ret = BZ2_bzDecompress(&bzs)) < 0) {
1141            delete [] byteBuf;
1142
1143            dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_BZDECOMPRESS, exception::ERRNO_BZIP, CODEEX_BADBZDECOMPRESSION, TOOLSCODEEX_BADBZDECOMPRESSION_STR, __LINE__, __FILE__);
1144        }
1145
1146        strBuf += dodo::string((char *)byteBuf, BZIP_CHUNK - bzs.avail_out);
1147    } while (bzs.avail_out == 0);
1148
1149    delete [] byteBuf;
1150
1151    ret = BZ2_bzDecompressEnd(&bzs);
1152    if (ret != BZ_OK)
1153        dodo_throw exception::basic(exception::MODULE_TOOLSCODE, CODEEX_BZDECOMPRESS, exception::ERRNO_BZIP, CODEEX_BADBZDECOMPRESSIONFINISH, TOOLSCODEEX_BADBZDECOMPRESSIONFINISH_STR, __LINE__, __FILE__);
1154
1155    return strBuf;
1156}
1157#endif
1158
1159//-------------------------------------------------------------------
1160
1161void
1162code::MD5Init(__MD5Context__ *context)
1163{
1164    context->count[0] = context->count[1] = 0;
1165
1166    context->state[0] = 0x67452301;
1167    context->state[1] = 0xefcdab89;
1168    context->state[2] = 0x98badcfe;
1169    context->state[3] = 0x10325476;
1170}
1171
1172//-------------------------------------------------------------------
1173
1174void
1175code::MD5Transform(unsigned int        state[4],
1176                   const unsigned char block[64])
1177{
1178    unsigned int a = state[0], b = state[1], c = state[2], d = state[3], x[16];
1179
1180    for (unsigned int i = 0, j = 0; j < 64; ++i, j += 4)
1181        x[i] = ((unsigned int)block[j]) | (((unsigned int)block[j + 1]) << 8) | (((unsigned int)block[j + 2]) << 16) | (((unsigned int)block[j + 3]) << 24);
1182
1183    FF(a, b, c, d, x[ 0], S11, 0xd76aa478);
1184    FF(d, a, b, c, x[ 1], S12, 0xe8c7b756);
1185    FF(c, d, a, b, x[ 2], S13, 0x242070db);
1186    FF(b, c, d, a, x[ 3], S14, 0xc1bdceee);
1187    FF(a, b, c, d, x[ 4], S11, 0xf57c0faf);
1188    FF(d, a, b, c, x[ 5], S12, 0x4787c62a);
1189    FF(c, d, a, b, x[ 6], S13, 0xa8304613);
1190    FF(b, c, d, a, x[ 7], S14, 0xfd469501);
1191    FF(a, b, c, d, x[ 8], S11, 0x698098d8);
1192    FF(d, a, b, c, x[ 9], S12, 0x8b44f7af);
1193    FF(c, d, a, b, x[10], S13, 0xffff5bb1);
1194    FF(b, c, d, a, x[11], S14, 0x895cd7be);
1195    FF(a, b, c, d, x[12], S11, 0x6b901122);
1196    FF(d, a, b, c, x[13], S12, 0xfd987193);
1197    FF(c, d, a, b, x[14], S13, 0xa679438e);
1198    FF(b, c, d, a, x[15], S14, 0x49b40821);
1199
1200    GG(a, b, c, d, x[ 1], S21, 0xf61e2562);
1201    GG(d, a, b, c, x[ 6], S22, 0xc040b340);
1202    GG(c, d, a, b, x[11], S23, 0x265e5a51);
1203    GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
1204    GG(a, b, c, d, x[ 5], S21, 0xd62f105d);
1205    GG(d, a, b, c, x[10], S22,  0x2441453);
1206    GG(c, d, a, b, x[15], S23, 0xd8a1e681);
1207    GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
1208    GG(a, b, c, d, x[ 9], S21, 0x21e1cde6);
1209    GG(d, a, b, c, x[14], S22, 0xc33707d6);
1210    GG(c, d, a, b, x[ 3], S23, 0xf4d50d87);
1211    GG(b, c, d, a, x[ 8], S24, 0x455a14ed);
1212    GG(a, b, c, d, x[13], S21, 0xa9e3e905);
1213    GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8);
1214    GG(c, d, a, b, x[ 7], S23, 0x676f02d9);
1215    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);
1216
1217    HH(a, b, c, d, x[ 5], S31, 0xfffa3942);
1218    HH(d, a, b, c, x[ 8], S32, 0x8771f681);
1219    HH(c, d, a, b, x[11], S33, 0x6d9d6122);
1220    HH(b, c, d, a, x[14], S34, 0xfde5380c);
1221    HH(a, b, c, d, x[ 1], S31, 0xa4beea44);
1222    HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9);
1223    HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60);
1224    HH(b, c, d, a, x[10], S34, 0xbebfbc70);
1225    HH(a, b, c, d, x[13], S31, 0x289b7ec6);
1226    HH(d, a, b, c, x[ 0], S32, 0xeaa127fa);
1227    HH(c, d, a, b, x[ 3], S33, 0xd4ef3085);
1228    HH(b, c, d, a, x[ 6], S34,  0x4881d05);
1229    HH(a, b, c, d, x[ 9], S31, 0xd9d4d039);
1230    HH(d, a, b, c, x[12], S32, 0xe6db99e5);
1231    HH(c, d, a, b, x[15], S33, 0x1fa27cf8);
1232    HH(b, c, d, a, x[ 2], S34, 0xc4ac5665);
1233
1234    II(a, b, c, d, x[ 0], S41, 0xf4292244);
1235    II(d, a, b, c, x[ 7], S42, 0x432aff97);
1236    II(c, d, a, b, x[14], S43, 0xab9423a7);
1237    II(b, c, d, a, x[ 5], S44, 0xfc93a039);
1238    II(a, b, c, d, x[12], S41, 0x655b59c3);
1239    II(d, a, b, c, x[ 3], S42, 0x8f0ccc92);
1240    II(c, d, a, b, x[10], S43, 0xffeff47d);
1241    II(b, c, d, a, x[ 1], S44, 0x85845dd1);
1242    II(a, b, c, d, x[ 8], S41, 0x6fa87e4f);
1243    II(d, a, b, c, x[15], S42, 0xfe2ce6e0);
1244    II(c, d, a, b, x[ 6], S43, 0xa3014314);
1245    II(b, c, d, a, x[13], S44, 0x4e0811a1);
1246    II(a, b, c, d, x[ 4], S41, 0xf7537e82);
1247    II(d, a, b, c, x[11], S42, 0xbd3af235);
1248    II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
1249    II(b, c, d, a, x[ 9], S44, 0xeb86d391);
1250
1251    state[0] += a;
1252    state[1] += b;
1253    state[2] += c;
1254    state[3] += d;
1255}
1256
1257//-------------------------------------------------------------------
1258
1259void
1260code::MD5Final(unsigned char  digest[16],
1261               __MD5Context__ *context)
1262{
1263    unsigned char bits[8];
1264    unsigned int index, padLen;
1265
1266    unsigned int i, j;
1267
1268    for (i = 0, j = 0; j < 8; ++i, j += 4) {
1269        bits[j] = (unsigned char)(context->count[i] & 0xff);
1270        bits[j + 1] = (unsigned char)((context->count[i] >> 8) & 0xff);
1271        bits[j + 2] = (unsigned char)((context->count[i] >> 16) & 0xff);
1272        bits[j + 3] = (unsigned char)((context->count[i] >> 24) & 0xff);
1273    }
1274
1275    index = (unsigned int)((context->count[0] >> 3) & 0x3f);
1276    padLen = index < 56 ? 56 - index : 120 - index;
1277    MD5Update(context, MD5Padding, padLen);
1278
1279    MD5Update(context, bits, 8);
1280
1281    for (i = 0, j = 0; j < 16; ++i, j += 4) {
1282        digest[j] = (unsigned char)(context->state[i] & 0xff);
1283        digest[j + 1] = (unsigned char)((context->state[i] >> 8) & 0xff);
1284        digest[j + 2] = (unsigned char)((context->state[i] >> 16) & 0xff);
1285        digest[j + 3] = (unsigned char)((context->state[i] >> 24) & 0xff);
1286    }
1287
1288    memset(context, 0, sizeof(__MD5Context__));
1289}
1290
1291//-------------------------------------------------------------------
1292
1293void
1294code::MD5Update(__MD5Context__      *context,
1295                const unsigned char *input,
1296                unsigned int        inputLen)
1297{
1298    unsigned int i, index, partLen;
1299
1300    index = (unsigned int )((context->count[0] >> 3) & 0x3F);
1301
1302    if ((context->count[0] += (inputLen << 3)) < (inputLen << 3))
1303        ++context->count[1];
1304
1305    context->count[1] += (inputLen >> 29);
1306
1307    partLen = 64 - index;
1308
1309    if (inputLen >= partLen) {
1310        memcpy(&context->buffer[index], input, partLen);
1311
1312        MD5Transform(context->state, context->buffer);
1313
1314        for (i = partLen; i + 63 < inputLen; i += 64)
1315            MD5Transform(context->state, &input[i]);
1316
1317        index = 0;
1318    } else
1319        i = 0;
1320
1321    memcpy(&context->buffer[index], &input[i], inputLen - i);
1322}
1323
1324//-------------------------------------------------------------------
1325
1326dodo::string
1327code::MD5(const dodo::string &string)
1328{
1329    __MD5Context__ context;
1330    unsigned char digest[16];
1331
1332    MD5Init(&context);
1333    MD5Update(&context, (unsigned char *)string.data(), string.size());
1334    MD5Final(digest, &context);
1335
1336    return dodo::string((char *)digest, 16);
1337}
1338
1339//-------------------------------------------------------------------
1340
1341dodo::string
1342code::MD5Hex(const dodo::string &string)
1343{
1344    return binToHex(MD5(string));
1345}
1346
1347//-------------------------------------------------------------------
1348
1349dodo::string
1350code::binToHex(const dodo::string &string)
1351{
1352    int j = string.size();
1353    dodo::string hex;
1354    char tmp[3];
1355
1356    for (int i = 0; i < j; ++i) {
1357        charToHex(tmp, string[i]);
1358        hex += dodo::string(tmp, 2);
1359    }
1360
1361    return hex;
1362}
1363
1364//-------------------------------------------------------------------
1365
1366void
1367code::SHA1Init(__SHA1_256Context__ *context)
1368{
1369    context->length = 0;
1370    context->messageBlockIndex = 0;
1371
1372        /* Initial Hash Values: FIPS-180-2 section 5.3.1 */
1373    context->intermediateHash[0] = 0x67452301;
1374    context->intermediateHash[1] = 0xEFCDAB89;
1375    context->intermediateHash[2] = 0x98BADCFE;
1376    context->intermediateHash[3] = 0x10325476;
1377    context->intermediateHash[4] = 0xC3D2E1F0;
1378}
1379
1380//-------------------------------------------------------------------
1381
1382void
1383code::SHA1Input(__SHA1_256Context__ *context,
1384                const unsigned char *bytes,
1385                unsigned int        bytecount)
1386{
1387    if (bytecount == 0)
1388        return;
1389
1390    while (bytecount--) {
1391        context->messageBlock[context->messageBlockIndex++] = (*bytes & 0xFF);
1392
1393        context->length += 8;
1394        if (context->messageBlockIndex == 64)
1395            SHA1ProcessMessageBlock(context);
1396
1397        ++bytes;
1398    }
1399}
1400
1401//-------------------------------------------------------------------
1402
1403void
1404code::SHA1Result(__SHA1_256Context__ *context,
1405                 unsigned char       digest[20])
1406{
1407    SHA1PadMessage(context, 0x80);
1408
1409    for (int i = 0; i < 20; ++i)
1410        digest[i] = context->intermediateHash[i >> 2] >> 8 * ( 3 - ( i & 0x03 ));
1411}
1412
1413//-------------------------------------------------------------------
1414
1415void
1416code::SHA1PadMessage(__SHA1_256Context__ *context,
1417                     unsigned char       padByte)
1418{
1419    if (context->messageBlockIndex >= 56) {
1420        context->messageBlock[context->messageBlockIndex++] = padByte;
1421
1422        while (context->messageBlockIndex < 64)
1423            context->messageBlock[context->messageBlockIndex++] = 0;
1424
1425        SHA1ProcessMessageBlock(context);
1426    } else {
1427        context->messageBlock[context->messageBlockIndex++] = padByte;
1428    }
1429
1430    while (context->messageBlockIndex < 56)
1431        context->messageBlock[context->messageBlockIndex++] = 0;
1432
1433    context->messageBlock[56] = context->length >> 56;
1434    context->messageBlock[57] = context->length >> 48;
1435    context->messageBlock[58] = context->length >> 40;
1436    context->messageBlock[59] = context->length >> 32;
1437    context->messageBlock[60] = context->length >> 24;
1438    context->messageBlock[61] = context->length >> 16;
1439    context->messageBlock[62] = context->length >> 8;
1440    context->messageBlock[63] = context->length;
1441
1442    SHA1ProcessMessageBlock(context);
1443}
1444
1445//-------------------------------------------------------------------
1446
1447void
1448code::SHA1ProcessMessageBlock(__SHA1_256Context__ *context)
1449{
1450        /* Constants defined in FIPS-180-2, section 4.2.1 */
1451    const static unsigned long K[4] = {
1452        0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
1453    };
1454
1455    int t;
1456    unsigned int temp;
1457    unsigned int W[80];
1458    unsigned int A, B, C, D, E;
1459
1460    for (t = 0; t < 16; ++t) {
1461        W[t]  = (unsigned int)context->messageBlock[t * 4] << 24;
1462        W[t] |= (unsigned int)context->messageBlock[t * 4 + 1] << 16;
1463        W[t] |= (unsigned int)context->messageBlock[t * 4 + 2] << 8;
1464        W[t] |= (unsigned int)context->messageBlock[t * 4 + 3];
1465    }
1466
1467    for (t = 16; t < 80; ++t)
1468        W[t] = SHA1_ROTL(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
1469
1470    A = context->intermediateHash[0];
1471    B = context->intermediateHash[1];
1472    C = context->intermediateHash[2];
1473    D = context->intermediateHash[3];
1474    E = context->intermediateHash[4];
1475
1476    for (t = 0; t < 20; ++t) {
1477        temp = SHA1_ROTL(5, A) + SHA_Ch(B, C, D) + E + W[t] + K[0];
1478        E = D;
1479        D = C;
1480        C = SHA1_ROTL(30, B);
1481        B = A;
1482        A = temp;
1483    }
1484
1485    for (t = 20; t < 40; ++t) {
1486        temp = SHA1_ROTL(5, A) + SHA_Parity(B, C, D) + E + W[t] + K[1];
1487        E = D;
1488        D = C;
1489        C = SHA1_ROTL(30, B);
1490        B = A;
1491        A = temp;
1492    }
1493
1494    for (t = 40; t < 60; ++t) {
1495        temp = SHA1_ROTL(5, A) + SHA_Maj(B, C, D) + E + W[t] + K[2];
1496        E = D;
1497        D = C;
1498        C = SHA1_ROTL(30, B);
1499        B = A;
1500        A = temp;
1501    }
1502
1503    for (t = 60; t < 80; ++t) {
1504        temp = SHA1_ROTL(5, A) + SHA_Parity(B, C, D) + E + W[t] + K[3];
1505        E = D;
1506        D = C;
1507        C = SHA1_ROTL(30, B);
1508        B = A;
1509        A = temp;
1510    }
1511
1512    context->intermediateHash[0] += A;
1513    context->intermediateHash[1] += B;
1514    context->intermediateHash[2] += C;
1515
1516    context->intermediateHash[3] += D;
1517    context->intermediateHash[4] += E;
1518
1519    context->messageBlockIndex = 0;
1520}
1521
1522//-------------------------------------------------------------------
1523
1524dodo::string
1525code::SHA1(const dodo::string &string)
1526{
1527    __SHA1_256Context__ context;
1528    unsigned char digest[20];
1529
1530    SHA1Init(&context);
1531    SHA1Input(&context, (unsigned char *)string.data(), string.size());
1532    SHA1Result(&context, digest);
1533
1534    return dodo::string((char *)digest, 20);
1535}
1536
1537//-------------------------------------------------------------------
1538
1539dodo::string
1540code::SHA1Hex(const dodo::string &string)
1541{
1542    return binToHex(SHA1(string));
1543}
1544
1545//-------------------------------------------------------------------
1546
1547void
1548code::SHA256Init(__SHA1_256Context__ *context)
1549{
1550    context->length = 0;
1551    context->messageBlockIndex = 0;
1552
1553        /* Initial Hash Values: FIPS-180-2 section 5.3.2 */
1554    context->intermediateHash[0] = 0x6A09E667;
1555    context->intermediateHash[1] = 0xBB67AE85;
1556    context->intermediateHash[2] = 0x3C6EF372;
1557    context->intermediateHash[3] = 0xA54FF53A;
1558    context->intermediateHash[4] = 0x510E527F;
1559    context->intermediateHash[5] = 0x9B05688C;
1560    context->intermediateHash[6] = 0x1F83D9AB;
1561    context->intermediateHash[7] = 0x5BE0CD19;
1562}
1563
1564//-------------------------------------------------------------------
1565
1566void
1567code::SHA256Input(__SHA1_256Context__ *context,
1568                  const unsigned char *bytes,
1569                  unsigned int        bytecount)
1570{
1571    if (bytecount == 0)
1572        return;
1573
1574    while (bytecount--) {
1575        context->messageBlock[context->messageBlockIndex++] = (*bytes & 0xFF);
1576
1577        context->length += 8;
1578        if (context->messageBlockIndex == 64)
1579            SHA256ProcessMessageBlock(context);
1580
1581        bytes++;
1582    }
1583}
1584
1585//-------------------------------------------------------------------
1586
1587void
1588code::SHA256Result(__SHA1_256Context__ *context,
1589                   unsigned char       digest[32])
1590{
1591    SHA256PadMessage(context, 0x80);
1592
1593    for (int i = 0; i < 32; ++i)
1594        digest[i] = (unsigned char)(context->intermediateHash[i >> 2] >> 8 * ( 3 - ( i & 0x03 )));
1595}
1596
1597//-------------------------------------------------------------------
1598
1599void
1600code::SHA256PadMessage(__SHA1_256Context__ *context,
1601                       unsigned char       padByte)
1602{
1603    if (context->messageBlockIndex >= 56) {
1604        context->messageBlock[context->messageBlockIndex++] = padByte;
1605
1606        while (context->messageBlockIndex < 64)
1607            context->messageBlock[context->messageBlockIndex++] = 0;
1608
1609        SHA256ProcessMessageBlock(context);
1610    } else
1611        context->messageBlock[context->messageBlockIndex++] = padByte;
1612
1613    while (context->messageBlockIndex < 56)
1614        context->messageBlock[context->messageBlockIndex++] = 0;
1615
1616    context->messageBlock[56] = context->length >> 56;
1617    context->messageBlock[57] = context->length >> 48;
1618    context->messageBlock[58] = context->length >> 40;
1619    context->messageBlock[59] = context->length >> 32;
1620    context->messageBlock[60] = context->length >> 24;
1621    context->messageBlock[61] = context->length >> 16;
1622    context->messageBlock[62] = context->length >> 8;
1623    context->messageBlock[63] = context->length;
1624
1625    SHA256ProcessMessageBlock(context);
1626}
1627
1628//-------------------------------------------------------------------
1629
1630void
1631code::SHA256ProcessMessageBlock(__SHA1_256Context__ *context)
1632{
1633        /* Constants defined in FIPS-180-2, section 4.2.2 */
1634    static const uint32_t K[64] = {
1635        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
1636        0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
1637        0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
1638        0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
1639        0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
1640        0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
1641        0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
1642        0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1643        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
1644        0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
1645        0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
1646        0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
1647        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1648    };
1649
1650    int t, t4;
1651    unsigned int temp1, temp2;
1652    unsigned int W[64];
1653    unsigned int A, B, C, D, E, F, G, H;
1654
1655    /*
1656     * Initialize the first 16 words in the array W
1657     */
1658    for (t = t4 = 0; t < 16; t++, t4 += 4) {
1659        W[t] = ((unsigned int)context->messageBlock[t4] << 24) |
1660               ((unsigned int)context->messageBlock[t4 + 1] << 16) |
1661               ((unsigned int)context->messageBlock[t4 + 2] << 8) |
1662               ((unsigned int)context->messageBlock[t4 + 3]);
1663    }
1664
1665    for (t = 16; t < 64; t++)
1666        W[t] = SHA256_sigma1(W[t - 2]) + W[t - 7] + SHA256_sigma0(W[t - 15]) + W[t - 16];
1667
1668    A = context->intermediateHash[0];
1669    B = context->intermediateHash[1];
1670    C = context->intermediateHash[2];
1671    D = context->intermediateHash[3];
1672    E = context->intermediateHash[4];
1673    F = context->intermediateHash[5];
1674    G = context->intermediateHash[6];
1675    H = context->intermediateHash[7];
1676
1677    for (t = 0; t < 64; t++) {
1678        temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
1679        temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
1680        H = G;
1681        G = F;
1682        F = E;
1683        E = D + temp1;
1684        D = C;
1685        C = B;
1686        B = A;
1687        A = temp1 + temp2;
1688    }
1689
1690    context->intermediateHash[0] += A;
1691    context->intermediateHash[1] += B;
1692    context->intermediateHash[2] += C;
1693    context->intermediateHash[3] += D;
1694    context->intermediateHash[4] += E;
1695    context->intermediateHash[5] += F;
1696    context->intermediateHash[6] += G;
1697    context->intermediateHash[7] += H;
1698
1699    context->messageBlockIndex = 0;
1700}
1701
1702//-------------------------------------------------------------------
1703
1704dodo::string
1705code::SHA256(const dodo::string &string)
1706{
1707    __SHA1_256Context__ context;
1708    unsigned char digest[32];
1709
1710    SHA256Init(&context);
1711    SHA256Input(&context, (unsigned char *)string.data(), string.size());
1712    SHA256Result(&context, digest);
1713
1714    return dodo::string((char *)digest, 32);
1715}
1716
1717//-------------------------------------------------------------------
1718
1719dodo::string
1720code::SHA256Hex(const dodo::string &string)
1721{
1722    return binToHex(SHA256(string));
1723}
1724
1725//-------------------------------------------------------------------
1726
1727void
1728code::SHA512Init(__SHA512Context__ *context)
1729{
1730    context->messageBlockIndex = 0;
1731
1732    context->lengthLow = context->lengthHigh = 0;
1733
1734    context->intermediateHash[0] = 0x6A09E667F3BCC908ULL;
1735    context->intermediateHash[1] = 0xBB67AE8584CAA73BULL;
1736    context->intermediateHash[2] = 0x3C6EF372FE94F82BULL;
1737    context->intermediateHash[3] = 0xA54FF53A5F1D36F1ULL;
1738    context->intermediateHash[4] = 0x510E527FADE682D1ULL;
1739    context->intermediateHash[5] = 0x9B05688C2B3E6C1FULL;
1740    context->intermediateHash[6] = 0x1F83D9ABFB41BD6BULL;
1741    context->intermediateHash[7] = 0x5BE0CD19137E2179ULL;
1742
1743    context->corrupted = false;
1744}
1745
1746//-------------------------------------------------------------------
1747
1748void
1749code::SHA512Input(__SHA512Context__   *context,
1750                  const unsigned char *bytes,
1751                  unsigned int        bytecount)
1752{
1753    if (bytecount == 0)
1754        return;
1755
1756    unsigned long addTemp;
1757#define SHA512AddLength(context, length) (addTemp = (context)->lengthLow, (context)->corrupted = (((context)->lengthLow += (length)) < addTemp) && (++(context)->lengthHigh == 0))
1758
1759    while (bytecount-- && !context->corrupted) {
1760        context->messageBlock[context->messageBlockIndex++] = (*bytes & 0xFF);
1761
1762        SHA512AddLength(context, 8);
1763        if (!context->corrupted && (context->messageBlockIndex == 128))
1764            SHA512ProcessMessageBlock(context);
1765
1766        bytes++;
1767    }
1768
1769#undef SHA512AddLength
1770}
1771
1772//-------------------------------------------------------------------
1773
1774void
1775code::SHA512Result(__SHA512Context__ *context,
1776                   unsigned char     digest[64])
1777{
1778    SHA512PadMessage(context, 0x80);
1779
1780    for (int i = -1, j = 0; i < 63; ++j) {
1781        digest[++i] = context->intermediateHash[j] >> 56;
1782        digest[++i] = context->intermediateHash[j] >> 48;
1783        digest[++i] = context->intermediateHash[j] >> 40;
1784        digest[++i] = context->intermediateHash[j] >> 32;
1785        digest[++i] = context->intermediateHash[j] >> 24;
1786        digest[++i] = context->intermediateHash[j] >> 16;
1787        digest[++i] = context->intermediateHash[j] >> 8;
1788        digest[++i] = context->intermediateHash[j];
1789    }
1790}
1791
1792//-------------------------------------------------------------------
1793
1794void
1795code::SHA512PadMessage(__SHA512Context__ *context,
1796                       unsigned char     padByte)
1797{
1798    if (context->messageBlockIndex >= 112) {
1799        context->messageBlock[context->messageBlockIndex++] = padByte;
1800
1801        while (context->messageBlockIndex < 128)
1802            context->messageBlock[context->messageBlockIndex++] = 0;
1803
1804        SHA512ProcessMessageBlock(context);
1805    } else
1806        context->messageBlock[context->messageBlockIndex++] = padByte;
1807
1808    while (context->messageBlockIndex < 112)
1809        context->messageBlock[context->messageBlockIndex++] = 0;
1810
1811    context->messageBlock[112] = context->lengthHigh >> 56;
1812    context->messageBlock[113] = context->lengthHigh >> 48;
1813    context->messageBlock[114] = context->lengthHigh >> 40;
1814    context->messageBlock[115] = context->lengthHigh >> 32;
1815    context->messageBlock[116] = context->lengthHigh >> 24;
1816    context->messageBlock[117] = context->lengthHigh >> 16;
1817    context->messageBlock[118] = context->lengthHigh >> 8;
1818    context->messageBlock[119] = context->lengthHigh;
1819
1820    context->messageBlock[120] = context->lengthLow >> 56;
1821    context->messageBlock[121] = context->lengthLow >> 48;
1822    context->messageBlock[122] = context->lengthLow >> 40;
1823    context->messageBlock[123] = context->lengthLow >> 32;
1824    context->messageBlock[124] = context->lengthLow >> 24;
1825    context->messageBlock[125] = context->lengthLow >> 16;
1826    context->messageBlock[126] = context->lengthLow >> 8;
1827    context->messageBlock[127] = context->lengthLow;
1828
1829    SHA512ProcessMessageBlock(context);
1830}
1831
1832//-------------------------------------------------------------------
1833
1834void
1835code::SHA512ProcessMessageBlock(__SHA512Context__ *context)
1836{
1837        /* Constants defined in FIPS-180-2, section 4.2.3 */
1838    const unsigned long long K[80] = {
1839        0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
1840        0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL, 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
1841        0xD807AA98A3030242ULL, 0x12835B0145706FBEULL, 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
1842        0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
1843        0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL, 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
1844        0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL, 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
1845        0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
1846        0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL, 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
1847        0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL, 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
1848        0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
1849        0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL, 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
1850        0xD192E819D6EF5218ULL, 0xD69906245565A910ULL, 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
1851        0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, 0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
1852        0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL, 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
1853        0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL, 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
1854        0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, 0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
1855        0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL, 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
1856        0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL, 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
1857        0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
1858        0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL, 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL
1859    };
1860
1861    int t, t8;
1862    unsigned long long temp1, temp2;
1863    unsigned long long W[80];
1864    unsigned long long A, B, C, D, E, F, G, H;
1865
1866    for (t = t8 = 0; t < 16; t8 += 8, ++t) {
1867        W[t] = ((unsigned long long)context->messageBlock[t8] << 56) |
1868               ((unsigned long long)context->messageBlock[t8 + 1] << 48) |
1869               ((unsigned long long)context->messageBlock[t8 + 2] << 40) |
1870               ((unsigned long long)context->messageBlock[t8 + 3] << 32) |
1871               ((unsigned long long)context->messageBlock[t8 + 4] << 24) |
1872               ((unsigned long long)context->messageBlock[t8 + 5] << 16) |
1873               ((unsigned long long)context->messageBlock[t8 + 6] <<  8) |
1874               ((unsigned long long)context->messageBlock[t8 + 7]);
1875    }
1876
1877    for (t = 16; t < 80; ++t)
1878        W[t] = SHA512_sigma1(W[t - 2]) + W[t - 7] + SHA512_sigma0(W[t - 15]) + W[t - 16];
1879
1880    A = context->intermediateHash[0];
1881    B = context->intermediateHash[1];
1882    C = context->intermediateHash[2];
1883    D = context->intermediateHash[3];
1884    E = context->intermediateHash[4];
1885    F = context->intermediateHash[5];
1886    G = context->intermediateHash[6];
1887    H = context->intermediateHash[7];
1888
1889    for (t = 0; t < 80; ++t) {
1890        temp1 = H + SHA512_SIGMA1(E) + SHA512_Ch(E, F, G) + K[t] + W[t];
1891
1892        temp2 = SHA512_SIGMA0(A) + SHA512_Maj(A, B, C);
1893
1894        H = G;
1895        G = F;
1896        F = E;
1897
1898        E = temp1 + D;
1899
1900        D = C;
1901        C = B;
1902        B = A;
1903
1904        A = temp1 + temp2;
1905    }
1906
1907    context->intermediateHash[0] += A;
1908    context->intermediateHash[1] += B;
1909    context->intermediateHash[2] += C;
1910    context->intermediateHash[3] += D;
1911    context->intermediateHash[4] += E;
1912    context->intermediateHash[5] += F;
1913    context->intermediateHash[6] += G;
1914    context->intermediateHash[7] += H;
1915
1916    context->messageBlockIndex = 0;
1917}
1918
1919//-------------------------------------------------------------------
1920
1921dodo::string
1922code::SHA512(const dodo::string &string)
1923{
1924    __SHA512Context__ context;
1925    unsigned char digest[64];
1926
1927    SHA512Init(&context);
1928    SHA512Input(&context, (unsigned char *)string.data(), string.size());
1929    SHA512Result(&context, digest);
1930
1931    return dodo::string((char *)digest, 64);
1932}
1933
1934//-------------------------------------------------------------------
1935
1936dodo::string
1937code::SHA512Hex(const dodo::string &string)
1938{
1939    return binToHex(SHA512(string));
1940}
1941
1942//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.