Code

:) Wrong line Josh :D
[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 */
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 void Sha1::init()
337     lenW   = 0;
338     sizeHi = 0;
339     sizeLo = 0;
341     // Initialize H with the magic constants (see FIPS180 for constants)
342     H[0] = 0x67452301L;
343     H[1] = 0xefcdab89L;
344     H[2] = 0x98badcfeL;
345     H[3] = 0x10325476L;
346     H[4] = 0xc3d2e1f0L;
348     for (int i = 0; i < 80; i++)
349         W[i] = 0;
353 void Sha1::append(unsigned char *dataIn, int len)
355     // Read the data into W and process blocks as they get full
356     for (int i = 0; i < len; i++)
357         {
358         W[lenW / 4] <<= 8;
359         W[lenW / 4] |= (unsigned long)dataIn[i];
360         if ((++lenW) % 64 == 0)
361             {
362             hashblock();
363             lenW = 0;
364             }
365         sizeLo += 8;
366         sizeHi += (sizeLo < 8);
367         }
371 void Sha1::finish(unsigned char hashout[20])
373     unsigned char pad0x80 = 0x80;
374     unsigned char pad0x00 = 0x00;
375     unsigned char padlen[8];
377     // Pad with a binary 1 (e.g. 0x80), then zeroes, then length
378     padlen[0] = (unsigned char)((sizeHi >> 24) & 255);
379     padlen[1] = (unsigned char)((sizeHi >> 16) & 255);
380     padlen[2] = (unsigned char)((sizeHi >>  8) & 255);
381     padlen[3] = (unsigned char)((sizeHi >>  0) & 255);
382     padlen[4] = (unsigned char)((sizeLo >> 24) & 255);
383     padlen[5] = (unsigned char)((sizeLo >> 16) & 255);
384     padlen[6] = (unsigned char)((sizeLo >>  8) & 255);
385     padlen[7] = (unsigned char)((sizeLo >>  0) & 255);
387     append(&pad0x80, 1);
389     while (lenW != 56)
390         append(&pad0x00, 1);
391     append(padlen, 8);
393     // Output hash
394     for (int i = 0; i < 20; i++)
395         {
396         hashout[i] = (unsigned char)(H[i / 4] >> 24);
397         H[i / 4] <<= 8;
398         }
400     // Re-initialize the context (also zeroizes contents)
401     init();
405 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
407 void Sha1::hashblock()
410     for (int t = 16; t <= 79; t++)
411         W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
413     unsigned long A = H[0];
414     unsigned long B = H[1];
415     unsigned long C = H[2];
416     unsigned long D = H[3];
417     unsigned long E = H[4];
419     unsigned long TEMP;
421     for (int t = 0; t <= 19; t++)
422         {
423         TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) +
424                 E + W[t] + 0x5a827999L) & 0xffffffffL;
425         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
426         }
427     for (int t = 20; t <= 39; t++)
428         {
429         TEMP = (SHA_ROTL(A,5) + (B^C^D) +
430                 E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
431         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
432         }
433     for (int t = 40; t <= 59; t++)
434         {
435         TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) +
436                 E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
437         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
438         }
439     for (int t = 60; t <= 79; t++)
440         {
441         TEMP = (SHA_ROTL(A,5) + (B^C^D) +
442                 E + W[t] + 0xca62c1d6L) & 0xffffffffL;
443         E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
444         }
446     H[0] += A;
447     H[1] += B;
448     H[2] += C;
449     H[3] += D;
450     H[4] += E;
458 //########################################################################
459 //########################################################################
460 //### M D 5      H A S H I N G
461 //########################################################################
462 //########################################################################
468 void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
470     Md5 md5;
471     md5.append(dataIn, len);
472     md5.finish(digest);
475 DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
477     Md5 md5;
478     md5.append(dataIn, len);
479     DOMString ret = md5.finishHex();
480     return ret;
485 /*
486  * Note: this code is harmless on little-endian machines.
487  */
488 /*
489 static void byteReverse(unsigned char *buf, unsigned long longs)
491     do
492         {
493         unsigned long t = (unsigned long)
494             ((unsigned) buf[3] << 8 | buf[2]) << 16 |
495             ((unsigned) buf[1] << 8 | buf[0]);
496         *(unsigned long *) buf = t;
497         buf += 4;
498         } while (--longs);
500 */
502 static void md5_memcpy(void *dest, void *src, int n)
504     unsigned char *s1 = (unsigned char *)dest;
505     unsigned char *s2 = (unsigned char *)src;
506     while (n--)
507         *s1++ = *s2++;
510 static void md5_memset(void *dest, char v, int n)
512     unsigned char *s = (unsigned char *)dest;
513     while (n--)
514         *s++ = v;
517 /**
518  * Initialize MD5 polynomials and storage
519  */
520 void Md5::init()
522     buf[0]  = 0x67452301;
523     buf[1]  = 0xefcdab89;
524     buf[2]  = 0x98badcfe;
525     buf[3]  = 0x10325476;
527     bits[0] = 0;
528     bits[1] = 0;
531 /*
532  * Update context to reflect the concatenation of another buffer full
533  * of bytes.
534  */
535 void Md5::append(unsigned char *source, unsigned long len)
538     // Update bitcount
539     unsigned long t = bits[0];
540     if ((bits[0] = t + ((unsigned long) len << 3)) < t)
541             bits[1]++;// Carry from low to high
542     bits[1] += len >> 29;
544         //Bytes already in shsInfo->data
545     t = (t >> 3) & 0x3f;
548     // Handle any leading odd-sized chunks
549     if (t)
550         {
551         unsigned char *p = (unsigned char *) in + t;
552         t = 64 - t;
553         if (len < t)
554             {
555             md5_memcpy(p, source, len);
556             return;
557             }
558         md5_memcpy(p, source, t);
559         //byteReverse(in, 16);
560         transform(buf, (unsigned long *) in);
561         source += t;
562         len    -= t;
563         }
565     // Process data in 64-byte chunks
566     while (len >= 64)
567         {
568         md5_memcpy(in, source, 64);
569         //byteReverse(in, 16);
570         transform(buf, (unsigned long *) in);
571         source += 64;
572         len    -= 64;
573         }
575     // Handle any remaining bytes of data.
576     md5_memcpy(in, source, len);
579 /*
580  * Update context to reflect the concatenation of another string
581  */
582 void Md5::append(const DOMString &str)
584     append((unsigned char *)str.c_str(), str.size());
587 /*
588  * Update context to reflect the concatenation of a single character
589  */
590 void Md5::append(unsigned char ch)
592     append(&ch, 1);
595 /*
596  * Final wrapup - pad to 64-byte boundary with the bit pattern
597  * 1 0* (64-bit count of bits processed, MSB-first)
598  */
599 void Md5::finish(unsigned char *digest)
601     // Compute number of bytes mod 64
602     unsigned int count = (bits[0] >> 3) & 0x3F;
604     // Set the first char of padding to 0x80.
605     // This is safe since there is always at least one byte free
606     unsigned char *p = in + count;
607     *p++ = 0x80;
609     // Bytes of padding needed to make 64 bytes
610     count = 64 - 1 - count;
612     // Pad out to 56 mod 64
613     if (count < 8)
614         {
615             // Two lots of padding:  Pad the first block to 64 bytes
616             md5_memset(p, 0, count);
617             //byteReverse(in, 16);
618             transform(buf, (unsigned long *) in);
620             // Now fill the next block with 56 bytes
621             md5_memset(in, 0, 56);
622         }
623     else
624         {
625         // Pad block to 56 bytes
626         md5_memset(p, 0, count - 8);
627         }
628     //byteReverse(in, 14);
630     // Append length in bits and transform
631     ((unsigned long *) in)[14] = bits[0];
632     ((unsigned long *) in)[15] = bits[1];
634     transform(buf, (unsigned long *) in);
635     //byteReverse((unsigned char *) buf, 4);
636     md5_memcpy(digest, buf, 16);
637     init();  // Security!  ;-)
640 static char *md5hex = "0123456789abcdef";
642 DOMString Md5::finishHex()
644     unsigned char hashout[16];
645     finish(hashout);
646     DOMString ret;
647     for (int i=0 ; i<16 ; i++)
648         {
649         unsigned char ch = hashout[i];
650         ret.push_back(md5hex[ (ch>>4) & 15 ]);
651         ret.push_back(md5hex[ ch      & 15 ]);
652         }
653     return ret;
658 //#  The four core functions - F1 is optimized somewhat
660 //  #define F1(x, y, z) (x & y | ~x & z)
661 #define F1(x, y, z) (z ^ (x & (y ^ z)))
662 #define F2(x, y, z) F1(z, x, y)
663 #define F3(x, y, z) (x ^ y ^ z)
664 #define F4(x, y, z) (y ^ (x | ~z))
666 // ## This is the central step in the MD5 algorithm.
667 #define MD5STEP(f, w, x, y, z, data, s) \
668         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
670 /*
671  * The core of the MD5 algorithm, this alters an existing MD5 hash to
672  * reflect the addition of 16 longwords of new data.  MD5Update blocks
673  * the data and converts bytes into longwords for this routine.
674  * @parm buf points to an array of 4 unsigned longs
675  * @parm in points to an array of 16 unsigned longs
676  */
677 void Md5::transform(unsigned long *buf, unsigned long *in)
679     unsigned long a = buf[0];
680     unsigned long b = buf[1];
681     unsigned long c = buf[2];
682     unsigned long d = buf[3];
684     MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
685     MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
686     MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
687     MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
688     MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
689     MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
690     MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
691     MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
692     MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
693     MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
694     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
695     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
696     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
697     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
698     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
699     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
701     MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
702     MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
703     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
704     MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
705     MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
706     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
707     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
708     MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
709     MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
710     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
711     MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
712     MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
713     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
714     MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
715     MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
716     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
718     MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
719     MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
720     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
721     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
722     MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
723     MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
724     MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
725     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
726     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
727     MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
728     MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
729     MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
730     MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
731     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
732     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
733     MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
735     MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
736     MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
737     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
738     MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
739     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
740     MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
741     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
742     MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
743     MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f,  6);
744     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
745     MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
746     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
747     MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82,  6);
748     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
749     MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
750     MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
752     buf[0] += a;
753     buf[1] += b;
754     buf[2] += c;
755     buf[3] += d;
767 //########################################################################
768 //########################################################################
769 //### T H R E A D
770 //########################################################################
771 //########################################################################
777 #ifdef __WIN32__
780 static DWORD WINAPI WinThreadFunction(LPVOID context)
782     Thread *thread = (Thread *)context;
783     thread->execute();
784     return 0;
788 void Thread::start()
790     DWORD dwThreadId;
791     HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
792                (LPVOID)this,  0,  &dwThreadId);
793     //Make sure the thread is started before 'this' is deallocated
794     while (!started)
795         sleep(10);
796     CloseHandle(hThread);
799 void Thread::sleep(unsigned long millis)
801     Sleep(millis);
804 #else /* UNIX */
807 void *PthreadThreadFunction(void *context)
809     Thread *thread = (Thread *)context;
810     thread->execute();
811     return NULL;
815 void Thread::start()
817     pthread_t thread;
819     int ret = pthread_create(&thread, NULL,
820             PthreadThreadFunction, (void *)this);
821     if (ret != 0)
822         printf("Thread::start: thread creation failed: %s\n", strerror(ret));
824     //Make sure the thread is started before 'this' is deallocated
825     while (!started)
826         sleep(10);
830 void Thread::sleep(unsigned long millis)
832     timespec requested;
833     requested.tv_sec = millis / 1000;
834     requested.tv_nsec = (millis % 1000 ) * 1000000L;
835     nanosleep(&requested, NULL);
838 #endif
847 //########################################################################
848 //########################################################################
849 //### S O C K E T
850 //########################################################################
851 //########################################################################
857 //#########################################################################
858 //# U T I L I T Y
859 //#########################################################################
861 static void mybzero(void *s, size_t n)
863     unsigned char *p = (unsigned char *)s;
864     while (n > 0)
865         {
866         *p++ = (unsigned char)0;
867         n--;
868         }
871 static void mybcopy(void *src, void *dest, size_t n)
873     unsigned char *p = (unsigned char *)dest;
874     unsigned char *q = (unsigned char *)src;
875     while (n > 0)
876         {
877         *p++ = *q++;
878         n--;
879         }
884 //#########################################################################
885 //# T C P    C O N N E C T I O N
886 //#########################################################################
888 TcpSocket::TcpSocket()
890     init();
894 TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
896     init();
897     hostname  = hostnameArg;
898     portno    = port;
902 #ifdef HAVE_SSL
904 static void cryptoLockCallback(int mode, int type, const char *file, int line)
906     //printf("########### LOCK\n");
907     static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
908     const char *errstr = NULL;
910     int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
911     if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
912         {
913         errstr = "invalid mode";
914         goto err;
915         }
917     if (type < 0 || type >= CRYPTO_NUM_LOCKS)
918         {
919         errstr = "type out of bounds";
920         goto err;
921         }
923     if (mode & CRYPTO_LOCK)
924         {
925         if (modes[type])
926             {
927             errstr = "already locked";
928             /* must not happen in a single-threaded program
929              * (would deadlock)
930              */
931             goto err;
932             }
934         modes[type] = rw;
935         }
936     else if (mode & CRYPTO_UNLOCK)
937         {
938         if (!modes[type])
939             {
940              errstr = "not locked";
941              goto err;
942              }
944         if (modes[type] != rw)
945             {
946             errstr = (rw == CRYPTO_READ) ?
947                   "CRYPTO_r_unlock on write lock" :
948                   "CRYPTO_w_unlock on read lock";
949             }
951         modes[type] = 0;
952         }
953     else
954         {
955         errstr = "invalid mode";
956         goto err;
957         }
959     err:
960     if (errstr)
961         {
962         /* we cannot use bio_err here */
963         fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
964                 errstr, mode, type, file, line);
965         }
968 static unsigned long cryptoIdCallback()
970 #ifdef __WIN32__
971     unsigned long ret = (unsigned long) GetCurrentThreadId();
972 #else
973     unsigned long ret = (unsigned long) pthread_self();
974 #endif
975     return ret;
978 #endif
981 TcpSocket::TcpSocket(const TcpSocket &other)
983     init();
984     sock      = other.sock;
985     hostname  = other.hostname;
986     portno    = other.portno;
989 static bool tcp_socket_inited = false;
991 void TcpSocket::init()
993     if (!tcp_socket_inited)
994         {
995 #ifdef __WIN32__
996         WORD wVersionRequested = MAKEWORD( 2, 2 );
997         WSADATA wsaData;
998         WSAStartup( wVersionRequested, &wsaData );
999 #endif
1000 #ifdef HAVE_SSL
1001         if (libssl_is_present)
1002         {
1003         sslStream  = NULL;
1004         sslContext = NULL;
1005             CRYPTO_set_locking_callback(cryptoLockCallback);
1006         CRYPTO_set_id_callback(cryptoIdCallback);
1007         SSL_library_init();
1008         SSL_load_error_strings();
1009         }
1010 #endif
1011         tcp_socket_inited = true;
1012         }
1013     sock           = -1;
1014     connected      = false;
1015     hostname       = "";
1016     portno         = -1;
1017     sslEnabled     = false;
1018     receiveTimeout = 0;
1021 TcpSocket::~TcpSocket()
1023     disconnect();
1026 bool TcpSocket::isConnected()
1028     if (!connected || sock < 0)
1029         return false;
1030     return true;
1033 bool TcpSocket::getHaveSSL()
1035 #ifdef HAVE_SSL
1036     if (libssl_is_present)
1037     {
1038         return true;
1039     } else {
1040         return false;
1041     }
1042 #else
1043     return false;
1044 #endif
1047 void TcpSocket::enableSSL(bool val)
1049     sslEnabled = val;
1052 bool TcpSocket::getEnableSSL()
1054     return sslEnabled;
1059 bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1061     hostname = hostnameArg;
1062     portno   = portnoArg;
1063     return connect();
1068 #ifdef HAVE_SSL
1069 /*
1070 static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1072     char *password = "password";
1073     if (bufLen < (int)(strlen(password)+1))
1074         return 0;
1076     strcpy(buf,password);
1077     int ret = strlen(password);
1078     return ret;
1081 static void infoCallback(const SSL *ssl, int where, int ret)
1083     switch (where)
1084         {
1085         case SSL_CB_ALERT:
1086             {
1087             printf("## %d SSL ALERT: %s\n",  where, SSL_alert_desc_string_long(ret));
1088             break;
1089             }
1090         default:
1091             {
1092             printf("## %d SSL: %s\n",  where, SSL_state_string_long(ssl));
1093             break;
1094             }
1095         }
1097 */
1098 #endif
1101 bool TcpSocket::startTls()
1103 #ifndef HAVE_SSL
1104     fprintf(stderr,
1105             "SSL starttls() error:  client not compiled with SSL enabled\n");
1106     return false;
1107 #else /*HAVE_SSL*/
1108     if (!libssl_is_present)
1109     {
1110     fprintf(stderr,
1111             "SSL starttls() error:  the correct version of libssl was not found \n");
1112     return false;
1113     } else {
1114             
1115     sslStream  = NULL;
1116     sslContext = NULL;
1118     //SSL_METHOD *meth = SSLv23_method();
1119     //SSL_METHOD *meth = SSLv3_client_method();
1120     SSL_METHOD *meth = TLSv1_client_method();
1121     sslContext = SSL_CTX_new(meth);
1122     //SSL_CTX_set_info_callback(sslContext, infoCallback);
1124     /**
1125      * For now, let's accept all connections.  Ignore this
1126      * block of code     
1127      *       
1128     char *keyFile  = "client.pem";
1129     char *caList   = "root.pem";
1130     //#  Load our keys and certificates
1131     if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1132         {
1133         fprintf(stderr, "Can't read certificate file\n");
1134         disconnect();
1135         return false;
1136         }
1138     SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1140     if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1141         {
1142         fprintf(stderr, "Can't read key file\n");
1143         disconnect();
1144         return false;
1145         }
1147     //## Load the CAs we trust
1148     if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1149         {
1150         fprintf(stderr, "Can't read CA list\n");
1151         disconnect();
1152         return false;
1153         }
1154     */
1156     /* Connect the SSL socket */
1157     sslStream  = SSL_new(sslContext);
1158     SSL_set_fd(sslStream, sock);
1160     int ret = SSL_connect(sslStream);
1161     if (ret == 0)
1162         {
1163         fprintf(stderr, "SSL connection not successful\n");
1164         disconnect();
1165         return false;
1166         }
1167     else if (ret < 0)
1168         {
1169         int err = SSL_get_error(sslStream, ret);
1170         fprintf(stderr, "SSL connect error %d\n", err);
1171         disconnect();
1172         return false;
1173         }
1175     sslEnabled = true;
1176     return true;
1177     }
1178 #endif /* HAVE_SSL */
1182 bool TcpSocket::connect()
1184     if (hostname.size()<1)
1185         {
1186         fprintf(stderr, "open: null hostname\n");
1187         return false;
1188         }
1190     if (portno<1)
1191         {
1192         fprintf(stderr, "open: bad port number\n");
1193         return false;
1194         }
1196     sock = socket(PF_INET, SOCK_STREAM, 0);
1197     if (sock < 0)
1198         {
1199         fprintf(stderr, "open: error creating socket\n");
1200         return false;
1201         }
1203     char *c_hostname = (char *)hostname.c_str();
1204     struct hostent *server = gethostbyname(c_hostname);
1205     if (!server)
1206         {
1207         fprintf(stderr, "open: could not locate host '%s'\n", c_hostname);
1208         return false;
1209         }
1211     struct sockaddr_in serv_addr;
1212     mybzero((char *) &serv_addr, sizeof(serv_addr));
1213     serv_addr.sin_family = AF_INET;
1214     mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1215          server->h_length);
1216     serv_addr.sin_port = htons(portno);
1218     int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1219     if (ret < 0)
1220         {
1221         fprintf(stderr, "open: could not connect to host '%s'\n", c_hostname);
1222         return false;
1223         }
1225      if (sslEnabled)
1226         {
1227         if (!startTls())
1228             return false;
1229         }
1230     connected = true;
1231     return true;
1234 bool TcpSocket::disconnect()
1236     bool ret  = true;
1237     connected = false;
1238 #ifdef HAVE_SSL
1239     if (libssl_is_present)
1240     {
1241     if (sslEnabled)
1242         {
1243         if (sslStream)
1244             {
1245             int r = SSL_shutdown(sslStream);
1246             switch(r)
1247                 {
1248                 case 1:
1249                     break; /* Success */
1250                 case 0:
1251                 case -1:
1252                 default:
1253                     //printf("Shutdown failed");
1254                     ret = false;
1255                 }
1256             SSL_free(sslStream);
1257             }
1258         if (sslContext)
1259             SSL_CTX_free(sslContext);
1260         }
1261     sslStream  = NULL;
1262     sslContext = NULL;
1263     }
1264 #endif /*HAVE_SSL*/
1266 #ifdef __WIN32__
1267     closesocket(sock);
1268 #else
1269     ::close(sock);
1270 #endif
1271     sock = -1;
1272     sslEnabled = false;
1274     return ret;
1279 bool TcpSocket::setReceiveTimeout(unsigned long millis)
1281     receiveTimeout = millis;
1282     return true;
1285 /**
1286  * For normal sockets, return the number of bytes waiting to be received.
1287  * For SSL, just return >0 when something is ready to be read.
1288  */
1289 long TcpSocket::available()
1291     if (!isConnected())
1292         return -1;
1294     long count = 0;
1295 #ifdef __WIN32__
1296     if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1297         return -1;
1298 #else
1299     if (ioctl(sock, FIONREAD, &count) != 0)
1300         return -1;
1301 #endif
1302     if (count<=0 && sslEnabled)
1303         {
1304 #ifdef HAVE_SSL
1305         if (libssl_is_present)
1306         {
1307             return SSL_pending(sslStream);
1308         }
1309 #endif
1310         }
1311     return count;
1316 bool TcpSocket::write(int ch)
1318     if (!isConnected())
1319         {
1320         fprintf(stderr, "write: socket closed\n");
1321         return false;
1322         }
1323     unsigned char c = (unsigned char)ch;
1325     if (sslEnabled)
1326         {
1327 #ifdef HAVE_SSL
1328         if (libssl_is_present)
1329         {
1330         int r = SSL_write(sslStream, &c, 1);
1331         if (r<=0)
1332             {
1333             switch(SSL_get_error(sslStream, r))
1334                 {
1335                 default:
1336                     fprintf(stderr, "SSL write problem");
1337                     return -1;
1338                 }
1339             }
1340         }
1341 #endif
1342         }
1343     else
1344         {
1345         if (send(sock, (const char *)&c, 1, 0) < 0)
1346         //if (send(sock, &c, 1, 0) < 0)
1347             {
1348             fprintf(stderr, "write: could not send data\n");
1349             return false;
1350             }
1351         }
1352     return true;
1355 bool TcpSocket::write(char *str)
1357    if (!isConnected())
1358         {
1359         fprintf(stderr, "write(str): socket closed\n");
1360         return false;
1361         }
1362     int len = strlen(str);
1364     if (sslEnabled)
1365         {
1366 #ifdef HAVE_SSL
1367         if (libssl_is_present)
1368         {
1369         int r = SSL_write(sslStream, (unsigned char *)str, len);
1370         if (r<=0)
1371             {
1372             switch(SSL_get_error(sslStream, r))
1373                 {
1374                 default:
1375                     fprintf(stderr, "SSL write problem");
1376                     return -1;
1377                 }
1378             }
1379         }
1380 #endif
1381         }
1382     else
1383         {
1384         if (send(sock, str, len, 0) < 0)
1385         //if (send(sock, &c, 1, 0) < 0)
1386             {
1387             fprintf(stderr, "write: could not send data\n");
1388             return false;
1389             }
1390         }
1391     return true;
1394 bool TcpSocket::write(const std::string &str)
1396     return write((char *)str.c_str());
1399 int TcpSocket::read()
1401     if (!isConnected())
1402         return -1;
1404     //We'll use this loop for timeouts, so that SSL and plain sockets
1405     //will behave the same way
1406     if (receiveTimeout > 0)
1407         {
1408         unsigned long tim = 0;
1409         while (true)
1410             {
1411             int avail = available();
1412             if (avail > 0)
1413                 break;
1414             if (tim >= receiveTimeout)
1415                 return -2;
1416             Thread::sleep(20);
1417             tim += 20;
1418             }
1419         }
1421     //check again
1422     if (!isConnected())
1423         return -1;
1425     unsigned char ch;
1426     if (sslEnabled)
1427         {
1428 #ifdef HAVE_SSL
1429         if (libssl_is_present)
1430         {
1431         if (!sslStream)
1432             return -1;
1433         int r = SSL_read(sslStream, &ch, 1);
1434         unsigned long err = SSL_get_error(sslStream, r);
1435         switch (err)
1436             {
1437             case SSL_ERROR_NONE:
1438                  break;
1439             case SSL_ERROR_ZERO_RETURN:
1440                 return -1;
1441             case SSL_ERROR_SYSCALL:
1442                 fprintf(stderr, "SSL read problem(syscall) %s\n",
1443                      ERR_error_string(ERR_get_error(), NULL));
1444                 return -1;
1445             default:
1446                 fprintf(stderr, "SSL read problem %s\n",
1447                      ERR_error_string(ERR_get_error(), NULL));
1448                 return -1;
1449             }
1450         }
1451 #endif
1452         }
1453     else
1454         {
1455         if (recv(sock, (char *)&ch, 1, 0) <= 0)
1456             {
1457             fprintf(stderr, "read: could not receive data\n");
1458             disconnect();
1459             return -1;
1460             }
1461         }
1462     return (int)ch;
1465 std::string TcpSocket::readLine()
1467     std::string ret;
1469     while (isConnected())
1470         {
1471         int ch = read();
1472         if (ch<0)
1473             return ret;
1474         if (ch=='\r' || ch=='\n')
1475             return ret;
1476         ret.push_back((char)ch);
1477         }
1479     return ret;
1490 } //namespace Pedro
1491 //########################################################################
1492 //# E N D    O F     F I L E
1493 //########################################################################