Code

e08bed0a6062a8ea31db59cdac65005c16d7e5f4
[inkscape.git] / src / pedro / pedroutil.cpp
1 /*
2  * Support classes for the Pedro mini-XMPP client
3  *
4  * Authors:
5  *   Bob Jamison
6  *
7  * Copyright (C) 2005-2006 Bob Jamison
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2.1 of the License, or (at your option) any later version.
13  *
14  *  This library 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 GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  */
25 #include <stdio.h>
26 #include <stdarg.h>
28 #include <sys/stat.h>
30 #include "pedroutil.h"
34 #ifdef __WIN32__
36 #include <windows.h>
38 #else /* UNIX */
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netdb.h>
44 #include <unistd.h>
45 #include <sys/ioctl.h>
47 #include <pthread.h>
49 #endif /* UNIX */
53 namespace Pedro
54 {
60 //########################################################################
61 //########################################################################
62 //# B A S E    6 4
63 //########################################################################
64 //########################################################################
67 //#################
68 //# ENCODER
69 //#################
72 static char *base64encode =
73     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
77 /**
78  * Writes the specified byte to the output buffer
79  */
80 void Base64Encoder::append(int ch)
81 {
82     outBuf   <<=  8;
83     outBuf   |=  (ch & 0xff);
84     bitCount +=  8;
85     if (bitCount >= 24)
86         {
87         int indx  = (int)((outBuf & 0x00fc0000L) >> 18);
88         int obyte = (int)base64encode[indx & 63];
89         buf.push_back(obyte);
91         indx      = (int)((outBuf & 0x0003f000L) >> 12);
92         obyte     = (int)base64encode[indx & 63];
93         buf.push_back(obyte);
95         indx      = (int)((outBuf & 0x00000fc0L) >>  6);
96         obyte     = (int)base64encode[indx & 63];
97         buf.push_back(obyte);
99         indx      = (int)((outBuf & 0x0000003fL)      );
100         obyte     = (int)base64encode[indx & 63];
101         buf.push_back(obyte);
103         bitCount = 0;
104         outBuf   = 0L;
105         }
108 /**
109  * Writes the specified string to the output buffer
110  */
111 void Base64Encoder::append(char *str)
113     while (*str)
114         append((int)*str++);
117 /**
118  * Writes the specified string to the output buffer
119  */
120 void Base64Encoder::append(unsigned char *str, int len)
122     while (len>0)
123         {
124         append((int)*str++);
125         len--;
126         }
129 /**
130  * Writes the specified string to the output buffer
131  */
132 void Base64Encoder::append(const DOMString &str)
134     append((char *)str.c_str());
137 /**
138  * Closes this output stream and releases any system resources
139  * associated with this stream.
140  */
141 DOMString Base64Encoder::finish()
143     //get any last bytes (1 or 2) out of the buffer
144     if (bitCount == 16)
145         {
146         outBuf <<= 2;  //pad to make 18 bits
148         int indx  = (int)((outBuf & 0x0003f000L) >> 12);
149         int obyte = (int)base64encode[indx & 63];
150         buf.push_back(obyte);
152         indx      = (int)((outBuf & 0x00000fc0L) >>  6);
153         obyte     = (int)base64encode[indx & 63];
154         buf.push_back(obyte);
156         indx      = (int)((outBuf & 0x0000003fL)      );
157         obyte     = (int)base64encode[indx & 63];
158         buf.push_back(obyte);
160         buf.push_back('=');
161         }
162     else if (bitCount == 8)
163         {
164         outBuf <<= 4; //pad to make 12 bits
166         int indx  = (int)((outBuf & 0x00000fc0L) >>  6);
167         int obyte = (int)base64encode[indx & 63];
168         buf.push_back(obyte);
170         indx      = (int)((outBuf & 0x0000003fL)      );
171         obyte     = (int)base64encode[indx & 63];
172         buf.push_back(obyte);
174         buf.push_back('=');
175         buf.push_back('=');
176         }
178     DOMString ret = buf;
179     reset();
180     return ret;
184 DOMString Base64Encoder::encode(const DOMString &str)
186     Base64Encoder encoder;
187     encoder.append(str);
188     DOMString ret = encoder.finish();
189     return ret;
194 //#################
195 //# DECODER
196 //#################
198 static int base64decode[] =
200 /*00*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
201 /*08*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
202 /*10*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
203 /*18*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
204 /*20*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
205 /*28*/    -1,   -1,   -1,   62,   -1,   -1,   -1,   63,
206 /*30*/    52,   53,   54,   55,   56,   57,   58,   59,
207 /*38*/    60,   61,   -1,   -1,   -1,   -1,   -1,   -1,
208 /*40*/    -1,    0,    1,    2,    3,    4,    5,    6,
209 /*48*/     7,    8,    9,   10,   11,   12,   13,   14,
210 /*50*/    15,   16,   17,   18,   19,   20,   21,   22,
211 /*58*/    23,   24,   25,   -1,   -1,   -1,   -1,   -1,
212 /*60*/    -1,   26,   27,   28,   29,   30,   31,   32,
213 /*68*/    33,   34,   35,   36,   37,   38,   39,   40,
214 /*70*/    41,   42,   43,   44,   45,   46,   47,   48,
215 /*78*/    49,   50,   51,   -1,   -1,   -1,   -1,   -1
216 };
220 /**
221  * Appends one char to the decoder
222  */
223 void Base64Decoder::append(int ch)
225     if (isspace(ch))
226         return;
227     else if (ch == '=') //padding
228         {
229         inBytes[inCount++] = 0;
230         }
231     else
232         {
233         int byteVal = base64decode[ch & 0x7f];
234         //printf("char:%c %d\n", ch, byteVal);
235         if (byteVal < 0)
236             {
237             //Bad lookup value
238             }
239         inBytes[inCount++] = byteVal;
240         }
242     if (inCount >=4 )
243         {
244         unsigned char b0 = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);
245         unsigned char b1 = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);
246         unsigned char b2 = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3]   ) & 0x3f);
247         buf.push_back(b0);
248         buf.push_back(b1);
249         buf.push_back(b2);
250         inCount = 0;
251         }
255 void Base64Decoder::append(char *str)
257     while (*str)
258         append((int)*str++);
261 void Base64Decoder::append(const DOMString &str)
263     append((char *)str.c_str());
266 std::vector<unsigned char> Base64Decoder::finish()
268     std::vector<unsigned char> ret = buf;
269     reset();
270     return ret;
273 std::vector<unsigned char> Base64Decoder::decode(const DOMString &str)
275     Base64Decoder decoder;
276     decoder.append(str);
277     std::vector<unsigned char> ret = decoder.finish();
278     return ret;
281 DOMString Base64Decoder::decodeToString(const DOMString &str)
283     Base64Decoder decoder;
284     decoder.append(str);
285     std::vector<unsigned char> ret = decoder.finish();
286     DOMString buf;
287     for (unsigned int i=0 ; i<ret.size() ; i++)
288         buf.push_back(ret[i]);
289     return buf;
298 //########################################################################
299 //########################################################################
300 //### S H A    1      H A S H I N G
301 //########################################################################
302 //########################################################################
307 void Sha1::hash(unsigned char *dataIn, int len, unsigned char *digest)
309     Sha1 sha1;
310     sha1.append(dataIn, len);
311     sha1.finish(digest);
314 static char *sha1hex = "0123456789abcdef";
316 DOMString Sha1::hashHex(unsigned char *dataIn, int len)
318     unsigned char hashout[20];
319     hash(dataIn, len, hashout);
320     DOMString ret;
321     for (int i=0 ; i<20 ; i++)
322         {
323         unsigned char ch = hashout[i];
324         ret.push_back(sha1hex[ (ch>>4) & 15 ]);
325         ret.push_back(sha1hex[ ch      & 15 ]);
326         }
327     return ret;
331 void Sha1::init()
334     lenW   = 0;
335     sizeHi = 0;
336     sizeLo = 0;
338     // Initialize H with the magic constants (see FIPS180 for constants)
339     H[0] = 0x67452301L;
340     H[1] = 0xefcdab89L;
341     H[2] = 0x98badcfeL;
342     H[3] = 0x10325476L;
343     H[4] = 0xc3d2e1f0L;
345     for (int i = 0; i < 80; i++)
346         W[i] = 0;
350 void Sha1::append(unsigned char *dataIn, int len)
352     // Read the data into W and process blocks as they get full
353     for (int i = 0; i < len; i++)
354         {
355         W[lenW / 4] <<= 8;
356         W[lenW / 4] |= (unsigned long)dataIn[i];
357         if ((++lenW) % 64 == 0)
358             {
359             hashblock();
360             lenW = 0;
361             }
362         sizeLo += 8;
363         sizeHi += (sizeLo < 8);
364         }
368 void Sha1::finish(unsigned char hashout[20])
370     unsigned char pad0x80 = 0x80;
371     unsigned char pad0x00 = 0x00;
372     unsigned char padlen[8];
374     // Pad with a binary 1 (e.g. 0x80), then zeroes, then length
375     padlen[0] = (unsigned char)((sizeHi >> 24) & 255);
376     padlen[1] = (unsigned char)((sizeHi >> 16) & 255);
377     padlen[2] = (unsigned char)((sizeHi >>  8) & 255);
378     padlen[3] = (unsigned char)((sizeHi >>  0) & 255);
379     padlen[4] = (unsigned char)((sizeLo >> 24) & 255);
380     padlen[5] = (unsigned char)((sizeLo >> 16) & 255);
381     padlen[6] = (unsigned char)((sizeLo >>  8) & 255);
382     padlen[7] = (unsigned char)((sizeLo >>  0) & 255);
384     append(&pad0x80, 1);
386     while (lenW != 56)
387         append(&pad0x00, 1);
388     append(padlen, 8);
390     // Output hash
391     for (int i = 0; i < 20; i++)
392         {
393         hashout[i] = (unsigned char)(H[i / 4] >> 24);
394         H[i / 4] <<= 8;
395         }
397     // Re-initialize the context (also zeroizes contents)
398     init();
402 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
404 void Sha1::hashblock()
407     for (int t = 16; t <= 79; t++)
408         W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
410     unsigned long A = H[0];
411     unsigned long B = H[1];
412     unsigned long C = H[2];
413     unsigned long D = H[3];
414     unsigned long E = H[4];
416     unsigned long TEMP;
418     for (int t = 0; t <= 19; t++)
419         {
420         TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) +
421                 E + W[t] + 0x5a827999L) & 0xffffffffL;
422         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
423         }
424     for (int t = 20; t <= 39; t++)
425         {
426         TEMP = (SHA_ROTL(A,5) + (B^C^D) +
427                 E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
428         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
429         }
430     for (int t = 40; t <= 59; t++)
431         {
432         TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) +
433                 E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
434         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
435         }
436     for (int t = 60; t <= 79; t++)
437         {
438         TEMP = (SHA_ROTL(A,5) + (B^C^D) +
439                 E + W[t] + 0xca62c1d6L) & 0xffffffffL;
440         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
441         }
443     H[0] += A;
444     H[1] += B;
445     H[2] += C;
446     H[3] += D;
447     H[4] += E;
455 //########################################################################
456 //########################################################################
457 //### M D 5      H A S H I N G
458 //########################################################################
459 //########################################################################
465 void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
467     Md5 md5;
468     md5.append(dataIn, len);
469     md5.finish(digest);
472 DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
474     Md5 md5;
475     md5.append(dataIn, len);
476     DOMString ret = md5.finishHex();
477     return ret;
482 /*
483  * Note: this code is harmless on little-endian machines.
484  */
485 /*
486 static void byteReverse(unsigned char *buf, unsigned long longs)
488     do
489         {
490         unsigned long t = (unsigned long)
491             ((unsigned) buf[3] << 8 | buf[2]) << 16 |
492             ((unsigned) buf[1] << 8 | buf[0]);
493         *(unsigned long *) buf = t;
494         buf += 4;
495         } while (--longs);
497 */
499 static void md5_memcpy(void *dest, void *src, int n)
501     unsigned char *s1 = (unsigned char *)dest;
502     unsigned char *s2 = (unsigned char *)src;
503     while (n--)
504         *s1++ = *s2++;
507 static void md5_memset(void *dest, char v, int n)
509     unsigned char *s = (unsigned char *)dest;
510     while (n--)
511         *s++ = v;
514 /**
515  * Initialize MD5 polynomials and storage
516  */
517 void Md5::init()
519     buf[0]  = 0x67452301;
520     buf[1]  = 0xefcdab89;
521     buf[2]  = 0x98badcfe;
522     buf[3]  = 0x10325476;
524     bits[0] = 0;
525     bits[1] = 0;
528 /*
529  * Update context to reflect the concatenation of another buffer full
530  * of bytes.
531  */
532 void Md5::append(unsigned char *source, unsigned long len)
535     // Update bitcount
536     unsigned long t = bits[0];
537     if ((bits[0] = t + ((unsigned long) len << 3)) < t)
538             bits[1]++;// Carry from low to high
539     bits[1] += len >> 29;
541         //Bytes already in shsInfo->data
542     t = (t >> 3) & 0x3f;
545     // Handle any leading odd-sized chunks
546     if (t)
547         {
548         unsigned char *p = (unsigned char *) in + t;
549         t = 64 - t;
550         if (len < t)
551             {
552             md5_memcpy(p, source, len);
553             return;
554             }
555         md5_memcpy(p, source, t);
556         //byteReverse(in, 16);
557         transform(buf, (unsigned long *) in);
558         source += t;
559         len    -= t;
560         }
562     // Process data in 64-byte chunks
563     while (len >= 64)
564         {
565         md5_memcpy(in, source, 64);
566         //byteReverse(in, 16);
567         transform(buf, (unsigned long *) in);
568         source += 64;
569         len    -= 64;
570         }
572     // Handle any remaining bytes of data.
573     md5_memcpy(in, source, len);
576 /*
577  * Update context to reflect the concatenation of another string
578  */
579 void Md5::append(const DOMString &str)
581     append((unsigned char *)str.c_str(), str.size());
584 /*
585  * Update context to reflect the concatenation of a single character
586  */
587 void Md5::append(unsigned char ch)
589     append(&ch, 1);
592 /*
593  * Final wrapup - pad to 64-byte boundary with the bit pattern
594  * 1 0* (64-bit count of bits processed, MSB-first)
595  */
596 void Md5::finish(unsigned char *digest)
598     // Compute number of bytes mod 64
599     unsigned int count = (bits[0] >> 3) & 0x3F;
601     // Set the first char of padding to 0x80.
602     // This is safe since there is always at least one byte free
603     unsigned char *p = in + count;
604     *p++ = 0x80;
606     // Bytes of padding needed to make 64 bytes
607     count = 64 - 1 - count;
609     // Pad out to 56 mod 64
610     if (count < 8)
611         {
612             // Two lots of padding:  Pad the first block to 64 bytes
613             md5_memset(p, 0, count);
614             //byteReverse(in, 16);
615             transform(buf, (unsigned long *) in);
617             // Now fill the next block with 56 bytes
618             md5_memset(in, 0, 56);
619         }
620     else
621         {
622         // Pad block to 56 bytes
623         md5_memset(p, 0, count - 8);
624         }
625     //byteReverse(in, 14);
627     // Append length in bits and transform
628     ((unsigned long *) in)[14] = bits[0];
629     ((unsigned long *) in)[15] = bits[1];
631     transform(buf, (unsigned long *) in);
632     //byteReverse((unsigned char *) buf, 4);
633     md5_memcpy(digest, buf, 16);
634     init();  // Security!  ;-)
637 static char *md5hex = "0123456789abcdef";
639 DOMString Md5::finishHex()
641     unsigned char hashout[16];
642     finish(hashout);
643     DOMString ret;
644     for (int i=0 ; i<16 ; i++)
645         {
646         unsigned char ch = hashout[i];
647         ret.push_back(md5hex[ (ch>>4) & 15 ]);
648         ret.push_back(md5hex[ ch      & 15 ]);
649         }
650     return ret;
655 //#  The four core functions - F1 is optimized somewhat
657 //  #define F1(x, y, z) (x & y | ~x & z)
658 #define F1(x, y, z) (z ^ (x & (y ^ z)))
659 #define F2(x, y, z) F1(z, x, y)
660 #define F3(x, y, z) (x ^ y ^ z)
661 #define F4(x, y, z) (y ^ (x | ~z))
663 // ## This is the central step in the MD5 algorithm.
664 #define MD5STEP(f, w, x, y, z, data, s) \
665         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
667 /*
668  * The core of the MD5 algorithm, this alters an existing MD5 hash to
669  * reflect the addition of 16 longwords of new data.  MD5Update blocks
670  * the data and converts bytes into longwords for this routine.
671  * @parm buf points to an array of 4 unsigned longs
672  * @parm in points to an array of 16 unsigned longs
673  */
674 void Md5::transform(unsigned long *buf, unsigned long *in)
676     unsigned long a = buf[0];
677     unsigned long b = buf[1];
678     unsigned long c = buf[2];
679     unsigned long d = buf[3];
681     MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
682     MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
683     MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
684     MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
685     MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
686     MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
687     MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
688     MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
689     MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
690     MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
691     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
692     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
693     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
694     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
695     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
696     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
698     MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
699     MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
700     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
701     MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
702     MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
703     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
704     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
705     MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
706     MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
707     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
708     MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
709     MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
710     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
711     MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
712     MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
713     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
715     MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
716     MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
717     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
718     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
719     MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
720     MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
721     MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
722     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
723     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
724     MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
725     MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
726     MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
727     MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
728     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
729     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
730     MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
732     MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
733     MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
734     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
735     MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
736     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
737     MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
738     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
739     MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
740     MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f,  6);
741     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
742     MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
743     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
744     MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82,  6);
745     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
746     MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
747     MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
749     buf[0] += a;
750     buf[1] += b;
751     buf[2] += c;
752     buf[3] += d;
764 //########################################################################
765 //########################################################################
766 //### T H R E A D
767 //########################################################################
768 //########################################################################
774 #ifdef __WIN32__
777 static DWORD WINAPI WinThreadFunction(LPVOID context)
779     Thread *thread = (Thread *)context;
780     thread->execute();
781     return 0;
785 void Thread::start()
787     DWORD dwThreadId;
788     HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
789                (LPVOID)this,  0,  &dwThreadId);
790     //Make sure the thread is started before 'this' is deallocated
791     while (!started)
792         sleep(10);
793     CloseHandle(hThread);
796 void Thread::sleep(unsigned long millis)
798     Sleep(millis);
801 #else /* UNIX */
804 void *PthreadThreadFunction(void *context)
806     Thread *thread = (Thread *)context;
807     thread->execute();
808     return NULL;
812 void Thread::start()
814     pthread_t thread;
816     int ret = pthread_create(&thread, NULL,
817             PthreadThreadFunction, (void *)this);
818     if (ret != 0)
819         printf("Thread::start: thread creation failed: %s\n", strerror(ret));
821     //Make sure the thread is started before 'this' is deallocated
822     while (!started)
823         sleep(10);
827 void Thread::sleep(unsigned long millis)
829     timespec requested;
830     requested.tv_sec = millis / 1000;
831     requested.tv_nsec = (millis % 1000 ) * 1000000L;
832     nanosleep(&requested, NULL);
835 #endif
844 //########################################################################
845 //########################################################################
846 //### S O C K E T
847 //########################################################################
848 //########################################################################
854 //#########################################################################
855 //# U T I L I T Y
856 //#########################################################################
858 static void mybzero(void *s, size_t n)
860     unsigned char *p = (unsigned char *)s;
861     while (n > 0)
862         {
863         *p++ = (unsigned char)0;
864         n--;
865         }
868 static void mybcopy(void *src, void *dest, size_t n)
870     unsigned char *p = (unsigned char *)dest;
871     unsigned char *q = (unsigned char *)src;
872     while (n > 0)
873         {
874         *p++ = *q++;
875         n--;
876         }
881 //#########################################################################
882 //# T C P    C O N N E C T I O N
883 //#########################################################################
885 TcpSocket::TcpSocket()
887     init();
891 TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
893     init();
894     hostname  = hostnameArg;
895     portno    = port;
899 #ifdef HAVE_SSL
901 static void cryptoLockCallback(int mode, int type, const char *file, int line)
903     //printf("########### LOCK\n");
904     static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
905     const char *errstr = NULL;
907     int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
908     if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
909         {
910         errstr = "invalid mode";
911         goto err;
912         }
914     if (type < 0 || type >= CRYPTO_NUM_LOCKS)
915         {
916         errstr = "type out of bounds";
917         goto err;
918         }
920     if (mode & CRYPTO_LOCK)
921         {
922         if (modes[type])
923             {
924             errstr = "already locked";
925             /* must not happen in a single-threaded program
926              * (would deadlock)
927              */
928             goto err;
929             }
931         modes[type] = rw;
932         }
933     else if (mode & CRYPTO_UNLOCK)
934         {
935         if (!modes[type])
936             {
937              errstr = "not locked";
938              goto err;
939              }
941         if (modes[type] != rw)
942             {
943             errstr = (rw == CRYPTO_READ) ?
944                   "CRYPTO_r_unlock on write lock" :
945                   "CRYPTO_w_unlock on read lock";
946             }
948         modes[type] = 0;
949         }
950     else
951         {
952         errstr = "invalid mode";
953         goto err;
954         }
956     err:
957     if (errstr)
958         {
959         /* we cannot use bio_err here */
960         fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
961                 errstr, mode, type, file, line);
962         }
965 static unsigned long cryptoIdCallback()
967 #ifdef __WIN32__
968     unsigned long ret = (unsigned long) GetCurrentThreadId();
969 #else
970     unsigned long ret = (unsigned long) pthread_self();
971 #endif
972     return ret;
975 #endif
978 TcpSocket::TcpSocket(const TcpSocket &other)
980     init();
981     sock      = other.sock;
982     hostname  = other.hostname;
983     portno    = other.portno;
986 static bool tcp_socket_inited = false;
988 void TcpSocket::init()
990     if (!tcp_socket_inited)
991         {
992 #ifdef __WIN32__
993         WORD wVersionRequested = MAKEWORD( 2, 2 );
994         WSADATA wsaData;
995         WSAStartup( wVersionRequested, &wsaData );
996 #endif
997 #ifdef HAVE_SSL
998         sslStream  = NULL;
999         sslContext = NULL;
1000             CRYPTO_set_locking_callback(cryptoLockCallback);
1001         CRYPTO_set_id_callback(cryptoIdCallback);
1002         SSL_library_init();
1003         SSL_load_error_strings();
1004 #endif
1005         tcp_socket_inited = true;
1006         }
1007     sock           = -1;
1008     connected      = false;
1009     hostname       = "";
1010     portno         = -1;
1011     sslEnabled     = false;
1012     receiveTimeout = 0;
1015 TcpSocket::~TcpSocket()
1017     disconnect();
1020 bool TcpSocket::isConnected()
1022     if (!connected || sock < 0)
1023         return false;
1024     return true;
1027 bool TcpSocket::getHaveSSL()
1029 #ifdef HAVE_SSL
1030     return true;
1031 #else
1032     return false;
1033 #endif
1036 void TcpSocket::enableSSL(bool val)
1038     sslEnabled = val;
1041 bool TcpSocket::getEnableSSL()
1043     return sslEnabled;
1048 bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1050     hostname = hostnameArg;
1051     portno   = portnoArg;
1052     return connect();
1057 #ifdef HAVE_SSL
1058 /*
1059 static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1061     char *password = "password";
1062     if (bufLen < (int)(strlen(password)+1))
1063         return 0;
1065     strcpy(buf,password);
1066     int ret = strlen(password);
1067     return ret;
1070 static void infoCallback(const SSL *ssl, int where, int ret)
1072     switch (where)
1073         {
1074         case SSL_CB_ALERT:
1075             {
1076             printf("## %d SSL ALERT: %s\n",  where, SSL_alert_desc_string_long(ret));
1077             break;
1078             }
1079         default:
1080             {
1081             printf("## %d SSL: %s\n",  where, SSL_state_string_long(ssl));
1082             break;
1083             }
1084         }
1086 */
1087 #endif
1090 bool TcpSocket::startTls()
1092 #ifndef HAVE_SSL
1093     fprintf(stderr,
1094             "SSL starttls() error:  client not compiled with SSL enabled\n");
1095     return false;
1096 #else /*HAVE_SSL*/
1098     sslStream  = NULL;
1099     sslContext = NULL;
1101     //SSL_METHOD *meth = SSLv23_method();
1102     //SSL_METHOD *meth = SSLv3_client_method();
1103     SSL_METHOD *meth = TLSv1_client_method();
1104     sslContext = SSL_CTX_new(meth);
1105     //SSL_CTX_set_info_callback(sslContext, infoCallback);
1107     /**
1108      * For now, let's accept all connections.  Ignore this
1109      * block of code     
1110      *       
1111     char *keyFile  = "client.pem";
1112     char *caList   = "root.pem";
1113     //#  Load our keys and certificates
1114     if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1115         {
1116         fprintf(stderr, "Can't read certificate file\n");
1117         disconnect();
1118         return false;
1119         }
1121     SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1123     if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1124         {
1125         fprintf(stderr, "Can't read key file\n");
1126         disconnect();
1127         return false;
1128         }
1130     //## Load the CAs we trust
1131     if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1132         {
1133         fprintf(stderr, "Can't read CA list\n");
1134         disconnect();
1135         return false;
1136         }
1137     */
1139     /* Connect the SSL socket */
1140     sslStream  = SSL_new(sslContext);
1141     SSL_set_fd(sslStream, sock);
1143     int ret = SSL_connect(sslStream);
1144     if (ret == 0)
1145         {
1146         fprintf(stderr, "SSL connection not successful\n");
1147         disconnect();
1148         return false;
1149         }
1150     else if (ret < 0)
1151         {
1152         int err = SSL_get_error(sslStream, ret);
1153         fprintf(stderr, "SSL connect error %d\n", err);
1154         disconnect();
1155         return false;
1156         }
1158     sslEnabled = true;
1159     return true;
1160 #endif /* HAVE_SSL */
1164 bool TcpSocket::connect()
1166     if (hostname.size()<1)
1167         {
1168         fprintf(stderr, "open: null hostname\n");
1169         return false;
1170         }
1172     if (portno<1)
1173         {
1174         fprintf(stderr, "open: bad port number\n");
1175         return false;
1176         }
1178     sock = socket(PF_INET, SOCK_STREAM, 0);
1179     if (sock < 0)
1180         {
1181         fprintf(stderr, "open: error creating socket\n");
1182         return false;
1183         }
1185     char *c_hostname = (char *)hostname.c_str();
1186     struct hostent *server = gethostbyname(c_hostname);
1187     if (!server)
1188         {
1189         fprintf(stderr, "open: could not locate host '%s'\n", c_hostname);
1190         return false;
1191         }
1193     struct sockaddr_in serv_addr;
1194     mybzero((char *) &serv_addr, sizeof(serv_addr));
1195     serv_addr.sin_family = AF_INET;
1196     mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1197          server->h_length);
1198     serv_addr.sin_port = htons(portno);
1200     int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1201     if (ret < 0)
1202         {
1203         fprintf(stderr, "open: could not connect to host '%s'\n", c_hostname);
1204         return false;
1205         }
1207      if (sslEnabled)
1208         {
1209         if (!startTls())
1210             return false;
1211         }
1212     connected = true;
1213     return true;
1216 bool TcpSocket::disconnect()
1218     bool ret  = true;
1219     connected = false;
1220 #ifdef HAVE_SSL
1221     if (sslEnabled)
1222         {
1223         if (sslStream)
1224             {
1225             int r = SSL_shutdown(sslStream);
1226             switch(r)
1227                 {
1228                 case 1:
1229                     break; /* Success */
1230                 case 0:
1231                 case -1:
1232                 default:
1233                     //printf("Shutdown failed");
1234                     ret = false;
1235                 }
1236             SSL_free(sslStream);
1237             }
1238         if (sslContext)
1239             SSL_CTX_free(sslContext);
1240         }
1241     sslStream  = NULL;
1242     sslContext = NULL;
1243 #endif /*HAVE_SSL*/
1245 #ifdef __WIN32__
1246     closesocket(sock);
1247 #else
1248     ::close(sock);
1249 #endif
1250     sock = -1;
1251     sslEnabled = false;
1253     return ret;
1258 bool TcpSocket::setReceiveTimeout(unsigned long millis)
1260     receiveTimeout = millis;
1261     return true;
1264 /**
1265  * For normal sockets, return the number of bytes waiting to be received.
1266  * For SSL, just return >0 when something is ready to be read.
1267  */
1268 long TcpSocket::available()
1270     if (!isConnected())
1271         return -1;
1273     long count = 0;
1274 #ifdef __WIN32__
1275     if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1276         return -1;
1277 #else
1278     if (ioctl(sock, FIONREAD, &count) != 0)
1279         return -1;
1280 #endif
1281     if (count<=0 && sslEnabled)
1282         {
1283 #ifdef HAVE_SSL
1284         return SSL_pending(sslStream);
1285 #endif
1286         }
1287     return count;
1292 bool TcpSocket::write(int ch)
1294     if (!isConnected())
1295         {
1296         fprintf(stderr, "write: socket closed\n");
1297         return false;
1298         }
1299     unsigned char c = (unsigned char)ch;
1301     if (sslEnabled)
1302         {
1303 #ifdef HAVE_SSL
1304         int r = SSL_write(sslStream, &c, 1);
1305         if (r<=0)
1306             {
1307             switch(SSL_get_error(sslStream, r))
1308                 {
1309                 default:
1310                     fprintf(stderr, "SSL write problem");
1311                     return -1;
1312                 }
1313             }
1314 #endif
1315         }
1316     else
1317         {
1318         if (send(sock, (const char *)&c, 1, 0) < 0)
1319         //if (send(sock, &c, 1, 0) < 0)
1320             {
1321             fprintf(stderr, "write: could not send data\n");
1322             return false;
1323             }
1324         }
1325     return true;
1328 bool TcpSocket::write(char *str)
1330    if (!isConnected())
1331         {
1332         fprintf(stderr, "write(str): socket closed\n");
1333         return false;
1334         }
1335     int len = strlen(str);
1337     if (sslEnabled)
1338         {
1339 #ifdef HAVE_SSL
1340         int r = SSL_write(sslStream, (unsigned char *)str, len);
1341         if (r<=0)
1342             {
1343             switch(SSL_get_error(sslStream, r))
1344                 {
1345                 default:
1346                     fprintf(stderr, "SSL write problem");
1347                     return -1;
1348                 }
1349             }
1350 #endif
1351         }
1352     else
1353         {
1354         if (send(sock, str, len, 0) < 0)
1355         //if (send(sock, &c, 1, 0) < 0)
1356             {
1357             fprintf(stderr, "write: could not send data\n");
1358             return false;
1359             }
1360         }
1361     return true;
1364 bool TcpSocket::write(const std::string &str)
1366     return write((char *)str.c_str());
1369 int TcpSocket::read()
1371     if (!isConnected())
1372         return -1;
1374     //We'll use this loop for timeouts, so that SSL and plain sockets
1375     //will behave the same way
1376     if (receiveTimeout > 0)
1377         {
1378         unsigned long tim = 0;
1379         while (true)
1380             {
1381             int avail = available();
1382             if (avail > 0)
1383                 break;
1384             if (tim >= receiveTimeout)
1385                 return -2;
1386             Thread::sleep(20);
1387             tim += 20;
1388             }
1389         }
1391     //check again
1392     if (!isConnected())
1393         return -1;
1395     unsigned char ch;
1396     if (sslEnabled)
1397         {
1398 #ifdef HAVE_SSL
1399         if (!sslStream)
1400             return -1;
1401         int r = SSL_read(sslStream, &ch, 1);
1402         unsigned long err = SSL_get_error(sslStream, r);
1403         switch (err)
1404             {
1405             case SSL_ERROR_NONE:
1406                  break;
1407             case SSL_ERROR_ZERO_RETURN:
1408                 return -1;
1409             case SSL_ERROR_SYSCALL:
1410                 fprintf(stderr, "SSL read problem(syscall) %s\n",
1411                      ERR_error_string(ERR_get_error(), NULL));
1412                 return -1;
1413             default:
1414                 fprintf(stderr, "SSL read problem %s\n",
1415                      ERR_error_string(ERR_get_error(), NULL));
1416                 return -1;
1417             }
1418 #endif
1419         }
1420     else
1421         {
1422         if (recv(sock, (char *)&ch, 1, 0) <= 0)
1423             {
1424             fprintf(stderr, "read: could not receive data\n");
1425             disconnect();
1426             return -1;
1427             }
1428         }
1429     return (int)ch;
1432 std::string TcpSocket::readLine()
1434     std::string ret;
1436     while (isConnected())
1437         {
1438         int ch = read();
1439         if (ch<0)
1440             return ret;
1441         if (ch=='\r' || ch=='\n')
1442             return ret;
1443         ret.push_back((char)ch);
1444         }
1446     return ret;
1457 } //namespace Pedro
1458 //########################################################################
1459 //# E N D    O F     F I L E
1460 //########################################################################