modules/libjar/nsZipArchive.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/modules/libjar/nsZipArchive.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,403 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef nsZipArchive_h_
    1.10 +#define nsZipArchive_h_
    1.11 +
    1.12 +#include "mozilla/Attributes.h"
    1.13 +
    1.14 +#define ZIP_TABSIZE   256
    1.15 +#define ZIP_BUFLEN    (4*1024)      /* Used as output buffer when deflating items to a file */
    1.16 +
    1.17 +#include "plarena.h"
    1.18 +#include "zlib.h"
    1.19 +#include "zipstruct.h"
    1.20 +#include "nsAutoPtr.h"
    1.21 +#include "nsIFile.h"
    1.22 +#include "nsISupportsImpl.h" // For mozilla::ThreadSafeAutoRefCnt
    1.23 +#include "mozilla/FileUtils.h"
    1.24 +#include "mozilla/FileLocation.h"
    1.25 +
    1.26 +#if defined(XP_WIN) && defined(_MSC_VER)
    1.27 +#define MOZ_WIN_MEM_TRY_BEGIN __try {
    1.28 +#define MOZ_WIN_MEM_TRY_CATCH(cmd) }                                \
    1.29 +  __except(GetExceptionCode()==EXCEPTION_IN_PAGE_ERROR ?            \
    1.30 +           EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)   \
    1.31 +  {                                                                 \
    1.32 +    NS_WARNING("EXCEPTION_IN_PAGE_ERROR in " __FUNCTION__);         \
    1.33 +    cmd;                                                            \
    1.34 +  }
    1.35 +#else
    1.36 +#define MOZ_WIN_MEM_TRY_BEGIN {
    1.37 +#define MOZ_WIN_MEM_TRY_CATCH(cmd) }
    1.38 +#endif
    1.39 +
    1.40 +class nsZipFind;
    1.41 +struct PRFileDesc;
    1.42 +
    1.43 +/**
    1.44 + * This file defines some of the basic structures used by libjar to
    1.45 + * read Zip files. It makes use of zlib in order to do the decompression.
    1.46 + *
    1.47 + * A few notes on the classes/structs:
    1.48 + * nsZipArchive   represents a single Zip file, and maintains an index
    1.49 + *                of all the items in the file.
    1.50 + * nsZipItem      represents a single item (file) in the Zip archive.
    1.51 + * nsZipFind      represents the metadata involved in doing a search,
    1.52 + *                and current state of the iteration of found objects.
    1.53 + * 'MT''safe' reading from the zipfile is performed through JARInputStream,
    1.54 + * which maintains its own file descriptor, allowing for multiple reads 
    1.55 + * concurrently from the same zip file.
    1.56 + */
    1.57 +
    1.58 +/**
    1.59 + * nsZipItem -- a helper struct for nsZipArchive
    1.60 + *
    1.61 + * each nsZipItem represents one file in the archive and all the
    1.62 + * information needed to manipulate it.
    1.63 + */
    1.64 +class nsZipItem
    1.65 +{
    1.66 +public:
    1.67 +  const char* Name() { return ((const char*)central) + ZIPCENTRAL_SIZE; }
    1.68 +
    1.69 +  uint32_t LocalOffset();
    1.70 +  uint32_t Size();
    1.71 +  uint32_t RealSize();
    1.72 +  uint32_t CRC32();
    1.73 +  uint16_t Date();
    1.74 +  uint16_t Time();
    1.75 +  uint16_t Compression();
    1.76 +  bool     IsDirectory();
    1.77 +  uint16_t Mode();
    1.78 +  const uint8_t* GetExtraField(uint16_t aTag, uint16_t *aBlockSize);
    1.79 +  PRTime   LastModTime();
    1.80 +
    1.81 +#ifdef XP_UNIX
    1.82 +  bool     IsSymlink();
    1.83 +#endif
    1.84 +
    1.85 +  nsZipItem*         next;
    1.86 +  const ZipCentral*  central;
    1.87 +  uint16_t           nameLength;
    1.88 +  bool               isSynthetic;
    1.89 +};
    1.90 +
    1.91 +class nsZipHandle;
    1.92 +
    1.93 +/** 
    1.94 + * nsZipArchive -- a class for reading the PKZIP file format.
    1.95 + *
    1.96 + */
    1.97 +class nsZipArchive 
    1.98 +{
    1.99 +  friend class nsZipFind;
   1.100 +
   1.101 +public:
   1.102 +  /** constructing does not open the archive. See OpenArchive() */
   1.103 +  nsZipArchive();
   1.104 +
   1.105 +  /** destructing the object closes the archive */
   1.106 +  ~nsZipArchive();
   1.107 +
   1.108 +  /** 
   1.109 +   * OpenArchive 
   1.110 +   * 
   1.111 +   * It's an error to call this more than once on the same nsZipArchive
   1.112 +   * object. If we were allowed to use exceptions this would have been 
   1.113 +   * part of the constructor 
   1.114 +   *
   1.115 +   * @param   aZipHandle  The nsZipHandle used to access the zip
   1.116 +   * @param   aFd         Optional PRFileDesc for Windows readahead optimization
   1.117 +   * @return  status code
   1.118 +   */
   1.119 +  nsresult OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd = nullptr);
   1.120 +
   1.121 +  /** 
   1.122 +   * OpenArchive 
   1.123 +   * 
   1.124 +   * Convenience function that generates nsZipHandle
   1.125 +   *
   1.126 +   * @param   aFile  The file used to access the zip
   1.127 +   * @return  status code
   1.128 +   */
   1.129 +  nsresult OpenArchive(nsIFile *aFile);
   1.130 +
   1.131 +  /**
   1.132 +   * Test the integrity of items in this archive by running
   1.133 +   * a CRC check after extracting each item into a memory 
   1.134 +   * buffer.  If an entry name is supplied only the 
   1.135 +   * specified item is tested.  Else, if null is supplied
   1.136 +   * then all the items in the archive are tested.
   1.137 +   *
   1.138 +   * @return  status code       
   1.139 +   */
   1.140 +  nsresult Test(const char *aEntryName);
   1.141 +
   1.142 +  /**
   1.143 +   * Closes an open archive.
   1.144 +   */
   1.145 +  nsresult CloseArchive();
   1.146 +
   1.147 +  /** 
   1.148 +   * GetItem
   1.149 +   * @param   aEntryName Name of file in the archive
   1.150 +   * @return  pointer to nsZipItem
   1.151 +   */  
   1.152 +  nsZipItem* GetItem(const char * aEntryName);
   1.153 +  
   1.154 +  /** 
   1.155 +   * ExtractFile
   1.156 +   *
   1.157 +   * @param   zipEntry   Name of file in archive to extract
   1.158 +   * @param   outFD      Filedescriptor to write contents to
   1.159 +   * @param   outname    Name of file to write to
   1.160 +   * @return  status code
   1.161 +   */
   1.162 +  nsresult ExtractFile(nsZipItem * zipEntry, const char *outname, PRFileDesc * outFD);
   1.163 +
   1.164 +  /**
   1.165 +   * FindInit
   1.166 +   *
   1.167 +   * Initializes a search for files in the archive. FindNext() returns
   1.168 +   * the actual matches. The nsZipFind must be deleted when you're done
   1.169 +   *
   1.170 +   * @param   aPattern    a string or RegExp pattern to search for
   1.171 +   *                      (may be nullptr to find all files in archive)
   1.172 +   * @param   aFind       a pointer to a pointer to a structure used
   1.173 +   *                      in FindNext.  In the case of an error this
   1.174 +   *                      will be set to nullptr.
   1.175 +   * @return  status code
   1.176 +   */
   1.177 +  nsresult FindInit(const char * aPattern, nsZipFind** aFind);
   1.178 +
   1.179 +  /*
   1.180 +   * Gets an undependent handle to the mapped file.
   1.181 +   */
   1.182 +  nsZipHandle* GetFD();
   1.183 +
   1.184 +  /**
   1.185 +   * Get pointer to the data of the item.
   1.186 +   * @param   aItem       Pointer to nsZipItem
   1.187 +   * reutrns null when zip file is corrupt.
   1.188 +   */
   1.189 +  const uint8_t* GetData(nsZipItem* aItem);
   1.190 +
   1.191 +  bool GetComment(nsACString &aComment);
   1.192 +
   1.193 +  /**
   1.194 +   * Gets the amount of memory taken up by the archive's mapping.
   1.195 +   * @return the size
   1.196 +   */
   1.197 +  int64_t SizeOfMapping();
   1.198 +
   1.199 +  /*
   1.200 +   * Refcounting
   1.201 +   */
   1.202 +  NS_METHOD_(MozExternalRefCountType) AddRef(void);
   1.203 +  NS_METHOD_(MozExternalRefCountType) Release(void);
   1.204 +
   1.205 +private:
   1.206 +  //--- private members ---
   1.207 +  mozilla::ThreadSafeAutoRefCnt mRefCnt; /* ref count */
   1.208 +  NS_DECL_OWNINGTHREAD
   1.209 +
   1.210 +  nsZipItem*    mFiles[ZIP_TABSIZE];
   1.211 +  PLArenaPool   mArena;
   1.212 +
   1.213 +  const char*   mCommentPtr;
   1.214 +  uint16_t      mCommentLen;
   1.215 +
   1.216 +  // Whether we synthesized the directory entries
   1.217 +  bool          mBuiltSynthetics;
   1.218 +
   1.219 +  // file handle
   1.220 +  nsRefPtr<nsZipHandle> mFd;
   1.221 +
   1.222 +  // file URI, for logging
   1.223 +  nsCString mURI;
   1.224 +
   1.225 +private:
   1.226 +  //--- private methods ---
   1.227 +  nsZipItem*        CreateZipItem();
   1.228 +  nsresult          BuildFileList(PRFileDesc *aFd = nullptr);
   1.229 +  nsresult          BuildSynthetics();
   1.230 +
   1.231 +  nsZipArchive& operator=(const nsZipArchive& rhs) MOZ_DELETE;
   1.232 +  nsZipArchive(const nsZipArchive& rhs) MOZ_DELETE;
   1.233 +};
   1.234 +
   1.235 +/** 
   1.236 + * nsZipFind 
   1.237 + *
   1.238 + * a helper class for nsZipArchive, representing a search
   1.239 + */
   1.240 +class nsZipFind
   1.241 +{
   1.242 +public:
   1.243 +  nsZipFind(nsZipArchive* aZip, char* aPattern, bool regExp);
   1.244 +  ~nsZipFind();
   1.245 +
   1.246 +  nsresult      FindNext(const char** aResult, uint16_t* aNameLen);
   1.247 +
   1.248 +private:
   1.249 +  nsRefPtr<nsZipArchive> mArchive;
   1.250 +  char*         mPattern;
   1.251 +  nsZipItem*    mItem;
   1.252 +  uint16_t      mSlot;
   1.253 +  bool          mRegExp;
   1.254 +
   1.255 +  nsZipFind& operator=(const nsZipFind& rhs) MOZ_DELETE;
   1.256 +  nsZipFind(const nsZipFind& rhs) MOZ_DELETE;
   1.257 +};
   1.258 +
   1.259 +/** 
   1.260 + * nsZipCursor -- a low-level class for reading the individual items in a zip.
   1.261 + */
   1.262 +class nsZipCursor {
   1.263 +public:
   1.264 +  /**
   1.265 +   * Initializes the cursor
   1.266 +   *
   1.267 +   * @param   aItem       Item of interest
   1.268 +   * @param   aZip        Archive
   1.269 +   * @param   aBuf        Buffer used for decompression.
   1.270 +   *                      This determines the maximum Read() size in the compressed case.
   1.271 +   * @param   aBufSize    Buffer size
   1.272 +   * @param   doCRC       When set to true Read() will check crc
   1.273 +   */
   1.274 +  nsZipCursor(nsZipItem *aItem, nsZipArchive *aZip, uint8_t* aBuf = nullptr, uint32_t aBufSize = 0, bool doCRC = false);
   1.275 +
   1.276 +  ~nsZipCursor();
   1.277 +
   1.278 +  /**
   1.279 +   * Performs reads. In the compressed case it uses aBuf(passed in constructor), for stored files
   1.280 +   * it returns a zero-copy buffer.
   1.281 +   *
   1.282 +   * @param   aBytesRead  Outparam for number of bytes read.
   1.283 +   * @return  data read or nullptr if item is corrupted.
   1.284 +   */
   1.285 +  uint8_t* Read(uint32_t *aBytesRead) {
   1.286 +    return ReadOrCopy(aBytesRead, false);
   1.287 +  }
   1.288 +
   1.289 +  /**
   1.290 +   * Performs a copy. It always uses aBuf(passed in constructor).
   1.291 +   *
   1.292 +   * @param   aBytesRead  Outparam for number of bytes read.
   1.293 +   * @return  data read or nullptr if item is corrupted.
   1.294 +   */
   1.295 +  uint8_t* Copy(uint32_t *aBytesRead) {
   1.296 +    return ReadOrCopy(aBytesRead, true);
   1.297 +  }
   1.298 +
   1.299 +private:
   1.300 +  /* Actual implementation for both Read and Copy above */
   1.301 +  uint8_t* ReadOrCopy(uint32_t *aBytesRead, bool aCopy);
   1.302 +
   1.303 +  nsZipItem *mItem; 
   1.304 +  uint8_t  *mBuf; 
   1.305 +  uint32_t  mBufSize; 
   1.306 +  z_stream  mZs;
   1.307 +  uint32_t mCRC;
   1.308 +  bool mDoCRC;
   1.309 +};
   1.310 +
   1.311 +/**
   1.312 + * nsZipItemPtr - a RAII convenience class for reading the individual items in a zip.
   1.313 + * It reads whole files and does zero-copy IO for stored files. A buffer is allocated
   1.314 + * for decompression.
   1.315 + * Do not use when the file may be very large.
   1.316 + */
   1.317 +class nsZipItemPtr_base {
   1.318 +public:
   1.319 +  /**
   1.320 +   * Initializes the reader
   1.321 +   *
   1.322 +   * @param   aZip        Archive
   1.323 +   * @param   aEntryName  Archive membername
   1.324 +   * @param   doCRC       When set to true Read() will check crc
   1.325 +   */
   1.326 +  nsZipItemPtr_base(nsZipArchive *aZip, const char *aEntryName, bool doCRC);
   1.327 +
   1.328 +  uint32_t Length() const {
   1.329 +    return mReadlen;
   1.330 +  }
   1.331 +
   1.332 +protected:
   1.333 +  nsRefPtr<nsZipHandle> mZipHandle;
   1.334 +  nsAutoArrayPtr<uint8_t> mAutoBuf;
   1.335 +  uint8_t *mReturnBuf;
   1.336 +  uint32_t mReadlen;
   1.337 +};
   1.338 +
   1.339 +template <class T>
   1.340 +class nsZipItemPtr : public nsZipItemPtr_base {
   1.341 +public:
   1.342 +  nsZipItemPtr(nsZipArchive *aZip, const char *aEntryName, bool doCRC = false) : nsZipItemPtr_base(aZip, aEntryName, doCRC) { }
   1.343 +  /**
   1.344 +   * @return buffer containing the whole zip member or nullptr on error.
   1.345 +   * The returned buffer is owned by nsZipItemReader.
   1.346 +   */
   1.347 +  const T* Buffer() const {
   1.348 +    return (const T*)mReturnBuf;
   1.349 +  }
   1.350 +
   1.351 +  operator const T*() const {
   1.352 +    return Buffer();
   1.353 +  }
   1.354 +
   1.355 +  /**
   1.356 +   * Relinquish ownership of zip member if compressed.
   1.357 +   * Copy member into a new buffer if uncompressed.
   1.358 +   * @return a buffer with whole zip member. It is caller's responsibility to free() it.
   1.359 +   */
   1.360 +  T* Forget() {
   1.361 +    if (!mReturnBuf)
   1.362 +      return nullptr;
   1.363 +    // In uncompressed mmap case, give up buffer
   1.364 +    if (mAutoBuf.get() == mReturnBuf) {
   1.365 +      mReturnBuf = nullptr;
   1.366 +      return (T*) mAutoBuf.forget();
   1.367 +    }
   1.368 +    T *ret = (T*) malloc(Length());
   1.369 +    memcpy(ret, mReturnBuf, Length());
   1.370 +    mReturnBuf = nullptr;
   1.371 +    return ret;
   1.372 +  }
   1.373 +};
   1.374 +
   1.375 +class nsZipHandle {
   1.376 +friend class nsZipArchive;
   1.377 +friend class mozilla::FileLocation;
   1.378 +public:
   1.379 +  static nsresult Init(nsIFile *file, nsZipHandle **ret,
   1.380 +                       PRFileDesc **aFd = nullptr);
   1.381 +  static nsresult Init(nsZipArchive *zip, const char *entry,
   1.382 +                       nsZipHandle **ret);
   1.383 +
   1.384 +  NS_METHOD_(MozExternalRefCountType) AddRef(void);
   1.385 +  NS_METHOD_(MozExternalRefCountType) Release(void);
   1.386 +
   1.387 +  int64_t SizeOfMapping();
   1.388 +
   1.389 +protected:
   1.390 +  const uint8_t * mFileData; /* pointer to mmaped file */
   1.391 +  uint32_t        mLen;      /* length of file and memory mapped area */
   1.392 +  mozilla::FileLocation mFile; /* source file if any, for logging */
   1.393 +
   1.394 +private:
   1.395 +  nsZipHandle();
   1.396 +  ~nsZipHandle();
   1.397 +
   1.398 +  PRFileMap *                       mMap;    /* nspr datastructure for mmap */
   1.399 +  nsAutoPtr<nsZipItemPtr<uint8_t> > mBuf;
   1.400 +  mozilla::ThreadSafeAutoRefCnt     mRefCnt; /* ref count */
   1.401 +  NS_DECL_OWNINGTHREAD
   1.402 +};
   1.403 +
   1.404 +nsresult gZlibInit(z_stream *zs);
   1.405 +
   1.406 +#endif /* nsZipArchive_h_ */

mercurial