about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTFTP.c
diff options
context:
space:
mode:
Diffstat (limited to 'WWW/Library/Implementation/HTFTP.c')
-rw-r--r--WWW/Library/Implementation/HTFTP.c115
1 files changed, 82 insertions, 33 deletions
diff --git a/WWW/Library/Implementation/HTFTP.c b/WWW/Library/Implementation/HTFTP.c
index d88bcf01..4c90ac0e 100644
--- a/WWW/Library/Implementation/HTFTP.c
+++ b/WWW/Library/Implementation/HTFTP.c
@@ -93,7 +93,7 @@ BUGS:	@@@	Limit connection cache size!
 
 typedef struct _connection {
     struct _connection *	next;	/* Link on list		*/
-    u_long			addr;	/* IP address		*/
+    unsigned long		addr;	/* IP address		*/
     int				socket; /* Socket number for communication */
     BOOL			binary; /* Binary mode? */
 } connection;
@@ -102,12 +102,13 @@ typedef struct _connection {
 */
 #include <HTML.h>
 
-#define PUTC(c) (*targetClass.put_character)(target, c)
-#define PUTS(s) (*targetClass.put_string)(target, s)
-#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
-#define END(e) (*targetClass.end_element)(target, e, 0)
-#define FREE_TARGET (*targetClass._free)(target)
-#define ABORT_TARGET (*targetClass._free)(target)
+#define PUTC(c)      (*targetClass.put_character) (target, c)
+#define PUTS(s)      (*targetClass.put_string)    (target, s)
+#define START(e)     (*targetClass.start_element) (target, e, 0, 0, -1, 0)
+#define END(e)       (*targetClass.end_element)   (target, e, 0)
+#define FREE_TARGET  (*targetClass._free)         (target)
+#define ABORT_TARGET (*targetClass._free)         (target)
+
 struct _HTStructured {
 	CONST HTStructuredClass *	isa;
 	/* ... */
@@ -117,6 +118,7 @@ struct _HTStructured {
 **	---------------------
 */
 PUBLIC int HTfileSortMethod = FILE_BY_NAME;
+
 #ifndef DISABLE_FTP /*This disables everything to end-of-file */
 PRIVATE char ThisYear[8];
 PRIVATE char LastYear[8];
@@ -133,6 +135,15 @@ PRIVATE int data_soc = -1;		/* Socket for data transfer =invalid */
 PRIVATE char *user_entered_password = NULL;
 PRIVATE char *last_username_and_host = NULL;
 
+/*
+ * ProFTPD 1.2.5rc1 is known to have a broken implementation of RETR.  If asked
+ * to retrieve a directory, it gets confused and fails subsequent commands such
+ * as CWD and LIST.  Since this is an unusual bug, we should remove this ifdef
+ * at some point - TD 2004/1/1.
+ */
+#define BROKEN_PROFTPD 1
+PRIVATE int ProFTPD_bugs = FALSE;
+
 typedef enum {
 	GENERIC_SERVER
 	, MACHTEN_SERVER
@@ -474,6 +485,12 @@ PRIVATE int response ARGS1(
 			    continuation == ' ')
 			    continuation_response = -1; /* ended */
 		}
+#ifdef BROKEN_PROFTPD
+		if (result == 220 && LYstrstr(response_text, "ProFTPD 1.2.5")) {
+		    ProFTPD_bugs = TRUE;
+		    CTRACE((tfp, "This server is broken (RETR)\n"));
+		}
+#endif
 		break;
 	    } /* if end of line */
 
@@ -2902,45 +2919,29 @@ unload_btree:
     return HT_LOADED;
 }
 
-/*	Retrieve File from Server
-**	-------------------------
-**
-** On entry,
-**	name		WWW address of a file: document, including hostname
-** On exit,
-**	returns		Socket number for file if good.
-**			<0 if bad.
-*/
-PUBLIC int HTFTPLoad ARGS4(
+/*
+ * Setup an FTP connection.
+ */
+PRIVATE int setup_connection ARGS2(
 	CONST char *,		name,
-	HTParentAnchor *,	anchor,
-	HTFormat,		format_out,
-	HTStream *,		sink)
+	HTParentAnchor *,	anchor)
 {
-    BOOL isDirectory = NO;
-    HTAtom * encoding = NULL;
-    int status, final_status;
     int retry;			/* How many times tried? */
-    int outstanding = 1;	/* outstanding control connection responses
-				   that we are willing to wait for, if we
-				   get to the point of reading data - kw */
-    HTFormat format;
-
-    CTRACE((tfp, "HTFTPLoad(%s) %s connection\n", name, ftp_passive ? "passive" : "normal"));
+    int status;
 
     /* set use_list to NOT since we don't know what kind of server
      * this is yet.  And set the type to GENERIC
      */
     use_list = FALSE;
     server_type = GENERIC_SERVER;
-    HTReadProgress(0,0);
+    ProFTPD_bugs = FALSE;
 
     for (retry = 0; retry < 2; retry++) { /* For timed out/broken connections */
 	status = get_connection(name, anchor);
 	if (status < 0)
 	    return status;
 
-	if (!ftp_passive) {
+	if (!ftp_local_passive) {
 	    status = get_listen_socket();
 	    if (status < 0) {
 		NETCLOSE (control->socket);
@@ -3090,6 +3091,37 @@ PUBLIC int HTFTPLoad ARGS4(
 	break;	/* No more retries */
 
     } /* for retries */
+    return status;
+}
+
+/*	Retrieve File from Server
+**	-------------------------
+**
+** On entry,
+**	name		WWW address of a file: document, including hostname
+** On exit,
+**	returns		Socket number for file if good.
+**			<0 if bad.
+*/
+PUBLIC int HTFTPLoad ARGS4(
+	CONST char *,		name,
+	HTParentAnchor *,	anchor,
+	HTFormat,		format_out,
+	HTStream *,		sink)
+{
+    BOOL isDirectory = NO;
+    HTAtom * encoding = NULL;
+    int status, final_status;
+    int outstanding = 1;	/* outstanding control connection responses
+				   that we are willing to wait for, if we
+				   get to the point of reading data - kw */
+    HTFormat format;
+
+    CTRACE((tfp, "HTFTPLoad(%s) %s connection\n", name, ftp_local_passive ? "passive" : "normal"));
+
+    HTReadProgress(0,0);
+
+    status = setup_connection(name, anchor);
     if (status < 0)
 	return status;		/* Failed with this code */
 
@@ -3540,6 +3572,23 @@ PUBLIC int HTFTPLoad ARGS4(
 	*/
 	if (!(type) || (type && *type != 'D')) {
 	    status = send_cmd_2("RETR", filename);
+#ifdef BROKEN_PROFTPD
+	    /*
+	     * ProFTPD 1.2.5rc1 gets confused when asked to RETR a directory.
+	     */
+	    if (status >= 5) {
+		int check;
+
+		if (ProFTPD_bugs) {
+		    CTRACE((tfp, "{{reconnecting...\n"));
+		    close_connection(control);
+		    check = setup_connection(name, anchor);
+		    CTRACE((tfp, "...done }}reconnecting\n"));
+		    if (check < 0)
+			return check;
+		}
+	    }
+#endif
 	} else {
 	    status = 5;		/* Failed status set as flag. - FM */
 	}
@@ -3571,7 +3620,7 @@ PUBLIC int HTFTPLoad ARGS4(
     }
 
 listen:
-    if(!ftp_passive) {
+    if(!ftp_local_passive) {
 	/* Wait for the connection */
 #ifdef INET6
 	struct sockaddr_storage soc_address;
@@ -3595,7 +3644,7 @@ listen:
 	}
 	CTRACE((tfp, "TCP: Accepted new socket %d\n", status));
 	data_soc = status;
-    } /* !ftp_passive */
+    } /* !ftp_local_passive */
 
 #if 0	/* no - this makes the data connection go away too soon (2.8.3dev.22) */
     if ((status = send_cmd_nowait("QUIT")) == 1)