зеркало из https://github.com/mozilla/gecko-dev.git
Fixes:
91019 "BSD Type: L8" alert msg when clicking download link 59039 FTP should proxy back nsIPrompt like HTTP 84525 Not handling 421 error on connect 86369 ftp hangs in CWD 84854 ftp pages are not cached so going backforth is slow 77032 Logging should not log users password! 88482 nsFTPChannel::IsPending() needs to be implemented Biggest change adds ftp cacheing. r=bbaetz@netscape.com, sr=darin@netscape.com
This commit is contained in:
Родитель
336ee9504c
Коммит
0714ae9359
|
@ -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<nsIProgressEventSink> 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<nsIFTPEventSink> 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<nsIPrompt> 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<nsIAuthPrompt> 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;
|
||||
}
|
||||
|
|
|
@ -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<nsIAuthPrompt> mAuthPrompter;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
|
||||
PRBool mConnected;
|
||||
PRBool mIsPending;
|
||||
PRUint32 mLoadFlags;
|
||||
|
||||
PRUint32 mSourceOffset;
|
||||
|
@ -110,6 +121,10 @@ protected:
|
|||
PRPackedBool mCanceled;
|
||||
|
||||
nsCOMPtr<nsIIOService> mIOService;
|
||||
|
||||
nsCOMPtr<nsICacheSession> mCacheSession;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
||||
|
||||
};
|
||||
|
||||
#endif /* nsFTPChannel_h___ */
|
||||
|
|
|
@ -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<nsIRequest> mRequest;
|
||||
nsCOMPtr<nsIFTPChannel> mFTPChannel;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsIProgressEventSink> mEventSink;
|
||||
nsCOMPtr<nsIRequest> mRequest;
|
||||
nsCOMPtr<nsIFTPChannel> mFTPChannel;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsIProgressEventSink> mEventSink;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> 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<nsITransport> cacheTransport;
|
||||
nsresult rv = cacheEntry->GetTransport(getter_AddRefs(cacheTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIOutputStream> out;
|
||||
rv = cacheTransport->OpenOutputStream(0, PRUint32(-1), 0, getter_AddRefs(out));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIStreamListenerTee> 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<nsIStreamListener> 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<nsIStreamListener> 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<nsITransport> 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<nsIURL> 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<nsIStreamListener> channelListener = do_QueryInterface(mChannel);
|
||||
nsCOMPtr<nsIRequest> channelRequest = do_QueryInterface(mChannel);
|
||||
|
||||
NS_ASSERTION(channelListener && channelRequest, "ftp channel better have these interfaces");
|
||||
|
||||
nsCOMPtr<nsIStreamListener> 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<nsIProgressEventSink> 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);
|
||||
|
|
|
@ -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<nsICacheSession> mCacheSession;
|
||||
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
||||
PRPackedBool mReadingFromCache;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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<nsIPref> prefs = do_GetService(kPrefServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
prefs->GetBoolPref("browser.cache.enable", &useCache);
|
||||
|
||||
checkedPref = PR_TRUE;
|
||||
}
|
||||
|
||||
if (useCache && !mCacheSession) {
|
||||
nsCOMPtr<nsICacheService> 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;
|
||||
|
|
|
@ -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<nsIIOService> mIOSvc;
|
||||
nsCOMPtr<nsICacheSession> mCacheSession;
|
||||
};
|
||||
|
||||
#endif /* nsFtpProtocolHandler_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче