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

« back to all changes in this revision

Viewing changes to mozilla/xpinstall/wizard/unix/src2/nsXIEngine.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
 *     Syd Logan syd@netscape.com
 
24
 */
 
25
 
 
26
#include "nsFTPConn.h"
 
27
#include "nsHTTPConn.h"
 
28
#include "nsXIEngine.h"
 
29
 
 
30
#include <errno.h>
 
31
#include <stdlib.h>
 
32
 
 
33
#define CORE_LIB_COUNT 11
 
34
 
 
35
const char kHTTPProto[] = "http://";
 
36
const char kFTPProto[] = "ftp://";
 
37
const char kDLMarkerPath[] = "./xpi/.current_download";
 
38
 
 
39
nsXIEngine::nsXIEngine() :
 
40
    mTmp(NULL),
 
41
    mTotalComps(0),
 
42
    mOriginalDir(NULL)
 
43
{
 
44
}
 
45
 
 
46
#define RM_PREFIX "rm -rf "
 
47
 
 
48
nsXIEngine::~nsXIEngine()   
 
49
{
 
50
    DUMP("~nsXIEngine");
 
51
 
 
52
    // reset back to original directory
 
53
    chdir(mOriginalDir);
 
54
 
 
55
    if ( mTmp != (char *) NULL ) {
 
56
 
 
57
      // blow away the temp dir 
 
58
 
 
59
      char *buf;
 
60
      buf = (char *) malloc( strlen(RM_PREFIX) + strlen( mTmp ) + 1 );
 
61
      if ( buf != (char *) NULL ) {
 
62
        strcpy( buf, RM_PREFIX );
 
63
        strcat( buf, mTmp );
 
64
        system( buf ); 
 
65
        XI_IF_FREE(mTmp);
 
66
        free( buf );
 
67
      }
 
68
    }
 
69
    XI_IF_FREE(mOriginalDir);
 
70
}
 
71
 
 
72
int     
 
73
EventPumpCB(void)
 
74
{
 
75
    return 0;
 
76
}
 
77
 
 
78
#define MAXCRC 4
 
79
 
 
80
int     
 
81
nsXIEngine::Download(int aCustom, nsComponentList *aComps)
 
