]> granicus.if.org Git - curl/commitdiff
FTP: allow "rubbish" prepended to the SIZE response
authorDaniel Stenberg <daniel@haxx.se>
Thu, 12 Sep 2019 15:50:21 +0000 (17:50 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 13 Sep 2019 12:21:00 +0000 (14:21 +0200)
This is a protocol violation but apparently there are legacy proprietary
servers doing this.

Added test 336 and 337 to verify.

Reported-by: Philippe Marguinaud
Closes #4339

lib/ftp.c
tests/data/Makefile.inc
tests/data/test336 [new file with mode: 0644]
tests/data/test337 [new file with mode: 0644]

index 0793dc1f3a7b68b837c77f11ecafc1baeb7d5d68..00233a80d781fa3d7be0a161c88dd1376113f013 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2244,9 +2244,25 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
   char *buf = data->state.buffer;
 
   /* get the size from the ascii string: */
-  if(ftpcode == 213)
+  if(ftpcode == 213) {
+    /* To allow servers to prepend "rubbish" in the response string, we scan
+       for all the digits at the end of the response and parse only those as a
+       number. */
+    char *start = &buf[4];
+    char *fdigit = strchr(start, '\r');
+    if(fdigit) {
+      do
+        fdigit--;
+      while(ISDIGIT(*fdigit) && (fdigit > start));
+      if(!ISDIGIT(*fdigit))
+        fdigit++;
+    }
+    else
+      fdigit = start;
     /* ignores parsing errors, which will make the size remain unknown */
-    (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize);
+    (void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
+
+  }
 
   if(instate == FTP_SIZE) {
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
index fc22c2f1771f96e5ca4dd7f506f7e7b0567b7655..3733bd6b919a19b71e522a8f67604dd3c908cdaf 100644 (file)
@@ -57,7 +57,7 @@ test298 test299 test300 test301 test302 test303 test304 test305 test306 \
 test307 test308 test309 test310 test311 test312 test313 test314 test315 \
 test316 test317 test318 test319 test320 test321 test322 test323 test324 \
 test325 test326 test327 test328 test329 test330 test331 test332 test333 \
-test334 test335 \
+test334 test335 test336 test337 \
 test340 \
 \
 test350 test351 test352 test353 test354 test355 test356 \
diff --git a/tests/data/test336 b/tests/data/test336
new file mode 100644 (file)
index 0000000..85477c9
--- /dev/null
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+TYPE A
+RETR
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+data
+    to
+      see
+that FTP
+works
+  so does it?
+</data>
+<datacheck nonewline="yes">
+data
+</datacheck>
+<servercmd>
+REPLY EPSV 500 no such command
+REPLY SIZE 500 no such command
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP range download when SIZE doesn't work
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/336 --use-ascii --range 3-6
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous\r
+PASS ftp@example.com\r
+PWD\r
+EPSV\r
+PASV\r
+TYPE A\r
+SIZE 336\r
+REST 3\r
+RETR 336\r
+ABOR\r
+QUIT\r
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test337 b/tests/data/test337
new file mode 100644 (file)
index 0000000..80086dd
--- /dev/null
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+TYPE A
+RETR
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+data
+    to
+      see
+that FTP
+works
+  so does it?
+</data>
+<datacheck nonewline="yes">
+data
+</datacheck>
+<servercmd>
+REPLY EPSV 500 no such command
+REPLY SIZE 213 file: 213, Size =51
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP range download with SIZE returning extra crap
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/337 --use-ascii --range 3-6
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous\r
+PASS ftp@example.com\r
+PWD\r
+EPSV\r
+PASV\r
+TYPE A\r
+SIZE 337\r
+REST 3\r
+RETR 337\r
+ABOR\r
+QUIT\r
+</protocol>
+</verify>
+</testcase>