Back to index

lightning-sunbird  0.9+nobinonly
InstAction.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "MacInstallWizard.h"
00041 
00042 #include "nsFTPConn.h"
00043 #include "nsHTTPConn.h"
00044 
00045 #define STANDALONE 1
00046 #define XP_MAC 1
00047 #include "zipstub.h"
00048 #include "zipfile.h"
00049 #include <ctype.h>
00050 
00051 /*-----------------------------------------------------------*
00052  *   Install Action
00053  *-----------------------------------------------------------*/
00054 
00055 static Boolean bXPIsExisted = true;
00056 static long sCurrTotalDLSize = 0;
00057 
00058 // info for download progress callback
00059 static int sCurrComp = 0;
00060 static Handle sCurrFullPath = 0;
00061 static int sCurrFullPathLen = 0;
00062 static char *sCurrURL = 0;
00063 static time_t sCurrStartTime;  /* start of download of current file */
00064 
00065 ConstStr255Param kDLMarker = "\pCurrent Download";
00066 
00067 #include <Math64.h>
00068 
00069 /* VersGreaterThan4 - utility function to test if it's >4.x running */
00070 static Boolean VersGreaterThan4(FSSpec *fSpec)
00071 {
00072        Boolean result = false;
00073        short  fRefNum = 0;
00074        
00075        SetResLoad(false);
00076        fRefNum = FSpOpenResFile(fSpec, fsRdPerm);
00077        SetResLoad(true);
00078        if (fRefNum != -1)
00079        {
00080               Handle h;
00081               h = Get1Resource('vers', 2);
00082               if (h && **(unsigned short**)h >= 0x0500)
00083                      result = true;
00084               CloseResFile(fRefNum);
00085        }
00086               
00087        return result;
00088 }
00089 
00090 /* Variant of FindRunningAppBySignature that looks from a specified PSN */
00091 static OSErr FindNextRunningAppBySignature (OSType sig, FSSpec *fSpec, ProcessSerialNumber *psn)
00092 {
00093        OSErr                err = noErr;
00094        ProcessInfoRec       info;
00095        FSSpec               tempFSSpec;
00096        
00097        while (true)
00098        {
00099               err = GetNextProcess(psn);
00100               if (err != noErr) return err;
00101               info.processInfoLength = sizeof(ProcessInfoRec);
00102               info.processName = nil;
00103               info.processAppSpec = &tempFSSpec;
00104               err = GetProcessInformation(psn, &info);
00105               if (err != noErr) return err;
00106               
00107               if (info.processSignature == sig)
00108               {
00109                      if (fSpec != nil)
00110                             *fSpec = tempFSSpec;
00111                      return noErr;
00112               }
00113        }
00114        
00115        return procNotFound;
00116 }
00117 
00118 pascal void* Install(void* unused)
00119 {      
00120        short                vRefNum, srcVRefNum;
00121        long                 dirID, srcDirID, modulesDirID;
00122        OSErr                err;
00123        FSSpec               coreFileSpec;
00124        short                dlErr;
00125        short           siteIndex;
00126 #ifdef MIW_DEBUG
00127        FSSpec               tmpSpec;
00128 #endif /* MIW_DEBUG */
00129        Str255               pIDIfname, pModulesDir;
00130        StringPtr            coreFile = NULL;
00131        THz                         ourHZ = NULL;
00132        Boolean              isDir = false, bCoreExists = false;
00133        GrafPtr                     oldPort = NULL;
00134        
00135        ProcessSerialNumber thePSN;
00136        FSSpec                      theSpec;
00137        DialogPtr pDlg = nil;
00138 
00139 #ifndef MIW_DEBUG
00140        /* get "Temporary Items" folder path */
00141        ERR_CHECK_RET(FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &vRefNum, &dirID), (void*)0);
00142 #else
00143        /* for DEBUG builds dump downloaded items in "<currProcessVolume>:Temp NSInstall:" */
00144        vRefNum = gControls->opt->vRefNum;
00145        err = FSMakeFSSpec( vRefNum, 0, kTempFolder, &tmpSpec );
00146        if (err != noErr)
00147        {
00148               err = FSpDirCreate(&tmpSpec, smSystemScript, &dirID);
00149               if (err != noErr)
00150               {
00151                      ErrorHandler(err, nil);
00152                      return (void*)0;
00153               }
00154        }
00155        else
00156        {
00157               err = FSpGetDirectoryID( &tmpSpec, &dirID, &isDir );
00158               if (!isDir || err!=noErr)
00159               {
00160                      ErrorHandler(err, nil);
00161                      return (void*)0;
00162               }
00163        }      
00164 #endif /* MIW_DEBUG */
00165        
00166        err = GetCWD(&srcDirID, &srcVRefNum);
00167        if (err != noErr)
00168        {
00169               ErrorHandler(err, nil);
00170               return (void*)nil;
00171        }
00172        
00173        /* get the "Installer Modules" relative subdir */
00174        GetIndString(pModulesDir, rStringList, sInstModules);
00175        isDir = false;  /* reuse */
00176        modulesDirID = 0;
00177        GetDirectoryID(srcVRefNum, srcDirID, pModulesDir, &modulesDirID, &isDir);
00178        srcDirID = modulesDirID;
00179        
00180        GetPort(&oldPort);
00181   ourHZ = GetZone();
00182        if (!isDir || !ExistArchives(srcVRefNum, srcDirID))
00183        {      
00184               bXPIsExisted = false;
00185               GetIndString(pIDIfname, rStringList, sTempIDIName);
00186        
00187            /* otherwise if site selector exists, replace global URL with selected site */
00188         if (gControls->cfg->numSites > 0)
00189         {
00190                if (gControls->cfg->globalURL[0])
00191                    DisposeHandle(gControls->cfg->globalURL[0]);
00192             gControls->cfg->globalURL[0] = NewHandleClear(kValueMaxLen);
00193             
00194             siteIndex = gControls->opt->siteChoice - 1;
00195             HLock(gControls->cfg->globalURL[0]);
00196             HLock(gControls->cfg->site[siteIndex].domain);
00197             strcpy(*(gControls->cfg->globalURL[0]), *(gControls->cfg->site[siteIndex].domain));
00198             HUnlock(gControls->cfg->globalURL[0]);
00199             HUnlock(gControls->cfg->site[siteIndex].domain);
00200            }
00201         
00202         if (gControls->state != eResuming)
00203             InitDLProgControls(false);
00204         dlErr = DownloadXPIs(srcVRefNum, srcDirID);
00205         if (dlErr == nsFTPConn::E_USER_CANCEL)
00206         {
00207             return (void *) nil;
00208         }
00209                   if (dlErr != 0)
00210                   {
00211                     ErrorHandler(dlErr, nil);
00212                          return (void*) nil;
00213                   }
00214     }
00215          else
00216                 bCoreExists = true;
00217        
00218     /* Short term fix for #58928 - prevent install if Mozilla or Netscape running. syd 3/18/2002 */
00219          while (FindRunningAppBySignature('MOSS', &theSpec, &thePSN) == noErr ||
00220                 FindRunningAppBySignature('MOZZ', &theSpec, &thePSN) == noErr)
00221          {
00222                        Str255 itemText;
00223                        SInt16 itemHit;
00224                        short itemType;
00225                        Handle item;
00226         Rect itemBox, iconRect, windRect;
00227         CIconHandle cicn;
00228  
00229         if ( pDlg == nil ) {
00230           pDlg = GetNewDialog(151, NULL, (WindowPtr) -1);
00231         
00232           ShowWindow(pDlg);
00233           SelectWindow(pDlg);
00234         
00235           GetDialogItem(pDlg, 3, &itemType, &item, &itemBox);
00236           GetResourcedString(itemText, rInstList, sExecuting);
00237           SetDialogItemText( item, itemText );
00238 
00239           GetDialogItem(pDlg, 2, &itemType, &item, &itemBox);
00240           GetResourcedString(itemText, rInstList, sNextBtn);
00241           SetControlTitle((ControlRecord **)item, itemText);
00242         
00243           GetDialogItem(pDlg, 1, &itemType, &item, &itemBox);
00244           GetResourcedString(itemText, rInstList, sQuitBtn);
00245           SetControlTitle((ControlRecord **)item, itemText);
00246 
00247 #if 1        
00248           GetDialogItem(pDlg, 4, &itemType, &item, &itemBox);
00249           cicn = GetCIcon( 129 );
00250           windRect = pDlg->portRect;
00251           LocalToGlobal((Point *) &windRect.top);
00252           LocalToGlobal((Point *) &windRect.bottom);
00253           SetRect(&iconRect, 
00254             windRect.left + itemBox.left, 
00255             windRect.top + itemBox.top, 
00256             windRect.left + itemBox.left + itemBox.right,
00257             windRect.top + itemBox.top + itemBox.bottom );
00258         
00259           if ( cicn != nil ) 
00260             PlotCIcon( &iconRect, cicn );
00261           SysBeep( 20L );
00262 #endif               
00263         }
00264         do
00265         {
00266           EventRecord evt;
00267           
00268           if(WaitNextEvent(everyEvent, &evt, 1, nil))
00269           {
00270             if ( IsDialogEvent( &evt ) == false ) 
00271             {
00272               // let someone else handle it
00273               HandleNextEvent(&evt); // XXX
00274             } 
00275             else 
00276             {
00277               // find out what was clicked
00278               DialogPtr tDlg;
00279               DialogSelect( &evt, &tDlg, &itemHit );
00280             }
00281           }
00282         } while(itemHit != 1 && itemHit != 2);
00283 
00284         if ( itemHit == 1 ) {
00285           DisposeDialog(pDlg);    
00286           gDone = true;
00287           return (void*) nil;
00288         } 
00289         else {
00290           itemHit = 0;
00291           SysBeep( 20L );
00292         }
00293     }
00294          
00295          if (pDlg != nil )
00296            DisposeDialog(pDlg);
00297 
00298     SetPort(oldPort);              
00299     /* otherwise core exists in cwd:Installer Modules, different from extraction location */
00300     ClearDLProgControls(false);
00301     DisableNavButtons();
00302               if (gWPtr)
00303               {
00304                      GetPort(&oldPort);
00305 
00306                      SetPort(gWPtr);
00307                      BeginUpdate(gWPtr);
00308                      DrawControls(gWPtr);
00309                      ShowLogo(false);
00310                      UpdateTerminalWin();
00311                      EndUpdate(gWPtr);
00312               
00313                      SetPort(oldPort);
00314               }
00315               SetZone(ourHZ);
00316 
00317 
00318        /* check if coreFile was downloaded */
00319        HLock(gControls->cfg->coreFile);
00320        if (*gControls->cfg->coreFile != NULL)
00321        {
00322               coreFile = CToPascal(*gControls->cfg->coreFile);
00323               if (!coreFile)
00324                      return (void*) memFullErr;
00325        }
00326        HUnlock(gControls->cfg->coreFile);
00327               
00328        if (coreFile != NULL && *coreFile > 0) /* core file was specified */
00329        {
00330               err = FSMakeFSSpec(srcVRefNum, srcDirID, coreFile, &coreFileSpec);
00331               if (err==noErr) /* core file was downloaded or packaged with installer */
00332               {
00333                      InitProgressBar();
00334                      
00335                      /* extract contents of downloaded or packaged core file */
00336                      err = ExtractCoreFile(srcVRefNum, srcDirID, vRefNum, dirID);
00337                      if (err!=noErr) 
00338                      {
00339                             ErrorHandler(err, nil);
00340                             if (coreFile)
00341                                    DisposePtr((Ptr)coreFile);
00342                             return (void*) nil;
00343                      }
00344               
00345                      /* run all .xpi's through XPInstall */
00346                      err = RunAllXPIs(srcVRefNum, srcDirID, vRefNum, dirID);
00347                      if (err!=noErr)
00348                             ErrorHandler(err, nil);
00349                             
00350                      CleanupExtractedFiles(vRefNum, dirID);
00351               }
00352               
00353               if (coreFile)
00354                      DisposePtr((Ptr)coreFile);
00355        }
00356        
00357        /* launch the downloaded apps who had the LAUNCHAPP attr set */
00358        if (err == noErr)
00359               LaunchApps(srcVRefNum, srcDirID);
00360        
00361        /* run apps that were set in RunAppsX sections */
00362        if (err == noErr && gControls->cfg->numRunApps > 0)
00363               RunApps();
00364         
00365        // cleanup downloaded .xpis 
00366        if (!gControls->opt->saveBits  && !bXPIsExisted)
00367               DeleteXPIs(srcVRefNum, srcDirID);  // "Installer Modules" folder location is supplied 
00368 
00369        /* wind down app */
00370        gDone = true;
00371        
00372        return (void*) 0;
00373 }
00374 
00375 long
00376 ComputeTotalDLSize(void)
00377 {
00378     int i, compsDone, instChoice;
00379     long totalDLSize = 0;
00380     
00381        compsDone = 0;
00382        instChoice = gControls->opt->instChoice-1;
00383        
00384        // loop through 0 to kMaxComponents
00385        for(i=0; i<kMaxComponents; i++)
00386        {
00387               // general test: if component in setup type
00388               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
00389                       (compsDone < gControls->cfg->st[instChoice].numComps) )
00390               { 
00391                      // if custom and selected -or- not custom setup type
00392                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
00393                               (gControls->cfg->comp[i].selected == true)) ||
00394                              (instChoice < gControls->cfg->numSetupTypes-1) )
00395                      {    
00396                          // XXX should this change to look at archive size instead?
00397                 totalDLSize += gControls->cfg->comp[i].size;
00398                 
00399                 compsDone++;
00400             }
00401         }
00402               else if (compsDone >= gControls->cfg->st[instChoice].numComps)
00403                      break;  
00404     }
00405     
00406     return totalDLSize;
00407 }
00408 
00409 #define MAXCRC 4
00410 
00411 short
00412 DownloadXPIs(short destVRefNum, long destDirID)
00413 {
00414     short rv = 0;
00415     Handle dlPath;
00416     short dlPathLen = 0;
00417     int i, compsDone = 0, instChoice = gControls->opt->instChoice-1, resPos = 0;
00418     Boolean bResuming = false;
00419     Boolean bDone = false;
00420     int markedIndex = 0, currGlobalURLIndex = 0;
00421     CONN myConn;
00422     int crcPass;
00423     int count = 0;
00424     
00425     GetFullPath(destVRefNum, destDirID, "\p", &dlPathLen, &dlPath);
00426        DLMarkerGetCurrent(&markedIndex, &compsDone);
00427        if (markedIndex >= 0)
00428            resPos = GetResPos(&gControls->cfg->comp[markedIndex]);
00429        
00430        myConn.URL = (char *) NULL;
00431        myConn.type = TYPE_UNDEF;
00432        
00433        crcPass = 1;
00434        while ( bDone == false && crcPass <= MAXCRC ) {
00435     for ( i = 0; i < kNumDLFields; i++ ) {
00436         ShowControl( gControls->tw->dlLabels[i] );
00437     }
00438        for(i = 0; i < kMaxComponents; i++)
00439        {
00440               // general test: if component in setup type
00441               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
00442                       (compsDone < gControls->cfg->st[instChoice].numComps) && 
00443                       gControls->cfg->comp[i].dirty == true)
00444               { 
00445                      // if custom and selected -or- not custom setup type
00446                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
00447                               (gControls->cfg->comp[i].selected == true)) ||
00448                              (instChoice < gControls->cfg->numSetupTypes-1) )
00449                      {    
00450                          // stat file even if index is less than markedIndex
00451                          // and download file if it isn't locally there;
00452                          // this can happen if a new setup type was selected
00453                          if (i < markedIndex)
00454                          {
00455                              if (noErr == ExistsXPI(i))
00456                                  continue;  
00457                          }
00458                          
00459                          count++;
00460                          
00461                          // set up vars for dl callback to use
00462                 sCurrComp = i;
00463                 sCurrFullPath = dlPath;
00464                 sCurrFullPathLen = dlPathLen;
00465                 
00466                 // download given full path and archive name
00467                 if (i == markedIndex && resPos > 0)
00468                 {
00469                     gControls->resPos = resPos;
00470                     gControls->state = eResuming;
00471                 }
00472 TRY_DOWNLOAD:
00473                 rv = DownloadFile(dlPath, dlPathLen, gControls->cfg->comp[i].archive, resPos, currGlobalURLIndex, &myConn);
00474                 if (rv == nsFTPConn::E_USER_CANCEL)
00475                 {
00476                     break;
00477                 }
00478                 if (rv != 0)
00479                 {
00480                     if (++currGlobalURLIndex < gControls->cfg->numGlobalURLs)
00481                         goto TRY_DOWNLOAD;
00482                         
00483                     ErrorHandler(rv, nil);
00484                     break;
00485                 } else
00486                      currGlobalURLIndex = 0;
00487                 resPos = 0; // reset after first file was resumed in the middle 
00488                 gControls->state = eDownloading;
00489                 compsDone++;
00490             }
00491         }
00492               else if (compsDone >= gControls->cfg->st[instChoice].numComps)
00493                      break;  
00494     } // end for
00495     
00496         if ( rv != nsFTPConn::E_USER_CANCEL ) {   // XXX cancel is also paused :-)
00497            bDone = CRCCheckDownloadedArchives(dlPath, dlPathLen, count); 
00498            if ( bDone == false ) {
00499                compsDone = 0;
00500                crcPass++;   
00501            }
00502         } else {
00503             break;  // cancel really happened, or we paused
00504         }
00505     } // end while
00506  
00507        // clean up the Conn struct
00508        
00509        CheckConn( "", TYPE_UNDEF, &myConn, true );  
00510                
00511     if ( crcPass >= MAXCRC ) {
00512         ErrorHandler( eDownload, nil );  // XXX need a better error message here
00513         rv = eDownload;
00514     }
00515     
00516     if (rv == 0)
00517         DLMarkerDelete();
00518         
00519     return rv;
00520 }
00521 
00522 const char kHTTP[8] = "http://";
00523 const char kFTP[7] = "ftp://";
00524 
00525 short
00526 DownloadFile(Handle destFolder, long destFolderLen, Handle archive, int resPos, int urlIndex, CONN *myConn)
00527 {
00528     short rv = 0;
00529     char *URL = 0, *proxyServerURL = 0, *destFile = 0, *destFolderCopy = 0;
00530     int globalURLLen, archiveLen, proxyServerURLLen;
00531     char *ftpHost = 0, *ftpPath = 0;
00532     Boolean bGetTried = false;
00533     Boolean isNewConn;
00534     
00535     // make URL using globalURL
00536     HLock(archive);
00537     DLMarkerSetCurrent(*archive);
00538     HLock(gControls->cfg->globalURL[urlIndex]);
00539     globalURLLen = strlen(*gControls->cfg->globalURL[urlIndex]);
00540     archiveLen = strlen(*archive);
00541     URL = (char *) malloc(globalURLLen + archiveLen + 1); // add 1 for NULL termination
00542     sprintf(URL, "%s%s", *gControls->cfg->globalURL[urlIndex], *archive);
00543     HUnlock(gControls->cfg->globalURL[urlIndex]);
00544     
00545     // set up for dl progress callback
00546     sCurrURL = URL;
00547     
00548     // make dest file using dest folder and archive name
00549     HLock(destFolder);
00550     destFolderCopy = (char *) malloc(destFolderLen + 1);  // GetFullPath doesn't NULL terminate
00551     if (! destFolderCopy)
00552     {    
00553         HUnlock(destFolder);
00554         return eMem;
00555     }
00556     strncpy(destFolderCopy, *destFolder, destFolderLen);
00557     *(destFolderCopy + destFolderLen) = 0;
00558     HUnlock(destFolder);
00559     
00560     destFile = (char *) malloc(destFolderLen + archiveLen + 1);
00561     sprintf(destFile, "%s%s", destFolderCopy, *archive);
00562     HUnlock(archive);
00563      
00564     UpdateControls( gWPtr, gWPtr->visRgn ); 
00565     ShowLogo( false );  
00566     // was proxy info specified?
00567     if (gControls->opt->proxyHost && gControls->opt->proxyPort)
00568     {
00569         nsHTTPConn *conn;
00570         
00571         // make HTTP URL with "http://proxyHost:proxyPort"
00572         proxyServerURLLen = strlen(kHTTP) + strlen(gControls->opt->proxyHost) + 1 + 
00573                             strlen(gControls->opt->proxyPort) + 1;
00574         proxyServerURL = (char *) calloc(proxyServerURLLen, sizeof( char ) );
00575         sprintf(proxyServerURL, "%s%s:%s", kHTTP, gControls->opt->proxyHost, gControls->opt->proxyPort);
00576          
00577         isNewConn = CheckConn( proxyServerURL, TYPE_PROXY, myConn, false ); // closes the old connection if any
00578         
00579         if ( isNewConn == true ) {
00580         
00581               conn = new nsHTTPConn(proxyServerURL, BreathFunc);
00582         
00583               // set proxy info: proxied URL, username, password
00584 
00585               conn->SetProxyInfo(URL, gControls->opt->proxyUsername, gControls->opt->proxyPassword);
00586         
00587               myConn->conn = (void *) conn;
00588               
00589               // open an HTTP connection
00590               rv = conn->Open();
00591             if ( rv == nsHTTPConn::OK ) {
00592               myConn->conn = (void *) conn;
00593               myConn->type = TYPE_PROXY;
00594               myConn->URL = (char *) calloc( strlen( proxyServerURL ) + 1, sizeof( char ) );
00595               if ( myConn->URL != (char *) NULL )
00596                      strcpy( myConn->URL, proxyServerURL );
00597            }
00598         } else {
00599               conn = (nsHTTPConn *) myConn->conn;
00600         }
00601         
00602         if (isNewConn ==false || rv == nsHTTPConn::OK)
00603         {
00604             sCurrStartTime = time(NULL);
00605             bGetTried = true;
00606             rv = conn->Get(DLProgressCB, destFile, resPos);
00607         }
00608     }
00609         
00610     // else do we have an HTTP URL? 
00611     else if (strncmp(URL, kHTTP, strlen(kHTTP)) == 0)
00612     {
00613        nsHTTPConn *conn;
00614 
00615         // XXX for now, the URL is always different, so we always create a new
00616         // connection here
00617         
00618         isNewConn = CheckConn( URL, TYPE_HTTP, myConn, false ); // closes the old connection if any
00619         
00620         if ( isNewConn == true ) {
00621               // open an HTTP connection
00622               
00623               conn = new nsHTTPConn(URL, BreathFunc);
00624         
00625               myConn->conn = (void *) conn;
00626         
00627               rv = conn->Open();
00628             if ( rv == nsHTTPConn::OK ) {
00629               myConn->conn = (void *) conn;
00630               myConn->type = TYPE_HTTP;
00631               myConn->URL = (char *) calloc( strlen( URL ) + 1, sizeof( char ) );
00632               if ( myConn->URL != (char *) NULL )
00633                      strcpy( myConn->URL, URL );
00634            }
00635         } else
00636               conn = (nsHTTPConn *) myConn->conn;
00637         
00638         if (isNewConn == false || rv == nsHTTPConn::OK)
00639         {
00640             sCurrStartTime = time(NULL);
00641             bGetTried = true;
00642             rv = conn->Get(DLProgressCB, destFile, resPos);
00643         }
00644     }
00645     
00646     // else do we have an FTP URL?
00647     else if (strncmp(URL, kFTP, strlen(kFTP)) == 0)
00648     {
00649         rv = ParseFTPURL(URL, &ftpHost, &ftpPath);
00650         if (!*ftpHost || !*ftpPath)
00651         {
00652             rv = nsHTTPConn::E_MALFORMED_URL;
00653         }
00654         else
00655         {
00656             nsFTPConn *conn;
00657             
00658             // open an FTP connection
00659               isNewConn = CheckConn( ftpHost, TYPE_FTP, myConn, false ); // closes the old connection if any
00660         
00661               if ( isNewConn == true ) {
00662               
00663               conn = new nsFTPConn(ftpHost, BreathFunc);
00664             
00665               rv = conn->Open();
00666               if ( rv == nsFTPConn::OK ) {
00667                      myConn->conn = (void *) conn;
00668                      myConn->type = TYPE_FTP;
00669                      myConn->URL = (char *) calloc( strlen( ftpHost ) + 1, sizeof( char ) );
00670                      if ( myConn->URL != (char *) NULL )
00671                             strcpy( myConn->URL, ftpHost );
00672               }
00673             } else 
00674               conn = (nsFTPConn *) myConn->conn;
00675               
00676             if (isNewConn == false || rv == nsFTPConn::OK)
00677             {
00678                 sCurrStartTime = time(NULL);
00679                 bGetTried = true;
00680                 rv = conn->Get(ftpPath, destFile, nsFTPConn::BINARY, resPos, 1, DLProgressCB);
00681             }
00682         }
00683         if (ftpHost)
00684             free(ftpHost);
00685         if (ftpPath)
00686             free(ftpPath);
00687     }
00688         
00689     // else not supported so report an error
00690     else
00691         rv = nsHTTPConn::E_MALFORMED_URL;
00692     
00693     if (bGetTried && rv != 0)
00694     {
00695        // Connection was closed for us, clear out the Conn information
00696        
00697  //    myConn->type = TYPE_UNDEF;
00698  //    free( myConn->URL );
00699  //    myConn->URL = (char *) NULL;
00700        
00701         if (++urlIndex < gControls->cfg->numGlobalURLs)
00702             return eDLFailed;  // don't pase yet: continue trying failover URLs
00703             
00704         /* the get failed before completing; simulate pause */
00705         SetPausedState();
00706         rv = nsFTPConn::E_USER_CANCEL;
00707     }
00708     
00709     return rv;
00710 }
00711 
00712 /* 
00713  * Name: CheckConn
00714  *
00715  * Arguments: 
00716  *
00717  * char *URL;     -- URL of connection we need to have established
00718  * int type;    -- connection type (TYPE_HTTP, etc.)
00719  * CONN *myConn;  -- connection state (info about currently established connection)
00720  * Boolean force; -- force closing of connection
00721  *
00722  * Description:
00723  *
00724  * This function determines if the caller should open a connection based upon the current
00725  * connection that is open (if any), and the type of connection desired.
00726  * If no previous connection was established, the function returns true. If the connection
00727  * is for a different protocol, then true is also returned (and the previous connection is
00728  * closed). If the connection is for the same protocol and the URL is different, the previous
00729  * connection is closed and true is returned. Otherwise, the connection has already been
00730  * established, and false is returned.
00731  *
00732  * Return Value: If a new connection needs to be opened, true. Otherwise, false is returned.
00733  *
00734  * Original Code: Syd Logan (syd@netscape.com) 6/24/2001
00735  *
00736 */
00737 
00738 Boolean
00739 CheckConn( char *URL, int type, CONN *myConn, Boolean force )
00740 {
00741        nsFTPConn *fconn;
00742        nsHTTPConn *hconn;
00743        Boolean retval = false;
00744 
00745        if ( myConn->type == TYPE_UNDEF )
00746               retval = true;                                   // first time
00747        else if ( ( myConn->type != type || strcmp( URL, myConn->URL ) || force == true ) && gControls->state != ePaused) {
00748               retval = true;
00749               switch ( myConn->type ) {
00750               case TYPE_HTTP:
00751               case TYPE_PROXY:
00752                      hconn = (nsHTTPConn *) myConn->conn;
00753                      hconn->Close();
00754                      break;
00755               case TYPE_FTP:
00756                      fconn = (nsFTPConn *) myConn->conn;
00757                      fconn->Close();
00758                      break;
00759               }
00760        }
00761        
00762        if ( retval == true && myConn->URL != (char *) NULL )
00763        free( myConn->URL );
00764 
00765        return retval;
00766 }
00767 
00768 OSErr 
00769 DLMarkerSetCurrent(char *aXPIName)
00770 {
00771     OSErr err = noErr;
00772     short vRefNum = 0;
00773     long dirID = 0;
00774     FSSpec fsMarker;
00775     short markerRefNum;
00776     long count = 0;
00777     
00778     if (!aXPIName)
00779         return paramErr;
00780         
00781     err = GetInstallerModules(&vRefNum, &dirID);
00782     if (err != noErr)
00783         return err;
00784         
00785     // check if marker file exists        
00786     err = FSMakeFSSpec(vRefNum, dirID, kDLMarker, &fsMarker);
00787     
00788     // delete old marker and recreate it so we truncate to 0
00789     if (err == noErr)
00790         FSpDelete(&fsMarker);
00791 
00792     err = FSpCreate(&fsMarker, 'ttxt', 'TEXT', smSystemScript);
00793     if (err != noErr)
00794         return err;
00795         
00796     // open data fork
00797     err = FSpOpenDF(&fsMarker, fsWrPerm, &markerRefNum);
00798     if (err != noErr)
00799         goto BAIL;
00800         
00801     // write xpi name into marker's data fork at offset 0    
00802     count = strlen(aXPIName);
00803     err = FSWrite(markerRefNum, &count, (void *) aXPIName);
00804     
00805 BAIL:
00806     // close marker file
00807     FSClose(markerRefNum);
00808     
00809     return err;
00810 }
00811 
00812 OSErr
00813 DLMarkerGetCurrent(int *aMarkedIndex, int *aCompsDone)
00814 {
00815     OSErr err = noErr;
00816     char xpiName[255];
00817     short vRefNum = 0;
00818     long dirID = 0;
00819     long count = 0;
00820     FSSpec fsMarker;
00821     short markerRefNum;
00822     
00823     if (!aMarkedIndex || !aCompsDone)
00824         return paramErr;
00825         
00826     err = GetInstallerModules(&vRefNum, &dirID);
00827     if (err != noErr)
00828         return err;
00829         
00830     // check if marker file exists
00831     err = FSMakeFSSpec(vRefNum, dirID, kDLMarker, &fsMarker);
00832     if (err == noErr)
00833     {
00834         // open for reading
00835         err = FSpOpenDF(&fsMarker, fsRdPerm, &markerRefNum);
00836         if (err != noErr)
00837             goto CLOSE_FILE;
00838             
00839         // get file size
00840         err = GetEOF(markerRefNum, &count);
00841         if (err != noErr)
00842             goto CLOSE_FILE;
00843             
00844         // read file contents
00845         err = FSRead(markerRefNum, &count, (void *) xpiName);
00846         if (err == noErr)
00847         {
00848             if (count <= 0)
00849                 err = readErr;
00850             else
00851             {
00852                 xpiName[count] = 0; // ensure only reading 'count' bytes
00853                 err = GetIndexFromName(xpiName, aMarkedIndex, aCompsDone);
00854             }
00855         }
00856         
00857 CLOSE_FILE:
00858         // close file
00859         FSClose(markerRefNum);
00860     }
00861     
00862     return err;
00863 }
00864 
00865 OSErr 
00866 DLMarkerDelete(void)
00867 {
00868     OSErr err;
00869     short vRefNum = 0;
00870     long dirID = 0;
00871     FSSpec fsMarker;
00872     
00873     err = GetInstallerModules(&vRefNum, &dirID);
00874     if (err == noErr)
00875     {
00876         err = FSMakeFSSpec(vRefNum, dirID, kDLMarker, &fsMarker);
00877         if (err == noErr)
00878             FSpDelete(&fsMarker);
00879     }
00880     
00881     return noErr;
00882 }
00883 
00884 OSErr
00885 GetIndexFromName(char *aXPIName, int *aIndex, int *aCompsDone)
00886 {
00887     OSErr err = noErr;
00888     int i, compsDone = 0, instChoice = gControls->opt->instChoice - 1;
00889     
00890     if (!aXPIName || !aIndex || !aCompsDone)
00891         return paramErr;
00892         
00893     // loop through 0 to kMaxComponents
00894        for(i = 0; i < kMaxComponents; i++)
00895        {
00896               // general test: if component in setup type
00897               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
00898                       (compsDone < gControls->cfg->st[instChoice].numComps) )
00899               { 
00900             // if custom and selected -or- not custom setup type
00901             if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
00902                  (gControls->cfg->comp[i].selected == true)) ||
00903                  (instChoice < gControls->cfg->numSetupTypes-1) )
00904             {   
00905                 HLock(gControls->cfg->comp[i].archive);
00906                 if (strncmp(aXPIName, (*(gControls->cfg->comp[i].archive)), strlen(aXPIName)) == 0)
00907                 {
00908                     HUnlock(gControls->cfg->comp[i].archive);
00909                     *aIndex = i;
00910                     *aCompsDone = compsDone;
00911                     break;
00912                 }   
00913                 else
00914                     HUnlock(gControls->cfg->comp[i].archive);                 
00915                 compsDone++;
00916             }
00917         }
00918               else if (compsDone >= gControls->cfg->st[instChoice].numComps)
00919               {
00920                   err = userDataItemNotFound;
00921                      break;
00922            }
00923     }
00924     return err;
00925 }
00926 
00927 int
00928 GetResPos(InstComp *aComp)
00929 {
00930     OSErr err = noErr;
00931     int resPos = 0;
00932     short vRefNum = 0;
00933     long dirID = 0;
00934     Str255 pArchiveName;
00935     long dataSize = 0, rsrcSize = 0;
00936     
00937     if (!aComp)
00938         return 0;
00939     
00940     err = GetInstallerModules(&vRefNum, &dirID);
00941     if (err == noErr)
00942     {
00943         HLock(aComp->archive);
00944         my_c2pstrcpy(*(aComp->archive), pArchiveName);
00945         HUnlock(aComp->archive);
00946         
00947         err = GetFileSize(vRefNum, dirID, pArchiveName, &dataSize, &rsrcSize);
00948         if (err == noErr && dataSize > 0)
00949             resPos = dataSize;
00950     }
00951     
00952     return resPos;
00953 }
00954 
00955 OSErr
00956 GetInstallerModules(short *aVRefNum, long *aDirID)
00957 {
00958     short cwdVRefNum = 0;
00959     long cwdDirID = 0, imDirID = 0;
00960     OSErr err;
00961     Boolean isDir = false;
00962     Str255 pIMFolder;  // "Installer Modules" fodler
00963     
00964     if (!aVRefNum || !aDirID)
00965         return paramErr;
00966       
00967     *aVRefNum = 0;
00968     *aDirID = 0;
00969       
00970     err = GetCWD(&cwdDirID, &cwdVRefNum);
00971     if (err != noErr)
00972         return err;
00973         
00974     GetIndString(pIMFolder, rStringList, sInstModules);
00975     err = GetDirectoryID(cwdVRefNum, cwdDirID, pIMFolder, &imDirID, &isDir);
00976     if (err != noErr)
00977         return err;
00978         
00979     if (isDir)
00980     {
00981         *aVRefNum = cwdVRefNum;
00982         *aDirID = imDirID;
00983     }
00984     else
00985         return dirNFErr;
00986         
00987     return err;
00988 }
00989 
00990 int 
00991 ParseFTPURL(char *aURL, char **aHost, char **aPath)
00992 {
00993     char *pos, *nextSlash, *nextColon, *end, *hostEnd;
00994     int protoLen = strlen(kFTP);
00995 
00996     if (!aURL || !aHost || !aPath)
00997         return -1;
00998 
00999     if (strncmp(aURL, kFTP, protoLen) != 0)
01000         return nsHTTPConn::E_MALFORMED_URL;
01001 
01002     pos = aURL + protoLen;
01003     nextColon = strchr(pos, ':');
01004     nextSlash = strchr(pos, '/');
01005 
01006     // only host in URL, assume '/' for path
01007     if (!nextSlash)
01008     {
01009         int copyLen;
01010         if (nextColon)
01011             copyLen = nextColon - pos;
01012         else
01013             copyLen = strlen(pos);
01014 
01015         *aHost = (char *) malloc(copyLen + 1); // to NULL terminate
01016         if (!aHost)
01017             return eMem;
01018         memset(*aHost, 0, copyLen + 1);
01019         strncpy(*aHost, pos, copyLen);
01020 
01021         *aPath = (char *) malloc(2);
01022         strcpy(*aPath, "/");
01023 
01024         return 0;
01025     }
01026     
01027     // normal parsing: both host and path exist
01028     if (nextColon)
01029         hostEnd = nextColon;
01030     else
01031         hostEnd = nextSlash;
01032     *aHost = (char *) malloc(hostEnd - pos + 1); // to NULL terminate
01033     if (!*aHost)
01034         return eMem;
01035     memset(*aHost, 0, hostEnd - pos + 1);
01036     strncpy(*aHost, pos, hostEnd - pos);
01037     *(*aHost + (hostEnd - pos)) = 0; // NULL terminate
01038 
01039     pos = nextSlash;
01040     end = aURL + strlen(aURL);
01041 
01042     *aPath = (char *) malloc(end - pos + 1);
01043     if (!*aPath)
01044     {
01045         if (*aHost)
01046             free(*aHost);
01047         return eMem;
01048     }
01049     memset(*aPath, 0, end - pos + 1);
01050     strncpy(*aPath, pos, end - pos);
01051 
01052     return 0;
01053 }
01054 
01055 void
01056 CompressToFit(char *origStr, char *outStr, int outStrLen)
01057 {
01058     int origStrLen;
01059     int halfOutStrLen;
01060     char *lastPart; // last origStr part start
01061 
01062     if (!origStr || !outStr || outStrLen <= 0)
01063         return;
01064         
01065     origStrLen = strlen(origStr);    
01066     halfOutStrLen = outStrLen/2;
01067     lastPart = origStr + origStrLen - halfOutStrLen;
01068     
01069     // don't truncate if already less than acceptable max len
01070     if (origStrLen < outStrLen)
01071     {
01072         strcpy(outStr, origStr);
01073         *(outStr + strlen(origStr)) = 0;
01074         return; 
01075     }
01076     
01077     strncpy(outStr, origStr, halfOutStrLen);
01078     *(outStr + halfOutStrLen) = 0;
01079     strcat(outStr, "");
01080     strncat(outStr, lastPart, strlen(lastPart));
01081     *(outStr + outStrLen + 1) = 0;
01082 }
01083 
01084 float
01085 ComputeRate(int bytes, time_t startTime, time_t endTime)
01086 {
01087     double period = difftime(endTime, startTime);
01088     float rate = bytes/period;
01089     
01090     rate /= 1024;  // convert from bytes/sec to KB/sec
01091     
01092     return rate;
01093 }
01094 
01095 #define kProgMsgLen 51
01096 #define kLowRateThreshold ((float)20)
01097 
01098 int
01099 DLProgressCB(int aBytesSoFar, int aTotalFinalSize)
01100 {   
01101     static int yielder = 0, yieldFrequency = 8;
01102     int len;
01103     char compressedStr[kProgMsgLen + 1];  // add one for NULL termination
01104     char *fullPathCopy = 0; // GetFullPath doesn't null terminate
01105     float rate = 0;
01106     time_t now;
01107     Rect teRect;
01108     Str255 dlStr;
01109     char tmp[kKeyMaxLen];
01110       
01111     if (gControls->state == ePaused)
01112     {
01113         return nsFTPConn::E_USER_CANCEL;
01114     }
01115             
01116     if (aTotalFinalSize != sCurrTotalDLSize)
01117     {
01118         sCurrTotalDLSize = aTotalFinalSize;
01119         if (gControls->tw->dlProgressBar)
01120             SetControlMaximum(gControls->tw->dlProgressBar, (aTotalFinalSize/1024));
01121         
01122         // set short desc name of package being downloaded in Downloading field
01123         if (gControls->cfg->comp[sCurrComp].shortDesc)
01124         {
01125             HLock(gControls->cfg->comp[sCurrComp].shortDesc);
01126             if (*(gControls->cfg->comp[sCurrComp].shortDesc) && gControls->tw->dlProgressMsgs[0])
01127             {
01128                 HLock((Handle)gControls->tw->dlProgressMsgs[0]);
01129                 teRect = (**(gControls->tw->dlProgressMsgs[0])).viewRect;
01130                 EraseRect(&teRect);
01131                 HUnlock((Handle)gControls->tw->dlProgressMsgs[0]);                
01132  
01133                 len = strlen(*(gControls->cfg->comp[sCurrComp].shortDesc));
01134                 TESetText(*(gControls->cfg->comp[sCurrComp].shortDesc), len, 
01135                     gControls->tw->dlProgressMsgs[0]);
01136                 TEUpdate(&teRect, gControls->tw->dlProgressMsgs[0]);
01137             }
01138             HUnlock(gControls->cfg->comp[sCurrComp].shortDesc);
01139         }
01140 
01141         // compress URL string and insert in From field
01142         if (sCurrURL && gControls->tw->dlProgressMsgs[1])
01143         {
01144             HLock((Handle)gControls->tw->dlProgressMsgs[1]);
01145             teRect = (**(gControls->tw->dlProgressMsgs[1])).viewRect;
01146             HUnlock((Handle)gControls->tw->dlProgressMsgs[1]);
01147             
01148             CompressToFit(sCurrURL, compressedStr, kProgMsgLen);
01149             TESetText(compressedStr, kProgMsgLen, gControls->tw->dlProgressMsgs[1]);
01150             TEUpdate(&teRect, gControls->tw->dlProgressMsgs[1]);
01151         }
01152                             
01153         // compress fullpath string and insert in To field
01154         if (sCurrFullPath)
01155         {
01156             HLock(sCurrFullPath);
01157             if (*sCurrFullPath && gControls->tw->dlProgressMsgs[2])
01158             {
01159                 fullPathCopy = (char *)malloc(sCurrFullPathLen + 1);               
01160                 if (fullPathCopy)
01161                 {
01162                     strncpy(fullPathCopy, (*sCurrFullPath), sCurrFullPathLen);
01163                     *(fullPathCopy + sCurrFullPathLen) = 0;
01164                     
01165                     HLock((Handle)gControls->tw->dlProgressMsgs[2]);
01166                     teRect = (**(gControls->tw->dlProgressMsgs[2])).viewRect;
01167                     HUnlock((Handle)gControls->tw->dlProgressMsgs[2]);
01168                     
01169                     CompressToFit(fullPathCopy, compressedStr, kProgMsgLen);
01170                     TESetText(compressedStr, kProgMsgLen, gControls->tw->dlProgressMsgs[2]);
01171                     TEUpdate(&teRect, gControls->tw->dlProgressMsgs[2]);
01172                     
01173                     free(fullPathCopy);
01174                 }                
01175             }
01176             HUnlock(sCurrFullPath);
01177         }
01178     }
01179         
01180     if (gControls->tw->dlProgressBar)
01181     {      
01182         // update rate info
01183         now = time(NULL);
01184         rate = ComputeRate(aBytesSoFar, sCurrStartTime, now);                      
01185         
01186         if ((rate < kLowRateThreshold) || ((++yielder) == yieldFrequency))
01187         {
01188             int adjustedBytesSoFar = aBytesSoFar;
01189             if (gControls->state == eResuming)
01190                 adjustedBytesSoFar += gControls->resPos;
01191             SetControlValue(gControls->tw->dlProgressBar, (adjustedBytesSoFar/1024));
01192             
01193             // create processing string "%d KB of %d KB  (%.2f KB/sec)"
01194             GetResourcedString(dlStr, rInstList, sDownloadKB);
01195             strcpy(compressedStr, PascalToC(dlStr));
01196             sprintf(tmp, "%d", adjustedBytesSoFar/1024);
01197             strtran(compressedStr, "%d1", tmp);
01198             sprintf(tmp, "%d", aTotalFinalSize/1024);
01199             strtran(compressedStr, "%d2", tmp);
01200             sprintf(tmp, "%.2f", rate);
01201             strtran(compressedStr, "%.2f", tmp);
01202 
01203             HLock((Handle)gControls->tw->dlProgressMsgs[3]);
01204             teRect = (**(gControls->tw->dlProgressMsgs[3])).viewRect;
01205             HUnlock((Handle)gControls->tw->dlProgressMsgs[3]);
01206             
01207             TESetText(compressedStr, strlen(compressedStr), gControls->tw->dlProgressMsgs[3]);
01208             TEUpdate(&teRect, gControls->tw->dlProgressMsgs[3]);
01209             
01210             yielder = 0;   
01211             YieldToAnyThread();
01212         }
01213     }
01214     
01215     return 0;
01216 }
01217 
01218 void
01219 IfRemoveOldCore(short vRefNum, long dirID)
01220 {
01221        FSSpec        fsViewer;
01222        OSErr  err = noErr;
01223        
01224        err = FSMakeFSSpec(vRefNum, dirID, kViewerFolder, &fsViewer);
01225        if (err == noErr)  // old core exists
01226               err = DeleteDirectory(fsViewer.vRefNum, fsViewer.parID, fsViewer.name);
01227 }
01228 
01229 #define IDI_BUF_SIZE 512
01230 
01231 Boolean       
01232 GenerateIDIFromOpt(Str255 idiName, long dirID, short vRefNum, FSSpec *idiSpec)
01233 {
01234        Boolean bSuccess = true;
01235        OSErr  err;
01236        short  refNum, instChoice;
01237        long   count, compsDone, i;
01238        char   ch, buf[IDI_BUF_SIZE];
01239        Ptr    keybuf;
01240        Str255 pkeybuf;
01241        FSSpec fsExists;
01242        StringPtr     pcurrArchive = 0;
01243        
01244        err = FSMakeFSSpec(vRefNum, dirID, idiName, idiSpec);
01245        if ((err != noErr) && (err != fnfErr))
01246        {
01247               ErrorHandler(err, nil);
01248               return false;
01249        }
01250        err = FSpCreate(idiSpec, 'NSCP', 'TEXT', smSystemScript);
01251        if ( (err != noErr) && (err != dupFNErr))
01252        {
01253               ErrorHandler(err, nil);
01254               return false;
01255        }
01256        ERR_CHECK_RET(FSpOpenDF(idiSpec, fsRdWrPerm, &refNum), false);
01257        
01258        compsDone = 0;
01259        instChoice = gControls->opt->instChoice-1;
01260        
01261        // loop through 0 to kMaxComponents
01262        for(i=0; i<kMaxComponents; i++)
01263        {
01264               // general test: if component in setup type
01265               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
01266                       (compsDone < gControls->cfg->st[instChoice].numComps) )
01267               { 
01268                      // if custom and selected, or not custom setup type
01269                      // add file to buffer
01270                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
01271                               (gControls->cfg->comp[i].selected == true)) ||
01272                              (instChoice < gControls->cfg->numSetupTypes-1) )
01273                      {
01274                             // verify that file does not exist already
01275                             HLock(gControls->cfg->comp[i].archive);
01276                             pcurrArchive = CToPascal(*gControls->cfg->comp[i].archive);
01277                             HUnlock(gControls->cfg->comp[i].archive);                      
01278                             err = FSMakeFSSpec(vRefNum, dirID, pcurrArchive, &fsExists);
01279                             
01280                             // if file doesn't exist
01281                             if (err == fnfErr)
01282                             {
01283                                 char   fnum[12];
01284                                    // get file number 
01285                                    // fnum = ltoa(compsDone);
01286                                    sprintf(fnum, "%ld", compsDone);
01287                                    
01288                                 memset(buf, 0, IDI_BUF_SIZE);
01289                                 
01290                                    // construct through concatenation [File<num>]\r
01291                                    GetIndString(pkeybuf, rIDIKeys, sFile);
01292 
01293                                    ch = '[';
01294                                    strncpy(buf, &ch, 1);
01295                     CopyPascalStrToC(pkeybuf, buf + strlen(buf));
01296                                    strncat(buf, fnum, strlen(fnum));
01297                                    strcat(buf, "]\r");
01298 
01299                                    // write out \tdesc=
01300                                    GetIndString(pkeybuf, rIDIKeys, sDesc);
01301                                    ch = '\t';                                                     
01302                                    strncat(buf, &ch, 1);                                   // \t
01303                                    CopyPascalStrToC(pkeybuf, buf + strlen(buf));
01304                                    ch = '=';                                                      // \tdesc=
01305                                    strncat(buf, &ch, 1);
01306                             
01307                                    // write out gControls->cfg->comp[i].shortDesc\r
01308                                    HLock(gControls->cfg->comp[i].shortDesc);
01309                                    strncat(buf, *gControls->cfg->comp[i].shortDesc, strlen(*gControls->cfg->comp[i].shortDesc));                          
01310                                    HUnlock(gControls->cfg->comp[i].shortDesc);
01311                                    ch = '\r';
01312                                    strncat(buf, &ch, 1);
01313                               
01314                                    // write out \t0=                       // \t0=
01315                                    strcat(buf, "\t0=");
01316                                    
01317                                    // tack on URL to xpi directory         // \t0=<URL>
01318                                    HLock(gControls->cfg->globalURL[0]);
01319                                    strcat(buf, *gControls->cfg->globalURL[0]);
01320                                    HUnlock(gControls->cfg->globalURL[0]);
01321                                    
01322                                    // tack on 'archive\r'                  // \t0=<URL>/archive\r
01323                                    HLock(gControls->cfg->comp[i].archive);
01324                                    strncat(buf, *gControls->cfg->comp[i].archive, strlen(*gControls->cfg->comp[i].archive));
01325                                    HUnlock(gControls->cfg->comp[i].archive);
01326                                    ch = '\r';
01327                                    strncat(buf, &ch, 1);
01328                                    
01329                                    count = strlen(buf);
01330                        err = FSWrite(refNum, &count, buf);
01331                        
01332                                    if (err != noErr)
01333                                        goto BAIL;
01334                                        
01335                                    compsDone++;
01336                             }
01337                      }
01338               }
01339               else if (compsDone >= gControls->cfg->st[instChoice].numComps)
01340                      break;  
01341        }                    
01342        
01343        // terminate by entering Netscape Install section
01344        memset(buf, 0, IDI_BUF_SIZE);
01345        GetIndString(pkeybuf, rIDIKeys, sNSInstall);
01346        keybuf = PascalToC(pkeybuf);
01347        ch = '[';
01348        strncpy(buf, &ch, 1);                                   // [
01349        strncat(buf, keybuf, strlen(keybuf));     // [Netscape Install
01350        if (keybuf)
01351               DisposePtr(keybuf);
01352        
01353        keybuf = NewPtrClear(2);
01354        keybuf = "]\r";                           
01355        strncat(buf, keybuf, strlen(keybuf));     // [Netscape Install]\r
01356        if (keybuf)
01357               DisposePtr(keybuf);
01358        
01359        // write out \tcore_file=<filename>\r
01360        AddKeyToIDI( sCoreFile, gControls->cfg->coreFile, buf );
01361        
01362        // write out \tcore_dir=<dirname>\r
01363        AddKeyToIDI( sCoreDir, gControls->cfg->coreDir, buf );
01364        
01365        // write out \tno_ads=<boolean>\r
01366        AddKeyToIDI( sNoAds, gControls->cfg->noAds, buf );
01367        
01368        // write out \tsilent=<boolean>\r
01369        AddKeyToIDI( sSilent, gControls->cfg->silent, buf );
01370        
01371        // write out \texecution=<boolean>\r
01372        AddKeyToIDI( sExecution, gControls->cfg->execution, buf );
01373        
01374        // write out \tconfirm_install=<boolean>
01375        AddKeyToIDI( sConfirmInstall, gControls->cfg->confirmInstall, buf );
01376        
01377        // write buf to disk
01378        count = strlen(buf);
01379        ERR_CHECK_RET(FSWrite(refNum, &count, buf), false);
01380 
01381 BAIL:  
01382        // close file
01383        ERR_CHECK_RET(FSClose(refNum), false);
01384        
01385        return bSuccess;
01386 }
01387 
01388 void
01389 AddKeyToIDI(short key, Handle val, char *ostream)
01390 {
01391        Str255 pkeybuf;
01392        char   *keybuf, *cval, ch;
01393        
01394        HLock(val);
01395        cval = *val;
01396        
01397        GetIndString(pkeybuf, rIDIKeys, key);
01398        keybuf = PascalToC(pkeybuf);
01399        ch = '\t';
01400        strncat(ostream, &ch, 1);                               // \t
01401        strncat(ostream, keybuf, strlen(keybuf)); // \t<key>
01402        ch = '=';
01403        strncat(ostream, &ch, 1);                               // \t<key>=
01404        strncat(ostream, cval, strlen(cval));            // \t<key>=<val>
01405        ch = '\r';
01406        strncat(ostream, &ch, 1);                               // \t<key>=<val>\r
01407        
01408        HUnlock(val);
01409        
01410        if (keybuf)
01411               DisposePtr(keybuf);
01412 }
01413 
01414 Boolean
01415 ExistArchives(short vRefNum, long dirID)
01416 {
01417        int           compsDone = 0, i;
01418        int           instChoice = gControls->opt->instChoice - 1;
01419        OSErr         err = noErr;
01420        StringPtr     pArchiveName;
01421        FSSpec        fsCurr;
01422        Boolean              bAllExist = true;
01423        
01424        // loop through 0 to kMaxComponents
01425        for(i=0; i<kMaxComponents; i++)
01426        {
01427               // general test: if component in setup type
01428               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
01429                       (compsDone < gControls->cfg->st[instChoice].numComps) )
01430               { 
01431                      // if custom and selected, or not custom setup type
01432                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
01433                               (gControls->cfg->comp[i].selected == true)) ||
01434                              (instChoice < gControls->cfg->numSetupTypes-1) )
01435                      {
01436                             HLock(gControls->cfg->comp[i].archive);
01437                             pArchiveName = CToPascal(*gControls->cfg->comp[i].archive);
01438                             HUnlock(gControls->cfg->comp[i].archive);
01439                             
01440                             err = FSMakeFSSpec(vRefNum, dirID, pArchiveName, &fsCurr);
01441                             if (err != noErr)
01442                             {
01443                                    bAllExist = false;
01444                                    if (pArchiveName)
01445                                           DisposePtr((Ptr)pArchiveName);
01446                                    break;
01447                             }
01448                             
01449                             if (pArchiveName)
01450                                    DisposePtr((Ptr)pArchiveName);
01451                      }
01452               }
01453               
01454               compsDone++;
01455        }
01456        
01457        return bAllExist;
01458 }
01459 
01460 OSErr
01461 ExistsXPI(int aIndex)
01462 {
01463     OSErr err = noErr;
01464     FSSpec fsComp;
01465     short vRefNum = 0;
01466     long dirID = 0;
01467     Str255 pArchive;
01468     
01469     if (aIndex < 0)
01470         return paramErr;
01471         
01472     err = GetInstallerModules(&vRefNum, &dirID);
01473     if (err == noErr)
01474     {
01475         HLock(gControls->cfg->comp[aIndex].archive);
01476         my_c2pstrcpy(*(gControls->cfg->comp[aIndex].archive), pArchive);
01477         HUnlock(gControls->cfg->comp[aIndex].archive);
01478         err = FSMakeFSSpec(vRefNum, dirID, pArchive, &fsComp);
01479     }
01480     
01481     return err;
01482 }
01483 
01484 void 
01485 LaunchApps(short vRefNum, long dirID)
01486 {
01487        int                         compsDone = 0, i;
01488        int                         instChoice = gControls->opt->instChoice-1;
01489        FSSpec                             fsCurrArchive, fsCurrApp;
01490        OSErr                       err = noErr;
01491        StringPtr                   pArchiveName;
01492        LaunchParamBlockRec  launchPB;
01493        
01494        // loop through 0 to kMaxComponents
01495        for(i=0; i<kMaxComponents; i++)
01496        {
01497               // general test: if component in setup type
01498               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
01499                       (compsDone < gControls->cfg->st[instChoice].numComps) )
01500               { 
01501                      // if custom and selected, or not custom setup type
01502                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
01503                               (gControls->cfg->comp[i].selected == true)) ||
01504                              (instChoice < gControls->cfg->numSetupTypes-1) )
01505                      {
01506                             // if the LAUNCHAPP attr was set
01507                             if (gControls->cfg->comp[i].launchapp)
01508                             {
01509                                    // AppleSingle decode the app
01510                                    HLock(gControls->cfg->comp[i].archive);
01511                                    pArchiveName = CToPascal(*gControls->cfg->comp[i].archive);
01512                                    HUnlock(gControls->cfg->comp[i].archive);
01513                                    
01514                                    err = FSMakeFSSpec(vRefNum, dirID, pArchiveName, &fsCurrArchive);
01515                                    if (err == noErr) /* archive exists */
01516                                    {
01517                                           err = AppleSingleDecode(&fsCurrArchive, &fsCurrApp);
01518                                           if (err == noErr) /* AppleSingle decoded successfully */
01519                                           {      
01520                                                  // launch the decoded app
01521                                                  launchPB.launchAppSpec = &fsCurrApp;
01522                                                  launchPB.launchAppParameters = NULL;
01523                                                  launchPB.launchBlockID = extendedBlock;
01524                                                  launchPB.launchEPBLength = extendedBlockLen;
01525                                                  launchPB.launchFileFlags = NULL;
01526                                                  launchPB.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
01527                                                  launchPB.launchControlFlags += launchDontSwitch;
01528 
01529                                                  err = LaunchApplication( &launchPB );
01530 #ifdef MIW_DEBUG
01531                                                  if (err!=noErr) SysBeep(10);
01532 #endif
01533                                                  
01534                                           }
01535                                    }
01536                                    
01537                                    if (pArchiveName)
01538                                           DisposePtr((Ptr)pArchiveName);
01539                             }      
01540                      }
01541               }
01542               
01543               compsDone++;
01544        }
01545 }
01546 
01547 void
01548 RunApps(void)
01549 {
01550        OSErr                       err = noErr;
01551        int                         i;
01552 #if 0
01553        Ptr                                appSigStr;
01554 #endif
01555        Ptr                                docStr;       
01556        StringPtr                   relAppPath;
01557        OSType                             appSig = 0x00000000;
01558        FSSpec                             app, doc;
01559        ProcessSerialNumber  psn;
01560        StringPtr                   pdocName;
01561        unsigned short              launchFileFlags, launchControlFlags;
01562        Boolean                     running = nil;
01563        LaunchParamBlockRec  launchPB;
01564        
01565        for (i = 0; i < gControls->cfg->numRunApps; i++)
01566        {      
01567               // convert str to ulong
01568               HLock(gControls->cfg->apps[i].targetApp);
01569 #if 0
01570               appSigStr = *(gControls->cfg->apps[i].targetApp);
01571               UNIFY_CHAR_CODE(appSig, *(appSigStr), *(appSigStr+1), *(appSigStr+2), *(appSigStr+3));
01572               err =  FindAppUsingSig(appSig, &app, &running, &psn);
01573 #endif
01574               relAppPath = CToPascal(*(gControls->cfg->apps[i].targetApp));
01575               err = FSMakeFSSpec(gControls->opt->vRefNum, gControls->opt->dirID, relAppPath, &app);
01576               HUnlock(gControls->cfg->apps[i].targetApp);
01577               if (err != noErr)
01578                      continue;
01579               
01580               // if doc supplied
01581               HLock(gControls->cfg->apps[i].targetDoc);
01582               docStr = *(gControls->cfg->apps[i].targetDoc);
01583               if ( gControls->cfg->apps[i].targetDoc && docStr && *docStr )
01584               {      
01585                      // qualify and create an FSSpec to it ensuring it exists
01586                      pdocName = CToPascal(docStr);
01587                      if (pdocName)
01588                      {
01589                             err = FSMakeFSSpec(gControls->opt->vRefNum, gControls->opt->dirID, pdocName, &doc);
01590                      
01591                             // launch app using doc
01592                             if (err == noErr)
01593                             {
01594                                    launchFileFlags = NULL;
01595                                    launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
01596                                    LaunchAppOpeningDoc(running, &app, &psn, &doc, 
01597                                                                       launchFileFlags, launchControlFlags);
01598                             }
01599                      }
01600                      if (pdocName)
01601                             DisposePtr((Ptr)pdocName);
01602               }
01603               // else if doc not supplied
01604               else
01605               {
01606                      // launch app                                           
01607                      launchPB.launchAppSpec = &app;
01608                      launchPB.launchAppParameters = NULL;
01609                      launchPB.launchBlockID = extendedBlock;
01610                      launchPB.launchEPBLength = extendedBlockLen;
01611                      launchPB.launchFileFlags = NULL;
01612                      launchPB.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
01613 
01614                      err = LaunchApplication( &launchPB );
01615                      
01616               }
01617               HUnlock(gControls->cfg->apps[i].targetDoc);
01618               
01619               if (relAppPath)
01620                      DisposePtr((Ptr) relAppPath);
01621        }
01622        
01623        return;
01624 }
01625 
01626 void
01627 DeleteXPIs(short vRefNum, long dirID)
01628 {
01629        int           compsDone = 0, i;
01630        int           instChoice = gControls->opt->instChoice - 1;
01631        OSErr         err = noErr;
01632        StringPtr     pArchiveName;
01633        FSSpec        fsCurr;
01634        
01635        // loop through 0 to kMaxComponents
01636        for(i=0; i<kMaxComponents; i++)
01637        {
01638               // general test: if component in setup type
01639               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
01640                       (compsDone < gControls->cfg->st[instChoice].numComps) )
01641               { 
01642                      // if custom and selected, or not custom setup type
01643                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
01644                               (gControls->cfg->comp[i].selected == true)) ||
01645                              (instChoice < gControls->cfg->numSetupTypes-1) )
01646                      {
01647                             HLock(gControls->cfg->comp[i].archive);
01648                             pArchiveName = CToPascal(*gControls->cfg->comp[i].archive);
01649                             HUnlock(gControls->cfg->comp[i].archive);
01650                             
01651                             err = FSMakeFSSpec(vRefNum, dirID, pArchiveName, &fsCurr);
01652                             if (err == noErr)
01653                             {
01654                                    err = FSpDelete(&fsCurr);
01655 #ifdef MIW_DEBUG
01656                                    if (err != noErr)
01657                                           SysBeep(10);
01658 #endif
01659                             }
01660                             
01661                             if (pArchiveName)
01662                                    DisposePtr((Ptr)pArchiveName);
01663                                    
01664                 compsDone++;
01665                      }
01666               }
01667         else if (compsDone >= gControls->cfg->st[instChoice].numComps)
01668             break;  
01669        }
01670 }
01671 
01672 void
01673 InitDLProgControls(Boolean onlyLabels)
01674 {
01675        Boolean       indeterminateFlag = false;
01676        Rect r;
01677        GrafPtr       oldPort;
01678        GetPort(&oldPort);    
01679        int i;
01680               
01681        if (gWPtr)
01682        {
01683            SetPort(gWPtr);
01684            
01685            if ( onlyLabels == false ) {
01686                gControls->tw->dlProgressBar = GetNewControl(rDLProgBar, gWPtr);
01687                if (gControls->tw->dlProgressBar)
01688                {
01689                    SetControlData(gControls->tw->dlProgressBar, kControlNoPart, kControlProgressBarIndeterminateTag, 
01690                        sizeof(indeterminateFlag), (Ptr) &indeterminateFlag);
01691                 Draw1Control(gControls->tw->dlProgressBar);
01692             }
01693         }
01694             // draw labels
01695         Str255 labelStr;
01696         for (i = 0; i < kNumDLFields; ++i)
01697         {
01698             gControls->tw->dlLabels[i] = GetNewControl(rLabDloading + i, gWPtr);
01699             if (gControls->tw->dlLabels[i])
01700             {
01701                 GetResourcedString(labelStr, rInstList, sLabDloading + i);
01702                 SetControlData(gControls->tw->dlLabels[i], kControlNoPart, 
01703                     kControlStaticTextTextTag, labelStr[0], (Ptr)&labelStr[1]); 
01704                 ShowControl(gControls->tw->dlLabels[i]);
01705             }
01706         }
01707         if ( onlyLabels == false ) {    
01708             TextFace(normal);
01709             TextSize(9);
01710             TextFont(applFont);
01711             for (i = 0; i < kNumDLFields; ++i)
01712             {          
01713                 SetRect(&r, (*gControls->tw->dlLabels[i])->contrlRect.right,
01714                             (*gControls->tw->dlLabels[i])->contrlRect.top + 1,
01715                             (*gControls->tw->dlLabels[i])->contrlRect.right + 310,
01716                             (*gControls->tw->dlLabels[i])->contrlRect.bottom + 1 );
01717              
01718                             
01719                 gControls->tw->dlProgressMsgs[i] = TENew(&r, &r);
01720             }
01721             TextSize(12);
01722             TextFont(systemFont);
01723            }
01724        }
01725        
01726        SetPort(oldPort);
01727 }
01728 
01729 void
01730 ClearDLProgControls(Boolean onlyLabels)
01731 {
01732     Rect teRect;
01733     GrafPtr oldPort;
01734     
01735     GetPort(&oldPort);
01736     SetPort(gWPtr);
01737         
01738     for (int i = 0; i < kNumDLFields; ++i)
01739     {
01740         if (gControls->tw->dlLabels[i])
01741             DisposeControl(gControls->tw->dlLabels[i]);
01742         if (gControls->tw->dlProgressMsgs[i] && onlyLabels == false)
01743         {
01744             HLock((Handle)gControls->tw->dlProgressMsgs[i]);
01745             teRect = (**(gControls->tw->dlProgressMsgs[i])).viewRect;
01746             HUnlock((Handle)gControls->tw->dlProgressMsgs[i]);
01747             EraseRect(&teRect);
01748                         
01749             TEDispose(gControls->tw->dlProgressMsgs[i]);
01750         }
01751     }
01752     
01753     if (gControls->tw->dlProgressBar && onlyLabels == false)
01754     {
01755         DisposeControl(gControls->tw->dlProgressBar);
01756         gControls->tw->dlProgressBar = NULL;
01757     }
01758     
01759     SetPort(oldPort);
01760 }
01761 
01762 void
01763 InitProgressBar(void)
01764 {
01765        Boolean       indeterminateFlag = true;
01766        Rect   r, r2;
01767        Str255 extractingStr;
01768        GrafPtr       oldPort;
01769        Handle rectH;
01770        OSErr reserr;
01771        
01772        GetPort(&oldPort);
01773        
01774        if (gWPtr)
01775        {
01776               SetPort(gWPtr);
01777               
01778               gControls->tw->allProgressBar = NULL;
01779               gControls->tw->allProgressBar = GetNewControl(rAllProgBar, gWPtr);
01780               
01781               gControls->tw->xpiProgressBar = NULL;
01782               gControls->tw->xpiProgressBar = GetNewControl(rPerXPIProgBar, gWPtr);
01783               
01784               if (gControls->tw->allProgressBar && gControls->tw->xpiProgressBar)
01785               {
01786                      /* init overall prog indicator */
01787                      SetControlData(gControls->tw->allProgressBar, kControlNoPart, kControlProgressBarIndeterminateTag,
01788                                                  sizeof(indeterminateFlag), (Ptr) &indeterminateFlag);
01789                      Draw1Control(gControls->tw->allProgressBar);
01790                      
01791                      /* init xpi package name display */
01792                      gControls->tw->allProgressMsg = NULL;
01793                      HLock((Handle)gControls->tw->allProgressBar);
01794                      SetRect(&r, (*gControls->tw->allProgressBar)->contrlRect.left,
01795                                           (*gControls->tw->allProgressBar)->contrlRect.top - 21,
01796                                           (*gControls->tw->allProgressBar)->contrlRect.right,
01797                                           (*gControls->tw->allProgressBar)->contrlRect.top - 5 );
01798                      HUnlock((Handle)gControls->tw->allProgressBar);
01799                      gControls->tw->allProgressMsg = TENew(&r, &r);
01800                      if (gControls->tw->allProgressMsg)
01801                      {
01802                             GetResourcedString(extractingStr, rInstList, sExtracting);
01803                             TEInsert(&extractingStr[1], extractingStr[0], gControls->tw->allProgressMsg);       
01804                      }
01805                      
01806                      /* init per xpi prog indicator */
01807                      SetControlData(gControls->tw->xpiProgressBar, kControlNoPart, kControlProgressBarIndeterminateTag,
01808                                                  sizeof(indeterminateFlag), (Ptr) &indeterminateFlag);
01809                      HideControl(gControls->tw->xpiProgressBar);
01810                      
01811                      
01812                      TextFace(normal);
01813                      TextSize(9);
01814                      TextFont(applFont);  
01815                      
01816                      gControls->tw->xpiProgressMsg = NULL;     /* used by XPInstall progress callback */
01817                      HLock((Handle)gControls->tw->xpiProgressBar);
01818                      SetRect(&r, (*gControls->tw->xpiProgressBar)->contrlRect.left,
01819                                           (*gControls->tw->xpiProgressBar)->contrlRect.top - 21,
01820                                           (*gControls->tw->xpiProgressBar)->contrlRect.right,
01821                                           (*gControls->tw->xpiProgressBar)->contrlRect.top - 5 );
01822                      HUnlock((Handle)gControls->tw->xpiProgressBar);
01823                      gControls->tw->xpiProgressMsg = TENew(&r, &r);
01824                      
01825                      TextFont(systemFont);       /* restore systemFont */
01826                      TextSize(12);
01827               }
01828        }
01829        
01830     rectH = GetResource('RECT', 165);
01831        reserr = ResError();
01832        if (reserr == noErr && rectH)
01833        {
01834            HLock(rectH);
01835               r = (Rect) **((Rect**)rectH);
01836               SetRect(&r2, r.left, r.top, r.right, r.bottom);
01837               HUnlock(rectH);
01838               reserr = ResError();
01839               if (reserr == noErr)
01840               {
01841                   EraseRect(&r2);
01842               }
01843        }
01844 
01845        SetPort(oldPort);
01846 }
01847 
01848 /* replace a substring "srch" (first found), with a new string "repl" */
01849 void strtran(char* str, const char* srch, const char* repl) 
01850 {
01851     int lsrch=strlen(srch);
01852     char *p;
01853     char tmp[kKeyMaxLen];
01854 
01855        p = strstr(str, srch);
01856        if( p == nil )
01857               return;
01858        strcpy(tmp, p);
01859        *p = '\0';
01860        strcat(str, repl);
01861        p = tmp;
01862        p = p + lsrch;
01863        strcat(str, p);
01864        
01865 }
01866 
01867 /* 
01868  * Name: VerifyArchive
01869  *
01870  * Arguments: 
01871  *
01872  * char *szArchive;     -- path of archive to verify
01873  *
01874  * Description:
01875  *
01876  * This function verifies that the specified path exists, that it is a XPI file, and
01877  * that it has a valid checksum.
01878  *
01879  * Return Value: If all tests pass, ZIP_OK. Otherwise, !ZIP_OK
01880  *
01881  * Original Code: Syd Logan (syd@netscape.com) 6/25/2001
01882  *
01883 */
01884 
01885 int 
01886 VerifyArchive(char *szArchive)
01887 {
01888   void *vZip;
01889   int  iTestRv;
01890   OSErr err;
01891   FSSpec spec;
01892 
01893   err = FSpLocationFromFullPath( strlen( szArchive ), szArchive, &spec );
01894                                                                
01895   /* Check for the existance of the from (source) file */
01896   if(err != noErr)
01897     return(!ZIP_OK);
01898 
01899   
01900   if((iTestRv = ZIP_OpenArchive(szArchive, &vZip)) == ZIP_OK)
01901   {
01902     BreathFunc();
01903     /* 1st parameter should be NULL or it will fail */
01904     /* It indicates extract the entire archive */
01905     iTestRv = ZIP_TestArchive(vZip);
01906     ZIP_CloseArchive(&vZip);
01907   } 
01908   if ( iTestRv != ZIP_OK )
01909     err = FSpDelete( &spec );      // nuke it
01910   return(iTestRv);
01911 }
01912 
01913 /* 
01914  * Name: CRCCheckDownloadedArchives
01915  *
01916  * Arguments: 
01917  *
01918  * Handle dlPath;     -- a handle to the location of the XPI files on disk
01919  * short dlPathlen;    -- length, in bytes, of dlPath
01920  *
01921  * Description:
01922  *
01923  * This function iterates the XPI files and calls VerifyArchive() on each to determine
01924  * which archives pass checksum checks. If a file passes, its dirty flag is set to false,
01925  * so that it is not re-read the next time we dload archives if any of the files come up
01926  * with an invalid CRC. 
01927  *
01928  * Return Value: if all archives pass, true. Otherwise, false.
01929  *
01930  * Original Code: Syd Logan (syd@netscape.com) 6/24/2001
01931  *
01932 */
01933 
01934 Boolean 
01935 CRCCheckDownloadedArchives(Handle dlPath, short dlPathlen, int count)
01936 {
01937     int i, len;
01938     Rect teRect;
01939     Boolean isClean;
01940     char buf[ 1024 ];
01941     char validatingBuf[ 128 ];
01942     Boolean indeterminateFlag = true;
01943        Str255 validatingStr;
01944        int compsDone = 0, instChoice = gControls->opt->instChoice-1;
01945 
01946     isClean = true;
01947 
01948     ClearDLProgControls(true); 
01949     DisablePauseAndResume();      
01950         
01951     for ( i = 1; i < kNumDLFields; i++ ) {
01952         HLock( (Handle) gControls->tw->dlProgressMsgs[i] );
01953         teRect = (**(gControls->tw->dlProgressMsgs[i])).viewRect;
01954         EraseRect(&teRect);
01955         HUnlock( (Handle) gControls->tw->dlProgressMsgs[i] );
01956     }
01957     if ( gControls->tw->dlProgressBar) {
01958         SetControlValue(gControls->tw->dlProgressBar, 0);
01959         SetControlMaximum(gControls->tw->dlProgressBar, count);
01960     } 
01961 
01962     GetResourcedString(validatingStr, rInstList, sValidating);
01963     strncpy( validatingBuf, (const char *) &validatingStr[1], (unsigned char) validatingStr[0] ); 
01964        for(i = 0; i < kMaxComponents; i++) {
01965            BreathFunc();
01966               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
01967                       (compsDone < gControls->cfg->st[instChoice].numComps) && 
01968                       gControls->cfg->comp[i].dirty == true)
01969               { 
01970                      // if custom and selected -or- not custom setup type
01971                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
01972                               (gControls->cfg->comp[i].selected == true)) ||
01973                              (instChoice < gControls->cfg->numSetupTypes-1) ) {
01974                 if (gControls->cfg->comp[i].shortDesc)
01975                 {
01976                     HLock(gControls->cfg->comp[i].shortDesc);
01977                     if (*(gControls->cfg->comp[i].shortDesc) && gControls->tw->dlProgressMsgs[0])
01978                     {
01979                         HLock((Handle)gControls->tw->dlProgressMsgs[0]);
01980                         teRect = (**(gControls->tw->dlProgressMsgs[0])).viewRect;
01981                         HUnlock((Handle)gControls->tw->dlProgressMsgs[0]);                
01982                         sprintf( buf, validatingBuf, *(gControls->cfg->comp[i].shortDesc));
01983                         len = strlen( buf );
01984                         TESetText(buf, len, 
01985                             gControls->tw->dlProgressMsgs[0]);
01986                         TEUpdate(&teRect, gControls->tw->dlProgressMsgs[0]);
01987                     }
01988                     HUnlock(gControls->cfg->comp[sCurrComp].shortDesc);
01989                 }
01990                    if ( gControls->cfg->comp[i].dirty == true ) {
01991                        HLock(dlPath);
01992                     HLock(gControls->cfg->comp[i].archive);
01993                     strncpy( buf, *dlPath, dlPathlen );
01994                     buf[ dlPathlen ] = '\0';
01995                     strcat( buf, *(gControls->cfg->comp[i].archive) );
01996                        HUnlock(dlPath);
01997                     HUnlock(gControls->cfg->comp[i].archive);
01998                     if (IsArchiveFile(buf) == false || VerifyArchive( buf ) == ZIP_OK) 
01999                         gControls->cfg->comp[i].dirty = false;
02000                     else
02001                         isClean = false;
02002                 }
02003                 if ( gControls->tw->dlProgressBar) {
02004                     SetControlValue(gControls->tw->dlProgressBar, 
02005                         GetControlValue(gControls->tw->dlProgressBar) + 1);
02006                 }  
02007             }
02008         }  
02009     }
02010     
02011     InitDLProgControls( true );
02012     return isClean;
02013 }
02014 
02015 /* 
02016  * Name: IsArchiveFile( char *path )
02017  * 
02018  * Arguments:
02019  * 
02020  * char *path -- NULL terminated pathname 
02021  *
02022  * Description: 
02023  *  
02024  * This function extracts the file extension of filename pointed to by path and then 
02025  * checks it against a table of extensions. If a match occurs, the file is considered
02026  * to be an archive file that has a checksum we can validate, and we return PR_TRUE.
02027  * Otherwise, PR_FALSE is returned.
02028  *
02029  * Return Value: true if the file extension matches one of those we are looking for,
02030  * and false otherwise.
02031  *
02032  * Original Code: Syd Logan 7/28/2001
02033  *
02034 */
02035 
02036 static char *extensions[] = { "ZIP", "XPI", "JAR" };  // must be uppercase
02037 
02038 Boolean
02039 IsArchiveFile( char *buf ) 
02040 {
02041     PRBool ret = false;
02042     char lbuf[1024];
02043     char *p;
02044     int i, max;
02045     
02046     // if we have a string and it contains a '.'
02047     
02048     if ( buf != (char *) NULL && ( p = strrchr( buf, '.' ) ) != (char *) NULL ) {
02049         p++;
02050         
02051         // if there are characters after the '.' then see if there is a match
02052         
02053         if ( *p != '\0' ) {
02054             
02055             // make a copy of the extension, and fold to uppercase, since mac has no strcasecmp
02056             // and we need to ensure we are comparing strings of chars that have the same case. 
02057 
02058             strcpy( lbuf, p );
02059             for ( i = 0; i < strlen( lbuf ); i++ )
02060               lbuf[i] = toupper(lbuf[i]);
02061             
02062             // search
02063               
02064             max = sizeof( extensions ) / sizeof ( char * );
02065             for ( i = 0; i < max; i++ ) 
02066                 if ( !strcmp( lbuf, extensions[i] ) ) {
02067                     ret = true;
02068                     break;
02069                 }
02070         }   
02071     }
02072     return ( ret );
02073 }