82
{
 
83
    DUMP("Download");
 
84
 
 
85
    if (!aComps)
 
86
        return E_PARAM;
 
87
 
 
88
    int err = OK;
 
89
    nsComponent *currComp = aComps->GetHead(), *markedComp = NULL;
 
90
    nsComponent *currCompSave;
 
91
    char *currURL = NULL;
 
92
    char *currHost = NULL;
 
93
    char *currPath = NULL;
 
94
    char localPath[MAXPATHLEN];
 
95
    char *srvPath = NULL;
 
96
    char *proxyURL = NULL;
 
97
    char *qualURL = NULL;
 
98
    int i, crcPass, bDone;
 
99
    int currPort;
 
100
    struct stat stbuf;
 
101
    int resPos = 0;
 
102
    int fileSize = 0;
 
103
    int currCompNum = 1, markedCompNum = 0;
 
104
    int numToDL = 0; // num xpis to download
 
105
    int passCount;
 
106
    CONN myConn;
 
107
    
 
108
    err = GetDLMarkedComp(aComps, aCustom, &markedComp, &markedCompNum);
 
109
    if (err == OK && markedComp)
 
110
    {
 
111
        currComp = markedComp;
 
112
        currCompNum = markedCompNum;
 
113
        sprintf(localPath, "%s/%s", XPI_DIR, currComp->GetArchive());
 
114
        currComp->SetResumePos(GetFileSize(localPath));
 
115
    }
 
116
    else
 
117
    {
 
118
        // if all .xpis exist in the ./xpi dir (blob/CD) 
 
119
        // we don't need to download
 
120
        if (ExistAllXPIs(aCustom, aComps, &mTotalComps))
 
121
            return OK; 
 
122
    }
 
123
 
 
124
    // check if ./xpi dir exists else create it
 
125
    if (0 != stat(XPI_DIR, &stbuf))
 
126
    {
 
127
        if (0 != mkdir(XPI_DIR, 0755))
 
128
            return E_MKDIR_FAIL;
 
129
    }
 
130
 
 
131
    numToDL = TotalToDownload(aCustom, aComps);
 
132
 
 
133
    myConn.URL = (char *) NULL;
 
134
    myConn.type = TYPE_UNDEF;
 
135
 
 
136
    crcPass = 0;
 
137
    currCompSave = currComp;
 
138
    bDone = 0;
 
139
    while ( bDone == 0 && crcPass < MAXCRC ) {
 
140
      passCount = 0;
 
141
      while (currComp)
 
142
      {
 
143
        if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) )
 
144
        {
 
145
            // in case we are resuming inter- or intra-installer session
 
146
            if (currComp->IsDownloaded())
 
147
            {
 
148
                currComp = currComp->GetNext();
 
149
                continue;
 
150
            }
 
151
 
 
152
            SetDLMarker(currComp->GetArchive());
 
153
 
 
154
            for (i = 0; i < MAX_URLS; i++)
 
155
            {
 
156
                currURL = currComp->GetURL(i);
 
157
                if (!currURL) break;
 
158
                
 
159
                if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
 
160
                    nsInstallDlg::SetDownloadComp(currComp, i, 
 
161
                        currCompNum, numToDL);
 
162
 
 
163
                // restore resume position
 
164
                resPos = currComp->GetResumePos();
 
165
 
 
166
                // has a proxy server been specified?
 
167
                if (gCtx->opt->mProxyHost && gCtx->opt->mProxyPort)
 
168
                {
 
169
                    // URL of the proxy server
 
170
                    proxyURL = (char *) malloc(strlen(kHTTPProto) + 
 
171
                                        strlen(gCtx->opt->mProxyHost) + 1 +
 
172
                                        strlen(gCtx->opt->mProxyPort) + 1);
 
173
                    if (!proxyURL)
 
174
                    {
 
175
                        err = E_MEM;
 
176
                        break;
 
177
                    }
 
178
 
 
179
                    sprintf(proxyURL, "%s%s:%s", kHTTPProto,
 
180
                            gCtx->opt->mProxyHost, gCtx->opt->mProxyPort);
 
181
 
 
182
                    nsHTTPConn *conn = new nsHTTPConn(proxyURL, EventPumpCB);
 
183
                    if (!conn)
 
184
                    {
 
185
                        err = E_MEM;
 
186
                        break;
 
187
                    }
 
188
 
 
189
                    // URL of the actual file to download
 
190
                    qualURL = (char *) malloc(strlen(currURL) + 
 
191
                                       strlen(currComp->GetArchive()) + 1);
 
192
                    if (!qualURL)
 
193
                    {
 
194
                        err = E_MEM;
 
195
                        break;
 
196
                    }
 
197
                    sprintf(qualURL, "%s%s", currURL, currComp->GetArchive());
 
198
 
 
199
                    if (*gCtx->opt->mProxyUser || *gCtx->opt->mProxyPswd)
 
200
                    {
 
201
                      conn->SetProxyInfo(qualURL, gCtx->opt->mProxyUser,
 
202
                                                  gCtx->opt->mProxyPswd);
 
203
                    }
 
204
                    else
 
205
                    {
 
206
                      conn->SetProxyInfo(qualURL, NULL, NULL);
 
207
                    }
 
208
 
 
209
                    err = conn->Open();
 
210
                    if (err == nsHTTPConn::OK)
 
211
                    {
 
212
                        sprintf(localPath, "%s/%s", XPI_DIR,
 
213
                            currComp->GetArchive());
 
214
                        if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT)
 
215
                          err = conn->Get(NULL, localPath, resPos);
 
216
                        else
 
217
                          err = conn->Get(nsInstallDlg::DownloadCB, localPath,
 
218
                                          resPos);
 
219
                        conn->Close();
 
220
                    }
 
221
                    
 
222
                    XI_IF_FREE(proxyURL);
 
223
                    XI_IF_FREE(qualURL);
 
224
                    XI_IF_DELETE(conn);
 
225
                }
 
226
            
 
227
                // is this an HTTP URL?
 
228
                else if (strncmp(currURL, kHTTPProto, strlen(kHTTPProto)) == 0)
 
229
                {
 
230
                    // URL of the actual file to download
 
231
                    qualURL = (char *) malloc(strlen(currURL) + 
 
232
                                       strlen(currComp->GetArchive()) + 1);
 
233
                    if (!qualURL)
 
234
                    {
 
235
                        err = E_MEM;
 
236
                        break;
 
237
                    }
 
238
                    sprintf(qualURL, "%s%s", currURL, currComp->GetArchive());
 
239
 
 
240
                    nsHTTPConn *conn = new nsHTTPConn(qualURL, EventPumpCB);
 
241
                    if (!conn)
 
242
                    {
 
243
                        err = E_MEM;
 
244
                        break;
 
245
                    }
 
246
    
 
247
                    err = conn->Open();
 
248
                    if (err == nsHTTPConn::OK)
 
249
                    {
 
250
                        sprintf(localPath, "%s/%s", XPI_DIR,
 
251
                            currComp->GetArchive());
 
252
                        if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT)
 
253
                          err = conn->Get(NULL, localPath, resPos);
 
254
                        else
 
255
                          err = conn->Get(nsInstallDlg::DownloadCB, localPath,
 
256
                                          resPos);
 
257
                        conn->Close();
 
258
                    }
 
259
 
 
260
                    XI_IF_FREE(qualURL);
 
261
                    XI_IF_DELETE(conn);
 
262
                }
 
263
 
 
264
                // or is this an FTP URL? 
 
265
                else if (strncmp(currURL, kFTPProto, strlen(kFTPProto)) == 0)
 
266
                {
 
267
                    PRBool isNewConn;
 
268
 
 
269
                    err = nsHTTPConn::ParseURL(kFTPProto, currURL, &currHost, 
 
270
                            &currPort, &currPath);
 
271
                    if (err != nsHTTPConn::OK)
 
272
                        break;
 
273
    
 
274
                    // path on the remote server
 
275
                    srvPath = (char *) malloc(strlen(currPath) +
 
276
                                        strlen(currComp->GetArchive()) + 1);
 
277
                    if (!srvPath)
 
278
                    {
 
279
                        err = E_MEM;
 
280
                        break;
 
281
                    }
 
282
                    sprintf(srvPath, "%s%s", currPath, currComp->GetArchive());
 
283
 
 
284
                    // closes the old connection if any
 
285
 
 
286
                    isNewConn = CheckConn( currHost, TYPE_FTP, &myConn, PR_FALSE ); 
 
287
                    err = nsFTPConn::OK;
 
288
 
 
289
                    nsFTPConn *conn;
 
290
                    if ( isNewConn == PR_TRUE ) {
 
291
                      conn = new nsFTPConn(currHost, EventPumpCB);
 
292
                      if (!conn) {
 
293
                        err = E_MEM;
 
294
                        break;
 
295
                      }
 
296
                      err = conn->Open();
 
297
                      myConn.conn = (void *) conn;
 
298
                      myConn.type = TYPE_FTP;
 
299
                      myConn.URL = (char *) calloc(strlen(currHost) + 1, sizeof(char));
 
300
                      if ( myConn.URL != (char *) NULL )
 
301
                        strcpy( myConn.URL, currHost );
 
302
                    } else
 
303
                      conn = (nsFTPConn *) myConn.conn;
 
304
 
 
305
                    if (isNewConn == PR_FALSE || err == nsFTPConn::OK)
 
306
                    {
 
307
                        sprintf(localPath, "%s/%s", XPI_DIR,
 
308
                            currComp->GetArchive());
 
309
                        if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT)
 
310
                          err = conn->Get(srvPath, localPath, nsFTPConn::BINARY, 
 
311
                              resPos, 1, NULL);
 
312
                        else
 
313
                          err = conn->Get(srvPath, localPath, nsFTPConn::BINARY, 
 
314
                              resPos, 1, nsInstallDlg::DownloadCB);
 
315
                        passCount++;
 
316
                    }
 
317
 
 
318
                    XI_IF_FREE(currHost);
 
319
                    XI_IF_FREE(currPath);
 
320
                    XI_IF_FREE(srvPath);
 
321
                }
 
