# HG changeset patch # Parent bcb8506b23d3df7acafd7c46df9cc391df19466d # User Andrea Marchesini try: -b do -p all -u all -t none diff --git a/dom/file/ArchiveEvent.cpp b/dom/file/ArchiveEvent.cpp --- a/dom/file/ArchiveEvent.cpp +++ b/dom/file/ArchiveEvent.cpp @@ -92,20 +92,25 @@ ArchiveReaderEvent::ShareMainThread() for (PRUint32 index = 0; index < mFileList.Length(); ++index) { nsRefPtr item = mFileList[index]; - PRInt32 offset = item->GetFilename().RFindChar('.'); + nsCString filename; + nsresult rv = item->GetFilename(filename); + if (NS_FAILED(rv)) + continue; + + PRInt32 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 file = item->File(mArchiveReader); - fileList.AppendElement(file); + if (file) + fileList.AppendElement(file); } } diff --git a/dom/file/ArchiveEvent.h b/dom/file/ArchiveEvent.h --- a/dom/file/ArchiveEvent.h +++ b/dom/file/ArchiveEvent.h @@ -32,7 +32,7 @@ public: virtual void SetType(const nsCString& aType); // Getter for the filename - virtual nsCString GetFilename() = 0; + virtual nsresult GetFilename(nsCString& aFilename) = 0; // Generate a DOMFile virtual nsIDOMFile* File(ArchiveReader* aArchiveReader) = 0; diff --git a/dom/file/ArchiveZipEvent.cpp b/dom/file/ArchiveZipEvent.cpp --- a/dom/file/ArchiveZipEvent.cpp +++ b/dom/file/ArchiveZipEvent.cpp @@ -8,6 +8,8 @@ #include "ArchiveZipFile.h" #include "nsContentUtils.h" +#include "nsIPlatformCharset.h" +#include "nsNativeCharsetUtils.h" #include "nsCExternalHandlerService.h" USING_FILE_NAMESPACE @@ -30,25 +32,115 @@ ArchiveZipItem::~ArchiveZipItem() MOZ_COUNT_DTOR(ArchiveZipItem); } -// Getter/Setter for the filename -nsCString -ArchiveZipItem::GetFilename() +nsresult +ArchiveZipItem::NativeFilename() { - return mFilename; + if (NS_IsNativeUTF8()) + return NS_ERROR_FAILURE; + + nsString filenameU; + nsCString charset; + + nsresult rv; + nsCOMPtr platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset); + NS_ENSURE_SUCCESS(rv, rv); + + rv = nsContentUtils::ConvertStringFromCharset(charset, mFilename, filenameU); + NS_ENSURE_SUCCESS(rv, rv); + + if (filenameU.IsEmpty()) + return NS_ERROR_FAILURE; + + mFilenameU = NS_ConvertUTF16toUTF8(filenameU); + return NS_OK; } -void -ArchiveZipItem::SetFilename(const nsCString& aFilename) +nsresult +ArchiveZipItem::GuessFilename() { - mFilename = aFilename; + nsCString charset; + nsresult rv = nsContentUtils::GuessCharset(mFilename.get(), mFilename.Length(), charset); + NS_ENSURE_SUCCESS(rv, rv); + + // The charset cannot be UTF-8: + if (charset.IsEmpty() || charset.EqualsLiteral("UTF-8")) + return NS_ERROR_FAILURE; + + nsString filenameU; + rv = nsContentUtils::ConvertStringFromCharset(charset, mFilename, filenameU); + NS_ENSURE_SUCCESS(rv, rv); + + if (filenameU.IsEmpty()) + return NS_ERROR_FAILURE; + + mFilenameU = NS_ConvertUTF16toUTF8(filenameU); + return NS_OK; } +nsresult +ArchiveZipItem::ISO8859Filename() +{ + nsString filenameU; + nsresult rv = nsContentUtils::ConvertStringFromCharset(NS_LITERAL_CSTRING("ISO-8859-1"), mFilename, filenameU); + NS_ENSURE_SUCCESS(rv, rv); + + if (filenameU.IsEmpty()) + return NS_ERROR_FAILURE; + + mFilenameU = NS_ConvertUTF16toUTF8(filenameU); + return NS_OK; +} + +nsresult +ArchiveZipItem::GetFilename(nsCString& aFilename) +{ + NS_ASSERTION(NS_IsMainThread(), "main thread only"); + + if (mFilenameU.IsEmpty()) { + nsresult rv = NS_ERROR_FAILURE; + + // Maybe this string is UTF-8: + if (IsUTF8(mFilename, false)) { + mFilenameU = mFilename; + rv = NS_OK; + } + + // native UTF8? + if (NS_FAILED(rv) && !NS_IsNativeUTF8()) { + rv = NativeFilename(); + } + + // Let's try to guess the charset: + if (NS_FAILED(rv)) { + rv = GuessFilename(); + } + + // Last option: + if (NS_FAILED(rv)) { + rv = ISO8859Filename(); + } + + 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), + nsCString filename; + nsresult rv = GetFilename(filename); + + if (NS_FAILED(rv)) + return 0; + + return new ArchiveZipFile(NS_ConvertUTF8toUTF16(filename), NS_ConvertUTF8toUTF16(GetType()), StrToInt32(mCentralStruct.orglen), mCentralStruct, diff --git a/dom/file/ArchiveZipEvent.h b/dom/file/ArchiveZipEvent.h --- a/dom/file/ArchiveZipEvent.h +++ b/dom/file/ArchiveZipEvent.h @@ -21,8 +21,7 @@ public: ZipCentral& aCentralStruct); virtual ~ArchiveZipItem(); - void SetFilename(const nsCString& aFilename); - nsCString GetFilename(); + nsresult GetFilename(nsCString& aFilename); // From zipItem to DOMFile: virtual nsIDOMFile* File(ArchiveReader* aArchiveReader); @@ -31,8 +30,15 @@ public: // for the event static PRUint32 StrToInt32(const PRUint8* aStr); static PRUint16 StrToInt16(const PRUint8* aStr); +private: + nsresult NativeFilename(); + nsresult GuessFilename(); + nsresult ISO8859Filename(); + private: // data nsCString mFilename; + + nsCString mFilenameU; ZipCentral mCentralStruct; }; diff --git a/dom/file/test/Makefile.in b/dom/file/test/Makefile.in --- a/dom/file/test/Makefile.in +++ b/dom/file/test/Makefile.in @@ -31,6 +31,7 @@ MOCHITEST_FILES = \ test_workers.html \ test_archivereader.html \ test_archivereader_zip_in_zip.html \ + test_archivereader_nonUnicode.html \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/file/test/test_archivereader_nonUnicode.html b/dom/file/test/test_archivereader_nonUnicode.html new file mode 100644 --- /dev/null +++ b/dom/file/test/test_archivereader_nonUnicode.html @@ -0,0 +1,80 @@ + + + + Archive Reader Non-Unicode Test + + + + + + + + + + +

+ +

+ + + +