~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpinstall/wizard/libxpnet/src/nsHTTPConn.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/*
 
3
 * The contents of this file are subject to the Netscape Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/NPL/
 
7
 *
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 *
 
13
 * The Original Code is Mozilla Communicator client code, 
 
14
 * released March 31, 1998. 
 
15
 *
 
16
 * The Initial Developer of the Original Code is Netscape Communications 
 
17
 * Corporation.  Portions created by Netscape are
 
18
 * Copyright (C) 1998 Netscape Communications Corporation. All
 
19
 * Rights Reserved.
 
20
 *
 
21
 * Contributor(s): 
 
22
 *     Samir Gehani <sgehani@netscape.com>
 
23
 */
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#include <assert.h>
 
29
#include <sys/stat.h>
 
30
#include "nsHTTPConn.h"
 
31
#include "nsSocket.h"
 
32
 
 
33
const char kHTTPProto[8] = "http://";
 
34
const char kFTPProto[8] = "ftp://";
 
35
const int kHTTPPort = 80;
 
36
const int kFTPPort = 21;
 
37
const int kRespBufSize = 1024;
 
38
const int kReqBufSize = 4096;
 
39
const int kHdrBufSize = 4096;
 
40
const char kCRLF[3] = "\r\n";
 
41
const char kHdrBodyDelim[5] = "\r\n\r\n";
 
42
const char kDefaultDestFile[11] = "index.html";
 
43
 
 
44
nsHTTPConn::nsHTTPConn(char *aHost, int aPort, char *aPath, int (*aEventPumpCB)(void)): 
 
45
    mEventPumpCB(aEventPumpCB),
 
46
    mHost(aHost),
 
47
    mPath(aPath),
 
48
    mProxiedURL(NULL),
 
49
    mProxyUser(NULL),
 
50
    mProxyPswd(NULL),
 
51
    mDestFile(NULL),
 
52
    mHostPathAllocd(FALSE),
 
53
    mSocket(NULL)
 
54
{
 
55
    if (aPort <= 0)
 
56
        mPort = kHTTPPort;
 
57
    else
 
58
        mPort = aPort;
 
59
 
 
60
    DUMP(("mHost = %s\n", mHost));
 
61
    DUMP(("mPort = %d\n", mPort));
 
62
    DUMP(("mPath = %s\n", mPath));
 
63
}
 
64
 
 
65
nsHTTPConn::nsHTTPConn(char *aHost, int aPort, char *aPath) :
 
66
    mEventPumpCB(NULL),
 
67
    mHost(aHost),
 
68
    mPath(aPath),
 
69
    mProxiedURL(NULL),
 
70
    mProxyUser(NULL),
 
71
    mProxyPswd(NULL),
 
72
    mDestFile(NULL),
 
73
    mHostPathAllocd(FALSE),
 
74
    mSocket(NULL)
 
75
{
 
76
    if (aPort <= 0)
 
77
        mPort = kHTTPPort;
 
78
    else
 
79
        mPort = aPort;
 
80
 
 
81
    DUMP(("mHost = %s\n", mHost));
 
82
    DUMP(("mPort = %d\n", mPort));
 
83
    DUMP(("mPath = %s\n", mPath));
 
84
}
 
85
 
 
86
nsHTTPConn::nsHTTPConn(char *aURL, int (*aEventPumpCB)(void)) :
 
87
    mEventPumpCB(aEventPumpCB),
 
88
    mPort(kHTTPPort),
 
89
    mProxiedURL(NULL),
 
90
    mProxyUser(NULL),
 
91
    mProxyPswd(NULL),
 
92
    mDestFile(NULL),
 
93
    mHostPathAllocd(FALSE),
 
94
    mSocket(NULL),
 
95
    mResponseCode(0)
 
96
{
 
97
    // parse URL
 
98
    if (ParseURL(kHTTPProto, aURL, &mHost, &mPort, &mPath) == OK)
 
99
        mHostPathAllocd = TRUE;
 
100
    else
 
101
    {
 
102
        mHost = NULL;
 
103
        mPath = NULL;
 
104
    }
 
105
 
 
106
    DUMP(("mHost = %s\n", mHost));
 
107
    DUMP(("mPort = %d\n", mPort));
 
108
    DUMP(("mPath = %s\n", mPath));
 
109
}
 
