From 255b5688c784152000efaefdcdfae9c70c641065 Mon Sep 17 00:00:00 2001 From: "syd%netscape.com" Date: Sat, 18 Aug 2001 01:15:59 +0000 Subject: [PATCH] Fix for 65672. Add CRC checking and single connection ftp to install. r=dveditz, sr=mscott git-svn-id: svn://10.0.0.236/trunk@101388 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpinstall/wizard/unix/src2/XIErrors.h | 3 +- .../xpinstall/wizard/unix/src2/installer.ini | 2 + .../wizard/unix/src2/nsComponent.cpp | 4 +- .../xpinstall/wizard/unix/src2/nsComponent.h | 2 +- .../wizard/unix/src2/nsInstallDlg.cpp | 254 ++++++++++----- .../xpinstall/wizard/unix/src2/nsInstallDlg.h | 11 +- .../wizard/unix/src2/nsXIContext.cpp | 2 + .../xpinstall/wizard/unix/src2/nsXIEngine.cpp | 303 ++++++++++++++++-- .../xpinstall/wizard/unix/src2/nsXIEngine.h | 21 +- 9 files changed, 501 insertions(+), 101 deletions(-) diff --git a/mozilla/xpinstall/wizard/unix/src2/XIErrors.h b/mozilla/xpinstall/wizard/unix/src2/XIErrors.h index b5cad0cd53e..a9d7e8f5f70 100644 --- a/mozilla/xpinstall/wizard/unix/src2/XIErrors.h +++ b/mozilla/xpinstall/wizard/unix/src2/XIErrors.h @@ -64,7 +64,8 @@ E_MKDIR_FAIL = -624, /* can't make destination dir */ E_OLD_INST = -625, /* old instllation exists */ E_NO_PERMS = -626, /* don't have rwx perms on selected dir */ - E_NO_DISK_SPACE = -627 /* not eough disk space to install */ + E_NO_DISK_SPACE = -627, /* not eough disk space to install */ + E_CRC_FAILED = -628 /* CRC failed */ }; #endif /* _XI_ERRORS_H_ */ diff --git a/mozilla/xpinstall/wizard/unix/src2/installer.ini b/mozilla/xpinstall/wizard/unix/src2/installer.ini index 985a9980af9..d58eb446d2c 100644 --- a/mozilla/xpinstall/wizard/unix/src2/installer.ini +++ b/mozilla/xpinstall/wizard/unix/src2/installer.ini @@ -44,6 +44,8 @@ DS_AVAIL=Disk Space Available = %ld KB DS_REQD=Disk Space Required = %ld KB NO_DISK_SPACE=Please select a directory on a disk with enough space to install or free some disk space on the selected disk. CXN_DROPPED=A network connection failure occured. Please check your network connection and press the 'Resume' button. Alternatively, press the 'Cancel' button to quit the installer. +CRC_CHECK=Some files failed to download correctly. Retrying. +CRC_FAILED=Installation has failed due to multiple CRC failures. DOWNLOADING=Downloading: FROM=From: TO=To: diff --git a/mozilla/xpinstall/wizard/unix/src2/nsComponent.cpp b/mozilla/xpinstall/wizard/unix/src2/nsComponent.cpp index 9a45021dc44..11e36ce458f 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsComponent.cpp +++ b/mozilla/xpinstall/wizard/unix/src2/nsComponent.cpp @@ -470,9 +470,9 @@ nsComponent::GetResumePos() } int -nsComponent::SetDownloaded() +nsComponent::SetDownloaded( int which ) { - mDownloaded = TRUE; + mDownloaded = which; return OK; } diff --git a/mozilla/xpinstall/wizard/unix/src2/nsComponent.h b/mozilla/xpinstall/wizard/unix/src2/nsComponent.h index 980b194ac59..3e6f6b8e041 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsComponent.h +++ b/mozilla/xpinstall/wizard/unix/src2/nsComponent.h @@ -84,7 +84,7 @@ public: int DepGetRefCount(); int SetResumePos(int aResPos); int GetResumePos(); - int SetDownloaded(); + int SetDownloaded(int which); int IsDownloaded(); /*---------------------------------------------------------------* diff --git a/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.cpp b/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.cpp index 4e96ee1ac0c..e81b91ee76b 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.cpp +++ b/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.cpp @@ -136,7 +136,7 @@ nsInstallDlg::Next(GtkWidget *aWidget, gpointer aData) if (bDownload) { - InitDLProgress(); + InitDLProgress( TRUE ); pauseLabel = gtk_label_new(gCtx->Res("PAUSE")); resumeLabel = gtk_label_new(gCtx->Res("RESUME")); @@ -180,7 +180,7 @@ nsInstallDlg::Next(GtkWidget *aWidget, gpointer aData) XI_GTK_UPDATE_UI(); bInstallClicked = TRUE; - WorkDammitWork(); + PerformInstall(); if (bDLCancel) // set only when download was cancelled { // mode auto has no call to gtk_main() @@ -523,9 +523,9 @@ nsInstallDlg::GetMsg0() } int -nsInstallDlg::WorkDammitWork() +nsInstallDlg::PerformInstall() { - DUMP("WorkDammitWork"); + DUMP("PerformInstall"); int err = OK; @@ -558,6 +558,11 @@ nsInstallDlg::WorkDammitWork() ShowCxnDroppedDlg(); return err; } + else if (err == E_CRC_FAILED) + { + ShowCRCFailedDlg(); + goto BAIL; + } else if (err == E_DL_PAUSE || err == E_DL_CANCEL) { DUMP("Pause or Cancel pressed"); @@ -1090,7 +1095,7 @@ nsInstallDlg::DLResume(GtkWidget *aWidget, gpointer aData) // enable pause button gtk_widget_set_sensitive(gCtx->back, TRUE); - WorkDammitWork(); + PerformInstall(); return; } @@ -1137,6 +1142,73 @@ nsInstallDlg::CancelOrPause() return err; } +static GtkWidget *crcDlg = (GtkWidget *) NULL; + +void +nsInstallDlg::ShowCRCDlg() +{ + GtkWidget *label, *okButton, *packer; + + if ( crcDlg == (GtkWidget *) NULL ) { + // throw up dialog informing user to press resume + // or to cancel out + crcDlg = gtk_dialog_new(); + label = gtk_label_new(gCtx->Res("CRC_CHECK")); + okButton = gtk_button_new_with_label(gCtx->Res("OK_LABEL")); + packer = gtk_packer_new(); + + if (crcDlg && label && okButton && packer) + { + gtk_packer_set_default_border_width(GTK_PACKER(packer), 20); + gtk_packer_add_defaults(GTK_PACKER(packer), label, GTK_SIDE_BOTTOM, + GTK_ANCHOR_CENTER, GTK_FILL_X); + gtk_window_set_title(GTK_WINDOW(crcDlg), gCtx->opt->mTitle); + gtk_window_set_position(GTK_WINDOW(crcDlg), GTK_WIN_POS_CENTER); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(crcDlg)->vbox), + packer); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(crcDlg)->action_area), + okButton); + gtk_signal_connect(GTK_OBJECT(okButton), "clicked", + GTK_SIGNAL_FUNC(CRCOKCb), crcDlg); + gtk_widget_show_all(crcDlg); + } + } + XI_GTK_UPDATE_UI(); +} + +int +nsInstallDlg::ShowCRCFailedDlg() +{ + GtkWidget *crcFailedDlg, *label, *okButton, *packer; + + // throw up dialog informing user to press resume + // or to cancel out + crcFailedDlg = gtk_dialog_new(); + label = gtk_label_new(gCtx->Res("CRC_FAILED")); + okButton = gtk_button_new_with_label(gCtx->Res("OK_LABEL")); + packer = gtk_packer_new(); + + if (crcFailedDlg && label && okButton && packer) + { + gtk_packer_set_default_border_width(GTK_PACKER(packer), 20); + gtk_packer_add_defaults(GTK_PACKER(packer), label, GTK_SIDE_BOTTOM, + GTK_ANCHOR_CENTER, GTK_FILL_X); + gtk_window_set_modal(GTK_WINDOW(crcFailedDlg), TRUE); + gtk_window_set_title(GTK_WINDOW(crcFailedDlg), gCtx->opt->mTitle); + gtk_window_set_position(GTK_WINDOW(crcFailedDlg), GTK_WIN_POS_CENTER); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(crcFailedDlg)->vbox), + packer); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(crcFailedDlg)->action_area), + okButton); + gtk_signal_connect(GTK_OBJECT(okButton), "clicked", + GTK_SIGNAL_FUNC(CRCFailedOK), crcFailedDlg); + gtk_widget_show_all(crcFailedDlg); + } + XI_GTK_UPDATE_UI(); + + return OK; +} + int nsInstallDlg::ShowCxnDroppedDlg() { @@ -1170,6 +1242,29 @@ nsInstallDlg::ShowCxnDroppedDlg() return OK; } +void +nsInstallDlg::CRCFailedOK(GtkWidget *aWidget, gpointer aData) +{ + gtk_main_quit(); + return; +} + +void +nsInstallDlg::DestroyCRCDlg() +{ + CRCOKCb( (GtkWidget *) NULL, (gpointer) NULL ); +} + +void +nsInstallDlg::CRCOKCb(GtkWidget *aWidget, gpointer aData) +{ + if (crcDlg != (GtkWidget *) NULL) + gtk_widget_destroy(crcDlg); + crcDlg = (GtkWidget *) NULL; + + return; +} + void nsInstallDlg::CxnDroppedOK(GtkWidget *aWidget, gpointer aData) { @@ -1194,7 +1289,7 @@ nsInstallDlg::HideNavButtons() } void -nsInstallDlg::InitDLProgress() +nsInstallDlg::InitDLProgress( int isFirst ) { GtkWidget *titles[4]; GtkWidget *hbox; @@ -1202,73 +1297,84 @@ nsInstallDlg::InitDLProgress() gCtx->idlg->HideTable(); - sDLProgress.vbox = gtk_vbox_new(FALSE, 10); - gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), - sDLProgress.vbox, NULL); - gtk_widget_show(sDLProgress.vbox); - - table = gtk_table_new(5, 2, FALSE); - gtk_box_pack_start(GTK_BOX(sDLProgress.vbox), table, FALSE, - FALSE, 0); - gtk_widget_show(table); + if ( isFirst == TRUE ) { + sDLProgress.vbox = gtk_vbox_new(FALSE, 10); + gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), + sDLProgress.vbox, NULL); + gtk_widget_show(sDLProgress.vbox); + + table = gtk_table_new(5, 2, FALSE); + gtk_box_pack_start(GTK_BOX(sDLProgress.vbox), table, FALSE, + FALSE, 0); + gtk_widget_show(table); - // setup static title progress labels in table left column - titles[0] = gtk_label_new(gCtx->Res("DOWNLOADING")); - titles[1] = gtk_label_new(gCtx->Res("FROM")); - titles[2] = gtk_label_new(gCtx->Res("TO")); - titles[3] = gtk_label_new(gCtx->Res("STATUS")); + // setup static title progress labels in table left column + titles[0] = gtk_label_new(gCtx->Res("DOWNLOADING")); + titles[1] = gtk_label_new(gCtx->Res("FROM")); + titles[2] = gtk_label_new(gCtx->Res("TO")); + titles[3] = gtk_label_new(gCtx->Res("STATUS")); - // setup dynamic progress labels in right column - sDLProgress.compName = gtk_label_new(gCtx->Res("UNKNOWN")); - sDLProgress.URL = gtk_label_new(gCtx->Res("UNKNOWN")); - sDLProgress.localPath = gtk_label_new(gCtx->Res("UNKNOWN")); - sDLProgress.status = gtk_label_new(gCtx->Res("UNKNOWN")); + // setup dynamic progress labels in right column + sDLProgress.compName = gtk_label_new(gCtx->Res("UNKNOWN")); + sDLProgress.URL = gtk_label_new(gCtx->Res("UNKNOWN")); + sDLProgress.localPath = gtk_label_new(gCtx->Res("UNKNOWN")); + sDLProgress.status = gtk_label_new(gCtx->Res("UNKNOWN")); - // pack and show titles - for (int i = 0; i < 4; ++i) - { - hbox = gtk_hbox_new(FALSE, 10); - gtk_box_pack_end(GTK_BOX(hbox), titles[i], FALSE, FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox, - 0, 1, i, i + 1, GTK_FILL, GTK_FILL, 5, 5); - gtk_widget_show(titles[i]); - gtk_widget_show(hbox); + // pack and show titles + for (int i = 0; i < 4; ++i) + { + hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_end(GTK_BOX(hbox), titles[i], FALSE, FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, + 0, 1, i, i + 1, GTK_FILL, GTK_FILL, 5, 5); + gtk_widget_show(titles[i]); + gtk_widget_show(hbox); + } + + // pack and show dynamic labels + hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.compName, FALSE, FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, + GTK_FILL, GTK_FILL, 5, 5); + gtk_widget_show(sDLProgress.compName); + gtk_widget_show(hbox); + + hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.URL, FALSE, FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2, + GTK_FILL, GTK_FILL, 5, 5); + gtk_widget_show(sDLProgress.URL); + gtk_widget_show(hbox); + + hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.localPath, FALSE, + FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3, + GTK_FILL, GTK_FILL, 5, 5); + gtk_widget_show(sDLProgress.localPath); + gtk_widget_show(hbox); + + hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.status, FALSE, + FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 3, 4, + GTK_FILL, GTK_FILL, 5, 5); + gtk_widget_show(sDLProgress.status); + gtk_widget_show(hbox); + + // init and show prog bar + sDLProgress.progBar = gtk_progress_bar_new(); + + // show prog bar + hbox = gtk_hbox_new(TRUE, 10); + gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.progBar, FALSE, + TRUE, 0); + gtk_box_pack_start(GTK_BOX(sDLProgress.vbox), hbox, FALSE, + FALSE, 0); + gtk_widget_show(sDLProgress.progBar); + gtk_widget_show(hbox); } - // pack and show dynamic labels - hbox = gtk_hbox_new(FALSE, 10); - gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.compName, FALSE, FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, - GTK_FILL, GTK_FILL, 5, 5); - gtk_widget_show(sDLProgress.compName); - gtk_widget_show(hbox); - - hbox = gtk_hbox_new(FALSE, 10); - gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.URL, FALSE, FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2, - GTK_FILL, GTK_FILL, 5, 5); - gtk_widget_show(sDLProgress.URL); - gtk_widget_show(hbox); - - hbox = gtk_hbox_new(FALSE, 10); - gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.localPath, FALSE, - FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3, - GTK_FILL, GTK_FILL, 5, 5); - gtk_widget_show(sDLProgress.localPath); - gtk_widget_show(hbox); - - hbox = gtk_hbox_new(FALSE, 10); - gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.status, FALSE, - FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 3, 4, - GTK_FILL, GTK_FILL, 5, 5); - gtk_widget_show(sDLProgress.status); - gtk_widget_show(hbox); - - // init and show prog bar - sDLProgress.progBar = gtk_progress_bar_new(); - // set to non-activity mode and initialize gtk_progress_set_activity_mode(GTK_PROGRESS(sDLProgress.progBar), FALSE); gtk_progress_bar_update(GTK_PROGRESS_BAR(sDLProgress.progBar), (gfloat) 0); @@ -1277,13 +1383,6 @@ nsInstallDlg::InitDLProgress() sDLProgress.downloadedBytes = 0; sDLProgress.totalKB = TotalDLSize(); - // show prog bar - hbox = gtk_hbox_new(TRUE, 10); - gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.progBar, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(sDLProgress.vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show(sDLProgress.progBar); - gtk_widget_show(hbox); - XI_GTK_UPDATE_UI(); } @@ -1354,3 +1453,8 @@ nsInstallDlg::CompressToFit(char *aOrigStr, char *aOutStr, int aOutStrLen) *(aOutStr + aOutStrLen + 1) = 0; } +void +nsInstallDlg::ReInitUI( void ) +{ + InitDLProgress( FALSE ); +} diff --git a/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.h b/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.h index 6a38839050c..da9b632adc3 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.h +++ b/mozilla/xpinstall/wizard/unix/src2/nsInstallDlg.h @@ -59,6 +59,10 @@ public: static void ClearRateLabel(); static int CancelOrPause(); + void ReInitUI(); + void ShowCRCDlg(); + void DestroyCRCDlg(); + enum { ACT_DOWNLOAD, @@ -80,7 +84,7 @@ public: char *GetMsg0(); private: - static int WorkDammitWork(void); // install start + static int PerformInstall(void); // install start static void SaveModulesToggled(GtkWidget *aWidget, gpointer aData); static void ShowProxySettings(GtkWidget *aWidget, gpointer aData); static void PSDlgOK (GtkWidget *aWidget, gpointer aData); @@ -93,14 +97,17 @@ private: static void DLPause(GtkWidget *aWidget, gpointer aData); static void DLResume(GtkWidget *aWidget, gpointer aData); static void DLCancel(GtkWidget *aWidget, gpointer aData); + static int ShowCRCFailedDlg(); static int ShowCxnDroppedDlg(); + static void CRCFailedOK(GtkWidget *aWidget, gpointer aData); static void CxnDroppedOK(GtkWidget *aWidget, gpointer aData); + static void CRCOKCb(GtkWidget *aWidget, gpointer aData); static void HideNavButtons(); - static void InitDLProgress(); static void InitInstallProgress(); static int TotalDLSize(); static void CompressToFit(char *aOrigStr, char *aOutStr, int aOutStrLen); + static void InitDLProgress(int IsFirst); char *mMsg0; }; diff --git a/mozilla/xpinstall/wizard/unix/src2/nsXIContext.cpp b/mozilla/xpinstall/wizard/unix/src2/nsXIContext.cpp index 8f38a959ec1..e050697a2c8 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsXIContext.cpp +++ b/mozilla/xpinstall/wizard/unix/src2/nsXIContext.cpp @@ -187,6 +187,8 @@ nsXIContext::LoadResources() "TO", "STATUS", "DL_STATUS_STR", + "CRC_FAILED", + "CRC_CHECK", "UNKNOWN", __EOT__ diff --git a/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.cpp b/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.cpp index 815f98648c2..0106249bf23 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.cpp +++ b/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.cpp @@ -20,6 +20,7 @@ * * Contributor(s): * Samir Gehani + * Syd Logan syd@netscape.com */ #include "nsFTPConn.h" @@ -27,6 +28,7 @@ #include "nsXIEngine.h" #include +#include #define CORE_LIB_COUNT 11 @@ -58,6 +60,8 @@ EventPumpCB(void) return 0; } +#define MAXCRC 4 + int nsXIEngine::Download(int aCustom, nsComponentList *aComps) { @@ -68,6 +72,7 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) int err = OK; nsComponent *currComp = aComps->GetHead(), *markedComp = NULL; + nsComponent *currCompSave; char *currURL = NULL; char *currHost = NULL; char *currPath = NULL; @@ -75,13 +80,14 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) char *srvPath = NULL; char *proxyURL = NULL; char *qualURL = NULL; - int i; + int i, crcPass, bDone; int currPort; struct stat stbuf; int resPos = 0; int fileSize = 0; int currCompNum = 1, markedCompNum = 0; int numToDL = 0; // num xpis to download + CONN myConn; err = GetDLMarkedComp(aComps, aCustom, &markedComp, &markedCompNum); if (err == OK && markedComp) @@ -108,8 +114,15 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) numToDL = TotalToDownload(aCustom, aComps); - while (currComp) - { + myConn.URL = (char *) NULL; + myConn.type = TYPE_UNDEF; + + crcPass = 0; + currCompSave = currComp; + bDone = 0; + while ( bDone == 0 && crcPass < MAXCRC ) { + while (currComp) + { if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) ) { // in case we are resuming inter- or intra-installer session @@ -219,6 +232,8 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) // or is this an FTP URL? else if (strncmp(currURL, kFTPProto, strlen(kFTPProto)) == 0) { + PRBool isNewConn; + err = nsHTTPConn::ParseURL(kFTPProto, currURL, &currHost, &currPort, &currPath); if (err != nsHTTPConn::OK) @@ -234,27 +249,40 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) } sprintf(srvPath, "%s%s", currPath, currComp->GetArchive()); - nsFTPConn *conn = new nsFTPConn(currHost, EventPumpCB); - if (!conn) - { + // closes the old connection if any + + isNewConn = CheckConn( currHost, TYPE_FTP, &myConn, PR_FALSE ); + + err = nsFTPConn::OK; + + nsFTPConn *conn; + if ( isNewConn == PR_TRUE ) { + conn = new nsFTPConn(currHost, EventPumpCB); + if (!conn) { err = E_MEM; break; - } - - err = conn->Open(); - if (err == nsFTPConn::OK) + } + err = conn->Open(); + myConn.conn = (void *) conn; + myConn.type = TYPE_FTP; + myConn.URL = (char *) calloc(strlen(currHost) + 1, sizeof(char)); + if ( myConn.URL != (char *) NULL ) + strcpy( myConn.URL, currHost ); + } else + conn = (nsFTPConn *) myConn.conn; + + if (isNewConn == PR_FALSE || err == nsFTPConn::OK) { sprintf(localPath, "%s/%s", XPI_DIR, currComp->GetArchive()); err = conn->Get(srvPath, localPath, nsFTPConn::BINARY, resPos, 1, nsInstallDlg::DownloadCB); - conn->Close(); +// conn->Close(); } XI_IF_FREE(currHost); XI_IF_FREE(currPath); XI_IF_FREE(srvPath); - XI_IF_DELETE(conn); } // else error: malformed URL @@ -299,7 +327,7 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) if (err == OK) { - currComp->SetDownloaded(); + currComp->SetDownloaded(TRUE); currCompNum++; break; // no need to failover } @@ -307,11 +335,95 @@ nsXIEngine::Download(int aCustom, nsComponentList *aComps) } currComp = currComp->GetNext(); + } + + CheckConn( "", TYPE_UNDEF, &myConn, true ); + + bDone = CRCCheckDownloadedArchives(XPI_DIR, strlen(XPI_DIR), currCompSave, currCompNum); + crcPass++; + if ( bDone == 0 && crcPass < MAXCRC ) { + // reset ourselves + if (markedComp) { + currComp = markedComp; + currCompNum = markedCompNum; + } else { + currComp = aComps->GetHead(); + currCompNum = 1; + } + currCompSave = currComp; + gCtx->idlg->ReInitUI(); + gCtx->idlg->ShowCRCDlg(); + numToDL = TotalToDownload(aCustom, aComps); + } } - - // download complete: remove marker - DelDLMarker(); - return OK; + gCtx->idlg->DestroyCRCDlg(); // destroy the CRC dialog if showing + if ( crcPass < MAXCRC ) { + // download complete: remove marker + DelDLMarker(); + return OK; + } else { + return E_CRC_FAILED; + } +} + +/* + * Name: CheckConn + * + * Arguments: + * + * char *URL; -- URL of connection we need to have established + * int type; -- connection type (TYPE_HTTP, etc.) + * CONN *myConn; -- connection state (info about currently established + * connection) + * PRBool force; -- force closing of connection + * + * Description: + * + * This function determines if the caller should open a connection based upon + * the current connection that is open (if any), and the type of connection + * desired. If no previous connection was established, the function returns + * true. If the connection is for a different protocol, then true is also + * returned (and the previous connection is closed). If the connection is for + * the same protocol and the URL is different, the previous connection is + * closed and true is returned. Otherwise, the connection has already been + * established, and false is returned. + * + * Return Value: If a new connection needs to be opened, true. Otherwise, + * false is returned. + * + * Original Code: Syd Logan (syd@netscape.com) 6/24/2001 + * +*/ + +PRBool +nsXIEngine::CheckConn( char *URL, int type, CONN *myConn, PRBool force ) +{ + nsFTPConn *fconn; + nsHTTPConn *hconn; + PRBool retval = false; + + if ( myConn->type == TYPE_UNDEF ) + retval = PR_TRUE; // first time + else if ( ( myConn->type != type || strcmp( URL, myConn->URL ) || force == PR_TRUE ) /* && gControls->state != ePaused */) { + retval = PR_TRUE; + switch ( myConn->type ) { + case TYPE_HTTP: + case TYPE_PROXY: + hconn = (nsHTTPConn *) myConn->conn; + hconn->Close(); + break; + case TYPE_FTP: + fconn = (nsFTPConn *) myConn->conn; + fconn->Close(); + XI_IF_DELETE(fconn); + break; + } + } + + if ( retval == PR_TRUE && myConn->URL != (char *) NULL ) + free( myConn->URL ); + + return retval; } int @@ -395,10 +507,9 @@ nsXIEngine::Install(int aCustom, nsComponentList *aComps, char *aDestination) currComp = currComp->GetNext(); } + UnloadXPIStub(&stub); } - UnloadXPIStub(&stub); - // restore LD_LIBRARY_PATH settings #ifdef SOLARIS char old_LD_env[MAXPATHLEN]; @@ -860,3 +971,157 @@ nsXIEngine::TotalToDownload(int aCustom, nsComponentList *aComps) return total; } + +/* + * Name: CRCCheckDownloadedArchives + * + * Arguments: + * + * Handle dlPath; -- a handle to the location of the XPI files on disk + * short dlPathlen; -- length, in bytes, of dlPath + * + * Description: + * + * This function iterates the XPI files and calls VerifyArchive() on each to + * determine which archives pass checksum checks. + * + * Return Value: if all archives pass, true. Otherwise, false. + * + * Original Code: Syd Logan (syd@netscape.com) 6/24/2001 + * +*/ + +PRBool +nsXIEngine::CRCCheckDownloadedArchives(char *dlPath, short dlPathlen, + nsComponent *currComp, int count) +{ + int i; + PRBool isClean; + char buf[ 1024 ]; + + isClean = PR_TRUE; + + for(i = 0; currComp != (nsComponent *) NULL && i < MAX_COMPONENTS; i++) { + strncpy( buf, (const char *) dlPath, dlPathlen ); + buf[ dlPathlen ] = '\0'; + strcat( buf, "/" ); + strcat( buf, currComp->GetArchive() ); + nsInstallDlg::MajorProgressCB(buf, i, count, nsInstallDlg::ACT_INSTALL); + if (IsArchiveFile(buf) == PR_TRUE && VerifyArchive( buf ) != ZIP_OK) { + currComp->SetDownloaded(FALSE); // VerifyArchive has unlinked it + isClean = false; + } + currComp = currComp->GetNext(); + } + return isClean; +} + +/* + * Name: IsArchiveFile( char *path ) + * + * Arguments: + * + * char *path -- NULL terminated pathname + * + * Description: + * + * This function extracts the file extension of filename pointed to by path + * and then checks it against a table of extensions. If a match occurs, the + * file is considered to be an archive file that has a checksum we can + * validate, and we return PR_TRUE. + * Otherwise, PR_FALSE is returned. + * + * Return Value: true if the file extension matches one of those we are + * looking for, and false otherwise. + * + * Original Code: Syd Logan 7/28/2001 + * +*/ + +static char *extensions[] = { "ZIP", "XPI", "JAR" }; // must be uppercase + +PRBool +nsXIEngine::IsArchiveFile( char *buf ) +{ + PRBool ret = false; + char lbuf[1024]; + char *p; + int i, max; + + // if we have a string and it contains a '.' + + if ( buf != (char *) NULL && ( p = strrchr( buf, '.' ) ) != (char *) NULL ) { + p++; + + // if there are characters after the '.' then see if there is a match + + if ( *p != '\0' ) { + + // make a copy of the extension, and fold to uppercase, since mac has no strcasecmp + // and we need to ensure we are comparing strings of chars that have the same case. + + strcpy( lbuf, p ); + for ( i = 0; i < (int) strlen( lbuf ); i++ ) + lbuf[i] = toupper(lbuf[i]); + + // search + + max = sizeof( extensions ) / sizeof ( char * ); + for ( i = 0; i < max; i++ ) + if ( !strcmp( lbuf, extensions[i] ) ) { + ret = true; + break; + } + } + } + return ( ret ); +} + +/* + * Name: VerifyArchive + * + * Arguments: + * + * char *szArchive; -- path of archive to verify + * + * Description: + * + * This function verifies that the specified path exists, that it is a XPI + * file, and that it has a valid checksum. + * + * Return Value: If all tests pass, ZIP_OK. Otherwise, !ZIP_OK + * + * Original Code: Syd Logan (syd@netscape.com) 6/25/2001 + * +*/ + +int +nsXIEngine::VerifyArchive(char *szArchive) +{ + void *vZip; + int iTestRv; + char *penv; + + if((iTestRv = ZIP_OpenArchive(szArchive, &vZip)) == ZIP_OK) + { + /* 1st parameter should be NULL or it will fail */ + /* It indicates extract the entire archive */ + iTestRv = ZIP_TestArchive(vZip); + ZIP_CloseArchive(&vZip); + } + + // for testing, this will cause about half of the CRCs to fail. Since + // randomly selecting which fail, likely next pass the same file will + // end up a success. + + penv = getenv("MOZ_INSTALL_TEST_CRC"); + if ( penv != (char *) NULL ) { + if ( random() < RAND_MAX / 2 ) + iTestRv = !ZIP_OK; + } + + if ( iTestRv != ZIP_OK ) + unlink( szArchive ); + return(iTestRv); +} + diff --git a/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.h b/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.h index aae38daa55c..6aab1a376fa 100644 --- a/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.h +++ b/mozilla/xpinstall/wizard/unix/src2/nsXIEngine.h @@ -34,6 +34,10 @@ #include "xpistub.h" +#define STANDALONE 1 +#include "zipfile.h" +#include + #include #include #include @@ -61,6 +65,17 @@ typedef struct _xpistub_t pfnXPI_Exit fn_exit; } xpistub_t; +#define TYPE_UNDEF 0 +#define TYPE_PROXY 1 +#define TYPE_HTTP 2 +#define TYPE_FTP 3 + +typedef struct _conn +{ + unsigned char type; // TYPE_UNDEF, etc. + char *URL; // URL this connection is for + void *conn; // pointer to open connection +} CONN; /*------------------------------------------------------------------------* * nsXIEngine @@ -103,7 +118,11 @@ private: nsComponent **aOutComp, int *aOutCompNum); int DelDLMarker(); int TotalToDownload(int aCustom, nsComponentList *aComps); - + PRBool CRCCheckDownloadedArchives(char *dlPath, short dlPathLen, + nsComponent *currComp, int count); + PRBool IsArchiveFile(char *path); + int VerifyArchive(char *szArchive); + PRBool CheckConn( char *URL, int type, CONN *myConn, PRBool force ); char *mTmp; int mTotalComps; char *mOriginalDir;