diff --git a/mailnews/compose/public/nsIURLFetcher.idl b/mailnews/compose/public/nsIURLFetcher.idl index 350f29e05b14..c824795b2ff7 100644 --- a/mailnews/compose/public/nsIURLFetcher.idl +++ b/mailnews/compose/public/nsIURLFetcher.idl @@ -22,11 +22,11 @@ #include "nsISupports.idl" #include "nsIURI.idl" +#include "nsIFileStreams.idl" +#include "nsILocalFile.idl" %{ C++ -#include "nsFileStream.h" - // // Callback declarations for URL completion // @@ -39,7 +39,6 @@ typedef nsresult (*nsAttachSaveCompletionCallback) (nsresult aStatus, %} -[ptr] native nsOutputFileStream(nsOutputFileStream); native nsAttachSaveCompletionCallback(nsAttachSaveCompletionCallback); @@ -48,7 +47,7 @@ interface nsIURLFetcher : nsISupports { boolean stillRunning(); - void fireURLRequest(in nsIURI aURL, in nsOutputFileStream fOut, in nsAttachSaveCompletionCallback cb, in voidPtr tagData); + void fireURLRequest(in nsIURI aURL, in nsILocalFile localFile, in nsIFileOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData); - void initialize(in nsOutputFileStream fOut, in nsAttachSaveCompletionCallback cb, in voidPtr tagData); + void initialize(in nsILocalFile localFile, in nsIFileOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData); }; diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.cpp b/mailnews/compose/src/nsMsgAttachmentHandler.cpp index a0c05a48a22b..46ad7f962764 100644 --- a/mailnews/compose/src/nsMsgAttachmentHandler.cpp +++ b/mailnews/compose/src/nsMsgAttachmentHandler.cpp @@ -100,7 +100,6 @@ nsMsgAttachmentHandler::nsMsgAttachmentHandler() mCompFields = nsnull; // Message composition fields for the sender mFileSpec = nsnull; - mOutFile = nsnull; mURL = nsnull; mRequest = nsnull; @@ -465,12 +464,17 @@ nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields) rv = NS_ERROR_FAILURE; goto done; } - mOutFile = new nsOutputFileStream(*mFileSpec, PR_WRONLY | PR_CREATE_FILE, 00600); - if (!mOutFile) + + nsCOMPtr localFile; + nsCOMPtr outputStream; + NS_FileSpecToIFile(mFileSpec, getter_AddRefs(localFile)); + rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), localFile, -1, 00600); + if (NS_FAILED(rv) || !outputStream) { rv = NS_MSG_UNABLE_TO_OPEN_TMP_FILE; goto done; } + mOutFile = do_QueryInterface(outputStream); nsCOMPtr fetcher = do_CreateInstance(NS_URLFETCHER_CONTRACTID, &rv); if (NS_FAILED(rv) || !fetcher) @@ -480,7 +484,7 @@ nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields) goto done; } - rv = fetcher->Initialize(mOutFile, FetcherURLDoneCallback, this); + rv = fetcher->Initialize(localFile, mOutFile, FetcherURLDoneCallback, this); rv = GetMessageServiceFromURI(m_uri, &messageService); if (NS_SUCCEEDED(rv) && messageService) { @@ -496,8 +500,7 @@ done: { if (mOutFile) { - mOutFile->close(); - delete mOutFile; + mOutFile->Close(); mOutFile = nsnull; } @@ -550,13 +553,17 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields) if (! mFileSpec ) return (NS_ERROR_FAILURE); - mOutFile = new nsOutputFileStream(*mFileSpec, PR_WRONLY | PR_CREATE_FILE, 00600); - if (!mOutFile) + nsCOMPtr localFile; + nsCOMPtr outputStream; + NS_FileSpecToIFile(mFileSpec, getter_AddRefs(localFile)); + status = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), localFile, -1, 00600); + if (NS_FAILED(status) || !outputStream) { delete mFileSpec; mFileSpec = nsnull; return NS_MSG_UNABLE_TO_OPEN_TMP_FILE; } + mOutFile = do_QueryInterface(outputStream); mURL->GetSpec(getter_Copies(url_string)); @@ -616,25 +623,25 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields) // then, if we have a resource fork, check the filename extension, maybe we don't need the resource fork! if (sendResourceFork) { - nsAutoString urlStr; urlStr.AssignWithConversion(url_string); - char *ext = nsMsgGetExtensionFromFileURL(urlStr); - if (ext && *ext) - { - sendResourceFork = - PL_strcasecmp(ext, "TXT") && - PL_strcasecmp(ext, "JPG") && - PL_strcasecmp(ext, "GIF") && - PL_strcasecmp(ext, "TIF") && - PL_strcasecmp(ext, "HTM") && - PL_strcasecmp(ext, "HTML") && - PL_strcasecmp(ext, "ART") && - PL_strcasecmp(ext, "XUL") && - PL_strcasecmp(ext, "XML") && - PL_strcasecmp(ext, "CSS") && - PL_strcasecmp(ext, "JS"); + nsAutoString urlStr; urlStr.AssignWithConversion(url_string); + char *ext = nsMsgGetExtensionFromFileURL(urlStr); + if (ext && *ext) + { + sendResourceFork = + PL_strcasecmp(ext, "TXT") && + PL_strcasecmp(ext, "JPG") && + PL_strcasecmp(ext, "GIF") && + PL_strcasecmp(ext, "TIF") && + PL_strcasecmp(ext, "HTM") && + PL_strcasecmp(ext, "HTML") && + PL_strcasecmp(ext, "ART") && + PL_strcasecmp(ext, "XUL") && + PL_strcasecmp(ext, "XML") && + PL_strcasecmp(ext, "CSS") && + PL_strcasecmp(ext, "JS"); + } + PR_FREEIF(ext); } - PR_FREEIF(ext); - } } // Only use appledouble if we aren't uuencoding. @@ -825,7 +832,7 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields) return rv; } - status = fetcher->FireURLRequest(mURL, mOutFile, FetcherURLDoneCallback, this); + status = fetcher->FireURLRequest(mURL, localFile, mOutFile, FetcherURLDoneCallback, this); if (NS_FAILED(status)) return NS_ERROR_UNEXPECTED; @@ -892,9 +899,7 @@ nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg) // Close the file, but don't delete the disk file (or the file spec.) if (mOutFile) { - mOutFile->close(); - - delete mOutFile; + mOutFile->Close(); mOutFile = nsnull; } diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.h b/mailnews/compose/src/nsMsgAttachmentHandler.h index 85d451a4cbf4..75217ee2ea84 100644 --- a/mailnews/compose/src/nsMsgAttachmentHandler.h +++ b/mailnews/compose/src/nsMsgAttachmentHandler.h @@ -29,6 +29,7 @@ #include "nsIMsgStatusFeedback.h" #include "nsIRequest.h" #include "nsIMsgSend.h" +#include "nsIFileStreams.h" #ifdef XP_MAC @@ -81,7 +82,7 @@ private: public: nsIURI *mURL; nsFileSpec *mFileSpec; // The temp file to which we save it - nsOutputFileStream *mOutFile; // The temp file stream pointer + nsCOMPtr mOutFile; nsIRequest *mRequest; // The live request used while fetching an attachment nsMsgCompFields *mCompFields; // Message composition fields for the sender PRBool m_bogus_attachment; // This is to catch problem children... diff --git a/mailnews/compose/src/nsMsgSend.cpp b/mailnews/compose/src/nsMsgSend.cpp index fa562e97282a..56b4772caa85 100644 --- a/mailnews/compose/src/nsMsgSend.cpp +++ b/mailnews/compose/src/nsMsgSend.cpp @@ -271,7 +271,7 @@ nsMsgComposeAndSend::Clear() if (m_plaintext) { if (m_plaintext->mOutFile) - m_plaintext->mOutFile->close(); + m_plaintext->mOutFile->Close(); if (m_plaintext->mFileSpec) { @@ -357,8 +357,8 @@ nsMsgComposeAndSend::Clear() PR_FREEIF (m_attachments [i].m_real_name); PR_FREEIF (m_attachments [i].m_encoding); PR_FREEIF (m_attachments [i].m_content_id); - if ( (m_attachments[i].mOutFile) && (m_attachments[i].mOutFile->is_open()) ) - m_attachments[i].mOutFile->close(); + if (m_attachments[i].mOutFile) + m_attachments[i].mOutFile->Close(); if (m_attachments[i].mFileSpec) { // Only Delete the file if this variable is set! diff --git a/mailnews/compose/src/nsURLFetcher.cpp b/mailnews/compose/src/nsURLFetcher.cpp index def950967086..cdaa4b0b7994 100644 --- a/mailnews/compose/src/nsURLFetcher.cpp +++ b/mailnews/compose/src/nsURLFetcher.cpp @@ -42,10 +42,10 @@ #include "nsIWebProgress.h" #include "nsMsgAttachmentHandler.h" #include "nsMsgSend.h" +#include "nsIStreamConverterService.h" static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); - NS_IMPL_ISUPPORTS6(nsURLFetcher, nsIURLFetcher, nsIStreamListener, nsIURIContentListener, nsIInterfaceRequestor, nsIWebProgressListener, nsISupportsWeakReference) @@ -61,13 +61,15 @@ nsURLFetcher::nsURLFetcher() NS_INIT_REFCNT(); // Init member variables... - mOutStream = nsnull; mTotalWritten = 0; + mBuffer = nsnull; + mBufferSize = 0; mStillRunning = PR_TRUE; mCallback = nsnull; - mContentType = nsnull; - mCharset = nsnull; mOnStopRequestProcessed = PR_FALSE; + + nsURLFetcherStreamConsumer *consumer = new nsURLFetcherStreamConsumer(this); + mConverter = do_QueryInterface(consumer); } nsURLFetcher::~nsURLFetcher() @@ -77,8 +79,7 @@ nsURLFetcher::~nsURLFetcher() #endif mStillRunning = PR_FALSE; - PR_FREEIF(mContentType); - PR_FREEIF(mCharset); + PR_FREEIF(mBuffer); // Remove the DocShell as a listener of the old WebProgress... if (mLoadCookie) { @@ -127,18 +128,11 @@ nsURLFetcher::CanHandleContent(const char * aContentType, PRBool * aCanHandleContent) { - // if the content type is unknown, we should let the unknown decoder take care of it. - // we will be called back again with a better content type! - if (nsCRT::strcasecmp(aContentType, UNKNOWN_CONTENT_TYPE) == 0) - *aCanHandleContent = PR_FALSE; - else - { if (nsCRT::strcasecmp(aContentType, MESSAGE_RFC822) == 0) *aDesiredContentType = nsCRT::strdup("text/html"); // since we explicilty loaded the url, we always want to handle it! *aCanHandleContent = PR_TRUE; - } return NS_OK; } @@ -150,9 +144,24 @@ nsURLFetcher::DoContent(const char * aContentType, PRBool * aAbortProcess) { nsresult rv = NS_OK; + if (aAbortProcess) *aAbortProcess = PR_FALSE; QueryInterface(NS_GET_IID(nsIStreamListener), (void **) aContentHandler); + + /* + Check the content-type to see if we need to insert a converter + */ + if (nsCRT::strcasecmp(aContentType, UNKNOWN_CONTENT_TYPE) == 0 || + nsCRT::strcasecmp(aContentType, MULTIPART_MIXED_REPLACE) == 0 || + nsCRT::strcasecmp(aContentType, MULTIPART_MIXED) == 0 || + nsCRT::strcasecmp(aContentType, MULTIPART_BYTERANGES) == 0) + { + rv = InsertConverter(aContentType); + if (NS_SUCCEEDED(rv)) + mConverterContentType = aContentType; + } + return rv; } @@ -216,31 +225,11 @@ nsresult nsURLFetcher::OnDataAvailable(nsIRequest *request, nsISupports * ctxt, nsIInputStream *aIStream, PRUint32 sourceOffset, PRUint32 aLength) { - PRUint32 readLen = aLength; - PRUint32 wroteIt; - - if (!mOutStream) - return NS_ERROR_INVALID_ARG; - - char *buf = (char *)PR_Malloc(aLength); - if (!buf) - return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */ - - // read the data from the input stram... - nsresult rv = aIStream->Read(buf, aLength, &readLen); - if (NS_FAILED(rv)) return rv; - - // write to the output file... - wroteIt = mOutStream->write(buf, readLen); - PR_FREEIF(buf); - - if (wroteIt != readLen) + /* let our converter or consumer process the data */ + if (!mConverter) return NS_ERROR_FAILURE; - else - { - mTotalWritten += wroteIt; - return NS_OK; - } + + return mConverter->OnDataAvailable(request, ctxt, aIStream, sourceOffset, aLength); } @@ -248,6 +237,7 @@ nsURLFetcher::OnDataAvailable(nsIRequest *request, nsISupports * ctxt, nsIInputS nsresult nsURLFetcher::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { + /* check if the user has canceld the operation */ nsMsgAttachmentHandler *attachmentHdl = (nsMsgAttachmentHandler *)mTagData; if (attachmentHdl) { @@ -268,23 +258,34 @@ nsURLFetcher::OnStartRequest(nsIRequest *request, nsISupports *ctxt) attachmentHdl->mRequest = request; } + /* call our converter or consumer */ + if (mConverter) + return mConverter->OnStartRequest(request, ctxt); + return NS_OK; } nsresult -nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * /* ctxt */, nsresult aStatus) +nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * ctxt, nsresult aStatus) { #if defined(DEBUG_ducarroz) printf("nsURLFetcher::OnStopRequest()\n"); #endif + nsresult rv = NS_OK; + // it's possible we could get in here from the channel calling us with an OnStopRequest and from our // onStatusChange method (in the case of an error). So we should protect against this to make sure we // don't process the on stop request twice... - if (mOnStopRequestProcessed) return NS_OK; + if (mOnStopRequestProcessed) + return NS_OK; mOnStopRequestProcessed = PR_TRUE; + /* first, call our converter or consumer */ + if (mConverter) + rv = mConverter->OnStopRequest(request, ctxt, aStatus); + nsMsgAttachmentHandler *attachmentHdl = (nsMsgAttachmentHandler *)mTagData; if (attachmentHdl) attachmentHdl->mRequest = nsnull; @@ -294,70 +295,52 @@ nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * /* ctxt */, nsres // mStillRunning = PR_FALSE; - // First close the output stream... + // time to close the output stream... if (mOutStream) { - mOutStream->close(); + mOutStream->Close(); mOutStream = nsnull; - } - - // Check the content type! - char *contentType = nsnull; - char *charset = nsnull; - - nsCOMPtr aChannel = do_QueryInterface(request); - if(!aChannel) return NS_ERROR_FAILURE; - - if (NS_SUCCEEDED(aChannel->GetContentType(&contentType)) && contentType) + /* In case of multipart/x-mixed-replace, we need to truncate the file to the current part size */ + if (PL_strcasecmp(mConverterContentType, MULTIPART_MIXED_REPLACE) == 0) { - if (PL_strcasecmp(contentType, UNKNOWN_CONTENT_TYPE)) - { - mContentType = contentType; - } - } - - nsCOMPtr httpChannel = do_QueryInterface(aChannel); - if (httpChannel) - { - if (NS_SUCCEEDED(httpChannel->GetCharset(&charset)) && charset) - { - mCharset = charset; + PRInt64 fileSize; + LL_I2L(fileSize, mTotalWritten); + mLocalFile->SetFileSize(fileSize); } } // Now if there is a callback, we need to call it... if (mCallback) - mCallback (aStatus, mContentType, mCharset, mTotalWritten, nsnull, mTagData); + mCallback (aStatus, (const char *)mContentType, (const char *)mCharset, mTotalWritten, nsnull, mTagData); // Time to return... return NS_OK; } nsresult -nsURLFetcher::Initialize(nsOutputFileStream *fOut, +nsURLFetcher::Initialize(nsILocalFile *localFile, + nsIFileOutputStream *outputStream, nsAttachSaveCompletionCallback cb, void *tagData) { - if (!fOut) + if (!outputStream || !localFile) return NS_ERROR_INVALID_ARG; - if (!fOut->is_open()) - return NS_ERROR_FAILURE; - - mOutStream = fOut; + mOutStream = outputStream; + mLocalFile = localFile; mCallback = cb; //JFD: Please, no more callback, use a listener... mTagData = tagData; //JFD: TODO, WE SHOULD USE A NSCOMPTR to hold this stuff!!! return NS_OK; } nsresult -nsURLFetcher::FireURLRequest(nsIURI *aURL, nsOutputFileStream *fOut, +nsURLFetcher::FireURLRequest(nsIURI *aURL, nsILocalFile *localFile, nsIFileOutputStream *outputStream, nsAttachSaveCompletionCallback cb, void *tagData) { nsresult rv; - rv = Initialize(fOut, cb, tagData); + rv = Initialize(localFile, outputStream, cb, tagData); NS_ENSURE_SUCCESS(rv, rv); // we're about to fire a new url request so make sure the on stop request flag is cleared... @@ -378,6 +361,30 @@ nsURLFetcher::FireURLRequest(nsIURI *aURL, nsOutputFileStream *fOut, return NS_OK; } +nsresult +nsURLFetcher::InsertConverter(const char * aContentType) +{ + nsresult rv; + + nsCOMPtr convServ(do_GetService("@mozilla.org/streamConverters;1", &rv)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr toListener(mConverter); + nsCOMPtr fromListener; + nsAutoString contentType; + + contentType.AssignWithConversion(aContentType); + rv = convServ->AsyncConvertData(contentType.get(), + NS_LITERAL_STRING("*/*").get(), + toListener, + nsnull, + getter_AddRefs(fromListener)); + if (NS_SUCCEEDED(rv)) + mConverter = fromListener; + } + + return rv; +} // web progress listener implementation @@ -432,3 +439,122 @@ nsURLFetcher::OnSecurityChange(nsIWebProgress *aWebProgress, { return NS_ERROR_NOT_IMPLEMENTED; } + + +/** + * Stream consumer used for handling special content type like multipart/x-mixed-replace + */ + +NS_IMPL_ISUPPORTS2(nsURLFetcherStreamConsumer, nsIStreamListener, nsIRequestObserver) + +nsURLFetcherStreamConsumer::nsURLFetcherStreamConsumer(nsURLFetcher* urlFetcher) : + mURLFetcher(urlFetcher) +{ +#if defined(DEBUG_ducarroz) + printf("CREATE nsURLFetcherStreamConsumer: %x\n", this); +#endif + NS_INIT_ISUPPORTS(); +} + +nsURLFetcherStreamConsumer::~nsURLFetcherStreamConsumer() +{ +#if defined(DEBUG_ducarroz) + printf("DISPOSE nsURLFetcherStreamConsumer: %x\n", this); +#endif +} + +/** nsIRequestObserver methods **/ + +/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */ +NS_IMETHODIMP nsURLFetcherStreamConsumer::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) +{ + if (!mURLFetcher || !mURLFetcher->mOutStream) + return NS_ERROR_FAILURE; + + /* In case of multipart/x-mixed-replace, we need to erase the output file content */ + if (PL_strcasecmp(mURLFetcher->mConverterContentType, MULTIPART_MIXED_REPLACE) == 0) + { + nsCOMPtr seekStream = do_QueryInterface(mURLFetcher->mOutStream); + if (seekStream) + seekStream->Seek(nsISeekableStream::NS_SEEK_SET, 0); + mURLFetcher->mTotalWritten = 0; + } + + return NS_OK; +} + +/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */ +NS_IMETHODIMP nsURLFetcherStreamConsumer::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status) +{ + if (!mURLFetcher) + return NS_ERROR_FAILURE; + + // Check the content type! + char *contentType = nsnull; + char *charset = nsnull; + + nsCOMPtr aChannel = do_QueryInterface(aRequest); + if(!aChannel) return NS_ERROR_FAILURE; + + if (NS_SUCCEEDED(aChannel->GetContentType(&contentType)) && contentType) + if (PL_strcasecmp(contentType, UNKNOWN_CONTENT_TYPE) != 0) + mURLFetcher->mContentType = contentType; + + if (contentType) + nsCRT::free(contentType); + + nsCOMPtr httpChannel = do_QueryInterface(aChannel); + if (httpChannel) + if (NS_SUCCEEDED(httpChannel->GetCharset(&charset)) && charset) + mURLFetcher->mCharset = charset; + + if (charset) + nsCRT::free(charset); + + return NS_OK; +} + +/** nsIStreamListener methods **/ + +/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */ +NS_IMETHODIMP nsURLFetcherStreamConsumer::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) +{ + PRUint32 readLen = count; + PRUint32 wroteIt; + + if (!mURLFetcher) + return NS_ERROR_FAILURE; + + if (!mURLFetcher->mOutStream) + return NS_ERROR_INVALID_ARG; + + if (mURLFetcher->mBufferSize < count) + { + PR_FREEIF(mURLFetcher->mBuffer); + + if (count > 0x1000) + mURLFetcher->mBufferSize = count; + else + mURLFetcher->mBufferSize = 0x1000; + + mURLFetcher->mBuffer = (char *)PR_Malloc(mURLFetcher->mBufferSize); + if (!mURLFetcher->mBuffer) + return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */ + } + + // read the data from the input stram... + nsresult rv = inStr->Read(mURLFetcher->mBuffer, count, &readLen); + if (NS_FAILED(rv)) + return rv; + + // write to the output file... + mURLFetcher->mOutStream->Write(mURLFetcher->mBuffer, readLen, &wroteIt); + + if (wroteIt != readLen) + return NS_ERROR_FAILURE; + else + { + mURLFetcher->mTotalWritten += wroteIt; + return NS_OK; + } +} diff --git a/mailnews/compose/src/nsURLFetcher.h b/mailnews/compose/src/nsURLFetcher.h index 5d86a3d1bb31..cf1973f1135b 100644 --- a/mailnews/compose/src/nsURLFetcher.h +++ b/mailnews/compose/src/nsURLFetcher.h @@ -33,7 +33,7 @@ #include "nsIURIContentListener.h" #include "nsIWebProgressListener.h" #include "nsWeakReference.h" - +#include "nsXPIDLString.h" class nsURLFetcher : public nsIURLFetcher, public nsIStreamListener, @@ -67,16 +67,47 @@ public: // Methods for nsIWebProgressListener NS_DECL_NSIWEBPROGRESSLISTENER +protected: + nsresult InsertConverter(const char * aContentType); + private: - nsOutputFileStream *mOutStream; // the output file stream + nsCOMPtr mOutStream; // the output file stream + nsCOMPtr mLocalFile; // the output file itself + nsCOMPtr mConverter; // the stream converter, if needed + nsXPIDLCString mConverterContentType; // The content type of the converter PRBool mStillRunning; // Are we still running? PRInt32 mTotalWritten; // Size counter variable - char *mContentType; // The content type retrieved from the server - char *mCharset; // The charset retrieved from the server + char *mBuffer; // Buffer used for reading the data + PRUint32 mBufferSize; // Buffer size; + nsXPIDLCString mContentType; // The content type retrieved from the server + nsXPIDLCString mCharset; // The charset retrieved from the server void *mTagData; // Tag data for callback... nsAttachSaveCompletionCallback mCallback; // Callback to call once the file is saved... nsCOMPtr mLoadCookie; // load cookie used by the uri loader when we fetch the url PRBool mOnStopRequestProcessed; // used to prevent calling OnStopRequest multiple times + + friend class nsURLFetcherStreamConsumer; }; + +/** + * Stream consumer used for handling special content type like multipart/x-mixed-replace + */ + +class nsURLFetcherStreamConsumer : public nsIStreamListener +{ +public: + nsURLFetcherStreamConsumer(nsURLFetcher* urlFetcher); + virtual ~nsURLFetcherStreamConsumer(); + + /* additional members */ + NS_DECL_ISUPPORTS + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIREQUESTOBSERVER + +private: + nsURLFetcher* mURLFetcher; +}; + + #endif /* nsURLFetcher_h_ */