From 172a65ae1121cbab87dff0501e4da3199c8f8e3b Mon Sep 17 00:00:00 2001 From: "gavin%gavinsharp.com" Date: Sun, 24 Sep 2006 16:23:31 +0000 Subject: [PATCH] back out bug 337561 --- modules/libjar/nsIZipReader.idl | 12 +- modules/libjar/nsJAR.cpp | 51 ++- modules/libjar/nsJAR.h | 4 +- modules/libjar/nsJARChannel.cpp | 14 +- modules/libjar/nsJARDirectoryInputStream.cpp | 309 +++++++++++++++++++ modules/libjar/nsJARInputStream.cpp | 224 ++------------ modules/libjar/nsJARInputStream.h | 25 +- modules/libjar/objs.mk | 1 + 8 files changed, 371 insertions(+), 269 deletions(-) diff --git a/modules/libjar/nsIZipReader.idl b/modules/libjar/nsIZipReader.idl index 45c61b56eba..c7afd76e350 100644 --- a/modules/libjar/nsIZipReader.idl +++ b/modules/libjar/nsIZipReader.idl @@ -90,7 +90,7 @@ interface nsIZipEntry : nsISupports readonly attribute boolean isSynthetic; }; -[scriptable, uuid(5cce7f53-23b3-47f8-be05-122c0ba703fd)] +[scriptable, uuid(08fa7e4b-4eec-4cae-b7fe-a3c1d1e9aed2)] interface nsIZipReader : nsISupports { /** @@ -186,18 +186,8 @@ interface nsIZipReader : nsISupports /** * Returns an input stream containing the contents of the specified zip * entry. - * @param zipEntry the name of the entry to open the stream from */ nsIInputStream getInputStream(in string zipEntry); - - /** - * Returns an input stream containing the contents of the specified zip - * entry. If the entry refers to a directory (ends with '/'), a directory stream - * is opened, otherwise the contents of the file entry is returned. - * @param aJarSpec the Spec of the URI for the JAR (only used for directory streams) - * @param zipEntry the name of the entry to open the stream from - */ - nsIInputStream getInputStreamWithSpec(in AUTF8String aJarSpec, in string zipEntry); }; //////////////////////////////////////////////////////////////////////////////// diff --git a/modules/libjar/nsJAR.cpp b/modules/libjar/nsJAR.cpp index 897f2213c0a..80e5c471c37 100644 --- a/modules/libjar/nsJAR.cpp +++ b/modules/libjar/nsJAR.cpp @@ -54,6 +54,8 @@ #include #endif +static PRTime GetModTime(PRUint16 aDate, PRUint16 aTime); + //---------------------------------------------- // nsJARManifestItem declaration //---------------------------------------------- @@ -312,42 +314,29 @@ nsJAR::FindEntries(const char *aPattern, nsIUTF8StringEnumerator **result) NS_IMETHODIMP nsJAR::GetInputStream(const char* aFilename, nsIInputStream** result) { - return GetInputStreamWithSpec(EmptyCString(), aFilename, result); -} - -NS_IMETHODIMP -nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec, - const char* aEntryName, nsIInputStream** result) -{ - NS_ENSURE_ARG_POINTER(aEntryName); NS_ENSURE_ARG_POINTER(result); - // Watch out for the jar:foo.zip!/ (aDir is empty) top-level special case! - PRFileDesc *fd = nsnull; - nsZipItem *item = nsnull; - if (*aEntryName) { - // First check if item exists in jar - item = mZip.GetItem(aEntryName); - if (!item) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST; - } - nsJARInputStream* jis = new nsJARInputStream(); - // addref now so we can call InitFile/InitDirectory() - NS_ENSURE_TRUE(jis, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*result = jis); + // First check if item exists in jar + nsZipItem *item = mZip.GetItem(aFilename); + if (!item) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST; - nsresult rv = NS_OK; - if (!item || item->isDirectory) { - rv = jis->InitDirectory(&mZip, aJarDirSpec, aEntryName); - } else { - // Open jarfile, to get its own filedescriptor for the stream - fd = OpenFile(); - rv = fd ? jis->InitFile(&mZip, item, fd) : NS_ERROR_FAILURE; - } + // Open jarfile, to get its own filedescriptor for the stream + PRFileDesc *fd = OpenFile(); + if (!fd) return NS_ERROR_FAILURE; + + nsJARInputStream* jis = new nsJARInputStream(); + if (!jis) return NS_ERROR_OUT_OF_MEMORY; + + // addref now so we can call Init() + *result = jis; + NS_ADDREF(*result); + + nsresult rv = jis->Init(this, item, fd); if (NS_FAILED(rv)) { NS_RELEASE(*result); - if (fd) PR_Close(fd); + return rv; } - return rv; + return NS_OK; } //---------------------------------------------- @@ -1280,7 +1269,7 @@ nsZipReaderCache::Observe(nsISupports *aSubject, return NS_OK; } -PRTime GetModTime(PRUint16 aDate, PRUint16 aTime) +static PRTime GetModTime(PRUint16 aDate, PRUint16 aTime) { char buffer[17]; diff --git a/modules/libjar/nsJAR.h b/modules/libjar/nsJAR.h index 96502412903..a3caec936aa 100644 --- a/modules/libjar/nsJAR.h +++ b/modules/libjar/nsJAR.h @@ -86,8 +86,6 @@ typedef enum JAR_NOT_SIGNED = 7 } JARManifestStatusType; -PRTime GetModTime(PRUint16 aDate, PRUint16 aTime); - /*------------------------------------------------------------------------- * Class nsJAR declaration. * nsJAR serves as an XPCOM wrapper for nsZipArchive with the addition of @@ -184,8 +182,8 @@ private: PRUint32 mSize; /* size in original file */ PRUint32 mRealsize; /* inflated size */ PRUint32 mCrc32; - PRUint16 mDate; PRUint16 mTime; + PRUint16 mDate; PRUint8 mCompression; PRPackedBool mIsDirectory; PRPackedBool mIsSynthetic; diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 87b698b4ac9..9c54464f33f 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -40,6 +40,7 @@ #include "nsJAR.h" #include "nsJARChannel.h" #include "nsJARProtocolHandler.h" +#include "nsJARDirectoryInputStream.h" #include "nsMimeTypes.h" #include "nsNetUtil.h" #include "nsInt64.h" @@ -144,16 +145,19 @@ nsJARInputThunk::EnsureJarStream() if (NS_FAILED(rv)) return rv; if (ENTRY_IS_DIRECTORY(mJarEntry)) { - // A directory stream also needs the Spec of the FullJarURI - // because is included in the stream data itself. + // This isn't simply part of nsJAR::GetInputStream because it shouldn't + // be possible to get an input stream for a directory in a zip via that + // path, just as it isn't possible to get a directory stream via an + // nsIFileInputStream nsCAutoString jarDirSpec; rv = mFullJarURI->GetAsciiSpec(jarDirSpec); if (NS_FAILED(rv)) return rv; - rv = mJarReader->GetInputStreamWithSpec(jarDirSpec, - mJarEntry.get(), - getter_AddRefs(mJarStream)); + rv = nsJARDirectoryInputStream::Create(mJarReader, + jarDirSpec, + mJarEntry.get(), + getter_AddRefs(mJarStream)); } else { rv = mJarReader->GetInputStream(mJarEntry.get(), diff --git a/modules/libjar/nsJARDirectoryInputStream.cpp b/modules/libjar/nsJARDirectoryInputStream.cpp index e69de29bb2d..3f96f541d1f 100644 --- a/modules/libjar/nsJARDirectoryInputStream.cpp +++ b/modules/libjar/nsJARDirectoryInputStream.cpp @@ -0,0 +1,309 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* nsJARDirectoryInputStream.cpp + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla libjar code. + * + * The Initial Developer of the Original Code is + * Jeff Walden . + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsJARDirectoryInputStream.h" +#include "nsNetUtil.h" +#include "nsEscape.h" +#include "nsIFile.h" + + +/*--------------------------------------------- + * nsISupports implementation + *--------------------------------------------*/ + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARDirectoryInputStream, nsIInputStream) + +/*---------------------------------------------------------- + * nsJARDirectoryInputStream implementation + *--------------------------------------------------------*/ + +NS_IMETHODIMP +nsJARDirectoryInputStream::Available(PRUint32 *_retval) +{ + if (NS_FAILED(mStatus)) + return mStatus; + + *_retval = mBuffer.Length(); + return NS_OK; +} + +NS_IMETHODIMP +nsJARDirectoryInputStream::Read(char* buf, PRUint32 count, PRUint32 *bytesRead) +{ + if (mStatus == NS_BASE_STREAM_CLOSED) { + *bytesRead = 0; + return NS_OK; + } + + if (NS_FAILED(mStatus)) + return mStatus; + + nsresult rv; + + // If the buffer contains data, copy what's there up to the desired amount + PRUint32 numRead = CopyDataToBuffer(buf, count); + + if (count > 0) { + // empty the buffer and start writing directory entry lines to it + mBuffer.Truncate(); + mBufPos = 0; + PRUint32 arrayLen = mArray.Count(); + for ( ;count > mBuffer.Length(); mArrPos++) { + // have we consumed all the directory contents? + if (arrayLen <= mArrPos) + break; + + // Name + const char * entryName = mArray[mArrPos]->get(); + PRUint32 entryNameLen = mArray[mArrPos]->Length(); + const char * relativeName = entryName + mDirNameLen; + PRUint32 relativeNameLen = entryNameLen - mDirNameLen; + + nsCOMPtr ze; + rv = mZip->GetEntry(entryName, getter_AddRefs(ze)); + if (NS_FAILED(rv)) return rv; + + // Type + PRBool isDir = PR_FALSE; + rv = ze->GetIsDirectory(&isDir); + if (NS_FAILED(rv)) return rv; + + // Size (real, not compressed) + PRUint32 itemRealSize = 0; + rv = ze->GetRealSize(&itemRealSize); + if (NS_FAILED(rv)) return rv; + + // Last Modified Time + PRTime lmt = LL_Zero(); + rv = ze->GetLastModifiedTime(&lmt); + if (NS_FAILED(rv)) return rv; + + PRExplodedTime tm; + PR_ExplodeTime(lmt, PR_GMTParameters, &tm); + char itemLastModTime[65]; + PR_FormatTimeUSEnglish(itemLastModTime, + sizeof(itemLastModTime), + " %a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", + &tm); + + // write a 201: line to the buffer for this item + // 200: filename content-length last-modified file-type + mBuffer.AppendLiteral("201: "); + + // Names must be escaped and relative, so use the pre-calculated length + // of the directory name as the offset into the string + // NS_EscapeURL adds the escaped URL to the give string buffer + NS_EscapeURL(relativeName, relativeNameLen, + esc_Minimal | esc_AlwaysCopy, mBuffer); + + mBuffer.AppendLiteral(" "); + mBuffer.AppendInt(itemRealSize, 10); + mBuffer.Append(itemLastModTime); // starts/ends with ' ' + mBuffer.Append(isDir ? "DIRECTORY\n" : "FILE\n"); + } + + // Copy up to the desired amount of data to buffer + numRead += CopyDataToBuffer(buf, count); + } + + *bytesRead = numRead; + return NS_OK; +} + +NS_IMETHODIMP +nsJARDirectoryInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval) +{ + // XXX write me! + NS_NOTREACHED("Consumers should be using Read()!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsJARDirectoryInputStream::IsNonBlocking(PRBool *aNonBlocking) +{ + *aNonBlocking = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsJARDirectoryInputStream::Close() +{ + mStatus = NS_BASE_STREAM_CLOSED; + return NS_OK; +} + +/* static */ nsresult +nsJARDirectoryInputStream::Create(nsIZipReader* aZip, + const nsACString& aJarDirSpec, + const char* aDir, + nsIInputStream** result) +{ + NS_ENSURE_ARG_POINTER(aZip); + NS_ENSURE_ARG_POINTER(aDir); + NS_ENSURE_ARG_POINTER(result); + + nsJARDirectoryInputStream* jdis = new nsJARDirectoryInputStream(); + if (!jdis) return NS_ERROR_OUT_OF_MEMORY; + + // addref now so we can call Init() + *result = jdis; + NS_ADDREF(*result); + + nsresult rv = jdis->Init(aZip, aJarDirSpec, aDir); + if (NS_FAILED(rv)) NS_RELEASE(*result); + + return rv; +} + +nsresult +nsJARDirectoryInputStream::Init(nsIZipReader* aZip, + const nsACString& aJarDirSpec, + const char* aDir) +{ + // Ensure that aDir is really a directory and that it exists. + // Watch out for the jar:foo.zip!/ (aDir is empty) top-level + // special case! + nsresult rv; + + // Keep the zipReader for getting the actual zipItems + mZip = aZip; + + if (*aDir) { + nsCOMPtr ze; + rv = aZip->GetEntry(aDir, getter_AddRefs(ze)); + if (NS_FAILED(rv)) return rv; + + PRBool isDir; + rv = ze->GetIsDirectory(&isDir); + if (NS_FAILED(rv)) return rv; + + if (!isDir) + return NS_ERROR_ILLEGAL_VALUE; + } + + // We can get aDir's contents as strings via FindEntries + // with the following pattern (see nsIZipReader.findEntries docs) + // assuming dirName is properly escaped: + // + // dirName + "?*~" + dirName + "?*/?*" + nsDependentCString dirName(aDir); + mDirNameLen = dirName.Length(); + + // iterate through dirName and copy it to escDirName, escaping chars + // which are special at the "top" level of the regexp so FindEntries + // works correctly + nsCAutoString escDirName; + const char* curr = dirName.BeginReading(); + const char* end = dirName.EndReading(); + while (curr != end) { + switch (*curr) { + case '*': + case '?': + case '$': + case '[': + case ']': + case '^': + case '~': + case '(': + case ')': + case '\\': + escDirName.Append('\\'); + // fall through + default: + escDirName.Append(*curr); + } + ++curr; + } + + nsCAutoString pattern = escDirName + NS_LITERAL_CSTRING("?*~") + + escDirName + NS_LITERAL_CSTRING("?*/?*"); + + nsCOMPtr dirEnum; + rv = aZip->FindEntries(pattern.get(), getter_AddRefs(dirEnum)); + if (NS_FAILED(rv)) return rv; + + PRBool more; + nsCAutoString entryName; + while (NS_SUCCEEDED(dirEnum->HasMore(&more)) && more) { + rv = dirEnum->GetNext(entryName); + if (NS_SUCCEEDED(rv)) { + mArray.AppendCString(entryName); + } + } + + // Sort it + mArray.Sort(); + + mBuffer.AppendLiteral("300: "); + mBuffer.Append(aJarDirSpec); + mBuffer.AppendLiteral("\n200: filename content-length last-modified file-type\n"); + + return NS_OK; +} + +PRUint32 +nsJARDirectoryInputStream::CopyDataToBuffer(char* &aBuffer, PRUint32 &aCount) +{ + PRUint32 writeLength = PR_MIN(aCount, mBuffer.Length() - mBufPos); + + if (writeLength > 0) { + memcpy(aBuffer, mBuffer.get() + mBufPos, writeLength); + mBufPos += writeLength; + aCount -= writeLength; + aBuffer += writeLength; + } + + // return number of bytes copied to the buffer so the + // Read method can return the number of bytes copied + return writeLength; +} + +//---------------------------------------------- +// nsJARDirectoryInputStream constructor and destructor +//---------------------------------------------- + +nsJARDirectoryInputStream::nsJARDirectoryInputStream() + : mStatus(NS_OK), mArrPos(0), mBufPos(0) +{ +} + +nsJARDirectoryInputStream::~nsJARDirectoryInputStream() +{ + Close(); +} diff --git a/modules/libjar/nsJARInputStream.cpp b/modules/libjar/nsJARInputStream.cpp index 9b7157ffef6..2672e1cdcde 100644 --- a/modules/libjar/nsJARInputStream.cpp +++ b/modules/libjar/nsJARInputStream.cpp @@ -42,9 +42,6 @@ #include "zipstruct.h" // defines ZIP compression codes #include "nsZipArchive.h" -#include "nsNetUtil.h" -#include "nsEscape.h" -#include "nsIFile.h" /*--------------------------------------------- * nsISupports implementation @@ -57,11 +54,11 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputStream, nsIInputStream) *--------------------------------------------------------*/ nsresult -nsJARInputStream::InitFile(nsZipArchive* aZip, nsZipItem *item, PRFileDesc *fd) +nsJARInputStream::Init(nsJAR* aJAR, nsZipItem *item, PRFileDesc *fd) { nsresult rv; - NS_ENSURE_ARG_POINTER(aZip); + NS_ENSURE_ARG_POINTER(aJAR); NS_ENSURE_ARG_POINTER(item); NS_ENSURE_ARG_POINTER(fd); @@ -96,96 +93,11 @@ nsJARInputStream::InitFile(nsZipArchive* aZip, nsZipItem *item, PRFileDesc *fd) } //-- Set filepointer to start of item - rv = aZip->SeekToItem(item, mFd); + rv = aJAR->mZip.SeekToItem(item, mFd); NS_ENSURE_SUCCESS(rv, NS_ERROR_FILE_CORRUPTED); // Open for reading mClosed = PR_FALSE; - mCurPos = 0; - return NS_OK; -} - -nsresult -nsJARInputStream::InitDirectory(nsZipArchive* aZip, - const nsACString& aJarDirSpec, - const char* aDir) -{ - NS_ENSURE_ARG_POINTER(aZip); - NS_ENSURE_ARG_POINTER(aDir); - - // Mark it as closed, in case something fails in initialisation - mClosed = PR_TRUE; - mDirectory = PR_TRUE; - - // Keep the zipReader for getting the actual zipItems - mZip = aZip; - nsZipFind *find; - nsresult rv; - if (*aDir) { - // We can get aDir's contents as strings via FindEntries - // with the following pattern (see nsIZipReader.findEntries docs) - // assuming dirName is properly escaped: - // - // dirName + "?*~" + dirName + "?*/?*" - nsDependentCString dirName(aDir); - mNameLen = dirName.Length(); - - // iterate through dirName and copy it to escDirName, escaping chars - // which are special at the "top" level of the regexp so FindEntries - // works correctly - nsCAutoString escDirName; - const char* curr = dirName.BeginReading(); - const char* end = dirName.EndReading(); - while (curr != end) { - switch (*curr) { - case '*': - case '?': - case '$': - case '[': - case ']': - case '^': - case '~': - case '(': - case ')': - case '\\': - escDirName.Append('\\'); - // fall through - default: - escDirName.Append(*curr); - } - ++curr; - } - nsCAutoString pattern = escDirName + NS_LITERAL_CSTRING("?*~") + - escDirName + NS_LITERAL_CSTRING("?*/?*"); - rv = aZip->FindInit(pattern.get(), &find); - } else { - mNameLen = 0; - rv = aZip->FindInit(nsnull, &find); - } - if (NS_FAILED(rv)) return rv; - - const char *name; - while ((rv = find->FindNext( &name )) == NS_OK) { - // No need to copy string, just share the one from nsZipArchive - mArray.AppendCString(nsDependentCString(name)); - } - delete find; - - if (rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST && NS_FAILED(rv)) { - return NS_ERROR_FAILURE; // no error translation - } - - // Sort it - mArray.Sort(); - - mBuffer.AssignLiteral("300: "); - mBuffer.Append(aJarDirSpec); - mBuffer.AppendLiteral("\n200: filename content-length last-modified file-type\n"); - - // Open for reading - mClosed = PR_FALSE; - mCurPos = 0; - mArrPos = 0; return NS_OK; } @@ -195,9 +107,7 @@ nsJARInputStream::Available(PRUint32 *_retval) if (mClosed) return NS_BASE_STREAM_CLOSED; - if (mDirectory) - *_retval = mBuffer.Length(); - else if (mInflate) + if (mInflate) *_retval = mInflate->mOutSize - mInflate->mZs.total_out; else *_retval = mInSize - mCurPos; @@ -216,31 +126,28 @@ nsJARInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) if (mClosed) return rv; - if (mDirectory) { - rv = ReadDirectory(aBuffer, aCount, aBytesRead); + if (mInflate) { + rv = ContinueInflate(aBuffer, aCount, aBytesRead); } else { - if (mInflate) { - rv = ContinueInflate(aBuffer, aCount, aBytesRead); - } else { - PRInt32 bytesRead = 0; - aCount = PR_MIN(aCount, mInSize - mCurPos); - if (aCount) { - bytesRead = PR_Read(mFd, aBuffer, aCount); - if (bytesRead < 0) - return NS_ERROR_FILE_CORRUPTED; - mCurPos += bytesRead; - } - *aBytesRead = bytesRead; - } - - // be aggressive about closing! - // note that sometimes, we will close mFd before we've finished - // deflating - this is because zlib buffers the input - // So, don't free the ReadBuf/InflateStruct yet. - if (mCurPos >= mInSize && mFd) { - PR_Close(mFd); - mFd = nsnull; + PRInt32 bytesRead = 0; + if (aCount > mInSize - mCurPos) + aCount = mInSize - mCurPos; + if (aCount) { + bytesRead = PR_Read(mFd, aBuffer, aCount); + if (bytesRead < 0) + return NS_ERROR_FILE_CORRUPTED; + mCurPos += bytesRead; } + *aBytesRead = bytesRead; + } + + // be aggressive about closing! + // note that sometimes, we will close mFd before we've finished + // deflating - this is because zlib buffers the input + // So, don't free the ReadBuf/InflateStruct yet. + if (mCurPos >= mInSize && mFd) { + PR_Close(mFd); + mFd = nsnull; } return rv; } @@ -294,7 +201,7 @@ nsJARInputStream::ContinueInflate(char* aBuffer, PRUint32 aCount, if (mInflate->mZs.avail_in == 0 && mCurPos < mInSize) { // time to fill the buffer! - PRUint32 bytesToRead = PR_MIN(mInSize - mCurPos, ZIP_BUFLEN); + PRUint32 bytesToRead = (mInSize-mCurPos < ZIP_BUFLEN) ? mInSize-mCurPos : ZIP_BUFLEN; NS_ASSERTION(mFd, "File handle missing"); PRInt32 bytesRead = PR_Read(mFd, mInflate->mReadBuf, bytesToRead); @@ -337,84 +244,3 @@ nsJARInputStream::ContinueInflate(char* aBuffer, PRUint32 aCount, return NS_OK; } - -nsresult -nsJARInputStream::ReadDirectory(char* buf, PRUint32 count, PRUint32 *bytesRead) -{ - // No need to check the args, ::Read did that, but assert them at least - NS_ASSERTION(aBuffer,"aBuffer parameter must not be null"); - NS_ASSERTION(aBytesRead,"aBytesRead parameter must not be null"); - - // If the buffer contains data, copy what's there up to the desired amount - PRUint32 numRead = CopyDataToBuffer(buf, count); - - if (count > 0) { - // empty the buffer and start writing directory entry lines to it - mBuffer.Truncate(); - mCurPos = 0; - const PRUint32 arrayLen = mArray.Count(); - - for ( ;count > mBuffer.Length(); mArrPos++) { - // have we consumed all the directory contents? - if (arrayLen <= mArrPos) - break; - - const char * entryName = mArray[mArrPos]->get(); - PRUint32 entryNameLen = mArray[mArrPos]->Length(); - nsZipItem* ze = mZip->GetItem(entryName); - NS_ENSURE_TRUE(ze, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST); - - // Last Modified Time - PRExplodedTime tm; - PR_ExplodeTime(GetModTime(ze->date, ze->time), PR_GMTParameters, &tm); - char itemLastModTime[65]; - PR_FormatTimeUSEnglish(itemLastModTime, - sizeof(itemLastModTime), - " %a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", - &tm); - - // write a 201: line to the buffer for this item - // 200: filename content-length last-modified file-type - mBuffer.AppendLiteral("201: "); - - // Names must be escaped and relative, so use the pre-calculated length - // of the directory name as the offset into the string - // NS_EscapeURL adds the escaped URL to the give string buffer - NS_EscapeURL(entryName + mNameLen, - entryNameLen - mNameLen, - esc_Minimal | esc_AlwaysCopy, - mBuffer); - - mBuffer.Append(' '); - mBuffer.AppendInt(ze->realsize, 10); - mBuffer.Append(itemLastModTime); // starts/ends with ' ' - if (ze->isDirectory) - mBuffer.AppendLiteral("DIRECTORY\n"); - else - mBuffer.AppendLiteral("FILE\n"); - } - - // Copy up to the desired amount of data to buffer - numRead += CopyDataToBuffer(buf, count); - } - - *bytesRead = numRead; - return NS_OK; -} - -PRUint32 -nsJARInputStream::CopyDataToBuffer(char* &aBuffer, PRUint32 &aCount) -{ - const PRUint32 writeLength = PR_MIN(aCount, mBuffer.Length() - mCurPos); - - if (writeLength > 0) { - memcpy(aBuffer, mBuffer.get() + mCurPos, writeLength); - mCurPos += writeLength; - aCount -= writeLength; - aBuffer += writeLength; - } - - // return number of bytes copied to the buffer so the - // Read method can return the number of bytes copied - return writeLength; -} diff --git a/modules/libjar/nsJARInputStream.h b/modules/libjar/nsJARInputStream.h index 12cbd68f97f..ec8249dc97d 100644 --- a/modules/libjar/nsJARInputStream.h +++ b/modules/libjar/nsJARInputStream.h @@ -52,23 +52,19 @@ class nsJARInputStream : public nsIInputStream { public: nsJARInputStream() : - mFd(nsnull), mInSize(0), mCurPos(0), - mClosed(PR_FALSE), mInflate(nsnull), mDirectory(0) { } + mFd(nsnull), mInSize(0), mCurPos(0), + mClosed(PR_FALSE), mInflate(nsnull) { } - ~nsJARInputStream() { Close(); } - NS_DECL_ISUPPORTS NS_DECL_NSIINPUTSTREAM - nsresult InitFile(nsZipArchive* aZip, nsZipItem *item, PRFileDesc *fd); - nsresult InitDirectory(nsZipArchive* aZip, - const nsACString& aJarDirSpec, - const char* aDir); + nsresult Init(nsJAR* jar, nsZipItem *item, PRFileDesc *fd); private: PRFileDesc* mFd; // My own file handle, for reading PRUint32 mInSize; // Size in original file PRUint32 mCurPos; // Current position in input + PRPackedBool mClosed; // Whether the stream is closed struct InflateStruct { PRUint32 mOutSize; // inflated size @@ -79,19 +75,8 @@ class nsJARInputStream : public nsIInputStream }; struct InflateStruct * mInflate; - /* For directory reading */ - nsZipArchive* mZip; // the zipReader - PRUint32 mNameLen; // length of dirname - nsCAutoString mBuffer; // storage for generated text of stream - PRUint32 mArrPos; // current position within mArray - nsCStringArray mArray; // array of names in (zip) directory - - PRPackedBool mDirectory; - PRPackedBool mClosed; // Whether the stream is closed - + ~nsJARInputStream() { Close(); } nsresult ContinueInflate(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead); - nsresult ReadDirectory(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead); - PRUint32 CopyDataToBuffer(char* &aBuffer, PRUint32 &aCount); }; #endif /* nsJARINPUTSTREAM_h__ */ diff --git a/modules/libjar/objs.mk b/modules/libjar/objs.mk index d87cda66de8..5c32b638fa8 100644 --- a/modules/libjar/objs.mk +++ b/modules/libjar/objs.mk @@ -43,6 +43,7 @@ MODULES_STANDALONE_LCPPSRCS = \ MODULES_LIBJAR_LCPPSRCS = \ $(MODULES_STANDALONE_LCPPSRCS) \ nsJARInputStream.cpp \ + nsJARDirectoryInputStream.cpp \ nsJAR.cpp \ nsJARFactory.cpp \ nsXPTZipLoader.cpp \