зеркало из https://github.com/mozilla/gecko-dev.git
Bug 781425 - Part 1: Enconding and dictionary. r=mounir, sr=sicking
This commit is contained in:
Родитель
d9a04350b5
Коммит
b971f025e1
|
@ -28,7 +28,11 @@ ArchiveItem::~ArchiveItem()
|
|||
nsCString
|
||||
ArchiveItem::GetType()
|
||||
{
|
||||
return mType.IsEmpty() ? nsCString("binary/octet-stream") : mType;
|
||||
if (mType.IsEmpty()) {
|
||||
return NS_LITERAL_CSTRING("binary/octet-stream");
|
||||
}
|
||||
|
||||
return mType;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -109,20 +113,29 @@ ArchiveReaderEvent::ShareMainThread()
|
|||
for (uint32_t index = 0; index < mFileList.Length(); ++index) {
|
||||
nsRefPtr<ArchiveItem> item = mFileList[index];
|
||||
|
||||
int32_t offset = item->GetFilename().RFindChar('.');
|
||||
nsString tmp;
|
||||
nsresult rv = item->GetFilename(tmp);
|
||||
nsCString filename = NS_ConvertUTF16toUTF8(tmp);
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t offset = filename.RFindChar('.');
|
||||
if (offset != kNotFound) {
|
||||
nsCString ext(item->GetFilename());
|
||||
ext.Cut(0, offset + 1);
|
||||
filename.Cut(0, offset + 1);
|
||||
|
||||
// Just to be sure, if something goes wrong, the mimetype is an empty string:
|
||||
nsCString type;
|
||||
if (NS_SUCCEEDED(GetType(ext, type)))
|
||||
if (NS_SUCCEEDED(GetType(filename, type))) {
|
||||
item->SetType(type);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a nsDOMFile:
|
||||
nsRefPtr<nsIDOMFile> file = item->File(mArchiveReader);
|
||||
fileList.AppendElement(file);
|
||||
if (file) {
|
||||
fileList.AppendElement(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
|
||||
BEGIN_FILE_NAMESPACE
|
||||
|
||||
// This class contains all the info needed for a single item
|
||||
// It must contain the implementation of the File() method.
|
||||
/**
|
||||
* This class contains all the info needed for a single item
|
||||
* It must contain the implementation of the File() method.
|
||||
*/
|
||||
class ArchiveItem : public nsISupports
|
||||
{
|
||||
public:
|
||||
|
@ -28,11 +30,11 @@ public:
|
|||
virtual ~ArchiveItem();
|
||||
|
||||
// Getter/Setter for the type
|
||||
virtual nsCString GetType();
|
||||
virtual void SetType(const nsCString& aType);
|
||||
nsCString GetType();
|
||||
void SetType(const nsCString& aType);
|
||||
|
||||
// Getter for the filename
|
||||
virtual nsCString GetFilename() = 0;
|
||||
virtual nsresult GetFilename(nsString& aFilename) = 0;
|
||||
|
||||
// Generate a DOMFile
|
||||
virtual nsIDOMFile* File(ArchiveReader* aArchiveReader) = 0;
|
||||
|
@ -41,9 +43,11 @@ protected:
|
|||
nsCString mType;
|
||||
};
|
||||
|
||||
// This class must be extended by any archive format supported by ArchiveReader API
|
||||
// This class runs in a different thread and it calls the 'exec()' method.
|
||||
// The exec() must populate mFileList and mStatus then it must call RunShare();
|
||||
/**
|
||||
* This class must be extended by any archive format supported by ArchiveReader API
|
||||
* This class runs in a different thread and it calls the 'exec()' method.
|
||||
* The exec() must populate mFileList and mStatus then it must call RunShare();
|
||||
*/
|
||||
class ArchiveReaderEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -40,11 +40,11 @@ ArchiveReader::Initialize(nsISupports* aOwner,
|
|||
uint32_t aArgc,
|
||||
JS::Value* aArgv)
|
||||
{
|
||||
NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
|
||||
NS_ENSURE_TRUE(aArgc == 1 || aArgc == 2, NS_ERROR_INVALID_ARG);
|
||||
|
||||
// We expect to get a Blob object
|
||||
if (!aArgv[0].isObject()) {
|
||||
return NS_ERROR_UNEXPECTED; // We're not interested
|
||||
return NS_ERROR_INVALID_ARG; // We're not interested
|
||||
}
|
||||
|
||||
JSObject* obj = &aArgv[0].toObject();
|
||||
|
@ -52,16 +52,22 @@ ArchiveReader::Initialize(nsISupports* aOwner,
|
|||
nsCOMPtr<nsIDOMBlob> blob;
|
||||
blob = do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj));
|
||||
if (!blob) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mBlob = blob;
|
||||
// Extra param is an object
|
||||
if (aArgc > 1) {
|
||||
nsresult rv = mOptions.Init(aCx, &aArgv[1]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mWindow = do_QueryInterface(aOwner);
|
||||
if (!mWindow) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mBlob = blob;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -122,7 +128,7 @@ ArchiveReader::OpenArchive()
|
|||
nsRefPtr<ArchiveReaderEvent> event;
|
||||
|
||||
/* FIXME: If we want to support more than 1 format we should check the content type here: */
|
||||
event = new ArchiveReaderZipEvent(this);
|
||||
event = new ArchiveReaderZipEvent(this, mOptions);
|
||||
rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -16,11 +16,15 @@
|
|||
#include "nsIChannel.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
|
||||
BEGIN_FILE_NAMESPACE
|
||||
|
||||
class ArchiveRequest;
|
||||
|
||||
/**
|
||||
* This is the ArchiveReader object
|
||||
*/
|
||||
class ArchiveReader MOZ_FINAL : public nsIDOMArchiveReader,
|
||||
public nsIJSNativeInitializer
|
||||
{
|
||||
|
@ -90,6 +94,8 @@ protected:
|
|||
nsTArray<nsCOMPtr<nsIDOMFile> > fileList;
|
||||
nsresult status;
|
||||
} mData;
|
||||
|
||||
ArchiveReaderOptions mOptions;
|
||||
};
|
||||
|
||||
END_FILE_NAMESPACE
|
||||
|
|
|
@ -44,7 +44,7 @@ ArchiveRequestEvent::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* ArchiveRequest */
|
||||
// ArchiveRequest
|
||||
|
||||
ArchiveRequest::ArchiveRequest(nsIDOMWindow* aWindow,
|
||||
ArchiveReader* aReader)
|
||||
|
@ -90,8 +90,9 @@ ArchiveRequest::Run()
|
|||
// Register this request to the reader.
|
||||
// When the reader is ready to return data, a 'Ready()' will be called
|
||||
nsresult rv = mArchiveReader->RegisterRequest(this);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
FireError(rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -187,7 +188,7 @@ ArchiveRequest::GetFilenamesResult(JSContext* aCx,
|
|||
if (!JS_FreezeObject(aCx, array)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
*aValue = OBJECT_TO_JSVAL(array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -205,8 +206,9 @@ ArchiveRequest::GetFileResult(JSContext* aCx,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (filename == mFilename) {
|
||||
JSObject* scope = JS_GetGlobalForScopeChain(aCx);
|
||||
nsresult rv = nsContentUtils::WrapNative(aCx, scope, file, aValue, nullptr, true);
|
||||
nsresult rv = nsContentUtils::WrapNative(
|
||||
aCx, JS_GetGlobalForScopeChain(aCx),
|
||||
file, &NS_GET_IID(nsIDOMFile), aValue);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,15 @@
|
|||
|
||||
BEGIN_FILE_NAMESPACE
|
||||
|
||||
/**
|
||||
* This is the ArchiveRequest that handles any operation
|
||||
* related to ArchiveReader
|
||||
*/
|
||||
class ArchiveRequest : public mozilla::dom::DOMRequest,
|
||||
public nsIDOMArchiveRequest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMARCHIVEREQUEST
|
||||
|
||||
NS_FORWARD_NSIDOMDOMREQUEST(DOMRequest::)
|
||||
|
|
|
@ -8,19 +8,24 @@
|
|||
#include "ArchiveZipFile.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
USING_FILE_NAMESPACE
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# define PATH_MAX 65536 // The filename length is stored in 2 bytes
|
||||
#endif
|
||||
|
||||
// ArchiveZipItem
|
||||
ArchiveZipItem::ArchiveZipItem(const char* aFilename,
|
||||
ZipCentral& aCentralStruct)
|
||||
const ZipCentral& aCentralStruct,
|
||||
const ArchiveReaderOptions& aOptions)
|
||||
: mFilename(aFilename),
|
||||
mCentralStruct(aCentralStruct)
|
||||
mCentralStruct(aCentralStruct),
|
||||
mOptions(aOptions)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ArchiveZipItem);
|
||||
}
|
||||
|
@ -30,25 +35,58 @@ ArchiveZipItem::~ArchiveZipItem()
|
|||
MOZ_COUNT_DTOR(ArchiveZipItem);
|
||||
}
|
||||
|
||||
// Getter/Setter for the filename
|
||||
nsCString
|
||||
ArchiveZipItem::GetFilename()
|
||||
nsresult
|
||||
ArchiveZipItem::ConvertFilename()
|
||||
{
|
||||
return mFilename;
|
||||
if (mOptions.encoding.IsEmpty()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsString filenameU;
|
||||
nsresult rv = nsContentUtils::ConvertStringFromCharset(
|
||||
NS_ConvertUTF16toUTF8(mOptions.encoding),
|
||||
mFilename, filenameU);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (filenameU.IsEmpty()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mFilenameU = filenameU;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ArchiveZipItem::SetFilename(const nsCString& aFilename)
|
||||
nsresult
|
||||
ArchiveZipItem::GetFilename(nsString& aFilename)
|
||||
{
|
||||
mFilename = aFilename;
|
||||
}
|
||||
if (mFilenameU.IsEmpty()) {
|
||||
// Maybe this string is UTF-8:
|
||||
if (IsUTF8(mFilename, false)) {
|
||||
mFilenameU = NS_ConvertUTF8toUTF16(mFilename);
|
||||
}
|
||||
|
||||
// Let's use the enconding value for the dictionary
|
||||
else {
|
||||
nsresult rv = ConvertFilename();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
aFilename = mFilenameU;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// From zipItem to DOMFile:
|
||||
nsIDOMFile*
|
||||
ArchiveZipItem::File(ArchiveReader* aArchiveReader)
|
||||
{
|
||||
return new ArchiveZipFile(NS_ConvertUTF8toUTF16(mFilename),
|
||||
nsString filename;
|
||||
|
||||
if (NS_FAILED(GetFilename(filename))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new ArchiveZipFile(filename,
|
||||
NS_ConvertUTF8toUTF16(GetType()),
|
||||
StrToInt32(mCentralStruct.orglen),
|
||||
mCentralStruct,
|
||||
|
@ -72,8 +110,10 @@ ArchiveZipItem::StrToInt16(const uint8_t* aStr)
|
|||
|
||||
// ArchiveReaderZipEvent
|
||||
|
||||
ArchiveReaderZipEvent::ArchiveReaderZipEvent(ArchiveReader* aArchiveReader)
|
||||
: ArchiveReaderEvent(aArchiveReader)
|
||||
ArchiveReaderZipEvent::ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
|
||||
const ArchiveReaderOptions& aOptions)
|
||||
: ArchiveReaderEvent(aArchiveReader),
|
||||
mOptions(aOptions)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -104,8 +144,7 @@ ArchiveReaderZipEvent::Exec()
|
|||
}
|
||||
|
||||
// Reading backward.. looking for the ZipEnd signature
|
||||
for (uint64_t curr = size - ZIPEND_SIZE; curr > 4; --curr)
|
||||
{
|
||||
for (uint64_t curr = size - ZIPEND_SIZE; curr > 4; --curr) {
|
||||
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, curr);
|
||||
|
||||
uint8_t buffer[ZIPEND_SIZE];
|
||||
|
@ -162,7 +201,7 @@ ArchiveReaderZipEvent::Exec()
|
|||
|
||||
// We ignore the directories:
|
||||
if (filename[filenameLen - 1] != '/') {
|
||||
mFileList.AppendElement(new ArchiveZipItem(filename, centralStruct));
|
||||
mFileList.AppendElement(new ArchiveZipItem(filename, centralStruct, mOptions));
|
||||
}
|
||||
|
||||
PR_Free(filename);
|
||||
|
|
|
@ -12,17 +12,22 @@
|
|||
#include "FileCommon.h"
|
||||
#include "zipstruct.h"
|
||||
|
||||
#include "DictionaryHelpers.h"
|
||||
|
||||
BEGIN_FILE_NAMESPACE
|
||||
|
||||
/**
|
||||
* ArchiveZipItem - ArchiveItem for ArchiveReaderZipEvent
|
||||
*/
|
||||
class ArchiveZipItem : public ArchiveItem
|
||||
{
|
||||
public:
|
||||
ArchiveZipItem(const char* aFilename,
|
||||
ZipCentral& aCentralStruct);
|
||||
const ZipCentral& aCentralStruct,
|
||||
const ArchiveReaderOptions& aOptions);
|
||||
virtual ~ArchiveZipItem();
|
||||
|
||||
void SetFilename(const nsCString& aFilename);
|
||||
nsCString GetFilename();
|
||||
nsresult GetFilename(nsString& aFilename);
|
||||
|
||||
// From zipItem to DOMFile:
|
||||
virtual nsIDOMFile* File(ArchiveReader* aArchiveReader);
|
||||
|
@ -31,17 +36,31 @@ public: // for the event
|
|||
static uint32_t StrToInt32(const uint8_t* aStr);
|
||||
static uint16_t StrToInt16(const uint8_t* aStr);
|
||||
|
||||
private:
|
||||
nsresult ConvertFilename();
|
||||
|
||||
private: // data
|
||||
nsCString mFilename;
|
||||
|
||||
nsString mFilenameU;
|
||||
ZipCentral mCentralStruct;
|
||||
|
||||
ArchiveReaderOptions mOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* ArchiveReaderEvent implements the ArchiveReaderEvent for the ZIP format
|
||||
*/
|
||||
class ArchiveReaderZipEvent : public ArchiveReaderEvent
|
||||
{
|
||||
public:
|
||||
ArchiveReaderZipEvent(ArchiveReader* aArchiveReader);
|
||||
ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
|
||||
const ArchiveReaderOptions& aOptions);
|
||||
|
||||
nsresult Exec();
|
||||
|
||||
private:
|
||||
ArchiveReaderOptions mOptions;
|
||||
};
|
||||
|
||||
END_FILE_NAMESPACE
|
||||
|
|
|
@ -15,8 +15,9 @@ USING_FILE_NAMESPACE
|
|||
|
||||
#define ZIP_CHUNK 16384
|
||||
|
||||
// a internat input stream object
|
||||
|
||||
/**
|
||||
* Input stream object for zip files
|
||||
*/
|
||||
class ArchiveInputStream MOZ_FINAL : public nsIInputStream,
|
||||
public nsISeekableStream
|
||||
{
|
||||
|
@ -92,22 +93,25 @@ ArchiveInputStream::Init()
|
|||
|
||||
memset(&mZs, 0, sizeof(z_stream));
|
||||
int zerr = inflateInit2(&mZs, -MAX_WBITS);
|
||||
if (zerr != Z_OK)
|
||||
if (zerr != Z_OK) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mData.sizeToBeRead = ArchiveZipItem::StrToInt32(mCentral.size);
|
||||
|
||||
uint32_t offset = ArchiveZipItem::StrToInt32(mCentral.localhdr_offset);
|
||||
|
||||
// The file is corrupt
|
||||
if (offset + ZIPLOCAL_SIZE > mData.parentSize)
|
||||
if (offset + ZIPLOCAL_SIZE > mData.parentSize) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// From the input stream to a seekable stream
|
||||
nsCOMPtr<nsISeekableStream> seekableStream;
|
||||
seekableStream = do_QueryInterface(mData.inputStream);
|
||||
if (!seekableStream)
|
||||
if (!seekableStream) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Seek + read the ZipLocal struct
|
||||
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
|
||||
|
@ -115,12 +119,14 @@ ArchiveInputStream::Init()
|
|||
uint32_t ret;
|
||||
|
||||
rv = mData.inputStream->Read((char*)buffer, ZIPLOCAL_SIZE, &ret);
|
||||
if (NS_FAILED(rv) || ret != ZIPLOCAL_SIZE)
|
||||
if (NS_FAILED(rv) || ret != ZIPLOCAL_SIZE) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Signature check:
|
||||
if (ArchiveZipItem::StrToInt32(buffer) != LOCALSIG)
|
||||
if (ArchiveZipItem::StrToInt32(buffer) != LOCALSIG) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ZipLocal local;
|
||||
memcpy(&local, buffer, ZIPLOCAL_SIZE);
|
||||
|
@ -131,8 +137,9 @@ ArchiveInputStream::Init()
|
|||
ArchiveZipItem::StrToInt16(local.extrafield_len);
|
||||
|
||||
// The file is corrupt if there is not enough data
|
||||
if (offset + mData.sizeToBeRead > mData.parentSize)
|
||||
if (offset + mData.sizeToBeRead > mData.parentSize) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Data starts here:
|
||||
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
|
||||
|
@ -182,8 +189,9 @@ ArchiveInputStream::Read(char* aBuffer,
|
|||
mStatus = Started;
|
||||
|
||||
rv = Init();
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Let's set avail_out to -1 so we read something from the stream.
|
||||
mZs.avail_out = (uInt)-1;
|
||||
|
@ -196,8 +204,7 @@ ArchiveInputStream::Read(char* aBuffer,
|
|||
}
|
||||
|
||||
// Stored file:
|
||||
if (!mData.compressed)
|
||||
{
|
||||
if (!mData.compressed) {
|
||||
rv = mData.inputStream->Read(aBuffer,
|
||||
(mData.sizeToBeRead > aCount ?
|
||||
aCount : mData.sizeToBeRead),
|
||||
|
@ -206,23 +213,24 @@ ArchiveInputStream::Read(char* aBuffer,
|
|||
mData.sizeToBeRead -= *_retval;
|
||||
mData.cursor += *_retval;
|
||||
|
||||
if (mData.sizeToBeRead == 0)
|
||||
if (mData.sizeToBeRead == 0) {
|
||||
mStatus = Done;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We have nothing ready to be processed:
|
||||
if (mZs.avail_out != 0 && mData.sizeToBeRead != 0)
|
||||
{
|
||||
if (mZs.avail_out != 0 && mData.sizeToBeRead != 0) {
|
||||
uint32_t ret;
|
||||
rv = mData.inputStream->Read((char*)mData.input,
|
||||
(mData.sizeToBeRead > sizeof(mData.input) ?
|
||||
sizeof(mData.input) : mData.sizeToBeRead),
|
||||
&ret);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Terminator:
|
||||
if (ret == 0) {
|
||||
|
@ -239,11 +247,13 @@ ArchiveInputStream::Read(char* aBuffer,
|
|||
mZs.next_out = (unsigned char*)aBuffer;
|
||||
|
||||
int ret = inflate(&mZs, mData.sizeToBeRead ? Z_NO_FLUSH : Z_FINISH);
|
||||
if (ret != Z_BUF_ERROR && ret != Z_OK && ret != Z_STREAM_END)
|
||||
if (ret != Z_BUF_ERROR && ret != Z_OK && ret != Z_STREAM_END) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (ret == Z_STREAM_END)
|
||||
if (ret == Z_STREAM_END) {
|
||||
mStatus = Done;
|
||||
}
|
||||
|
||||
*_retval = aCount - mZs.avail_out;
|
||||
mData.cursor += *_retval;
|
||||
|
@ -291,11 +301,13 @@ ArchiveInputStream::Seek(int32_t aWhence, int64_t aOffset)
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (pos == int64_t(mData.cursor))
|
||||
if (pos == int64_t(mData.cursor)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (pos < 0 || pos >= mLength)
|
||||
if (pos < 0 || pos >= mLength) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We have to terminate the previous operation:
|
||||
nsresult rv;
|
||||
|
@ -312,11 +324,13 @@ ArchiveInputStream::Seek(int32_t aWhence, int64_t aOffset)
|
|||
char buffer[1024];
|
||||
while (pos > 0) {
|
||||
rv = Read(buffer, pos > int64_t(sizeof(buffer)) ? sizeof(buffer) : pos, &ret);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
pos -= ret;
|
||||
}
|
||||
|
@ -342,8 +356,9 @@ ArchiveInputStream::SetEOF()
|
|||
NS_IMETHODIMP
|
||||
ArchiveZipFile::GetInternalStream(nsIInputStream** aStream)
|
||||
{
|
||||
if (mLength > INT32_MAX)
|
||||
if (mLength > INT32_MAX) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint64_t size;
|
||||
nsresult rv = mArchiveReader->GetSize(&size);
|
||||
|
@ -351,8 +366,9 @@ ArchiveZipFile::GetInternalStream(nsIInputStream** aStream)
|
|||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
rv = mArchiveReader->GetInputStream(getter_AddRefs(inputStream));
|
||||
if (NS_FAILED(rv) || !inputStream)
|
||||
if (NS_FAILED(rv) || !inputStream) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsRefPtr<ArchiveInputStream> stream = new ArchiveInputStream(size,
|
||||
inputStream,
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
BEGIN_FILE_NAMESPACE
|
||||
|
||||
/**
|
||||
* ZipFile to DOMFileCC
|
||||
*/
|
||||
class ArchiveZipFile : public nsDOMFileCC
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -14,6 +14,14 @@ interface nsIDOMArchiveReader : nsISupports
|
|||
nsIDOMArchiveRequest getFile(in DOMString filename);
|
||||
};
|
||||
|
||||
/* This dictionary is the optional argument for the
|
||||
* ArchiveReader constructor:
|
||||
* var a = new ArchiveReader(blob, { encoding: "iso-8859-1" }); */
|
||||
dictionary ArchiveReaderOptions
|
||||
{
|
||||
DOMString encoding = "windows-1252"; // Default fallback encoding
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_ARCHIVEREADER_CID \
|
||||
{0xb6b8c817, 0x4e9a, 0x46f8, \
|
||||
|
|
|
@ -31,6 +31,7 @@ MOCHITEST_FILES = \
|
|||
test_workers.html \
|
||||
test_archivereader.html \
|
||||
test_archivereader_zip_in_zip.html \
|
||||
test_archivereader_nonUnicode.html \
|
||||
test_bug_793311.html \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Archive Reader Non-Unicode Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function createNonUnicodeData() {
|
||||
const Cc = SpecialPowers.wrap(Components).classes;
|
||||
const Ci = SpecialPowers.wrap(Components).interfaces;
|
||||
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
testFile.append("fileArchiveReader_nonUnicode.zip");
|
||||
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
|
||||
var binaryData = "";
|
||||
for (var i = 0, len = binaryString.length / 2; i < len; ++i) {
|
||||
var hex = binaryString[i * 2] + binaryString[i * 2 + 1];
|
||||
binaryData += String.fromCharCode(parseInt(hex,16));
|
||||
}
|
||||
outStream.write(binaryData, binaryData.length);
|
||||
outStream.close();
|
||||
|
||||
var fileList = document.getElementById('fileList');
|
||||
SpecialPowers.wrap(fileList).value = testFile.path;
|
||||
|
||||
return fileList.files[0];
|
||||
}
|
||||
|
||||
function test1()
|
||||
{
|
||||
var binaryFile = createNonUnicodeData();
|
||||
|
||||
var r = new ArchiveReader(binaryFile, { encoding: "ISO-8859-1" });
|
||||
isnot(r, null, "ArchiveReader cannot be null");
|
||||
|
||||
// GetFilename
|
||||
var handle = r.getFilenames();
|
||||
isnot(handle, null, "ArchiveReader.getFilenames() cannot be null");
|
||||
handle.onsuccess = function() {
|
||||
ok(true, "ArchiveReader.getFilenames() should return a 'success'");
|
||||
is(this.result instanceof Array, true, "ArchiveReader.getFilenames() should return an array");
|
||||
is(this.result.length, 1, "ArchiveReader.getFilenames(): the array contains 1 item");
|
||||
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
|
||||
dump('Content: ' + this.result[0] + '\n');
|
||||
test2();
|
||||
}
|
||||
}
|
||||
|
||||
function test2()
|
||||
{
|
||||
var binaryFile = createNonUnicodeData();
|
||||
|
||||
var r = new ArchiveReader(binaryFile, { encoding: "random stuff" });
|
||||
isnot(r, null, "ArchiveReader cannot be null");
|
||||
|
||||
// GetFilename
|
||||
var handle = r.getFilenames();
|
||||
isnot(handle, null, "ArchiveReader.getFilenames() cannot be null");
|
||||
handle.onsuccess = function() {
|
||||
ok(true, "ArchiveReader.getFilenames() should return a 'success'");
|
||||
is(this.result instanceof Array, true, "ArchiveReader.getFilenames() should return an array");
|
||||
is(this.result.length, 0, "ArchiveReader.getFilenames(): the array contains 0 item");
|
||||
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
|
||||
finishTest();
|
||||
}
|
||||
}
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
test1();
|
||||
yield;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();">
|
||||
<p id="display">
|
||||
<input id="fileList" type="file"></input>
|
||||
</p>
|
||||
<script type="text/javascript;version=1.7">
|
||||
var binaryString = '' +
|
||||
'504B0304140000000000255D094100000000000000000000000002000000912F504B03040A0000000000285D09416BB50A5A' +
|
||||
'010000000100000007000000912F9B2E747874D8504B01023F00140000000000255D09410000000000000000000000000200' +
|
||||
'24000000000000001000000000000000912F0A002000000000000100180062505F1A1376CD0162505F1A1376CD01FE3F8D59' +
|
||||
'1176CD01504B01023F000A0000000000285D09416BB50A5A0100000001000000070024000000000000002000000020000000' +
|
||||
'912F9B2E7478740A0020000000000001001800565EF41D1376CD0107BD73631176CD0107BD73631176CD01504B0506000000' +
|
||||
'0002000200AD000000460000000000';
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -20,7 +20,8 @@ dictionaries = [
|
|||
[ 'CameraPosition', 'nsIDOMCameraManager.idl' ],
|
||||
[ 'CameraSelector', 'nsIDOMCameraManager.idl' ],
|
||||
[ 'CameraPictureOptions', 'nsIDOMCameraManager.idl' ],
|
||||
[ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ]
|
||||
[ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ],
|
||||
[ 'ArchiveReaderOptions', 'nsIDOMArchiveReader.idl' ]
|
||||
]
|
||||
|
||||
# include file names
|
||||
|
|
Загрузка…
Ссылка в новой задаче