import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "nscore.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
/*
* Fully reads the required amount of data. Keeps reading until all the
* data is retrieved or an error is hit.
*/
nsresult ZW_ReadData(nsIInputStream *aStream, char *aBuffer, uint32_t aCount)
{
while (aCount > 0) {
uint32_t read;
nsresult rv = aStream->Read(aBuffer, aCount, &read);
NS_ENSURE_SUCCESS(rv, rv);
aCount -= read;
aBuffer += read;
// If we hit EOF before reading the data we need then throw.
if (read == 0 && aCount > 0)
return NS_ERROR_FAILURE;
}
return NS_OK;
}
/*
* Fully writes the required amount of data. Keeps writing until all the
* data is written or an error is hit.
*/
nsresult ZW_WriteData(nsIOutputStream *aStream, const char *aBuffer,
uint32_t aCount)
{
while (aCount > 0) {
uint32_t written;
nsresult rv = aStream->Write(aBuffer, aCount, &written);
NS_ENSURE_SUCCESS(rv, rv);
if (written <= 0)
return NS_ERROR_FAILURE;
aCount -= written;
aBuffer += written;
}
return NS_OK;
}

View file

@ -0,0 +1,68 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _nsStreamFunctions_h_
#define _nsStreamFunctions_h_
#include "nscore.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
/*
* ZIP file data is stored little-endian. These are helper functions to read and
* write little endian data to/from a char buffer.
* The off argument, where present, is incremented according to the number of
* bytes consumed from the buffer.
*/
inline void WRITE8(uint8_t* buf, uint32_t* off, uint8_t val)
{
buf[(*off)++] = val;
}
inline void WRITE16(uint8_t* buf, uint32_t* off, uint16_t val)
{
WRITE8(buf, off, val & 0xff);
WRITE8(buf, off, (val >> 8) & 0xff);
}
inline void WRITE32(uint8_t* buf, uint32_t* off, uint32_t val)
{
WRITE16(buf, off, val & 0xffff);
WRITE16(buf, off, (val >> 16) & 0xffff);
}
inline uint8_t READ8(const uint8_t* buf, uint32_t* off)
{
return buf[(*off)++];
}
inline uint16_t READ16(const uint8_t* buf, uint32_t* off)
{
uint16_t val = READ8(buf, off);
val |= READ8(buf, off) << 8;
return val;
}
inline uint32_t READ32(const uint8_t* buf, uint32_t* off)
{
uint32_t val = READ16(buf, off);
val |= READ16(buf, off) << 16;
return val;
}
inline uint32_t PEEK32(const uint8_t* buf)
{
return (uint32_t)( (buf [0] ) |
(buf [1] << 8) |
(buf [2] << 16) |
(buf [3] << 24) );
}
nsresult ZW_ReadData(nsIInputStream *aStream, char *aBuffer, uint32_t aCount);
nsresult ZW_WriteData(nsIOutputStream *aStream, const char *aBuffer,
uint32_t aCount);
#endif

View file

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "mozilla/ModuleUtils.h"
#include "nsDeflateConverter.h"
#include "nsZipWriter.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeflateConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsZipWriter)
NS_DEFINE_NAMED_CID(DEFLATECONVERTER_CID);
NS_DEFINE_NAMED_CID(ZIPWRITER_CID);
static const mozilla::Module::CIDEntry kZipWriterCIDs[] = {
{ &kDEFLATECONVERTER_CID, false, nullptr, nsDeflateConverterConstructor },
{ &kZIPWRITER_CID, false, nullptr, nsZipWriterConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kZipWriterContracts[] = {
{ "@mozilla.org/streamconv;1?from=uncompressed&to=deflate", &kDEFLATECONVERTER_CID },
{ "@mozilla.org/streamconv;1?from=uncompressed&to=gzip", &kDEFLATECONVERTER_CID },
{ "@mozilla.org/streamconv;1?from=uncompressed&to=x-gzip", &kDEFLATECONVERTER_CID },
{ "@mozilla.org/streamconv;1?from=uncompressed&to=rawdeflate", &kDEFLATECONVERTER_CID },
{ ZIPWRITER_CONTRACTID, &kZIPWRITER_CID },
{ nullptr }
};
static const mozilla::Module kZipWriterModule = {
mozilla::Module::kVersion,
kZipWriterCIDs,
kZipWriterContracts
};
NSMODULE_DEFN(ZipWriterModule) = &kZipWriterModule;

View file

@ -0,0 +1,24 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
XPIDL_SOURCES += [
'nsIZipWriter.idl',
]
XPIDL_MODULE = 'zipwriter'
UNIFIED_SOURCES += [
'nsDeflateConverter.cpp',
'nsZipDataStream.cpp',
'nsZipHeader.cpp',
'nsZipWriter.cpp',
'StreamFunctions.cpp',
'ZipWriterModule.cpp',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,188 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "StreamFunctions.h"
#include "nsDeflateConverter.h"
#include "nsStringStream.h"
#include "nsIInputStreamPump.h"
#include "nsComponentManagerUtils.h"
#include "nsMemory.h"
#include "plstr.h"
#include "mozilla/UniquePtr.h"
#define ZLIB_TYPE "deflate"
#define GZIP_TYPE "gzip"
#define X_GZIP_TYPE "x-gzip"
using namespace mozilla;
/**
* nsDeflateConverter is a stream converter applies the deflate compression
* method to the data.
*/
NS_IMPL_ISUPPORTS(nsDeflateConverter, nsIStreamConverter,
nsIStreamListener,
nsIRequestObserver)
nsresult nsDeflateConverter::Init()
{
int zerr;
mOffset = 0;
mZstream.zalloc = Z_NULL;
mZstream.zfree = Z_NULL;
mZstream.opaque = Z_NULL;
int32_t window = MAX_WBITS;
switch (mWrapMode) {
case WRAP_NONE:
window = -window;
break;
case WRAP_GZIP:
window += 16;
break;
default:
break;
}
zerr = deflateInit2(&mZstream, mLevel, Z_DEFLATED, window, 8,
Z_DEFAULT_STRATEGY);
if (zerr != Z_OK) return NS_ERROR_OUT_OF_MEMORY;
mZstream.next_out = mWriteBuffer;
mZstream.avail_out = sizeof(mWriteBuffer);
// mark the input buffer as empty.
mZstream.avail_in = 0;
mZstream.next_in = Z_NULL;
return NS_OK;
}
NS_IMETHODIMP nsDeflateConverter::Convert(nsIInputStream *aFromStream,
const char *aFromType,
const char *aToType,
nsISupports *aCtxt,
nsIInputStream **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsDeflateConverter::AsyncConvertData(const char *aFromType,
const char *aToType,
nsIStreamListener *aListener,
nsISupports *aCtxt)
{
if (mListener)
return NS_ERROR_ALREADY_INITIALIZED;
NS_ENSURE_ARG_POINTER(aListener);
if (!PL_strncasecmp(aToType, ZLIB_TYPE, sizeof(ZLIB_TYPE)-1))
mWrapMode = WRAP_ZLIB;
else if (!PL_strcasecmp(aToType, GZIP_TYPE) ||
!PL_strcasecmp(aToType, X_GZIP_TYPE))
mWrapMode = WRAP_GZIP;
else
mWrapMode = WRAP_NONE;
nsresult rv = Init();
NS_ENSURE_SUCCESS(rv, rv);
mListener = aListener;
mContext = aCtxt;
return rv;
}
NS_IMETHODIMP nsDeflateConverter::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
uint64_t aOffset,
uint32_t aCount)
{
if (!mListener)
return NS_ERROR_NOT_INITIALIZED;
auto buffer = MakeUnique<char[]>(aCount);
NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
NS_ENSURE_SUCCESS(rv, rv);
// make sure we aren't reading too much
mZstream.avail_in = aCount;
mZstream.next_in = (unsigned char*)buffer.get();
int zerr = Z_OK;
// deflate loop
while (mZstream.avail_in > 0 && zerr == Z_OK) {
zerr = deflate(&mZstream, Z_NO_FLUSH);
while (mZstream.avail_out == 0) {
// buffer is full, push the data out to the listener
rv = PushAvailableData(aRequest, aContext);
NS_ENSURE_SUCCESS(rv, rv);
zerr = deflate(&mZstream, Z_NO_FLUSH);
}
}
return NS_OK;
}
NS_IMETHODIMP nsDeflateConverter::OnStartRequest(nsIRequest *aRequest,
nsISupports *aContext)
{
if (!mListener)
return NS_ERROR_NOT_INITIALIZED;
return mListener->OnStartRequest(aRequest, mContext);
}
NS_IMETHODIMP nsDeflateConverter::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatusCode)
{
if (!mListener)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv;
int zerr;
do {
zerr = deflate(&mZstream, Z_FINISH);
rv = PushAvailableData(aRequest, aContext);
NS_ENSURE_SUCCESS(rv, rv);
} while (zerr == Z_OK);
deflateEnd(&mZstream);
return mListener->OnStopRequest(aRequest, mContext, aStatusCode);
}
nsresult nsDeflateConverter::PushAvailableData(nsIRequest *aRequest,
nsISupports *aContext)
{
uint32_t bytesToWrite = sizeof(mWriteBuffer) - mZstream.avail_out;
// We don't need to do anything if there isn't any data
if (bytesToWrite == 0)
return NS_OK;
MOZ_ASSERT(bytesToWrite <= INT32_MAX);
nsCOMPtr<nsIInputStream> stream;
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
(char*)mWriteBuffer, bytesToWrite);
NS_ENSURE_SUCCESS(rv, rv);
rv = mListener->OnDataAvailable(aRequest, mContext, stream, mOffset,
bytesToWrite);
// now set the state for 'deflate'
mZstream.next_out = mWriteBuffer;
mZstream.avail_out = sizeof(mWriteBuffer);
mOffset += bytesToWrite;
return rv;
}

View file

@ -0,0 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _nsDeflateConverter_h_
#define _nsDeflateConverter_h_
#include "nsIStreamConverter.h"
#include "nsCOMPtr.h"
#include "nsIPipe.h"
#include "zlib.h"
#include "mozilla/Attributes.h"
#define DEFLATECONVERTER_CID { 0x461cd5dd, 0x73c6, 0x47a4, \
{ 0x8c, 0xc3, 0x60, 0x3b, 0x37, 0xd8, 0x4a, 0x61 } }
#define ZIP_BUFLEN (4 * 1024 - 1)
class nsDeflateConverter final : public nsIStreamConverter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISTREAMCONVERTER
nsDeflateConverter()
{
// 6 is Z_DEFAULT_COMPRESSION but we need the actual value
mLevel = 6;
}
explicit nsDeflateConverter(int32_t level)
{
mLevel = level;
}
private:
~nsDeflateConverter()
{
}
enum WrapMode {
WRAP_ZLIB,
WRAP_GZIP,
WRAP_NONE
};
WrapMode mWrapMode;
uint64_t mOffset;
int32_t mLevel;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mContext;
z_stream mZstream;
unsigned char mWriteBuffer[ZIP_BUFLEN];
nsresult Init();
nsresult PushAvailableData(nsIRequest *aRequest, nsISupports *aContext);
};
#endif