322
 
 
323
                // else error: malformed URL
 
324
                else
 
325
                {
 
326
                    err = nsHTTPConn::E_MALFORMED_URL;
 
327
                }
 
328
 
 
329
                if (err == nsHTTPConn::E_USER_CANCEL)
 
330
                    err = nsInstallDlg::CancelOrPause();
 
331
 
 
332
                // user hit pause and subsequently resumed
 
333
                if (err == nsInstallDlg::E_DL_PAUSE)
 
334
                {
 
335
                    currComp->SetResumePos(GetFileSize(localPath));
 
336
                    return err;
 
337
                }
 
338
 
 
339
                // user cancelled during download
 
340
                else if (err == nsInstallDlg::E_DL_CANCEL)
 
341
                    return err;
 
342
 
 
343
                // user didn't cancel or pause: some other dl error occured
 
344
                else if (err != OK)
 
345
                {
 
346
                    fileSize = GetFileSize(localPath);
 
347
 
 
348
                    if (fileSize > 0)
 
349
                    {
 
350
                        // assume dropped connection if file size > 0
 
351
                        currComp->SetResumePos(fileSize);
 
352
                        return nsInstallDlg::E_DL_DROP_CXN;
 
353
                    }
 
354
                    else
 
355
                    {
 
356
                        // failover
 
357
                        continue;
 
358
                    }
 
359
                }
 
360
 
 
361
                if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
 
362
                    nsInstallDlg::ClearRateLabel(); // clean after ourselves
 
363
 
 
364
                if (err == OK) 
 
365
                {
 
366
                    currComp->SetDownloaded(TRUE);
 
367
                    currCompNum++;
 
368
                    break;  // no need to failover
 
369
                }
 
370
            }
 
371
        }
 
372
        
 
373
        currComp = currComp->GetNext();
 
374
      }
 
375
   
 
376
      CheckConn( "", TYPE_UNDEF, &myConn, true );
 
377
 
 
378
      bDone = CRCCheckDownloadedArchives(XPI_DIR, strlen(XPI_DIR), 
 
379
                currCompSave, passCount, aCustom);
 
380
      crcPass++;
 
381
      if ( bDone == 0 && crcPass < MAXCRC ) {
 
382
        // reset ourselves
 
383
        if (markedComp) {
 
384
          currComp = markedComp;
 
385
          currCompNum = markedCompNum;
 
386
        } else {
 
387
          currComp = aComps->GetHead();
 
388
          currCompNum = 1;
 
389
        }
 
390
        currCompSave = currComp;
 
391
        if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
 
392
          gCtx->idlg->ReInitUI(); 
 
393
        gCtx->idlg->ShowCRCDlg(); 
 
394
        numToDL = TotalToDownload(aCustom, aComps);
 
395
      }
 
396
    }
 
397
    gCtx->idlg->DestroyCRCDlg(); // destroy the CRC dialog if showing
 
398
    if ( crcPass < MAXCRC ) {
 
399
      // download complete: remove marker
 
400
      DelDLMarker();
 
401
      return OK;
 
402
    } else {
 
403
      return E_CRC_FAILED;
 
404
    }
 
405
}
 
406
 
 
407
/* 
 
408
 * Name: CheckConn
 
409
 *
 
410
 * Arguments: 
 
411
 *
 
412
 * char *URL; -- URL of connection we need to have established
 
413
 * int type; -- connection type (TYPE_HTTP, etc.)
 
414
 * CONN *myConn; -- connection state (info about currently established 
 
415
 *                   connection)
 
416
 * PRBool force; -- force closing of connection
 
417
 *
 
418
 * Description:
 
419
 *
 
420
 * This function determines if the caller should open a connection based upon 
 
421
 * the current connection that is open (if any), and the type of connection 
 
422
 * desired. If no previous connection was established, the function returns 
 
423
 * true. If the connection is for a different protocol, then true is also 
 
424
 * returned (and the previous connection is closed). If the connection is for 
 
425
 * the same protocol and the URL is different, the previous connection is 
 
426
 * closed and true is returned. Otherwise, the connection has already been
 
427
 * established, and false is returned.
 
428
 *
 
429
 * Return Value: If a new connection needs to be opened, true. Otherwise, 
 
430
 * false is returned.
 
431
 *
 
432
 * Original Code: Syd Logan (syd@netscape.com) 6/24/2001
 
433
 *
 
434
*/
 
435
 
 
436
PRBool
 
437
nsXIEngine::CheckConn( char *URL, int type, CONN *myConn, PRBool force )
 