110
 
 
111
nsHTTPConn::nsHTTPConn(char *aURL) :
 
112
    mEventPumpCB(NULL),
 
113
    mPort(kHTTPPort),
 
114
    mProxiedURL(NULL),
 
115
    mProxyUser(NULL),
 
116
    mProxyPswd(NULL),
 
117
    mDestFile(NULL),
 
118
    mHostPathAllocd(FALSE),
 
119
    mSocket(NULL),
 
120
    mResponseCode(0)
 
121
{
 
122
    // parse URL
 
123
    if (ParseURL(kHTTPProto, aURL, &mHost, &mPort, &mPath) == OK)
 
124
        mHostPathAllocd = TRUE;
 
125
    else
 
126
    {
 
127
        mHost = NULL;
 
128
        mPath = NULL;
 
129
    }
 
130
 
 
131
    DUMP(("mHost = %s\n", mHost));
 
132
    DUMP(("mPort = %d\n", mPort));
 
133
    DUMP(("mPath = %s\n", mPath));
 
134
}
 
135
 
 
136
nsHTTPConn::~nsHTTPConn()
 
137
{
 
138
    if (mHostPathAllocd)
 
139
    {
 
140
        if (mHost)
 
141
            free(mHost);
 
142
        if (mPath)
 
143
            free(mPath);
 
144
    }
 
145
}
 
146
    
 
147
int
 
148
nsHTTPConn::Open()
 
149
{
 
150
    // verify host && path
 
151
    if (!mHost || !mPath)
 
152
        return E_MALFORMED_URL;
 
153
 
 
154
    // create socket
 
155
    mSocket = new nsSocket(mHost, mPort, mEventPumpCB);
 
156
    if (!mSocket)
 
157
        return E_MEM;
 
158
 
 
159
    // open socket
 
160
    return mSocket->Open();
 
161
}
 
162
 
 
163
int
 
164
nsHTTPConn::ResumeOrGet(HTTPGetCB aCallback, char *aDestFile)
 
165
{
 
166
    struct stat stbuf;
 
167
    int rv = 0;
 
168
    int resPos = 0;
 
169
    
 
170
    if (!aDestFile)
 
171
        return E_PARAM;
 
172
 
 
173
    /* stat local file */
 
174
    rv = stat(aDestFile, &stbuf);
 
175
    if (rv == 0)
 
176
        resPos = stbuf.st_size;
 
177
 
 
178
    return Get(aCallback, aDestFile, resPos);
 
179
 
 
180
    // XXX TO DO:
 
181
    // XXX handle proxies
 
182
}
 
183
 
 
184
int 
 
185
nsHTTPConn::Get(HTTPGetCB aCallback, char *aDestFile)
 
186
{
 
187
    // deprecated API; wrapper for backwards compatibility
 
188
 
 
189
    return ResumeOrGet(aCallback, aDestFile);
 
190
}
 
191
 
 
192
int
 
193
nsHTTPConn::Get(HTTPGetCB aCallback, char *aDestFile, int aResumePos)
 
194
{
 
195
    int rv;
 
196
    char *pathToUse;
 
197
 
 
198
    // verify host && path
 
199
    if (!mHost || !mPath)
 
200
        return E_MALFORMED_URL;
 
201
 
 
202
    if (!aDestFile)
 
203
    {
 
204
        if (mProxiedURL)
 
205
            pathToUse = mProxiedURL;
 
206
        else
 
207
            pathToUse = mPath;
 
208
 
 
209
        // no leaf: assume default file 'index.html'
 
210
        if (*(pathToUse + strlen(pathToUse) - 1) == '/')
 
211
            aDestFile = (char *) kDefaultDestFile;
 
212
        else
 
213
            aDestFile = strrchr(pathToUse, '/') + 1;
 
214
    }
 
215
 
 
216
    // issue request
 
217
    rv = Request(aResumePos);
 
218
 
 
219
    // recv response
 
220
    if (rv == OK)
 
221
        rv = Response(aCallback, aDestFile, aResumePos);
 
222
 
 
223
    return rv;
 
224
}
 
225
 
 
226
int
 
227
nsHTTPConn::Close()
 