View file

@ -0,0 +1,220 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "nsISupports.idl"
interface nsIChannel;
interface nsIInputStream;
interface nsIRequestObserver;
interface nsIFile;
interface nsIZipEntry;
/**
* nsIZipWriter
*
* An interface for a zip archiver that can be used from script.
*
* The interface supports both a synchronous method of archiving data and a
* queueing system to allow operations to be prepared then run in sequence
* with notification after completion.
*
* Operations added to the queue do not get performed until performQueue is
* called at which point they will be performed in the order that they were
* added to the queue.
*
* Operations performed on the queue will throw any errors out to the
* observer.
*
* An attempt to perform a synchronous operation while the background queue
* is in progress will throw NS_ERROR_IN_PROGRESS.
*
* Entry names should use /'s as path separators and should not start with
* a /.
*
* It is not generally necessary to add directory entries in order to add file
* entries within them, however it is possible that some zip programs may
* experience problems what that.
*/
[scriptable, uuid(3ca10750-797e-4a22-bcfe-66170b5e96dd)]
interface nsIZipWriter : nsISupports
{
/**
* Some predefined compression levels
*/
const uint32_t COMPRESSION_NONE = 0;
const uint32_t COMPRESSION_FASTEST = 1;
const uint32_t COMPRESSION_DEFAULT = 6;
const uint32_t COMPRESSION_BEST = 9;
/**
* Gets or sets the comment associated with the open zip file.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
*/
attribute ACString comment;
/**
* Indicates that operations on the background queue are being performed.
*/
readonly attribute boolean inQueue;
/**
* The file that the zipwriter is writing to.
*/
readonly attribute nsIFile file;
/**
* Opens a zip file.
*
* @param aFile the zip file to open
* @param aIoFlags the open flags for the zip file from prio.h
*
* @throws NS_ERROR_ALREADY_INITIALIZED if a zip file is already open
* @throws NS_ERROR_INVALID_ARG if aFile is null
* @throws NS_ERROR_FILE_NOT_FOUND if aFile does not exist and flags did
* not allow for creation
* @throws NS_ERROR_FILE_CORRUPTED if the file does not contain zip markers
* @throws <other-error> on failure to open zip file (most likely corrupt
* or unsupported form)
*/
void open(in nsIFile aFile, in int32_t aIoFlags);
/**
* Returns a nsIZipEntry describing a specified zip entry or null if there
* is no such entry in the zip file
*
* @param aZipEntry the path of the entry
*/
nsIZipEntry getEntry(in AUTF8String aZipEntry);
/**
* Checks whether the zipfile contains an entry specified by zipEntry.
*
* @param aZipEntry the path of the entry
*/
boolean hasEntry(in AUTF8String aZipEntry);
/**
* Adds a new directory entry to the zip file. If aZipEntry does not end with
* "/" then it will be added.
*
* @param aZipEntry the path of the directory entry
* @param aModTime the modification time of the entry in microseconds
* @param aQueue adds the operation to the background queue. Will be
* performed when processQueue is called.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_FILE_ALREADY_EXISTS if the path already exists in the
* file
* @throws NS_ERROR_IN_PROGRESS if another operation is currently in progress
*/
void addEntryDirectory(in AUTF8String aZipEntry, in PRTime aModTime,
in boolean aQueue);
/**
* Adds a new file or directory to the zip file. If the specified file is
* a directory then this will be equivalent to a call to
* addEntryDirectory(aZipEntry, aFile.lastModifiedTime, aQueue)
*
* @param aZipEntry the path of the file entry
* @param aCompression the compression level, 0 is no compression, 9 is best
* @param aFile the file to get the data and modification time from
* @param aQueue adds the operation to the background queue. Will be
* performed when processQueue is called.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_FILE_ALREADY_EXISTS if the path already exists in the zip
* @throws NS_ERROR_IN_PROGRESS if another operation is currently in progress
* @throws NS_ERROR_FILE_NOT_FOUND if file does not exist
*/
void addEntryFile(in AUTF8String aZipEntry,
in int32_t aCompression, in nsIFile aFile,
in boolean aQueue);
/**
* Adds data from a channel to the zip file. If the operation is performed
* on the queue then the channel will be opened asynchronously, otherwise
* the channel must support being opened synchronously.
*
* @param aZipEntry the path of the file entry
* @param aModTime the modification time of the entry in microseconds
* @param aCompression the compression level, 0 is no compression, 9 is best
* @param aChannel the channel to get the data from
* @param aQueue adds the operation to the background queue. Will be
* performed when processQueue is called.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_FILE_ALREADY_EXISTS if the path already exists in the zip
* @throws NS_ERROR_IN_PROGRESS if another operation is currently in progress
*/
void addEntryChannel(in AUTF8String aZipEntry, in PRTime aModTime,
in int32_t aCompression, in nsIChannel aChannel,
in boolean aQueue);
/**
* Adds data from an input stream to the zip file.
*
* @param aZipEntry the path of the file entry
* @param aModTime the modification time of the entry in microseconds
* @param aCompression the compression level, 0 is no compression, 9 is best
* @param aStream the input stream to get the data from
* @param aQueue adds the operation to the background queue. Will be
* performed when processQueue is called.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_FILE_ALREADY_EXISTS if the path already exists in the zip
* @throws NS_ERROR_IN_PROGRESS if another operation is currently in progress
*/
void addEntryStream(in AUTF8String aZipEntry, in PRTime aModTime,
in int32_t aCompression, in nsIInputStream aStream,
in boolean aQueue);
/**
* Removes an existing entry from the zip file.
*
* @param aZipEntry the path of the entry to be removed
* @param aQueue adds the operation to the background queue. Will be
* performed when processQueue is called.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_IN_PROGRESS if another operation is currently in progress
* @throws NS_ERROR_FILE_NOT_FOUND if no entry with the given path exists
* @throws <other-error> on failure to update the zip file
*/
void removeEntry(in AUTF8String aZipEntry, in boolean aQueue);
/**
* Processes all queued items until complete or some error occurs. The
* observer will be notified when the first operation starts and when the
* last operation completes. Any failures will be passed to the observer.
* The zip writer will be busy until the queue is complete or some error
* halted processing of the queue early. In the event of an early failure,
* remaining items will stay in the queue and calling processQueue will
* continue.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_IN_PROGRESS if the queue is already in progress
*/
void processQueue(in nsIRequestObserver aObserver, in nsISupports aContext);
/**
* Closes the zip file.
*
* @throws NS_ERROR_NOT_INITIALIZED if no zip file has been opened
* @throws NS_ERROR_IN_PROGRESS if another operation is currently in progress
* @throws <other-error> on failure to complete the zip file
*/
void close();
/**
* Make all stored(uncompressed) files align to given alignment size.
*
* @param aAlignSize is the alignment size, valid values from 2 to 32768, and
must be power of 2.
*
* @throws NS_ERROR_INVALID_ARG if aAlignSize is invalid
* @throws <other-error> on failure to update the zip file
*/
void alignStoredFiles(in uint16_t aAlignSize);
};

View file

