Bug 511754 - make nsZipItems point at ZipCentral references to mmapped jar area r=tglek

This commit is contained in:
Alfred Kayser 2009-10-17 17:54:54 +02:00
parent 33365a4e60
commit 2f6c7190a3
5 changed files with 182 additions and 184 deletions

View File

@ -237,9 +237,9 @@ nsJAR::Extract(const char *zipEntry, nsIFile* outFile)
rv == NS_ERROR_FAILURE)
return rv;
if (item->isDirectory)
if (item->IsDirectory())
{
rv = localFile->Create(nsIFile::DIRECTORY_TYPE, item->mode);
rv = localFile->Create(nsIFile::DIRECTORY_TYPE, item->Mode());
//XXX Do this in nsZipArchive? It would be nice to keep extraction
//XXX code completely there, but that would require a way to get a
//XXX PRDir from localFile.
@ -247,7 +247,7 @@ nsJAR::Extract(const char *zipEntry, nsIFile* outFile)
else
{
PRFileDesc* fd;
rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, item->mode, &fd);
rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, item->Mode(), &fd);
if (NS_FAILED(rv)) return rv;
// ExtractFile also closes the fd handle and resolves the symlink if needed
@ -259,7 +259,7 @@ nsJAR::Extract(const char *zipEntry, nsIFile* outFile)
}
if (NS_FAILED(rv)) return rv;
PRTime prtime = GetModTime(item->date, item->time);
PRTime prtime = GetModTime(item->Date(), item->Time());
// nsIFile needs milliseconds, while prtime is in microseconds.
PRTime conversion = LL_ZERO;
PRTime newTime = LL_ZERO;
@ -336,7 +336,7 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
NS_ADDREF(*result = jis);
nsresult rv = NS_OK;
if (!item || item->isDirectory) {
if (!item || item->IsDirectory()) {
rv = jis->InitDirectory(this, aJarDirSpec, aEntryName);
} else {
rv = jis->InitFile(this, item);
@ -894,9 +894,9 @@ NS_IMETHODIMP
nsJAREnumerator::HasMore(PRBool* aResult)
{
// try to get the next element
if (!mCurr) {
if (!mName) {
NS_ASSERTION(mFind, "nsJAREnumerator: Missing zipFind.");
nsresult rv = mFind->FindNext( &mCurr );
nsresult rv = mFind->FindNext( &mName, &mNameLen );
if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
*aResult = PR_FALSE; // No more matches available
return NS_OK;
@ -915,14 +915,14 @@ NS_IMETHODIMP
nsJAREnumerator::GetNext(nsACString& aResult)
{
// check if the current item is "stale"
if (!mCurr) {
if (!mName) {
PRBool bMore;
nsresult rv = HasMore(&bMore);
if (NS_FAILED(rv) || !bMore)
return NS_ERROR_FAILURE; // no error translation
}
aResult = mCurr;
mCurr = 0; // we just gave this one away
aResult.Assign(mName, mNameLen);
mName = 0; // we just gave this one away
return NS_OK;
}
@ -930,13 +930,13 @@ nsJAREnumerator::GetNext(nsACString& aResult)
NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARItem, nsIZipEntry)
nsJARItem::nsJARItem(nsZipItem* aZipItem)
: mSize(aZipItem->size),
mRealsize(aZipItem->realsize),
mCrc32(aZipItem->crc32),
mDate(aZipItem->date),
mTime(aZipItem->time),
mCompression(aZipItem->compression),
mIsDirectory(aZipItem->isDirectory),
: mSize(aZipItem->Size()),
mRealsize(aZipItem->RealSize()),
mCrc32(aZipItem->CRC32()),
mDate(aZipItem->Date()),
mTime(aZipItem->Time()),
mCompression(aZipItem->Compression()),
mIsDirectory(aZipItem->IsDirectory()),
mIsSynthetic(aZipItem->isSynthetic)
{
}

View File

@ -186,7 +186,7 @@ private:
PRUint32 mCrc32;
PRUint16 mDate;
PRUint16 mTime;
PRUint8 mCompression;
PRUint16 mCompression;
PRPackedBool mIsDirectory;
PRPackedBool mIsSynthetic;
};
@ -203,13 +203,14 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIUTF8STRINGENUMERATOR
nsJAREnumerator(nsZipFind *aFind) : mFind(aFind), mCurr(nsnull) {
nsJAREnumerator(nsZipFind *aFind) : mFind(aFind), mName(nsnull) {
NS_ASSERTION(mFind, "nsJAREnumerator: Missing zipFind.");
}
private:
nsZipFind *mFind;
const char* mCurr; // pointer to an name owned by mArchive -- DON'T delete
const char* mName; // pointer to an name owned by mArchive -- DON'T delete
PRUint16 mNameLen;
~nsJAREnumerator() { delete mFind; }
};

View File

@ -68,7 +68,7 @@ nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
// Mark it as closed, in case something fails in initialisation
mMode = MODE_CLOSED;
//-- prepare for the compression type
switch (item->compression) {
switch (item->Compression()) {
case STORED:
mMode = MODE_COPY;
break;
@ -78,8 +78,7 @@ nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
NS_ENSURE_SUCCESS(rv, rv);
mMode = MODE_INFLATE;
mOutSize = item->realsize;
mInCrc = item->crc32;
mInCrc = item->CRC32();
mOutCrc = crc32(0L, Z_NULL, 0);
break;
@ -90,8 +89,8 @@ nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
// Must keep handle to filepointer and mmap structure as long as we need access to the mmapped data
mFd = aJar->mZip.GetFD();
mZs.next_in = aJar->mZip.GetData(item);
mZs.avail_in = item->size;
mOutSize = item->realsize;
mZs.avail_in = item->Size();
mOutSize = item->RealSize();
mZs.total_out = 0;
return NS_OK;
}
@ -150,9 +149,10 @@ nsJARInputStream::InitDirectory(nsJAR* aJar,
if (NS_FAILED(rv)) return rv;
const char *name;
while ((rv = find->FindNext( &name )) == NS_OK) {
// No need to copy string, just share the one from nsZipArchive
mArray.AppendElement(nsDependentCString(name));
PRUint16 nameLen;
while ((rv = find->FindNext( &name, &nameLen )) == NS_OK) {
// Must copy, to make it zero-terminated
mArray.AppendElement(nsCString(name,nameLen));
}
delete find;
@ -344,7 +344,7 @@ nsJARInputStream::ReadDirectory(char* aBuffer, PRUint32 aCount, PRUint32 *aBytes
// Last Modified Time
PRExplodedTime tm;
PR_ExplodeTime(GetModTime(ze->date, ze->time), PR_GMTParameters, &tm);
PR_ExplodeTime(GetModTime(ze->Date(), ze->Time()), PR_GMTParameters, &tm);
char itemLastModTime[65];
PR_FormatTimeUSEnglish(itemLastModTime,
sizeof(itemLastModTime),
@ -364,9 +364,9 @@ nsJARInputStream::ReadDirectory(char* aBuffer, PRUint32 aCount, PRUint32 *aBytes
mBuffer);
mBuffer.Append(' ');
mBuffer.AppendInt(ze->realsize, 10);
mBuffer.AppendInt(ze->RealSize(), 10);
mBuffer.Append(itemLastModTime); // starts/ends with ' '
if (ze->isDirectory)
if (ze->IsDirectory())
mBuffer.AppendLiteral("DIRECTORY\n");
else
mBuffer.AppendLiteral("FILE\n");

View File

@ -49,7 +49,6 @@
* or pointers to it across thread boundaries.
*/
#define READTYPE PRInt32
#include "zlib.h"
#include "nsISupportsUtils.h"
@ -59,7 +58,6 @@
#include "prlog.h"
#include "stdlib.h"
#include "nsWildCard.h"
#include "zipstruct.h"
#include "nsZipArchive.h"
/**
@ -100,12 +98,16 @@ nsRecyclingAllocator *gZlibAllocator = NULL;
# endif
#endif /* XP_UNIX */
static PRUint16 xtoint(unsigned char *ii);
static PRUint32 xtolong(unsigned char *ll);
static PRUint16 ExtractMode(unsigned char *ll);
static PRUint32 HashName(const char* aName);
static const PRUint32 kMaxNameLength = PATH_MAX; /* Maximum name length */
// For synthetic zip entries. Date/time corresponds to 1980-01-01 00:00.
static const PRUint16 kSyntheticTime = 0;
static const PRUint16 kSyntheticDate = (1 + (1 << 5) + (0 << 9));
static PRUint16 xtoint(const unsigned char *ii);
static PRUint32 xtolong(const unsigned char *ll);
static PRUint32 HashName(const char* aName, PRUint16 nameLen);
#if defined(XP_UNIX) || defined(XP_BEOS)
static PRBool IsSymlink(unsigned char *ll);
static nsresult ResolveSymlink(const char *path);
#endif
@ -243,7 +245,7 @@ nsresult nsZipArchive::Test(const char *aEntryName)
if (!currItem)
return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
//-- don't test (synthetic) directory items
if (currItem->isDirectory)
if (currItem->IsDirectory())
return NS_OK;
return ExtractFile(currItem, 0, 0);
}
@ -252,7 +254,7 @@ nsresult nsZipArchive::Test(const char *aEntryName)
for (int i = 0; i < ZIP_TABSIZE; i++) {
for (currItem = mFiles[i]; currItem; currItem = currItem->next) {
//-- don't test (synthetic) directory items
if (currItem->isDirectory)
if (currItem->IsDirectory())
continue;
nsresult rv = ExtractFile(currItem, 0, 0);
if (rv != NS_OK)
@ -291,19 +293,20 @@ nsresult nsZipArchive::CloseArchive()
nsZipItem* nsZipArchive::GetItem(const char * aEntryName)
{
if (aEntryName) {
PRUint32 len = strlen(aEntryName);
//-- If the request is for a directory, make sure that synthetic entries
//-- are created for the directories without their own entry.
if (!mBuiltSynthetics) {
PRUint32 len = strlen(aEntryName);
if ((len > 0) && (aEntryName[len-1] == '/')) {
if (BuildSynthetics() != NS_OK)
return 0;
}
}
nsZipItem* item = mFiles[ HashName(aEntryName) ];
nsZipItem* item = mFiles[ HashName(aEntryName, len) ];
while (item) {
if (!strcmp(aEntryName, item->name))
if ((len == item->nameLength) &&
(!memcmp(aEntryName, item->Name(), len)))
return item; //-- found it
item = item->next;
}
@ -328,12 +331,12 @@ nsresult nsZipArchive::ExtractFile(nsZipItem *item, const char *outname,
// Directory extraction is handled in nsJAR::Extract,
// so the item to be extracted should never be a directory
PR_ASSERT(!item->isDirectory);
PR_ASSERT(!item->IsDirectory());
nsresult rv;
//-- extract the file using the appropriate method
switch(item->compression)
switch(item->Compression())
{
case STORED:
rv = CopyItemToDisk(item, aFd);
@ -354,7 +357,7 @@ nsresult nsZipArchive::ExtractFile(nsZipItem *item, const char *outname,
if (rv != NS_OK)
PR_Delete(outname);
#if defined(XP_UNIX) || defined(XP_BEOS)
else if (item->isSymlink)
else if (item->IsSymlink())
rv = ResolveSymlink(outname);
#endif
}
@ -423,12 +426,13 @@ nsZipArchive::FindInit(const char * aPattern, nsZipFind **aFind)
//---------------------------------------------
// nsZipFind::FindNext
//---------------------------------------------
nsresult nsZipFind::FindNext(const char ** aResult)
nsresult nsZipFind::FindNext(const char ** aResult, PRUint16 *aNameLen)
{
if (!mArchive || !aResult)
if (!mArchive || !aResult || !aNameLen)
return NS_ERROR_ILLEGAL_VALUE;
*aResult = 0;
*aNameLen = 0;
// we start from last match, look for next
while (mSlot < ZIP_TABSIZE)
@ -442,12 +446,19 @@ nsresult nsZipFind::FindNext(const char ** aResult)
else if (!mPattern)
found = PR_TRUE; // always match
else if (mRegExp)
found = (NS_WildCardMatch(mItem->name, mPattern, PR_FALSE) == MATCH);
{
char buf[kMaxNameLength+1];
memcpy(buf, mItem->Name(), mItem->nameLength);
buf[mItem->nameLength]='\0';
found = (NS_WildCardMatch(buf, mPattern, PR_FALSE) == MATCH);
}
else
found = (PL_strcmp(mItem->name, mPattern) == 0);
found = ((mItem->nameLength == strlen(mPattern)) &&
(memcmp(mItem->Name(), mPattern, mItem->nameLength) == 0));
if (found) {
*aResult = mItem->name;
// Need also to return the name length, as it is NOT zero-terminatdd...
*aResult = mItem->Name();
*aNameLen = mItem->nameLength;
return NS_OK;
}
}
@ -483,17 +494,14 @@ static nsresult ResolveSymlink(const char *path)
// nsZipArchive -- private implementation
//***********************************************************
#define BR_BUF_SIZE 1024 /* backward read buffer size */
//---------------------------------------------
// nsZipArchive::CreateZipItem
//---------------------------------------------
nsZipItem* nsZipArchive::CreateZipItem(PRUint16 namelen)
nsZipItem* nsZipArchive::CreateZipItem()
{
// sizeof(nsZipItem) includes space for name's null byte
// Arena allocate the nsZipItem
void *mem;
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsZipItem)+namelen);
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsZipItem));
return (nsZipItem*)mem;
}
@ -504,20 +512,21 @@ nsresult nsZipArchive::BuildFileList()
{
// Get archive size using end pos
PRUint8* buf;
PRUint8* endp = mFd->mFileData + mFd->mLen;
PRUint8* startp = mFd->mFileData;
PRUint8* endp = startp + mFd->mLen;
for (buf = endp - ZIPEND_SIZE; xtolong(buf) != ENDSIG; buf--)
{
if (buf == mFd->mFileData) {
if (buf == startp) {
// We're at the beginning of the file, and still no sign
// of the end signature. File must be corrupted!
return NS_ERROR_FILE_CORRUPTED;
}
}
PRUint32 central = xtolong(((ZipEnd *)buf)->offset_central_dir);
PRUint32 centralOffset = xtolong(((ZipEnd *)buf)->offset_central_dir);
//-- Read the central directory headers
buf = mFd->mFileData + central;
buf = startp + centralOffset;
PRUint32 sig = xtolong(buf);
while (sig == CENTRALSIG) {
// Make sure there is enough data available.
@ -531,44 +540,27 @@ nsresult nsZipArchive::BuildFileList()
PRUint16 extralen = xtoint(central->extrafield_len);
PRUint16 commentlen = xtoint(central->commentfield_len);
// Point to the next item at the top of loop
buf += ZIPCENTRAL_SIZE + namelen + extralen + commentlen;
// Sanity check variable sizes and refuse to deal with
// anything too big: it's likely a corrupt archive.
if (namelen > BR_BUF_SIZE || extralen > BR_BUF_SIZE || commentlen > 2*BR_BUF_SIZE)
if (namelen > kMaxNameLength || buf >= endp)
return NS_ERROR_FILE_CORRUPTED;
nsZipItem* item = CreateZipItem(namelen);
nsZipItem* item = CreateZipItem();
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
item->headerOffset = xtolong(central->localhdr_offset);
item->size = xtolong(central->size);
item->realsize = xtolong(central->orglen);
item->crc32 = xtolong(central->crc32);
item->time = xtoint(central->time);
item->date = xtoint(central->date);
item->isSynthetic = PR_FALSE;
item->compression = PR_MIN(xtoint(central->method), UNSUPPORTED);
item->mode = ExtractMode(central->external_attributes);
#if defined(XP_UNIX) || defined(XP_BEOS)
// Check if item is a symlink
item->isSymlink = IsSymlink(central->external_attributes);
#endif
buf += ZIPCENTRAL_SIZE;
// Get the item name
memcpy(item->name, buf, namelen);
item->name[namelen] = 0;
// An item whose name ends with '/' is a directory
item->isDirectory = ('/' == item->name[namelen - 1]);
item->central = central;
item->nameLength = namelen;
item->isSynthetic = false;
// Add item to file table
PRUint32 hash = HashName(item->name);
PRUint32 hash = HashName(item->Name(), namelen);
item->next = mFiles[hash];
mFiles[hash] = item;
// Point to the next item at the top of loop
buf += namelen + extralen + commentlen;
sig = xtolong(buf);
} /* while reading central directory records */
@ -601,64 +593,40 @@ nsresult nsZipArchive::BuildSynthetics()
//-- create already exists
//-- start just before the last char so as to not add the item
//-- twice if it's a directory
PRUint16 namelen = strlen(item->name);
for (char* p = item->name + namelen - 2; p >= item->name; p--)
PRUint16 namelen = item->nameLength;
const char *name = item->Name();
for (PRUint16 dirlen = namelen - 1; dirlen > 0; dirlen--)
{
if ('/' != *p)
if (name[dirlen-1] != '/')
continue;
// See whether we need to create any more implicit directories,
// because if we don't we can avoid a lot of work.
// We can even avoid (de)allocating space for a bogus dirname with
// a little trickery -- save the char at item->name[dirnamelen],
// set it to 0, compare the strings, and restore the saved
// char when done
const PRUint32 dirnamelen = p + 1 - item->name;
const char savedChar = item->name[dirnamelen];
item->name[dirnamelen] = 0;
// Is the directory in the file table?
PRUint32 hash = HashName(item->name);
// Is the directory already in the file table?
PRUint32 hash = HashName(item->Name(), dirlen);
PRBool found = PR_FALSE;
for (nsZipItem* zi = mFiles[hash]; zi != NULL; zi = zi->next)
{
if (0 == strcmp(item->name, zi->name))
if ((dirlen == zi->nameLength) &&
(0 == memcmp(item->Name(), zi->Name(), dirlen)))
{
// we've already added this dir and all its parents
found = PR_TRUE;
break;
}
}
// restore the char immediately
item->name[dirnamelen] = savedChar;
// if the directory was found, break out of the directory
// creation loop now that we know all implicit directories
// are there -- otherwise, start creating the zip item
if (found)
break;
nsZipItem* diritem = CreateZipItem(dirnamelen);
nsZipItem* diritem = CreateZipItem();
if (!diritem)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(diritem->name, item->name, dirnamelen);
diritem->name[dirnamelen] = 0;
diritem->isDirectory = PR_TRUE;
diritem->isSynthetic = PR_TRUE;
diritem->compression = STORED;
diritem->size = diritem->realsize = 0;
diritem->crc32 = 0;
diritem->mode = 0755;
// Set an obviously wrong last-modified date/time, because
// finding something more accurate like the most recent
// last-modified date/time of the dir's contents is a lot
// of effort. The date/time corresponds to 1980-01-01 00:00.
diritem->time = 0;
diritem->date = 1 + (1 << 5) + (0 << 9);
// Point to the central record of the original item for the name part.
diritem->central = item->central;
diritem->nameLength = dirlen;
diritem->isSynthetic = true;
// add diritem to the file table
diritem->next = mFiles[hash];
@ -685,27 +653,29 @@ PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
//-- read local header to get variable length values and calculate
//-- the real data offset
if (aItem->headerOffset + ZIPLOCAL_SIZE > mFd->mLen)
PRUint32 len = mFd->mLen;
PRUint8* data = mFd->mFileData;
PRUint32 offset = aItem->LocalOffset();
if (offset + ZIPLOCAL_SIZE > len)
return nsnull;
// -- check signature before using the structure, in case the zip file is corrupt
ZipLocal* Local = (ZipLocal*)(mFd->mFileData + aItem->headerOffset);
ZipLocal* Local = (ZipLocal*)(data + offset);
if ((xtolong(Local->signature) != LOCALSIG))
return nsnull;
//-- NOTE: extralen is different in central header and local header
//-- for archives created using the Unix "zip" utility. To set
//-- the offset accurately we need the _local_ extralen.
PRUint32 dataOffset = aItem->headerOffset +
ZIPLOCAL_SIZE +
xtoint(Local->filename_len) +
xtoint(Local->extrafield_len);
offset += ZIPLOCAL_SIZE +
xtoint(Local->filename_len) +
xtoint(Local->extrafield_len);
// -- check if there is enough source data in the file
if (dataOffset + aItem->size > mFd->mLen)
if (offset + aItem->Size() > len)
return nsnull;
return mFd->mFileData + dataOffset;
return data + offset;
}
//---------------------------------------------
@ -721,16 +691,16 @@ nsZipArchive::CopyItemToDisk(nsZipItem *item, PRFileDesc* outFD)
if (!itemData)
return NS_ERROR_FILE_CORRUPTED;
if (outFD && PR_Write(outFD, itemData, item->size) < (READTYPE)item->size)
if (outFD && PR_Write(outFD, itemData, item->Size()) < (READTYPE)item->Size())
{
//-- Couldn't write all the data (disk full?)
return NS_ERROR_FILE_DISK_FULL;
}
//-- Calculate crc
PRUint32 crc = crc32(0L, (const unsigned char*)itemData, item->size);
PRUint32 crc = crc32(0L, (const unsigned char*)itemData, item->Size());
//-- verify crc32
if (crc != item->crc32)
if (crc != item->CRC32())
return NS_ERROR_FILE_CORRUPTED;
return NS_OK;
@ -758,7 +728,7 @@ nsresult nsZipArchive::InflateItem(nsZipItem * item, PRFileDesc* outFD)
return NS_ERROR_FAILURE;
//-- inflate loop
zs.avail_in = item->size;
zs.avail_in = item->Size();
zs.next_in = (Bytef*)GetData(item);
if (!zs.next_in)
return NS_ERROR_FILE_CORRUPTED;
@ -792,7 +762,7 @@ nsresult nsZipArchive::InflateItem(nsZipItem * item, PRFileDesc* outFD)
inflateEnd(&zs);
//-- verify crc32
if ((status == NS_OK) && (crc != item->crc32))
if ((status == NS_OK) && (crc != item->CRC32()))
{
status = NS_ERROR_FILE_CORRUPTED;
}
@ -850,13 +820,15 @@ nsZipFind::~nsZipFind()
*
* returns a hash key for the entry name
*/
static PRUint32 HashName(const char* aName)
static PRUint32 HashName(const char* aName, PRUint16 len)
{
PR_ASSERT(aName != 0);
const PRUint8* p = (const PRUint8*)aName;
const PRUint8* endp = p + len;
PRUint32 val = 0;
for (PRUint8* c = (PRUint8*)aName; *c != 0; c++) {
val = val*37 + *c;
while (p != endp) {
val = val*37 + *p++;
}
return (val % ZIP_TABSIZE);
@ -868,7 +840,7 @@ static PRUint32 HashName(const char* aName)
* Converts a two byte ugly endianed integer
* to our platform's integer.
*/
static PRUint16 xtoint (unsigned char *ii)
static PRUint16 xtoint (const unsigned char *ii)
{
return (PRUint16) ((ii [0]) | (ii [1] << 8));
}
@ -879,7 +851,7 @@ static PRUint16 xtoint (unsigned char *ii)
* Converts a four byte ugly endianed integer
* to our platform's integer.
*/
static PRUint32 xtolong (unsigned char *ll)
static PRUint32 xtolong (const unsigned char *ll)
{
return (PRUint32)( (ll [0] << 0) |
(ll [1] << 8) |
@ -887,28 +859,56 @@ static PRUint32 xtolong (unsigned char *ll)
(ll [3] << 24) );
}
/*
* ExtractMode
*
* Extracts bits 17-24 from a 32-bit unsigned long
* representation of the external attributes field.
* Subsequently it tacks on the implicit user-read
* bit.
*/
static PRUint16 ExtractMode(unsigned char *ll)
PRUint32 const nsZipItem::LocalOffset()
{
return ((PRUint16)(ll[2])) | 0x0100;
return xtolong(central->localhdr_offset);
}
PRUint32 const nsZipItem::Size()
{
return isSynthetic ? 0 : xtolong(central->size);
}
PRUint32 const nsZipItem::RealSize()
{
return isSynthetic ? 0 : xtolong(central->orglen);
}
PRUint32 const nsZipItem::CRC32()
{
return isSynthetic ? 0 : xtolong(central->crc32);
}
PRUint16 const nsZipItem::Date()
{
return isSynthetic ? kSyntheticDate : xtoint(central->date);
}
PRUint16 const nsZipItem::Time()
{
return isSynthetic ? kSyntheticTime : xtoint(central->time);
}
PRUint16 const nsZipItem::Compression()
{
return isSynthetic ? STORED : xtoint(central->method);
}
bool const nsZipItem::IsDirectory()
{
return isSynthetic || ((nameLength > 0) && ('/' == Name()[nameLength - 1]));
}
PRUint16 const nsZipItem::Mode()
{
if (isSynthetic) return 0755;
return ((PRUint16)(central->external_attributes[2]) | 0x100);
}
#if defined(XP_UNIX) || defined(XP_BEOS)
/*
*
* Return true if the attributes are for a symbolic link
*
*/
static PRBool IsSymlink(unsigned char *ll)
bool const nsZipItem::IsSymlink()
{
return ((xtoint(ll+2) & S_IFMT) == S_IFLNK);
if (isSynthetic) return false;
return (xtoint(central->external_attributes+2) & S_IFMT) == S_IFLNK;
}
#endif

View File

@ -43,16 +43,14 @@
#ifndef nsZipArchive_h_
#define nsZipArchive_h_
#define ZIP_MAGIC 0x5A49505FL /* "ZIP_" */
#define ZIPFIND_MAGIC 0x5A495046L /* "ZIPF" */
#define ZIP_TABSIZE 256
/* We really want to be a (multiple of) 4K for optimal file IO */
#define ZIP_BUFLEN (4*1024) /* Used as output buffer when deflating items to a file */
#define PL_ARENA_CONST_ALIGN_MASK 7
#define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1)
#include "plarena.h"
#include "zlib.h"
#include "zipstruct.h"
#include "nsAutoPtr.h"
class nsZipFind;
@ -80,30 +78,29 @@ struct PRFileDesc;
* each nsZipItem represents one file in the archive and all the
* information needed to manipulate it.
*/
struct nsZipItem
class nsZipItem
{
nsZipItem* next;
public:
const char* Name() { return ((const char*)central) + ZIPCENTRAL_SIZE; }
PRUint32 headerOffset;
PRUint32 size; /* size in original file */
PRUint32 realsize; /* inflated size */
PRUint32 crc32;
PRUint32 const LocalOffset();
PRUint32 const Size();
PRUint32 const RealSize();
PRUint32 const CRC32();
PRUint16 const Date();
PRUint16 const Time();
PRUint16 const Compression();
bool const IsDirectory();
PRUint16 const Mode();
/*
* Keep small items together, to avoid overhead.
*/
PRUint16 time;
PRUint16 date;
PRUint16 mode;
PRUint8 compression;
bool isDirectory;
bool isSynthetic; /* whether item is an actual zip entry or was
generated as part of a real entry's path */
#if defined(XP_UNIX) || defined(XP_BEOS)
bool isSymlink;
bool const IsSymlink();
#endif
char name[1]; /* actually, bigger than 1 */
nsZipItem* next;
const ZipCentral* central;
PRUint16 nameLength;
bool isSynthetic;
};
class nsZipHandle;
@ -211,7 +208,7 @@ private:
nsZipArchive& operator=(const nsZipArchive& rhs); // prevent assignments
nsZipArchive(const nsZipArchive& rhs); // prevent copies
nsZipItem* CreateZipItem(PRUint16 namelen);
nsZipItem* CreateZipItem();
nsresult BuildFileList();
nsresult BuildSynthetics();
@ -252,7 +249,7 @@ public:
nsZipFind(nsZipArchive* aZip, char* aPattern, PRBool regExp);
~nsZipFind();
nsresult FindNext(const char ** aResult);
nsresult FindNext(const char** aResult, PRUint16* aNameLen);
private:
nsZipArchive* mArchive;