228
{
 
229
    int rv;
 
230
 
 
231
    // close socket
 
232
    rv = mSocket->Close();
 
233
 
 
234
    // destroy socket
 
235
    delete mSocket;
 
236
 
 
237
    return rv;
 
238
}
 
239
 
 
240
void
 
241
nsHTTPConn::SetProxyInfo(char *aProxiedURL, char *aProxyUser, 
 
242
                                            char *aProxyPswd)
 
243
{
 
244
    mProxiedURL = aProxiedURL;
 
245
    mProxyUser = aProxyUser;
 
246
    mProxyPswd = aProxyPswd;
 
247
}
 
248
 
 
249
int
 
250
nsHTTPConn::Request(int aResumePos)
 
251
{
 
252
    char req[kReqBufSize];
 
253
    char hdr[kHdrBufSize];
 
254
    int rv;
 
255
 
 
256
    memset(req, 0, kReqBufSize);
 
257
 
 
258
    // format header buf:
 
259
 
 
260
    // request line
 
261
    memset(hdr, 0, kHdrBufSize);
 
262
    if (mProxiedURL)
 
263
    {
 
264
        char *host = NULL, *path = NULL;
 
265
        char proto[8];
 
266
        int port;
 
267
#ifdef DEBUG
 
268
        assert(sizeof hdr > (strlen(mProxiedURL) + 15 ));
 
269
#endif
 
270
        sprintf(hdr, "GET %s HTTP/1.0%s", mProxiedURL, kCRLF);
 
271
        strcpy(req, hdr);
 
272
        if (strncmp(mProxiedURL, kFTPProto, strlen(kFTPProto)) == 0) 
 
273
        {
 
274
            strcpy(proto,kFTPProto);
 
275
            port = kFTPPort;
 
276
        } 
 
277
        else 
 
278
        {
 
279
            strcpy(proto,kHTTPProto);
 
280
            port = kHTTPPort;
 
281
        }
 
282
        rv = ParseURL(proto, mProxiedURL,
 
283
                      &host, &port, &path);
 
284
        if (rv == OK) {
 
285
            memset(hdr, 0, kHdrBufSize);
 
286
            sprintf(hdr, "Host: %s:%d%s", host, port, kCRLF);
 
287
            strcat(req, hdr);
 
288
        }
 
289
        if (host)
 
290
            free(host);
 
291
        if (path)
 
292
            free(path);
 
293
    }
 
294
    else
 
295
    {
 
296
        sprintf(hdr, "GET %s HTTP/1.0%s", mPath, kCRLF);
 
297
        strcpy(req, hdr);
 
298
 
 
299
        memset(hdr, 0, kHdrBufSize);
 
300
        sprintf(hdr, "Host: %s%s", mHost, kCRLF);
 
301
        strcat(req, hdr);
 
302
    }
 
303
 
 
304
    // if proxy set and proxy user/pswd set
 
305
    if (mProxyUser && mProxyPswd)
 
306
    {
 
307
        char *usrPsd = (char *) malloc(strlen(mProxyUser) +
 
308
                                       strlen(":")        +
 
309
                                       strlen(mProxyPswd) + 1);
 
310
        if (!usrPsd)
 
311
            return E_MEM;
 
312
        sprintf(usrPsd, "%s:%s", mProxyUser, mProxyPswd);
 
313
 
 
314
        // base 64 encode proxy header
 
315
        char usrPsdEncoded[128];  // pray that 128 is long enough 
 
316
        memset(usrPsdEncoded, 0, 128);
 
317
 
 
318
        DUMP(("Unencoded string: %s\n", usrPsd));
 
319
        rv = Base64Encode((const unsigned char *)usrPsd, strlen(usrPsd),
 
320
                          usrPsdEncoded, 128);
 
321
        DUMP(("Encoded string: %s\n", usrPsdEncoded));
 
322
        DUMP(("Base64Encode returned: %d\n", rv));
 
323
        if (rv <= 0)
 
324
        {
 
325
            return E_B64_ENCODE;
 
326
        }
 
327
 
 
328
        // append proxy header to header buf
 
329
        memset(hdr, 0, kHdrBufSize);
 
330
        sprintf(hdr, "Proxy-authorization: Basic %s%s", usrPsdEncoded, kCRLF);
 
331
        strcat(req, hdr);
 
332
 
 
333
        // XXX append host with port 21 if ftp
 
334
        
 
335
    }
 
336
 
 
337
    // byte range support
 
338
    if (aResumePos > 0)
 
339
    {
 
340
        sprintf(hdr, "Range: bytes=%d-%s", aResumePos, kCRLF);
 
341
        strcat(req, hdr);
 
342
    }
 
343
 
 
344
    // headers all done so indicate
 
345
    strcat(req, kCRLF);
 
346
 
 
347
    // send header buf over socket
 
348
    int bufSize = strlen(req);
 
349
    rv = mSocket->Send((unsigned char *) req, &bufSize);
 
350
    DUMP(("\n\n%s", req));
 
351
 
 
352
    if (bufSize != (int) strlen(req))
 
353
        rv = E_REQ_INCOMPLETE;
 
354
 
 
355
    return rv;
 
356
}
 