@ -0,0 +1,181 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "StreamFunctions.h"
#include "nsZipDataStream.h"
#include "nsStringStream.h"
#include "nsISeekableStream.h"
#include "nsDeflateConverter.h"
#include "nsNetUtil.h"
#include "nsComponentManagerUtils.h"
#include "nsMemory.h"
#define ZIP_METHOD_STORE 0
#define ZIP_METHOD_DEFLATE 8
using namespace mozilla;
/**
* nsZipDataStream handles the writing an entry's into the zip file.
* It is set up to wither write the data as is, or in the event that compression
* has been requested to pass it through a stream converter.
* Currently only the deflate compression method is supported.
* The CRC checksum for the entry's data is also generated here.
*/
NS_IMPL_ISUPPORTS(nsZipDataStream, nsIStreamListener,
nsIRequestObserver)
nsresult nsZipDataStream::Init(nsZipWriter *aWriter,
nsIOutputStream *aStream,
nsZipHeader *aHeader,
int32_t aCompression)
{
mWriter = aWriter;
mHeader = aHeader;
mStream = aStream;
mHeader->mCRC = crc32(0L, Z_NULL, 0);
nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
if (aCompression > 0) {
mHeader->mMethod = ZIP_METHOD_DEFLATE;
nsCOMPtr<nsIStreamConverter> converter =
new nsDeflateConverter(aCompression);
NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY);
rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
mOutput = do_QueryInterface(converter, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
mHeader->mMethod = ZIP_METHOD_STORE;
}
return NS_OK;
}
NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
uint64_t aOffset,
uint32_t aCount)
{
if (!mOutput)
return NS_ERROR_NOT_INITIALIZED;
auto buffer = MakeUnique<char[]>(aCount);
NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
NS_ENSURE_SUCCESS(rv, rv);
return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount);
}
NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest,
nsISupports *aContext)
{
if (!mOutput)
return NS_ERROR_NOT_INITIALIZED;
return mOutput->OnStartRequest(aRequest, aContext);
}
NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatusCode)
{
if (!mOutput)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv = mOutput->OnStopRequest(aRequest, aContext, aStatusCode);
mOutput = nullptr;
if (NS_FAILED(rv)) {
mWriter->EntryCompleteCallback(mHeader, rv);
}
else {
rv = CompleteEntry();
rv = mWriter->EntryCompleteCallback(mHeader, rv);
}
mStream = nullptr;
mWriter = nullptr;
mHeader = nullptr;
return rv;
}
inline nsresult nsZipDataStream::CompleteEntry()
{
nsresult rv;
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv);
NS_ENSURE_SUCCESS(rv, rv);
int64_t pos;
rv = seekable->Tell(&pos);
NS_ENSURE_SUCCESS(rv, rv);
mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
mHeader->mWriteOnClose = true;
return NS_OK;
}
nsresult nsZipDataStream::ProcessData(nsIRequest *aRequest,
nsISupports *aContext, char *aBuffer,
uint64_t aOffset, uint32_t aCount)
{
mHeader->mCRC = crc32(mHeader->mCRC,
reinterpret_cast<const unsigned char*>(aBuffer),
aCount);
MOZ_ASSERT(aCount <= INT32_MAX);
nsCOMPtr<nsIInputStream> stream;
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
aBuffer, aCount);
NS_ENSURE_SUCCESS(rv, rv);
rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount);
mHeader->mUSize += aCount;
return rv;
}
nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream)
{
if (!mOutput)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv = OnStartRequest(nullptr, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
auto buffer = MakeUnique<char[]>(4096);
NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
uint32_t read = 0;
uint32_t offset = 0;
do
{
rv = aStream->Read(buffer.get(), 4096, &read);
if (NS_FAILED(rv)) {
OnStopRequest(nullptr, nullptr, rv);
return rv;
}
if (read > 0) {
rv = ProcessData(nullptr, nullptr, buffer.get(), offset, read);
if (NS_FAILED(rv)) {
OnStopRequest(nullptr, nullptr, rv);
return rv;
}
offset += read;
}
} while (read > 0);
return OnStopRequest(nullptr, nullptr, NS_OK);
}

View file

@ -0,0 +1,45 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _nsZipDataStream_h_
#define _nsZipDataStream_h_
#include "nsZipWriter.h"
#include "nsIOutputStream.h"
#include "nsIStreamListener.h"
#include "nsAutoPtr.h"
#include "mozilla/Attributes.h"
class nsZipDataStream final : public nsIStreamListener
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
nsZipDataStream()
{
}
nsresult Init(nsZipWriter *aWriter, nsIOutputStream *aStream,
nsZipHeader *aHeader, int32_t aCompression);
nsresult ReadStream(nsIInputStream *aStream);
private:
~nsZipDataStream() {}
nsCOMPtr<nsIStreamListener> mOutput;
nsCOMPtr<nsIOutputStream> mStream;
RefPtr<nsZipWriter> mWriter;
RefPtr<nsZipHeader> mHeader;
nsresult CompleteEntry();
nsresult ProcessData(nsIRequest *aRequest, nsISupports *aContext,
char *aBuffer, uint64_t aOffset, uint32_t aCount);
};
#endif

View file

