~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/pedro/pedroutil.cpp

  • Committer: JazzyNico
  • Date: 2011-08-29 20:25:30 UTC
  • Revision ID: nicoduf@yahoo.fr-20110829202530-6deuoz11q90usldv
Code refactoring and merging with trunk (revision 10599).

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 */
23
 
 
24
 
 
25
 
#include <stdio.h>
26
 
#include <stdarg.h>
27
 
#include <string.h>
28
 
#include <sys/stat.h>
29
 
 
30
 
#include "pedroutil.h"
31
 
 
32
 
 
33
 
 
34
 
#ifdef __WIN32__
35
 
 
36
 
#include <windows.h>
37
 
 
38
 
#else /* UNIX */
39
 
 
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>
46
 
 
47
 
#include <pthread.h>
48
 
 
49
 
#endif /* UNIX */
50
 
 
51
 
#ifdef HAVE_SSL
52
 
RELAYTOOL_SSL
53
 
#endif
54
 
 
55
 
 
56
 
namespace Pedro
57
 
{
58
 
 
59
 
 
60
 
 
61
 
 
62
 
 
63
 
//########################################################################
64
 
//########################################################################
65
 
//# B A S E    6 4
66
 
//########################################################################
67
 
//########################################################################
68
 
 
69
 
 
70
 
//#################
71
 
//# ENCODER
72
 
//#################
73
 
 
74
 
 
75
 
static const char *base64encode =
76
 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
77
 
 
78
 
 
79
 
 
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);
93
 
 
94
 
        indx      = (int)((outBuf & 0x0003f000L) >> 12);
95
 
        obyte     = (int)base64encode[indx & 63];
96
 
        buf.push_back(obyte);
97
 
 
98
 
        indx      = (int)((outBuf & 0x00000fc0L) >>  6);
99
 
        obyte     = (int)base64encode[indx & 63];
100
 
        buf.push_back(obyte);
101
 
 
102
 
        indx      = (int)((outBuf & 0x0000003fL)      );
103
 
        obyte     = (int)base64encode[indx & 63];
104
 
        buf.push_back(obyte);
105
 
 
106
 
        bitCount = 0;
107
 
        outBuf   = 0L;
108
 
        }
109
 
}
110
 
 
111
 
/**
112
 
 * Writes the specified string to the output buffer
113
 
 */
114
 
void Base64Encoder::append(char *str)
115
 
{
116
 
    while (*str)
117
 
        append((int)*str++);
118
 
}
119
 
 
120
 
/**
121
 
 * Writes the specified string to the output buffer
122
 
 */
123
 
void Base64Encoder::append(unsigned char *str, int len)
124
 
{
125
 
    while (len>0)
126
 
        {
127
 
        append((int)*str++);
128
 
        len--;
129
 
        }
130
 
}
131
 
 
132
 
/**
133
 
 * Writes the specified string to the output buffer
134
 
 */
135
 
void Base64Encoder::append(const DOMString &str)
136
 
{
137
 
    append((char *)str.c_str());
138
 
}
139
 
 
140
 
/**
141
 
 * Closes this output stream and releases any system resources
142
 
 * associated with this stream.
143
 
 */
144
 
DOMString Base64Encoder::finish()
145
 
{
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
150
 
 
151
 
        int indx  = (int)((outBuf & 0x0003f000L) >> 12);
152
 
        int obyte = (int)base64encode[indx & 63];
153
 
        buf.push_back(obyte);
154
 
 
155
 
        indx      = (int)((outBuf & 0x00000fc0L) >>  6);
156
 
        obyte     = (int)base64encode[indx & 63];
157
 
        buf.push_back(obyte);
158
 
 
159
 
        indx      = (int)((outBuf & 0x0000003fL)      );
160
 
        obyte     = (int)base64encode[indx & 63];
161
 
        buf.push_back(obyte);
162
 
 
163
 
        buf.push_back('=');
164
 
        }
165
 
    else if (bitCount == 8)
166
 
        {
167
 
        outBuf <<= 4; //pad to make 12 bits
168
 
 
169
 
        int indx  = (int)((outBuf & 0x00000fc0L) >>  6);
170
 
        int obyte = (int)base64encode[indx & 63];
171
 
        buf.push_back(obyte);
172
 
 
173
 
        indx      = (int)((outBuf & 0x0000003fL)      );
174
 
        obyte     = (int)base64encode[indx & 63];
175
 
        buf.push_back(obyte);
176
 
 
177
 
        buf.push_back('=');
178
 
        buf.push_back('=');
179
 
        }
180
 
 
181
 
    DOMString ret = buf;
182
 
    reset();
183
 
    return ret;
184
 
}
185
 
 
186
 
 
187
 
DOMString Base64Encoder::encode(const DOMString &str)
188
 
{
189
 
    Base64Encoder encoder;
190
 
    encoder.append(str);
191
 
    DOMString ret = encoder.finish();
192
 
    return ret;
193
 
}
194
 
 
195
 
 
196
 
 
197
 
//#################
198
 
//# DECODER
199
 
//#################
200
 
 
201
 
static int base64decode[] =
202
 
{
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
 
};
220
 
 
221
 
 
222
 
 
223
 
/**
224
 
 * Appends one char to the decoder
225
 
 */
226
 
void Base64Decoder::append(int ch)
227
 
{
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
 
        }
244
 
 
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
 
        }
255
 
 
256
 
}
257
 
 
258
 
void Base64Decoder::append(char *str)
259
 
{
260
 
    while (*str)
261
 
        append((int)*str++);
262
 
}
263
 
 
264
 
void Base64Decoder::append(const DOMString &str)
265
 
{
266
 
    append((char *)str.c_str());
267
 
}
268
 
 
269
 
std::vector<unsigned char> Base64Decoder::finish()
270
 
{
271
 
    std::vector<unsigned char> ret = buf;
272
 
    reset();
273
 
    return ret;
274
 
}
275
 
 
276
 
std::vector<unsigned char> Base64Decoder::decode(const DOMString &str)
277
 
{
278
 
    Base64Decoder decoder;
279
 
    decoder.append(str);
280
 
    std::vector<unsigned char> ret = decoder.finish();
281
 
    return ret;
282
 
}
283
 
 
284
 
DOMString Base64Decoder::decodeToString(const DOMString &str)
285
 
{
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;
293
 
}
294
 
 
295
 
 
296
 
 
297
 
 
298
 
 
299
 
 
300
 
 
301
 
//########################################################################
302
 
