diff --git a/mozilla/ef/Runtime/FileReader/ZipArchive.cpp b/mozilla/ef/Runtime/FileReader/ZipArchive.cpp index 11ea10016c2..c6cdce423b8 100644 --- a/mozilla/ef/Runtime/FileReader/ZipArchive.cpp +++ b/mozilla/ef/Runtime/FileReader/ZipArchive.cpp @@ -150,7 +150,7 @@ static void import(Internal_EndCentralDirectoryHeader *, /* Public functions */ ZipArchive::ZipArchive(const char *archiveName, Pool &pool, bool &status) - : pool(pool), dir(0) + : pool(pool) { status = true; @@ -166,17 +166,6 @@ ZipArchive::~ZipArchive() PR_Close(fp); } -const DirectoryEntry *ZipArchive::lookup(const char *fileName) -{ - Uint32 i; - - for (i = 0; i < nel; ++i) - if (PL_strcasecmp(dir[i].fn, fileName) == 0) - return &dir[i]; - - return NULL; -} - bool ZipArchive::get(const DirectoryEntry *dp, char *&buf, Int32 &len) { char *xbuf; @@ -201,36 +190,45 @@ bool ZipArchive::get(const DirectoryEntry *dp, char *&buf, Int32 &len) Uint32 ZipArchive::getNumElements(const char *fn_suffix) { int suf_len = strlen(fn_suffix); - Uint32 nelems; - Uint32 i; - - for (i=0, nelems=0; i < nel; i++) { - char *fn = dir[i].fn; + Uint32 nelems = 0; + DirectoryEntry *entry; + + entry = dir.firstNode(); + while (entry) { + const char *fn = entry->fn; int fn_len = strlen(fn); if (suf_len >= fn_len && PL_strncasecmp(&fn[fn_len - suf_len], fn_suffix, suf_len) == 0) { nelems++; } + entry = dir.next(entry); } + return nelems; } -Uint32 ZipArchive::listElements(const char *fn_suffix, char **&buf) +Uint32 ZipArchive::listElements(const char *fn_suffix, char **&rbuf) { int suf_len = strlen(fn_suffix); Uint32 nelems; Uint32 i; - buf = new (pool) char *[nel]; - + char **buf = new (pool) char *[nel]; + DirectoryEntry *entry; + + rbuf = buf; + entry = dir.firstNode(); + for (i=0, nelems=0; i < nel; i++) { - char *fn = dir[i].fn; + const char *fn = entry->fn; int fn_len = strlen(fn); if (fn_len >= suf_len && PL_strncasecmp(&fn[fn_len - suf_len], fn_suffix, suf_len) == 0) { buf[nelems] = dupString(fn, pool); nelems++; } + entry = dir.next(entry); } + return nelems; } @@ -244,6 +242,7 @@ bool ZipArchive::initReader() External_EndCentralDirectoryHeader ext_ehdr; Internal_EndCentralDirectoryHeader int_ehdr; char *central_directory, *cd_ptr; + DirectoryEntry *edir; PRInt32 pos; if (! findEnd()) @@ -271,35 +270,30 @@ bool ZipArchive::initReader() // Import all of the individual directory entries. nel = int_ehdr.total_entries_central_dir; - dir = new (pool) DirectoryEntry[nel]; + edir = new (pool) DirectoryEntry[nel]; cd_ptr = central_directory; for (int i = 0; i < nel; ++i) { Internal_CentralDirectoryHeader int_chdr; import(&int_chdr, *(External_CentralDirectoryHeader*)cd_ptr); - dir[i].len = int_chdr.uncompressed_size; - dir[i].size = int_chdr.compressed_size; - dir[i].method = int_chdr.compression_method; - dir[i].mod = 0; // FIXME - dir[i].off = (int_chdr.relative_offset_local_header - + sizeof(External_LocalFileHeader) - + int_chdr.filename_length - + int_chdr.file_comment_length - + int_chdr.extra_field_length); + edir[i].len = int_chdr.uncompressed_size; + edir[i].size = int_chdr.compressed_size; + edir[i].method = int_chdr.compression_method; + edir[i].mod = 0; // FIXME + edir[i].off = (int_chdr.relative_offset_local_header + + sizeof(External_LocalFileHeader) + + int_chdr.filename_length + + int_chdr.file_comment_length + + int_chdr.extra_field_length); // ??? Why is this extra 4 needed? infozip source is less than readable. if (int_chdr.extra_field_length) - dir[i].off += 4; + edir[i].off += 4; cd_ptr += sizeof(External_CentralDirectoryHeader); - dir[i].fn = cd_ptr; + edir[i].fn = cd_ptr; cd_ptr += int_chdr.filename_length; - cd_ptr += int_chdr.extra_field_length; - - // Sanity check the entry. - if (cd_ptr - central_directory > int_ehdr.size_central_directory) - return false; // Null terminate the filename at the expense of either the // extra_field_length padding, or the signature on the next @@ -308,7 +302,16 @@ bool ZipArchive::initReader() // FIXME -- do we care about transforming filenames as infozip // would have us do in the general case? - dir[i].fn[int_chdr.filename_length] = '\0'; + *cd_ptr = '\0'; + + cd_ptr += int_chdr.extra_field_length; + + // Sanity check the entry. + if (cd_ptr - central_directory > int_ehdr.size_central_directory) + return false; + + // Insert the entry into the tree. + dir.insert(edir[i]); } return true; diff --git a/mozilla/ef/Runtime/FileReader/ZipArchive.h b/mozilla/ef/Runtime/FileReader/ZipArchive.h index facb738d562..ab58e2d8743 100644 --- a/mozilla/ef/Runtime/FileReader/ZipArchive.h +++ b/mozilla/ef/Runtime/FileReader/ZipArchive.h @@ -20,40 +20,67 @@ #include "Fundamentals.h" #include "prio.h" +#include "plstr.h" +#include "Tree.h" /* * Central zip directory entry */ -typedef struct { - char *fn; /* file name */ - Uint32 len; /* file size */ - Uint32 size; /* file compressed size */ - Int32 method; /* Compression method */ - Int32 mod; /* file modification time */ - Int32 off; /* file contents offset */ -} DirectoryEntry; -/* An object that represents a zip archive */ +class DirectoryEntry_Key { +private: + const char * const str; + +public: + explicit DirectoryEntry_Key(const char *s) : str(s) { } + DirectoryEntry_Key(const DirectoryEntry_Key &other) : str(other.str) { } + + bool operator== (const DirectoryEntry_Key &other) const { + return PL_strcasecmp(str, other.str) == 0; + } + + bool operator< (const DirectoryEntry_Key &other) const { + return PL_strcasecmp(str, other.str) < 0; + } +}; + +struct DirectoryEntry : public TreeNode { + const char *fn; // file name + Uint32 len; // file size + Uint32 size; // file compressed size + Int32 method; // compression method + Int32 mod; // file modification time + Int32 off; // file contents offset + + // Bits to interface with the tree code. + DirectoryEntry_Key getKey() const { + return DirectoryEntry_Key(fn); + } +}; + + +/* + * An object that represents a zip archive. + */ + class ZipArchive { public: - /* Create a zip archive reader from a zip archive whose - * canonical pathname is archiveName. Pool is used to allocate - * memory for data structures. Sets status to true if it was - * able to successfully open the archive; returns false if - * it could not. - */ + // Create a zip archive reader from a zip archive whose + // canonical pathname is archiveName. Pool is used to allocate + // memory for data structures. Sets status to true if it was + // able to successfully open the archive; returns false if + // it could not. ZipArchive(const char *archiveName, Pool &pool, bool &status); ~ZipArchive(); - /* Read a file given by fileName from the zip archive into - * buf, allocating as much memory as necessary. This memory - * is allocated using the pool passed into the constructor - * and will go away when the pool is destroyed. On success, - * returns true and sets len to the length of the file read. - * Returns false if the file was not found in the archive, or - * if there was an error. - */ + // Read a file given by fileName from the zip archive into + // buf, allocating as much memory as necessary. This memory + // is allocated using the pool passed into the constructor + // and will go away when the pool is destroyed. On success, + // returns true and sets len to the length of the file read. + // Returns false if the file was not found in the archive, or + // if there was an error. bool get(const char *fileName, char *&buf, Int32 &len) { const DirectoryEntry *entry = lookup(fileName); @@ -63,47 +90,40 @@ public: return get(entry, buf, len); } - /* Exactly like get() above, but works with a directory entry - * obtained via lookup(). - */ + // Exactly like get() above, but works with a directory entry + // obtained via lookup(). bool get(const DirectoryEntry *entry, char *&buf, Int32 &len); - /* returns true if the given file exists in the archive, false - * otherwise. - */ + // Returns true if the given file exists in the archive, false + // otherwise. bool exists(const char *fileName) { return (lookup(fileName) != 0); } - /* lookup a file and return it's directory entry if it exists. - * If not, return false. - */ - const DirectoryEntry *lookup(const char *fileName); + // Lookup a file and return it's directory entry if it exists. + // If not, return false. + const DirectoryEntry *lookup(const char *fileName) { + return dir.find(DirectoryEntry_Key(fileName)); + } - /* Return number of elements in the zip archive whose filenames - * have the suffix indicated by fileNameSuffix. - */ + // Return number of elements in the zip archive whose filenames + // have the suffix indicated by fileNameSuffix. Uint32 getNumElements(const char *fileNameSuffix); - /* Gets the names of all elements in the zip archive whose filenames - * have the suffix indicated by fileNameSuffix. Returns the number - * of matching elements. Memory for buf is allocated using the - * pool passed into the constructor and is destroyed when the - * pool is destroyed. - */ + // Gets the names of all elements in the zip archive whose filenames + // have the suffix indicated by fileNameSuffix. Returns the number + // of matching elements. Memory for buf is allocated using the + // pool passed into the constructor and is destroyed when the + // pool is destroyed. Uint32 listElements(const char *fileNameSuffix, char **&buf); - private: - Pool &pool; /* Pool used to allocate internal memory */ - - /* File descriptor */ - PRFileDesc *fp; - - DirectoryEntry *dir; /* zip file directory */ - Uint32 nel; /* number of directory entries */ - Uint32 cenoff; /* Offset of central directory (CEN) */ - Uint32 endoff; /* Offset of end-of-central-directory record */ + Pool &pool; // Pool used to allocate internal memory + PRFileDesc *fp; // File descriptor + SortedTree dir; // zip file directory + Uint32 nel; // number of directory entries + Uint32 cenoff; // Offset of central directory (CEN) + Uint32 endoff; // Offset of end-of-central-directory record bool initReader(); bool findEnd(); @@ -111,5 +131,4 @@ private: bool inflateFully(Uint32 size, void *buf, Uint32 len); }; - #endif /* _ZIP_ARCHIVE_H_ */