mozglue/linker/Zip.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef Zip_h
     6 #define Zip_h
     8 #include <cstring>
     9 #include <stdint.h>
    10 #include <vector>
    11 #include <zlib.h>
    12 #include "Utils.h"
    13 #include "mozilla/RefPtr.h"
    15 /**
    16  * Forward declaration
    17  */
    18 class ZipCollection;
    20 /**
    21  * Class to handle access to Zip archive streams. The Zip archive is mapped
    22  * in memory, and streams are direct references to that mapped memory.
    23  * Zip files are assumed to be correctly formed. No boundary checks are
    24  * performed, which means hand-crafted malicious Zip archives can make the
    25  * code fail in bad ways. However, since the only intended use is to load
    26  * libraries from Zip archives, there is no interest in making this code
    27  * safe, since the libraries could contain malicious code anyways.
    28  */
    29 class Zip: public mozilla::AtomicRefCounted<Zip>
    30 {
    31 public:
    32   MOZ_DECLARE_REFCOUNTED_TYPENAME(Zip)
    33   /**
    34    * Create a Zip instance for the given file name. Returns nullptr in case
    35    * of failure.
    36    */
    37   static mozilla::TemporaryRef<Zip> Create(const char *filename);
    39   /**
    40    * Create a Zip instance using the given buffer.
    41    */
    42   static mozilla::TemporaryRef<Zip> Create(void *buffer, size_t size) {
    43     return Create(nullptr, buffer, size);
    44   }
    46 private:
    47   static mozilla::TemporaryRef<Zip> Create(const char *filename,
    48                                            void *buffer, size_t size);
    50   /**
    51    * Private constructor
    52    */
    53   Zip(const char *filename, void *buffer, size_t size);
    55 public:
    56   /**
    57    * Destructor
    58    */
    59   ~Zip();
    61   /**
    62    * Class used to access Zip archive item streams
    63    */
    64   class Stream
    65   {
    66   public:
    67     /**
    68      * Stream types
    69      */
    70     enum Type {
    71       STORE = 0,
    72       DEFLATE = 8
    73     };
    75     /**
    76      * Constructor
    77      */
    78     Stream(): compressedBuf(nullptr), compressedSize(0), uncompressedSize(0)
    79             , type(STORE) { }
    81     /**
    82      * Getters
    83      */
    84     const void *GetBuffer() { return compressedBuf; }
    85     size_t GetSize() { return compressedSize; }
    86     size_t GetUncompressedSize() { return uncompressedSize; }
    87     Type GetType() { return type; }
    89     /**
    90      * Returns a z_stream for use with inflate functions using the given
    91      * buffer as inflate output. The caller is expected to allocate enough
    92      * memory for the Stream uncompressed size.
    93      */
    94     z_stream GetZStream(void *buf)
    95     {
    96       z_stream zStream;
    97       memset(&zStream, 0, sizeof(zStream));
    98       zStream.avail_in = compressedSize;
    99       zStream.next_in = reinterpret_cast<Bytef *>(
   100                         const_cast<void *>(compressedBuf));
   101       zStream.avail_out = uncompressedSize;
   102       zStream.next_out = static_cast<Bytef *>(buf);
   103       return zStream;
   104     }
   106   protected:
   107     friend class Zip;
   108     const void *compressedBuf;
   109     size_t compressedSize;
   110     size_t uncompressedSize;
   111     Type type;
   112   };
   114   /**
   115    * Returns a stream from the Zip archive.
   116    */
   117   bool GetStream(const char *path, Stream *out) const;
   119   /**
   120    * Returns the file name of the archive
   121    */
   122   const char *GetName() const
   123   {
   124     return name;
   125   }
   127 private:
   128   /* File name of the archive */
   129   char *name;
   130   /* Address where the Zip archive is mapped */
   131   void *mapped;
   132   /* Size of the archive */
   133   size_t size;
   135   /**
   136    * Strings (file names, comments, etc.) in the Zip headers are NOT zero
   137    * terminated. This class is a helper around them.
   138    */
   139   class StringBuf
   140   {
   141   public:
   142     /**
   143      * Constructor
   144      */
   145     StringBuf(const char *buf, size_t length): buf(buf), length(length) { }
   147     /**
   148      * Returns whether the string has the same content as the given zero
   149      * terminated string.
   150      */
   151     bool Equals(const char *str) const
   152     {
   153       return strncmp(str, buf, length) == 0;
   154     }
   156   private:
   157     const char *buf;
   158     size_t length;
   159   };
   161 /* All the following types need to be packed */
   162 #pragma pack(1)
   163 public:
   164   /**
   165    * A Zip archive is an aggregate of entities which all start with a
   166    * signature giving their type. This template is to be used as a base
   167    * class for these entities.
   168    */
   169   template <typename T>
   170   class SignedEntity
   171   {
   172   public:
   173     /**
   174      * Equivalent to reinterpret_cast<const T *>(buf), with an additional
   175      * check of the signature.
   176      */
   177     static const T *validate(const void *buf)
   178     {
   179       const T *ret = static_cast<const T *>(buf);
   180       if (ret->signature == T::magic)
   181         return ret;
   182       return nullptr;
   183     }
   185     SignedEntity(uint32_t magic): signature(magic) { }
   186   private:
   187     le_uint32 signature;
   188   };
   190 private:
   191   /**
   192    * Header used to describe a Local File entry. The header is followed by
   193    * the file name and an extra field, then by the data stream.
   194    */
   195   struct LocalFile: public SignedEntity<LocalFile>
   196   {
   197     /* Signature for a Local File header */
   198     static const uint32_t magic = 0x04034b50;
   200     /**
   201      * Returns the file name
   202      */
   203     StringBuf GetName() const
   204     {
   205       return StringBuf(reinterpret_cast<const char *>(this) + sizeof(*this),
   206                        filenameSize);
   207     }
   209     /**
   210      * Returns a pointer to the data associated with this header
   211      */
   212     const void *GetData() const
   213     {
   214       return reinterpret_cast<const char *>(this) + sizeof(*this)
   215              + filenameSize + extraFieldSize;
   216     }
   218     le_uint16 minVersion;
   219     le_uint16 generalFlag;
   220     le_uint16 compression;
   221     le_uint16 lastModifiedTime;
   222     le_uint16 lastModifiedDate;
   223     le_uint32 CRC32;
   224     le_uint32 compressedSize;
   225     le_uint32 uncompressedSize;
   226     le_uint16 filenameSize;
   227     le_uint16 extraFieldSize;
   228   };
   230   /**
   231    * In some cases, when a zip archive is created, compressed size and CRC
   232    * are not known when writing the Local File header. In these cases, the
   233    * 3rd bit of the general flag in the Local File header is set, and there
   234    * is an additional header following the compressed data.
   235    */
   236   struct DataDescriptor: public SignedEntity<DataDescriptor>
   237   {
   238     /* Signature for a Data Descriptor header */
   239     static const uint32_t magic = 0x08074b50;
   241     le_uint32 CRC32;
   242     le_uint32 compressedSize;
   243     le_uint32 uncompressedSize;
   244   };
   246   /**
   247    * Header used to describe a Central Directory Entry. The header is
   248    * followed by the file name, an extra field, and a comment.
   249    */
   250   struct DirectoryEntry: public SignedEntity<DirectoryEntry>
   251   {
   252     /* Signature for a Central Directory Entry header */
   253     static const uint32_t magic = 0x02014b50;
   255     /**
   256      * Returns the file name
   257      */
   258     StringBuf GetName() const
   259     {
   260       return StringBuf(reinterpret_cast<const char *>(this) + sizeof(*this),
   261                        filenameSize);
   262     }
   264     /**
   265      * Returns  the Central Directory Entry following this one.
   266      */
   267     const DirectoryEntry *GetNext() const
   268     {
   269       return validate(reinterpret_cast<const char *>(this) + sizeof(*this)
   270                       + filenameSize + extraFieldSize + fileCommentSize);
   271     }
   273     le_uint16 creatorVersion;
   274     le_uint16 minVersion;
   275     le_uint16 generalFlag;
   276     le_uint16 compression;
   277     le_uint16 lastModifiedTime;
   278     le_uint16 lastModifiedDate;
   279     le_uint32 CRC32;
   280     le_uint32 compressedSize;
   281     le_uint32 uncompressedSize;
   282     le_uint16 filenameSize;
   283     le_uint16 extraFieldSize;
   284     le_uint16 fileCommentSize;
   285     le_uint16 diskNum;
   286     le_uint16 internalAttributes;
   287     le_uint32 externalAttributes;
   288     le_uint32 offset;
   289   };
   291   /**
   292    * Header used to describe the End of Central Directory Record.
   293    */
   294   struct CentralDirectoryEnd: public SignedEntity<CentralDirectoryEnd>
   295   {
   296     /* Signature for the End of Central Directory Record */
   297     static const uint32_t magic = 0x06054b50;
   299     le_uint16 diskNum;
   300     le_uint16 startDisk;
   301     le_uint16 recordsOnDisk;
   302     le_uint16 records;
   303     le_uint32 size;
   304     le_uint32 offset;
   305     le_uint16 commentSize;
   306   };
   307 #pragma pack()
   309   /**
   310    * Returns the first Directory entry
   311    */
   312   const DirectoryEntry *GetFirstEntry() const;
   314   /* Pointer to the Local File Entry following the last one GetStream() used.
   315    * This is used by GetStream to avoid scanning the Directory Entries when the
   316    * requested entry is that one. */
   317   mutable const LocalFile *nextFile;
   319   /* Likewise for the next Directory entry */
   320   mutable const DirectoryEntry *nextDir;
   322   /* Pointer to the Directory entries */
   323   mutable const DirectoryEntry *entries;
   324 };
   326 /**
   327  * Class for bookkeeping Zip instances
   328  */
   329 class ZipCollection
   330 {
   331 public:
   332   static ZipCollection Singleton;
   334   /**
   335    * Get a Zip instance for the given path. If there is an existing one
   336    * already, return that one, otherwise create a new one.
   337    */
   338   static mozilla::TemporaryRef<Zip> GetZip(const char *path);
   340 protected:
   341   friend class Zip;
   342   /**
   343    * Register the given Zip instance. This method is meant to be called
   344    * by Zip::Create.
   345    */
   346   static void Register(Zip *zip);
   348   /**
   349    * Forget about the given Zip instance. This method is meant to be called
   350    * by the Zip destructor.
   351    */
   352   static void Forget(Zip *zip);
   354 private:
   355   /* Zip instances bookkept in this collection */
   356   std::vector<Zip *> zips;
   357 };
   359 #endif /* Zip_h */

mercurial