mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Insert directory entries into a SortedTree for searching.
This commit is contained in:
parent
4f1d3174f2
commit
5ca08c04d2
@ -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;
|
||||
|
@ -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<DirectoryEntry> {
|
||||
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<DirectoryEntry,DirectoryEntry_Key> 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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user