@ -0,0 +1,389 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "StreamFunctions.h"
#include "nsZipHeader.h"
#include "nsMemory.h"
#include "prtime.h"
#define ZIP_FILE_HEADER_SIGNATURE 0x04034b50
#define ZIP_FILE_HEADER_SIZE 30
#define ZIP_CDS_HEADER_SIGNATURE 0x02014b50
#define ZIP_CDS_HEADER_SIZE 46
#define FLAGS_IS_UTF8 0x800
#define ZIP_EXTENDED_TIMESTAMP_FIELD 0x5455
#define ZIP_EXTENDED_TIMESTAMP_MODTIME 0x01
using namespace mozilla;
/**
* nsZipHeader represents an entry from a zip file.
*/
NS_IMPL_ISUPPORTS(nsZipHeader, nsIZipEntry)
NS_IMETHODIMP nsZipHeader::GetCompression(uint16_t *aCompression)
{
NS_ASSERTION(mInited, "Not initalised");
*aCompression = mMethod;
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetSize(uint32_t *aSize)
{
NS_ASSERTION(mInited, "Not initalised");
*aSize = mCSize;
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetRealSize(uint32_t *aRealSize)
{
NS_ASSERTION(mInited, "Not initalised");
*aRealSize = mUSize;
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetCRC32(uint32_t *aCRC32)
{
NS_ASSERTION(mInited, "Not initalised");
*aCRC32 = mCRC;
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetIsDirectory(bool *aIsDirectory)
{
NS_ASSERTION(mInited, "Not initalised");
if (mName.Last() == '/')
*aIsDirectory = true;
else
*aIsDirectory = false;
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetLastModifiedTime(PRTime *aLastModifiedTime)
{
NS_ASSERTION(mInited, "Not initalised");
// Try to read timestamp from extra field
uint16_t blocksize;
const uint8_t *tsField = GetExtraField(ZIP_EXTENDED_TIMESTAMP_FIELD, false, &blocksize);
if (tsField && blocksize >= 5) {
uint32_t pos = 4;
uint8_t 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) & 0x1F;
time.tm_min = (mTime >> 5) & 0x3F;
time.tm_sec = (mTime & 0x1F) * 2;
time.tm_year = (mDate >> 9) + 1980;
time.tm_month = ((mDate >> 5) & 0x0F) - 1;
time.tm_mday = mDate & 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;
*aLastModifiedTime = PR_ImplodeTime(&time);
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetIsSynthetic(bool *aIsSynthetic)
{
NS_ASSERTION(mInited, "Not initalised");
*aIsSynthetic = false;
return NS_OK;
}
NS_IMETHODIMP nsZipHeader::GetPermissions(uint32_t *aPermissions)
{
NS_ASSERTION(mInited, "Not initalised");
// Always give user read access at least, this matches nsIZipReader's behaviour
*aPermissions = ((mEAttr >> 16) & 0xfff) | 0x100;
return NS_OK;
}
void nsZipHeader::Init(const nsACString & aPath, PRTime aDate, uint32_t aAttr,
uint32_t aOffset)
{
NS_ASSERTION(!mInited, "Already initalised");
PRExplodedTime time;
PR_ExplodeTime(aDate, PR_LocalTimeParameters, &time);
mTime = time.tm_sec / 2 + (time.tm_min << 5) + (time.tm_hour << 11);
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 = MakeUnique<uint8_t[]>(mFieldLength);
if (!mExtraField) {
mFieldLength = 0;
} else {
uint32_t 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 = MakeUnique<uint8_t[]>(mFieldLength);
if (mLocalExtraField) {
mLocalFieldLength = mFieldLength;
memcpy(mLocalExtraField.get(), mExtraField.get(), mLocalFieldLength);
}
}
mEAttr = aAttr;
mOffset = aOffset;
mName = aPath;
mComment = NS_LITERAL_CSTRING("");
// Claim a UTF-8 path in case it needs it.
mFlags |= FLAGS_IS_UTF8;
mInited = true;
}
uint32_t nsZipHeader::GetFileHeaderLength()
{
return ZIP_FILE_HEADER_SIZE + mName.Length() + mLocalFieldLength;
}
nsresult nsZipHeader::WriteFileHeader(nsIOutputStream *aStream)
{
NS_ASSERTION(mInited, "Not initalised");
uint8_t buf[ZIP_FILE_HEADER_SIZE];
uint32_t pos = 0;
WRITE32(buf, &pos, ZIP_FILE_HEADER_SIGNATURE);
WRITE16(buf, &pos, mVersionNeeded);
WRITE16(buf, &pos, mFlags);
WRITE16(buf, &pos, mMethod);
WRITE16(buf, &pos, mTime);
WRITE16(buf, &pos, mDate);
WRITE32(buf, &pos, mCRC);
WRITE32(buf, &pos, mCSize);
WRITE32(buf, &pos, mUSize);
WRITE16(buf, &pos, mName.Length());
WRITE16(buf, &pos, mLocalFieldLength);
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 (mLocalFieldLength)
{
rv = ZW_WriteData(aStream, (const char *)mLocalExtraField.get(), mLocalFieldLength);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
uint32_t nsZipHeader::GetCDSHeaderLength()
{
return ZIP_CDS_HEADER_SIZE + mName.Length() + mComment.Length() +
mFieldLength;
}
nsresult nsZipHeader::WriteCDSHeader(nsIOutputStream *aStream)
{
NS_ASSERTION(mInited, "Not initalised");
uint8_t buf[ZIP_CDS_HEADER_SIZE];
uint32_t pos = 0;
WRITE32(buf, &pos, ZIP_CDS_HEADER_SIGNATURE);
WRITE16(buf, &pos, mVersionMade);
WRITE16(buf, &pos, mVersionNeeded);
WRITE16(buf, &pos, mFlags);
WRITE16(buf, &pos, mMethod);
WRITE16(buf, &pos, mTime);
WRITE16(buf, &pos, mDate);
WRITE32(buf, &pos, mCRC);
WRITE32(buf, &pos, mCSize);
WRITE32(buf, &pos, mUSize);
WRITE16(buf, &pos, mName.Length());
WRITE16(buf, &pos, mFieldLength);
WRITE16(buf, &pos, mComment.Length());
WRITE16(buf, &pos, mDisk);
WRITE16(buf, &pos, mIAttr);
WRITE32(buf, &pos, mEAttr);
WRITE32(buf, &pos, mOffset);
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, (const char *)mExtraField.get(), mFieldLength);
NS_ENSURE_SUCCESS(rv, rv);
}
return ZW_WriteData(aStream, mComment.get(), mComment.Length());
}
nsresult nsZipHeader::ReadCDSHeader(nsIInputStream *stream)
{
NS_ASSERTION(!mInited, "Already initalised");
uint8_t buf[ZIP_CDS_HEADER_SIZE];
nsresult rv = ZW_ReadData(stream, (char *)buf, ZIP_CDS_HEADER_SIZE);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t pos = 0;
uint32_t signature = READ32(buf, &pos);
if (signature != ZIP_CDS_HEADER_SIGNATURE)
return NS_ERROR_FILE_CORRUPTED;
mVersionMade = READ16(buf, &pos);
mVersionNeeded = READ16(buf, &pos);
mFlags = READ16(buf, &pos);
mMethod = READ16(buf, &pos);
mTime = READ16(buf, &pos);
mDate = READ16(buf, &pos);
mCRC = READ32(buf, &pos);
mCSize = READ32(buf, &pos);
mUSize = READ32(buf, &pos);
uint16_t namelength = READ16(buf, &pos);
mFieldLength = READ16(buf, &pos);
uint16_t commentlength = READ16(buf, &pos);
mDisk = READ16(buf, &pos);
mIAttr = READ16(buf, &pos);
mEAttr = READ32(buf, &pos);
mOffset = READ32(buf, &pos);
if (namelength > 0) {
auto field = MakeUnique<char[]>(namelength);
NS_ENSURE_TRUE(field, NS_ERROR_OUT_OF_MEMORY);
rv = ZW_ReadData(stream, field.get(), namelength);
NS_ENSURE_SUCCESS(rv, rv);
mName.Assign(field.get(), namelength);
}
else
mName = NS_LITERAL_CSTRING("");
if (mFieldLength > 0) {
mExtraField = MakeUnique<uint8_t[]>(mFieldLength);
NS_ENSURE_TRUE(mExtraField, NS_ERROR_OUT_OF_MEMORY);
rv = ZW_ReadData(stream, (char *)mExtraField.get(), mFieldLength);
NS_ENSURE_SUCCESS(rv, rv);
}
if (commentlength > 0) {
auto field = MakeUnique<char[]>(commentlength);
NS_ENSURE_TRUE(field, NS_ERROR_OUT_OF_MEMORY);
rv = ZW_ReadData(stream, field.get(), commentlength);
NS_ENSURE_SUCCESS(rv, rv);
mComment.Assign(field.get(), commentlength);
}
else
mComment = NS_LITERAL_CSTRING("");
mInited = true;
return NS_OK;
}
const uint8_t * nsZipHeader::GetExtraField(uint16_t aTag, bool aLocal, uint16_t *aBlockSize)
{
const uint8_t *buf = aLocal ? mLocalExtraField.get() : mExtraField.get();
uint32_t buflen = aLocal ? mLocalFieldLength : mFieldLength;
uint32_t pos = 0;
uint16_t 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 nullptr;
}
/*
* Pad extra field to align data starting position to specified size.
*/
nsresult nsZipHeader::PadExtraField(uint32_t aOffset, uint16_t aAlignSize)
{
uint32_t pad_size;
uint32_t pa_offset;
uint32_t pa_end;
// Check for range and power of 2.
if (aAlignSize < 2 || aAlignSize > 32768 ||
(aAlignSize & (aAlignSize - 1)) != 0) {
return NS_ERROR_INVALID_ARG;
}
// Point to current starting data position.
aOffset += ZIP_FILE_HEADER_SIZE + mName.Length() + mLocalFieldLength;
// Calculate aligned offset.
pa_offset = aOffset & ~(aAlignSize - 1);
pa_end = pa_offset + aAlignSize;
pad_size = pa_end - aOffset;
if (pad_size == 0) {
return NS_OK;
}
// Leave enough room(at least 4 bytes) for valid values in extra field.
while (pad_size < 4) {
pad_size += aAlignSize;
}
// Extra field length is 2 bytes.
if (mLocalFieldLength + pad_size > 65535) {
return NS_ERROR_FAILURE;
}
UniquePtr<uint8_t[]> field = Move(mLocalExtraField);
uint32_t pos = mLocalFieldLength;
mLocalExtraField = MakeUnique<uint8_t[]>(mLocalFieldLength + pad_size);
memcpy(mLocalExtraField.get(), field.get(), mLocalFieldLength);
// Use 0xFFFF as tag ID to avoid conflict with other IDs.
// For more information, please read "Extensible data fields" section in:
// http://www.pkware.com/documents/casestudies/APPNOTE.TXT
WRITE16(mLocalExtraField.get(), &pos, 0xFFFF);
WRITE16(mLocalExtraField.get(), &pos, pad_size - 4);
memset(mLocalExtraField.get() + pos, 0, pad_size - 4);
mLocalFieldLength += pad_size;
return NS_OK;
}

View file

@ -0,0 +1,94 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _nsZipHeader_h_
#define _nsZipHeader_h_
#include "nsString.h"
#include "nsIOutputStream.h"
#include "nsIInputStream.h"
#include "nsIZipReader.h"
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
// High word is S_IFREG, low word is DOS file attribute
#define ZIP_ATTRS_FILE 0x80000000
// High word is S_IFDIR, low word is DOS dir attribute
#define ZIP_ATTRS_DIRECTORY 0x40000010
#define PERMISSIONS_FILE 0644
#define PERMISSIONS_DIR 0755
// Combine file type attributes with unix style permissions
#define ZIP_ATTRS(p, a) ((p & 0xfff) << 16) | a
class nsZipHeader final : public nsIZipEntry
{
~nsZipHeader()
{
mExtraField = nullptr;
mLocalExtraField = nullptr;
}
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIZIPENTRY
nsZipHeader() :
mCRC(0),
mCSize(0),
mUSize(0),
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),
mMethod(0),
mTime(0),
mDate(0),
mDisk(0),
mIAttr(0),
mInited(false),
mWriteOnClose(false),
mExtraField(nullptr),
mLocalExtraField(nullptr)
{
}
uint32_t mCRC;
uint32_t mCSize;
uint32_t mUSize;
uint32_t mEAttr;
uint32_t mOffset;
uint32_t mFieldLength;
uint32_t mLocalFieldLength;
uint16_t mVersionMade;
uint16_t mVersionNeeded;
uint16_t mFlags;
uint16_t mMethod;
uint16_t mTime;
uint16_t mDate;
uint16_t mDisk;
uint16_t mIAttr;
bool mInited;
bool mWriteOnClose;
nsCString mName;
nsCString mComment;
mozilla::UniquePtr<uint8_t[]> mExtraField;
mozilla::UniquePtr<uint8_t[]> mLocalExtraField;
void Init(const nsACString & aPath, PRTime aDate, uint32_t aAttr,
uint32_t aOffset);
uint32_t GetFileHeaderLength();
nsresult WriteFileHeader(nsIOutputStream *aStream);
uint32_t GetCDSHeaderLength();
nsresult WriteCDSHeader(nsIOutputStream *aStream);
nsresult ReadCDSHeader(nsIInputStream *aStream);
const uint8_t * GetExtraField(uint16_t aTag, bool aLocal, uint16_t *aBlockSize);
nsresult PadExtraField(uint32_t aOffset, uint16_t aAlignSize);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,80 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _nsZipWriter_h_
#define _nsZipWriter_h_
#include "nsIZipWriter.h"
#include "nsIFileStreams.h"
#include "nsIBufferedStreams.h"
#include "nsIRequestObserver.h"
#include "nsZipHeader.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsDataHashtable.h"
#include "mozilla/Attributes.h"
#define ZIPWRITER_CONTRACTID "@mozilla.org/zipwriter;1"
#define ZIPWRITER_CID { 0x430d416c, 0xa722, 0x4ad1, \
{ 0xbe, 0x98, 0xd9, 0xa4, 0x45, 0xf8, 0x5e, 0x3f } }
#define OPERATION_ADD 0
#define OPERATION_REMOVE 1
struct nsZipQueueItem
{
public:
uint32_t mOperation;
nsCString mZipEntry;
nsCOMPtr<nsIFile> mFile;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIInputStream> mStream;
PRTime mModTime;
int32_t mCompression;
uint32_t mPermissions;
};
class nsZipWriter final : public nsIZipWriter,
public nsIRequestObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIZIPWRITER
NS_DECL_NSIREQUESTOBSERVER
nsZipWriter();
nsresult EntryCompleteCallback(nsZipHeader *aHeader, nsresult aStatus);
private:
~nsZipWriter();
uint32_t mCDSOffset;
bool mCDSDirty;
bool mInQueue;
nsCOMPtr<nsIFile> mFile;
nsCOMPtr<nsIRequestObserver> mProcessObserver;
nsCOMPtr<nsISupports> mProcessContext;
nsCOMPtr<nsIOutputStream> mStream;
nsCOMArray<nsZipHeader> mHeaders;
nsTArray<nsZipQueueItem> mQueue;
nsDataHashtable<nsCStringHashKey, int32_t> mEntryHash;
nsCString mComment;
nsresult SeekCDS();
void Cleanup();
nsresult ReadFile(nsIFile *aFile);
nsresult InternalAddEntryDirectory(const nsACString & aZipEntry,
PRTime aModTime, uint32_t aPermissions);
nsresult BeginProcessingAddition(nsZipQueueItem* aItem, bool* complete);
nsresult BeginProcessingRemoval(int32_t aPos);
nsresult AddEntryStream(const nsACString & aZipEntry, PRTime aModTime,
int32_t aCompression, nsIInputStream *aStream,
bool aQueue, uint32_t aPermissions);
void BeginProcessingNextItem();
void FinishQueue(nsresult aStatus);
};
#endif

View file

@ -0,0 +1 @@
Small (16 bytes)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -0,0 +1,5 @@
This is a test text file for the zipwriter component.
It will be made available in the unit test directory.
It will also be compressed into a testcase zip file
made by a 3rd party zip tool to test the opening of
existing zip files.

Binary file not shown.

View file

@ -0,0 +1,160 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="Content-Language" content="en-gb"><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><meta name="generator" content="Fog Creek CityDesk 2.0.19"><meta name="citydesk" content="BB40F561/251"><title>TK's Sleater-Kinney pages</title><style type="text/css">
<!--
body {
font-family: verdana, arial;
font-size: 10pt;
color: black;
background-color: #D0E8E8;
}
td {
font-family: verdana, arial;
font-size: 10pt;
}
hr {
color: #808080;
height: 1px;
}
caption {
font-family: verdana, arial;
font-size: 8pt;
color: #808080;
background-color: white;
}
.bigText {
font-family: verdana, arial;
font-size: 18pt;
font-weight: bold;
color: black;
padding-bottom: 10px;
}
.smallText {
font-family: verdana, arial;
font-size: 7pt;
color: #808080;
}
.tabText {
font-family: Courier, "Courier New", monospace;
font-size: 7pt;
color: #808080;
}
.emphasis
{
font-weight: bold;
color: #000000;
}
.articleHeader {
padding-bottom: 4px;
border-bottom: #808080 dotted 1px;
}
.headerCell {
background-color: #689090;
color: white;
padding: 4px;
}
.navbarText {
color: white;
font-weight: bold;
}
.articleTable {
border: #808080 solid 1px;
background-color: white;
padding: 15px;
}
-->
</style></head><body>
<div align="center">
<center>
<table border="0" cellpadding="0" cellspacing="0" width="700">
<tbody><tr>
<td><p class="bigText">TK's Sleater-Kinney pages</p>
</td>
</tr>
<tr>
<td valign="top">
<table class="articleTable" border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td class="headerCell" align="right"><p class="navbarText">
: <a class="navbarText" href="http://tk-jk.net/S-K/index.html"> <span class="1home">Home</span></a>
: <a class="navbarText" href="http://tk-jk.net/S-K/blog/general/Archive.html"> <span class="2archive">Archive</span></a>
: <a class="navbarText" href="http://tk-jk.net/S-K/blog/general/Tabs.html"> <span class="3tabs">Tabs</span></a>
: <a class="navbarText" href="http://tk-jk.net/S-K/blog/general/Drumtabs.html"> <span class="4drumtabs">Drum tabs</span></a>
: <a class="navbarText" href="http://tk-jk.net/S-K/blog/general/SetLists.html"> <span class="5setlists">Set Lists</span></a>
: <a class="navbarText" href="http://tk-jk.net/S-K/blog/general/About.html"> <span class="6about">About</span></a> :
</p>
</td>
</tr>
<tr>
<td valign="top">
<div align="left">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td width="100%">
<p class="bigText"><strong>All Hands on the Bad One</strong>
</p>
<p></p><p><strong>All Hands on the Bad One, <em>"All Hands on the Bad One"</em></strong></p>
<p dir="ltr">This, followed by <a href="http://tk-jk.net/S-K/Tabs/YouthDecay.html">Youth Decay</a>&nbsp;- wow - most bands would be happy just to have just one of these songs.&nbsp; S-K has a boatload.</p>
<p dir="ltr">Tabbing this was very frustrating.&nbsp;Riff 3 is a
masterpiece of guitar and vocal harmony, rhythm and guitar
interplay.&nbsp; It has a bass intro and stacks guitars and vocals on
top. This is the definition of Sleater-Kinney magic. You can't&nbsp;get
it all done on two guitars.&nbsp; You can get close.&nbsp;&nbsp; I
haven't done it justice.</p>
<p dir="ltr">As usual the guitar 2's rhythms are vital to the S-K sound.&nbsp; It's still good if you don't get it just right.</p>
<p dir="ltr">I sure hope I've done this well enough for you to figure out.</p>
<ul dir="ltr">
<li>
<div style="margin-right: 0px;">Quarter note =&nbsp;153 or so.</div>
</li><li>
<div style="margin-right: 0px;">Standard tuning. But tuning down 3 half steps makes Riff 3 easier and more authentic.</div>
</li><li>
<div style="margin-right: 0px;">Tabbed&nbsp;where it felt good&nbsp;on the fretboard but there are alternatives.</div>
</li><li>
<div style="margin-right: 0px;">Tuning down is required for authenticity but it sounds great in standard tuning</div></li></ul><strong>
</strong><p dir="ltr"><strong><br>1:</strong></p>
<p></p><span><img alt="All Hands on the Bad One Riff 1" src="AllHandsontheBadOne_files/AHOTBO1.jpg" cd:pos="2" align="left" border="0" height="500" hspace="4" width="580"><br clear="all"></span>
<p><strong></strong>&nbsp;</p>
<p><strong>2:</strong></p><span><img alt="All Hands on the Bad One Riff 2" src="AllHandsontheBadOne_files/AHOTBO2.jpg" cd:pos="2" align="left" border="0" height="257" hspace="4" width="580"><br clear="all"></span>
<p><strong></strong>&nbsp;</p>
<p><strong>Riff 3 (3a and 3b) is a little masterpeice:</strong></p><span><img alt="All Hands on the Bad One Riff 3a" src="AllHandsontheBadOne_files/AHOTBO3a.jpg" cd:pos="2" align="left" border="0" height="446" hspace="4" width="580"><br clear="all"></span>
<p><span><img alt="All Hands on the Bad One Riff 3b" src="AllHandsontheBadOne_files/AHOTBO3b.jpg" cd:pos="2" align="left" border="0" height="179" hspace="4" width="580"><br clear="all"></span></p>
<p>&nbsp;</p>
<p>The Outro</p>
<p><span><img alt="All Hands on the Bad One Riff 4" src="AllHandsontheBadOne_files/AHOTBO4.jpg" cd:pos="2" align="left" border="0" height="216" hspace="4" width="580"><br clear="all"></span></p><p></p>
</td>
</tr>
</tbody></table>
</div>
</td>
</tr>
<tr>
<td valign="top">
<hr>
<center>
<div class="smallText">
The views expressed within this site pretty much represent those of the author.<br>
Copyright (c) 2002 <a href="http://tk-jk.net/">Terry Kearns</a>. All rights reserved.
</div>
</center>
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</center>
</div>
</body></html>

View file

@ -0,0 +1,16 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="Content-Language" content="en-us"><title>Lorem Ipsum</title><style type="text/css">
body {
font-family: verdana, arial;
font-size: 10pt;
color: black;
background-color: #D0E8E8;
}
</style></head><body>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.</p>
</body></html>

View file

@ -0,0 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
var Ci = Components.interfaces;
var Cc = Components.classes;
const NS_ERROR_IN_PROGRESS = 2152398863;
const PR_RDONLY = 0x01
const PR_WRONLY = 0x02
const PR_RDWR = 0x04
const PR_CREATE_FILE = 0x08
const PR_APPEND = 0x10
const PR_TRUNCATE = 0x20
const PR_SYNC = 0x40
const PR_EXCL = 0x80
const ZIP_EOCDR_HEADER_SIZE = 22;
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;
const PR_USEC_PER_SEC = 1000000;
const PR_MSEC_PER_SEC = 1000;
const DATA_DIR = "data/";
var ioSvc = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var ZipWriter = Components.Constructor("@mozilla.org/zipwriter;1",
"nsIZipWriter");
var ZipReader = Components.Constructor("@mozilla.org/libjar/zip-reader;1",
"nsIZipReader", "open");
var tmpDir = do_get_profile();
var tmpFile = tmpDir.clone();
tmpFile.append("zipwriter-test.zip");
if (tmpFile.exists())
tmpFile.remove(true);
var zipW = new ZipWriter();

View file

@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
try {
zipW.close();
}
catch (e) {
// Just ignore a failure here and attempt to delete the file anyway.
}
if (tmpFile.exists())
tmpFile.remove(true);

View file

@ -0,0 +1,113 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "ZIP WRITER TEST DATA";
const FILENAME = "test_data.txt";
const CRC = 0xe6164331;
const time = 1199145600000; // Jan 1st 2008
var TESTS = [
{
name: "test.txt",
compression: Ci.nsIZipWriter.COMPRESSION_DEFAULT
},
{
name: "test.png",
compression: Ci.nsIZipWriter.COMPRESSION_NONE
}
];
function swap16(n)
{
return (((n >> 8) & 0xFF) << 0) |
(((n >> 0) & 0xFF) << 8);
}
function swap32(n)
{
return (((n >> 24) & 0xFF) << 0) |
(((n >> 16) & 0xFF) << 8) |
(((n >> 8) & 0xFF) << 16) |
(((n >> 0) & 0xFF) << 24);
}
function move_to_data(bis, offset)
{
bis.readBytes(18); // Move to compressed size
var size = swap32(bis.read32());
bis.readBytes(4);
var file_len = swap16(bis.read16());
var extra_len = swap16(bis.read16());
var file = bis.readBytes(file_len);
bis.readBytes(extra_len);
offset += ZIP_FILE_HEADER_SIZE + file_len + extra_len;
return {offset: offset, size: size};
}
function test_alignment(align_size)
{
// Create zip for testing.
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR + TESTS[i].name);
zipW.addEntryFile(TESTS[i].name, TESTS[i].compression, source, false);
}
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData(DATA, DATA.length);
zipW.addEntryStream(FILENAME, time * PR_USEC_PER_MSEC,
Ci.nsIZipWriter.COMPRESSION_NONE, stream, false);
zipW.alignStoredFiles(align_size);
zipW.close();
// Check data can be decompressed.
var zipR = new ZipReader(tmpFile);
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
stream.init(zipR.getInputStream(FILENAME));
var result = stream.read(DATA.length);
do_check_eq(result, DATA);
stream.close();
zipR.close();
// Check data is correct and aligned.
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
fis.init(tmpFile, -1, -1, null);
let bis = Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream);
bis.setInputStream(fis);
var offset = 0;
var ret = move_to_data(bis, offset); // "test.txt"
offset = ret.offset;
bis.readBytes(ret.size);
offset += ret.size;
ret = move_to_data(bis, offset); // "test.png"
offset = ret.offset;
do_check_eq(offset % align_size, 0);
bis.readBytes(ret.size);
offset += ret.size;
ret = move_to_data(bis, offset); // "test_data.txt"
offset = ret.offset;
var result = bis.readBytes(DATA.length);
do_check_eq(result, DATA);
do_check_eq(offset % align_size, 0);
fis.close();
bis.close();
}
function run_test()
{
test_alignment(2);
test_alignment(4);
test_alignment(16);
test_alignment(4096);
test_alignment(32768);
}

View file

@ -0,0 +1,107 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
var Cu = Components.utils;
Cu.import("resource://gre/modules/NetUtil.jsm");
// Values taken from using zipinfo to list the test.zip contents
var TESTS = [
{
name: "test.txt",
size: 232,
crc: 0x0373ac26
},
{
name: "test.png",
size: 3402,
crc: 0x504a5c30
}
];
var size = 0;
var observer = {
onStartRequest: function(request, context)
{
},
onStopRequest: function(request, context, status)
{
do_check_eq(status, Components.results.NS_OK);
zipW.close();
size += ZIP_EOCDR_HEADER_SIZE;
do_check_eq(size, tmpFile.fileSize);
// Test the stored data with the zipreader
var zipR = new ZipReader(tmpFile);
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR + TESTS[i].name);
for (let method in methods) {
var entryName = method + "/" + TESTS[i].name;
do_check_true(zipR.hasEntry(entryName));
var entry = zipR.getEntry(entryName);
do_check_eq(entry.realSize, TESTS[i].size);
do_check_eq(entry.size, TESTS[i].size);
do_check_eq(entry.CRC32, TESTS[i].crc);
do_check_eq(Math.floor(entry.lastModifiedTime / PR_USEC_PER_SEC),
Math.floor(source.lastModifiedTime / PR_MSEC_PER_SEC));
zipR.test(entryName);
}
}
zipR.close();
do_test_finished();
}
};
var methods = {
file: function method_file(entry, source)
{
zipW.addEntryFile(entry, Ci.nsIZipWriter.COMPRESSION_NONE, source,
true);
},
channel: function method_channel(entry, source)
{
zipW.addEntryChannel(entry, source.lastModifiedTime * PR_MSEC_PER_SEC,
Ci.nsIZipWriter.COMPRESSION_NONE,
NetUtil.newChannel({
uri: ioSvc.newFileURI(source),
loadUsingSystemPrincipal: true
}), true);
},
stream: function method_stream(entry, source)
{
zipW.addEntryStream(entry, source.lastModifiedTime * PR_MSEC_PER_SEC,
Ci.nsIZipWriter.COMPRESSION_NONE,
NetUtil.newChannel({
uri: ioSvc.newFileURI(source),
loadUsingSystemPrincipal: true
}).open2(), true);
}
}
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR+TESTS[i].name);
for (let method in methods) {
var entry = method + "/" + TESTS[i].name;
methods[method](entry, source);
size += ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
(ZIP_EXTENDED_TIMESTAMP_SIZE * 2) +
(entry.length*2) + TESTS[i].size;
}
}
do_test_pending();
zipW.processQueue(observer, null);
do_check_true(zipW.inQueue);
}

