fixed buffer mem allocation inconsistencies. we now loop for more data on long dir listings. we also consider any server string with 'windows' in it, to be an NT server. also added deletion of dir listing underlying buffer fir stringstream to the OnDataAvailEvent destructor; kinda ugly, but works

This commit is contained in:
valeski%netscape.com 1999-09-13 23:29:12 +00:00
Родитель 354974765f
Коммит 9e63a60731
3 изменённых файлов: 130 добавлений и 70 удалений

Просмотреть файл

@ -1218,84 +1218,137 @@ nsFtpConnectionThread::S_list() {
return mCOutStream->Write(buffer, bufLen, &bytes);
}
// listBuf is free'd by the eventHandler, don't free him.
FTP_STATE
nsFtpConnectionThread::R_list() {
nsresult rv;
char listBuf[NS_FTP_BUFFER_READ_SIZE];
PRUint32 read;
// XXX need to loop this read somehow.
rv = mDInStream->Read(listBuf, NS_FTP_BUFFER_READ_SIZE, &read);
PRBool sentStart = PR_FALSE;
PRUint32 dataLeft, bufSize, read;
char *listBuf = nsnull; // the buffer receiving the listing
rv = mDInStream->Available(&dataLeft);
if (NS_FAILED(rv)) return FTP_ERROR;
// tell the user about the data.
bufSize = PR_MIN(dataLeft, NS_FTP_BUFFER_READ_SIZE);
nsIInputStream *stringStream = nsnull;
nsISupports *stringStrmSup = nsnull;
rv = NS_NewCharInputStream(&stringStrmSup, listBuf);
if (NS_FAILED(rv)) return FTP_ERROR;
if (bufSize > 0) {
listBuf = (char*)nsAllocator::Alloc(bufSize + 1);
if (!listBuf) return FTP_ERROR;
rv = stringStrmSup->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&stringStream);
if (NS_FAILED(rv)) return FTP_ERROR;
// this is ascii data coming in. terminate this sucker.
listBuf[bufSize] = '\0';
nsFTPContext *dataCtxt = new nsFTPContext();
if (!dataCtxt) return FTP_ERROR;
dataCtxt->SetContentType("text/ftp-dirListing");
nsISupports *ctxtSup = nsnull;
rv = dataCtxt->QueryInterface(NS_GET_IID(nsISupports), (void**)&ctxtSup);
// we're now receiving a dir listing. push it through a converter.
NS_WITH_SERVICE(nsIStreamConverterService, StreamConvService, kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv)) return FTP_ERROR;
nsString fromStr("text/ftp-dir-");
SetDirMIMEType(fromStr);
// all FTP directory listings are converted to http-index
nsString toStr("application/http-index-format");
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return FTP_ERROR;
// setup a listener to push the data into. This listener sits inbetween the
// unconverted data of fromType, and the final listener in the chain (in this case
// the mListener).
nsIStreamListener *converterListener = nsnull;
rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(),
toStr.GetUnicode(),
mListener, mUrl, &converterListener);
if (NS_FAILED(rv)) return FTP_ERROR;
// tell the user that we've begun the transaction.
nsFtpOnStartRequestEvent* startEvent =
new nsFtpOnStartRequestEvent(converterListener, mChannel, mContext);
if (!startEvent) return FTP_ERROR;
rv = startEvent->Fire(mEventQueue);
if (NS_FAILED(rv)) {
delete startEvent;
rv = mDInStream->Read(listBuf, bufSize, &read);
if (NS_FAILED(rv) || read < 1) {
nsAllocator::Free(listBuf);
return FTP_ERROR;
}
} else {
return FTP_ERROR;
}
// send data off
nsFtpOnDataAvailableEvent* availEvent =
new nsFtpOnDataAvailableEvent(converterListener, mChannel, ctxtSup);
if (!availEvent) return FTP_ERROR;
do {
// tell the user about the data.
rv = availEvent->Init(stringStream, 0, read);
NS_RELEASE(stringStream);
if (NS_FAILED(rv)) {
delete availEvent;
return FTP_ERROR;
}
nsIInputStream *stringStream = nsnull;
nsISupports *stringStrmSup = nsnull;
rv = NS_NewCharInputStream(&stringStrmSup, listBuf); // char streams keep ref to buffer
if (NS_FAILED(rv)) return FTP_ERROR;
rv = stringStrmSup->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&stringStream);
if (NS_FAILED(rv)) return FTP_ERROR;
nsFTPContext *dataCtxt = new nsFTPContext();
if (!dataCtxt) return FTP_ERROR;
dataCtxt->SetContentType("text/ftp-dirListing");
nsISupports *ctxtSup = nsnull;
rv = dataCtxt->QueryInterface(NS_GET_IID(nsISupports), (void**)&ctxtSup);
// we're receiving a dir listing. push it through a converter.
nsIStreamListener *converterListener = nsnull;
if (!sentStart) {
sentStart = PR_TRUE;
NS_WITH_SERVICE(nsIStreamConverterService, StreamConvService, kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv)) return FTP_ERROR;
nsString fromStr("text/ftp-dir-");
SetDirMIMEType(fromStr);
// all FTP directory listings are converted to http-index
nsString toStr("application/http-index-format");
// setup a listener to push the data into. This listener sits inbetween the
// unconverted data of fromType, and the final listener in the chain (in this case
// the mListener).
rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(),
toStr.GetUnicode(),
mListener, mUrl, &converterListener);
if (NS_FAILED(rv)) {
nsAllocator::Free(listBuf);
return FTP_ERROR;
}
// tell the user that we've begun the transaction.
nsFtpOnStartRequestEvent* startEvent =
new nsFtpOnStartRequestEvent(converterListener, mChannel, mContext);
if (!startEvent) return FTP_ERROR;
rv = startEvent->Fire(mEventQueue);
if (NS_FAILED(rv)) {
delete startEvent;
return FTP_ERROR;
}
} // END sentStart
// send data off
nsFtpOnDataAvailableEvent* availEvent =
new nsFtpOnDataAvailableEvent(converterListener, mChannel, ctxtSup);
if (!availEvent) return FTP_ERROR;
PRUint32 streamLen;
rv = stringStream->Available(&streamLen);
if (NS_FAILED(rv)) return FTP_ERROR;
rv = availEvent->Init(stringStream, 0, streamLen, listBuf); // pass the buffer ptr in so it
// can be deleted later.
NS_RELEASE(stringStream);
if (NS_FAILED(rv)) {
delete availEvent;
return FTP_ERROR;
}
rv = availEvent->Fire(mEventQueue);
if (NS_FAILED(rv)) {
delete availEvent;
return FTP_ERROR;
}
rv = mDInStream->Available(&dataLeft);
if (NS_FAILED(rv)) return FTP_ERROR;
bufSize = PR_MIN(dataLeft, NS_FTP_BUFFER_READ_SIZE);
// don't free the old buf, that'll happen in the availEvent destructor.
if (bufSize > 0) {
char *listBuf = (char*)nsAllocator::Alloc(bufSize);
if (!listBuf) return FTP_ERROR;
// this is ascii data coming in. terminate this sucker.
listBuf[bufSize] = '\0';
// get more data
rv = mDInStream->Read(listBuf, bufSize, &read);
if (NS_FAILED(rv)) {
nsAllocator::Free(listBuf);
return FTP_ERROR;
}
} else {
// fall out
rv = NS_ERROR_FAILURE;
}
} while (NS_SUCCEEDED(rv) && read > 0); // end do: stmt
rv = availEvent->Fire(mEventQueue);
if (NS_FAILED(rv)) {
delete availEvent;
return FTP_ERROR;
}
// NOTE: that we're not firing an OnStopRequest() to the converterListener (the
// stream converter). It (at least this implementation of it) doesn't care
@ -1783,7 +1836,8 @@ nsFtpConnectionThread::SetSystInternals(void) {
mServerType = FTP_UNIX_TYPE;
mList = PR_TRUE;
}
else if (mResponseMsg.Find("Windows_NT") > -1) {
else if (mResponseMsg.Find("windows", PR_TRUE) > -1) {
// treat any server w/ "windows" in it as a dos based NT server.
mServerType = FTP_NT_TYPE;
mList = PR_TRUE;
}

Просмотреть файл

@ -118,8 +118,9 @@ nsFtpOnDataAvailableEvent::~nsFtpOnDataAvailableEvent()
nsresult
nsFtpOnDataAvailableEvent::Init(nsIInputStream* aIStream,
PRUint32 aSourceOffset, PRUint32 aLength)
PRUint32 aSourceOffset, PRUint32 aLength, char *aBuffer)
{
mUnderlyingBuffer = aBuffer;
mLength = aLength;
mSourceOffset = aSourceOffset;
mIStream = aIStream;
@ -130,8 +131,12 @@ nsFtpOnDataAvailableEvent::Init(nsIInputStream* aIStream,
NS_IMETHODIMP
nsFtpOnDataAvailableEvent::HandleEvent()
{
nsresult rv;
nsIStreamListener* receiver = (nsIStreamListener*)mListener;
return receiver->OnDataAvailable(mChannel, mContext, mIStream, mSourceOffset, mLength);
rv = receiver->OnDataAvailable(mChannel, mContext, mIStream, mSourceOffset, mLength);
if (mUnderlyingBuffer)
nsAllocator::Free(mUnderlyingBuffer);
return rv;
}
/*
NS_IMETHODIMP

Просмотреть файл

@ -65,13 +65,14 @@ public:
mIStream(nsnull), mLength(0) {}
virtual ~nsFtpOnDataAvailableEvent();
nsresult Init(nsIInputStream* aIStream, PRUint32 aSourceOffset, PRUint32 aLength);
nsresult Init(nsIInputStream* aIStream, PRUint32 aSourceOffset, PRUint32 aLength, char *aBuffer=nsnull);
NS_IMETHOD HandleEvent();
protected:
nsIInputStream* mIStream;
nsIInputStream* mIStream;
PRUint32 mSourceOffset;
PRUint32 mLength;
char * mUnderlyingBuffer;
};