438
{
 
439
        nsFTPConn *fconn;
 
440
        nsHTTPConn *hconn;
 
441
        PRBool retval = false;
 
442
 
 
443
        if ( myConn->type == TYPE_UNDEF )
 
444
                retval = PR_TRUE;                                       // first time
 
445
        else if ( ( myConn->type != type || myConn->URL == (char *) NULL || strcmp( URL, myConn->URL ) || force == PR_TRUE ) /* && gControls->state != ePaused */) {
 
446
                retval = PR_TRUE;
 
447
                switch ( myConn->type ) {
 
448
                case TYPE_HTTP:
 
449
                case TYPE_PROXY:
 
450
                        hconn = (nsHTTPConn *) myConn->conn;
 
451
                        hconn->Close();
 
452
                        break;
 
453
                case TYPE_FTP:
 
454
                        fconn = (nsFTPConn *) myConn->conn;
 
455
      if ( fconn != (nsFTPConn *) NULL ) {
 
456
        fconn->Close();
 
457
        XI_IF_DELETE(fconn);
 
458
        myConn->conn = NULL;
 
459
      }
 
460
                        break;
 
461
                }
 
462
        }
 
463
        
 
464
        if ( retval == PR_TRUE && myConn->URL != (char *) NULL ) {
 
465
    free( myConn->URL );
 
466
    myConn->URL = (char *) NULL;
 
467
  }
 
468
 
 
469
        return retval;
 
470
}
 
471
 
 
472
int     
 
473
nsXIEngine::Extract(nsComponent *aXPIEngine)
 
474
{
 
475
    int rv;
 
476
 
 
477
    if (!aXPIEngine)
 
478
        return E_PARAM;
 
479
 
 
480
    mTmp = NULL;
 
481
    rv = MakeUniqueTmpDir();
 
482
    if (!mTmp || rv != OK)
 
483
        return E_DIR_CREATE;
 
484
 
 
485
    nsZipExtractor *unzip = new nsZipExtractor(XPI_DIR, mTmp);
 
486
    rv = unzip->Extract(aXPIEngine, CORE_LIB_COUNT);
 
487
    XI_IF_DELETE(unzip);
 
488
 
 
489
    return rv;
 
490
}
 
491
 
 
492
int     
 
493
nsXIEngine::Install(int aCustom, nsComponentList *aComps, char *aDestination)
 
494
{
 
495
    DUMP("Install");
 
496
 
 
497
    int err = OK;
 
498
    xpistub_t stub;
 
499
    char *old_LD_LIBRARY_PATH = NULL;
 
500
    char new_LD_LIBRARY_PATH[MAXPATHLEN];
 
501
    int i;
 
502
    int compNum = 1;
 
503
    nsComponent *currComp = NULL;
 
504
 
 
505
    if (!aComps || !aDestination)
 
506
        return E_PARAM;
 
507
 
 
508
    // handle LD_LIBRARY_PATH settings
 
509
#if defined (SOLARIS) || defined (IRIX)
 
510
    sprintf(new_LD_LIBRARY_PATH, "LD_LIBRARY_PATH=%s/bin:.", mTmp);
 
511
#else
 
512
    sprintf(new_LD_LIBRARY_PATH, "%s/bin:.", mTmp);
 
513
#endif
 
514
    DUMP(new_LD_LIBRARY_PATH);
 
515
    old_LD_LIBRARY_PATH = getenv("LD_LIBRARY_PATH");
 
516
#if defined (SOLARIS) || defined (IRIX)
 
517
    putenv(new_LD_LIBRARY_PATH);
 
518
#else
 
519
    setenv("LD_LIBRARY_PATH", new_LD_LIBRARY_PATH, 1);
 
520
#endif 
 
521
    currComp = aComps->GetHead();
 
522
    err = LoadXPIStub(&stub, aDestination);
 
523
    if (err == OK)
 
524
    {
 
525
        for (i = 0; i < MAX_COMPONENTS; i++)
 
526
        {
 
527
            if (!currComp)
 
528
                break;
 
529
 
 
530
            if (  (aCustom && currComp->IsSelected()) ||
 
531
                  (!aCustom)  )
 
532
            {
 
533
#ifdef DEBUG
 
534
                printf("%s %d: DOWNLOAD_ONLY for %s is %d\n", __FILE__, __LINE__, 
 
535
                    currComp->GetArchive(), currComp->IsDownloadOnly());
 
536
#endif
 
537
                if (!currComp->IsDownloadOnly())
 
538
                {
 
539
                    if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
 
540
                        nsInstallDlg::MajorProgressCB(currComp->GetDescShort(),
 
541
                            compNum, mTotalComps, nsInstallDlg::ACT_INSTALL);
 
542
                    err = InstallXPI(currComp, &stub);
 
543
                    if (err != OK)
 
544
                    if (err == E_INSTALL)
 
545
                        ErrorHandler(err, currComp->GetArchive()); //handle E_INSTALL separately
 
546
                    else
 
547
                        ErrorHandler(err); //handle and continue 
 
548
                    compNum++;
 
549
                }
 
550
            }
 
551
 
 
552
            currComp = currComp->GetNext();
 
553
        }
 
554
        UnloadXPIStub(&stub);
 
555
    }
 
556
 
 
557
    // restore LD_LIBRARY_PATH settings
 
558
#if defined (SOLARIS) || defined (IRIX)
 
559
    char old_LD_env[MAXPATHLEN];
 
560
 
 
561
    sprintf(old_LD_env, "LD_LIBRARY_PATH=%s", old_LD_LIBRARY_PATH);
 
562
    putenv(old_LD_env);
 
563
#else
 
564
    setenv("LD_LIBRARY_PATH", old_LD_LIBRARY_PATH, 1);
 
565
#endif
 
566
 
 
567
    return err;
 
568
}
 
569
 
 
570
int
 
571
nsXIEngine::MakeUniqueTmpDir()
 