357
 
 
358
int 
 
359
nsHTTPConn::Response(HTTPGetCB aCallback, char *aDestFile, int aResumePos)
 
360
{
 
361
    // NOTE: overwrites dest file if it already exists
 
362
 
 
363
    int rv = OK;
 
364
    char resp[kRespBufSize];
 
365
    int bufSize, total = 0, fwriteLen, fwrote, bytesWritten = 0, expectedSize = 0;
 
366
    FILE *destFd;
 
367
    char *fwritePos;
 
368
    int bFirstIter = TRUE;
 
369
 
 
370
    if (!aDestFile)
 
371
        return E_PARAM;
 
372
 
 
373
    // open dest file 
 
374
    if (aResumePos > 0)
 
375
    {
 
376
        destFd = fopen(aDestFile, "r+b");
 
377
        if (!destFd)
 
378
            return E_OPEN_FILE;
 
379
 
 
380
        if (fseek(destFd, aResumePos, SEEK_SET) != 0)
 
381
        {
 
382
            fclose(destFd);
 
383
            return E_SEEK_FILE;
 
384
        }
 
385
    }
 
386
    else
 
387
    {
 
388
        destFd = fopen(aDestFile, "w+b");
 
389
        if (!destFd)
 
390
            return E_OPEN_FILE;
 
391
    }
 
392
 
 
393
    // iteratively recv response 
 
394
    do
 
395
    {
 
396
        memset(resp, 0, kRespBufSize);
 
397
        bufSize = kRespBufSize;       
 
398
        
 
399
        rv = mSocket->Recv((unsigned char *) resp, &bufSize);
 
400
        DUMP(("nsSocket::Recv returned: %d\t and recd: %d\n", rv, bufSize));
 
401
 
 
402
        if(rv == nsSocket::E_EOF_FOUND || (rv != nsSocket::E_READ_MORE && rv != nsSocket::OK) ) {
 
403
            break;
 
404
        }
 
405
 
 
406
        if (bFirstIter)
 
407
        {
 
408
            fwritePos = strstr(resp, kHdrBodyDelim);
 
409
            if (fwritePos == NULL)
 
410
            {
 
411
                // XXX  no header!  should we handle?
 
412
                fwritePos = resp;
 
413
                fwriteLen = bufSize;
 
414
            }
 
415
            else
 
416
            {
 
417
                ParseResponseCode((const char *)resp, &mResponseCode);
 
418
                
 
419
                if ( mResponseCode < 200 || mResponseCode >=300 )
 
420
                {
 
421
                  // if we don't get a response code in the 200 range then fail
 
422
                  // TODO: handle the response codes in the 300 range
 
423
                  rv = nsHTTPConn::E_HTTP_RESPONSE;
 
424
                  break;
 
425
                }
 
426
 
 
427
                ParseContentLength((const char *)resp, &expectedSize);
 
428
 
 
429
                // move past hdr-body delimiter
 
430
                fwritePos += strlen(kHdrBodyDelim);
 
431
                fwriteLen = bufSize - (fwritePos - resp);
 
432
                total = expectedSize + aResumePos;
 
433
            }
 
434
 
 
435
            bFirstIter = FALSE;
 
436
        }
 
437
        else
 
438
        {
 
439
            fwritePos = resp;
 
440
            fwriteLen = bufSize;
 
441
        }
 
442
 
 
443
        fwrote = fwrite(fwritePos, sizeof(char), fwriteLen, destFd);
 
444
        assert(fwrote == fwriteLen);
 
445
 
 
446
        if (fwriteLen > 0)
 
447
            bytesWritten += fwriteLen;
 
448
        if (aCallback && 
 
449
           (aCallback(bytesWritten, total) == E_USER_CANCEL))
 
450
              rv = E_USER_CANCEL; // we want to ignore all errors returned
 
451
                                  // from aCallback() except E_USER_CANCEL 
 
452
 
 
453
        if ( mEventPumpCB )
 
454
            mEventPumpCB();
 
455
 
 
456
    } while ( rv == nsSocket::E_READ_MORE || rv == nsSocket::OK);
 
457
    
 
458
    if ( bytesWritten == expectedSize && rv != nsHTTPConn::E_HTTP_RESPONSE)
 
459
        rv = nsSocket::E_EOF_FOUND;
 
460
        
 
461
    if (rv == nsSocket::E_EOF_FOUND)
 
462
    {
 
463
        DUMP(("EOF detected\n"));
 
464
        rv = OK;
 
465
    }
 
466
 
 
467
    fclose(destFd);
 
468
 
 
469
    return rv;
 
470
}
 
