Added error handling.

This commit is contained in:
valeski%netscape.com 1999-04-27 19:55:09 +00:00
parent fd21497373
commit 5d149c884c
2 changed files with 390 additions and 96 deletions

View File

@ -75,6 +75,7 @@ nsFtpConnectionThread::~nsFtpConnectionThread() {
NS_IMETHODIMP NS_IMETHODIMP
nsFtpConnectionThread::Run() { nsFtpConnectionThread::Run() {
nsresult rv; nsresult rv;
PRBool processing = PR_TRUE;
nsITransport* lCPipe = nsnull; nsITransport* lCPipe = nsnull;
nsITransport* lDPipe = nsnull; nsITransport* lDPipe = nsnull;
@ -115,11 +116,15 @@ nsFtpConnectionThread::Run() {
return rv; return rv;
} }
while (1) { PRUint32 bytes = 0;
PRUint32 prevBytes = 0;
while (processing) {
nsresult rv; nsresult rv;
char *buffer = nsnull; // the buffer to be sent to the server char *buffer = nsnull; // the buffer to be sent to the server
// XXX the buffer symantics need to be established
// XXX and proper newing and deleting needs to occur.
PRUint32 bufLen = 0; PRUint32 bufLen = 0;
PRUint32 bytes = 0;
// each hunk of data that comes in is evaluated, appropriate action // each hunk of data that comes in is evaluated, appropriate action
// is taken and the state is incremented. // is taken and the state is incremented.
@ -128,6 +133,10 @@ nsFtpConnectionThread::Run() {
// XXX and replaced with static char or #defines. // XXX and replaced with static char or #defines.
switch(mState) { switch(mState) {
//////////////////////////////
//// INTERNAL STATES
//////////////////////////////
// Reading state. used after a write in order to retrieve // Reading state. used after a write in order to retrieve
// the response from the server. // the response from the server.
case FTP_READ_BUF: case FTP_READ_BUF:
@ -135,12 +144,56 @@ nsFtpConnectionThread::Run() {
if (mState == mNextState) if (mState == mNextState)
NS_ASSERTION(0, "ftp read state mixup"); NS_ASSERTION(0, "ftp read state mixup");
rv = Read(); rv = Read(); // parse out the response code and load the repsonse buffer
if (NS_FAILED(rv))
mState = FTP_ERROR;
else
mState = mNextState; mState = mNextState;
break; break;
} }
// END: FTP_READ_BUF // END: FTP_READ_BUF
case FTP_ERROR:
{
// We have error'd out. Stop binding and pass the error back to the user.
nsIString* errorMsg = nsnull;
nsFtpOnStopBindingEvent* event =
new nsFtpOnStopBindingEvent(mListener, nsnull);
if (!event)
return NS_ERROR_OUT_OF_MEMORY;
rv = MapResultCodeToString(rv, &errorMsg);
if (NS_FAILED(rv)) {
delete event;
return rv;
}
rv = event->Init(rv, errorMsg);
if (NS_FAILED(rv)) {
delete event;
return rv;
}
rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) {
delete event;
return rv;
}
// after notifying the user of the error, stop processing.
processing = PR_FALSE;
break;
}
// END: FTP_ERROR
case FTP_COMPLETE:
{
break;
}
// END: FTP_COMPLETE
////////////////////////////// //////////////////////////////
//// CONNECTION SETUP STATES //// CONNECTION SETUP STATES
////////////////////////////// //////////////////////////////
@ -152,14 +205,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
if (bytes < bufLen) {
// didn't write everything, try again
// XXX remember how much data was written and send the amount left
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_USER; mNextState = FTP_R_USER;
break; break;
@ -190,12 +245,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// PR_smprintf(buffer, "PASS %.256s\r\n", mPassword); // PR_smprintf(buffer, "PASS %.256s\r\n", mPassword);
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
if (bytes < bufLen) {
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_PASS; mNextState = FTP_R_PASS;
break; break;
@ -223,13 +282,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
if (bytes < bufLen) {
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_SYST; mNextState = FTP_R_SYST;
break; break;
@ -266,13 +328,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
if (bytes < bufLen) {
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_ACCT; mNextState = FTP_R_ACCT;
break; break;
@ -285,8 +350,9 @@ nsFtpConnectionThread::Run() {
mState = FTP_S_SYST; mState = FTP_S_SYST;
} else { } else {
// failure. couldn't login // failure. couldn't login
// XXX use a more descriptive error code. rv = NS_ERROR_FTP_LOGIN;
return NS_ERROR_NOT_IMPLEMENTED; mState = FTP_ERROR;
break;
} }
break; break;
} }
@ -298,12 +364,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_MACB; mNextState = FTP_R_MACB;
break; break;
@ -332,12 +402,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_PWD; mNextState = FTP_R_PWD;
break; break;
@ -406,7 +480,10 @@ nsFtpConnectionThread::Run() {
const char *initialPath = nsnull; const char *initialPath = nsnull;
rv = mUrl->GetPath(&initialPath); rv = mUrl->GetPath(&initialPath);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
if (initialPath && *initialPath) { if (initialPath && *initialPath) {
if (newPath.Last() == '/') if (newPath.Last() == '/')
@ -442,12 +519,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_MODE; mNextState = FTP_R_MODE;
break; break;
@ -458,6 +539,7 @@ nsFtpConnectionThread::Run() {
{ {
if (mResponseCode != 2) { if (mResponseCode != 2) {
// indicate error. // indicate error.
rv = NS_ERROR_FTP_MODE;
mState = FTP_ERROR; mState = FTP_ERROR;
break; break;
} }
@ -474,7 +556,10 @@ nsFtpConnectionThread::Run() {
{ {
const char * path = nsnull; const char * path = nsnull;
rv = mUrl->GetPath(&path); rv = mUrl->GetPath(&path);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
if (mServerType == FTP_VMS_TYPE) { if (mServerType == FTP_VMS_TYPE) {
char *slash = nsnull; char *slash = nsnull;
@ -497,12 +582,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_CWD; mNextState = FTP_R_CWD;
break; break;
@ -532,6 +621,7 @@ nsFtpConnectionThread::Run() {
// we're not VMS, and we've already failed a RETR. // we're not VMS, and we've already failed a RETR.
mState = FTP_S_LIST; mState = FTP_S_LIST;
} else { } else {
rv = NS_ERROR_FTP_CWD;
mState = FTP_ERROR; mState = FTP_ERROR;
} }
break; break;
@ -542,7 +632,10 @@ nsFtpConnectionThread::Run() {
{ {
const char *path = nsnull; const char *path = nsnull;
rv = mUrl->GetPath(&path); rv = mUrl->GetPath(&path);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
if (mServerType == FTP_VMS_TYPE) { if (mServerType == FTP_VMS_TYPE) {
mState = FindGetState(); mState = FindGetState();
@ -553,12 +646,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_SIZE; mNextState = FTP_R_SIZE;
break; break;
@ -580,7 +677,10 @@ nsFtpConnectionThread::Run() {
{ {
const char *path = nsnull; const char *path = nsnull;
rv = mUrl->GetPath(&path); rv = mUrl->GetPath(&path);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
if (mServerType == FTP_VMS_TYPE) { if (mServerType == FTP_VMS_TYPE) {
mState = FindGetState(); mState = FindGetState();
@ -591,12 +691,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_MDTM; mNextState = FTP_R_MDTM;
break; break;
@ -623,7 +727,11 @@ nsFtpConnectionThread::Run() {
time_t tt; time_t tt;
char *timeStr = nsnull; char *timeStr = nsnull;
timeStr = mResponseMsg.ToNewCString(); timeStr = mResponseMsg.ToNewCString();
if (!timeStr) return NS_ERROR_OUT_OF_MEMORY; if (!timeStr) {
rv = NS_ERROR_OUT_OF_MEMORY;
mState = FTP_ERROR;
break;
}
ts.tm_year = ts.tm_year =
(timeStr[0] - '0') * 1000 + (timeStr[0] - '0') * 1000 +
@ -661,12 +769,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_LIST; mNextState = FTP_R_LIST;
break; break;
@ -684,7 +796,10 @@ nsFtpConnectionThread::Run() {
nsIByteBufferInputStream* in; nsIByteBufferInputStream* in;
rv = NS_NewByteBufferInputStream(&in); rv = NS_NewByteBufferInputStream(&in);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
#define LIST_BUF_LEN 4096 #define LIST_BUF_LEN 4096
char listBuf[LIST_BUF_LEN]; // XXX tune this mem. char listBuf[LIST_BUF_LEN]; // XXX tune this mem.
@ -694,30 +809,45 @@ nsFtpConnectionThread::Run() {
PRUint32 writeCnt = 0; PRUint32 writeCnt = 0;
rv = in->Fill(listBuf, bytes, &writeCnt); rv = in->Fill(listBuf, bytes, &writeCnt);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
// tell the user about the data. // tell the user about the data.
nsFtpOnDataAvailableEvent* event = nsFtpOnDataAvailableEvent* event =
new nsFtpOnDataAvailableEvent(mListener, nsnull); // XXX the destroy event method new nsFtpOnDataAvailableEvent(mListener, nsnull); // XXX the destroy event method
// XXX needs to clean up this new. // XXX needs to clean up this new.
if (event == nsnull) if (!event) {
return NS_ERROR_OUT_OF_MEMORY; rv = NS_ERROR_OUT_OF_MEMORY;
mState = FTP_ERROR;
break;
}
event->Init(in, 0, writeCnt); rv = event->Init(in, 0, writeCnt);
if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
rv = event->Fire(mEventQueue); rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
delete event; delete event;
return rv; mState = FTP_ERROR;
break;
} }
rv = mDInStream->Read(listBuf, LIST_BUF_LEN, &bytes); rv = mDInStream->Read(listBuf, LIST_BUF_LEN, &bytes);
if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
} }
if (bytes == 1) { if (bytes == 1) {
// XXX we're done // XXX we're done
} else if (bytes < 0) { } else if (bytes < 0) {
// XXX indicate errror // XXX indicate error
} }
@ -732,7 +862,10 @@ nsFtpConnectionThread::Run() {
{ {
const char *path = nsnull; const char *path = nsnull;
rv = mUrl->GetPath(&path); rv = mUrl->GetPath(&path);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
NS_ASSERTION(mFilename.Length() > 0, "ftp filename not present"); NS_ASSERTION(mFilename.Length() > 0, "ftp filename not present");
@ -743,12 +876,16 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_RETR; mNextState = FTP_R_RETR;
break; break;
@ -771,7 +908,10 @@ nsFtpConnectionThread::Run() {
nsIByteBufferInputStream* in; nsIByteBufferInputStream* in;
rv = NS_NewByteBufferInputStream(&in); rv = NS_NewByteBufferInputStream(&in);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
#define FILE_BUF_LEN 4096 #define FILE_BUF_LEN 4096
char listBuf[FILE_BUF_LEN]; // XXX tune this mem alloc. char listBuf[FILE_BUF_LEN]; // XXX tune this mem alloc.
@ -781,24 +921,39 @@ nsFtpConnectionThread::Run() {
PRUint32 writeCnt = 0; PRUint32 writeCnt = 0;
rv = in->Fill(listBuf, bytes, &writeCnt); rv = in->Fill(listBuf, bytes, &writeCnt);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
// tell the user about the data. // tell the user about the data.
nsFtpOnDataAvailableEvent* event = nsFtpOnDataAvailableEvent* event =
new nsFtpOnDataAvailableEvent(mListener, nsnull); // XXX the destroy event method new nsFtpOnDataAvailableEvent(mListener, nsnull); // XXX the destroy event method
// XXX needs to clean up this new. // XXX needs to clean up this new.
if (event == nsnull) if (!event) {
return NS_ERROR_OUT_OF_MEMORY; rv = NS_ERROR_OUT_OF_MEMORY;
mState = FTP_ERROR;
break;
}
event->Init(in, 0, writeCnt); rv = event->Init(in, 0, writeCnt);
if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
rv = event->Fire(mEventQueue); rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
delete event; delete event;
return rv; mState = FTP_ERROR;
break;
} }
rv = mDInStream->Read(listBuf, LIST_BUF_LEN, &bytes); rv = mDInStream->Read(listBuf, LIST_BUF_LEN, &bytes);
if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
} }
if (bytes == 1) { if (bytes == 1) {
@ -829,11 +984,16 @@ nsFtpConnectionThread::Run() {
buffer = "PASV\r\n"; buffer = "PASV\r\n";
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_PASV; mNextState = FTP_R_PASV;
break; break;
@ -851,6 +1011,7 @@ nsFtpConnectionThread::Run() {
mUsePasv = PR_FALSE; mUsePasv = PR_FALSE;
// until we have PORT support, we'll just fail. // until we have PORT support, we'll just fail.
rv = NS_ERROR_FTP_PASV;
mState = FTP_ERROR; mState = FTP_ERROR;
break; break;
} }
@ -859,8 +1020,11 @@ nsFtpConnectionThread::Run() {
char *ptr = nsnull; char *ptr = nsnull;
char *response = mResponseMsg.ToNewCString(); char *response = mResponseMsg.ToNewCString();
if (!response) if (!response) {
return NS_ERROR_OUT_OF_MEMORY; rv = NS_ERROR_OUT_OF_MEMORY;
mState = FTP_ERROR;
break;
}
// The returned address string can be of the form // The returned address string can be of the form
// (xxx,xxx,xxx,xxx,ppp,ppp) or // (xxx,xxx,xxx,xxx,ppp,ppp) or
@ -896,6 +1060,7 @@ nsFtpConnectionThread::Run() {
mUsePasv = PR_FALSE; mUsePasv = PR_FALSE;
// until we have port support, we'll just fail // until we have port support, we'll just fail
//mState = FTP_S_PORT; //mState = FTP_S_PORT;
rv = NS_ERROR_FTP_PASV;
mState = FTP_ERROR; mState = FTP_ERROR;
break; break;
} }
@ -906,16 +1071,25 @@ nsFtpConnectionThread::Run() {
// now we know where to connect our data channel // now we know where to connect our data channel
rv = sts->CreateTransport(host, port, &lDPipe); // the command channel rv = sts->CreateTransport(host, port, &lDPipe); // the command channel
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
if (mAction == GET) { if (mAction == GET) {
// get the input stream so we can read data from the server. // get the input stream so we can read data from the server.
rv = lDPipe->OpenInputStream(&mDInStream); rv = lDPipe->OpenInputStream(&mDInStream);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
} else { } else {
// get the output stream so we can write to the server // get the output stream so we can write to the server
rv = lDPipe->OpenOutputStream(&mDOutStream); rv = lDPipe->OpenOutputStream(&mDOutStream);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
} }
// we're connected figure out what type of transfer we're doing (ascii or binary) // we're connected figure out what type of transfer we're doing (ascii or binary)
@ -933,17 +1107,24 @@ nsFtpConnectionThread::Run() {
nsresult rv; nsresult rv;
rv = mUrl->GetPath(&filename); // XXX we should probably check to rv = mUrl->GetPath(&filename); // XXX we should probably check to
// XXX make sure we have an actual filename. // XXX make sure we have an actual filename.
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
PR_smprintf(buffer, "DELE %s\r\n", filename); PR_smprintf(buffer, "DELE %s\r\n", filename);
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_DEL_FILE; mNextState = FTP_R_DEL_FILE;
break; break;
@ -968,17 +1149,24 @@ nsFtpConnectionThread::Run() {
const char *dir = nsnull; const char *dir = nsnull;
nsresult rv; nsresult rv;
rv = mUrl->GetPath(&dir); rv = mUrl->GetPath(&dir);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
PR_smprintf(buffer, "RMD %s\r\n", dir); PR_smprintf(buffer, "RMD %s\r\n", dir);
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_DEL_DIR; mNextState = FTP_R_DEL_DIR;
@ -990,7 +1178,9 @@ nsFtpConnectionThread::Run() {
{ {
if (mResponseCode != 2) { if (mResponseCode != 2) {
// failed. // failed.
// XXX indicate failure rv = NS_ERROR_FTP_DEL_DIR;
mState = FTP_ERROR;
break;
} }
mState = FTP_COMPLETE; mState = FTP_COMPLETE;
break; break;
@ -1002,17 +1192,24 @@ nsFtpConnectionThread::Run() {
const char *dir = nsnull; const char *dir = nsnull;
nsresult rv; nsresult rv;
rv = mUrl->GetPath(&dir); rv = mUrl->GetPath(&dir);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) {
mState = FTP_ERROR;
break;
}
PR_smprintf(buffer, "MKD %s\r\n", dir); PR_smprintf(buffer, "MKD %s\r\n", dir);
bufLen = PL_strlen(buffer); bufLen = PL_strlen(buffer);
// send off the command // send off the command
rv = mCOutStream->Write(buffer, bufLen, &bytes); rv = mCOutStream->Write(buffer+prevBytes, bufLen-prevBytes, &bytes);
if (NS_FAILED(rv)) {
if (bytes < bufLen) { mState = FTP_ERROR;
break; break;
} }
prevBytes += bytes;
if (prevBytes < bufLen) break; // not done writing. kick back into this state.
prevBytes = 0;
mState = FTP_READ_BUF; mState = FTP_READ_BUF;
mNextState = FTP_R_MKDIR; mNextState = FTP_R_MKDIR;
break; break;
@ -1021,7 +1218,9 @@ nsFtpConnectionThread::Run() {
case FTP_R_MKDIR: case FTP_R_MKDIR:
if (mResponseCode != 2) { if (mResponseCode != 2) {
// XXX indicate failure rv = NS_ERROR_FTP_MKDIR;
mState = FTP_ERROR;
break;
} }
mState = FTP_COMPLETE; mState = FTP_COMPLETE;
break; break;
@ -1038,6 +1237,8 @@ nsFtpConnectionThread::Run() {
// Close the command channel // Close the command channel
NS_RELEASE(lCPipe); NS_RELEASE(lCPipe);
return NS_OK;
} }
nsresult nsresult
@ -1081,7 +1282,7 @@ nsFtpConnectionThread::Read(void) {
rv = mCInStream->GetLength(&len); rv = mCInStream->GetLength(&len);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
buffer = new char[len+1]; buffer = new char[len+1];
if (!buffer) return 0; // XXX need a better return code if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
rv = mCInStream->Read(buffer, len, &read); rv = mCInStream->Read(buffer, len, &read);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
delete [] buffer; delete [] buffer;
@ -1194,3 +1395,94 @@ nsFtpConnectionThread::FindGetState(void) {
return FTP_ERROR; return FTP_ERROR;
} }
nsresult
nsFtpConnectionThread::MapResultCodeToString(nsresult aResultCode, nsIString* *aOutMsg) {
#if 0 // XXX waiting on NS_NewString() to make it's way into the builds (raptorbase.dll)
nsresult rv;
nsStr* string = nsnull;
rv = NS_NewString(aOutMsg);
if (NS_FAILED(rv)) return rv;
string = new nsStr;
if (!string) return NS_ERROR_OUT_OF_MEMORY;
switch (aResultCode) {
case NS_ERROR_FTP_LOGIN:
{
string->mStr = "FTP: Login failed.";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
case NS_ERROR_FTP_MODE:
{
string->mStr = "FTP: MODE command failed.";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
case NS_ERROR_FTP_CWD:
{
string->mStr = "FTP: CWD command failed.";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
case NS_ERROR_FTP_PASV:
{
string->mStr = "FTP: PASV command failed.";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
case NS_ERROR_FTP_DEL_DIR:
{
string->mStr = "FTP: DEL directory command failed.";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
case NS_ERROR_FTP_MKDIR:
{
string->mStr = "FTP: MKDIR command failed";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
default:
{
string->mStr = "Unknown FTP error.";
rv = (*aOutMsg)->SetStr(string);
if (NS_FAILED(rv)) {
delete string;
return rv;
}
break;
}
} // END: switch
delete string;
#endif // if 0
return NS_OK;
}

View File

@ -22,6 +22,7 @@
#include "nsIStreamListener.h" #include "nsIStreamListener.h"
#include "nsIOutputStream.h" #include "nsIOutputStream.h"
#include "nsIUrl.h" #include "nsIUrl.h"
#include "nsIString.h"
#include "nsString2.h" #include "nsString2.h"
#include "plevent.h" #include "plevent.h"
@ -74,17 +75,17 @@ typedef enum _FTP_STATE {
FTP_R_MKDIR, FTP_R_MKDIR,
FTP_S_MODE, // send ASCII or BINARY FTP_S_MODE, // send ASCII or BINARY
FTP_R_MODE, FTP_R_MODE,
FTP_S_CWD, FTP_S_CWD, // send change working directory
FTP_R_CWD, FTP_R_CWD,
FTP_S_SIZE, FTP_S_SIZE, // send size
FTP_R_SIZE, FTP_R_SIZE,
FTP_S_PUT, FTP_S_PUT, // send STOR to upload the file
FTP_R_PUT, FTP_R_PUT,
FTP_S_RETR, FTP_S_RETR, // send retrieve to download the file
FTP_R_RETR, FTP_R_RETR,
FTP_S_MDTM, FTP_S_MDTM, // send MDTM to get time information
FTP_R_MDTM, FTP_R_MDTM,
FTP_S_LIST, FTP_S_LIST, // send LIST or NLST (server dependent) to get a dir listing
FTP_R_LIST, FTP_R_LIST,
/////////////////////// ///////////////////////
@ -126,6 +127,7 @@ private:
void SetSystInternals(void); void SetSystInternals(void);
FTP_STATE FindActionState(void); FTP_STATE FindActionState(void);
FTP_STATE FindGetState(void); FTP_STATE FindGetState(void);
nsresult MapResultCodeToString(nsresult aResultCode, nsIString* *aOutMsg);
// Private members // Private members