//########################################################################
303
 
//### S H A    1      H A S H I N G
304
 
//########################################################################
305
 
//########################################################################
306
 
 
307
 
void Sha1::hash(unsigned char *dataIn, int len, unsigned char *digest)
308
 
{
309
 
    Sha1 sha1;
310
 
    sha1.append(dataIn, len);
311
 
    sha1.finish(digest);
312
 
}
313
 
 
314
 
static const char *sha1hex = "0123456789abcdef";
315
 
 
316
 
DOMString Sha1::hashHex(unsigned char *dataIn, int len)
317
 
{
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;
328
 
}
329
 
 
330
 
 
331
 
DOMString Sha1::hashHex(const DOMString &str)
332
 
{
333
 
    return hashHex((unsigned char *)str.c_str(), str.size());
334
 
}
335
 
 
336
 
 
337
 
void Sha1::init()
338
 
{
339
 
 
340
 
    longNr    = 0;
341
 
    byteNr    = 0;
342
 
    nrBytesHi = 0;
343
 
    nrBytesLo = 0;
344
 
 
345
 
    // Initialize H with the magic constants (see FIPS180 for constants)
346
 
    hashBuf[0] = 0x67452301L;
347
 
    hashBuf[1] = 0xefcdab89L;
348
 
    hashBuf[2] = 0x98badcfeL;
349
 
    hashBuf[3] = 0x10325476L;
350
 
    hashBuf[4] = 0xc3d2e1f0L;
351
 
 
352
 
    for (int i = 0; i < 4; i++)
353
 
        inb[i] = 0;
354
 
 
355
 
    for (int i = 0; i < 80; i++)
356
 
        inBuf[i] = 0;
357
 
}
358
 
 
359
 
 
360
 
void Sha1::append(unsigned char ch)
361
 
{
362
 
    if (nrBytesLo == 0xffffffffL)
363
 
        {
364
 
        nrBytesHi++;
365
 
        nrBytesLo = 0;
366
 
        }
367
 
    else
368
 
        nrBytesLo++;
369
 
 
370
 
    inb[byteNr++] = (unsigned long)ch;
371
 
    if (byteNr >= 4)
372
 
        {
373
 
        inBuf[longNr++] = inb[0] << 24 | inb[1] << 16 |
374
 
                          inb[2] << 8  | inb[3];
375
 
        byteNr = 0;
376
 
        }
377
 
    if (longNr >= 16)
378
 
        {
379
 
        transform();
380
 
        longNr = 0;
381
 
        }
382
 
}
383
 
 
384
 
 
385
 
void Sha1::append(unsigned char *dataIn, int len)
386
 
{
387
 
    for (int i = 0; i < len; i++)
388
 
        append(dataIn[i]);
389
 
}
390
 
 
391
 
 
392
 
void Sha1::append(const DOMString &str)
393
 
{
394
 
    append((unsigned char *)str.c_str(), str.size());
395
 
}
396
 
 
397
 
 
398
 
void Sha1::finish(unsigned char digest[20])
399
 
{
400
 
    //snapshot the bit count now before padding
401
 
    unsigned long nrBitsLo = (nrBytesLo << 3) & 0xffffffff;
402
 
    unsigned long nrBitsHi = (nrBytesHi << 3) | ((nrBytesLo >> 29) & 7);
403
 
 
404
 
    //Append terminal char
405
 
    append(0x80);
406
 
 
407
 
    //pad until we have a 56 of 64 bytes, allowing for 8 bytes at the end
408
 
    while (longNr != 14)
409
 
        append(0);
410
 
 
411
 
 
412
 
    //##### Append length in bits
413
 
    append((unsigned char)((nrBitsHi>>24) & 0xff));
414
 
    append((unsigned char)((nrBitsHi>>16) & 0xff));
415
 
    append((unsigned char)((nrBitsHi>> 8) & 0xff));
416
 
    append((unsigned char)((nrBitsHi    ) & 0xff));
417
 
    append((unsigned char)((nrBitsLo>>24) & 0xff));
418
 
    append((unsigned char)((nrBitsLo>>16) & 0xff));
419
 
    append((unsigned char)((nrBitsLo>> 8) & 0xff));
420
 
    append((unsigned char)((nrBitsLo    ) & 0xff));
421
 
 
422
 
 
423
 
    //copy out answer
424
 
    int indx = 0;
425
 
    for (int i=0 ; i<5 ; i++)
426
 
        {
427
 
        digest[indx++] = (unsigned char)((hashBuf[i] >> 24) & 0xff);
428
 
        digest[indx++] = (unsigned char)((hashBuf[i] >> 16) & 0xff);
429
 
        digest[indx++] = (unsigned char)((hashBuf[i] >>  8) & 0xff);
430
 
        digest[indx++] = (unsigned char)((hashBuf[i]      ) & 0xff);
431
 
        }
432
 
 
433
 
    // Re-initialize the context (also zeroizes contents)
434
 
    init();
435
 
}
436
 
 
437
 
 
438
 
 
439
 
#define SHA_ROTL(X,n) ((((X) << (n)) & 0xffffffff) | (((X) >> (32-(n))) & 0xffffffff))
440
 
 
441
 
void Sha1::transform()
442
 