471
 
 
472
int
 
473
nsHTTPConn::ParseURL(const char *aProto, char *aURL, char **aHost, 
 
474
                     int *aPort, char **aPath)
 
475
{
 
476
    char *pos, *nextSlash, *nextColon, *end, *hostEnd;
 
477
    int protoLen = strlen(aProto);
 
478
 
 
479
    if (!aURL || !aHost || !aPort || !aPath || !aProto)
 
480
        return E_PARAM;
 
481
 
 
482
    if ((strncmp(aURL, aProto, protoLen) != 0) ||
 
483
        (strlen(aURL) < 9))
 
484
        return E_MALFORMED_URL;
 
485
 
 
486
    pos = aURL + protoLen;
 
487
    nextColon = strchr(pos, ':');
 
488
    nextSlash = strchr(pos, '/');
 
489
 
 
490
    // optional port specification
 
491
    if (nextColon && ((nextSlash && nextColon < nextSlash) || 
 
492
                       !nextSlash))
 
493
    {
 
494
        int portStrLen;
 
495
        if (nextSlash)
 
496
            portStrLen = nextSlash - nextColon;
 
497
        else
 
498
            portStrLen = strlen(nextColon);
 
499
 
 
500
        char *portStr = (char *) malloc(portStrLen + 1);
 
501
        if (!portStr)
 
502
            return E_MEM;
 
503
        memset(portStr, 0, portStrLen + 1);
 
504
        strncpy(portStr, nextColon+1, portStrLen);
 
505
        *aPort = atoi(portStr);
 
506
        free(portStr);
 
507
    }
 
508
    if ( (!nextColon || (nextSlash && (nextColon > nextSlash)))
 
509
         && *aPort <= 0) // don't override port if already set
 
510
        *aPort = -1;
 
511
 
 
512
    // only host in URL, assume '/' for path
 
513
    if (!nextSlash)
 
514
    {
 
515
        int copyLen;
 
516
        if (nextColon)
 
517
            copyLen = nextColon - pos;
 
518
        else
 
519
            copyLen = strlen(pos);
 
520
 
 
521
        *aHost = (char *) malloc(copyLen + 1); // to NULL terminate
 
522
        if (!aHost)
 
523
            return E_MEM;
 
524
        memset(*aHost, 0, copyLen + 1);
 
525
        strncpy(*aHost, pos, copyLen);
 
526
 
 
527
        *aPath = (char *) malloc(2);
 
528
        strcpy(*aPath, "/");
 
529
 
 
530
        return OK;
 
531
    }
 
532
    
 
533
    // normal parsing: both host and path exist
 
534
    if (nextColon)
 
535
        hostEnd = nextColon;
 
536
    else
 
537
        hostEnd = nextSlash;
 
538
    *aHost = (char *) malloc(hostEnd - pos + 1); // to NULL terminate
 
539
    if (!*aHost)
 
540
        return E_MEM;
 
541
                memset(*aHost, 0, hostEnd - pos + 1);
 
542
    strncpy(*aHost, pos, hostEnd - pos);
 
543
    *(*aHost + (hostEnd - pos)) = 0; // NULL terminate
 
544
 
 
545
    pos = nextSlash;
 
546
    end = aURL + strlen(aURL);
 
547
 
 
548
    *aPath = (char *) malloc(end - pos + 1);
 
549
    if (!*aPath)
 
550
    {
 
551
        if (*aHost)
 
552
            free(*aHost);
 
553
        return E_MEM;
 
554
    }
 
555
    memset(*aPath, 0, end - pos + 1);
 
556
    strncpy(*aPath, pos, end - pos);
 
557
 
 
558
    return OK;
 
559
}
 