View file

@ -0,0 +1,35 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const FILENAME = "missing.txt";
var observer = {
onStartRequest: function(request, context)
{
},
onStopRequest: function(request, context, status)
{
do_check_eq(status, Components.results.NS_ERROR_FILE_NOT_FOUND);
zipW.close();
do_check_eq(ZIP_EOCDR_HEADER_SIZE, tmpFile.fileSize);
do_test_finished();
}
};
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
var source = tmpDir.clone();
source.append(FILENAME);
zipW.addEntryFile(FILENAME, Ci.nsIZipWriter.COMPRESSION_NONE, source, true);
do_test_pending();
zipW.processQueue(observer, null);
// With nothing to actually do the queue would have completed immediately
do_check_false(zipW.inQueue);
}

View file

@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const FILENAME = "missing.txt";
var observer = {
onStartRequest: function(request, context)
{
},
onStopRequest: function(request, context, status)
{
do_check_eq(status, Components.results.NS_ERROR_FILE_NOT_FOUND);
zipW.close();
do_check_eq(ZIP_EOCDR_HEADER_SIZE, tmpFile.fileSize);
do_test_finished();
}
};
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
zipW.removeEntry(FILENAME, true);
do_test_pending();
zipW.processQueue(observer, null);
// With nothing to actually do the queue would have completed immediately
do_check_false(zipW.inQueue);
}

