зеркало из https://github.com/mozilla/pjs.git
Bug 511754 - make nsZipItems point at ZipCentral references to mmapped jar area r=tglek
This commit is contained in:
Родитель
e272369a42
Коммит
2a8fd0e070
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче