adding next rev of ftp protocol

This commit is contained in:
valeski%netscape.com 1999-08-11 22:26:32 +00:00
parent 7f09e481ea
commit 87e42a03b1
7 changed files with 1475 additions and 1021 deletions

View File

@ -26,6 +26,7 @@ XPIDL_MODULE = necko_ftp
XPIDLSRCS = \
nsIFTPChannel.idl \
nsIFTPContext.idl \
$(NULL)
EXPORTS = \

View File

@ -24,6 +24,7 @@ XPIDL_MODULE = necko_ftp
XPIDLSRCS = \
.\nsIFTPChannel.idl \
.\nsIFTPContext.idl \
$(NULL)
EXPORTS = \

View File

@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsISupports.idl"
[scriptable, uuid(4D4955D0-491B-11d3-A16F-0050041CAF44)]
interface nsIFTPContext : nsISupports
{
boolean IsCmdResponse();
attribute string ContentType;
};

View File

@ -26,7 +26,15 @@
#include "nsIEventQueueService.h"
#include "nsIProgressEventSink.h"
#include "nsIEventSinkGetter.h"
#include "nsIIOService.h"
#include "nsIBuffer.h"
#include "nsILoadGroup.h"
#include "nsIFTPContext.h"
#include "nsIMIMEService.h"
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "prprf.h" // PR_sscanf
@ -42,7 +50,7 @@ static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
nsFTPChannel::nsFTPChannel()
: mUrl(nsnull), mConnected(PR_FALSE), mListener(nsnull),
mLoadAttributes(LOAD_NORMAL), mLoadGroup(nsnull)
mLoadAttributes(LOAD_NORMAL), mLoadGroup(nsnull), mContext(nsnull)
{
nsresult rv;
@ -62,6 +70,7 @@ nsFTPChannel::~nsFTPChannel() {
NS_IF_RELEASE(mListener);
NS_IF_RELEASE(mEventQueue);
NS_IF_RELEASE(mLoadGroup);
NS_IF_RELEASE(mContext);
}
NS_IMPL_ADDREF(nsFTPChannel);
@ -95,23 +104,24 @@ nsFTPChannel::Init(const char* verb, nsIURI* uri, nsIEventSinkGetter* getter,
if (mConnected)
return NS_ERROR_FAILURE;
if (!getter) {
return NS_ERROR_FAILURE;
}
mUrl = uri;
NS_ADDREF(mUrl);
mEventQueue = queue;
NS_ADDREF(mEventQueue);
nsIProgressEventSink* eventSink;
rv = getter->GetEventSink(verb, nsCOMTypeInfo<nsIProgressEventSink>::GetIID(),
(nsISupports**)&eventSink);
if (NS_FAILED(rv)) return rv;
if (getter) {
nsIProgressEventSink* eventSink;
rv = getter->GetEventSink(verb, nsCOMTypeInfo<nsIProgressEventSink>::GetIID(),
(nsISupports**)&eventSink);
//if (NS_FAILED(rv)) return rv;
mEventSink = eventSink;
NS_ADDREF(mEventSink);
// XXX event sinks are optional in ftp
if (eventSink) {
mEventSink = eventSink;
NS_ADDREF(mEventSink);
}
}
return NS_OK;
}
@ -166,11 +176,54 @@ nsFTPChannel::GetURI(nsIURI * *aURL)
return NS_OK;
}
// This class
NS_IMETHODIMP
nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
nsIInputStream **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
// The ftp channel will act as the listener which will receive
// events from the ftp connection thread. It then uses a syncstreamlistener
// as it's mListener which receives the listener notifications and writes
// data down the output stream end of a pipe.
nsresult rv;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
if (!mEventQueue) {
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &mEventQueue);
if (NS_FAILED(rv)) return rv;
}
rv = serv->NewSyncStreamListener(_retval /* nsIInputStream **inStream */,
&mBufferOutputStream /* nsIBufferOutputStream **outStream */,
&mListener/* nsIStreamListener **listener */);
if (NS_FAILED(rv)) return rv;
// XXX not sure how we should be using these. I suppose we need to use them
// XXX in the nsFTPChannel::OnDataAvailable() method.
mSourceOffset = startPosition;
mAmount = readCount;
////////////////////////////////
//// setup the channel thread
nsIThread* workerThread = nsnull;
nsFtpConnectionThread* protocolInterpreter =
new nsFtpConnectionThread(mEventQueue, this, this, nsnull);
if (!protocolInterpreter)
return NS_ERROR_OUT_OF_MEMORY;
protocolInterpreter->Init(mUrl);
protocolInterpreter->SetUsePasv(PR_TRUE);
rv = NS_NewThread(&workerThread, protocolInterpreter);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
@ -184,7 +237,60 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *ctxt,
nsIStreamListener *listener)
{
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv;
///////////////////////////
//// setup channel state
if (ctxt) {
mContext = ctxt;
NS_ADDREF(mContext);
}
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
if (!mEventQueue) {
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &mEventQueue);
if (NS_FAILED(rv)) return rv;
}
rv = serv->NewAsyncStreamListener(listener, mEventQueue, &mListener);
if (NS_FAILED(rv)) return rv;
rv = NS_NewPipe(&mBufferInputStream, &mBufferOutputStream,
NS_FTP_SEGMENT_SIZE,
NS_FTP_BUFFER_SIZE, PR_TRUE, nsnull/*this*/); // XXX need channel to implement
// nsIBufferObserver
if (NS_FAILED(rv)) return rv;
rv = mBufferOutputStream->SetNonBlocking(PR_TRUE);
if (NS_FAILED(rv)) return rv;
mSourceOffset = startPosition;
mAmount = readCount;
////////////////////////////////
//// setup the channel thread
nsIThread* workerThread = nsnull;
nsFtpConnectionThread* protocolInterpreter =
new nsFtpConnectionThread(mEventQueue, this, this, ctxt);
NS_ADDREF(protocolInterpreter);
if (!protocolInterpreter)
return NS_ERROR_OUT_OF_MEMORY;
protocolInterpreter->Init(mUrl);
protocolInterpreter->SetUsePasv(PR_TRUE);
rv = NS_NewThread(&workerThread, protocolInterpreter);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
@ -211,12 +317,47 @@ nsFTPChannel::SetLoadAttributes(PRUint32 aLoadAttributes)
return NS_OK;
}
// FTP does not provide a file typing mechanism. We fallback to file
// extension mapping.
#define FTP_DUMMY_TYPE "text/html"
NS_IMETHODIMP
nsFTPChannel::GetContentType(char* *contentType) {
// XXX for ftp we need to do a file extension-to-type mapping lookup
// XXX in some hash table/registry of mime-types
return NS_ERROR_NOT_IMPLEMENTED;
nsFTPChannel::GetContentType(char* *aContentType) {
nsresult rv = NS_OK;
// Parameter validation...
if (!aContentType) {
return NS_ERROR_NULL_POINTER;
}
*aContentType = nsnull;
if (mContentType.Length()) {
*aContentType = mContentType.ToNewCString();
if (!*aContentType) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
return rv;
}
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = MIMEService->GetTypeFromURI(mUrl, aContentType);
if (NS_SUCCEEDED(rv)) {
mContentType = *aContentType;
return rv;
}
}
// if all else fails treat it as text/html?
if (!*aContentType)
*aContentType = nsCRT::strdup(FTP_DUMMY_TYPE);
if (!*aContentType) {
rv = NS_ERROR_OUT_OF_MEMORY;
} else {
rv = NS_OK;
}
return rv;
}
NS_IMETHODIMP
@ -241,25 +382,7 @@ nsFTPChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
NS_IMETHODIMP
nsFTPChannel::Get(void) {
nsresult rv;
nsIThread* workerThread = nsnull;
nsFtpConnectionThread* protocolInterpreter =
new nsFtpConnectionThread(mEventQueue, this, this, nsnull);
NS_ASSERTION(protocolInterpreter, "ftp protocol interpreter alloc failed");
NS_ADDREF(protocolInterpreter);
if (!protocolInterpreter)
return NS_ERROR_OUT_OF_MEMORY;
protocolInterpreter->Init(workerThread, mUrl);
protocolInterpreter->SetUsePasv(PR_TRUE);
rv = NS_NewThread(&workerThread, protocolInterpreter);
NS_ASSERTION(NS_SUCCEEDED(rv), "new thread failed");
// XXX this release should probably be in the destructor.
NS_RELEASE(protocolInterpreter);
return NS_OK;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
@ -274,7 +397,7 @@ nsFTPChannel::Put(void) {
if (!protocolInterpreter)
return NS_ERROR_OUT_OF_MEMORY;
protocolInterpreter->Init(workerThread, mUrl);
protocolInterpreter->Init(mUrl);
protocolInterpreter->SetAction(PUT);
protocolInterpreter->SetUsePasv(PR_TRUE);
@ -298,15 +421,22 @@ nsFTPChannel::SetStreamListener(nsIStreamListener *aListener) {
NS_IMETHODIMP
nsFTPChannel::OnStartRequest(nsIChannel* channel, nsISupports* context) {
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = NS_OK;
if (mListener) {
rv = mListener->OnStartRequest(channel, context);
}
return rv;
}
NS_IMETHODIMP
nsFTPChannel::OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
// Release the lock so the user get's the data stream
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = NS_OK;
if (mListener) {
rv = mListener->OnStopRequest(channel, context, aStatus, aMsg);
}
return rv;
}
////////////////////////////////////////////////////////////////////////////////
@ -317,8 +447,24 @@ nsFTPChannel::OnDataAvailable(nsIChannel* channel, nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
// Fill in the buffer w/ the new data.
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = NS_OK;
nsIFTPContext *ftpCtxt = nsnull;
rv = context->QueryInterface(nsCOMTypeInfo<nsIFTPContext>::GetIID(), (void**)&ftpCtxt);
if (NS_FAILED(rv)) return rv;
char *type = nsnull;
rv = ftpCtxt->GetContentType(&type);
if (NS_FAILED(rv)) return rv;
mContentType = type;
nsAllocator::Free(type);
if (mListener) {
rv = mListener->OnDataAvailable(channel, context, aIStream, aSourceOffset, aLength);
}
return rv;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -27,8 +27,13 @@
#include "nsIURI.h"
#include "nsString2.h"
#include "nsIEventQueue.h"
#include "nsIBufferOutputStream.h"
#include "nsIBufferInputStream.h"
#include "nsILoadGroup.h"
#include "nsCOMPtr.h"
class nsIEventSinkGetter;
class nsIProgressEventSink;
@ -97,8 +102,20 @@ protected:
PRBool mConnected;
nsIStreamListener* mListener;
nsISupports* mContext;
PRUint32 mLoadAttributes;
nsIBufferInputStream* mBufferInputStream;
nsIBufferOutputStream* mBufferOutputStream;
PRUint32 mSourceOffset;
PRInt32 mAmount;
nsILoadGroup* mLoadGroup;
nsString2 mContentType;
};
#define NS_FTP_SEGMENT_SIZE (4*1024)
#define NS_FTP_BUFFER_SIZE (8*1024)
#endif /* nsFTPChannel_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -16,17 +16,21 @@
* Reserved.
*/
#ifndef __nsftpconnectionthread__h_
#define __nsftpconnectionthread__h_
#include "nsIThread.h"
#include "nsISocketTransportService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsIOutputStream.h"
#include "nsIURI.h"
#include "prlock.h"
#include "nsAutoLock.h"
#include "nsString2.h"
#include "nsIEventQueue.h"
#include "time.h" // XXX should probably be using PRTime stuff
@ -87,15 +91,14 @@ typedef enum _FTP_STATE {
FTP_R_MDTM,
FTP_S_LIST, // send LIST or NLST (server dependent) to get a dir listing
FTP_R_LIST,
FTP_S_TYPE, // send TYPE to indicate what type of file will be transfered
FTP_R_TYPE,
///////////////////////
//// Data channel connection setup states
///////////////////////
FTP_S_PASV, // send passsive
FTP_R_PASV
// FTP_S_PORT, // send port
// FTP_R_PORT
} FTP_STATE;
// higher level ftp actions
@ -116,21 +119,56 @@ public:
// nsIRunnable method
NS_IMETHOD Run();
#if 0
// nsICancelable methods:
NS_IMETHOD Cancel(void);
NS_IMETHOD Suspend(void);
NS_IMETHOD Resume(void);
#endif
nsresult Init(nsIThread* aThread,
nsIURI* aUrl);
nsresult Init(nsIURI* aUrl);
nsresult Process();
// user level setup
nsresult SetAction(FTP_ACTION aAction);
nsresult SetUsePasv(PRBool aUsePasv);
private:
nsresult Read(void);
///////////////////////////////////
// STATE METHODS
///////////////////////////////////
nsresult S_user();
FTP_STATE R_user();
nsresult S_pass();
FTP_STATE R_pass();
nsresult S_syst();
FTP_STATE R_syst();
nsresult S_acct();
FTP_STATE R_acct();
nsresult S_macb();
FTP_STATE R_macb();
nsresult S_pwd();
FTP_STATE R_pwd();
nsresult S_mode();
FTP_STATE R_mode();
nsresult S_cwd();
FTP_STATE R_cwd();
nsresult S_size();
FTP_STATE R_size();
nsresult S_mdtm();
FTP_STATE R_mdtm();
nsresult S_list();
FTP_STATE R_list();
nsresult S_retr();
FTP_STATE R_retr();
nsresult S_pasv();
FTP_STATE R_pasv();
nsresult S_del_file();
FTP_STATE R_del_file();
nsresult S_del_dir();
FTP_STATE R_del_dir();
nsresult S_mkdir();
FTP_STATE R_mkdir();
///////////////////////////////////
// END: STATE METHODS
///////////////////////////////////
void SetSystInternals(void);
FTP_STATE FindActionState(void);
FTP_STATE FindGetState(void);
@ -145,19 +183,26 @@ private:
FTP_STATE mNextState; // the next state
FTP_ACTION mAction; // the higher level action
nsIInputStream* mCInStream; // command channel input
nsISocketTransportService *mSTS; // the socket transport service;
nsIChannel *mCPipe; // the command channel transport
nsIChannel *mDPipe; // the data channel transport
nsIOutputStream* mCOutStream; // command channel output
nsIInputStream* mCInStream; // command channel input
//nsString2 mDataAddress; // the host:port combo for the data connection
nsIInputStream* mDInStream; // data channel input
nsIOutputStream* mDOutStream; // data channel output
nsIInputStream* mDInStream; // data channel input
nsIBufferInputStream* mCBufInStream; // data channel input (async)
PRInt32 mResponseCode; // the last command response code.
nsString2 mResponseMsg; // the last command response text
nsString2 mUsername;
nsString2 mPassword;
nsString2 mFilename; // url filename (if any)
PRInt32 mLength; // length of the file
PRUint32 mLength; // length of the file
time_t mLastModified; // last modified time for file
// these members should be hung off of a specific transport connection
@ -169,17 +214,23 @@ private:
PRBool mConnected;
PRBool mUseDefaultPath; // use PWD to figure out path
PRBool mUsePasv; // use a passive data connection.
PRBool mAscii; // transfer mode (ascii or binary)
PRBool mDirectory; // this url is a directory
PRBool mBin; // transfer mode (ascii or binary)
nsIStreamListener* mListener; // the listener we want to call
// during our event firing.
nsIChannel* mChannel;
nsISupports* mContext;
PRLock *mLock;
PRThread *mThread;
PRBool mKeepRunning; // thread event loop boolean
nsString2 mContentType; // the content type of the data we're dealing w/.
};
#define NS_FTP_THREAD_SEGMENT_SIZE (4*1024)
#define NS_FTP_THREAD_BUFFER_SIZE (16*1024)
#define NS_FTP_BUFFER_READ_SIZE (4*1024)
#define NS_FTP_BUFFER_WRITE_SIZE (4*1024)
#endif //__nsftpconnectionthread__h_