572
{
 
573
    int err = E_DIR_CREATE;
 
574
    char tmpnam[MAXPATHLEN];
 
575
    char *tmpdir = getenv("TMPDIR");
 
576
    if (!tmpdir) tmpdir = getenv("TMP");
 
577
    if (!tmpdir) tmpdir = getenv("TEMP");
 
578
    if (!tmpdir) tmpdir = P_tmpdir;
 
579
    snprintf(tmpnam, sizeof(tmpnam), "%s/xpi.XXXXXX", tmpdir);
 
580
#ifdef HAVE_MKDTEMP
 
581
    if (mkdtemp(tmpnam)) {
 
582
      mTmp = strdup(tmpnam);
 
583
      if (mTmp) err = OK;
 
584
    }
 
585
#else
 
586
    int fd = mkstemp(tmpnam);
 
587
    if (fd < 0) return err;
 
588
    close(fd);
 
589
    if (unlink(tmpnam) < 0) return err;
 
590
    mTmp = strdup(tmpnam);
 
591
    if (!mTmp) return err;
 
592
    if (mkdir(mTmp, 0755) < 0) return err;
 
593
    err = OK;
 
594
#endif
 
595
    return err;
 
596
}
 
597
 
 
598
int
 
599
nsXIEngine::ParseURL(char *aURL, char **aHost, char **aDir)
 
600
{
 
601
    int err = OK;
 
602
    char *host = NULL;
 
603
    char *hostTerminator = NULL;
 
604
    char *dirTerminator = NULL;
 
605
 
 
606
    if (!aURL || !aHost || !aDir)
 
607
        return E_PARAM;
 
608
 
 
609
    if (0 != strncmp(aURL, "ftp://", 6)) return E_BAD_FTP_URL;
 
610
 
 
611
    host = aURL + 6;
 
612
    if (!host) return E_BAD_FTP_URL;
 
613
    hostTerminator = strchr(host, '/'); 
 
614
    if (!hostTerminator) return E_BAD_FTP_URL;
 
615
    
 
616
    *aHost = (char *) calloc(hostTerminator - host + 1, 1);
 
617
    strncpy(*aHost, host, hostTerminator - host);
 
618
 
 
619
    dirTerminator = strrchr(hostTerminator + 1, '/');
 
620
    if (!dirTerminator)
 
621
    {
 
622
        // no dir == root dir
 
623
        *aDir = (char *) malloc(2);
 
624
        sprintf(*aDir, "/");
 
625
    }
 
626
    else
 
627
    {
 
628
        *aDir = (char *) malloc(sizeof(char) * 
 
629
                         (dirTerminator - hostTerminator + 2));
 
630
        memset(*aDir, 0, (dirTerminator - hostTerminator + 2));
 
631
        strncpy(*aDir, hostTerminator, dirTerminator - hostTerminator + 1);
 
632
    }
 
633
    
 
634
    return err;
 
635
}
 
636
 
 
637
int
 
638
nsXIEngine::LoadXPIStub(xpistub_t *aStub, char *aDestination)
 
639
{
 
640
    int err = OK;
 
641
 
 
642
    char libpath[MAXPATHLEN];
 
643
    char libloc[MAXPATHLEN];
 
644
        char *dlerr;
 
645
    nsresult rv = 0;
 
646
 
 
647
        DUMP("LoadXPIStub");
 
648
 
 
649
    /* param check */
 
650
    if (!aStub || !aDestination)
 
651
        return E_PARAM;
 
652
 
 
653
    /* save original directory to reset it after installing */
 
654
    mOriginalDir = (char *) malloc(MAXPATHLEN * sizeof(char));
 
655
    getcwd(mOriginalDir, MAXPATHLEN);
 
656
 
 
657
    /* chdir to library location for dll deps resolution */
 
658
    sprintf(libloc, "%s/bin", mTmp);
 
659
    chdir(libloc);
 
660
    
 
661
        /* open the library */
 
662
    getcwd(libpath, MAXPATHLEN);
 
663
    sprintf(libpath, "%s/%s", libpath, XPISTUB);
 
664
 
 
665
#ifdef DEBUG
 
666
printf("DEBUG: libpath = >>%s<<\n", libpath);
 
667
#endif
 
668
 
 
669
        aStub->handle = NULL;
 
670
        aStub->handle = dlopen(libpath, RTLD_LAZY);
 
671
        if (!aStub->handle)
 
672
        {
 
673
                dlerr = dlerror();
 
674
                DUMP(dlerr);
 
675
                return E_LIB_OPEN;
 
676
        }
 
677
        DUMP("xpistub opened");
 
678
        
 
679
        /* read and store symbol addresses */
 
680
        aStub->fn_init    = (pfnXPI_Init) dlsym(aStub->handle, FN_INIT);
 
681
        aStub->fn_install = (pfnXPI_Install) dlsym(aStub->handle, FN_INSTALL);
 
682
        aStub->fn_exit    = (pfnXPI_Exit) dlsym(aStub->handle, FN_EXIT);
 
683
        if (!aStub->fn_init || !aStub->fn_install || !aStub->fn_exit)
 
684
        {
 
685
                dlerr = dlerror();
 
686
                DUMP(dlerr);
 
687
                err = E_LIB_SYM;
 
688
        goto BAIL;
 
689
        }
 
690
    DUMP("xpistub symbols loaded");
 
691
 
 
692
    rv = aStub->fn_init(aDestination, NULL, ProgressCallback);
 
693
 
 
694
#ifdef DEBUG
 
695
printf("DEBUG: XPI_Init returned 0x%.8X\n", rv);
 
696
#endif
 
697
 
 
698
    DUMP("XPI_Init called");
 
699
        if (NS_FAILED(rv))
 
700
        {
 
701
                err = E_XPI_FAIL;
 
702
        goto BAIL;
 
703
        }
 
704
 
 
705
    return err;
 
706
 
 
707
BAIL:
 
708
    return err;
 
709
}
 
710
 
 
711
int
 
712
nsXIEngine::InstallXPI(nsComponent *aXPI, xpistub_t *aStub)
 
