LCOV - code coverage report
Current view: directory - modules/libjar - nsZipArchive.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 472 371 78.6 %
Date: 2012-06-02 Functions: 50 44 88.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code, released
      16                 :  * March 31, 1998.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Daniel Veditz <dveditz@netscape.com>
      25                 :  *   Samir Gehani <sgehani@netscape.com>
      26                 :  *   Mitch Stoltz <mstoltz@netscape.com>
      27                 :  *   Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
      28                 :  *   Jeff Walden <jwalden+code@mit.edu>
      29                 :  *   Taras Glek <tglek@mozilla.com>
      30                 :  *
      31                 :  * Alternatively, the contents of this file may be used under the terms of
      32                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      33                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      34                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      35                 :  * of those above. If you wish to allow use of your version of this file only
      36                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      37                 :  * use your version of this file under the terms of the MPL, indicate your
      38                 :  * decision by deleting the provisions above and replace them with the notice
      39                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      40                 :  * the provisions above, a recipient may use your version of this file under
      41                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      42                 :  *
      43                 :  * ***** END LICENSE BLOCK ***** */
      44                 : 
      45                 : /*
      46                 :  * This module implements a simple archive extractor for the PKZIP format.
      47                 :  *
      48                 :  * The underlying nsZipArchive is NOT thread-safe. Do not pass references
      49                 :  * or pointers to it across thread boundaries.
      50                 :  */
      51                 : 
      52                 : #define READTYPE  PRInt32
      53                 : #include "zlib.h"
      54                 : #include "nsISupportsUtils.h"
      55                 : #include "prio.h"
      56                 : #include "plstr.h"
      57                 : #include "prlog.h"
      58                 : #include "stdlib.h"
      59                 : #include "nsWildCard.h"
      60                 : #include "nsZipArchive.h"
      61                 : #include "nsString.h"
      62                 : #include "mozilla/FunctionTimer.h"
      63                 : #include "prenv.h"
      64                 : #if defined(XP_WIN)
      65                 : #include <windows.h>
      66                 : #endif
      67                 : 
      68                 : // For placement new used for arena allocations of zip file list
      69                 : #include NEW_H
      70                 : #define ZIP_ARENABLOCKSIZE (1*1024)
      71                 : 
      72                 : #ifdef XP_UNIX
      73                 :     #include <sys/types.h>
      74                 :     #include <sys/stat.h>
      75                 :     #include <limits.h>
      76                 :     #include <unistd.h>
      77                 : #elif defined(XP_WIN) || defined(XP_OS2)
      78                 :     #include <io.h>
      79                 : #endif
      80                 : 
      81                 : #ifdef __SYMBIAN32__
      82                 :     #include <sys/syslimits.h>
      83                 : #endif /*__SYMBIAN32__*/
      84                 : 
      85                 : 
      86                 : #ifndef XP_UNIX /* we need some constants defined in limits.h and unistd.h */
      87                 : #  ifndef S_IFMT
      88                 : #    define S_IFMT 0170000
      89                 : #  endif
      90                 : #  ifndef S_IFLNK
      91                 : #    define S_IFLNK  0120000
      92                 : #  endif
      93                 : #  ifndef PATH_MAX
      94                 : #    define PATH_MAX 1024
      95                 : #  endif
      96                 : #endif  /* XP_UNIX */
      97                 : 
      98                 : 
      99                 : using namespace mozilla;
     100                 : 
     101                 : static const PRUint32 kMaxNameLength = PATH_MAX; /* Maximum name length */
     102                 : // For synthetic zip entries. Date/time corresponds to 1980-01-01 00:00.
     103                 : static const PRUint16 kSyntheticTime = 0;
     104                 : static const PRUint16 kSyntheticDate = (1 + (1 << 5) + (0 << 9));
     105                 : 
     106                 : static PRUint16 xtoint(const PRUint8 *ii);
     107                 : static PRUint32 xtolong(const PRUint8 *ll);
     108                 : static PRUint32 HashName(const char* aName, PRUint16 nameLen);
     109                 : #ifdef XP_UNIX
     110                 : static nsresult ResolveSymlink(const char *path);
     111                 : #endif
     112                 : 
     113                 : //***********************************************************
     114                 : // For every inflation the following allocations are done:
     115                 : // malloc(1 * 9520)
     116                 : // malloc(32768 * 1)
     117                 : //***********************************************************
     118                 : 
     119            1223 : nsresult gZlibInit(z_stream *zs)
     120                 : {
     121            1223 :   memset(zs, 0, sizeof(z_stream));
     122            1223 :   int zerr = inflateInit2(zs, -MAX_WBITS);
     123            1223 :   if (zerr != Z_OK) return NS_ERROR_OUT_OF_MEMORY;
     124                 : 
     125            1223 :   return NS_OK;
     126                 : }
     127                 : 
     128            2428 : nsZipHandle::nsZipHandle()
     129                 :   : mFileData(nsnull)
     130                 :   , mLen(0)
     131                 :   , mMap(nsnull)
     132            2428 :   , mRefCnt(0)
     133                 : {
     134            2428 :   MOZ_COUNT_CTOR(nsZipHandle);
     135            2428 : }
     136                 : 
     137            6192 : NS_IMPL_THREADSAFE_ADDREF(nsZipHandle)
     138            8620 : NS_IMPL_THREADSAFE_RELEASE(nsZipHandle)
     139                 : 
     140            2383 : nsresult nsZipHandle::Init(nsILocalFile *file, nsZipHandle **ret)
     141                 : {
     142            4766 :   mozilla::AutoFDClose fd;
     143            2383 :   nsresult rv = file->OpenNSPRFileDesc(PR_RDONLY, 0000, &fd);
     144            2383 :   if (NS_FAILED(rv))
     145               0 :     return rv;
     146                 : 
     147            2383 :   PRInt64 size = PR_Available64(fd);
     148            2383 :   if (size >= PR_INT32_MAX)
     149               0 :     return NS_ERROR_FILE_TOO_BIG;
     150                 : 
     151            2383 :   PRFileMap *map = PR_CreateFileMap(fd, size, PR_PROT_READONLY);
     152            2383 :   if (!map)
     153               0 :     return NS_ERROR_FAILURE;
     154                 :   
     155            2383 :   PRUint8 *buf = (PRUint8*) PR_MemMap(map, 0, (PRUint32) size);
     156                 :   // Bug 525755: PR_MemMap fails when fd points at something other than a normal file.
     157            2383 :   if (!buf) {
     158               1 :     PR_CloseFileMap(map);
     159               1 :     return NS_ERROR_FAILURE;
     160                 :   }
     161                 : 
     162            4764 :   nsRefPtr<nsZipHandle> handle = new nsZipHandle();
     163            2382 :   if (!handle) {
     164               0 :     PR_MemUnmap(buf, (PRUint32) size);
     165               0 :     PR_CloseFileMap(map);
     166               0 :     return NS_ERROR_OUT_OF_MEMORY;
     167                 :   }
     168                 : 
     169            2382 :   handle->mMap = map;
     170            2382 :   handle->mFile.Init(file);
     171            2382 :   handle->mLen = (PRUint32) size;
     172            2382 :   handle->mFileData = buf;
     173            2382 :   *ret = handle.forget().get();
     174            2382 :   return NS_OK;
     175                 : }
     176                 : 
     177              46 : nsresult nsZipHandle::Init(nsZipArchive *zip, const char *entry,
     178                 :                            nsZipHandle **ret)
     179                 : {
     180              92 :   nsRefPtr<nsZipHandle> handle = new nsZipHandle();
     181              46 :   if (!handle)
     182               0 :     return NS_ERROR_OUT_OF_MEMORY;
     183                 : 
     184              46 :   handle->mBuf = new nsZipItemPtr<PRUint8>(zip, entry);
     185              46 :   if (!handle->mBuf)
     186               0 :     return NS_ERROR_OUT_OF_MEMORY;
     187                 : 
     188              46 :   if (!handle->mBuf->Buffer())
     189               0 :     return NS_ERROR_UNEXPECTED;
     190                 : 
     191              46 :   handle->mMap = nsnull;
     192              46 :   handle->mFile.Init(zip, entry);
     193              46 :   handle->mLen = handle->mBuf->Length();
     194              46 :   handle->mFileData = handle->mBuf->Buffer();
     195              46 :   *ret = handle.forget().get();
     196              46 :   return NS_OK;
     197                 : }
     198                 : 
     199               0 : PRInt64 nsZipHandle::SizeOfMapping()
     200                 : {
     201               0 :     return mLen;
     202                 : }
     203                 : 
     204            4856 : nsZipHandle::~nsZipHandle()
     205                 : {
     206            2428 :   if (mMap) {
     207            2382 :     PR_MemUnmap((void *)mFileData, mLen);
     208            2382 :     PR_CloseFileMap(mMap);
     209                 :   }
     210            2428 :   mFileData = nsnull;
     211            2428 :   mMap = nsnull;
     212            2428 :   mBuf = nsnull;
     213            2428 :   MOZ_COUNT_DTOR(nsZipHandle);
     214            2428 : }
     215                 : 
     216                 : //***********************************************************
     217                 : //      nsZipArchive  --  public methods
     218                 : //***********************************************************
     219                 : 
     220                 : //---------------------------------------------
     221                 : //  nsZipArchive::OpenArchive
     222                 : //---------------------------------------------
     223            2428 : nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle)
     224                 : {
     225            2428 :   mFd = aZipHandle;
     226                 : 
     227                 :   // Initialize our arena
     228            2428 :   PL_INIT_ARENA_POOL(&mArena, "ZipArena", ZIP_ARENABLOCKSIZE);
     229                 : 
     230                 :   //-- get table of contents for archive
     231            2428 :   nsresult rv = BuildFileList();
     232            2428 :   char *env = PR_GetEnv("MOZ_JAR_LOG_DIR");
     233            2428 :   if (env && NS_SUCCEEDED(rv) && aZipHandle->mFile) {
     234               0 :     nsCOMPtr<nsILocalFile> logFile;
     235               0 :     nsresult rv2 = NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false, getter_AddRefs(logFile));
     236                 :     
     237               0 :     if (!NS_SUCCEEDED(rv2))
     238               0 :       return rv;
     239                 : 
     240                 :     // Create a directory for the log (in case it doesn't exist)
     241               0 :     logFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
     242                 : 
     243               0 :     nsAutoString name;
     244               0 :     nsCOMPtr<nsILocalFile> file = aZipHandle->mFile.GetBaseFile();
     245               0 :     file->GetLeafName(name);
     246               0 :     name.Append(NS_LITERAL_STRING(".log"));
     247               0 :     logFile->Append(name);
     248                 : 
     249                 :     PRFileDesc* fd;
     250               0 :     rv2 = logFile->OpenNSPRFileDesc(PR_WRONLY|PR_CREATE_FILE|PR_APPEND, 0644, &fd);
     251               0 :     if (NS_SUCCEEDED(rv2))
     252               0 :       mLog = fd;
     253                 :   }
     254            2428 :   return rv;
     255                 : }
     256                 : 
     257            2383 : nsresult nsZipArchive::OpenArchive(nsIFile *aFile)
     258                 : {
     259                 :   nsresult rv;
     260            4766 :   nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFile, &rv);
     261            2383 :   NS_ENSURE_SUCCESS(rv, rv);
     262                 : 
     263            4766 :   nsRefPtr<nsZipHandle> handle;
     264            2383 :   rv = nsZipHandle::Init(localFile, getter_AddRefs(handle));
     265            2383 :   if (NS_FAILED(rv))
     266               1 :     return rv;
     267                 : 
     268            2382 :   return OpenArchive(handle);
     269                 : }
     270                 : 
     271                 : //---------------------------------------------
     272                 : //  nsZipArchive::Test
     273                 : //---------------------------------------------
     274              16 : nsresult nsZipArchive::Test(const char *aEntryName)
     275                 : {
     276                 :   nsZipItem* currItem;
     277                 : 
     278              16 :   if (aEntryName) // only test specified item
     279                 :   {
     280              14 :     currItem = GetItem(aEntryName);
     281              14 :     if (!currItem)
     282               0 :       return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
     283                 :     //-- don't test (synthetic) directory items
     284              14 :     if (currItem->IsDirectory())
     285               0 :       return NS_OK;
     286              14 :     return ExtractFile(currItem, 0, 0);
     287                 :   }
     288                 : 
     289                 :   // test all items in archive
     290             514 :   for (int i = 0; i < ZIP_TABSIZE; i++) {
     291             516 :     for (currItem = mFiles[i]; currItem; currItem = currItem->next) {
     292                 :       //-- don't test (synthetic) directory items
     293               4 :       if (currItem->IsDirectory())
     294               3 :         continue;
     295               1 :       nsresult rv = ExtractFile(currItem, 0, 0);
     296               1 :       if (rv != NS_OK)
     297               0 :         return rv;
     298                 :     }
     299                 :   }
     300                 : 
     301               2 :   return NS_OK;
     302                 : }
     303                 : 
     304                 : //---------------------------------------------
     305                 : //  nsZipArchive::CloseArchive
     306                 : //---------------------------------------------
     307            5728 : nsresult nsZipArchive::CloseArchive()
     308                 : {
     309            5728 :   if (mFd) {
     310            2428 :     PL_FinishArenaPool(&mArena);
     311            2428 :     mFd = NULL;
     312                 :   }
     313                 : 
     314                 :   // CAUTION:
     315                 :   // We don't need to delete each of the nsZipItem as the memory for
     316                 :   // the zip item and the filename it holds are both allocated from the Arena.
     317                 :   // Hence, destroying the Arena is like destroying all the memory
     318                 :   // for all the nsZipItem in one shot. But if the ~nsZipItem is doing
     319                 :   // anything more than cleaning up memory, we should start calling it.
     320                 :   // Let us also cleanup the mFiles table for re-use on the next 'open' call
     321            5728 :   memset(mFiles, 0, sizeof(mFiles));
     322            5728 :   mBuiltSynthetics = false;
     323            5728 :   return NS_OK;
     324                 : }
     325                 : 
     326                 : //---------------------------------------------
     327                 : // nsZipArchive::GetItem
     328                 : //---------------------------------------------
     329            3932 : nsZipItem*  nsZipArchive::GetItem(const char * aEntryName)
     330                 : {
     331            3932 :   if (aEntryName) {
     332            3932 :     PRUint32 len = strlen(aEntryName);
     333                 :     //-- If the request is for a directory, make sure that synthetic entries 
     334                 :     //-- are created for the directories without their own entry.
     335            3932 :     if (!mBuiltSynthetics) {
     336            1462 :         if ((len > 0) && (aEntryName[len-1] == '/')) {
     337               1 :             if (BuildSynthetics() != NS_OK)
     338               0 :                 return 0;
     339                 :         }
     340                 :     }
     341                 : MOZ_WIN_MEM_TRY_BEGIN
     342            3932 :     nsZipItem* item = mFiles[ HashName(aEntryName, len) ];
     343            8006 :     while (item) {
     344            7700 :       if ((len == item->nameLength) && 
     345            3850 :           (!memcmp(aEntryName, item->Name(), len))) {
     346                 :         
     347            3708 :         if (mLog) {
     348                 :           // Successful GetItem() is a good indicator that the file is about to be read
     349               0 :           char *tmp = PL_strdup(aEntryName);
     350               0 :           tmp[len]='\n';
     351               0 :           PR_Write(mLog, tmp, len+1);
     352               0 :           PL_strfree(tmp);
     353                 :         }
     354            3708 :         return item; //-- found it
     355                 :       }
     356             142 :       item = item->next;
     357                 :     }
     358                 : MOZ_WIN_MEM_TRY_CATCH(return nsnull)
     359                 :   }
     360             224 :   return nsnull;
     361                 : }
     362                 : 
     363                 : //---------------------------------------------
     364                 : // nsZipArchive::ExtractFile
     365                 : // This extracts the item to the filehandle provided.
     366                 : // If 'aFd' is null, it only tests the extraction.
     367                 : // On extraction error(s) it removes the file.
     368                 : // When needed, it also resolves the symlink.
     369                 : //---------------------------------------------
     370             731 : nsresult nsZipArchive::ExtractFile(nsZipItem *item, const char *outname,
     371                 :                                    PRFileDesc* aFd)
     372                 : {
     373             731 :   if (!item)
     374               0 :     return NS_ERROR_ILLEGAL_VALUE;
     375             731 :   if (!mFd)
     376               0 :     return NS_ERROR_FAILURE;
     377                 : 
     378                 :   // Directory extraction is handled in nsJAR::Extract,
     379                 :   // so the item to be extracted should never be a directory
     380             731 :   PR_ASSERT(!item->IsDirectory());
     381                 : 
     382                 :   Bytef outbuf[ZIP_BUFLEN];
     383                 : 
     384            1462 :   nsZipCursor cursor(item, this, outbuf, ZIP_BUFLEN, true);
     385                 : 
     386             731 :   nsresult rv = NS_OK;
     387                 : 
     388             468 :   while (true) {
     389            1199 :     PRUint32 count = 0;
     390            1199 :     PRUint8* buf = cursor.Read(&count);
     391            1199 :     if (!buf) {
     392               0 :       rv = NS_ERROR_FILE_CORRUPTED;
     393               0 :       break;
     394            1199 :     } else if (count == 0) {
     395             731 :       break;
     396                 :     }
     397                 : 
     398             468 :     if (aFd && PR_Write(aFd, buf, count) < (READTYPE)count) {
     399               0 :       rv = NS_ERROR_FILE_DISK_FULL;
     400               0 :       break;
     401                 :     }
     402                 :   }
     403                 : 
     404                 :   //-- delete the file on errors, or resolve symlink if needed
     405             731 :   if (aFd) {
     406             716 :     PR_Close(aFd);
     407             716 :     if (rv != NS_OK)
     408               0 :       PR_Delete(outname);
     409                 : #ifdef XP_UNIX
     410             716 :     else if (item->IsSymlink())
     411               0 :       rv = ResolveSymlink(outname);
     412                 : #endif
     413                 :   }
     414                 : 
     415             731 :   return rv;
     416                 : }
     417                 : 
     418                 : //---------------------------------------------
     419                 : // nsZipArchive::FindInit
     420                 : //---------------------------------------------
     421                 : PRInt32
     422            2144 : nsZipArchive::FindInit(const char * aPattern, nsZipFind **aFind)
     423                 : {
     424            2144 :   if (!aFind)
     425               0 :     return NS_ERROR_ILLEGAL_VALUE;
     426                 : 
     427                 :   // null out param in case an error happens
     428            2144 :   *aFind = NULL;
     429                 : 
     430            2144 :   bool    regExp = false;
     431            2144 :   char*   pattern = 0;
     432                 : 
     433                 :   // Create synthetic directory entries on demand
     434            2144 :   nsresult rv = BuildSynthetics();
     435            2144 :   if (rv != NS_OK)
     436               0 :     return rv;
     437                 : 
     438                 :   // validate the pattern
     439            2144 :   if (aPattern)
     440                 :   {
     441             792 :     switch (NS_WildCardValid((char*)aPattern))
     442                 :     {
     443                 :       case INVALID_SXP:
     444               0 :         return NS_ERROR_ILLEGAL_VALUE;
     445                 : 
     446                 :       case NON_SXP:
     447               0 :         regExp = false;
     448               0 :         break;
     449                 : 
     450                 :       case VALID_SXP:
     451             792 :         regExp = true;
     452             792 :         break;
     453                 : 
     454                 :       default:
     455                 :         // undocumented return value from RegExpValid!
     456               0 :         PR_ASSERT(false);
     457               0 :         return NS_ERROR_ILLEGAL_VALUE;
     458                 :     }
     459                 : 
     460             792 :     pattern = PL_strdup(aPattern);
     461             792 :     if (!pattern)
     462               0 :       return NS_ERROR_OUT_OF_MEMORY;
     463                 :   }
     464                 : 
     465            2144 :   *aFind = new nsZipFind(this, pattern, regExp);
     466            2144 :   if (!*aFind) {
     467               0 :     PL_strfree(pattern);
     468               0 :     return NS_ERROR_OUT_OF_MEMORY;
     469                 :   }
     470                 : 
     471            2144 :   return NS_OK;
     472                 : }
     473                 : 
     474                 : 
     475                 : 
     476                 : //---------------------------------------------
     477                 : // nsZipFind::FindNext
     478                 : //---------------------------------------------
     479            4124 : nsresult nsZipFind::FindNext(const char ** aResult, PRUint16 *aNameLen)
     480                 : {
     481            4124 :   if (!mArchive || !aResult || !aNameLen)
     482               0 :     return NS_ERROR_ILLEGAL_VALUE;
     483                 : 
     484            4124 :   *aResult = 0;
     485            4124 :   *aNameLen = 0;
     486                 : MOZ_WIN_MEM_TRY_BEGIN
     487                 :   // we start from last match, look for next
     488          558103 :   while (mSlot < ZIP_TABSIZE)
     489                 :   {
     490                 :     // move to next in current chain, or move to new slot
     491          551837 :     mItem = mItem ? mItem->next : mArchive->mFiles[mSlot];
     492                 : 
     493          551837 :     bool found = false;
     494          551837 :     if (!mItem)
     495          548588 :       ++mSlot;                          // no more in this chain, move to next slot
     496            3249 :     else if (!mPattern)
     497            1910 :       found = true;            // always match
     498            1339 :     else if (mRegExp)
     499                 :     {
     500                 :       char buf[kMaxNameLength+1];
     501            1339 :       memcpy(buf, mItem->Name(), mItem->nameLength);
     502            1339 :       buf[mItem->nameLength]='\0';
     503            1339 :       found = (NS_WildCardMatch(buf, mPattern, false) == MATCH);
     504                 :     }
     505                 :     else
     506               0 :       found = ((mItem->nameLength == strlen(mPattern)) &&
     507               0 :                (memcmp(mItem->Name(), mPattern, mItem->nameLength) == 0));
     508          551837 :     if (found) {
     509                 :       // Need also to return the name length, as it is NOT zero-terminatdd...
     510            1982 :       *aResult = mItem->Name();
     511            1982 :       *aNameLen = mItem->nameLength;
     512            1982 :       return NS_OK;
     513                 :     }
     514                 :   }
     515                 : MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
     516            2142 :   return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
     517                 : }
     518                 : 
     519                 : #ifdef XP_UNIX
     520                 : //---------------------------------------------
     521                 : // ResolveSymlink
     522                 : //---------------------------------------------
     523               0 : static nsresult ResolveSymlink(const char *path)
     524                 : {
     525               0 :   PRFileDesc * fIn = PR_Open(path, PR_RDONLY, 0000);
     526               0 :   if (!fIn)
     527               0 :     return NS_ERROR_FILE_DISK_FULL;
     528                 : 
     529                 :   char buf[PATH_MAX+1];
     530               0 :   PRInt32 length = PR_Read(fIn, (void*)buf, PATH_MAX);
     531               0 :   PR_Close(fIn);
     532                 : 
     533               0 :   if ( (length <= 0)
     534               0 :     || ((buf[length] = 0, PR_Delete(path)) != 0)
     535               0 :     || (symlink(buf, path) != 0))
     536                 :   {
     537               0 :      return NS_ERROR_FILE_DISK_FULL;
     538                 :   }
     539               0 :   return NS_OK;
     540                 : }
     541                 : #endif
     542                 : 
     543                 : //***********************************************************
     544                 : //      nsZipArchive  --  private implementation
     545                 : //***********************************************************
     546                 : 
     547                 : //---------------------------------------------
     548                 : //  nsZipArchive::CreateZipItem
     549                 : //---------------------------------------------
     550            8474 : nsZipItem* nsZipArchive::CreateZipItem()
     551                 : {
     552                 :   // Arena allocate the nsZipItem
     553                 :   void *mem;
     554            8474 :   PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsZipItem));
     555            8474 :   return (nsZipItem*)mem;
     556                 : }
     557                 : 
     558                 : //---------------------------------------------
     559                 : //  nsZipArchive::BuildFileList
     560                 : //---------------------------------------------
     561            2428 : nsresult nsZipArchive::BuildFileList()
     562                 : {
     563                 : #ifndef XP_WIN
     564                 :   NS_TIME_FUNCTION;
     565                 : #endif
     566                 :   // Get archive size using end pos
     567                 :   const PRUint8* buf;
     568            2428 :   const PRUint8* startp = mFd->mFileData;
     569            2428 :   const PRUint8* endp = startp + mFd->mLen;
     570                 : MOZ_WIN_MEM_TRY_BEGIN
     571            2428 :   PRUint32 centralOffset = 4;
     572            2428 :   if (mFd->mLen > ZIPCENTRAL_SIZE && xtolong(startp + centralOffset) == CENTRALSIG) {
     573                 :     // Success means optimized jar layout from bug 559961 is in effect
     574                 :   } else {
     575            7285 :     for (buf = endp - ZIPEND_SIZE; buf > startp; buf--)
     576                 :       {
     577            7266 :         if (xtolong(buf) == ENDSIG) {
     578            2408 :           centralOffset = xtolong(((ZipEnd *)buf)->offset_central_dir);
     579            2408 :           break;
     580                 :         }
     581                 :       }
     582                 :   }
     583                 : 
     584            2428 :   if (!centralOffset)
     585               0 :     return NS_ERROR_FILE_CORRUPTED;
     586                 : 
     587                 :   //-- Read the central directory headers
     588            2428 :   buf = startp + centralOffset;
     589            2428 :   PRUint32 sig = 0;
     590           13327 :   while (buf + PRInt32(sizeof(PRUint32)) <= endp &&
     591                 :          (sig = xtolong(buf)) == CENTRALSIG) {
     592                 :     // Make sure there is enough data available.
     593            8471 :     if (endp - buf < ZIPCENTRAL_SIZE)
     594               0 :       return NS_ERROR_FILE_CORRUPTED;
     595                 : 
     596                 :     // Read the fixed-size data.
     597            8471 :     ZipCentral* central = (ZipCentral*)buf;
     598                 : 
     599            8471 :     PRUint16 namelen = xtoint(central->filename_len);
     600            8471 :     PRUint16 extralen = xtoint(central->extrafield_len);
     601            8471 :     PRUint16 commentlen = xtoint(central->commentfield_len);
     602                 : 
     603                 :     // Point to the next item at the top of loop
     604            8471 :     buf += ZIPCENTRAL_SIZE + namelen + extralen + commentlen;
     605                 : 
     606                 :     // Sanity check variable sizes and refuse to deal with
     607                 :     // anything too big: it's likely a corrupt archive.
     608            8471 :     if (namelen > kMaxNameLength || buf >= endp)
     609               0 :       return NS_ERROR_FILE_CORRUPTED;
     610                 : 
     611            8471 :     nsZipItem* item = CreateZipItem();
     612            8471 :     if (!item)
     613               0 :       return NS_ERROR_OUT_OF_MEMORY;
     614                 : 
     615            8471 :     item->central = central;
     616            8471 :     item->nameLength = namelen;
     617            8471 :     item->isSynthetic = false;
     618                 : 
     619                 :     // Add item to file table
     620            8471 :     PRUint32 hash = HashName(item->Name(), namelen);
     621            8471 :     item->next = mFiles[hash];
     622            8471 :     mFiles[hash] = item;
     623                 : 
     624            8471 :     sig = 0;
     625                 :   } /* while reading central directory records */
     626                 : 
     627            2428 :   if (sig != ENDSIG)
     628              20 :     return NS_ERROR_FILE_CORRUPTED;
     629                 : 
     630                 :   // Make the comment available for consumers.
     631            2408 :   if (endp - buf >= ZIPEND_SIZE) {
     632            2408 :     ZipEnd *zipend = (ZipEnd *)buf;
     633                 : 
     634            2408 :     buf += ZIPEND_SIZE;
     635            2408 :     PRUint16 commentlen = xtoint(zipend->commentfield_len);
     636            2408 :     if (endp - buf >= commentlen) {
     637            2408 :       mCommentPtr = (const char *)buf;
     638            2408 :       mCommentLen = commentlen;
     639                 :     }
     640                 :   }
     641                 : 
     642                 : MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
     643            2408 :   return NS_OK;
     644                 : }
     645                 : 
     646                 : //---------------------------------------------
     647                 : //  nsZipArchive::BuildSynthetics
     648                 : //---------------------------------------------
     649            2145 : nsresult nsZipArchive::BuildSynthetics()
     650                 : {
     651            2145 :   if (mBuiltSynthetics)
     652             787 :     return NS_OK;
     653            1358 :   mBuiltSynthetics = true;
     654                 : 
     655                 : MOZ_WIN_MEM_TRY_BEGIN
     656                 :   // Create synthetic entries for any missing directories.
     657                 :   // Do this when all ziptable has scanned to prevent double entries.
     658          349006 :   for (int i = 0; i < ZIP_TABSIZE; ++i)
     659                 :   {
     660          349567 :     for (nsZipItem* item = mFiles[i]; item != 0; item = item->next)
     661                 :     {
     662            1919 :       if (item->isSynthetic)
     663               1 :         continue;
     664                 :     
     665                 :       //-- add entries for directories in the current item's path
     666                 :       //-- go from end to beginning, because then we can stop trying
     667                 :       //-- to create diritems if we find that the diritem we want to
     668                 :       //-- create already exists
     669                 :       //-- start just before the last char so as to not add the item
     670                 :       //-- twice if it's a directory
     671            1918 :       PRUint16 namelen = item->nameLength;
     672            1918 :       const char *name = item->Name();
     673           20987 :       for (PRUint16 dirlen = namelen - 1; dirlen > 0; dirlen--)
     674                 :       {
     675           19125 :         if (name[dirlen-1] != '/')
     676           19066 :           continue;
     677                 : 
     678                 :         // Is the directory already in the file table?
     679              59 :         PRUint32 hash = HashName(item->Name(), dirlen);
     680              59 :         bool found = false;
     681              59 :         for (nsZipItem* zi = mFiles[hash]; zi != NULL; zi = zi->next)
     682                 :         {
     683             112 :           if ((dirlen == zi->nameLength) &&
     684              56 :               (0 == memcmp(item->Name(), zi->Name(), dirlen)))
     685                 :           {
     686                 :             // we've already added this dir and all its parents
     687              56 :             found = true;
     688              56 :             break;
     689                 :           }
     690                 :         }
     691                 :         // if the directory was found, break out of the directory
     692                 :         // creation loop now that we know all implicit directories
     693                 :         // are there -- otherwise, start creating the zip item
     694              59 :         if (found)
     695              56 :           break;
     696                 : 
     697               3 :         nsZipItem* diritem = CreateZipItem();
     698               3 :         if (!diritem)
     699               0 :           return NS_ERROR_OUT_OF_MEMORY;
     700                 : 
     701                 :         // Point to the central record of the original item for the name part.
     702               3 :         diritem->central =  item->central;
     703               3 :         diritem->nameLength = dirlen;
     704               3 :         diritem->isSynthetic = true;
     705                 : 
     706                 :         // add diritem to the file table
     707               3 :         diritem->next = mFiles[hash];
     708               3 :         mFiles[hash] = diritem;
     709                 :       } /* end processing of dirs in item's name */
     710                 :     }
     711                 :   }
     712                 : MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
     713            1358 :   return NS_OK;
     714                 : }
     715                 : 
     716            1336 : nsZipHandle* nsZipArchive::GetFD()
     717                 : {
     718            1336 :   if (!mFd)
     719               0 :     return NULL;
     720            1336 :   return mFd.get();
     721                 : }
     722                 : 
     723                 : //---------------------------------------------
     724                 : // nsZipArchive::GetData
     725                 : //---------------------------------------------
     726            2072 : const PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
     727                 : {
     728            2072 :   PR_ASSERT (aItem);
     729                 : MOZ_WIN_MEM_TRY_BEGIN
     730                 :   //-- read local header to get variable length values and calculate
     731                 :   //-- the real data offset
     732            2072 :   PRUint32 len = mFd->mLen;
     733            2072 :   const PRUint8* data = mFd->mFileData;
     734            2072 :   PRUint32 offset = aItem->LocalOffset();
     735            2072 :   if (offset + ZIPLOCAL_SIZE > len)
     736               0 :     return nsnull;
     737                 : 
     738                 :   // -- check signature before using the structure, in case the zip file is corrupt
     739            2072 :   ZipLocal* Local = (ZipLocal*)(data + offset);
     740            2072 :   if ((xtolong(Local->signature) != LOCALSIG))
     741               1 :     return nsnull;
     742                 : 
     743                 :   //-- NOTE: extralen is different in central header and local header
     744                 :   //--       for archives created using the Unix "zip" utility. To set
     745                 :   //--       the offset accurately we need the _local_ extralen.
     746                 :   offset += ZIPLOCAL_SIZE +
     747            2071 :             xtoint(Local->filename_len) +
     748            2071 :             xtoint(Local->extrafield_len);
     749                 : 
     750                 :   // -- check if there is enough source data in the file
     751            2071 :   if (offset + aItem->Size() > len)
     752               0 :     return nsnull;
     753                 : 
     754            2071 :   return data + offset;
     755                 : MOZ_WIN_MEM_TRY_CATCH(return nsnull)
     756                 : }
     757                 : 
     758                 : // nsZipArchive::GetComment
     759               2 : bool nsZipArchive::GetComment(nsACString &aComment)
     760                 : {
     761                 : MOZ_WIN_MEM_TRY_BEGIN
     762               2 :   aComment.Assign(mCommentPtr, mCommentLen);
     763                 : MOZ_WIN_MEM_TRY_CATCH(return false)
     764               2 :   return true;
     765                 : }
     766                 : 
     767                 : //---------------------------------------------
     768                 : // nsZipArchive::SizeOfMapping
     769                 : //---------------------------------------------
     770               0 : PRInt64 nsZipArchive::SizeOfMapping()
     771                 : {
     772               0 :     return mFd ? mFd->SizeOfMapping() : 0;
     773                 : }
     774                 : 
     775                 : //------------------------------------------
     776                 : // nsZipArchive constructor and destructor
     777                 : //------------------------------------------
     778                 : 
     779            2431 : nsZipArchive::nsZipArchive()
     780                 :   : mRefCnt(0)
     781            2431 :   , mBuiltSynthetics(false)
     782                 : {
     783            2431 :   MOZ_COUNT_CTOR(nsZipArchive);
     784                 : 
     785                 :   // initialize the table to NULL
     786            2431 :   memset(mFiles, 0, sizeof(mFiles));
     787            2431 : }
     788                 : 
     789            4621 : NS_IMPL_THREADSAFE_ADDREF(nsZipArchive)
     790            7052 : NS_IMPL_THREADSAFE_RELEASE(nsZipArchive)
     791                 : 
     792            4862 : nsZipArchive::~nsZipArchive()
     793                 : {
     794            2431 :   CloseArchive();
     795                 : 
     796            2431 :   MOZ_COUNT_DTOR(nsZipArchive);
     797            2431 : }
     798                 : 
     799                 : 
     800                 : //------------------------------------------
     801                 : // nsZipFind constructor and destructor
     802                 : //------------------------------------------
     803                 : 
     804            2144 : nsZipFind::nsZipFind(nsZipArchive* aZip, char* aPattern, bool aRegExp) : 
     805                 :   mArchive(aZip),
     806                 :   mPattern(aPattern),
     807                 :   mItem(0),
     808                 :   mSlot(0),
     809            2144 :   mRegExp(aRegExp)
     810                 : {
     811            2144 :   MOZ_COUNT_CTOR(nsZipFind);
     812            2144 : }
     813                 : 
     814            4288 : nsZipFind::~nsZipFind()
     815                 : {
     816            2144 :   PL_strfree(mPattern);
     817                 : 
     818            2144 :   MOZ_COUNT_DTOR(nsZipFind);
     819            2144 : }
     820                 : 
     821                 : //------------------------------------------
     822                 : // helper functions
     823                 : //------------------------------------------
     824                 : 
     825                 : /* 
     826                 :  * HashName 
     827                 :  *
     828                 :  * returns a hash key for the entry name 
     829                 :  */
     830           12462 : static PRUint32 HashName(const char* aName, PRUint16 len)
     831                 : {
     832           12462 :   PR_ASSERT(aName != 0);
     833                 : 
     834           12462 :   const PRUint8* p = (const PRUint8*)aName;
     835           12462 :   const PRUint8* endp = p + len;
     836           12462 :   PRUint32 val = 0;
     837          371354 :   while (p != endp) {
     838          346430 :     val = val*37 + *p++;
     839                 :   }
     840                 : 
     841           12462 :   return (val % ZIP_TABSIZE);
     842                 : }
     843                 : 
     844                 : /*
     845                 :  *  x t o i n t
     846                 :  *
     847                 :  *  Converts a two byte ugly endianed integer
     848                 :  *  to our platform's integer.
     849                 :  */
     850           44982 : static PRUint16 xtoint (const PRUint8 *ii)
     851                 : {
     852           44982 :   return (PRUint16) ((ii [0]) | (ii [1] << 8));
     853                 : }
     854                 : 
     855                 : /*
     856                 :  *  x t o l o n g
     857                 :  *
     858                 :  *  Converts a four byte ugly endianed integer
     859                 :  *  to our platform's integer.
     860                 :  */
     861           41369 : static PRUint32 xtolong (const PRUint8 *ll)
     862                 : {
     863           41369 :   return (PRUint32)( (ll [0] <<  0) |
     864           41369 :                      (ll [1] <<  8) |
     865           41369 :                      (ll [2] << 16) |
     866          124107 :                      (ll [3] << 24) );
     867                 : }
     868                 : 
     869                 : /*
     870                 :  * GetModTime
     871                 :  *
     872                 :  * returns last modification time in microseconds
     873                 :  */
     874               0 : static PRTime GetModTime(PRUint16 aDate, PRUint16 aTime)
     875                 : {
     876                 :   // Note that on DST shift we can't handle correctly the hour that is valid
     877                 :   // in both DST zones
     878                 :   PRExplodedTime time;
     879                 : 
     880               0 :   time.tm_usec = 0;
     881                 : 
     882               0 :   time.tm_hour = (aTime >> 11) & 0x1F;
     883               0 :   time.tm_min = (aTime >> 5) & 0x3F;
     884               0 :   time.tm_sec = (aTime & 0x1F) * 2;
     885                 : 
     886               0 :   time.tm_year = (aDate >> 9) + 1980;
     887               0 :   time.tm_month = ((aDate >> 5) & 0x0F) - 1;
     888               0 :   time.tm_mday = aDate & 0x1F;
     889                 : 
     890               0 :   time.tm_params.tp_gmt_offset = 0;
     891               0 :   time.tm_params.tp_dst_offset = 0;
     892                 : 
     893               0 :   PR_NormalizeTime(&time, PR_GMTParameters);
     894               0 :   time.tm_params.tp_gmt_offset = PR_LocalTimeParameters(&time).tp_gmt_offset;
     895               0 :   PR_NormalizeTime(&time, PR_GMTParameters);
     896               0 :   time.tm_params.tp_dst_offset = PR_LocalTimeParameters(&time).tp_dst_offset;
     897                 : 
     898               0 :   return PR_ImplodeTime(&time);
     899                 : }
     900                 : 
     901            2072 : PRUint32 nsZipItem::LocalOffset()
     902                 : {
     903            2072 :   return xtolong(central->localhdr_offset);
     904                 : }
     905                 : 
     906            5642 : PRUint32 nsZipItem::Size()
     907                 : {
     908            5642 :   return isSynthetic ? 0 : xtolong(central->size);
     909                 : }
     910                 : 
     911            2847 : PRUint32 nsZipItem::RealSize()
     912                 : {
     913            2847 :   return isSynthetic ? 0 : xtolong(central->orglen);
     914                 : }
     915                 : 
     916            3540 : PRUint32 nsZipItem::CRC32()
     917                 : {
     918            3540 :   return isSynthetic ? 0 : xtolong(central->crc32);
     919                 : }
     920                 : 
     921               0 : PRUint16 nsZipItem::Date()
     922                 : {
     923               0 :   return isSynthetic ? kSyntheticDate : xtoint(central->date);
     924                 : }
     925                 : 
     926               0 : PRUint16 nsZipItem::Time()
     927                 : {
     928               0 :   return isSynthetic ? kSyntheticTime : xtoint(central->time);
     929                 : }
     930                 : 
     931            5655 : PRUint16 nsZipItem::Compression()
     932                 : {
     933            5655 :   return isSynthetic ? STORED : xtoint(central->method);
     934                 : }
     935                 : 
     936            4254 : bool nsZipItem::IsDirectory()
     937                 : {
     938            4254 :   return isSynthetic || ((nameLength > 0) && ('/' == Name()[nameLength - 1]));
     939                 : }
     940                 : 
     941             716 : PRUint16 nsZipItem::Mode()
     942                 : {
     943             716 :   if (isSynthetic) return 0755;
     944             716 :   return ((PRUint16)(central->external_attributes[2]) | 0x100);
     945                 : }
     946                 : 
     947            2216 : const PRUint8 * nsZipItem::GetExtraField(PRUint16 aTag, PRUint16 *aBlockSize)
     948                 : {
     949            2216 :   if (isSynthetic) return nsnull;
     950                 : MOZ_WIN_MEM_TRY_BEGIN
     951                 :   const unsigned char *buf = ((const unsigned char*)central) + ZIPCENTRAL_SIZE +
     952            2216 :                              nameLength;
     953            2216 :   PRUint32 buflen = (PRUint32)xtoint(central->extrafield_len);
     954            2216 :   PRUint32 pos = 0;
     955                 :   PRUint16 tag, blocksize;
     956                 : 
     957            4432 :   while (buf && (pos + 4) <= buflen) {
     958            2216 :     tag = xtoint(buf + pos);
     959            2216 :     blocksize = xtoint(buf + pos + 2);
     960                 : 
     961            2216 :     if (aTag == tag && (pos + 4 + blocksize) <= buflen) {
     962            2216 :       *aBlockSize = blocksize;
     963            2216 :       return buf + pos;
     964                 :     }
     965                 : 
     966               0 :     pos += blocksize + 4;
     967                 :   }
     968                 : 
     969                 : MOZ_WIN_MEM_TRY_CATCH(return nsnull)
     970               0 :   return nsnull;
     971                 : }
     972                 : 
     973                 : 
     974            2216 : PRTime nsZipItem::LastModTime()
     975                 : {
     976            2216 :   if (isSynthetic) return GetModTime(kSyntheticDate, kSyntheticTime);
     977                 : 
     978                 :   // Try to read timestamp from extra field
     979                 :   PRUint16 blocksize;
     980            2216 :   const PRUint8 *tsField = GetExtraField(EXTENDED_TIMESTAMP_FIELD, &blocksize);
     981            2216 :   if (tsField && blocksize >= 5 && tsField[4] & EXTENDED_TIMESTAMP_MODTIME) {
     982            2216 :     return (PRTime)(xtolong(tsField + 5)) * PR_USEC_PER_SEC;
     983                 :   }
     984                 : 
     985               0 :   return GetModTime(Date(), Time());
     986                 : }
     987                 : 
     988                 : #ifdef XP_UNIX
     989             716 : bool nsZipItem::IsSymlink()
     990                 : {
     991             716 :   if (isSynthetic) return false;
     992             716 :   return (xtoint(central->external_attributes+2) & S_IFMT) == S_IFLNK;
     993                 : }
     994                 : #endif
     995                 : 
     996             784 : nsZipCursor::nsZipCursor(nsZipItem *item, nsZipArchive *aZip, PRUint8* aBuf, PRUint32 aBufSize, bool doCRC) :
     997                 :   mItem(item),
     998                 :   mBuf(aBuf),
     999                 :   mBufSize(aBufSize),
    1000             784 :   mDoCRC(doCRC)
    1001                 : {
    1002             784 :   if (mItem->Compression() == DEFLATED) {
    1003                 : #ifdef DEBUG
    1004                 :     nsresult status =
    1005                 : #endif
    1006             389 :       gZlibInit(&mZs);
    1007             389 :     NS_ASSERTION(status == NS_OK, "Zlib failed to initialize");
    1008             389 :     NS_ASSERTION(aBuf, "Must pass in a buffer for DEFLATED nsZipItem");
    1009                 :   }
    1010                 :   
    1011             784 :   mZs.avail_in = item->Size();
    1012             784 :   mZs.next_in = (Bytef*)aZip->GetData(item);
    1013                 :   
    1014             784 :   if (doCRC)
    1015             738 :     mCRC = crc32(0L, Z_NULL, 0);
    1016             784 : }
    1017                 : 
    1018             784 : nsZipCursor::~nsZipCursor()
    1019                 : {
    1020             784 :   if (mItem->Compression() == DEFLATED) {
    1021             389 :     inflateEnd(&mZs);
    1022                 :   }
    1023             784 : }
    1024                 : 
    1025            1252 : PRUint8* nsZipCursor::ReadOrCopy(PRUint32 *aBytesRead, bool aCopy) {
    1026                 :   int zerr;
    1027            1252 :   PRUint8 *buf = nsnull;
    1028            1252 :   bool verifyCRC = true;
    1029                 : 
    1030            1252 :   if (!mZs.next_in)
    1031               0 :     return nsnull;
    1032                 : MOZ_WIN_MEM_TRY_BEGIN
    1033            1252 :   switch (mItem->Compression()) {
    1034                 :   case STORED:
    1035             487 :     if (!aCopy) {
    1036             485 :       *aBytesRead = mZs.avail_in;
    1037             485 :       buf = mZs.next_in;
    1038             485 :       mZs.next_in += mZs.avail_in;
    1039             485 :       mZs.avail_in = 0;
    1040                 :     } else {
    1041               2 :       *aBytesRead = mZs.avail_in > mBufSize ? mBufSize : mZs.avail_in;
    1042               2 :       memcpy(mBuf, mZs.next_in, *aBytesRead);
    1043               2 :       mZs.avail_in -= *aBytesRead;
    1044               2 :       mZs.next_in += *aBytesRead;
    1045                 :     }
    1046             487 :     break;
    1047                 :   case DEFLATED:
    1048             765 :     buf = mBuf;
    1049             765 :     mZs.next_out = buf;
    1050             765 :     mZs.avail_out = mBufSize;
    1051                 :     
    1052             765 :     zerr = inflate(&mZs, Z_PARTIAL_FLUSH);
    1053             765 :     if (zerr != Z_OK && zerr != Z_STREAM_END)
    1054               0 :       return nsnull;
    1055                 :     
    1056             765 :     *aBytesRead = mZs.next_out - buf;
    1057             765 :     verifyCRC = (zerr == Z_STREAM_END);
    1058             765 :     break;
    1059                 :   default:
    1060               0 :     return nsnull;
    1061                 :   }
    1062                 : 
    1063            1252 :   if (mDoCRC) {
    1064            1206 :     mCRC = crc32(mCRC, (const unsigned char*)buf, *aBytesRead);
    1065            1206 :     if (verifyCRC && mCRC != mItem->CRC32())
    1066               2 :       return nsnull;
    1067                 :   }
    1068                 : MOZ_WIN_MEM_TRY_CATCH(return nsnull)
    1069            1250 :   return buf;
    1070                 : }
    1071                 : 
    1072              48 : nsZipItemPtr_base::nsZipItemPtr_base(nsZipArchive *aZip, const char * aEntryName, bool doCRC) :
    1073              48 :   mReturnBuf(nsnull)
    1074                 : {
    1075                 :   // make sure the ziparchive hangs around
    1076              48 :   mZipHandle = aZip->GetFD();
    1077                 : 
    1078              48 :   nsZipItem* item = aZip->GetItem(aEntryName);
    1079              48 :   if (!item)
    1080               1 :     return;
    1081                 : 
    1082              47 :   PRUint32 size = 0;
    1083              47 :   if (item->Compression() == DEFLATED) {
    1084               7 :     size = item->RealSize();
    1085              14 :     mAutoBuf = new PRUint8[size];
    1086                 :   }
    1087                 : 
    1088              94 :   nsZipCursor cursor(item, aZip, mAutoBuf, size, doCRC);
    1089              47 :   mReturnBuf = cursor.Read(&mReadlen);
    1090              47 :   if (!mReturnBuf) {
    1091                 :     return;
    1092                 :   }
    1093                 : 
    1094              47 :   if (mReadlen != item->RealSize()) {
    1095               0 :     NS_ASSERTION(mReadlen == item->RealSize(), "nsZipCursor underflow");
    1096               0 :     mReturnBuf = nsnull;
    1097                 :     return;
    1098                 :   }
    1099                 : }

Generated by: LCOV version 1.7