View file

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
var TESTS = [
"test.txt",
"test.png"
];
var observer = {
onStartRequest: function(request, context)
{
},
onStopRequest: function(request, context, status)
{
do_check_eq(status, Components.results.NS_OK);
zipW.close();
// Empty zip file should just be the end of central directory marker
var newTmpFile = tmpFile.clone();
do_check_eq(newTmpFile.fileSize, ZIP_EOCDR_HEADER_SIZE);
do_test_finished();
}
};
function run_test()
{
// Copy our test zip to the tmp dir so we can modify it
var testzip = do_get_file(DATA_DIR + "test.zip");
testzip.copyTo(tmpDir, tmpFile.leafName);
do_check_true(tmpFile.exists());
zipW.open(tmpFile, PR_RDWR);
for (var i = 0; i < TESTS.length; i++) {
do_check_true(zipW.hasEntry(TESTS[i]));
zipW.removeEntry(TESTS[i], true);
}
do_test_pending();
zipW.processQueue(observer, null);
do_check_true(zipW.inQueue);
}

View file

@ -0,0 +1,86 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function BinaryComparer(file, callback) {
var fstream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fstream.init(file, -1, 0, 0);
this.length = file.fileSize;
this.fileStream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
this.fileStream.setInputStream(fstream);
this.offset = 0;
this.callback = callback;
}
BinaryComparer.prototype = {
fileStream: null,
offset: null,
length: null,
callback: null,
onStartRequest: function(aRequest, aContext) {
},
onStopRequest: function(aRequest, aContext, aStatusCode) {
this.fileStream.close();
do_check_eq(aStatusCode, Components.results.NS_OK);
do_check_eq(this.offset, this.length);
this.callback();
},
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
var stream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
stream.setInputStream(aInputStream);
var source, actual;
for (var i = 0; i < aCount; i++) {
try {
source = this.fileStream.read8();
}
catch (e) {
do_throw("Unable to read from file at offset " + this.offset + " " + e);
}
try {
actual = stream.read8();
}
catch (e) {
do_throw("Unable to read from converted stream at offset " + this.offset + " " + e);
}
if (source != actual)
do_throw("Invalid value " + actual + " at offset " + this.offset + ", should have been " + source);
this.offset++;
}
}
}
function comparer_callback()
{
do_test_finished();
}
function run_test()
{
var source = do_get_file(DATA_DIR + "test_bug399727.html");
var comparer = new BinaryComparer(do_get_file(DATA_DIR + "test_bug399727.zlib"),
comparer_callback);
// Prepare the stream converter
var scs = Cc["@mozilla.org/streamConverters;1"].
getService(Ci.nsIStreamConverterService);
var converter = scs.asyncConvertData("uncompressed", "deflate", comparer, null);
// Open the expected output file
var fstream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fstream.init(source, -1, 0, 0);
// Set up a pump to push data from the file to the stream converter
var pump = Cc["@mozilla.org/network/input-stream-pump;1"].
createInstance(Ci.nsIInputStreamPump);
pump.init(fstream, -1, -1, 0, 0, true);
pump.asyncRead(converter, null);
do_test_pending();
}

View file

@ -0,0 +1,70 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "";
const FILENAME = "test.txt";
const CRC = 0x00000000;
// XXX Must use a constant time here away from DST changes. See bug 402434.
const time = 1199145600000; // Jan 1st 2008
function testpass(source)
{
// Should exist.
do_check_true(source.hasEntry(FILENAME));
var entry = source.getEntry(FILENAME);
do_check_neq(entry, null);
do_check_false(entry.isDirectory);
// Should be stored
do_check_eq(entry.compression, ZIP_METHOD_DEFLATE);
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, time);
// File size should match our data size.
do_check_eq(entry.realSize, DATA.length);
// Check that the CRC is accurate
do_check_eq(entry.CRC32, CRC);
}
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
// Shouldn't be there to start with.
do_check_false(zipW.hasEntry(FILENAME));
do_check_false(zipW.inQueue);
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData(DATA, DATA.length);
zipW.addEntryStream(FILENAME, time * PR_USEC_PER_MSEC,
Ci.nsIZipWriter.COMPRESSION_BEST, stream, false);
// Check that zip state is right at this stage.
testpass(zipW);
zipW.close();
// Check to see if we get the same results loading afresh.
zipW.open(tmpFile, PR_RDWR);
testpass(zipW);
zipW.close();
// Test the stored data with the zipreader
var zipR = new ZipReader(tmpFile);
testpass(zipR);
zipR.test(FILENAME);
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
stream.init(zipR.getInputStream(FILENAME));
var result = stream.read(DATA.length);
stream.close();
zipR.close();
do_check_eq(result, DATA);
}