{
443
 
    unsigned long *W = inBuf;
444
 
    unsigned long *H = hashBuf;
445
 
 
446
 
    for (int t = 16; t <= 79; t++)
447
 
        W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
448
 
 
449
 
    unsigned long A = H[0];
450
 
    unsigned long B = H[1];
451
 
    unsigned long C = H[2];
452
 
    unsigned long D = H[3];
453
 
    unsigned long E = H[4];
454
 
 
455
 
    unsigned long TEMP;
456
 
 
457
 
    for (int t = 0; t <= 19; t++)
458
 
        {
459
 
        TEMP = (SHA_ROTL(A,5) + ((B&C)|((~B)&D)) +
460
 
                E + W[t] + 0x5a827999L) & 0xffffffffL;
461
 
        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
462
 
        }
463
 
    for (int t = 20; t <= 39; t++)
464
 
        {
465
 
        TEMP = (SHA_ROTL(A,5) + (B^C^D) +
466
 
                E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
467
 
        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
468
 
        }
469
 
    for (int t = 40; t <= 59; t++)
470
 
        {
471
 
        TEMP = (SHA_ROTL(A,5) + ((B&C)|(B&D)|(C&D)) +
472
 
                E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
473
 
        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
474
 
        }
475
 
    for (int t = 60; t <= 79; t++)
476
 
        {
477
 
        TEMP = (SHA_ROTL(A,5) + (B^C^D) +
478
 
                E + W[t] + 0xca62c1d6L) & 0xffffffffL;
479
 
        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
480
 
        }
481
 
 
482
 
    H[0] = (H[0] + A) & 0xffffffffL;
483
 
    H[1] = (H[1] + B) & 0xffffffffL;
484
 
    H[2] = (H[2] + C) & 0xffffffffL;
485
 
    H[3] = (H[3] + D) & 0xffffffffL;
486
 
    H[4] = (H[4] + E) & 0xffffffffL;
487
 
}
488
 
 
489
 
 
490
 
 
491
 
//########################################################################
492
 
//########################################################################
493
 
//### M D 5      H A S H I N G
494
 
//########################################################################
495
 
//########################################################################
496
 
 
497
 
 
498
 
 
499
 
 
500
 
void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
501
 
{
502
 
    Md5 md5;
503
 
    md5.append(dataIn, len);
504
 
    md5.finish(digest);
505
 
}
506
 
 
507
 
DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
508
 
{
509
 
    Md5 md5;
510
 
    md5.append(dataIn, len);
511
 
    DOMString ret = md5.finishHex();
512
 
    return ret;
513
 
}
514
 
 
515
 
DOMString Md5::hashHex(const DOMString &str)
516
 
{
517
 
    Md5 md5;
518
 
    md5.append(str);
519
 
    DOMString ret = md5.finishHex();
520
 
    return ret;
521
 
}
522
 
 
523
 
 
524
 
/**
525
 
 * Initialize MD5 polynomials and storage
526
 
 */
527
 
void Md5::init()
528
 
{
529
 
    hashBuf[0]  = 0x67452301;
530
 
    hashBuf[1]  = 0xefcdab89;
531
 
    hashBuf[2]  = 0x98badcfe;
532
 
    hashBuf[3]  = 0x10325476;
533
 
 
534
 
    nrBytesHi = 0;
535
 
    nrBytesLo = 0;
536
 
    byteNr    = 0;
537
 
    longNr    = 0;
538
 
}
539
 
 
540
 
 
541
 
 
542
 
 
543
 
/**
544
 
 * Update with one character
545
 
 */
546
 
void Md5::append(unsigned char ch)
547
 
{
548
 
    if (nrBytesLo == 0xffffffff)
549
 
        {
550
 
        nrBytesLo = 0;
551
 
        nrBytesHi++;
552
 
        }
553
 
    else
554
 
        nrBytesLo++;
555
 
 
556
 
    //pack 64 bytes into 16 longs
557
 
    inb[byteNr++] = (unsigned long)ch;
558
 
    if (byteNr >= 4)
559
 
        {
560
 
        unsigned long val =
561
 
             inb[3] << 24 | inb[2] << 16 | inb[1] << 8 | inb[0];
562
 
        inBuf[longNr++] = val;
563
 
        byteNr = 0;
564
 
        }
565
 
    if (longNr >= 16)
566
 
        {
567
 
        transform();
568
 
        longNr = 0;
569
 
        }
570
 
}
571
 
 
572
 
 
573
 
/*
574
 
 * Update context to reflect the concatenation of another buffer full
575
 
 * of bytes.
576
 
 */
577
 
void Md5::append(unsigned char *source, unsigned long len)
578
 
{
579
 
    while (len--)
580
 
        append(*source++);
581
 
}
582
 
 
583
 
 
584
 
/*
585
 
 * Update context to reflect the concatenation of another string
586
 
 */
587
 
void Md5::append(const DOMString &str)
588
 
{
589
 
    append((unsigned char *)str.c_str(), str.size());
590
 
}
591
 
 
592
 
 
593
 
/*
594
 
 * Final wrapup - pad to 64-byte boundary with the bit pattern
595
 
 * 1 0* (64-bit count of bits processed, MSB-first)
596
 
 */
597
 
void Md5::finish(unsigned char *digest)
598
 
{
599
 
    //snapshot the bit count now before padding
600
 
    unsigned long nrBitsLo = (nrBytesLo << 3) & 0xffffffff;
601
 
    unsigned long nrBitsHi = (nrBytesHi << 3) | ((nrBytesLo >> 29) & 7);
602
 
 
603
 
    //Append terminal char
604
 
    append(0x80);
605
 
 
606
 
    //pad until we have a 56 of 64 bytes, allowing for 8 bytes at the end
607
 
    while (longNr != 14)
608
 
        append(0);
609
 
 
610
 
    //##### Append length in bits
611
 
    append((unsigned char)((nrBitsLo    ) & 0xff));
612
 
    append((unsigned char)((nrBitsLo>> 8) & 0xff));
613
 
    append((unsigned char)((nrBitsLo>>16) & 0xff));
614
 
    append((unsigned char)((nrBitsLo>>24) & 0xff));
615
 
    append((unsigned char)((nrBitsHi    ) & 0xff));
616
 
    append((unsigned char)((nrBitsHi>> 8) & 0xff));
617
 
    append((unsigned char)((nrBitsHi>>16) & 0xff));
618
 
    append((unsigned char)((nrBitsHi>>24) & 0xff));
619
 
 
620
 
    //copy out answer
621
 
    int indx = 0;
622
 
    for (int i=0 ; i<4 ; i++)
623
 
        {
624
 
        digest[indx++] = (unsigned char)((hashBuf[i]      ) & 0xff);
625
 
        digest[indx++] = (unsigned char)((hashBuf[i] >>  8) & 0xff);
626
 
        digest[indx++] = (unsigned char)((hashBuf[i] >> 16) & 0xff);
627
 
        digest[indx++] = (unsigned char)((hashBuf[i] >> 24) & 0xff);
628
 
        }
629
 
 
630
 
    init();  // Security!  ;-)
631
 
}
632
 
 
633
 
 
634
 
 
635
 
static const char *md5hex = "0123456789abcdef";
636
 
 
637
 
DOMString Md5::finishHex()
638
 
{
639
 
    unsigned char hashout[16];
640
 
    finish(hashout);
641
 
    DOMString ret;
642
 
    for (int i=0 ; i<16 ; i++)
643
 
        {
644
 
        unsigned char ch = hashout[i];
645
 
        ret.push_back(md5hex[ (ch>>4) & 15 ]);
646
 
        ret.push_back(md5hex[ ch      & 15 ]);
647
 
        }
648
 
    return ret;
649
 
}
650
 
 
651
 
 
652
 
 
653
 
//#  The four core functions - F1 is optimized somewhat
654
 
 
655
 
// #define F1(x, y, z) (x & y | ~x & z)
656
 
#define M(x) ((x) &= 0xffffffff)
657
 
#define F1(x, y, z) (z ^ (x & (y ^ z)))
658
 
#define F2(x, y, z) F1(z, x, y)
659
 
#define F3(x, y, z) (x ^ y ^ z)
660
 
#define F4(x, y, z) (y ^ (x | ~z))
661
 
 
662
 
// ## This is the central step in the MD5 algorithm.
663
 
#define MD5STEP(f, w, x, y, z, data, s) \
664
 
        ( w += (f(x, y, z) + data), M(w), w = w<<s | w>>(32-s), w += x, M(w) )
665
 
 
666
 
/*
667
 
 * The core of the MD5 algorithm, this alters an existing MD5 hash to
668
 
 * reflect the addition of 16 longwords of new data.  MD5Update blocks
669
 
 * the data and converts bytes into longwords for this routine.
670
 
 * @parm buf points to an array of 4 unsigned 32bit (at least) integers
671
 
 * @parm in points to an array of 16 unsigned 32bit (at least) integers
672
 
 */
673
 
void Md5::transform()
674
 
{
675
 
    unsigned long *i = inBuf;
676
 
    unsigned long a  = hashBuf[0];
677
 
    unsigned long b  = hashBuf[1];
678
 
    unsigned long c  = hashBuf[2];
679
 
    unsigned long d  = hashBuf[3];
680
 
 
681
 
    MD5STEP(F1, a, b, c, d, i[ 0] + 0xd76aa478,  7);
682
 
    MD5STEP(F1, d, a, b, c, i[ 1] + 0xe8c7b756, 12);
683
 
    MD5STEP(F1, c, d, a, b, i[ 2] + 0x242070db, 17);
684
 
    MD5STEP(F1, b, c, d, a, i[ 3] + 0xc1bdceee, 22);
685
 
    MD5STEP(F1, a, b, c, d, i[ 4] + 0xf57c0faf,  7);
686
 
    MD5STEP(F1, d, a, b, c, i[ 5] + 0x4787c62a, 12);
687
 
    MD5STEP(F1, c, d, a, b, i[ 6] + 0xa8304613, 17);
688
 
    MD5STEP(F1, b, c, d, a, i[ 7] + 0xfd469501, 22);
689
 
    MD5STEP(F1, a, b, c, d, i[ 8] + 0x698098d8,  7);
690
 
    MD5STEP(F1, d, a, b, c, i[ 9] + 0x8b44f7af, 12);
691
 
    MD5STEP(F1, c, d, a, b, i[10] + 0xffff5bb1, 17);
692
 
    MD5STEP(F1, b, c, d, a, i[11] + 0x895cd7be, 22);
693
 
    MD5STEP(F1, a, b, c, d, i[12] + 0x6b901122,  7);
694
 
    MD5STEP(F1, d, a, b, c, i[13] + 0xfd987193, 12);
695
 
    MD5STEP(F1, c, d, a, b, i[14] + 0xa679438e, 17);
696
 
    MD5STEP(F1, b, c, d, a, i[15] + 0x49b40821, 22);
697
 
 
698
 
    MD5STEP(F2, a, b, c, d, i[ 1] + 0xf61e2562,  5);
699
 
    MD5STEP(F2, d, a, b, c, i[ 6] + 0xc040b340,  9);
700
 
    MD5STEP(F2, c, d, a, b, i[11] + 0x265e5a51, 14);
701
 
    MD5STEP(F2, b, c, d, a, i[ 0] + 0xe9b6c7aa, 20);
702
 
    MD5STEP(F2, a, b, c, d, i[ 5] + 0xd62f105d,  5);
703
 
    MD5STEP(F2, d, a, b, c, i[10] + 0x02441453,  9);
704
 
    MD5STEP(F2, c, d, a, b, i[15] + 0xd8a1e681, 14);
705
 
    MD5STEP(F2, b, c, d, a, i[ 4] + 0xe7d3fbc8, 20);
706
 
    MD5STEP(F2, a, b, c, d, i[ 9] + 0x21e1cde6,  5);
707
 
    MD5STEP(F2, d, a, b, c, i[14] + 0xc33707d6,  9);
708
 
    MD5STEP(F2, c, d, a, b, i[ 3] + 0xf4d50d87, 14);
709
 
    MD5STEP(F2, b, c, d, a, i[ 8] + 0x455a14ed, 20);
710
 
    MD5STEP(F2, a, b, c, d, i[13] + 0xa9e3e905,  5);
711
 
    MD5STEP(F2, d, a, b, c, i[ 2] + 0xfcefa3f8,  9);
712
 
    MD5STEP(F2, c, d, a, b, i[ 7] + 0x676f02d9, 14);
713
 
    MD5STEP(F2, b, c, d, a, i[12] + 0x8d2a4c8a, 20);
714
 
 
715
 
    MD5STEP(F3, a, b, c, d, i[ 5] + 0xfffa3942,  4);
716
 
    MD5STEP(F3, d, a, b, c, i[ 8] + 0x8771f681, 11);
717
 
    MD5STEP(F3, c, d, a, b, i[11] + 0x6d9d6122, 16);
718
 
    MD5STEP(F3, b, c, d, a, i[14] + 0xfde5380c, 23);
719
 
    MD5STEP(F3, a, b, c, d, i[ 1] + 0xa4beea44,  4);
720
 
    MD5STEP(F3, d, a, b, c, i[ 4] + 0x4bdecfa9, 11);
721
 
    MD5STEP(F3, c, d, a, b, i[ 7] + 0xf6bb4b60, 16);
722
 
    MD5STEP(F3, b, c, d, a, i[10] + 0xbebfbc70, 23);
723
 
    MD5STEP(F3, a, b, c, d, i[13] + 0x289b7ec6,  4);
724
 
    MD5STEP(F3, d, a, b, c, i[ 0] + 0xeaa127fa, 11);
725
 
    MD5STEP(F3, c, d, a, b, i[ 3] + 0xd4ef3085, 16);
726
 
    MD5STEP(F3, b, c, d, a, i[ 6] + 0x04881d05, 23);
727
 
    MD5STEP(F3, a, b, c, d, i[ 9] + 0xd9d4d039,  4);
728
 
    MD5STEP(F3, d, a, b, c, i[12] + 0xe6db99e5, 11);
729
 
    MD5STEP(F3, c, d, a, b, i[15] + 0x1fa27cf8, 16);
730
 
    MD5STEP(F3, b, c, d, a, i[ 2] + 0xc4ac5665, 23);
731
 
 
732
 
    MD5STEP(F4, a, b, c, d, i[ 0] + 0xf4292244,  6);
733
 
    MD5STEP(F4, d, a, b, c, i[ 7] + 0x432aff97, 10);
734
 
    MD5STEP(F4, c, d, a, b, i[14] + 0xab9423a7, 15);
735
 
    MD5STEP(F4, b, c, d, a, i[ 5] + 0xfc93a039, 21);
736
 
    MD5STEP(F4, a, b, c, d, i[12] + 0x655b59c3,  6);
737
 
    MD5STEP(F4, d, a, b, c, i[ 3] + 0x8f0ccc92, 10);
738
 
    MD5STEP(F4, c, d, a, b, i[10] + 0xffeff47d, 15);
739
 
    MD5STEP(F4, b, c, d, a, i[ 1] + 0x85845dd1, 21);
740
 
    MD5STEP(F4, a, b, c, d, i[ 8] + 0x6fa87e4f,  6);
741
 
    MD5STEP(F4, d, a, b, c, i[15] + 0xfe2ce6e0, 10);
742
 
    MD5STEP(F4, c, d, a, b, i[ 6] + 0xa3014314, 15);
743
 
    MD5STEP(F4, b, c, d, a, i[13] + 0x4e0811a1, 21);
744
 
    MD5STEP(F4, a, b, c, d, i[ 4] + 0xf7537e82,  6);
745
 
    MD5STEP(F4, d, a, b, c, i[11] + 0xbd3af235, 10);
746
 
    MD5STEP(F4, c, d, a, b, i[ 2] + 0x2ad7d2bb, 15);
747
 
    MD5STEP(F4, b, c, d, a, i[ 9] + 0xeb86d391, 21);
748
 
 
749
 
    hashBuf[0] += a;
750
 
    hashBuf[1] += b;
751
 
    hashBuf[2] += c;
752
 
    hashBuf[3] += d;
753
 
}
754
 
 
755
 
 
756
 
 
757
 
 
758
 
 
759
 
//########################################################################
760
 
//########################################################################
761
 
//### T H R E A D
762
 
//########################################################################
763
 
//########################################################################
764
 
 
765
 
 
766
 
 
767
 
 
768
 
 
769
 
#ifdef __WIN32__
770
 
 
771
 
 
772
 
static DWORD WINAPI WinThreadFunction(LPVOID context)
773
 
{
774
 
    Thread *thread = (Thread *)context;
775
 
    thread->execute();
776
 
    return 0;
777
 
}
778
 
 
779
 
 
780
 
void Thread::start()
781
 
{
782
 
    DWORD dwThreadId;
783
 
    HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
784
 
               (LPVOID)this,  0,  &dwThreadId);
785
 
    //Make sure the thread is started before 'this' is deallocated
786
 
    while (!started)
787
 
        sleep(10);
788
 
    CloseHandle(hThread);
789
 
}
790
 
 
791
 
void Thread::sleep(unsigned long millis)
792
 
{
793
 
    Sleep(millis);
794
 
}
795
 
 
796
 
#else /* UNIX */
797
 
 
798
 
 
799
 
void *PthreadThreadFunction(void *context)
800
 
{
801
 
    Thread *thread = (Thread *)context;
802
 
    thread->execute();
803
 
    return NULL;
804
 
}
805
 
 
806
 
 
807
 
void Thread::start()
808
 
{
809
 
    pthread_t thread;
810
 
 
811
 
    int ret = pthread_create(&thread, NULL,
812
 
            PthreadThreadFunction, (void *)this);
813
 
    if (ret != 0)
814
 
        printf("Thread::start: thread creation failed: %s\n", strerror(ret));
815
 
 
816
 
    //Make sure the thread is started before 'this' is deallocated
817
 
    while (!started)
818
 
        sleep(10);
819
 
 
820
 
}
821
 
 
822
 
void Thread::sleep(unsigned long millis)
823
 
{
824
 
    timespec requested;
825
 
    requested.tv_sec = millis / 1000;
826
 
    requested.tv_nsec = (millis % 1000 ) * 1000000L;
827
 
    nanosleep(&requested, NULL);
828
 
}
829
 
 
830
 
#endif
831
 
 
832
 
 
833
 
 
834
 
 
835
 
 
836
 
 
837
 
 
838
 
 
839
 
//########################################################################
840
 
//########################################################################
841
 
//### S O C K E T
842
 
//########################################################################
843
 
//########################################################################
844
 
 
845
 
 
846
 
 
847
 
 
848
 
 
849
 
//#########################################################################
850
 
//# U T I L I T Y
851
 
//#########################################################################
852
 
 
853
 
static void mybzero(void *s, size_t n)
854
 
{
855
 
    unsigned char *p = (unsigned char *)s;
856
 
    while (n > 0)
857
 
        {
858
 
        *p++ = (unsigned char)0;
859
 
        n--;
860
 
        }
861
 
}
862
 
 
863
 
static void mybcopy(void *src, void *dest, size_t n)
864
 
{
865
 
    unsigned char *p = (unsigned char *)dest;
866
 
    unsigned char *q = (unsigned char *)src;
867
 
    while (n > 0)
868
 
        {
869
 
        *p++ = *q++;
870
 
        n--;
871
 
        }
872
 
}
873
 
 
874
 
 
875
 
 
876
 
//#########################################################################
877
 
//# T C P    C O N N E C T I O N
878
 
//#########################################################################
879
 
 
880
 
TcpSocket::TcpSocket()
881
 
{
882
 
    init();
883
 
}
884
 
 
885
 
 
886
 
TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
887
 
{
888
 
    init();
889
 
    hostname  = hostnameArg;
890
 
    portno    = port;
891
 
}
892
 
 
893
 
 
894
 
 
895
 
 
896
 
#ifdef HAVE_SSL
897
 
 
898
 
static void cryptoLockCallback(int mode, int type, const char */*file*/, int /*line*/)
899
 
{
900
 
    //printf("########### LOCK\n");
901
 
    static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
902
 
    const char *errstr = NULL;
903
 
 
904
 
    int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
905
 
    if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
906
 
        {
907
 
        errstr = "invalid mode";
908
 
        goto err;
909
 
        }
910
 
 
911
 
    if (type < 0 || type >= CRYPTO_NUM_LOCKS)
912
 
        {
913
 
        errstr = "type out of bounds";
914
 
        goto err;
915
 
        }
916
 
 
917
 
    if (mode & CRYPTO_LOCK)
918
 
        {
919
 
        if (modes[type])
920
 
            {
921
 
            errstr = "already locked";
922
 
            /* must not happen in a single-threaded program
923
 
             * (would deadlock)
924
 
             */
925
 
            goto err;
926
 
            }
927
 
 
928
 
        modes[type] = rw;
929
 
        }
930
 
    else if (mode & CRYPTO_UNLOCK)
931
 
        {
932
 
        if (!modes[type])
933
 
            {
934
 
             errstr = "not locked";
935
 
             goto err;
936
 
             }
937
 
 
938
 
        if (modes[type] != rw)
939
 
            {
940
 
            errstr = (rw == CRYPTO_READ) ?
941
 
                  "CRYPTO_r_unlock on write lock" :
942
 
                  "CRYPTO_w_unlock on read lock";
943
 
            }
944
 
 
945
 
        modes[type] = 0;
946
 
        }
947
 
    else
948
 
        {
949
 
        errstr = "invalid mode";
950
 
        goto err;
951
 
        }
952
 
 
953
 
    err:
954
 
    if (errstr)
955
 
        {
956
 
        //how do we pass a context pointer here?
957
 
        //error("openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d",
958
 
        //        errstr, mode, type, file, line);
959
 
        }
960
 
}
961
 
 
962
 
static unsigned long cryptoIdCallback()
963
 
{
964
 
#ifdef __WIN32__
965
 
    unsigned long ret = (unsigned long) GetCurrentThreadId();
966
 
#else
967
 
    unsigned long ret = (unsigned long) pthread_self();
968
 
#endif
969
 
    return ret;
970
 
}
971
 
 
972
 
#endif
973
 
 
974
 
 
975
 
TcpSocket::TcpSocket(const TcpSocket &other)
976
 
{
977
 
    init();
978
 
    sock      = other.sock;
979
 
    hostname  = other.hostname;
980
 
    portno    = other.portno;
981
 
}
982
 
 
983
 
 
984
 
void TcpSocket::error(const char *fmt, ...)
985
 
{
986
 
    static char buf[256];
987
 
    lastError = "TcpSocket err: ";
988
 
    va_list args;
989
 
    va_start(args, fmt);
990
 
    vsnprintf(buf, 255, fmt, args);
991
 
    va_end(args);
992
 
    lastError.append(buf);
993
 
    fprintf(stderr, "%s\n", lastError.c_str());
994
 
}
995
 
 
996
 
 
997
 
DOMString &TcpSocket::getLastError()
998
 
{
999
 
    return lastError;
1000
 
}
1001
 
 
1002
 
 
1003
 
 
1004
 
static bool tcp_socket_inited = false;
1005
 
 
1006
 
void TcpSocket::init()
1007
 
{
1008
 
    if (!tcp_socket_inited)
1009
 
        {
1010
 
#ifdef __WIN32__
1011
 
        WORD wVersionRequested = MAKEWORD( 2, 2 );
1012
 
        WSADATA wsaData;
1013
 
        WSAStartup( wVersionRequested, &wsaData );
1014
 
#endif
1015
 
#ifdef HAVE_SSL
1016
 
        if (libssl_is_present)
1017
 
        {
1018
 
        sslStream  = NULL;
1019
 
        sslContext = NULL;
1020
 
            CRYPTO_set_locking_callback(cryptoLockCallback);
1021
 
        CRYPTO_set_id_callback(cryptoIdCallback);
1022
 
        SSL_library_init();
1023
 
        SSL_load_error_strings();
1024
 
        }
1025
 
#endif
1026
 
        tcp_socket_inited = true;
1027
 
        }
1028
 
    sock           = -1;
1029
 
    connected      = false;
1030
 
    hostname       = "";
1031
 
    portno         = -1;
1032
 
    sslEnabled     = false;
1033
 
    receiveTimeout = 0;
1034
 
}
1035
 
 
1036
 
TcpSocket::~TcpSocket()
1037
 
{
1038
 
    disconnect();
1039
 
}
1040
 
 
1041
 
bool TcpSocket::isConnected()
1042
 
{
1043
 
    if (!connected || sock < 0)
1044
 
        return false;
1045
 
    return true;
1046
 
}
1047
 
 
1048
 
bool TcpSocket::getHaveSSL()
1049
 
{
1050
 
#ifdef HAVE_SSL
1051
 
    if (libssl_is_present)
1052
 
    {
1053
 
        return true;
1054
 
    } else {
1055
 
        return false;
1056
 
    }
1057
 
#else
1058
 
    return false;
1059
 
#endif
1060
 
}
1061
 
 
1062
 
void TcpSocket::enableSSL(bool val)
1063
 
{
1064
 
    sslEnabled = val;
1065
 
}
1066
 
 
1067
 
bool TcpSocket::getEnableSSL()
1068
 
{
1069
 
    return sslEnabled;
1070
 
}
1071
 
 
1072
 
 
1073
 
 
1074
 
bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1075
 
{
1076
 
    hostname = hostnameArg;
1077
 
    portno   = portnoArg;
1078
 
    return connect();
1079
 
}
1080
 
 
1081
 
 
1082
 
 
1083
 
#ifdef HAVE_SSL
1084
 
/*
1085
 
static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1086
 
{
1087
 
    char *password = "password";
1088
 
    if (bufLen < (int)(strlen(password)+1))
1089
 
        return 0;
1090
 
 
1091
 
    strcpy(buf,password);
1092
 
    int ret = strlen(password);
1093
 
    return ret;
1094
 
}
1095
 
 
1096
 
static void infoCallback(const SSL *ssl, int where, int ret)
1097
 
{
1098
 
    switch (where)
1099
 
        {
1100
 
        case SSL_CB_ALERT:
1101
 
            {
1102
 
            printf("## %d SSL ALERT: %s\n",  where, SSL_alert_desc_string_long(ret));
1103
 
            break;
1104
 
            }
1105
 
        default:
1106
 
            {
1107
 
            printf("## %d SSL: %s\n",  where, SSL_state_string_long(ssl));
1108
 
            break;
1109
 
            }
1110
 
        }
1111
 
}
1112
 
*/
1113
 
#endif
1114
 
 
1115
 
 
1116
 
bool TcpSocket::startTls()
1117
 
{
1118
 
#ifndef HAVE_SSL
1119
 
    error("SSL starttls() error:  client not compiled with SSL enabled");
1120
 
    return false;
1121
 
#else /*HAVE_SSL*/
1122
 
    if (!libssl_is_present)
1123
 
        {
1124
 
        error("SSL starttls() error:  the correct version of libssl was not found");
1125
 
        return false;
1126
 
        }
1127
 
 
1128
 
    sslStream  = NULL;
1129
 
    sslContext = NULL;
1130
 
 
1131
 
    //SSL_METHOD *meth = SSLv23_method();
1132
 
    //SSL_METHOD *meth = SSLv3_client_method();
1133
 
    SSL_METHOD *meth = TLSv1_client_method();
1134
 
    sslContext = SSL_CTX_new(meth);
1135
 
    //SSL_CTX_set_info_callback(sslContext, infoCallback);
1136
 
 
1137
 
    /**
1138
 
     * For now, let's accept all connections.  Ignore this
1139
 
     * block of code     
1140
 
     *       
1141
 
    char *keyFile  = "client.pem";
1142
 
    char *caList   = "root.pem";
1143
 
    //#  Load our keys and certificates
1144
 
    if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1145
 
        {
1146
 
        fprintf(stderr, "Can't read certificate file\n");
1147
 
        disconnect();
1148
 
        return false;
1149
 
        }
1150
 
 
1151
 
    SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1152
 
 
1153
 
    if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1154
 
        {
1155
 
        fprintf(stderr, "Can't read key file\n");
1156
 
        disconnect();
1157
 
        return false;
1158
 
        }
1159
 
 
1160
 
    //## Load the CAs we trust
1161
 
    if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1162
 
        {
1163
 
        fprintf(stderr, "Can't read CA list\n");
1164
 
        disconnect();
1165
 
        return false;
1166
 
        }
1167
 
    */
1168
 
 
1169
 
    /* Connect the SSL socket */
1170
 
    sslStream  = SSL_new(sslContext);
1171
 
    SSL_set_fd(sslStream, sock);
1172
 
 
1173
 
    int ret = SSL_connect(sslStream);
1174
 
    if (ret == 0)
1175
 
        {
1176
 
        error("SSL connection not successful");
1177
 
        disconnect();
1178
 
        return false;
1179
 
        }
1180
 
    else if (ret < 0)
1181
 
        {
1182
 
        int err = SSL_get_error(sslStream, ret);
1183
 
        error("SSL connect error %d", err);
1184
 
        disconnect();
1185
 
        return false;
1186
 
        }
1187
 
 
1188
 
    sslEnabled = true;
1189
 
    return true;
1190
 
#endif /* HAVE_SSL */
1191
 
}
1192
 
 
1193
 
 
1194
 
bool TcpSocket::connect()
1195
 
{
1196
 
    if (hostname.size()<1)
1197
 
        {
1198
 
        error("open: null hostname");
1199
 
        return false;
1200
 
        }
1201
 
 
1202
 
    if (portno<1)
1203
 
        {
1204
 
        error("open: bad port number");
1205
 
        return false;
1206
 
        }
1207
 
 
1208
 
    sock = socket(PF_INET, SOCK_STREAM, 0);
1209
 
    if (sock < 0)
1210
 
        {
1211
 
        error("open: error creating socket");
1212
 
        return false;
1213
 
        }
1214
 
 
1215
 
    char *c_hostname = (char *)hostname.c_str();
1216
 
    struct hostent *server = gethostbyname(c_hostname);
1217
 
    if (!server)
1218
 
        {
1219
 
        error("open: could not locate host '%s'", c_hostname);
1220
 
        return false;
1221
 
        }
1222
 
 
1223
 
    struct sockaddr_in serv_addr;
1224
 
    mybzero((char *) &serv_addr, sizeof(serv_addr));
1225
 
    serv_addr.sin_family = AF_INET;
1226
 
    mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1227
 
         server->h_length);
1228
 
    serv_addr.sin_port = htons(portno);
1229
 
 
1230
 
    int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1231
 
    if (ret < 0)
1232
 
        {
1233
 
        error("open: could not connect to host '%s'", c_hostname);
1234
 
        return false;
1235
 
        }
1236
 
 
1237
 
     if (sslEnabled)
1238
 
        {
1239
 
        if (!startTls())
1240
 
            return false;
1241
 
        }
1242
 
    connected = true;
1243
 
    return true;
1244
 
}
1245
 
 
1246
 
