From da51f9b2c41ca5f7de5ef3c6d6b8fd5fb2a8142b Mon Sep 17 00:00:00 2001
From: Micah Cowan <micah@cowan.name>
Date: Thu, 15 May 2008 22:26:00 -0700
Subject: [PATCH] Fix file-checking in FTP with --spider.

---
 src/ChangeLog |  5 +++++
 src/ftp.c     | 35 +++++++++++++++++++++++++++++++----
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index b8b466c0..149bc521 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2008-05-15  Steven Schubiger  <schubiger@gmail.com>
+
+	* ftp.c (getftp): Verify that the file actually exists in FTP, by
+	checking it against the listing.
+
 2008-05-12  Micah Cowan  <micah@cowan.name>
 
 	* main.c (main): Downgrade "-N with -O" to a warning, and switch
diff --git a/src/ftp.c b/src/ftp.c
index 3223ea59..5bfd2aa8 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -227,6 +227,8 @@ print_length (wgint size, wgint start, bool authoritative)
   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
 }
 
+static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
+
 /* Retrieves a file with denoted parameters through opening an FTP
    connection to the server.  It always closes the data connection,
    and closes the control connection in case of error.  */
@@ -776,12 +778,37 @@ Error in server response, closing control connection.\n"));
 
   if (cmd & DO_RETR)
     {
-      /* If we're in spider mode, don't really retrieve anything.  The
-         fact that we got to this point should be proof enough that
-         the file exists, vaguely akin to HTTP's concept of a "HEAD"
-         request.  */
+      /* If we're in spider mode, don't really retrieve anything except
+	 the directory listing and verify whether the given "file" exists.  */
       if (opt.spider)
         {
+	  bool exists = false;
+	  uerr_t res;
+	  struct fileinfo *f;
+	  res = ftp_get_listing (u, con, &f);
+	  /* Set the DO_RETR command flag again, because it gets unset when 
+	     calling ftp_get_listing() and would otherwise cause an assertion 
+	     failure earlier on when this function gets repeatedly called 
+	     (e.g., when recursing).  */
+	  con->cmd |= DO_RETR;
+	  if (res == RETROK)
+	    {
+	      while (f) 
+		{
+		  if (!strcmp (f->name, u->file))
+		    {
+		      exists = true;
+		      break;
+		    }
+		  f = f->next;
+		}
+	      if (!exists)
+		{
+		  logputs (LOG_VERBOSE, "\n");
+		  logprintf (LOG_NOTQUIET, _("No such file `%s'.\n"),
+			     escnonprint (u->file));
+		}
+	    }
           fd_close (csock);
           con->csock = -1;
           fd_close (dtsock);