View file

@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "";
const FILENAME = "test.txt";
const CRC = 0x00000000;
const time = Date.now();
function testpass(source)
{
// Should exist.
do_check_true(source.hasEntry(FILENAME));
var entry = source.getEntry(FILENAME);
do_check_neq(entry, null);
do_check_false(entry.isDirectory);
// Should be stored
do_check_eq(entry.compression, ZIP_METHOD_DEFLATE);
// File size should match our data size.
do_check_eq(entry.realSize, DATA.length);
// Check that the CRC is accurate
do_check_eq(entry.CRC32, CRC);
}
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
// Shouldn't be there to start with.
do_check_false(zipW.hasEntry(FILENAME));
do_check_false(zipW.inQueue);
var file = do_get_file(DATA_DIR + "emptyfile.txt");
zipW.addEntryFile(FILENAME, Ci.nsIZipWriter.COMPRESSION_BEST, file, false);
// Check that zip state is right at this stage.
testpass(zipW);
zipW.close();
// Check to see if we get the same results loading afresh.
zipW.open(tmpFile, PR_RDWR);
testpass(zipW);
zipW.close();
// Test the stored data with the zipreader
var zipR = new ZipReader(tmpFile);
testpass(zipR);
zipR.test(FILENAME);
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
stream.init(zipR.getInputStream(FILENAME));
var result = stream.read(DATA.length);
stream.close();
zipR.close();
do_check_eq(result, DATA);
}

View file

@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DIRNAME = "test/";
const time = Date.now();
function run_test()
{
// Copy in the test file.
var source = do_get_file("data/test.zip");
source.copyTo(tmpFile.parent, tmpFile.leafName);
// Open it and add something so the CDS is rewritten.
zipW.open(tmpFile, PR_RDWR | PR_APPEND);
zipW.addEntryDirectory(DIRNAME, time * PR_USEC_PER_MSEC, false);
do_check_true(zipW.hasEntry(DIRNAME));
zipW.close();
var zipR = new ZipReader(tmpFile);
do_check_true(zipR.hasEntry(DIRNAME));
zipR.close();
// 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) + (ZIP_EXTENDED_TIMESTAMP_SIZE * 2);
do_check_eq(source.fileSize + extra, tmpFile.fileSize);
}

View file

@ -0,0 +1,73 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test()
{
var test;
// zipW is an uninitialised zipwriter at this point.
try {
test = zipW.file;
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
test = zipW.comment;
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
zipW.comment = "test";
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
zipW.addEntryDirectory("test", 0, false);
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
zipW.addEntryFile("test", Ci.nsIZipWriter.COMPRESSION_DEFAULT, tmpDir, false);
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
zipW.removeEntry("test", false);
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
zipW.processQueue(null, null);
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
try {
zipW.close();
do_throw("Should have thrown uninitialized error.");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_NOT_INITIALIZED);
}
}

View file

@ -0,0 +1,37 @@
function run_test() {
var testBundle = do_get_file("data/test_bug446708");
RecursivelyZipDirectory(testBundle);
}
// Add |file| to the zip. |path| is the current path for the file.
function AddToZip(zipWriter, path, file)
{
var currentPath = path + file.leafName;
if (file.isDirectory()) {
currentPath += "/";
}
// THIS IS WHERE THE ERROR OCCURS, FOR THE FILE "st14-1.tiff" IN "test_bug446708"
zipWriter.addEntryFile(currentPath, Ci.nsIZipWriter.COMPRESSION_DEFAULT, file, false);
// if it's a dir, continue adding its contents recursively...
if (file.isDirectory()) {
var entries = file.QueryInterface(Components.interfaces.nsIFile).directoryEntries;
while (entries.hasMoreElements()) {
var entry = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
AddToZip(zipWriter, currentPath, entry);
}
}
// ...otherwise, we're done
}
function RecursivelyZipDirectory(bundle)
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
AddToZip(zipW, "", bundle);
zipW.close();
}

View file

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test()
{
// In this test we try to open some files that aren't archives:
// - An empty file, that is certainly not an archive.
// - A file that couldn't be mistaken for archive, since it is too small.
// - A file that could be mistaken for archive, if we checked only the file
// size, but is invalid since it contains no ZIP signature.
var invalidArchives = ["emptyfile.txt", "smallfile.txt", "test.png"];
invalidArchives.forEach(function(invalidArchive) {
// Get a reference to the invalid file
var invalidFile = do_get_file(DATA_DIR + invalidArchive);
// Opening the invalid file should fail (but not crash)
try {
zipW.open(invalidFile, PR_RDWR);
do_throw("Should have thrown NS_ERROR_FILE_CORRUPTED on " +
invalidArchive + " !");
} catch (e if (e instanceof Ci.nsIException &&
e.result == Components.results.NS_ERROR_FILE_CORRUPTED)) {
// do nothing
}
});
}

View file

@ -0,0 +1,92 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0
*/
function BinaryComparer(file, callback) {
var fstream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fstream.init(file, -1, 0, 0);
this.length = file.fileSize;
this.fileStream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
this.fileStream.setInputStream(fstream);
this.offset = 0;
this.callback = callback;
}
BinaryComparer.prototype = {
fileStream: null,
offset: null,
length: null,
callback: null,
onStartRequest: function(aRequest, aContext) {
},
onStopRequest: function(aRequest, aContext, aStatusCode) {
this.fileStream.close();
do_check_eq(aStatusCode, Components.results.NS_OK);
do_check_eq(this.offset, this.length);
this.callback();
},
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
var stream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
stream.setInputStream(aInputStream);
var source, actual;
for (var i = 0; i < aCount; i++) {
try {
source = this.fileStream.read8();
}
catch (e) {
do_throw("Unable to read from file at offset " + this.offset + " " + e);
}
try {
actual = stream.read8();
}
catch (e) {
do_throw("Unable to read from converted stream at offset " + this.offset + " " + e);
}
// The byte at offset 9 is the OS byte (see RFC 1952, section 2.3), which
// can legitimately differ when the source is compressed on different
// operating systems. The actual .gz for this test was created on a Unix
// system, but we want the test to work correctly everywhere. So ignore
// the byte at offset 9.
if (this.offset == 9)
;
else if (source != actual)
do_throw("Invalid value " + actual + " at offset " + this.offset + ", should have been " + source);
this.offset++;
}
}
}
function comparer_callback()
{
do_test_finished();
}
function run_test()
{
var source = do_get_file(DATA_DIR + "test_bug717061.html");
var comparer = new BinaryComparer(do_get_file(DATA_DIR + "test_bug717061.gz"),
comparer_callback);
// Prepare the stream converter
var scs = Cc["@mozilla.org/streamConverters;1"].
getService(Ci.nsIStreamConverterService);
var converter = scs.asyncConvertData("uncompressed", "gzip", comparer, null);
// Open the expected output file
var fstream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fstream.init(source, -1, 0, 0);
// Set up a pump to push data from the file to the stream converter
var pump = Cc["@mozilla.org/network/input-stream-pump;1"].
createInstance(Ci.nsIInputStreamPump);
pump.init(fstream, -1, -1, 0, 0, true);
pump.asyncRead(converter, null);
do_test_pending();
}

View file

@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
zipW.close();
// Should have created a zip file
do_check_true(tmpFile.exists());
// Empty zip file should just be the end of central directory marker
do_check_eq(tmpFile.fileSize, ZIP_EOCDR_HEADER_SIZE);
}

View file

@ -0,0 +1,53 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "ZIP WRITER TEST DATA";
const FILENAME = "test.txt";
const CRC = 0xe6164331;
// XXX Must use a constant time here away from DST changes. See bug 402434.
const time = 1199145600000; // Jan 1st 2008
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
// Shouldn't be there to start with.
do_check_false(zipW.hasEntry(FILENAME));
do_check_false(zipW.inQueue);
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData(DATA, DATA.length);
zipW.addEntryStream(FILENAME, time * PR_USEC_PER_MSEC,
Ci.nsIZipWriter.COMPRESSION_BEST, stream, false);
var entry = zipW.getEntry(FILENAME);
do_check_true(entry != null);
// Check entry seems right.
do_check_eq(entry.compression, ZIP_METHOD_DEFLATE);
do_check_eq(entry.CRC32, CRC);
do_check_eq(entry.realSize, DATA.length);
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, time);
zipW.close();
// Test the stored data with the zipreader
var zipR = new ZipReader(tmpFile);
do_check_true(zipR.hasEntry(FILENAME));
zipR.test(FILENAME);
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
stream.init(zipR.getInputStream(FILENAME));
var result = stream.read(DATA.length);
stream.close();
zipR.close();
do_check_eq(result, DATA);
}

View file

@ -0,0 +1,27 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DIRNAME1 = "test";
const DIRNAME1_CORRECT = "test/";
const DIRNAME2 = "test2/";
const time = Date.now();
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
zipW.addEntryDirectory(DIRNAME1, time * PR_USEC_PER_MSEC, false);
do_check_false(zipW.hasEntry(DIRNAME1));
do_check_true(zipW.hasEntry(DIRNAME1_CORRECT));
var entry = zipW.getEntry(DIRNAME1_CORRECT);
do_check_true(entry.isDirectory);
zipW.addEntryDirectory(DIRNAME2, time * PR_USEC_PER_MSEC, false);
do_check_true(zipW.hasEntry(DIRNAME2));
entry = zipW.getEntry(DIRNAME2);
do_check_true(entry.isDirectory);
zipW.close();
}

View file