bool TcpSocket::disconnect()
1247
 
{
1248
 
    bool ret  = true;
1249
 
    connected = false;
1250
 
#ifdef HAVE_SSL
1251
 
    if (libssl_is_present)
1252
 
    {
1253
 
    if (sslEnabled)
1254
 
        {
1255
 
        if (sslStream)
1256
 
            {
1257
 
            int r = SSL_shutdown(sslStream);
1258
 
            switch(r)
1259
 
                {
1260
 
                case 1:
1261
 
                    break; /* Success */
1262
 
                case 0:
1263
 
                case -1:
1264
 
                default:
1265
 
                    error("Shutdown failed");
1266
 
                    ret = false;
1267
 
                }
1268
 
            SSL_free(sslStream);
1269
 
            }
1270
 
        if (sslContext)
1271
 
            SSL_CTX_free(sslContext);
1272
 
        }
1273
 
    sslStream  = NULL;
1274
 
    sslContext = NULL;
1275
 
    }
1276
 
#endif /*HAVE_SSL*/
1277
 
 
1278
 
#ifdef __WIN32__
1279
 
    closesocket(sock);
1280
 
#else
1281
 
    ::close(sock);
1282
 
#endif
1283
 
    sock = -1;
1284
 
    sslEnabled = false;
1285
 
 
1286
 
    return ret;
1287
 
}
1288
 
 
1289
 
 
1290
 
 
1291
 