713
{
 
714
    int err = OK;
 
715
    char xpipath[MAXPATHLEN];
 
716
    nsresult rv = 0;
 
717
 
 
718
    if (!aStub || !aXPI || !mOriginalDir)
 
719
        return E_PARAM;
 
720
 
 
721
    sprintf(xpipath, "%s/%s/%s", mOriginalDir, XPI_DIR, aXPI->GetArchive());
 
722
    DUMP(xpipath);
 
723
 
 
724
#define XPI_NO_NEW_THREAD 0x1000
 
725
 
 
726
    rv = aStub->fn_install(xpipath, "", XPI_NO_NEW_THREAD);
 
727
 
 
728
#ifdef DEBUG
 
729
printf("DEBUG: XPI_Install %s returned %d\n", aXPI->GetArchive(), rv);
 
730
#endif
 
731
 
 
732
    if (NS_FAILED(rv))
 
733
        err = E_INSTALL;
 
734
 
 
735
    return err;
 
736
}
 
737
 
 
738
int
 
739
nsXIEngine::UnloadXPIStub(xpistub_t *aStub)
 
740
{
 
741
    int err = OK;
 
742
 
 
743
    /* param check */
 
744
    if (!aStub)
 
745
        return E_PARAM;
 
746
 
 
747
        /* release XPCOM and XPInstall */
 
748
    XI_ASSERT(aStub->fn_exit, "XPI_Exit is NULL and wasn't called!");
 
749
        if (aStub->fn_exit)
 
750
        {
 
751
                aStub->fn_exit();
 
752
                DUMP("XPI_Exit called");
 
753
        }
 
754
 
 
755
#if 0
 
756
    /* NOTE:
 
757
     * ----
 
758
     *      Don't close the stub: it'll be released on exit.
 
759
     *      This fixes the seg fault on exit bug,
 
760
     *      Apparently, the global destructors are no longer
 
761
     *      around when the app exits (since xpcom etc. was 
 
762
     *      unloaded when the stub was unloaded).  To get 
 
763
     *      around this we don't close the stub (which is 
 
764
     *      apparently safe on Linux/Unix).
 
765
     */
 
766
 
 
767
        /* close xpistub library */
 
768
        if (aStub->handle)
 
769
        {
 
770
                dlclose(aStub->handle);
 
771
                DUMP("xpistub closed");
 
772
        }
 
773
#endif
 
774
 
 
775
    return err;
 
776
}
 
777
 
 
778
void
 
779
nsXIEngine::ProgressCallback(const char* aMsg, PRInt32 aVal, PRInt32 aMax)
 
780
{
 
781
    // DUMP("ProgressCallback");
 
782
    
 
783
    nsInstallDlg::XPIProgressCB(aMsg, (int)aVal, (int)aMax);
 
784
}
 
785
 
 
786
int 
 
787
nsXIEngine::ExistAllXPIs(int aCustom, nsComponentList *aComps, int *aTotal)
 
788
{
 
789
    // param check
 
790
    if (!aComps || !aTotal)
 
791
        return E_PARAM;
 
792
    
 
793
    int bAllExist = TRUE;
 
794
    nsComponent *currComp = aComps->GetHead();
 
795
    char currArchivePath[256];
 
796
    struct stat dummy;
 
797
 
 
798
    while (currComp)
 
799
    {
 
800
        if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) )
 
801
        {
 
802
            sprintf(currArchivePath, "%s/%s", XPI_DIR, currComp->GetArchive());
 
803
            DUMP(currArchivePath);
 
804
            
 
805
            if (0 != stat(currArchivePath, &dummy))
 
806
                bAllExist = FALSE;
 
807
            else
 
808
                currComp->SetDownloaded(TRUE);
 
809
 
 
810
            (*aTotal)++;
 
811
        }
 
812
        
 
813
        currComp = currComp->GetNext();
 
814
    }
 
815
 
 
816
    return bAllExist;
 
817
}
 
818
 
 
819
int
 
820
nsXIEngine::DeleteXPIs(int aCustom, nsComponentList *aComps)
 
821
{
 
822
    int err = OK;
 
823
    nsComponent *currComp = aComps->GetHead();
 
824
    char currXPIPath[MAXPATHLEN];
 
825
 
 
826
    if (!aComps || !mOriginalDir)
 
827
        return E_PARAM;
 
828
 
 
829
    while (currComp)
 
830
    {
 
831
        if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) )
 
832
        {
 
833
            sprintf(currXPIPath, "%s/%s/%s", mOriginalDir, XPI_DIR, 
 
834
                    currComp->GetArchive());
 
835
            
 
836
            // delete the xpi
 
837
            err = unlink(currXPIPath);
 
838
 
 
839
#ifdef DEBUG
 
840
            printf("%s %d: unlink %s returned: %d\n", __FILE__, __LINE__, 
 
841
                currXPIPath, err); 
 
842
#endif
 
843
        }
 
844
 
 
845
        currComp = currComp->GetNext();
 
846
    }
 
847
 
 
848
    // all xpi should be deleted so delete the ./xpi dir
 
849
    sprintf(currXPIPath, "%s/xpi", mOriginalDir);
 
850
    err = rmdir(currXPIPath);
 
851
 
 
852
#ifdef DEBUG
 
853
    printf("%s %d: rmdir %s returned: %d\n", __FILE__, __LINE__, 
 
854
        currXPIPath, err);
 
855
#endif
 
856
    
 
857
    return err;
 
858
}
 
859
 
 
860
int
 
861
nsXIEngine::GetFileSize(char *aPath)
 
862
{
 
863
    struct stat stbuf;
 
864
 
 
865
    if (!aPath)
 
866
        return 0;
 
867
 
 
868
    if (0 == stat(aPath, &stbuf))
 
869
    {
 
870
        return stbuf.st_size;
 
871
    }
 
872
 
 
873
    return 0;
 
874
}
 
875
 
 
876
int
 
877
nsXIEngine::SetDLMarker(char *aCompName)
 
