/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Mozilla Communicator client code, * released March 31, 1998. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * Samir Gehani */ #include "nsXIEngine.h" #define CORE_LIB_COUNT 9 static char sCoreLibs[ CORE_LIB_COUNT * 2 ][ 32 ] = { /* Archive Subdir File */ /* -------------- ---- */ "bin/", "libjsdom.so", "bin/", "libmozjs.so", "bin/", "libnspr4.so", "bin/", "libplc4.so", "bin/", "libplds4.so", "bin/", "libxpcom.so", "bin/", "libxpistub.so", "bin/components/", "libxpinstall.so", "bin/components/", "libjar50.so" }; nsXIEngine::nsXIEngine() : mTmp(NULL) { } nsXIEngine::~nsXIEngine() { DUMP("~nsXIEngine"); // rm tmp dir char cmd[1024]; sprintf(cmd, "rm -rf %s", mTmp); system(cmd); XI_IF_FREE(mTmp); } int nsXIEngine::Download(int aCustom, nsComponentList *aComps) { DUMP("Download"); if (!aComps) return E_PARAM; int err = OK; nsComponent *currComp = aComps->GetHead(); char *currURL = NULL; char *currHost = NULL; char *currDir = NULL; int i; mTmp = NULL; err = MakeUniqueTmpDir(); if (!mTmp || err != OK) return E_DIR_CREATE; // if all .xpis exist in the ./xpi dir (blob/CD) we don't need to download if (ExistAllXPIs(aCustom, aComps)) return CopyToTmp(aCustom, aComps); while (currComp) { if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) ) { for (i = 0; i < MAX_URLS; i++) { currURL = currComp->GetURL(i); if (!currURL) break; currHost = NULL; currDir = NULL; err = ParseURL(currURL, &currHost, &currDir); if (err == OK) { err = FTPAnonGet(currHost, currDir, currComp->GetArchive()); if (err == OK) break; // no need to failover } } } currComp = currComp->GetNext(); } return OK; } int nsXIEngine::Extract(nsComponent *aXPIEngine) { DUMP("Extract"); char path[1024]; char bindir[512]; char unzipcmd[512]; struct stat dummy; int i; if (!aXPIEngine || !(aXPIEngine->GetArchive())) return E_PARAM; sprintf(path, "%s/%s", mTmp, aXPIEngine->GetArchive()); if (-1 == stat(path, &dummy)) return E_NO_DOWNLOAD; for (i = 0; i < CORE_LIB_COUNT*2; i++) { sprintf(unzipcmd, "unzip %s -d %s %s%s > /dev/null", path, mTmp, sCoreLibs[i], sCoreLibs[i+1]); i++; system(unzipcmd); } sprintf(bindir, "%s/%s", mTmp, TMP_EXTRACT_SUBDIR); if (-1 == stat(bindir, &dummy)) return E_EXTRACTION; return OK; } int nsXIEngine::Install(int aCustom, nsComponentList *aComps, char *aDestination) { DUMP("Install"); int err = OK; xpistub_t stub; char cmd[1024]; char *old_LD_LIBRARY_PATH = NULL; char new_LD_LIBRARY_PATH[256]; int i; int compNum = 1; int totalComps; nsComponent *currComp = NULL; if (!aComps || !aDestination) return E_PARAM; // handle LD_LIBRARY_PATH settings memset(new_LD_LIBRARY_PATH, 0, 256); sprintf(new_LD_LIBRARY_PATH, "%s/bin:.", mTmp); DUMP(new_LD_LIBRARY_PATH); old_LD_LIBRARY_PATH = getenv("LD_LIBRARY_PATH"); setenv("LD_LIBRARY_PATH", new_LD_LIBRARY_PATH, 1); if (aCustom) totalComps = aComps->GetLengthSelected(); else totalComps = aComps->GetLength(); currComp = aComps->GetHead(); err = LoadXPIStub(&stub, aDestination); if (err == OK) { for (i = 0; i < MAX_COMPONENTS; i++) { if (!currComp) break; if ( (aCustom && currComp->IsSelected()) || (!aCustom) ) { nsInstallDlg::MajorProgressCB(currComp->GetDescShort(), compNum, totalComps); err = InstallXPI(currComp, &stub); if (err != OK) ErrorHandler(err); // handle and continue compNum++; } currComp = currComp->GetNext(); } } UnloadXPIStub(&stub); // restore LD_LIBRARY_PATH settings setenv("LD_LIBRARY_PATH", old_LD_LIBRARY_PATH, 1); // rm tmp dir --> now in {ROOT}/ chdir("../.."); sprintf(cmd, "rm -rf %s", mTmp); DUMP(cmd); system(cmd); // XXX call gCtx->me->Shutdown(); gtk_main_quit(); exit(err); return err; } int nsXIEngine::MakeUniqueTmpDir() { int err = OK; int i; char buf[1024]; char cwd[1024]; char cmd[1030]; struct stat dummy; mTmp = NULL; memset(cwd, 0, 1024); if (!getcwd(cwd, 1024)) return E_MEM; for (i = 0; i < MAX_TMP_DIRS; i++) { memset(buf, 0, 1024); sprintf(buf, TMP_DIR_TEMPLATE, cwd, i); if (-1 == stat(buf, &dummy)) break; } mTmp = (char *) malloc( (strlen(buf) * sizeof(char)) + 1 ); if (!mTmp) return E_MEM; sprintf(mTmp, "%s", buf); sprintf(cmd, "mkdir %s", mTmp); system(cmd); return err; } int nsXIEngine::ParseURL(char *aURL, char **aHost, char **aDir) { int err = OK; char *host = NULL; char *hostTerminator = NULL; char *dirTerminator = NULL; if (!aURL || !aHost || !aDir) return E_PARAM; if (0 != strncmp(aURL, "ftp://", 6)) return E_BAD_FTP_URL; host = aURL + 6; if (!host) return E_BAD_FTP_URL; hostTerminator = strchr(host, '/'); if (!hostTerminator) return E_BAD_FTP_URL; *aHost = (char *) malloc(sizeof(char) * (hostTerminator - host + 1)); memset(*aHost, 0, (hostTerminator - host + 1)); strncpy(*aHost, host, hostTerminator - host); dirTerminator = strrchr(hostTerminator + 1, '/'); if (!dirTerminator) { // no dir == root dir *aDir = (char *) malloc(2); sprintf(*aDir, "/"); } else { *aDir = (char *) malloc(sizeof(char) * (dirTerminator - hostTerminator + 2)); memset(*aDir, 0, (dirTerminator - hostTerminator + 2)); strncpy(*aDir, hostTerminator, dirTerminator - hostTerminator + 1); } return err; } int nsXIEngine::FTPAnonGet(char *aHost, char *aDir, char *aArchive) { int err = OK; char qualifiedPath[1024]; char basename[256]; char ftpcmds[1024]; struct stat dummy; if (!aHost || !aDir || !aArchive) return E_PARAM; sprintf(qualifiedPath, "%s%s", aDir, aArchive); sprintf(basename, "%s/%s", mTmp, aArchive); sprintf(ftpcmds, "\ \ ftp -n %s <>%s<<\n", libpath); #endif aStub->handle = NULL; aStub->handle = dlopen(libpath, RTLD_LAZY); if (!aStub->handle) { dlerr = dlerror(); DUMP(dlerr); return E_LIB_OPEN; } DUMP("xpistub opened"); /* read and store symbol addresses */ aStub->fn_init = (pfnXPI_Init) dlsym(aStub->handle, FN_INIT); aStub->fn_install = (pfnXPI_Install) dlsym(aStub->handle, FN_INSTALL); aStub->fn_exit = (pfnXPI_Exit) dlsym(aStub->handle, FN_EXIT); if (!aStub->fn_init || !aStub->fn_install || !aStub->fn_exit) { dlerr = dlerror(); DUMP(dlerr); err = E_LIB_SYM; goto BAIL; } DUMP("xpistub symbols loaded"); rv = aStub->fn_init(aDestination, ProgressCallback); #ifdef DEBUG printf("DEBUG: XPI_Init returned 0x%.8X\n", rv); #endif DUMP("XPI_Init called"); if (NS_FAILED(rv)) { err = E_XPI_FAIL; goto BAIL; } return err; BAIL: return err; } int nsXIEngine::InstallXPI(nsComponent *aXPI, xpistub_t *aStub) { int err = OK; char xpipath[1024]; nsresult rv = 0; if (!aStub || !aXPI) return E_PARAM; memset(xpipath, 0, 1024); sprintf(xpipath, "../%s", aXPI->GetArchive()); DUMP(xpipath); #define XPI_NO_NEW_THREAD 0x1000 rv = aStub->fn_install(xpipath, "", XPI_NO_NEW_THREAD); #ifdef DEBUG printf("DEBUG: XPI_Install %s returned %d\n", aXPI->GetArchive(), rv); #endif if (!NS_SUCCEEDED(rv)) err = E_INSTALL; return err; } int nsXIEngine::UnloadXPIStub(xpistub_t *aStub) { int err = OK; /* param check */ if (!aStub) return E_PARAM; /* release XPCOM and XPInstall */ if (aStub->fn_exit) { aStub->fn_exit(); DUMP("XPI_Exit called"); } /* close xpistub library */ if (aStub->handle) { dlclose(aStub->handle); DUMP("xpistub closed"); } return err; } void nsXIEngine::ProgressCallback(const char* aMsg, PRInt32 aVal, PRInt32 aMax) { // DUMP("ProgressCallback"); pthread_mutex_lock(&gCtx->prog_mutex); nsInstallDlg::XPIProgressCB(aMsg, (int)aVal, (int)aMax); gCtx->threadTurn = nsXIContext::UI_THREAD; pthread_cond_signal(&gCtx->prog_cv); pthread_mutex_unlock(&gCtx->prog_mutex); } int nsXIEngine::ExistAllXPIs(int aCustom, nsComponentList *aComps) { int bAllExist = TRUE; nsComponent *currComp = aComps->GetHead(); char currArchivePath[256]; struct stat dummy; while (currComp) { if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) ) { memset(currArchivePath, 0, 256); sprintf(currArchivePath, "%s/%s", XPI_DIR, currComp->GetArchive()); DUMP(currArchivePath); if (0 != stat(currArchivePath, &dummy)) return FALSE; } currComp = currComp->GetNext(); } return bAllExist; } int nsXIEngine::CopyToTmp(int aCustom, nsComponentList *aComps) { int err = OK; nsComponent *currComp = aComps->GetHead(); char cmd[256]; while (currComp) { if ( (aCustom == TRUE && currComp->IsSelected()) || (aCustom == FALSE) ) { memset(cmd, 0, 256); sprintf(cmd, "cp %s/%s %s", XPI_DIR, currComp->GetArchive(), mTmp); DUMP(cmd); system(cmd); } currComp = currComp->GetNext(); } return err; }