bool TcpSocket::setReceiveTimeout(unsigned long millis)
1292
 
{
1293
 
    receiveTimeout = millis;
1294
 
    return true;
1295
 
}
1296
 
 
1297
 
/**
1298
 
 * For normal sockets, return the number of bytes waiting to be received.
1299
 
 * For SSL, just return >0 when something is ready to be read.
1300
 
 */
1301
 
long TcpSocket::available()
1302
 
{
1303
 
    if (!isConnected())
1304
 
        return -1;
1305
 
 
1306
 
    long count = 0;
1307
 
#ifdef __WIN32__
1308
 
    if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1309
 
        return -1;
1310
 
#else
1311
 
    if (ioctl(sock, FIONREAD, &count) != 0)
1312
 
        return -1;
1313
 
#endif
1314
 
    if (count<=0 && sslEnabled)
1315
 
        {
1316
 
#ifdef HAVE_SSL
1317
 
            if (libssl_is_present)
1318
 
                {
1319
 
            return SSL_pending(sslStream);
1320
 
                }
1321
 
#endif
1322
 
        }
1323
 
    return count;
1324
 
}
1325
 
 
1326
 
 
1327
 
 
1328
 
bool TcpSocket::write(int ch)
1329
 
{
1330
 
    if (!isConnected())
1331
 
        {
1332
 
        error("write: socket closed");
1333
 
        return false;
1334
 
        }
1335
 
    unsigned char c = (unsigned char)ch;
1336
 
 
1337
 
    if (sslEnabled)
1338
 
        {
1339
 
#ifdef HAVE_SSL
1340
 
        if (libssl_is_present)
1341
 
        {
1342
 
        int r = SSL_write(sslStream, &c, 1);
1343
 
        if (r<=0)
1344
 
            {
1345
 
            switch(SSL_get_error(sslStream, r))
1346
 
                {
1347
 
                default:
1348
 
                    error("SSL write problem");
1349
 
                    return -1;
1350
 
                }
1351
 
            }
1352
 
        }
1353
 
#endif
1354
 
        }
1355
 
    else
1356
 
        {
1357
 
        if (send(sock, (const char *)&c, 1, 0) < 0)
1358
 
        //if (send(sock, &c, 1, 0) < 0)
1359
 
            {
1360
 
            error("write: could not send data");
1361
 
            return false;
1362
 
            }
1363
 
        }
1364
 
    return true;
1365
 
}
1366
 
 
1367
 