878
{
 
879
    int rv = OK;
 
880
    FILE *dlMarkerFD;
 
881
    int compNameLen;
 
882
 
 
883
    if (!aCompName)
 
884
        return E_PARAM;
 
885
 
 
886
    // open the marker file
 
887
    dlMarkerFD = fopen(kDLMarkerPath, "w");
 
888
    if (!dlMarkerFD)
 
889
        return E_OPEN_MKR;
 
890
 
 
891
    // write out the current comp name
 
892
    compNameLen = strlen(aCompName);
 
893
    if (compNameLen > 0)
 
894
    {
 
895
        rv = fwrite((void *) aCompName, sizeof(char), compNameLen, dlMarkerFD);
 
896
        if (rv != compNameLen)
 
897
            rv = E_WRITE_MKR;
 
898
        else
 
899
            rv = OK;
 
900
    }
 
901
 
 
902
    // close the marker file
 
903
    fclose(dlMarkerFD);
 
904
        
 
905
#ifdef DEBUG
 
906
    printf("%s %d: SetDLMarker rv = %d\n", __FILE__, __LINE__, rv);
 
907
#endif
 
908
    return rv;
 
909
}
 
910
 
 
911
int
 
912
nsXIEngine::GetDLMarkedComp(nsComponentList *aComps, int aCustom, 
 
913
                            nsComponent **aOutComp, int *aOutCompNum)
 
914
{
 
915
    int rv = OK;
 
916
    FILE *dlMarkerFD = NULL;
 
917
    struct stat stbuf;
 
918
    char *compNameInFile = NULL;
 
919
    int compNum = 1;
 
920
    nsComponent *currComp = NULL;
 
921
 
 
922
    if (!aComps || !aOutComp || !aOutCompNum)
 
923
        return E_PARAM;
 
924
 
 
925
    *aOutComp = NULL;
 
926
    currComp = aComps->GetHead();
 
927
 
 
928
    // open the marker file
 
929
    dlMarkerFD = fopen(kDLMarkerPath, "r");
 
930
    if (!dlMarkerFD)
 
931
        return E_OPEN_MKR;
 
932
 
 
933
    // find it's length 
 
934
    if (0 != stat(kDLMarkerPath, &stbuf))
 
935
    {
 
936
        rv = E_STAT;
 
937
        goto BAIL;
 
938
    }
 
939
    if (stbuf.st_size <= 0)
 
940
    {
 
941
        rv = E_FIND_COMP;
 
942
        goto BAIL;
 
943
    }
 
944
 
 
945
    // allocate a buffer the length of the file
 
946
    compNameInFile = (char *) malloc(sizeof(char) * (stbuf.st_size + 1));
 
947
    if (!compNameInFile)
 
948
    {
 
949
        rv = E_MEM;
 
950
        goto BAIL;
 
951
    }
 
952
    memset(compNameInFile, 0 , (stbuf.st_size + 1));
 
953
 
 
954
    // read in the file contents
 
955
    rv = fread((void *) compNameInFile, sizeof(char), 
 
956
               stbuf.st_size, dlMarkerFD);
 
957
    if (rv != stbuf.st_size)
 
958
        rv = E_READ_MKR;
 
959
    else
 
960
        rv = OK; 
 
961
 
 
962
    if (rv == OK)
 
963
    {
 
964
        // compare the comp name read in with all those in the components list
 
965
        while (currComp)
 
966
        {
 
967
            if ( (aCustom == TRUE && currComp->IsSelected()) || 
 
968
                 (aCustom == FALSE) )
 
969
            {
 
970
                if (strcmp(currComp->GetArchive(), compNameInFile) == 0)
 
971
                {
 
972
                    *aOutComp = currComp;
 
973
                    break;
 
974
                }
 
975
 
 
976
                compNum++;
 
977
            }
 
978
            
 
979
            currComp = currComp->GetNext();
 
980
        }
 
981
    }
 
982
 
 
983
    *aOutCompNum = compNum;
 
984
 
 
985
BAIL:
 
986
    if (dlMarkerFD)
 
987
        fclose(dlMarkerFD);
 
988
 
 
989
    XI_IF_FREE(compNameInFile);
 
990
 
 
991
    return rv;
 
992
}
 
993
 
 
994
int
 
995
nsXIEngine::DelDLMarker()
 
996
{
 
997
    return unlink(kDLMarkerPath);
 
998
}
 
999
 
 
1000
int
 
1001
nsXIEngine::TotalToDownload(int aCustom, nsComponentList *aComps)
 
1002
{
 
1003
    int total = 0;
 
1004
    nsComponent *currComp;
 
1005
 
 
1006
    if (!aComps)
 
1007
        return 0;
 
1008
 
 
1009
    currComp = aComps->GetHead();
 
1010
    while (currComp)
 
1011
    {
 
1012
        if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) )
 
1013
        {
 
1014
            if (!currComp->IsDownloaded())
 
1015
                total++;
 
1016
        }
 
1017
        currComp = currComp->GetNext();
 
1018
    }
 
1019
 
 
1020
    return total;
 
1021
}
 
1022
 
 
1023
/* 
 
1024
 * Name: CRCCheckDownloadedArchives
 
1025
 *
 
1026
 * Arguments: 
 
1027
 *
 
1028
 * Handle dlPath;     -- a handle to the location of the XPI files on disk
 
1029
 * short dlPathlen;       -- length, in bytes, of dlPath
 
1030
 *
 
1031
 * Description:
 
1032
 *
 
1033
 * This function iterates the XPI files and calls VerifyArchive() on each to 
 
1034
 * determine which archives pass checksum checks. 
 
1035
 *
 
1036
 * Return Value: if all archives pass, true. Otherwise, false.
 
1037
 *
 
1038
 * Original Code: Syd Logan (syd@netscape.com) 6/24/2001
 
1039
 *
 
1040
*/
 
1041
 
 
1042
PRBool 
 
1043
nsXIEngine::CRCCheckDownloadedArchives(char *dlPath, short dlPathlen, 
 
1044
  nsComponent *currComp, int count, int aCustom)
 
