Code

c19498281842148d203fb89b6fc2c5c10ccced4a
[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-2007 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 */
51 #ifdef HAVE_SSL
52 RELAYTOOL_SSL
53 #endif
56 namespace Pedro
57 {
63 //########################################################################
64 //########################################################################
65 //# B A S E    6 4
66 //########################################################################
67 //########################################################################
70 //#################
71 //# ENCODER
72 //#################
75 static char *base64encode =
76     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
80 /**
81  * Writes the specified byte to the output buffer
82  */
83 void Base64Encoder::append(int ch)
84 {
85     outBuf   <<=  8;
86     outBuf   |=  (ch & 0xff);
87     bitCount +=  8;
88     if (bitCount >= 24)
89         {
90         int indx  = (int)((outBuf & 0x00fc0000L) >> 18);
91         int obyte = (int)base64encode[indx & 63];
92         buf.push_back(obyte);
94         indx      = (int)((outBuf & 0x0003f000L) >> 12);
95         obyte     = (int)base64encode[indx & 63];
96         buf.push_back(obyte);
98         indx      = (int)((outBuf & 0x00000fc0L) >>  6);
99         obyte     = (int)base64encode[indx & 63];
100         buf.push_back(obyte);
102         indx      = (int)((outBuf & 0x0000003fL)      );
103         obyte     = (int)base64encode[indx & 63];
104         buf.push_back(obyte);
106         bitCount = 0;
107         outBuf   = 0L;
108         }
111 /**
112  * Writes the specified string to the output buffer
113  */
114 void Base64Encoder::append(char *str)
116     while (*str)
117         append((int)*str++);
120 /**
121  * Writes the specified string to the output buffer
122  */
123 void Base64Encoder::append(unsigned char *str, int len)
125     while (len>0)
126         {
127         append((int)*str++);
128         len--;
129         }
132 /**
133  * Writes the specified string to the output buffer
134  */
135 void Base64Encoder::append(const DOMString &str)
137     append((char *)str.c_str());
140 /**
141  * Closes this output stream and releases any system resources
142  * associated with this stream.
143  */
144 DOMString Base64Encoder::finish()
146     //get any last bytes (1 or 2) out of the buffer
147     if (bitCount == 16)
148         {
149         outBuf <<= 2;  //pad to make 18 bits
151         int indx  = (int)((outBuf & 0x0003f000L) >> 12);
152         int obyte = (int)base64encode[indx & 63];
153         buf.push_back(obyte);
155         indx      = (int)((outBuf & 0x00000fc0L) >>  6);
156         obyte     = (int)base64encode[indx & 63];
157         buf.push_back(obyte);
159         indx      = (int)((outBuf & 0x0000003fL)      );
160         obyte     = (int)base64encode[indx & 63];
161         buf.push_back(obyte);
163         buf.push_back('=');
164         }
165     else if (bitCount == 8)
166         {
167         outBuf <<= 4; //pad to make 12 bits
169         int indx  = (int)((outBuf & 0x00000fc0L) >>  6);
170         int obyte = (int)base64encode[indx & 63];
171         buf.push_back(obyte);
173         indx      = (int)((outBuf & 0x0000003fL)      );
174         obyte     = (int)base64encode[indx & 63];
175         buf.push_back(obyte);
177         buf.push_back('=');
178         buf.push_back('=');
179         }
181     DOMString ret = buf;
182     reset();
183     return ret;
187 DOMString Base64Encoder::encode(const DOMString &str)
189     Base64Encoder encoder;
190     encoder.append(str);
191     DOMString ret = encoder.finish();
192     return ret;
197 //#################
198 //# DECODER
199 //#################
201 static int base64decode[] =
203 /*00*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
204 /*08*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
205 /*10*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
206 /*18*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
207 /*20*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
208 /*28*/    -1,   -1,   -1,   62,   -1,   -1,   -1,   63,
209 /*30*/    52,   53,   54,   55,   56,   57,   58,   59,
210 /*38*/    60,   61,   -1,   -1,   -1,   -1,   -1,   -1,
211 /*40*/    -1,    0,    1,    2,    3,    4,    5,    6,
212 /*48*/     7,    8,    9,   10,   11,   12,   13,   14,
213 /*50*/    15,   16,   17,   18,   19,   20,   21,   22,
214 /*58*/    23,   24,   25,   -1,   -1,   -1,   -1,   -1,
215 /*60*/    -1,   26,   27,   28,   29,   30,   31,   32,
216 /*68*/    33,   34,   35,   36,   37,   38,   39,   40,
217 /*70*/    41,   42,   43,   44,   45,   46,   47,   48,
218 /*78*/    49,   50,   51,   -1,   -1,   -1,   -1,   -1
219 };
223 /**
224  * Appends one char to the decoder
225  */
226 void Base64Decoder::append(int ch)
228     if (isspace(ch))
229         return;
230     else if (ch == '=') //padding
231         {
232         inBytes[inCount++] = 0;
233         }
234     else
235         {
236         int byteVal = base64decode[ch & 0x7f];
237         //printf("char:%c %d\n", ch, byteVal);
238         if (byteVal < 0)
239             {
240             //Bad lookup value
241             }
242         inBytes[inCount++] = byteVal;
243         }
245     if (inCount >=4 )
246         {
247         unsigned char b0 = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);
248         unsigned char b1 = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);
249         unsigned char b2 = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3]   ) & 0x3f);
250         buf.push_back(b0);
251         buf.push_back(b1);
252         buf.push_back(b2);
253         inCount = 0;
254         }
258 void Base64Decoder::append(char *str)
260     while (*str)
261         append((int)*str++);
264 void Base64Decoder::append(const DOMString &str)
266     append((char *)str.c_str());
269 std::vector<unsigned char> Base64Decoder::finish()
271     std::vector<unsigned char> ret = buf;
272     reset();
273     return ret;
276 std::vector<unsigned char> Base64Decoder::decode(const DOMString &str)
278     Base64Decoder decoder;
279     decoder.append(str);
280     std::vector<unsigned char> ret = decoder.finish();
281     return ret;
284 DOMString Base64Decoder::decodeToString(const DOMString &str)
286     Base64Decoder decoder;
287     decoder.append(str);
288     std::vector<unsigned char> ret = decoder.finish();
289     DOMString buf;
290     for (unsigned int i=0 ; i<ret.size() ; i++)
291         buf.push_back(ret[i]);
292     return buf;
301 //########################################################################
302 //########################################################################
303 //### S H A    1      H A S H I N G
304 //########################################################################
305 //########################################################################
310 void Sha1::hash(unsigned char *dataIn, int len, unsigned char *digest)
312     Sha1 sha1;
313     sha1.append(dataIn, len);
314     sha1.finish(digest);
317 static char *sha1hex = "0123456789abcdef";
319 DOMString Sha1::hashHex(unsigned char *dataIn, int len)
321     unsigned char hashout[20];
322     hash(dataIn, len, hashout);
323     DOMString ret;
324     for (int i=0 ; i<20 ; i++)
325         {
326         unsigned char ch = hashout[i];
327         ret.push_back(sha1hex[ (ch>>4) & 15 ]);
328         ret.push_back(sha1hex[ ch      & 15 ]);
329         }
330     return ret;
334 DOMString Sha1::hashHex(const DOMString &str)
336     return hashHex((unsigned char *)str.c_str(), str.size());
340 void Sha1::init()
343     lenW   = 0;
344     sizeHi = 0;
345     sizeLo = 0;
347     // Initialize H with the magic constants (see FIPS180 for constants)
348     H[0] = 0x67452301L;
349     H[1] = 0xefcdab89L;
350     H[2] = 0x98badcfeL;
351     H[3] = 0x10325476L;
352     H[4] = 0xc3d2e1f0L;
354     for (int i = 0; i < 80; i++)
355         W[i] = 0;
359 void Sha1::append(unsigned char ch)
361     // Read the data into W and process blocks as they get full
362     W[lenW / 4] <<= 8;
363     W[lenW / 4] |= (unsigned long)ch;
364     if ((++lenW) % 64 == 0)
365         {
366         hashblock();
367         lenW = 0;
368         }
369     sizeLo += 8;
370     sizeHi += (sizeLo < 8);
374 void Sha1::append(unsigned char *dataIn, int len)
376     // Read the data into W and process blocks as they get full
377     for (int i = 0; i < len; i++)
378         append(dataIn[i]);
382 void Sha1::append(const DOMString &str)
384     append((unsigned char *)str.c_str(), str.size());
388 void Sha1::finish(unsigned char hashout[20])
390     unsigned char pad0x80 = 0x80;
391     unsigned char pad0x00 = 0x00;
392     unsigned char padlen[8];
394     // Pad with a binary 1 (e.g. 0x80), then zeroes, then length
395     padlen[0] = (unsigned char)((sizeHi >> 24) & 255);
396     padlen[1] = (unsigned char)((sizeHi >> 16) & 255);
397     padlen[2] = (unsigned char)((sizeHi >>  8) & 255);
398     padlen[3] = (unsigned char)((sizeHi >>  0) & 255);
399     padlen[4] = (unsigned char)((sizeLo >> 24) & 255);
400     padlen[5] = (unsigned char)((sizeLo >> 16) & 255);
401     padlen[6] = (unsigned char)((sizeLo >>  8) & 255);
402     padlen[7] = (unsigned char)((sizeLo >>  0) & 255);
404     append(&pad0x80, 1);
406     while (lenW != 56)
407         append(&pad0x00, 1);
408     append(padlen, 8);
410     // Output hash
411     for (int i = 0; i < 20; i++)
412         {
413         hashout[i] = (unsigned char)(H[i / 4] >> 24);
414         H[i / 4] <<= 8;
415         }
417     // Re-initialize the context (also zeroizes contents)
418     init();
422 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
424 void Sha1::hashblock()
427     for (int t = 16; t <= 79; t++)
428         W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
430     unsigned long A = H[0];
431     unsigned long B = H[1];
432     unsigned long C = H[2];
433     unsigned long D = H[3];
434     unsigned long E = H[4];
436     unsigned long TEMP;
438     for (int t = 0; t <= 19; t++)
439         {
440         TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) +
441                 E + W[t] + 0x5a827999L) & 0xffffffffL;
442         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
443         }
444     for (int t = 20; t <= 39; t++)
445         {
446         TEMP = (SHA_ROTL(A,5) + (B^C^D) +
447                 E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
448         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
449         }
450     for (int t = 40; t <= 59; t++)
451         {
452         TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) +
453                 E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
454         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
455         }
456     for (int t = 60; t <= 79; t++)
457         {
458         TEMP = (SHA_ROTL(A,5) + (B^C^D) +
459                 E + W[t] + 0xca62c1d6L) & 0xffffffffL;
460         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
461         }
463     H[0] += A;
464     H[1] += B;
465     H[2] += C;
466     H[3] += D;
467     H[4] += E;
475 //########################################################################
476 //########################################################################
477 //### M D 5      H A S H I N G
478 //########################################################################
479 //########################################################################
485 void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
487     Md5 md5;
488     md5.append(dataIn, len);
489     md5.finish(digest);
492 DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
494     Md5 md5;
495     md5.append(dataIn, len);
496     DOMString ret = md5.finishHex();
497     return ret;
500 DOMString Md5::hashHex(const DOMString &str)
502     Md5 md5;
503     md5.append(str);
504     DOMString ret = md5.finishHex();
505     return ret;
509 /**
510  * Initialize MD5 polynomials and storage
511  */
512 void Md5::init()
514     hashBuf[0]  = 0x67452301;
515     hashBuf[1]  = 0xefcdab89;
516     hashBuf[2]  = 0x98badcfe;
517     hashBuf[3]  = 0x10325476;
519     nrBytesHi = 0;
520     nrBytesLo = 0;
521     byteNr    = 0;
522     longNr    = 0;
528 /*
529  * Update with one character
530  */
531 void Md5::append(unsigned char ch)
533     if (nrBytesLo == 0xffffffff)
534         {
535         nrBytesLo = 0;
536         nrBytesHi++;
537         }
538     else
539         nrBytesLo++;
541     //pack 64 bytes into 16 longs
542     inb[byteNr++] = (unsigned long)ch;
543     if (byteNr >= 4)
544         {
545         unsigned long val =
546              inb[3] << 24 | inb[2] << 16 | inb[1] << 8 | inb[0];
547         inBuf[longNr++] = val;
548         byteNr = 0;
549         }
550     if (longNr >= 16)
551         {
552         transform();
553         longNr = 0;
554         }
558 /*
559  * Update context to reflect the concatenation of another buffer full
560  * of bytes.
561  */
562 void Md5::append(unsigned char *source, unsigned long len)
564     while (len--)
565         append(*source++);
569 /*
570  * Update context to reflect the concatenation of another string
571  */
572 void Md5::append(const DOMString &str)
574     append((unsigned char *)str.c_str(), str.size());
578 /*
579  * Final wrapup - pad to 64-byte boundary with the bit pattern
580  * 1 0* (64-bit count of bits processed, MSB-first)
581  */
582 void Md5::finish(unsigned char *digest)
584     //snapshot the bit count now before padding
585     unsigned long nrBitsLo = nrBytesLo << 3;
586     unsigned long nrBitsHi = (nrBytesHi << 3) | ((nrBytesLo >> 29) & 7);
588     //Append terminal char
589     append(0x80);
591     //pad until we have a 56 of 64 bits, allowing for 8 bytes at the end
592     while (true)
593         {
594         int remain = (int)(nrBytesLo & 63);
595         if (remain == 56)
596             break;
597         append(0);
598         }
600     //##### Append length in bits
601     int shift;
602     shift = 0;
603     for (int i=0 ; i<4 ; i++)
604         {
605         unsigned char ch = (unsigned char)((nrBitsLo>>shift) & 0xff);
606         append(ch);
607         shift += 8;
608         }
610     shift = 0;
611     for (int i=0 ; i<4 ; i++)
612         {
613         unsigned char ch = (unsigned char)((nrBitsHi>>shift) & 0xff);
614         append(ch);
615         shift += 8;
616         }
618     //copy out answer
619     int indx = 0;
620     for (int i=0 ; i<4 ; i++)
621         {
622         digest[indx++] = (unsigned char)((hashBuf[i]      ) & 0xff);
623         digest[indx++] = (unsigned char)((hashBuf[i] >>  8) & 0xff);
624         digest[indx++] = (unsigned char)((hashBuf[i] >> 16) & 0xff);
625         digest[indx++] = (unsigned char)((hashBuf[i] >> 24) & 0xff);
626         }
628     init();  // Security!  ;-)
633 static const char *md5hex = "0123456789abcdef";
635 DOMString Md5::finishHex()
637     unsigned char hashout[16];
638     finish(hashout);
639     DOMString ret;
640     for (int i=0 ; i<16 ; i++)
641         {
642         unsigned char ch = hashout[i];
643         ret.push_back(md5hex[ (ch>>4) & 15 ]);
644         ret.push_back(md5hex[ ch      & 15 ]);
645         }
646     return ret;
651 //#  The four core functions - F1 is optimized somewhat
653 //  #define F1(x, y, z) (x & y | ~x & z)
654 #define F1(x, y, z) (z ^ (x & (y ^ z)))
655 #define F2(x, y, z) F1(z, x, y)
656 #define F3(x, y, z) (x ^ y ^ z)
657 #define F4(x, y, z) (y ^ (x | ~z))
659 // ## This is the central step in the MD5 algorithm.
660 #define MD5STEP(f, w, x, y, z, data, s) \
661         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
663 /*
664  * The core of the MD5 algorithm, this alters an existing MD5 hash to
665  * reflect the addition of 16 longwords of new data.  MD5Update blocks
666  * the data and converts bytes into longwords for this routine.
667  * @parm buf points to an array of 4 unsigned longs
668  * @parm in points to an array of 16 unsigned longs
669  */
670 void Md5::transform()
672     unsigned long *i = inBuf;
673     unsigned long a  = hashBuf[0];
674     unsigned long b  = hashBuf[1];
675     unsigned long c  = hashBuf[2];
676     unsigned long d  = hashBuf[3];
678     MD5STEP(F1, a, b, c, d, i[ 0] + 0xd76aa478,  7);
679     MD5STEP(F1, d, a, b, c, i[ 1] + 0xe8c7b756, 12);
680     MD5STEP(F1, c, d, a, b, i[ 2] + 0x242070db, 17);
681     MD5STEP(F1, b, c, d, a, i[ 3] + 0xc1bdceee, 22);
682     MD5STEP(F1, a, b, c, d, i[ 4] + 0xf57c0faf,  7);
683     MD5STEP(F1, d, a, b, c, i[ 5] + 0x4787c62a, 12);
684     MD5STEP(F1, c, d, a, b, i[ 6] + 0xa8304613, 17);
685     MD5STEP(F1, b, c, d, a, i[ 7] + 0xfd469501, 22);
686     MD5STEP(F1, a, b, c, d, i[ 8] + 0x698098d8,  7);
687     MD5STEP(F1, d, a, b, c, i[ 9] + 0x8b44f7af, 12);
688     MD5STEP(F1, c, d, a, b, i[10] + 0xffff5bb1, 17);
689     MD5STEP(F1, b, c, d, a, i[11] + 0x895cd7be, 22);
690     MD5STEP(F1, a, b, c, d, i[12] + 0x6b901122,  7);
691     MD5STEP(F1, d, a, b, c, i[13] + 0xfd987193, 12);
692     MD5STEP(F1, c, d, a, b, i[14] + 0xa679438e, 17);
693     MD5STEP(F1, b, c, d, a, i[15] + 0x49b40821, 22);
695     MD5STEP(F2, a, b, c, d, i[ 1] + 0xf61e2562,  5);
696     MD5STEP(F2, d, a, b, c, i[ 6] + 0xc040b340,  9);
697     MD5STEP(F2, c, d, a, b, i[11] + 0x265e5a51, 14);
698     MD5STEP(F2, b, c, d, a, i[ 0] + 0xe9b6c7aa, 20);
699     MD5STEP(F2, a, b, c, d, i[ 5] + 0xd62f105d,  5);
700     MD5STEP(F2, d, a, b, c, i[10] + 0x02441453,  9);
701     MD5STEP(F2, c, d, a, b, i[15] + 0xd8a1e681, 14);
702     MD5STEP(F2, b, c, d, a, i[ 4] + 0xe7d3fbc8, 20);
703     MD5STEP(F2, a, b, c, d, i[ 9] + 0x21e1cde6,  5);
704     MD5STEP(F2, d, a, b, c, i[14] + 0xc33707d6,  9);
705     MD5STEP(F2, c, d, a, b, i[ 3] + 0xf4d50d87, 14);
706     MD5STEP(F2, b, c, d, a, i[ 8] + 0x455a14ed, 20);
707     MD5STEP(F2, a, b, c, d, i[13] + 0xa9e3e905,  5);
708     MD5STEP(F2, d, a, b, c, i[ 2] + 0xfcefa3f8,  9);
709     MD5STEP(F2, c, d, a, b, i[ 7] + 0x676f02d9, 14);
710     MD5STEP(F2, b, c, d, a, i[12] + 0x8d2a4c8a, 20);
712     MD5STEP(F3, a, b, c, d, i[ 5] + 0xfffa3942,  4);
713     MD5STEP(F3, d, a, b, c, i[ 8] + 0x8771f681, 11);
714     MD5STEP(F3, c, d, a, b, i[11] + 0x6d9d6122, 16);
715     MD5STEP(F3, b, c, d, a, i[14] + 0xfde5380c, 23);
716     MD5STEP(F3, a, b, c, d, i[ 1] + 0xa4beea44,  4);
717     MD5STEP(F3, d, a, b, c, i[ 4] + 0x4bdecfa9, 11);
718     MD5STEP(F3, c, d, a, b, i[ 7] + 0xf6bb4b60, 16);
719     MD5STEP(F3, b, c, d, a, i[10] + 0xbebfbc70, 23);
720     MD5STEP(F3, a, b, c, d, i[13] + 0x289b7ec6,  4);
721     MD5STEP(F3, d, a, b, c, i[ 0] + 0xeaa127fa, 11);
722     MD5STEP(F3, c, d, a, b, i[ 3] + 0xd4ef3085, 16);
723     MD5STEP(F3, b, c, d, a, i[ 6] + 0x04881d05, 23);
724     MD5STEP(F3, a, b, c, d, i[ 9] + 0xd9d4d039,  4);
725     MD5STEP(F3, d, a, b, c, i[12] + 0xe6db99e5, 11);
726     MD5STEP(F3, c, d, a, b, i[15] + 0x1fa27cf8, 16);
727     MD5STEP(F3, b, c, d, a, i[ 2] + 0xc4ac5665, 23);
729     MD5STEP(F4, a, b, c, d, i[ 0] + 0xf4292244,  6);
730     MD5STEP(F4, d, a, b, c, i[ 7] + 0x432aff97, 10);
731     MD5STEP(F4, c, d, a, b, i[14] + 0xab9423a7, 15);
732     MD5STEP(F4, b, c, d, a, i[ 5] + 0xfc93a039, 21);
733     MD5STEP(F4, a, b, c, d, i[12] + 0x655b59c3,  6);
734     MD5STEP(F4, d, a, b, c, i[ 3] + 0x8f0ccc92, 10);
735     MD5STEP(F4, c, d, a, b, i[10] + 0xffeff47d, 15);
736     MD5STEP(F4, b, c, d, a, i[ 1] + 0x85845dd1, 21);
737     MD5STEP(F4, a, b, c, d, i[ 8] + 0x6fa87e4f,  6);
738     MD5STEP(F4, d, a, b, c, i[15] + 0xfe2ce6e0, 10);
739     MD5STEP(F4, c, d, a, b, i[ 6] + 0xa3014314, 15);
740     MD5STEP(F4, b, c, d, a, i[13] + 0x4e0811a1, 21);
741     MD5STEP(F4, a, b, c, d, i[ 4] + 0xf7537e82,  6);
742     MD5STEP(F4, d, a, b, c, i[11] + 0xbd3af235, 10);
743     MD5STEP(F4, c, d, a, b, i[ 2] + 0x2ad7d2bb, 15);
744     MD5STEP(F4, b, c, d, a, i[ 9] + 0xeb86d391, 21);
746     hashBuf[0] += a;
747     hashBuf[1] += b;
748     hashBuf[2] += c;
749     hashBuf[3] += d;
758 //########################################################################
759 //########################################################################
760 //### T H R E A D
761 //########################################################################
762 //########################################################################
768 #ifdef __WIN32__
771 static DWORD WINAPI WinThreadFunction(LPVOID context)
773     Thread *thread = (Thread *)context;
774     thread->execute();
775     return 0;
779 void Thread::start()
781     DWORD dwThreadId;
782     HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
783                (LPVOID)this,  0,  &dwThreadId);
784     //Make sure the thread is started before 'this' is deallocated
785     while (!started)
786         sleep(10);
787     CloseHandle(hThread);
790 void Thread::sleep(unsigned long millis)
792     Sleep(millis);
795 #else /* UNIX */
798 void *PthreadThreadFunction(void *context)
800     Thread *thread = (Thread *)context;
801     thread->execute();
802     return NULL;
806 void Thread::start()
808     pthread_t thread;
810     int ret = pthread_create(&thread, NULL,
811             PthreadThreadFunction, (void *)this);
812     if (ret != 0)
813         printf("Thread::start: thread creation failed: %s\n", strerror(ret));
815     //Make sure the thread is started before 'this' is deallocated
816     while (!started)
817         sleep(10);
821 void Thread::sleep(unsigned long millis)
823     timespec requested;
824     requested.tv_sec = millis / 1000;
825     requested.tv_nsec = (millis % 1000 ) * 1000000L;
826     nanosleep(&requested, NULL);
829 #endif
838 //########################################################################
839 //########################################################################
840 //### S O C K E T
841 //########################################################################
842 //########################################################################
848 //#########################################################################
849 //# U T I L I T Y
850 //#########################################################################
852 static void mybzero(void *s, size_t n)
854     unsigned char *p = (unsigned char *)s;
855     while (n > 0)
856         {
857         *p++ = (unsigned char)0;
858         n--;
859         }
862 static void mybcopy(void *src, void *dest, size_t n)
864     unsigned char *p = (unsigned char *)dest;
865     unsigned char *q = (unsigned char *)src;
866     while (n > 0)
867         {
868         *p++ = *q++;
869         n--;
870         }
875 //#########################################################################
876 //# T C P    C O N N E C T I O N
877 //#########################################################################
879 TcpSocket::TcpSocket()
881     init();
885 TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
887     init();
888     hostname  = hostnameArg;
889     portno    = port;
893 #ifdef HAVE_SSL
895 static void cryptoLockCallback(int mode, int type, const char *file, int line)
897     //printf("########### LOCK\n");
898     static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
899     const char *errstr = NULL;
901     int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
902     if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
903         {
904         errstr = "invalid mode";
905         goto err;
906         }
908     if (type < 0 || type >= CRYPTO_NUM_LOCKS)
909         {
910         errstr = "type out of bounds";
911         goto err;
912         }
914     if (mode & CRYPTO_LOCK)
915         {
916         if (modes[type])
917             {
918             errstr = "already locked";
919             /* must not happen in a single-threaded program
920              * (would deadlock)
921              */
922             goto err;
923             }
925         modes[type] = rw;
926         }
927     else if (mode & CRYPTO_UNLOCK)
928         {
929         if (!modes[type])
930             {
931              errstr = "not locked";
932              goto err;
933              }
935         if (modes[type] != rw)
936             {
937             errstr = (rw == CRYPTO_READ) ?
938                   "CRYPTO_r_unlock on write lock" :
939                   "CRYPTO_w_unlock on read lock";
940             }
942         modes[type] = 0;
943         }
944     else
945         {
946         errstr = "invalid mode";
947         goto err;
948         }
950     err:
951     if (errstr)
952         {
953         /* we cannot use bio_err here */
954         fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
955                 errstr, mode, type, file, line);
956         }
959 static unsigned long cryptoIdCallback()
961 #ifdef __WIN32__
962     unsigned long ret = (unsigned long) GetCurrentThreadId();
963 #else
964     unsigned long ret = (unsigned long) pthread_self();
965 #endif
966     return ret;
969 #endif
972 TcpSocket::TcpSocket(const TcpSocket &other)
974     init();
975     sock      = other.sock;
976     hostname  = other.hostname;
977     portno    = other.portno;
980 static bool tcp_socket_inited = false;
982 void TcpSocket::init()
984     if (!tcp_socket_inited)
985         {
986 #ifdef __WIN32__
987         WORD wVersionRequested = MAKEWORD( 2, 2 );
988         WSADATA wsaData;
989         WSAStartup( wVersionRequested, &wsaData );
990 #endif
991 #ifdef HAVE_SSL
992         if (libssl_is_present)
993         {
994         sslStream  = NULL;
995         sslContext = NULL;
996             CRYPTO_set_locking_callback(cryptoLockCallback);
997         CRYPTO_set_id_callback(cryptoIdCallback);
998         SSL_library_init();
999         SSL_load_error_strings();
1000         }
1001 #endif
1002         tcp_socket_inited = true;
1003         }
1004     sock           = -1;
1005     connected      = false;
1006     hostname       = "";
1007     portno         = -1;
1008     sslEnabled     = false;
1009     receiveTimeout = 0;
1012 TcpSocket::~TcpSocket()
1014     disconnect();
1017 bool TcpSocket::isConnected()
1019     if (!connected || sock < 0)
1020         return false;
1021     return true;
1024 bool TcpSocket::getHaveSSL()
1026 #ifdef HAVE_SSL
1027     if (libssl_is_present)
1028     {
1029         return true;
1030     } else {
1031         return false;
1032     }
1033 #else
1034     return false;
1035 #endif
1038 void TcpSocket::enableSSL(bool val)
1040     sslEnabled = val;
1043 bool TcpSocket::getEnableSSL()
1045     return sslEnabled;
1050 bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1052     hostname = hostnameArg;
1053     portno   = portnoArg;
1054     return connect();
1059 #ifdef HAVE_SSL
1060 /*
1061 static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1063     char *password = "password";
1064     if (bufLen < (int)(strlen(password)+1))
1065         return 0;
1067     strcpy(buf,password);
1068     int ret = strlen(password);
1069     return ret;
1072 static void infoCallback(const SSL *ssl, int where, int ret)
1074     switch (where)
1075         {
1076         case SSL_CB_ALERT:
1077             {
1078             printf("## %d SSL ALERT: %s\n",  where, SSL_alert_desc_string_long(ret));
1079             break;
1080             }
1081         default:
1082             {
1083             printf("## %d SSL: %s\n",  where, SSL_state_string_long(ssl));
1084             break;
1085             }
1086         }
1088 */
1089 #endif
1092 bool TcpSocket::startTls()
1094 #ifndef HAVE_SSL
1095     fprintf(stderr,
1096             "SSL starttls() error:  client not compiled with SSL enabled\n");
1097     return false;
1098 #else /*HAVE_SSL*/
1099     if (!libssl_is_present)
1100     {
1101     fprintf(stderr,
1102             "SSL starttls() error:  the correct version of libssl was not found \n");
1103     return false;
1104     } else {
1105             
1106     sslStream  = NULL;
1107     sslContext = NULL;
1109     //SSL_METHOD *meth = SSLv23_method();
1110     //SSL_METHOD *meth = SSLv3_client_method();
1111     SSL_METHOD *meth = TLSv1_client_method();
1112     sslContext = SSL_CTX_new(meth);
1113     //SSL_CTX_set_info_callback(sslContext, infoCallback);
1115     /**
1116      * For now, let's accept all connections.  Ignore this
1117      * block of code     
1118      *       
1119     char *keyFile  = "client.pem";
1120     char *caList   = "root.pem";
1121     //#  Load our keys and certificates
1122     if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1123         {
1124         fprintf(stderr, "Can't read certificate file\n");
1125         disconnect();
1126         return false;
1127         }
1129     SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1131     if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1132         {
1133         fprintf(stderr, "Can't read key file\n");
1134         disconnect();
1135         return false;
1136         }
1138     //## Load the CAs we trust
1139     if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1140         {
1141         fprintf(stderr, "Can't read CA list\n");
1142         disconnect();
1143         return false;
1144         }
1145     */
1147     /* Connect the SSL socket */
1148     sslStream  = SSL_new(sslContext);
1149     SSL_set_fd(sslStream, sock);
1151     int ret = SSL_connect(sslStream);
1152     if (ret == 0)
1153         {
1154         fprintf(stderr, "SSL connection not successful\n");
1155         disconnect();
1156         return false;
1157         }
1158     else if (ret < 0)
1159         {
1160         int err = SSL_get_error(sslStream, ret);
1161         fprintf(stderr, "SSL connect error %d\n", err);
1162         disconnect();
1163         return false;
1164         }
1166     sslEnabled = true;
1167     return true;
1168     }
1169 #endif /* HAVE_SSL */
1173 bool TcpSocket::connect()
1175     if (hostname.size()<1)
1176         {
1177         fprintf(stderr, "open: null hostname\n");
1178         return false;
1179         }
1181     if (portno<1)
1182         {
1183         fprintf(stderr, "open: bad port number\n");
1184         return false;
1185         }
1187     sock = socket(PF_INET, SOCK_STREAM, 0);
1188     if (sock < 0)
1189         {
1190         fprintf(stderr, "open: error creating socket\n");
1191         return false;
1192         }
1194     char *c_hostname = (char *)hostname.c_str();
1195     struct hostent *server = gethostbyname(c_hostname);
1196     if (!server)
1197         {
1198         fprintf(stderr, "open: could not locate host '%s'\n", c_hostname);
1199         return false;
1200         }
1202     struct sockaddr_in serv_addr;
1203     mybzero((char *) &serv_addr, sizeof(serv_addr));
1204     serv_addr.sin_family = AF_INET;
1205     mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1206          server->h_length);
1207     serv_addr.sin_port = htons(portno);
1209     int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1210     if (ret < 0)
1211         {
1212         fprintf(stderr, "open: could not connect to host '%s'\n", c_hostname);
1213         return false;
1214         }
1216      if (sslEnabled)
1217         {
1218         if (!startTls())
1219             return false;
1220         }
1221     connected = true;
1222     return true;
1225 bool TcpSocket::disconnect()
1227     bool ret  = true;
1228     connected = false;
1229 #ifdef HAVE_SSL
1230     if (libssl_is_present)
1231     {
1232     if (sslEnabled)
1233         {
1234         if (sslStream)
1235             {
1236             int r = SSL_shutdown(sslStream);
1237             switch(r)
1238                 {
1239                 case 1:
1240                     break; /* Success */
1241                 case 0:
1242                 case -1:
1243                 default:
1244                     //printf("Shutdown failed");
1245                     ret = false;
1246                 }
1247             SSL_free(sslStream);
1248             }
1249         if (sslContext)
1250             SSL_CTX_free(sslContext);
1251         }
1252     sslStream  = NULL;
1253     sslContext = NULL;
1254     }
1255 #endif /*HAVE_SSL*/
1257 #ifdef __WIN32__
1258     closesocket(sock);
1259 #else
1260     ::close(sock);
1261 #endif
1262     sock = -1;
1263     sslEnabled = false;
1265     return ret;
1270 bool TcpSocket::setReceiveTimeout(unsigned long millis)
1272     receiveTimeout = millis;
1273     return true;
1276 /**
1277  * For normal sockets, return the number of bytes waiting to be received.
1278  * For SSL, just return >0 when something is ready to be read.
1279  */
1280 long TcpSocket::available()
1282     if (!isConnected())
1283         return -1;
1285     long count = 0;
1286 #ifdef __WIN32__
1287     if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1288         return -1;
1289 #else
1290     if (ioctl(sock, FIONREAD, &count) != 0)
1291         return -1;
1292 #endif
1293     if (count<=0 && sslEnabled)
1294         {
1295 #ifdef HAVE_SSL
1296         if (libssl_is_present)
1297         {
1298             return SSL_pending(sslStream);
1299         }
1300 #endif
1301         }
1302     return count;
1307 bool TcpSocket::write(int ch)
1309     if (!isConnected())
1310         {
1311         fprintf(stderr, "write: socket closed\n");
1312         return false;
1313         }
1314     unsigned char c = (unsigned char)ch;
1316     if (sslEnabled)
1317         {
1318 #ifdef HAVE_SSL
1319         if (libssl_is_present)
1320         {
1321         int r = SSL_write(sslStream, &c, 1);
1322         if (r<=0)
1323             {
1324             switch(SSL_get_error(sslStream, r))
1325                 {
1326                 default:
1327                     fprintf(stderr, "SSL write problem");
1328                     return -1;
1329                 }
1330             }
1331         }
1332 #endif
1333         }
1334     else
1335         {
1336         if (send(sock, (const char *)&c, 1, 0) < 0)
1337         //if (send(sock, &c, 1, 0) < 0)
1338             {
1339             fprintf(stderr, "write: could not send data\n");
1340             return false;
1341             }
1342         }
1343     return true;
1346 bool TcpSocket::write(char *str)
1348    if (!isConnected())
1349         {
1350         fprintf(stderr, "write(str): socket closed\n");
1351         return false;
1352         }
1353     int len = strlen(str);
1355     if (sslEnabled)
1356         {
1357 #ifdef HAVE_SSL
1358         if (libssl_is_present)
1359         {
1360         int r = SSL_write(sslStream, (unsigned char *)str, len);
1361         if (r<=0)
1362             {
1363             switch(SSL_get_error(sslStream, r))
1364                 {
1365                 default:
1366                     fprintf(stderr, "SSL write problem");
1367                     return -1;
1368                 }
1369             }
1370         }
1371 #endif
1372         }
1373     else
1374         {
1375         if (send(sock, str, len, 0) < 0)
1376         //if (send(sock, &c, 1, 0) < 0)
1377             {
1378             fprintf(stderr, "write: could not send data\n");
1379             return false;
1380             }
1381         }
1382     return true;
1385 bool TcpSocket::write(const std::string &str)
1387     return write((char *)str.c_str());
1390 int TcpSocket::read()
1392     if (!isConnected())
1393         return -1;
1395     //We'll use this loop for timeouts, so that SSL and plain sockets
1396     //will behave the same way
1397     if (receiveTimeout > 0)
1398         {
1399         unsigned long tim = 0;
1400         while (true)
1401             {
1402             int avail = available();
1403             if (avail > 0)
1404                 break;
1405             if (tim >= receiveTimeout)
1406                 return -2;
1407             Thread::sleep(20);
1408             tim += 20;
1409             }
1410         }
1412     //check again
1413     if (!isConnected())
1414         return -1;
1416     unsigned char ch;
1417     if (sslEnabled)
1418         {
1419 #ifdef HAVE_SSL
1420         if (libssl_is_present)
1421         {
1422         if (!sslStream)
1423             return -1;
1424         int r = SSL_read(sslStream, &ch, 1);
1425         unsigned long err = SSL_get_error(sslStream, r);
1426         switch (err)
1427             {
1428             case SSL_ERROR_NONE:
1429                  break;
1430             case SSL_ERROR_ZERO_RETURN:
1431                 return -1;
1432             case SSL_ERROR_SYSCALL:
1433                 fprintf(stderr, "SSL read problem(syscall) %s\n",
1434                      ERR_error_string(ERR_get_error(), NULL));
1435                 return -1;
1436             default:
1437                 fprintf(stderr, "SSL read problem %s\n",
1438                      ERR_error_string(ERR_get_error(), NULL));
1439                 return -1;
1440             }
1441         }
1442 #endif
1443         }
1444     else
1445         {
1446         if (recv(sock, (char *)&ch, 1, 0) <= 0)
1447             {
1448             fprintf(stderr, "read: could not receive data\n");
1449             disconnect();
1450             return -1;
1451             }
1452         }
1453     return (int)ch;
1456 std::string TcpSocket::readLine()
1458     std::string ret;
1460     while (isConnected())
1461         {
1462         int ch = read();
1463         if (ch<0)
1464             return ret;
1465         if (ch=='\r' || ch=='\n')
1466             return ret;
1467         ret.push_back((char)ch);
1468         }
1470     return ret;
1481 } //namespace Pedro
1482 //########################################################################
1483 //# E N D    O F     F I L E
1484 //########################################################################