bool TcpSocket::write(char *str)
1368
 
{
1369
 
   if (!isConnected())
1370
 
        {
1371
 
        error("write(str): socket closed");
1372
 
        return false;
1373
 
        }
1374
 
    int len = strlen(str);
1375
 
 
1376
 
    if (sslEnabled)
1377
 
        {
1378
 
#ifdef HAVE_SSL
1379
 
        if (libssl_is_present)
1380
 
        {
1381
 
        int r = SSL_write(sslStream, (unsigned char *)str, len);
1382
 
        if (r<=0)
1383
 
            {
1384
 
            switch(SSL_get_error(sslStream, r))
1385
 
                {
1386
 
                default:
1387
 
                    error("SSL write problem");
1388
 
                    return -1;
1389
 
                }
1390
 
            }
1391
 
        }
1392
 
#endif
1393
 
        }
1394
 
    else
1395
 
        {
1396
 
        if (send(sock, str, len, 0) < 0)
1397
 
        //if (send(sock, &c, 1, 0) < 0)
1398
 
            {
1399
 
            error("write: could not send data");
1400
 
            return false;
1401
 
            }
1402
 
        }
1403
 
    return true;
1404
 
}
1405
 
 
1406
 
bool TcpSocket::write(const std::string &str)
1407
 
