diff --git a/netwerk/protocol/ftp/src/nsFTPChannel.cpp b/netwerk/protocol/ftp/src/nsFTPChannel.cpp index 7490bf1d16b7..af3843c8c5a6 100644 --- a/netwerk/protocol/ftp/src/nsFTPChannel.cpp +++ b/netwerk/protocol/ftp/src/nsFTPChannel.cpp @@ -28,6 +28,7 @@ #include "nsIMIMEService.h" #include "nsNetUtil.h" #include "nsMimeTypes.h" +#include "nsIProxyObjectManager.h" static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); @@ -35,6 +36,22 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); extern PRLogModuleInfo* gFTPLog; #endif /* PR_LOGGING */ +////////////// this needs to move to nspr +static inline PRUint32 +PRTimeToSeconds(PRTime t_usec) +{ + PRTime usec_per_sec; + PRUint32 t_sec; + LL_I2L(usec_per_sec, PR_USEC_PER_SEC); + LL_DIV(t_usec, t_usec, usec_per_sec); + LL_L2I(t_sec, t_usec); + return t_sec; +} + +#define NowInSeconds() PRTimeToSeconds(PR_Now()) +////////////// end + + // There are two transport connections established for an // ftp connection. One is used for the command channel , and // the other for the data channel. The command channel is the first @@ -44,7 +61,8 @@ extern PRLogModuleInfo* gFTPLog; // Client initiation is the most common case and is attempted first. nsFTPChannel::nsFTPChannel() - : mLoadFlags(LOAD_NORMAL), + : mIsPending(0), + mLoadFlags(LOAD_NORMAL), mSourceOffset(0), mAmount(0), mContentLength(-1), @@ -67,17 +85,18 @@ nsFTPChannel::~nsFTPChannel() if (mLock) PR_DestroyLock(mLock); } -NS_IMPL_THREADSAFE_ISUPPORTS7(nsFTPChannel, +NS_IMPL_THREADSAFE_ISUPPORTS8(nsFTPChannel, nsIChannel, nsIFTPChannel, nsIRequest, nsIInterfaceRequestor, nsIProgressEventSink, nsIStreamListener, - nsIRequestObserver); + nsIRequestObserver, + nsICacheListener); nsresult -nsFTPChannel::Init(nsIURI* uri) +nsFTPChannel::Init(nsIURI* uri, nsICacheSession* session) { nsresult rv = NS_OK; @@ -94,6 +113,8 @@ nsFTPChannel::Init(nsIURI* uri) mIOService = do_GetIOService(&rv); if (NS_FAILED(rv)) return rv; + + mCacheSession = session; return NS_OK; } @@ -135,9 +156,8 @@ nsFTPChannel::GetName(PRUnichar* *result) NS_IMETHODIMP nsFTPChannel::IsPending(PRBool *result) { - nsAutoLock lock(mLock); - NS_NOTREACHED("nsFTPChannel::IsPending"); - return NS_ERROR_NOT_IMPLEMENTED; + *result = mIsPending; + return NS_OK; } NS_IMETHODIMP @@ -166,7 +186,7 @@ nsFTPChannel::Cancel(nsresult status) { mStatus = status; if (mFTPState) - return mFTPState->Cancel(status); + (void)mFTPState->Cancel(status); return NS_OK; } @@ -230,6 +250,23 @@ nsFTPChannel::Open(nsIInputStream **result) return NS_ERROR_NOT_IMPLEMENTED; } +nsresult +nsFTPChannel::GenerateCacheKey(nsACString &cacheKey) +{ + cacheKey.SetLength(0); + + nsXPIDLCString spec; + mURL->GetSpec(getter_Copies(spec)); + + // Strip any trailing #ref from the URL before using it as the key + const char *p = PL_strchr(spec, '#'); + if (p) + cacheKey.Append(spec, p - spec); + else + cacheKey.Append(spec); + return NS_OK; +} + NS_IMETHODIMP nsFTPChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { @@ -252,20 +289,51 @@ nsFTPChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) rv = mLoadGroup->AddRequest(this, nsnull); if (NS_FAILED(rv)) return rv; } + PRBool offline; - //////////////////////////////// - //// setup the channel thread + if (mCacheSession) { + mIOService->GetOffline(&offline); + + // Set the desired cache access mode accordingly... + nsCacheAccessMode accessRequested; + if (offline) { + // Since we are offline, we can only read from the cache. + accessRequested = nsICache::ACCESS_READ; + } + else if (mLoadFlags & LOAD_BYPASS_CACHE) + accessRequested = nsICache::ACCESS_WRITE; // replace cache entry + else + accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing + + nsCAutoString cacheKey; + GenerateCacheKey(cacheKey); + + return mCacheSession->AsyncOpenCacheEntry(cacheKey, accessRequested, this); + } + + return SetupState(); +} + +nsresult +nsFTPChannel::SetupState() +{ if (!mFTPState) { NS_NEWXPCOM(mFTPState, nsFtpState); if (!mFTPState) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(mFTPState); } - rv = mFTPState->Init(this, mPrompter, mAuthPrompter, mFTPEventSink); + nsresult rv = mFTPState->Init(this, + mPrompter, + mAuthPrompter, + mFTPEventSink, + mCacheEntry); if (NS_FAILED(rv)) return rv; rv = mFTPState->Connect(); - - return rv; + if (NS_FAILED(rv)) return rv; + + mIsPending = PR_TRUE; + return NS_OK; } NS_IMETHODIMP @@ -381,21 +449,59 @@ nsFTPChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallb { mCallbacks = aNotificationCallbacks; - // FIX these should be proxies! if (mCallbacks) { + + // nsIProgressEventSink + nsCOMPtr sink; (void)mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink), - getter_AddRefs(mEventSink)); + getter_AddRefs(sink)); - (void)mCallbacks->GetInterface(NS_GET_IID(nsIPrompt), - getter_AddRefs(mPrompter)); - NS_ASSERTION ( mPrompter, "Channel doesn't have a prompt!!!" ); + if (sink) + NS_GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsIProgressEventSink), + sink, + PROXY_ASYNC | PROXY_ALWAYS, + getter_AddRefs(mEventSink)); - (void)mCallbacks->GetInterface(NS_GET_IID(nsIFTPEventSink), - getter_AddRefs(mFTPEventSink)); + // nsIFTPEventSink + nsCOMPtr ftpSink; + (void)mCallbacks->GetInterface(NS_GET_IID(nsIFTPEventSink), + getter_AddRefs(ftpSink)); + + if (ftpSink) + NS_GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsIFTPEventSink), + sink, + PROXY_ASYNC | PROXY_ALWAYS, + getter_AddRefs(mFTPEventSink)); + + // nsIPrompt + nsCOMPtr prompt; + (void)mCallbacks->GetInterface(NS_GET_IID(nsIPrompt), + getter_AddRefs(prompt)); + + NS_ASSERTION ( prompt, "Channel doesn't have a prompt!!!" ); + + if (prompt) + NS_GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsIPrompt), + prompt, + PROXY_SYNC, + getter_AddRefs(mPrompter)); + + // nsIAuthPrompt + nsCOMPtr aPrompt; (void)mCallbacks->GetInterface(NS_GET_IID(nsIAuthPrompt), - getter_AddRefs(mAuthPrompter)); - NS_ASSERTION ( mAuthPrompter, "Channel doesn't have an auth prompt!!!" ); + getter_AddRefs(aPrompt)); + + if (aPrompt) + NS_GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsIAuthPrompt), + aPrompt, + PROXY_SYNC, + getter_AddRefs(mAuthPrompter)); + } return NS_OK; } @@ -467,18 +573,29 @@ nsFTPChannel::OnStopRequest(nsIRequest *request, nsISupports* aContext, mStatus = aStatus; if (mObserver) { - rv = mObserver->OnStopRequest(this, mUserContext, aStatus); - if (NS_FAILED(rv)) return rv; + (void) mObserver->OnStopRequest(this, mUserContext, aStatus); } if (mListener) { - rv = mListener->OnStopRequest(this, mUserContext, aStatus); - if (NS_FAILED(rv)) return rv; + (void) mListener->OnStopRequest(this, mUserContext, aStatus); } if (mLoadGroup) { - rv = mLoadGroup->RemoveRequest(this, nsnull, aStatus); - if (NS_FAILED(rv)) return rv; + (void) mLoadGroup->RemoveRequest(this, nsnull, aStatus); } + + if (mCacheEntry) { + if (NS_SUCCEEDED(aStatus)) { + (void) mCacheEntry->SetExpirationTime( NowInSeconds() + 900 ); // valid for 15 minutes. + (void) mCacheEntry->MarkValid(); + } + else { + (void) mCacheEntry->Doom(); + } + mCacheEntry->Close(); + mCacheEntry = 0; + } + + mIsPending = PR_FALSE; return rv; } @@ -511,3 +628,26 @@ nsFTPChannel::OnDataAvailable(nsIRequest *request, nsISupports* aContext, PRUint32 aLength) { return mListener->OnDataAvailable(this, mUserContext, aInputStream, aSourceOffset, aLength); } + +//----------------------------------------------------------------------------- +// nsFTPChannel::nsICacheListener +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsFTPChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, + nsCacheAccessMode access, + nsresult status) +{ + nsresult rv; + + if (NS_SUCCEEDED(status)) { + mCacheEntry = entry; + } + + rv = SetupState(); + + if (NS_FAILED(rv)) { + Cancel(rv); + } + return NS_OK; +} diff --git a/netwerk/protocol/ftp/src/nsFTPChannel.h b/netwerk/protocol/ftp/src/nsFTPChannel.h index 323c04b06a16..ae197ecea466 100644 --- a/netwerk/protocol/ftp/src/nsFTPChannel.h +++ b/netwerk/protocol/ftp/src/nsFTPChannel.h @@ -43,6 +43,11 @@ #include "nsIAuthPrompt.h" #include "nsIFTPChannel.h" +#include "nsICacheService.h" +#include "nsICacheEntryDescriptor.h" +#include "nsICacheListener.h" +#include "nsICacheSession.h" + #define FTP_COMMAND_CHANNEL_SEG_SIZE 64 #define FTP_COMMAND_CHANNEL_MAX_SIZE 512 @@ -54,7 +59,9 @@ class nsFTPChannel : public nsIFTPChannel, public nsIInterfaceRequestor, public nsIProgressEventSink, - public nsIStreamListener { + public nsIStreamListener, + public nsICacheListener +{ public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUEST @@ -64,6 +71,7 @@ public: NS_DECL_NSIPROGRESSEVENTSINK NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSICACHELISTENER // nsFTPChannel methods: nsFTPChannel(); @@ -74,7 +82,10 @@ public: Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult); // initializes the channel. - nsresult Init(nsIURI* uri); + nsresult Init(nsIURI* uri, nsICacheSession* session); + + nsresult SetupState(); + nsresult GenerateCacheKey(nsACString &cacheKey); protected: @@ -88,7 +99,7 @@ protected: nsCOMPtr mAuthPrompter; nsCOMPtr mCallbacks; - PRBool mConnected; + PRBool mIsPending; PRUint32 mLoadFlags; PRUint32 mSourceOffset; @@ -110,6 +121,10 @@ protected: PRPackedBool mCanceled; nsCOMPtr mIOService; + + nsCOMPtr mCacheSession; + nsCOMPtr mCacheEntry; + }; #endif /* nsFTPChannel_h___ */ diff --git a/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp b/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp index 418ab7f35029..e1b8ee6aa271 100644 --- a/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp +++ b/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp @@ -47,17 +47,21 @@ #include "nsMimeTypes.h" #include "nsIStringBundle.h" +#include "nsICacheEntryDescriptor.h" +#include "nsICacheListener.h" + static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); static NS_DEFINE_CID(kWalletServiceCID, NS_WALLETSERVICE_CID); static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); +static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID); + #if defined(PR_LOGGING) extern PRLogModuleInfo* gFTPLog; #endif /* PR_LOGGING */ - class DataRequestForwarder : public nsIFTPChannel, public nsIStreamListener, public nsIInterfaceRequestor, @@ -69,7 +73,8 @@ public: nsresult Init(nsIRequest *request); nsresult SetStreamListener(nsIStreamListener *listener); - + nsresult SetCacheEntry(nsICacheEntryDescriptor *entry); + NS_DECL_ISUPPORTS NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER @@ -84,10 +89,11 @@ public: protected: - nsCOMPtr mRequest; - nsCOMPtr mFTPChannel; - nsCOMPtr mListener; - nsCOMPtr mEventSink; + nsCOMPtr mRequest; + nsCOMPtr mFTPChannel; + nsCOMPtr mListener; + nsCOMPtr mEventSink; + nsCOMPtr mCacheEntry; nsresult DelayedOnStartRequest(nsIRequest *request, nsISupports *ctxt); PRBool mDelayedOnStartFired; @@ -155,6 +161,35 @@ DataRequestForwarder::Init(nsIRequest *request) return NS_OK; } + +nsresult +DataRequestForwarder::SetCacheEntry(nsICacheEntryDescriptor *cacheEntry) +{ + // if there is a cache entry descriptor, send data to it. + if (!cacheEntry) + return NS_ERROR_FAILURE; + + mCacheEntry = cacheEntry; + nsCOMPtr cacheTransport; + nsresult rv = cacheEntry->GetTransport(getter_AddRefs(cacheTransport)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr out; + rv = cacheTransport->OpenOutputStream(0, PRUint32(-1), 0, getter_AddRefs(out)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr tee = + do_CreateInstance(kStreamListenerTeeCID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = tee->Init(mListener, out); + if (NS_FAILED(rv)) return rv; + + mListener = do_QueryInterface(tee, &rv); + return NS_OK; +} + + nsresult DataRequestForwarder::SetStreamListener(nsIStreamListener *listener) { @@ -195,7 +230,6 @@ DataRequestForwarder::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsre if (sTrans) sTrans->SetReuseConnection(PR_FALSE); } - if (mListener) return mListener->OnStopRequest(this, ctxt, statusCode); @@ -828,6 +862,10 @@ return rv; /////////////////////////////////// nsresult nsFtpState::S_user() { + // some servers on connect send us a 421. (84525) + if (mResponseCode == 421) + return NS_ERROR_FAILURE; + nsresult rv; nsCAutoString usernameStr("USER "); @@ -1013,7 +1051,9 @@ nsFtpState::S_syst() { FTP_STATE nsFtpState::R_syst() { if (mResponseCode/100 == 2) { - if (mResponseMsg.Find("UNIX") > -1) { + if (( mResponseMsg.Find("UNIX") > -1) || + ( mResponseMsg.Find("BSD") > -1) ) // non standard response (91019) + { mServerType = FTP_UNIX_TYPE; } else if ( ( mResponseMsg.Find("WIN32", PR_TRUE) > -1) || @@ -1111,7 +1151,7 @@ nsFtpState::R_size() { } if (mResponseCode == 550) // File unavailable (e.g., file not found, no access). - return FTP_S_RETR; + return FTP_S_RETR; // Even if the file reports zero size, lets try retr (91292) // if we tried downloading this, lets try restarting it... if (mDRequestForwarder && mDRequestForwarder->GetBytesTransfered() > 0) @@ -1120,28 +1160,42 @@ nsFtpState::R_size() { return FTP_S_RETR; } +nsresult +nsFtpState::SetContentType() +{ + if (mGenerateRawContent) { + nsAutoString fromStr(NS_LITERAL_STRING("text/ftp-dir-")); + SetDirMIMEType(fromStr); + + nsCAutoString contentType;contentType.AssignWithConversion(fromStr); + return mChannel->SetContentType(contentType); + } + + if (mGenerateHTMLContent) + return mChannel->SetContentType("text/html"); + + return mChannel->SetContentType("application/http-index-format"); +} + nsresult nsFtpState::S_list() { nsresult rv; if (!mDRequestForwarder) return NS_ERROR_FAILURE; - - if (mGenerateRawContent) { - nsAutoString fromStr(NS_LITERAL_STRING("text/ftp-dir-")); - SetDirMIMEType(fromStr); - nsCAutoString contentType;contentType.AssignWithConversion(fromStr); - rv = mChannel->SetContentType(contentType); - } - else if (mGenerateHTMLContent) - rv = mChannel->SetContentType("text/html"); - else - rv = mChannel->SetContentType("application/http-index-format"); + rv = SetContentType(); if (NS_FAILED(rv)) return FTP_ERROR; + // save off the server type if we are caching. + if(mCacheEntry) { + nsCAutoString serverType; + serverType.AppendInt(mServerType); + (void) mCacheEntry->SetMetaDataElement("servertype", serverType); + } + nsCOMPtr converter; rv = BuildStreamConverter(getter_AddRefs(converter)); @@ -1157,7 +1211,8 @@ nsFtpState::S_list() { // to the channel. Lets hijack and send the notifications // to the stream converter. mDRequestForwarder->SetStreamListener(converter); - + mDRequestForwarder->SetCacheEntry(mCacheEntry); + nsCAutoString listString("LIST" CRLF); return SendFTPCommand(listString); @@ -1579,7 +1634,8 @@ nsresult nsFtpState::Init(nsIFTPChannel* aChannel, nsIPrompt* aPrompter, nsIAuthPrompt* aAuthPrompter, - nsIFTPEventSink* sink) + nsIFTPEventSink* sink, + nsICacheEntryDescriptor* cacheEntry) { nsresult rv = NS_OK; @@ -1587,7 +1643,8 @@ nsFtpState::Init(nsIFTPChannel* aChannel, mPrompter = aPrompter; mFTPEventSink = sink; mAuthPrompter = aAuthPrompter; - + mCacheEntry = cacheEntry; + // parameter validation NS_ASSERTION(aChannel, "FTP: needs a channel"); @@ -1595,7 +1652,47 @@ nsFtpState::Init(nsIFTPChannel* aChannel, rv = aChannel->GetURI(getter_AddRefs(mURL)); if (NS_FAILED(rv)) return rv; + + if (mCacheEntry) { + nsCacheAccessMode access; + mCacheEntry->GetAccessGranted(&access); + if (access & nsICache::ACCESS_READ) { + + // make sure the channel knows wassup + SetContentType(); + + NS_ASSERTION(!mDRequestForwarder, "there should not be a data forwarder"); + mDRequestForwarder = new DataRequestForwarder; + if (!mDRequestForwarder) return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(mDRequestForwarder); + + rv = mDRequestForwarder->Init(mChannel); + + nsXPIDLCString serverType; + (void) mCacheEntry->GetMetaDataElement("servertype", getter_Copies(serverType)); + nsCAutoString serverNum(serverType.get()); + PRInt32 err; + mServerType = serverNum.ToInteger(&err); + + nsCOMPtr converter; + rv = BuildStreamConverter(getter_AddRefs(converter)); + if (NS_FAILED(rv)) return rv; + + mDRequestForwarder->SetStreamListener(converter); + mDRequestForwarder->SetCacheEntry(mCacheEntry); + // Get a transport to the cached data... + nsCOMPtr transport; + rv = mCacheEntry->GetTransport(getter_AddRefs(transport)); + if (NS_FAILED(rv)) return rv; + + // Pump the cache data downstream + return transport->AsyncRead(mDRequestForwarder, + nsnull, + 0, PRUint32(-1), 0, + getter_AddRefs(mDPipeRequest)); + } + } char *path = nsnull; nsCOMPtr aURL(do_QueryInterface(mURL)); @@ -1644,6 +1741,9 @@ nsFtpState::Init(nsIFTPChannel* aChannel, nsresult nsFtpState::Connect() { + if (mDRequestForwarder) + return NS_OK; // we are already connected. + nsresult rv; mState = FTP_COMMAND_CONNECT; @@ -1729,11 +1829,7 @@ nsFtpState::StopProcessing() { #ifdef DEBUG_dougt printf("FTP Stopped: [response code %d] [response msg follows:]\n%s\n", mResponseCode, mResponseMsg.get()); #endif - - // Lets mask the FTP error code so that a client does not have to parse it - nsresult broadcastErrorCode = NS_BINDING_ABORTED; - // did the protocol fail? if ( NS_FAILED(mInternalError) && mResponseMsg.Length()) { // check to see if the control status is bad. @@ -1744,29 +1840,27 @@ nsFtpState::StopProcessing() { NS_ASSERTION(mPrompter, "no prompter!"); if (mPrompter) (void) mPrompter->Alert(nsnull, text.get()); -#if DEBUG - else - printf("NO ALERT! FTP error: %s", text.get()); -#endif } - - if ( NS_FAILED(mControlStatus) ) { - broadcastErrorCode = mControlStatus; + + nsresult broadcastErrorCode = NS_OK; + if ( NS_FAILED(mControlStatus) || NS_FAILED(mInternalError)) { + // Lets mask the FTP error code so that a client does not have to parse it + broadcastErrorCode = NS_BINDING_ABORTED; } if (mFireCallbacks && mChannel) { - nsCOMPtr channelListener = do_QueryInterface(mChannel); nsCOMPtr channelRequest = do_QueryInterface(mChannel); - + NS_ASSERTION(channelListener && channelRequest, "ftp channel better have these interfaces"); + nsCOMPtr asyncListener; rv = NS_NewAsyncStreamListener(getter_AddRefs(asyncListener), channelListener, NS_UI_THREAD_EVENTQ); - if(NS_FAILED(rv)) return rv; - - //(void) asyncListener->OnStartRequest(channelRequest, nsnull); - (void) asyncListener->OnStopRequest(channelRequest, nsnull, broadcastErrorCode); + if(asyncListener) { + (void) asyncListener->OnStartRequest(channelRequest, nsnull); + (void) asyncListener->OnStopRequest(channelRequest, nsnull, broadcastErrorCode); + } } - + // Clean up the event loop mKeepRunning = PR_FALSE; @@ -1774,9 +1868,7 @@ nsFtpState::StopProcessing() { nsCOMPtr sink(do_QueryInterface(mChannel)); if (sink) - // parameter can be null cause the channel fills them in. - sink->OnStatus(nsnull, nsnull, - NS_NET_STATUS_END_FTP_TRANSACTION, nsnull); + sink->OnStatus(nsnull, nsnull, NS_NET_STATUS_END_FTP_TRANSACTION, nsnull); // Release the Observers mWriteStream = 0; @@ -1887,18 +1979,15 @@ nsresult nsFtpState::SendFTPCommand(nsCString& command) { NS_ASSERTION(mControlConnection, "null control connection"); - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) Writing \"%s\"\n", this, command.get())); - - if (mFTPEventSink) { - if (command.CompareWithConversion("PASS ", PR_FALSE, 5) == 0) - { - mFTPEventSink->OnFTPControlLog(PR_FALSE, "PASS "); - } - else - { - mFTPEventSink->OnFTPControlLog(PR_FALSE, command.get()); - } - } + + // we don't want to log the password: + nsCAutoString logcmd(command); + if (command.CompareWithConversion("PASS ", PR_FALSE, 5) == 0) + logcmd = "PASS xxxxx"; + + PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x)(dwait=%d) Writing \"%s\"\n", this, mWaitingForDConn, logcmd.get())); + if (mFTPEventSink) + mFTPEventSink->OnFTPControlLog(PR_FALSE, logcmd.get()); if (mControlConnection) { return mControlConnection->Write(command, mWaitingForDConn); diff --git a/netwerk/protocol/ftp/src/nsFtpConnectionThread.h b/netwerk/protocol/ftp/src/nsFtpConnectionThread.h index ca636019463c..572016afb8c9 100644 --- a/netwerk/protocol/ftp/src/nsFtpConnectionThread.h +++ b/netwerk/protocol/ftp/src/nsFtpConnectionThread.h @@ -46,11 +46,7 @@ #include "nsFtpControlConnection.h" -#ifdef DOUGT_NEW_CACHE -#include "nsICacheService.h" -#include "nsICacheSession.h" #include "nsICacheEntryDescriptor.h" -#endif // ftp server types #define FTP_GENERIC_TYPE 0 @@ -98,7 +94,11 @@ public: nsFtpState(); virtual ~nsFtpState(); - nsresult Init(nsIFTPChannel *aChannel, nsIPrompt *aPrompter, nsIAuthPrompt *aAuthPrompter, nsIFTPEventSink *sink); + nsresult Init(nsIFTPChannel *aChannel, + nsIPrompt *aPrompter, + nsIAuthPrompt *aAuthPrompter, + nsIFTPEventSink *sink, + nsICacheEntryDescriptor* cacheEntry); // use this to provide a stream to be written to the server. nsresult SetWriteStream(nsIInputStream* aInStream, PRUint32 aWriteCount); @@ -143,6 +143,7 @@ private: nsresult EstablishControlConnection(); nsresult SendFTPCommand(nsCString& command); nsresult BuildStreamConverter(nsIStreamListener** convertStreamListener); + nsresult SetContentType(); /////////////////////////////////// // Private members @@ -207,12 +208,8 @@ private: PRPackedBool mControlReadContinue; PRPackedBool mControlReadBrokenLine; nsCAutoString mControlReadCarryOverBuf; -#ifdef DOUGT_NEW_CACHE - nsCOMPtr mCacheSession; + nsCOMPtr mCacheEntry; - PRPackedBool mReadingFromCache; -#endif - }; diff --git a/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp b/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp index bab4273bed66..c875a1ab1e35 100644 --- a/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp +++ b/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp @@ -42,6 +42,7 @@ #include "nsIInterfaceRequestor.h" #include "nsIProgressEventSink.h" #include "prlog.h" +#include "nsIPref.h" #include "nsNetUtil.h" // For proxification of FTP URLs @@ -68,6 +69,8 @@ static NS_DEFINE_IID(kIOServiceCID, NS_IOSERVICE_CID); static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); static NS_DEFINE_CID(kHttpHandlerCID, NS_HTTPPROTOCOLHANDLER_CID); static NS_DEFINE_CID(kErrorServiceCID, NS_ERRORSERVICE_CID); +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); +static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); nsSupportsHashtable* nsFtpProtocolHandler::mRootConnectionList = nsnull; //////////////////////////////////////////////////////////////////////////////// @@ -158,7 +161,34 @@ nsFtpProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result) rv = nsFTPChannel::Create(nsnull, NS_GET_IID(nsIChannel), (void**)&channel); if (NS_FAILED(rv)) return rv; - rv = channel->Init(url); + static PRBool checkedPref = PR_FALSE; + static PRBool useCache = PR_TRUE; + + if (!checkedPref) { + // XXX should register a prefs changed callback for this + nsCOMPtr prefs = do_GetService(kPrefServiceCID, &rv); + if (NS_FAILED(rv)) return rv; + + prefs->GetBoolPref("browser.cache.enable", &useCache); + + checkedPref = PR_TRUE; + } + + if (useCache && !mCacheSession) { + nsCOMPtr serv = do_GetService(kCacheServiceCID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = serv->CreateSession("FTP", + nsICache::STORE_ANYWHERE, + nsICache::STREAM_BASED, + getter_AddRefs(mCacheSession)); + if (NS_FAILED(rv)) return rv; + + rv = mCacheSession->SetDoomEntriesIfExpired(PR_TRUE); + if (NS_FAILED(rv)) return rv; + } + + rv = channel->Init(url, mCacheSession); if (NS_FAILED(rv)) { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFtpProtocolHandler::NewChannel() FAILED\n")); return rv; diff --git a/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h b/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h index 4b31f1df4118..5217a2fadbaf 100644 --- a/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h +++ b/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h @@ -30,6 +30,7 @@ #include "nsIThreadPool.h" #include "nsIObserverService.h" #include "nsAutoLock.h" +#include "nsICacheSession.h" // {25029490-F132-11d2-9588-00805F369F95} #define NS_FTPPROTOCOLHANDLER_CID \ @@ -49,11 +50,13 @@ public: // FTP Connection list access static nsresult InsertConnection(nsIURI *aKey, nsISupports *aConn); static nsresult RemoveConnection(nsIURI *aKey, nsISupports **_retval); - + + static nsresult BuildStreamConverter(nsIStreamListener* in, nsIStreamListener** out); protected: static nsSupportsHashtable* mRootConnectionList; nsCOMPtr mIOSvc; + nsCOMPtr mCacheSession; }; #endif /* nsFtpProtocolHandler_h___ */