Back to index

lightning-sunbird  0.9+nobinonly
nsZipExtractor.cpp
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) 1998
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 the GNU General Public License Version 2 or later (the "GPL"), or
00028  * 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 "nsZipExtractor.h"
00041 
00042 #define STANDALONE 1
00043 #include "zipstub.h"
00044 #include "zipfile.h"
00045 
00046 nsZipExtractor::nsZipExtractor(char *aSrc, char *aDest) :
00047     mSrc(NULL),
00048     mDest(NULL)
00049 {
00050     if (aSrc)
00051         mSrc = strdup(aSrc);
00052     if (aDest)
00053         mDest = strdup(aDest);
00054 }
00055 
00056 nsZipExtractor::~nsZipExtractor()
00057 {
00058     XI_IF_FREE(mSrc);
00059     XI_IF_FREE(mDest);
00060 }
00061 
00062 int
00063 nsZipExtractor::Extract(nsComponent *aXPIEngine, int aTotal)
00064 {
00065     DUMP("Extract");
00066    
00067     char apath[MAXPATHLEN]; /* archive path */
00068     char bindir[512];
00069     char zpath[MAXPATHLEN]; /* path of file in zip archive */
00070     char epath[MAXPATHLEN]; /* path of file after being extracted */
00071     char *leaf = NULL, *lslash = NULL;
00072     struct stat dummy;
00073     int i, bFoundAll = FALSE, err = OK;
00074     PRInt32 zerr = ZIP_OK;
00075     void *hZip = NULL, *hFind = NULL;
00076 
00077     if (!aXPIEngine || !(aXPIEngine->GetArchive()))
00078         return E_PARAM;
00079 
00080     sprintf(apath, "%s/%s", mSrc, aXPIEngine->GetArchive());
00081     if (-1 == stat(apath, &dummy))
00082         return E_NO_DOWNLOAD;
00083 
00084     /* initialize archive etc. 
00085      */
00086     zerr = ZIP_OpenArchive(apath, &hZip);
00087     if (zerr != ZIP_OK) return E_EXTRACTION;
00088     hFind = ZIP_FindInit(hZip, (const char *) NULL);
00089     if (!hFind)
00090     {
00091         err = E_EXTRACTION;
00092         goto au_revoir;
00093     }
00094 
00095     /* extract files 
00096      */
00097     i = 0;
00098     while (!bFoundAll)
00099     {
00100         memset(zpath, 0, MAXPATHLEN);
00101         zerr = ZIP_FindNext(hFind, zpath, MAXPATHLEN);
00102         if (zerr == ZIP_ERR_FNF)
00103         {
00104             bFoundAll = true;
00105             break;
00106         }
00107         if (zerr != ZIP_OK)
00108         {
00109             err = E_EXTRACTION;
00110             goto au_revoir;
00111         }
00112 
00113         /* directory encountered: ignore entry
00114          */
00115         lslash = strrchr(zpath, '/');
00116         if (lslash == (zpath + strlen(zpath) - 1))
00117             continue;
00118 
00119         if (!lslash)
00120             leaf = zpath;
00121         else
00122             leaf = lslash + 1;
00123         if (!leaf)
00124             continue;
00125 
00126         /* update UI
00127          */
00128         if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
00129             nsInstallDlg::MajorProgressCB(leaf, i, 
00130                 aTotal, nsInstallDlg::ACT_EXTRACT);
00131 
00132         sprintf(epath, "%s/%s", mDest, zpath);
00133         err = DirCreateRecursive(epath);
00134         if (err != OK) goto au_revoir;
00135 
00136         zerr = ZIP_ExtractFile(hZip, zpath, epath);
00137         if (zerr != ZIP_OK)
00138         {
00139             err = E_EXTRACTION;
00140             goto au_revoir;
00141         }
00142 
00143         i++;
00144     }
00145     
00146     sprintf(bindir, "%s/%s", mDest, TMP_EXTRACT_SUBDIR);
00147     if (-1 == stat(bindir, &dummy))
00148         err = E_EXTRACTION;
00149 
00150 au_revoir:
00151     /* close archive etc.
00152      */
00153     if (hFind)
00154         ZIP_FindFree(hFind);
00155     if (hZip)
00156         ZIP_CloseArchive(&hZip);
00157     return err;
00158 }
00159 
00160 int
00161 nsZipExtractor::DirCreateRecursive(char *aPath)
00162 {
00163     int err = OK;
00164     char *slash = NULL, *pathpos = NULL;
00165     char currdir[MAXPATHLEN];
00166     struct stat dummy;
00167     
00168     if (!aPath || !mDest)
00169         return E_PARAM;
00170 
00171     slash = aPath + strlen(mDest);
00172     if (*slash != '/')
00173         return E_INVALID_PTR;
00174 
00175     while (slash)
00176     {
00177         memset(currdir, 0, MAXPATHLEN);
00178         strncpy(currdir, aPath, slash - aPath);
00179         
00180         if (-1 == stat(currdir, &dummy))
00181             mkdir(currdir, 0755);
00182         
00183         pathpos = slash;
00184         slash = strchr(pathpos+1, '/');
00185     }   
00186 
00187     return err;
00188 }