From a8b060e36e883300ec6cc01c314bf9f14b33b6bd Mon Sep 17 00:00:00 2001
From: "valeski%netscape.com" <valeski%netscape.com>
Date: Fri, 23 Apr 1999 17:34:33 +0000
Subject: [PATCH] nsFtpConnectionThread.* added more states. we now handle
 mkdir and delete (file/dir). nsFtpFactory.cpp api change.

---
 .../ftp/src/nsFtpConnectionThread.cpp         | 132 +++++++++++++++++-
 .../protocol/ftp/src/nsFtpConnectionThread.h  |   9 ++
 netwerk/protocol/ftp/src/nsFtpFactory.cpp     |   2 +
 3 files changed, 138 insertions(+), 5 deletions(-)

diff --git a/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp b/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp
index 8200e82f855c..42ef2d1decec 100644
--- a/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp
@@ -221,10 +221,11 @@ nsFtpConnectionThread::Run() {
 
 		    case FTP_R_SYST:
 			    if (mResponseCode == 2) {
-				    if (mUseDefaultPath)
+                    if (mUseDefaultPath) {
 					    mState = FTP_S_PWD;
-				    else
-					    ; // ftp figure out what to do.
+                    } else {
+                        mState = FindActionState();
+                    }
 
 				    SetSystInternals(); // must be called first to setup member vars.
 
@@ -294,7 +295,7 @@ nsFtpConnectionThread::Run() {
 					    mServerType = FTP_NCSA_TYPE;	
 				    }
 			    }
-                // XXX mState figure out what to do
+                mState = FindActionState();
 			    break;
 			    // END: FTP_R_MACB
 
@@ -326,7 +327,7 @@ nsFtpConnectionThread::Run() {
 			    }
 
 			    // default next state
-			    // mState = figure out what to do
+			    mState = FindActionState();
 
 			    // reset server types if necessary
 			    if (mServerType == FTP_TCPC_TYPE) {
@@ -405,6 +406,102 @@ nsFtpConnectionThread::Run() {
 //////////////////////////////
 //// ACTION STATES
 //////////////////////////////
+            case FTP_S_DEL_FILE:
+                {
+                const char *filename = nsnull;
+                nsresult rv;
+                rv = mUrl->GetPath(&filename); // XXX we should probably check to 
+                                               // XXX make sure we have an actual filename.
+                if (NS_FAILED(rv)) return rv;
+                PR_smprintf(buffer, "DELE %s\r\n", filename);
+                bufLen = PL_strlen(buffer);
+
+    		    // send off the command
+                rv = mOutStream->Write(buffer, bufLen, &bytes);
+
+                if (bytes < bufLen) {
+                    break;
+                }
+                
+                mState = FTP_READ_BUF;
+			    mNextState = FTP_R_DEL_FILE;
+                break;
+                }
+                // END: FTP_S_DEL_FILE
+
+            case FTP_R_DEL_FILE:
+                if (mResponseCode != 2) {
+                    // failed. Increment to the dir delete.
+                    mState = FTP_S_DEL_DIR;
+                    break;
+                }
+
+                mState = FTP_COMPLETE;
+                break;
+                // END: FTP_R_DEL_FILE
+
+            case FTP_S_DEL_DIR:
+                {
+                const char *dir = nsnull;
+                nsresult rv;
+                rv = mUrl->GetPath(&dir);
+                if (NS_FAILED(rv)) return rv;
+                PR_smprintf(buffer, "RMD %s\r\n", dir);
+                bufLen = PL_strlen(buffer);
+
+    		    // send off the command
+                rv = mOutStream->Write(buffer, bufLen, &bytes);
+
+                if (bytes < bufLen) {
+                    break;
+                }
+                
+                mState = FTP_READ_BUF;
+			    mNextState = FTP_R_DEL_DIR;
+
+                break;
+                }
+                // END: FTP_S_DEL_DIR
+
+            case FTP_R_DEL_DIR:
+                if (mResponseCode != 2) {
+                    // failed.
+                    // XXX indicate failure
+                }
+                mState = FTP_COMPLETE;
+                break;
+                // END: FTP_R_DEL_DIR
+
+            case FTP_S_MKDIR:
+                {
+                const char *dir = nsnull;
+                nsresult rv;
+                rv = mUrl->GetPath(&dir);
+                if (NS_FAILED(rv)) return rv;
+                PR_smprintf(buffer, "MKD %s\r\n", dir);
+                bufLen = PL_strlen(buffer);
+
+    		    // send off the command
+                rv = mOutStream->Write(buffer, bufLen, &bytes);
+
+                if (bytes < bufLen) {
+                    break;
+                }
+                
+                mState = FTP_READ_BUF;
+			    mNextState = FTP_R_MKDIR;
+                break;
+                }
+                // END: FTP_S_MKDIR
+
+            case FTP_R_MKDIR:
+                if (mResponseCode != 2) {
+                    // XXX indicate failure
+                }
+                mState = FTP_COMPLETE;
+                break;
+                // END: FTP_R_MKDIR
+
             default:
                 ;
 
@@ -510,3 +607,28 @@ nsFtpConnectionThread::SetSystInternals(void) {
 		mList = TRUE;
 	}
 }
+
+FTP_STATE
+nsFtpConnectionThread::FindActionState(void) {
+
+    // These operations require the separate data channel.
+    if (mAction == GET || mAction == POST) {
+        // we're doing an operation that requies the data channel.
+        // figure out what kind of data channel we want to setup,
+        // and do it.
+        if (mUsePasv)
+            return FTP_S_PASV;
+        else
+            return FTP_S_PORT;
+    }
+
+    // These operations use the command channel response as the
+    // data to return to the user.
+    if (mAction == DEL)
+        return FTP_S_DEL_FILE; // we assume it's a file
+
+    if (mAction == MKDIR)
+        return FTP_S_MKDIR;
+
+    return FTP_ERROR;
+}
diff --git a/netwerk/protocol/ftp/src/nsFtpConnectionThread.h b/netwerk/protocol/ftp/src/nsFtpConnectionThread.h
index 8f04c348cd48..4a60c6ff2d0d 100644
--- a/netwerk/protocol/ftp/src/nsFtpConnectionThread.h
+++ b/netwerk/protocol/ftp/src/nsFtpConnectionThread.h
@@ -45,6 +45,8 @@ typedef enum _FTP_STATE {
 //// Internal states
 ///////////////////////
     FTP_READ_BUF,
+    FTP_ERROR,
+    FTP_COMPLETE,
 
 ///////////////////////
 //// Command channel connection setup states
@@ -61,6 +63,12 @@ typedef enum _FTP_STATE {
 	FTP_R_MACB,
 	FTP_S_PWD ,		// send parent working directory (pwd)
 	FTP_R_PWD ,
+    FTP_S_DEL_FILE, // send delete file
+    FTP_R_DEL_FILE,
+    FTP_S_DEL_DIR , // send delete directory
+    FTP_R_DEL_DIR ,
+    FTP_S_MKDIR,    // send mkdir
+    FTP_R_MKDIR,
 
 ///////////////////////
 //// Data channel connection setup states
@@ -99,6 +107,7 @@ public:
 private:
     nsresult Read(void);
     void SetSystInternals(void);
+    FTP_STATE FindActionState(void);
 
 	PLEventQueue*		mEventQueue;        // used to communicate outside this thread
 
diff --git a/netwerk/protocol/ftp/src/nsFtpFactory.cpp b/netwerk/protocol/ftp/src/nsFtpFactory.cpp
index 5dfe6e92680c..6a1907392f17 100644
--- a/netwerk/protocol/ftp/src/nsFtpFactory.cpp
+++ b/netwerk/protocol/ftp/src/nsFtpFactory.cpp
@@ -104,6 +104,8 @@ nsresult nsNetFactory::LockFactory(PRBool aLock)
 extern "C" PR_IMPLEMENT(nsresult)
 NSGetFactory(nsISupports* aServMgr,
              const nsCID &aClass,
+             const char *aClassName,
+             const char *aProgID,
              nsIFactory **aFactory)
 {
     if (aFactory == nsnull)