@ -0,0 +1,62 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Values taken from using zipinfo to list the test.zip contents
var TESTS = [
{
name: "test.txt",
size: 232,
crc: 0x0373ac26,
time: Date.UTC(2007, 4, 1, 20, 44, 55)
},
{
name: "test.png",
size: 3402,
crc: 0x504a5c30,
time: Date.UTC(2007, 4, 1, 20, 49, 39)
}
];
var BADENTRY = "unknown.txt";
function run_test()
{
// Copy our test zip to the tmp dir so we can modify it
var testzip = do_get_file(DATA_DIR + "test.zip");
testzip.copyTo(tmpDir, tmpFile.leafName);
do_check_true(tmpFile.exists());
zipW.open(tmpFile, PR_RDWR);
for (var i = 0; i < TESTS.length; i++) {
do_check_true(zipW.hasEntry(TESTS[i].name));
var entry = zipW.getEntry(TESTS[i].name);
do_check_true(entry != null);
do_check_eq(entry.realSize, TESTS[i].size);
do_check_eq(entry.CRC32, TESTS[i].crc);
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, TESTS[i].time);
}
try {
zipW.removeEntry(BADENTRY, false);
do_throw("shouldn't be able to remove an entry that doesn't exist");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_FILE_NOT_FOUND);
}
for (var i = 0; i < TESTS.length; i++) {
zipW.removeEntry(TESTS[i].name, false);
}
zipW.close();
// Certain platforms cache the file size so get a fresh file to check.
tmpFile = tmpFile.clone();
// Empty zip file should just be the end of central directory marker
do_check_eq(tmpFile.fileSize, ZIP_EOCDR_HEADER_SIZE);
}

View file

@ -0,0 +1,78 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "ZIP WRITER TEST DATA";
const FILENAME = "test.txt";
const FILENAME2 = "test2.txt";
const CRC = 0xe6164331;
// XXX Must use a constant time here away from DST changes. See bug 402434.
const time = 1199145600000; // Jan 1st 2008
function testpass(source)
{
// Should exist.
do_check_true(source.hasEntry(FILENAME));
var entry = source.getEntry(FILENAME);
do_check_neq(entry, null);
do_check_false(entry.isDirectory);
// Should be stored
do_check_eq(entry.compression, ZIP_METHOD_STORE);
do_check_eq(entry.lastModifiedTime / PR_USEC_PER_MSEC, time);
// File size should match our data size.
do_check_eq(entry.realSize, DATA.length);
// When stored sizes should match.
do_check_eq(entry.size, entry.realSize);
// Check that the CRC is accurate
do_check_eq(entry.CRC32, CRC);
}
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
// Shouldn't be there to start with.
do_check_false(zipW.hasEntry(FILENAME));
do_check_false(zipW.inQueue);
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData(DATA, DATA.length);
zipW.addEntryStream(FILENAME, time * PR_USEC_PER_MSEC,
Ci.nsIZipWriter.COMPRESSION_NONE, stream, false);
// Check that zip state is right at this stage.
testpass(zipW);
zipW.close();
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.
zipW.open(tmpFile, PR_RDWR);
testpass(zipW);
zipW.close();
// Test the stored data with the zipreader
var zipR = new ZipReader(tmpFile);
testpass(zipR);
zipR.test(FILENAME);
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
stream.init(zipR.getInputStream(FILENAME));
var result = stream.read(DATA.length);
stream.close();
zipR.close();
do_check_eq(result, DATA);
}

View file

@ -0,0 +1,57 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Values taken from using zipinfo to list the test.zip contents
var TESTS = [
{
name: "test.txt",
size: 232,
crc: 0x0373ac26
},
{
name: "test.png",
size: 3402,
crc: 0x504a5c30
}
];
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
var size = 0;
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR + TESTS[i].name);
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;
}
zipW.close();
size += ZIP_EOCDR_HEADER_SIZE;
do_check_eq(size, tmpFile.fileSize);
// Test the stored data with the zipreader
var zipR = new ZipReader(tmpFile);
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR + TESTS[i].name);
do_check_true(zipR.hasEntry(TESTS[i].name));
var entry = zipR.getEntry(TESTS[i].name);
do_check_eq(entry.realSize, TESTS[i].size);
do_check_eq(entry.size, TESTS[i].size);
do_check_eq(entry.CRC32, TESTS[i].crc);
do_check_eq(Math.floor(entry.lastModifiedTime / PR_USEC_PER_SEC),
Math.floor(source.lastModifiedTime / PR_MSEC_PER_SEC));
zipR.test(TESTS[i].name);
}
zipR.close();
}

View file

@ -0,0 +1,42 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Values taken from using zipinfo to list the test.zip contents
var TESTS = [
"test.txt",
"test.png"
];
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR + TESTS[i]);
zipW.addEntryFile(TESTS[i], Ci.nsIZipWriter.COMPRESSION_NONE, source,
false);
}
try {
var source = do_get_file(DATA_DIR + TESTS[0]);
zipW.addEntryFile(TESTS[0], Ci.nsIZipWriter.COMPRESSION_NONE, source,
false);
do_throw("Should not be able to add the same file twice");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_FILE_ALREADY_EXISTS);
}
// Remove all the tests and see if we are left with an empty zip
for (var i = 0; i < TESTS.length; i++) {
zipW.removeEntry(TESTS[i], false);
}
zipW.close();
// Empty zip file should just be the end of central directory marker
var newTmpFile = tmpFile.clone();
do_check_eq(newTmpFile.fileSize, ZIP_EOCDR_HEADER_SIZE);
}

View file

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "ZIP WRITER TEST COMMENT";
const DATA2 = "ANOTHER ONE";
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
zipW.comment = DATA;
zipW.close();
// Should have created a zip file
do_check_true(tmpFile.exists());
// Empty zip file should just be the end of central directory marker
// and comment
do_check_eq(tmpFile.fileSize, ZIP_EOCDR_HEADER_SIZE + DATA.length);
zipW.open(tmpFile, PR_RDWR);
// Should have the set comment
do_check_eq(zipW.comment, DATA);
zipW.comment = DATA2;
zipW.close();
// Certain platforms cache the file size so get a fresh file to check.
tmpFile = tmpFile.clone();
// Empty zip file should just be the end of central directory marker
// and comment. This should now be shorter
do_check_eq(tmpFile.fileSize, ZIP_EOCDR_HEADER_SIZE + DATA2.length);
}

View file

@ -0,0 +1,83 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const DATA = "ZIP WRITER TEST DATA";
var TESTS = [];
function build_tests() {
var id = 0;
// Minimum mode is 0o400
for (let u = 4; u <= 7; u++) {
for (let g = 0; g <= 7; g++) {
for (let o = 0; o <= 7; o++) {
TESTS[id] = {
name: "test" + u + g + o,
permission: (u << 6) + (g << 3) + o
};
id++;
}
}
}
}
function run_test() {
build_tests();
var foStream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
var tmp = tmpDir.clone();
tmp.append("temp-permissions");
tmp.createUnique(Ci.nsILocalFile.DIRECTORY_TYPE, 0o755);
var file = tmp.clone();
file.append("tempfile");
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
for (let i = 0; i < TESTS.length; i++) {
// Open the file with the permissions to match how the zipreader extracts
// This obeys the umask
foStream.init(file, 0x02 | 0x08 | 0x20, TESTS[i].permission, 0);
foStream.close();
// umask may have altered the permissions so test against what they really were.
// This reduces the coverage of the test but there isn't much we can do
var perm = file.permissions & 0xfff;
if (TESTS[i].permission != perm) {
dump("File permissions for " + TESTS[i].name + " were " + perm.toString(8) + "\n");
TESTS[i].permission = perm;
}
zipW.addEntryFile(TESTS[i].name, Ci.nsIZipWriter.COMPRESSION_NONE, file, false);
do_check_eq(zipW.getEntry(TESTS[i].name).permissions, TESTS[i].permission | 0o400);
file.permissions = 0o600;
file.remove(true);
}
zipW.close();
zipW.open(tmpFile, PR_RDWR);
for (let i = 0; i < TESTS.length; i++) {
dump("Testing zipwriter file permissions for " + TESTS[i].name + "\n");
do_check_eq(zipW.getEntry(TESTS[i].name).permissions, TESTS[i].permission | 0o400);
}
zipW.close();
var zipR = new ZipReader(tmpFile);
for (let i = 0; i < TESTS.length; i++) {
dump("Testing zipreader file permissions for " + TESTS[i].name + "\n");
do_check_eq(zipR.getEntry(TESTS[i].name).permissions, TESTS[i].permission | 0o400);
dump("Testing extracted file permissions for " + TESTS[i].name + "\n");
zipR.extract(TESTS[i].name, file);
do_check_eq(file.permissions & 0xfff, TESTS[i].permission);
do_check_false(file.isDirectory());
file.permissions = 0o600;
file.remove(true);
}
zipR.close();
tmp.remove(true);
}

View file

@ -0,0 +1,37 @@
[DEFAULT]
head = head_zipwriter.js
tail = tail_zipwriter.js
support-files =
data/test_bug446708/thumbs/st14-1.tiff
data/emptyfile.txt
data/smallfile.txt
data/test.png
data/test.txt
data/test.zip
data/test_bug399727.html
data/test_bug399727.zlib
data/test_bug717061.gz
data/test_bug717061.html
[test_asyncadd.js]
[test_asyncbadadd.js]
[test_asyncbadremove.js]
[test_asyncremove.js]
[test_bug399727.js]
[test_bug419769_1.js]
[test_bug419769_2.js]
[test_bug425768.js]
[test_bug433248.js]
[test_bug446708.js]
[test_bug467740.js]
[test_createempty.js]
[test_deflatedata.js]
[test_directory.js]
[test_editexisting.js]
[test_storedata.js]
[test_sync.js]
[test_undochange.js]
[test_zipcomment.js]
[test_zippermissions.js]
[test_bug717061.js]
[test_alignment.js]