1045
{
 
1046
  int i;
 
1047
  PRBool isClean;
 
1048
  char buf[ 1024 ];
 
1049
 
 
1050
  isClean = PR_TRUE;
 
1051
 
 
1052
  for(i = 0; currComp != (nsComponent *) NULL && i < MAX_COMPONENTS; i++) {
 
1053
    strncpy( buf, (const char *) dlPath, dlPathlen );
 
1054
    buf[ dlPathlen ] = '\0';
 
1055
    strcat( buf, "/" );
 
1056
    strcat( buf, currComp->GetArchive() );
 
1057
    if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
 
1058
        nsInstallDlg::MajorProgressCB(buf, i, count, nsInstallDlg::ACT_INSTALL);
 
1059
    if (((aCustom == TRUE && currComp->IsSelected()) || 
 
1060
        (aCustom == FALSE)) && IsArchiveFile(buf) == PR_TRUE && 
 
1061
        VerifyArchive( buf ) != ZIP_OK) {
 
1062
      currComp->SetDownloaded(FALSE); // VerifyArchive has unlinked it
 
1063
      isClean = false;
 
1064
    }
 
1065
    currComp = currComp->GetNext();
 
1066
  }
 
1067
  return isClean;
 
1068
}
 
1069
 
 
1070
/* 
 
1071
 * Name: IsArchiveFile( char *path )
 
1072
 * 
 
1073
 * Arguments:
 
1074
 * 
 
1075
 * char *path -- NULL terminated pathname 
 
1076
 *
 
1077
 * Description: 
 
1078
 *  
 
1079
 * This function extracts the file extension of filename pointed to by path 
 
1080
 * and then checks it against a table of extensions. If a match occurs, the 
 
1081
 * file is considered to be an archive file that has a checksum we can 
 
1082
 * validate, and we return PR_TRUE.
 
1083
 * Otherwise, PR_FALSE is returned.
 
1084
 *
 
1085
 * Return Value: true if the file extension matches one of those we are 
 
1086
 * looking for, and false otherwise.
 
1087
 *
 
1088
 * Original Code: Syd Logan 7/28/2001
 
1089
 *
 
1090
*/
 
1091
 
 
1092
static char *extensions[] = { "ZIP", "XPI", "JAR" };  // must be uppercase
 
1093
 
 
1094
PRBool
 
1095
nsXIEngine::IsArchiveFile( char *buf ) 
 
1096
{
 
1097
    PRBool ret = false;
 
1098
    char lbuf[1024];
 
1099
    char *p;
 
1100
    int i, max;
 
1101
    
 
1102
    // if we have a string and it contains a '.'
 
1103
    
 
1104
    if ( buf != (char *) NULL && ( p = strrchr( buf, '.' ) ) != (char *) NULL ) {
 
1105
        p++;
 
1106
        
 
1107
        // if there are characters after the '.' then see if there is a match
 
1108
        
 
1109
        if ( *p != '\0' ) {
 
1110
            
 
1111
            // make a copy of the extension, and fold to uppercase, since mac has no strcasecmp
 
1112
            // and we need to ensure we are comparing strings of chars that have the same case. 
 
1113
 
 
1114
            strcpy( lbuf, p );
 
1115
            for ( i = 0; i < (int) strlen( lbuf ); i++ )
 
1116
                lbuf[i] = toupper(lbuf[i]);
 
1117
            
 
1118
            // search
 
1119
                
 
1120
            max = sizeof( extensions ) / sizeof ( char * );
 
1121
            for ( i = 0; i < max; i++ ) 
 
1122
                if ( !strcmp( lbuf, extensions[i] ) ) {
 
1123
                    ret = true;
 
1124
                    break;
 
1125
                }
 
1126
        }   
 
1127
    }
 
1128
    return ( ret );
 
1129
}
 
1130
 
 
1131
/*
 
1132
 * Name: VerifyArchive
 
1133
 *
 
1134
 * Arguments:
 
1135
 *
 
1136
 * char *szArchive;     -- path of archive to verify
 
1137
 *
 
1138
 * Description:
 
1139
 *
 
1140
 * This function verifies that the specified path exists, that it is a XPI 
 
1141
 * file, and that it has a valid checksum.
 
1142
 *
 
1143
 * Return Value: If all tests pass, ZIP_OK. Otherwise, !ZIP_OK
 
1144
 *
 
1145
 * Original Code: Syd Logan (syd@netscape.com) 6/25/2001
 
1146
 *
 
1147
*/
 
1148
 
 
1149
int
 
1150
nsXIEngine::VerifyArchive(char *szArchive)
 
1151
{
 
1152
  void *vZip;
 
1153
  int  iTestRv;
 
1154
  char *penv;
 
1155
 
 
1156
  if((iTestRv = ZIP_OpenArchive(szArchive, &vZip)) == ZIP_OK)
 
1157
  {
 
1158
    /* 1st parameter should be NULL or it will fail */
 
1159
    /* It indicates extract the entire archive */
 
1160
    iTestRv = ZIP_TestArchive(vZip);
 
1161
    ZIP_CloseArchive(&vZip);
 
1162
  }
 
1163
 
 
1164
  // for testing, this will cause about half of the CRCs to fail. Since 
 
1165
  // randomly selecting which fail, likely next pass the same file will 
 
1166
  // end up a success.
 
1167
 
 
1168
  penv = getenv("MOZ_INSTALL_TEST_CRC");
 
1169
  if ( penv != (char *) NULL ) { 
 
1170
    if ( random() < RAND_MAX / 2 ) 
 
1171
      iTestRv = !ZIP_OK;
 
1172
  }
 
1173
 
 
1174
  if ( iTestRv != ZIP_OK )
 
1175
    unlink( szArchive );
 
1176
  return(iTestRv);
 
1177
}
 
1178