560
 
 
561
void
 
562
nsHTTPConn::ParseResponseCode(const char *aBuf, int *aCode)
 
563
{
 
564
  char codeStr[4];
 
565
  const char *pos;
 
566
 
 
567
  if (!aBuf || !aCode)
 
568
    return;
 
569
 
 
570
  // make sure the beginning of the buffer is the HTTP status code
 
571
  if (strncmp(aBuf,"HTTP/",5) == 0)
 
572
  {
 
573
    pos = strstr(aBuf," ");  // find the space before the code
 
574
    ++pos;                   // move to the beginning of the code
 
575
    strncpy((char *)codeStr,pos, 3);
 
576
    codeStr[3] = '\0';
 
577
    *aCode = atoi(codeStr);
 
578
  }
 
579
}
 
580
 
 
581
void
 
582
nsHTTPConn::ParseContentLength(const char *aBuf, int *aLength)
 
583
{
 
584
    const char *clHdr; // Content-length header line start
 
585
    const char *eol, *pos;
 
586
    char clNameStr1[16] = "Content-length:";
 
587
    char clNameStr2[16] = "Content-Length:";
 
588
    char *clNameStr = clNameStr1;
 
589
 
 
590
    if (!aBuf || !aLength)
 
591
        return;  // non fatal so no error codes returned
 
592
    *aLength = 0;
 
593
 
 
594
    // XXX strcasestr() needs to be ported for Solaris (and Win32 and Mac?)
 
595
    clHdr = strstr(aBuf, (char *)clNameStr1);
 
596
    if (!clHdr)
 
597
    {
 
598
        clHdr = strstr(aBuf, (char *)clNameStr2);
 
599
        clNameStr = clNameStr2;
 
600
    }
 
601
    if (clHdr)
 
602
    {
 
603
        eol = strstr(clHdr, kCRLF); // end of line
 
604
        pos = clHdr + strlen(clNameStr);
 
605
        while ((pos < eol) && (*pos == ' ' || *pos == '\t'))
 
606
            pos++;
 
607
        if (pos < eol)
 
608
        {
 
609
            int clValStrLen = eol - pos + 1; // extra byte to NULL terminate
 
610
            char *clValStr = (char *) malloc(clValStrLen);
 
611
            if (!clValStr)
 
612
                return; // imminent doom!
 
613
 
 
614
            memset(clValStr, 0, clValStrLen);
 
615
            strncpy(clValStr, pos, eol - pos);
 
616
            *aLength = atoi(clValStr);
 
617
        }
 
618
    } 
 
619
}
 
620
 
 
621
int 
 
622
nsHTTPConn::Base64Encode(const unsigned char *in_str, int in_len, 
 
623
                         char *out_str, int out_len)
 