{
1408
 
    return write((char *)str.c_str());
1409
 
}
1410
 
 
1411
 
int TcpSocket::read()
1412
 
{
1413
 
    if (!isConnected())
1414
 
        return -1;
1415
 
 
1416
 
    //We'll use this loop for timeouts, so that SSL and plain sockets
1417
 
    //will behave the same way
1418
 
    if (receiveTimeout > 0)
1419
 
        {
1420
 
        unsigned long tim = 0;
1421
 
        while (true)
1422
 
            {
1423
 
            int avail = available();
1424
 
            if (avail > 0)
1425
 
                break;
1426
 
            if (tim >= receiveTimeout)
1427
 
                return -2;
1428
 
            Thread::sleep(20);
1429
 
            tim += 20;
1430
 
            }
1431
 
        }
1432
 
 
1433
 
    //check again
1434
 
    if (!isConnected())
1435
 
        return -1;
1436
 
 
1437
 
    unsigned char ch;
1438
 
    if (sslEnabled)
1439
 
        {
1440
 
#ifdef HAVE_SSL
1441
 
        if (libssl_is_present)
1442
 
        {
1443
 
        if (!sslStream)
1444
 
            return -1;
1445
 
        int r = SSL_read(sslStream, &ch, 1);
1446
 
        unsigned long err = SSL_get_error(sslStream, r);
1447
 
        switch (err)
1448
 
            {
1449
 
            case SSL_ERROR_NONE:
1450
 
                 break;
1451
 
            case SSL_ERROR_ZERO_RETURN:
1452
 
                return -1;
1453
 
            case SSL_ERROR_SYSCALL:
1454
 
                error("SSL read problem(syscall) %s",
1455
 
                     ERR_error_string(ERR_get_error(), NULL));
1456
 
                return -1;
1457
 
            default:
1458
 
                error("SSL read problem %s",
1459
 
                     ERR_error_string(ERR_get_error(), NULL));
1460
 
                return -1;
1461
 
            }
1462
 
        }
1463
 
#endif
1464
 
        }
1465
 
    else
1466
 
        {
1467
 
        if (recv(sock, (char *)&ch, 1, 0) <= 0)
1468
 
            {
1469
 
            error("read: could not receive data");
1470
 
            disconnect();
1471
 
            return -1;
1472
 
            }
1473
 
        }
1474
 
    return (int)ch;
1475
 
}
1476
 
 
1477
 
std::string TcpSocket::readLine()
1478
 
{
1479
 
    std::string ret;
1480
 
 
1481
 
    while (isConnected())
1482
 
        {
1483
 
        int ch = read();
1484
 
        if (ch<0)
1485
 
            return ret;
1486
 
        if (ch=='\r' || ch=='\n')
1487
 
            return ret;
1488
 
        ret.push_back((char)ch);
1489
 
        }
1490
 
 
1491
 
    return ret;
1492
 
}
1493
 
 
1494
 
 
1495
 
 
1496
 
 
1497
 
 
1498
 
 
1499
 
 
1500
 
 
1501
 
 
1502
 
} //namespace Pedro
1503
 
//########################################################################
1504
 
//# E N D    O F     F I L E
1505
 
//########################################################################
1506
 
 
1507
 
 
1508
 
 
1509
 
 
1510
 
 
1511
 
 
1512
 
 
1513
 
 
1514
 
 
1515
 
 
1516