mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 525741 - two JAR tests fail if modification date of their files is on day daylight saving time starts or ends and after time change. r=dtownsend,tglek
This commit is contained in:
parent
a090ac8577
commit
a107124c97
@ -259,14 +259,9 @@ nsJAR::Extract(const char *zipEntry, nsIFile* outFile)
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRTime prtime = GetModTime(item->Date(), item->Time());
|
||||
// nsIFile needs milliseconds, while prtime is in microseconds.
|
||||
PRTime conversion = LL_ZERO;
|
||||
PRTime newTime = LL_ZERO;
|
||||
LL_I2L(conversion, PR_USEC_PER_MSEC);
|
||||
LL_DIV(newTime, prtime, conversion);
|
||||
// non-fatal if this fails, ignore errors
|
||||
outFile->SetLastModifiedTime(newTime);
|
||||
outFile->SetLastModifiedTime(item->LastModTime() / PR_USEC_PER_MSEC);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -933,8 +928,7 @@ nsJARItem::nsJARItem(nsZipItem* aZipItem)
|
||||
: mSize(aZipItem->Size()),
|
||||
mRealsize(aZipItem->RealSize()),
|
||||
mCrc32(aZipItem->CRC32()),
|
||||
mDate(aZipItem->Date()),
|
||||
mTime(aZipItem->Time()),
|
||||
mLastModTime(aZipItem->LastModTime()),
|
||||
mCompression(aZipItem->Compression()),
|
||||
mIsDirectory(aZipItem->IsDirectory()),
|
||||
mIsSynthetic(aZipItem->isSynthetic)
|
||||
@ -1021,7 +1015,7 @@ nsJARItem::GetLastModifiedTime(PRTime* aLastModTime)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLastModTime);
|
||||
|
||||
*aLastModTime = GetModTime(mDate, mTime);
|
||||
*aLastModTime = mLastModTime;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1267,27 +1261,4 @@ nsZipReaderCache::Observe(nsISupports *aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRTime GetModTime(PRUint16 aDate, PRUint16 aTime)
|
||||
{
|
||||
PRExplodedTime time;
|
||||
|
||||
time.tm_usec = 0;
|
||||
|
||||
time.tm_hour = (aTime >> 11) & 0x1F;
|
||||
time.tm_min = (aTime >> 5) & 0x3F;
|
||||
time.tm_sec = (aTime & 0x1F) * 2;
|
||||
|
||||
time.tm_year = (aDate >> 9) + 1980;
|
||||
time.tm_month = ((aDate >> 5) & 0x0F)-1;
|
||||
time.tm_mday = aDate & 0x1F;
|
||||
|
||||
time.tm_params.tp_gmt_offset = 0;
|
||||
time.tm_params.tp_dst_offset = 0;
|
||||
|
||||
PR_NormalizeTime(&time, PR_GMTParameters);
|
||||
time.tm_params = PR_LocalTimeParameters(&time);
|
||||
|
||||
return PR_ImplodeTime(&time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -85,8 +85,6 @@ typedef enum
|
||||
JAR_NOT_SIGNED = 7
|
||||
} JARManifestStatusType;
|
||||
|
||||
PRTime GetModTime(PRUint16 aDate, PRUint16 aTime);
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Class nsJAR declaration.
|
||||
* nsJAR serves as an XPCOM wrapper for nsZipArchive with the addition of
|
||||
@ -184,8 +182,7 @@ private:
|
||||
PRUint32 mSize; /* size in original file */
|
||||
PRUint32 mRealsize; /* inflated size */
|
||||
PRUint32 mCrc32;
|
||||
PRUint16 mDate;
|
||||
PRUint16 mTime;
|
||||
PRTime mLastModTime;
|
||||
PRUint16 mCompression;
|
||||
PRPackedBool mIsDirectory;
|
||||
PRPackedBool mIsSynthetic;
|
||||
|
@ -346,7 +346,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(ze->LastModTime(), PR_GMTParameters, &tm);
|
||||
char itemLastModTime[65];
|
||||
PR_FormatTimeUSEnglish(itemLastModTime,
|
||||
sizeof(itemLastModTime),
|
||||
|
@ -104,8 +104,8 @@ static const PRUint32 kMaxNameLength = PATH_MAX; /* Maximum name length */
|
||||
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 PRUint16 xtoint(const PRUint8 *ii);
|
||||
static PRUint32 xtolong(const PRUint8 *ll);
|
||||
static PRUint32 HashName(const char* aName, PRUint16 nameLen);
|
||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||
static nsresult ResolveSymlink(const char *path);
|
||||
@ -848,7 +848,7 @@ static PRUint32 HashName(const char* aName, PRUint16 len)
|
||||
* Converts a two byte ugly endianed integer
|
||||
* to our platform's integer.
|
||||
*/
|
||||
static PRUint16 xtoint (const unsigned char *ii)
|
||||
static PRUint16 xtoint (const PRUint8 *ii)
|
||||
{
|
||||
return (PRUint16) ((ii [0]) | (ii [1] << 8));
|
||||
}
|
||||
@ -859,7 +859,7 @@ static PRUint16 xtoint (const unsigned char *ii)
|
||||
* Converts a four byte ugly endianed integer
|
||||
* to our platform's integer.
|
||||
*/
|
||||
static PRUint32 xtolong (const unsigned char *ll)
|
||||
static PRUint32 xtolong (const PRUint8 *ll)
|
||||
{
|
||||
return (PRUint32)( (ll [0] << 0) |
|
||||
(ll [1] << 8) |
|
||||
@ -867,56 +867,129 @@ static PRUint32 xtolong (const unsigned char *ll)
|
||||
(ll [3] << 24) );
|
||||
}
|
||||
|
||||
PRUint32 const nsZipItem::LocalOffset()
|
||||
/*
|
||||
* GetModTime
|
||||
*
|
||||
* returns last modification time in microseconds
|
||||
*/
|
||||
static PRTime GetModTime(PRUint16 aDate, PRUint16 aTime)
|
||||
{
|
||||
// Note that on DST shift we can't handle correctly the hour that is valid
|
||||
// in both DST zones
|
||||
PRExplodedTime time;
|
||||
|
||||
time.tm_usec = 0;
|
||||
|
||||
time.tm_hour = (aTime >> 11) & 0x1F;
|
||||
time.tm_min = (aTime >> 5) & 0x3F;
|
||||
time.tm_sec = (aTime & 0x1F) * 2;
|
||||
|
||||
time.tm_year = (aDate >> 9) + 1980;
|
||||
time.tm_month = ((aDate >> 5) & 0x0F) - 1;
|
||||
time.tm_mday = aDate & 0x1F;
|
||||
|
||||
time.tm_params.tp_gmt_offset = 0;
|
||||
time.tm_params.tp_dst_offset = 0;
|
||||
|
||||
PR_NormalizeTime(&time, PR_GMTParameters);
|
||||
time.tm_params.tp_gmt_offset = PR_LocalTimeParameters(&time).tp_gmt_offset;
|
||||
PR_NormalizeTime(&time, PR_GMTParameters);
|
||||
time.tm_params.tp_dst_offset = PR_LocalTimeParameters(&time).tp_dst_offset;
|
||||
|
||||
return PR_ImplodeTime(&time);
|
||||
}
|
||||
|
||||
PRUint32 nsZipItem::LocalOffset()
|
||||
{
|
||||
return xtolong(central->localhdr_offset);
|
||||
}
|
||||
|
||||
PRUint32 const nsZipItem::Size()
|
||||
PRUint32 nsZipItem::Size()
|
||||
{
|
||||
return isSynthetic ? 0 : xtolong(central->size);
|
||||
}
|
||||
|
||||
PRUint32 const nsZipItem::RealSize()
|
||||
PRUint32 nsZipItem::RealSize()
|
||||
{
|
||||
return isSynthetic ? 0 : xtolong(central->orglen);
|
||||
}
|
||||
|
||||
PRUint32 const nsZipItem::CRC32()
|
||||
PRUint32 nsZipItem::CRC32()
|
||||
{
|
||||
return isSynthetic ? 0 : xtolong(central->crc32);
|
||||
}
|
||||
|
||||
PRUint16 const nsZipItem::Date()
|
||||
PRUint16 nsZipItem::Date()
|
||||
{
|
||||
return isSynthetic ? kSyntheticDate : xtoint(central->date);
|
||||
}
|
||||
|
||||
PRUint16 const nsZipItem::Time()
|
||||
PRUint16 nsZipItem::Time()
|
||||
{
|
||||
return isSynthetic ? kSyntheticTime : xtoint(central->time);
|
||||
}
|
||||
|
||||
PRUint16 const nsZipItem::Compression()
|
||||
PRUint16 nsZipItem::Compression()
|
||||
{
|
||||
return isSynthetic ? STORED : xtoint(central->method);
|
||||
}
|
||||
|
||||
bool const nsZipItem::IsDirectory()
|
||||
bool nsZipItem::IsDirectory()
|
||||
{
|
||||
return isSynthetic || ((nameLength > 0) && ('/' == Name()[nameLength - 1]));
|
||||
}
|
||||
|
||||
PRUint16 const nsZipItem::Mode()
|
||||
PRUint16 nsZipItem::Mode()
|
||||
{
|
||||
if (isSynthetic) return 0755;
|
||||
return ((PRUint16)(central->external_attributes[2]) | 0x100);
|
||||
}
|
||||
|
||||
const PRUint8 * nsZipItem::GetExtraField(PRUint16 aTag, PRUint16 *aBlockSize)
|
||||
{
|
||||
if (isSynthetic) return NULL;
|
||||
|
||||
const unsigned char *buf = ((const unsigned char*)central) + ZIPCENTRAL_SIZE +
|
||||
nameLength;
|
||||
PRUint32 buflen = (PRUint32)xtoint(central->extrafield_len);
|
||||
PRUint32 pos = 0;
|
||||
PRUint16 tag, blocksize;
|
||||
|
||||
while (buf && (pos + 4) <= buflen) {
|
||||
tag = xtoint(buf + pos);
|
||||
blocksize = xtoint(buf + pos + 2);
|
||||
|
||||
if (aTag == tag && (pos + 4 + blocksize) <= buflen) {
|
||||
*aBlockSize = blocksize;
|
||||
return buf + pos;
|
||||
}
|
||||
|
||||
pos += blocksize + 4;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PRTime nsZipItem::LastModTime()
|
||||
{
|
||||
if (isSynthetic) return GetModTime(kSyntheticDate, kSyntheticTime);
|
||||
|
||||
// Try to read timestamp from extra field
|
||||
PRUint16 blocksize;
|
||||
const PRUint8 *tsField = GetExtraField(EXTENDED_TIMESTAMP_FIELD, &blocksize);
|
||||
if (tsField && blocksize >= 5 && tsField[4] & EXTENDED_TIMESTAMP_MODTIME) {
|
||||
return (PRTime)(xtolong(tsField + 5)) * PR_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
return GetModTime(Date(), Time());
|
||||
}
|
||||
|
||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||
bool const nsZipItem::IsSymlink()
|
||||
bool nsZipItem::IsSymlink()
|
||||
{
|
||||
if (isSynthetic) return false;
|
||||
return (xtoint(central->external_attributes+2) & S_IFMT) == S_IFLNK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -83,18 +83,20 @@ class nsZipItem
|
||||
public:
|
||||
const char* Name() { return ((const char*)central) + ZIPCENTRAL_SIZE; }
|
||||
|
||||
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();
|
||||
PRUint32 LocalOffset();
|
||||
PRUint32 Size();
|
||||
PRUint32 RealSize();
|
||||
PRUint32 CRC32();
|
||||
PRUint16 Date();
|
||||
PRUint16 Time();
|
||||
PRUint16 Compression();
|
||||
bool IsDirectory();
|
||||
PRUint16 Mode();
|
||||
const PRUint8* GetExtraField(PRUint16 aTag, PRUint16 *aBlockSize);
|
||||
PRTime LastModTime();
|
||||
|
||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||
bool const IsSymlink();
|
||||
bool IsSymlink();
|
||||
#endif
|
||||
|
||||
nsZipItem* next;
|
||||
|
@ -7,8 +7,8 @@ const path = "data/test_bug379841.zip";
|
||||
const MAX_TIME_DIFF = 2000000;
|
||||
|
||||
var ENTRY_NAME = "test";
|
||||
// Actual time of file was 07 May 2007 14:35:49
|
||||
var ENTRY_TIME = new Date(2007, 4, 7, 14, 35, 49, 0);
|
||||
// Actual time of file was 07 May 2007 13:35:49 UTC
|
||||
var ENTRY_TIME = new Date(Date.UTC(2007, 4, 7, 13, 35, 49, 0));
|
||||
|
||||
function run_test() {
|
||||
var file = do_get_file(path);
|
||||
|
@ -122,6 +122,10 @@ typedef struct ZipEnd_
|
||||
#define CENTRALSIG 0x02014B50l
|
||||
#define ENDSIG 0x06054B50l
|
||||
|
||||
/* extra fields */
|
||||
#define EXTENDED_TIMESTAMP_FIELD 0x5455
|
||||
#define EXTENDED_TIMESTAMP_MODTIME 0x01
|
||||
|
||||
/* compression methods */
|
||||
#define STORED 0
|
||||
#define SHRUNK 1
|
||||
|
@ -50,47 +50,43 @@
|
||||
* The off argument, where present, is incremented according to the number of
|
||||
* bytes consumed from the buffer.
|
||||
*/
|
||||
inline NS_HIDDEN_(void) WRITE8(char* buf, PRUint32* off, PRUint8 val)
|
||||
inline NS_HIDDEN_(void) WRITE8(PRUint8* buf, PRUint32* off, PRUint8 val)
|
||||
{
|
||||
buf[(*off)++] = val & 0xff;
|
||||
buf[(*off)++] = val;
|
||||
}
|
||||
|
||||
inline NS_HIDDEN_(void) WRITE16(char* buf, PRUint32* off, PRUint16 val)
|
||||
inline NS_HIDDEN_(void) WRITE16(PRUint8* buf, PRUint32* off, PRUint16 val)
|
||||
{
|
||||
buf[(*off)++] = val & 0xff;
|
||||
buf[(*off)++] = (val >> 8) & 0xff;
|
||||
WRITE8(buf, off, val & 0xff);
|
||||
WRITE8(buf, off, (val >> 8) & 0xff);
|
||||
}
|
||||
|
||||
inline NS_HIDDEN_(void) WRITE32(char* buf, PRUint32* off, PRUint32 val)
|
||||
inline NS_HIDDEN_(void) WRITE32(PRUint8* buf, PRUint32* off, PRUint32 val)
|
||||
{
|
||||
buf[(*off)++] = val & 0xff;
|
||||
buf[(*off)++] = (val >> 8) & 0xff;
|
||||
buf[(*off)++] = (val >> 16) & 0xff;
|
||||
buf[(*off)++] = (val >> 24) & 0xff;
|
||||
WRITE16(buf, off, val & 0xffff);
|
||||
WRITE16(buf, off, (val >> 16) & 0xffff);
|
||||
}
|
||||
|
||||
inline NS_HIDDEN_(PRUint8) READ8(char* buf, PRUint32* off)
|
||||
inline NS_HIDDEN_(PRUint8) READ8(const PRUint8* buf, PRUint32* off)
|
||||
{
|
||||
return (PRUint8)buf[(*off)++];
|
||||
return buf[(*off)++];
|
||||
}
|
||||
|
||||
inline NS_HIDDEN_(PRUint16) READ16(char* buf, PRUint32* off)
|
||||
inline NS_HIDDEN_(PRUint16) READ16(const PRUint8* buf, PRUint32* off)
|
||||
{
|
||||
PRUint16 val = (PRUint16)buf[(*off)++] & 0xff;
|
||||
val |= ((PRUint16)buf[(*off)++] & 0xff) << 8;
|
||||
PRUint16 val = READ8(buf, off);
|
||||
val |= READ8(buf, off) << 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
inline NS_HIDDEN_(PRUint32) READ32(char* buf, PRUint32* off)
|
||||
inline NS_HIDDEN_(PRUint32) READ32(const PRUint8* buf, PRUint32* off)
|
||||
{
|
||||
PRUint32 val = (PRUint32)buf[(*off)++] & 0xff;
|
||||
val |= ((PRUint32)buf[(*off)++] & 0xff) << 8;
|
||||
val |= ((PRUint32)buf[(*off)++] & 0xff) << 16;
|
||||
val |= ((PRUint32)buf[(*off)++] & 0xff) << 24;
|
||||
PRUint32 val = READ16(buf, off);
|
||||
val |= READ16(buf, off) << 16;
|
||||
return val;
|
||||
}
|
||||
|
||||
inline NS_HIDDEN_(PRUint32) PEEK32(unsigned char *buf)
|
||||
inline NS_HIDDEN_(PRUint32) PEEK32(const PRUint8* buf)
|
||||
{
|
||||
return (PRUint32)( (buf [0] ) |
|
||||
(buf [1] << 8) |
|
||||
|
@ -47,6 +47,9 @@
|
||||
|
||||
#define FLAGS_IS_UTF8 0x800
|
||||
|
||||
#define ZIP_EXTENDED_TIMESTAMP_FIELD 0x5455
|
||||
#define ZIP_EXTENDED_TIMESTAMP_MODTIME 0x01
|
||||
|
||||
/**
|
||||
* nsZipHeader represents an entry from a zip file.
|
||||
*/
|
||||
@ -105,11 +108,28 @@ NS_IMETHODIMP nsZipHeader::GetLastModifiedTime(PRTime *aLastModifiedTime)
|
||||
{
|
||||
NS_ASSERTION(mInited, "Not initalised");
|
||||
|
||||
// Try to read timestamp from extra field
|
||||
PRUint16 blocksize;
|
||||
const PRUint8 *tsField = GetExtraField(ZIP_EXTENDED_TIMESTAMP_FIELD, PR_FALSE, &blocksize);
|
||||
if (tsField && blocksize >= 5) {
|
||||
PRUint32 pos = 4;
|
||||
PRUint8 flags;
|
||||
flags = READ8(tsField, &pos);
|
||||
if (flags & ZIP_EXTENDED_TIMESTAMP_MODTIME) {
|
||||
*aLastModifiedTime = (PRTime)(READ32(tsField, &pos))
|
||||
* PR_USEC_PER_SEC;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Use DOS date/time fields
|
||||
// Note that on DST shift we can't handle correctly the hour that is valid
|
||||
// in both DST zones
|
||||
PRExplodedTime time;
|
||||
|
||||
time.tm_usec = 0;
|
||||
|
||||
time.tm_hour = mTime >> 11;
|
||||
time.tm_hour = (mTime >> 11) & 0x1F;
|
||||
time.tm_min = (mTime >> 5) & 0x3F;
|
||||
time.tm_sec = (mTime & 0x1F) * 2;
|
||||
|
||||
@ -121,7 +141,9 @@ NS_IMETHODIMP nsZipHeader::GetLastModifiedTime(PRTime *aLastModifiedTime)
|
||||
time.tm_params.tp_dst_offset = 0;
|
||||
|
||||
PR_NormalizeTime(&time, PR_GMTParameters);
|
||||
time.tm_params = PR_LocalTimeParameters(&time);
|
||||
time.tm_params.tp_gmt_offset = PR_LocalTimeParameters(&time).tp_gmt_offset;
|
||||
PR_NormalizeTime(&time, PR_GMTParameters);
|
||||
time.tm_params.tp_dst_offset = PR_LocalTimeParameters(&time).tp_dst_offset;
|
||||
|
||||
*aLastModifiedTime = PR_ImplodeTime(&time);
|
||||
|
||||
@ -149,6 +171,27 @@ void nsZipHeader::Init(const nsACString & aPath, PRTime aDate, PRUint32 aAttr,
|
||||
mDate = time.tm_mday + ((time.tm_month + 1) << 5) +
|
||||
((time.tm_year - 1980) << 9);
|
||||
|
||||
// Store modification timestamp as extra field
|
||||
// First fill CDS extra field
|
||||
mFieldLength = 9;
|
||||
mExtraField = new PRUint8[mFieldLength];
|
||||
if (!mExtraField) {
|
||||
mFieldLength = 0;
|
||||
} else {
|
||||
PRUint32 pos = 0;
|
||||
WRITE16(mExtraField.get(), &pos, ZIP_EXTENDED_TIMESTAMP_FIELD);
|
||||
WRITE16(mExtraField.get(), &pos, 5);
|
||||
WRITE8(mExtraField.get(), &pos, ZIP_EXTENDED_TIMESTAMP_MODTIME);
|
||||
WRITE32(mExtraField.get(), &pos, aDate / PR_USEC_PER_SEC);
|
||||
|
||||
// Fill local extra field
|
||||
mLocalExtraField = new PRUint8[mFieldLength];
|
||||
if (mLocalExtraField) {
|
||||
mLocalFieldLength = mFieldLength;
|
||||
memcpy(mLocalExtraField.get(), mExtraField.get(), mLocalFieldLength);
|
||||
}
|
||||
}
|
||||
|
||||
mEAttr = aAttr;
|
||||
mOffset = aOffset;
|
||||
mName = aPath;
|
||||
@ -160,14 +203,14 @@ void nsZipHeader::Init(const nsACString & aPath, PRTime aDate, PRUint32 aAttr,
|
||||
|
||||
PRUint32 nsZipHeader::GetFileHeaderLength()
|
||||
{
|
||||
return ZIP_FILE_HEADER_SIZE + mName.Length();
|
||||
return ZIP_FILE_HEADER_SIZE + mName.Length() + mLocalFieldLength;
|
||||
}
|
||||
|
||||
nsresult nsZipHeader::WriteFileHeader(nsIOutputStream *aStream)
|
||||
{
|
||||
NS_ASSERTION(mInited, "Not initalised");
|
||||
|
||||
char buf[ZIP_FILE_HEADER_SIZE];
|
||||
PRUint8 buf[ZIP_FILE_HEADER_SIZE];
|
||||
PRUint32 pos = 0;
|
||||
WRITE32(buf, &pos, ZIP_FILE_HEADER_SIGNATURE);
|
||||
WRITE16(buf, &pos, mVersionNeeded);
|
||||
@ -179,12 +222,21 @@ nsresult nsZipHeader::WriteFileHeader(nsIOutputStream *aStream)
|
||||
WRITE32(buf, &pos, mCSize);
|
||||
WRITE32(buf, &pos, mUSize);
|
||||
WRITE16(buf, &pos, mName.Length());
|
||||
WRITE16(buf, &pos, 0);
|
||||
WRITE16(buf, &pos, mLocalFieldLength);
|
||||
|
||||
nsresult rv = ZW_WriteData(aStream, buf, pos);
|
||||
nsresult rv = ZW_WriteData(aStream, (const char *)buf, pos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return ZW_WriteData(aStream, mName.get(), mName.Length());
|
||||
rv = ZW_WriteData(aStream, mName.get(), mName.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mLocalFieldLength)
|
||||
{
|
||||
rv = ZW_WriteData(aStream, (const char *)mLocalExtraField.get(), mLocalFieldLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 nsZipHeader::GetCDSHeaderLength()
|
||||
@ -197,7 +249,7 @@ nsresult nsZipHeader::WriteCDSHeader(nsIOutputStream *aStream)
|
||||
{
|
||||
NS_ASSERTION(mInited, "Not initalised");
|
||||
|
||||
char buf[ZIP_CDS_HEADER_SIZE];
|
||||
PRUint8 buf[ZIP_CDS_HEADER_SIZE];
|
||||
PRUint32 pos = 0;
|
||||
WRITE32(buf, &pos, ZIP_CDS_HEADER_SIGNATURE);
|
||||
WRITE16(buf, &pos, mVersionMade);
|
||||
@ -217,13 +269,13 @@ nsresult nsZipHeader::WriteCDSHeader(nsIOutputStream *aStream)
|
||||
WRITE32(buf, &pos, mEAttr);
|
||||
WRITE32(buf, &pos, mOffset);
|
||||
|
||||
nsresult rv = ZW_WriteData(aStream, buf, pos);
|
||||
nsresult rv = ZW_WriteData(aStream, (const char *)buf, pos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ZW_WriteData(aStream, mName.get(), mName.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mExtraField) {
|
||||
rv = ZW_WriteData(aStream, mExtraField, mFieldLength);
|
||||
rv = ZW_WriteData(aStream, (const char *)mExtraField.get(), mFieldLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return ZW_WriteData(aStream, mComment.get(), mComment.Length());
|
||||
@ -233,9 +285,9 @@ nsresult nsZipHeader::ReadCDSHeader(nsIInputStream *stream)
|
||||
{
|
||||
NS_ASSERTION(!mInited, "Already initalised");
|
||||
|
||||
char buf[ZIP_CDS_HEADER_SIZE];
|
||||
PRUint8 buf[ZIP_CDS_HEADER_SIZE];
|
||||
|
||||
nsresult rv = ZW_ReadData(stream, buf, ZIP_CDS_HEADER_SIZE);
|
||||
nsresult rv = ZW_ReadData(stream, (char *)buf, ZIP_CDS_HEADER_SIZE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 pos = 0;
|
||||
@ -271,9 +323,9 @@ nsresult nsZipHeader::ReadCDSHeader(nsIInputStream *stream)
|
||||
mName = NS_LITERAL_CSTRING("");
|
||||
|
||||
if (mFieldLength > 0) {
|
||||
mExtraField = new char[mFieldLength];
|
||||
mExtraField = new PRUint8[mFieldLength];
|
||||
NS_ENSURE_TRUE(mExtraField, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = ZW_ReadData(stream, mExtraField.get(), mFieldLength);
|
||||
rv = ZW_ReadData(stream, (char *)mExtraField.get(), mFieldLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -290,3 +342,25 @@ nsresult nsZipHeader::ReadCDSHeader(nsIInputStream *stream)
|
||||
mInited = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const PRUint8 * nsZipHeader::GetExtraField(PRUint16 aTag, PRBool aLocal, PRUint16 *aBlockSize)
|
||||
{
|
||||
const PRUint8 *buf = aLocal ? mLocalExtraField : mExtraField;
|
||||
PRUint32 buflen = aLocal ? mLocalFieldLength : mFieldLength;
|
||||
PRUint32 pos = 0;
|
||||
PRUint16 tag, blocksize;
|
||||
|
||||
while (buf && (pos + 4) <= buflen) {
|
||||
tag = READ16(buf, &pos);
|
||||
blocksize = READ16(buf, &pos);
|
||||
|
||||
if (aTag == tag && (pos + blocksize) <= buflen) {
|
||||
*aBlockSize = blocksize;
|
||||
return buf + pos - 4;
|
||||
}
|
||||
|
||||
pos += blocksize;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
mEAttr(0),
|
||||
mOffset(0),
|
||||
mFieldLength(0),
|
||||
mLocalFieldLength(0),
|
||||
mVersionMade(0x0300 + 23), // Generated on Unix by v2.3 (matches infozip)
|
||||
mVersionNeeded(20), // Requires v2.0 to extract
|
||||
mFlags(0),
|
||||
@ -77,13 +78,15 @@ public:
|
||||
mDisk(0),
|
||||
mIAttr(0),
|
||||
mInited(PR_FALSE),
|
||||
mExtraField(NULL)
|
||||
mExtraField(NULL),
|
||||
mLocalExtraField(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~nsZipHeader()
|
||||
{
|
||||
mExtraField = NULL;
|
||||
mLocalExtraField = NULL;
|
||||
}
|
||||
|
||||
PRUint32 mCRC;
|
||||
@ -92,6 +95,7 @@ public:
|
||||
PRUint32 mEAttr;
|
||||
PRUint32 mOffset;
|
||||
PRUint32 mFieldLength;
|
||||
PRUint32 mLocalFieldLength;
|
||||
PRUint16 mVersionMade;
|
||||
PRUint16 mVersionNeeded;
|
||||
PRUint16 mFlags;
|
||||
@ -103,7 +107,8 @@ public:
|
||||
PRPackedBool mInited;
|
||||
nsCString mName;
|
||||
nsCString mComment;
|
||||
nsAutoArrayPtr<char> mExtraField;
|
||||
nsAutoArrayPtr<PRUint8> mExtraField;
|
||||
nsAutoArrayPtr<PRUint8> mLocalExtraField;
|
||||
|
||||
void Init(const nsACString & aPath, PRTime aDate, PRUint32 aAttr,
|
||||
PRUint32 aOffset);
|
||||
@ -112,6 +117,7 @@ public:
|
||||
PRUint32 GetCDSHeaderLength();
|
||||
nsresult WriteCDSHeader(nsIOutputStream *aStream);
|
||||
nsresult ReadCDSHeader(nsIInputStream *aStream);
|
||||
const PRUint8 * GetExtraField(PRUint16 aTag, PRBool aLocal, PRUint16 *aBlockSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -147,7 +147,7 @@ nsresult nsZipWriter::ReadFile(nsIFile *aFile)
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), aFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char buf[1024];
|
||||
PRUint8 buf[1024];
|
||||
PRInt64 seek = size - 1024;
|
||||
PRUint32 length = 1024;
|
||||
|
||||
@ -164,7 +164,7 @@ nsresult nsZipWriter::ReadFile(nsIFile *aFile)
|
||||
inputStream->Close();
|
||||
return rv;
|
||||
}
|
||||
rv = ZW_ReadData(inputStream, buf, length);
|
||||
rv = ZW_ReadData(inputStream, (char *)buf, length);
|
||||
if (NS_FAILED(rv)) {
|
||||
inputStream->Close();
|
||||
return rv;
|
||||
@ -177,7 +177,7 @@ nsresult nsZipWriter::ReadFile(nsIFile *aFile)
|
||||
// We know it's at least this far from the end
|
||||
for (PRUint32 pos = length - ZIP_EOCDR_HEADER_SIZE;
|
||||
(PRInt32)pos >= 0; pos--) {
|
||||
PRUint32 sig = PEEK32((unsigned char *)buf + pos);
|
||||
PRUint32 sig = PEEK32(buf + pos);
|
||||
if (sig == ZIP_EOCDR_HEADER_SIGNATURE) {
|
||||
// Skip down to entry count
|
||||
pos += 10;
|
||||
@ -190,7 +190,7 @@ nsresult nsZipWriter::ReadFile(nsIFile *aFile)
|
||||
if (commentlen == 0)
|
||||
mComment.Truncate();
|
||||
else if (pos + commentlen <= length)
|
||||
mComment.Assign(buf + pos, commentlen);
|
||||
mComment.Assign((const char *)buf + pos, commentlen);
|
||||
else {
|
||||
if ((seek + pos + commentlen) > size) {
|
||||
inputStream->Close();
|
||||
@ -682,7 +682,7 @@ NS_IMETHODIMP nsZipWriter::Close()
|
||||
size += mHeaders[i]->GetCDSHeaderLength();
|
||||
}
|
||||
|
||||
char buf[ZIP_EOCDR_HEADER_SIZE];
|
||||
PRUint8 buf[ZIP_EOCDR_HEADER_SIZE];
|
||||
PRUint32 pos = 0;
|
||||
WRITE32(buf, &pos, ZIP_EOCDR_HEADER_SIGNATURE);
|
||||
WRITE16(buf, &pos, 0);
|
||||
@ -693,7 +693,7 @@ NS_IMETHODIMP nsZipWriter::Close()
|
||||
WRITE32(buf, &pos, mCDSOffset);
|
||||
WRITE16(buf, &pos, mComment.Length());
|
||||
|
||||
nsresult rv = ZW_WriteData(mStream, buf, pos);
|
||||
nsresult rv = ZW_WriteData(mStream, (const char *)buf, pos);
|
||||
if (NS_FAILED(rv)) {
|
||||
Cleanup();
|
||||
return rv;
|
||||
|
@ -55,12 +55,10 @@ const ZIP_FILE_HEADER_SIZE = 30;
|
||||
const ZIP_CDS_HEADER_SIZE = 46;
|
||||
const ZIP_METHOD_STORE = 0
|
||||
const ZIP_METHOD_DEFLATE = 8
|
||||
const ZIP_EXTENDED_TIMESTAMP_SIZE = 9;
|
||||
|
||||
const PR_USEC_PER_MSEC = 1000;
|
||||
|
||||
// ZIP times are stored at a 2 second resolution.
|
||||
const TIME_RESOLUTION = 2000;
|
||||
|
||||
const DATA_DIR = "data/";
|
||||
|
||||
var ZipWriter = Components.Constructor("@mozilla.org/zipwriter;1",
|
||||
|
@ -77,11 +77,8 @@ var observer = {
|
||||
do_check_eq(entry.realSize, TESTS[i].size);
|
||||
do_check_eq(entry.size, TESTS[i].size);
|
||||
do_check_eq(entry.CRC32, TESTS[i].crc);
|
||||
|
||||
var diff = Math.abs((entry.lastModifiedTime/PR_USEC_PER_MSEC) -
|
||||
source.lastModifiedTime);
|
||||
if (diff > TIME_RESOLUTION)
|
||||
do_throw(diff);
|
||||
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC,
|
||||
source.lastModifiedTime);
|
||||
|
||||
zipR.test(TESTS[i].name);
|
||||
}
|
||||
@ -100,6 +97,7 @@ function run_test()
|
||||
zipW.addEntryFile(TESTS[i].name, Ci.nsIZipWriter.COMPRESSION_NONE, source,
|
||||
true);
|
||||
size += ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
|
||||
(ZIP_EXTENDED_TIMESTAMP_SIZE * 2) +
|
||||
(TESTS[i].name.length*2) + TESTS[i].size;
|
||||
}
|
||||
do_test_pending();
|
||||
|
@ -55,9 +55,7 @@ function testpass(source)
|
||||
// Should be stored
|
||||
do_check_eq(entry.compression, ZIP_METHOD_DEFLATE);
|
||||
|
||||
var diff = Math.abs((entry.lastModifiedTime / PR_USEC_PER_MSEC) - time);
|
||||
if (diff > TIME_RESOLUTION)
|
||||
do_throw(diff);
|
||||
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, time);
|
||||
|
||||
// File size should match our data size.
|
||||
do_check_eq(entry.realSize, DATA.length);
|
||||
|
@ -57,6 +57,8 @@ function run_test()
|
||||
|
||||
// Adding the directory would have added a fixed amount to the file size.
|
||||
// Any difference suggests the CDS was written out incorrectly.
|
||||
var extra = ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE + (DIRNAME.length * 2);
|
||||
var extra = ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
|
||||
(DIRNAME.length * 2) + (ZIP_EXTENDED_TIMESTAMP_SIZE * 2);
|
||||
|
||||
do_check_eq(source.fileSize + extra, tmpFile.fileSize);
|
||||
}
|
||||
|
@ -65,9 +65,7 @@ function run_test()
|
||||
do_check_eq(entry.compression, ZIP_METHOD_DEFLATE);
|
||||
do_check_eq(entry.CRC32, CRC);
|
||||
do_check_eq(entry.realSize, DATA.length);
|
||||
var diff = Math.abs((entry.lastModifiedTime/PR_USEC_PER_MSEC) - time);
|
||||
if (diff > TIME_RESOLUTION)
|
||||
do_throw(diff);
|
||||
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, time);
|
||||
|
||||
zipW.close();
|
||||
|
||||
|
@ -42,13 +42,13 @@ var TESTS = [
|
||||
name: "test.txt",
|
||||
size: 232,
|
||||
crc: 0x0373ac26,
|
||||
time: new Date(2007, 4, 1, 21, 44, 56)
|
||||
time: Date.UTC(2007, 4, 1, 20, 44, 55)
|
||||
},
|
||||
{
|
||||
name: "test.png",
|
||||
size: 3402,
|
||||
crc: 0x504a5c30,
|
||||
time: new Date(2007, 4, 1, 21, 49, 40)
|
||||
time: Date.UTC(2007, 4, 1, 20, 49, 39)
|
||||
}
|
||||
];
|
||||
var BADENTRY = "unknown.txt";
|
||||
@ -70,10 +70,7 @@ function run_test()
|
||||
|
||||
do_check_eq(entry.realSize, TESTS[i].size);
|
||||
do_check_eq(entry.CRC32, TESTS[i].crc);
|
||||
var diff = Math.abs(TESTS[i].time -
|
||||
(entry.lastModifiedTime / PR_USEC_PER_MSEC));
|
||||
if (diff > TIME_RESOLUTION)
|
||||
do_throw(diff);
|
||||
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, TESTS[i].time);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -56,9 +56,7 @@ function testpass(source)
|
||||
// Should be stored
|
||||
do_check_eq(entry.compression, ZIP_METHOD_STORE);
|
||||
|
||||
var diff = Math.abs((entry.lastModifiedTime / PR_USEC_PER_MSEC) - time);
|
||||
if (diff > TIME_RESOLUTION)
|
||||
do_throw(diff);
|
||||
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, time);
|
||||
|
||||
// File size should match our data size.
|
||||
do_check_eq(entry.realSize, DATA.length);
|
||||
@ -90,6 +88,7 @@ function run_test()
|
||||
|
||||
do_check_eq(tmpFile.fileSize,
|
||||
DATA.length + ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
|
||||
(ZIP_EXTENDED_TIMESTAMP_SIZE * 2) +
|
||||
(FILENAME.length * 2) + ZIP_EOCDR_HEADER_SIZE);
|
||||
|
||||
// Check to see if we get the same results loading afresh.
|
||||
|
@ -60,6 +60,7 @@ function run_test()
|
||||
zipW.addEntryFile(TESTS[i].name, Ci.nsIZipWriter.COMPRESSION_NONE, source,
|
||||
false);
|
||||
size += ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
|
||||
(ZIP_EXTENDED_TIMESTAMP_SIZE * 2) +
|
||||
(TESTS[i].name.length*2) + TESTS[i].size;
|
||||
}
|
||||
|
||||
@ -79,11 +80,8 @@ function run_test()
|
||||
do_check_eq(entry.realSize, TESTS[i].size);
|
||||
do_check_eq(entry.size, TESTS[i].size);
|
||||
do_check_eq(entry.CRC32, TESTS[i].crc);
|
||||
|
||||
var diff = Math.abs((entry.lastModifiedTime/PR_USEC_PER_MSEC) -
|
||||
source.lastModifiedTime);
|
||||
if (diff > TIME_RESOLUTION)
|
||||
do_throw(diff);
|
||||
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC,
|
||||
source.lastModifiedTime);
|
||||
|
||||
zipR.test(TESTS[i].name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user