624
{
 
625
    // NOTE: shamelessly copied from nsAbSyncPostEngine.cpp
 
626
 
 
627
    static unsigned char base64[] =
 
628
    {  
 
629
      /* 0    1    2    3    4    5    6    7        */ 
 
630
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 0 */
 
631
        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 1 */ 
 
632
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 2 */ 
 
633
        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 3 */ 
 
634
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 4 */ 
 
635
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 5 */ 
 
636
        'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 6 */
 
637
        '4', '5', '6', '7', '8', '9', '+', '/'  /* 7 */ 
 
638
    };
 
639
 
 
640
    int curr_out_len = 0;
 
641
 
 
642
    int i = 0;
 
643
    unsigned char a, b, c;
 
644
 
 
645
    out_str[0] = '\0';
 
646
    
 
647
    if (in_len > 0)
 
648
    {
 
649
 
 
650
        while (i < in_len)
 
651
        {
 
652
            a = in_str[i];
 
653
            b = (i + 1 >= in_len) ? 0 : in_str[i + 1];
 
654
            c = (i + 2 >= in_len) ? 0 : in_str[i + 2];
 
655
 
 
656
            if (i + 2 < in_len)
 
657
            {
 
658
                out_str[curr_out_len++] = (base64[(a >> 2) & 0x3F]);
 
659
                out_str[curr_out_len++] = (base64[((a << 4) & 0x30)
 
660
                                            + ((b >> 4) & 0xf)]);
 
661
                out_str[curr_out_len++] = (base64[((b << 2) & 0x3c)
 
662
                                            + ((c >> 6) & 0x3)]);
 
663
                out_str[curr_out_len++] = (base64[c & 0x3F]);
 
664
            }
 
665
            else if (i + 1 < in_len)
 
666
            {
 
667
                out_str[curr_out_len++] = (base64[(a >> 2) & 0x3F]);
 
668
                out_str[curr_out_len++] = (base64[((a << 4) & 0x30)
 
669
                                            + ((b >> 4) & 0xf)]);
 
670
                out_str[curr_out_len++] = (base64[((b << 2) & 0x3c)
 
671
                                            + ((c >> 6) & 0x3)]);
 
672
                out_str[curr_out_len++] = '=';
 
673
            }
 
674
            else
 
675
            {
 
676
                out_str[curr_out_len++] = (base64[(a >> 2) & 0x3F]);
 
677
                out_str[curr_out_len++] = (base64[((a << 4) & 0x30)
 
678
                                            + ((b >> 4) & 0xf)]);
 
679
                out_str[curr_out_len++] = '=';
 
680
                out_str[curr_out_len++] = '=';
 
681
            }
 
682
 
 
683
            i += 3;
 
684
 
 
685
            if ((curr_out_len + 4) > out_len)
 
686
            {
 
687
                return(-1);
 
688
            }
 
689
 
 
690
        }
 
691
        out_str[curr_out_len] = '\0';
 
692
    }
 
693
    
 
694
    return curr_out_len;
 
695
}
 
696
 
 
697
#ifdef TEST_NSHTTPCONN
 
698
 
 
699
int
 
700
TestHTTPCB(int aBytesRd, int aTotal)
 
701
{
 
702
    DUMP(("Bytes rd: %d\tTotal: %d\n", aBytesRd, aTotal));
 
703
    return 0;
 
704
}
 
705
 
 
706
int
 
707
main(int argc, char **argv)
 
708
{
 
709
    nsHTTPConn *conn;
 
710
    int rv = nsHTTPConn::OK;
 
711
    char *proxiedURL = NULL;
 
712
    char *proxyUser = NULL;
 
713
    char *proxyPswd = NULL;
 
714
 
 
715
    DUMP(("*** %s: A self-test for the nsHTTPConn class.\n", argv[0]));
 
716
 
 
717
    if (argc < 2)
 
718
    {
 
719
        printf("usage: %s <http_url> [<proxied_url> [<proxy_user> ", argv[0]);
 
720
        printf("<proxy_pswd>]]\n");
 
721
        exit(1);
 
722
    }
 
723
 
 
724
    conn = new nsHTTPConn(argv[1]);
 
725
 
 
726
    if (argc >= 3)
 
727
    {
 
728
        proxiedURL = argv[2];
 
729
    }
 
730
    if (argc >= 5)
 
731
    {
 
732
        proxyUser = argv[3];
 
733
        proxyPswd = argv[4];
 
734
    }
 
735
 
 
736
    conn->SetProxyInfo(proxiedURL, proxyUser, proxyPswd);
 
737
 
 
738
    rv = conn->Open();
 
739
    DUMP(("nsHTTPConn::Open returned: %d\n", rv));
 
740
 
 
741
    rv = conn->Get(TestHTTPCB, NULL); // NULL: local file name = URL leaf
 
742
    DUMP(("nsHTTPConn::Get returned: %d\n", rv));
 
743
 
 
744
    rv = conn->Close();
 
745
    DUMP(("nsHTTPConn::Close returned: %d\n", rv));
 
746
 
 
747
    return 0;
 
748
}
 
749
 
 
750
#endif /* TEST_NSHTTPCONN */