/* -*- 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 "nsZipExtractor.h" #define STANDALONE 1 #include "zipstub.h" #include "zipfile.h" nsZipExtractor::nsZipExtractor(char *aTmp) : mTmp(aTmp) { } nsZipExtractor::~nsZipExtractor() { // don't free mTmp: we don't own it } int nsZipExtractor::Extract(nsComponent *aXPIEngine, int aTotal) { DUMP("Extract"); char apath[MAXPATHLEN]; /* archive path */ char bindir[512]; char zpath[MAXPATHLEN]; /* path of file in zip archive */ char epath[MAXPATHLEN]; /* path of file after being extracted */ char *leaf = NULL, *lslash = NULL; struct stat dummy; int i, bFoundAll = FALSE, err = OK; PRInt32 zerr = ZIP_OK; void *hZip = NULL, *hFind = NULL; if (!aXPIEngine || !(aXPIEngine->GetArchive())) return E_PARAM; sprintf(apath, "%s/%s", mTmp, aXPIEngine->GetArchive()); if (-1 == stat(apath, &dummy)) return E_NO_DOWNLOAD; /* initialize archive etc. */ zerr = ZIP_OpenArchive(apath, &hZip); if (zerr != ZIP_OK) return E_EXTRACTION; hFind = ZIP_FindInit(hZip, (const char *) NULL); if (!hFind) { err = E_EXTRACTION; goto au_revoir; } /* extract files */ i = 0; while (!bFoundAll) { memset(zpath, 0, MAXPATHLEN); zerr = ZIP_FindNext(hFind, zpath, MAXPATHLEN); if (zerr == ZIP_ERR_FNF) { bFoundAll = true; break; } if (zerr != ZIP_OK) { err = E_EXTRACTION; goto au_revoir; } /* directory encountered: ignore entry */ lslash = strrchr(zpath, '/'); if (lslash == (zpath + strlen(zpath) - 1)) continue; if (!lslash) leaf = zpath; else leaf = lslash + 1; if (!leaf) continue; /* update UI */ nsInstallDlg::MajorProgressCB(leaf, i, aTotal, nsInstallDlg::ACT_EXTRACT); sprintf(epath, "%s/%s", mTmp, zpath); err = DirCreateRecursive(epath); if (err != OK) goto au_revoir; zerr = ZIP_ExtractFile(hZip, zpath, epath); if (zerr != ZIP_OK) { err = E_EXTRACTION; goto au_revoir; } i++; } sprintf(bindir, "%s/%s", mTmp, TMP_EXTRACT_SUBDIR); if (-1 == stat(bindir, &dummy)) err = E_EXTRACTION; au_revoir: /* close archive etc. */ if (hFind) ZIP_FindFree(hFind); if (hZip) ZIP_CloseArchive(&hZip); return err; } int nsZipExtractor::DirCreateRecursive(char *aPath) { int err = OK; char *slash = NULL, *pathpos = NULL; char currdir[MAXPATHLEN]; struct stat dummy; if (!aPath || !mTmp) return E_PARAM; slash = aPath + strlen(mTmp); if (*slash != '/') return E_INVALID_PTR; while (slash) { memset(currdir, 0, MAXPATHLEN); strncpy(currdir, aPath, slash - aPath); if (-1 == stat(currdir, &dummy)) mkdir(currdir, 0755); pathpos = slash; slash = strchr(pathpos+1, '/'); } return err; }