[vlc-devel] [PATCH] Improve FTP servers compatibility

Sylver Bruneau sylver.bruneau at gmail.com
Sat Nov 28 11:47:29 CET 2015


---
 modules/access/ftp.c | 69 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 56 insertions(+), 13 deletions(-)

diff --git a/modules/access/ftp.c b/modules/access/ftp.c
index da04c8d..6d666ae 100644
--- a/modules/access/ftp.c
+++ b/modules/access/ftp.c
@@ -146,6 +146,7 @@ struct access_sys_t
     bool       out;
     uint64_t   offset;
     uint64_t   size;
+    char      *p_filename;
 };
 #define GET_OUT_SYS( p_this ) \
     ((access_sys_t *)(((sout_access_out_t *)(p_this))->p_sys))
@@ -598,7 +599,6 @@ static int parseURL( vlc_url_t *url, const char *path, enum tls_mode_e mode )
         return VLC_SUCCESS;
     /* FTP URLs are relative to user's default directory (RFC1738 §3.2)
     For absolute path use ftp://foo.bar//usr/local/etc/filename */
-    /* FIXME: we should issue a series of CWD, one per slash */
     if( url->psz_path )
     {
         assert( url->psz_path[0] == '/' );
@@ -626,6 +626,9 @@ static int InOpen( vlc_object_t *p_this )
     access_sys_t *p_sys;
     char         *psz_arg;
     bool          b_directory = false;
+    char         *p_temp_path;
+    char         *p_path_element;
+    int           i_element_count = 0;
 
     /* Init p_access */
     access_InitFields( p_access );
@@ -644,11 +647,56 @@ static int InOpen( vlc_object_t *p_this )
     if( Connect( p_this, p_sys ) )
         goto exit_error;
 
+    /* count number of elements in path */
+    p_temp_path = (char *)calloc( 1, strlen( p_sys->url.psz_path ) + 1 );
+    strcpy(p_temp_path, p_sys->url.psz_path);
+    for (p_path_element = strtok(p_temp_path, "/"); p_path_element; p_path_element = strtok(NULL, "/"))
+    {
+        i_element_count++;
+    }
+
+    /* go to root path (this is needed on some FTP servers) */
+    if( ftp_SendCommand( p_this, p_sys, "CWD /") < 0 )
+        goto error;
+    else
+    if( ftp_RecvCommand( p_this, p_sys, NULL, NULL ) != 2 )
+    {
+        msg_Err( p_this, "file or directory does not exist" );
+        goto error;
+    }
+
+    /* Perform a CWD for each path element and save file name for future use */
+    strcpy(p_temp_path, p_sys->url.psz_path);
+    p_path_element = strtok(p_temp_path, "/");
+
+    while (i_element_count > 0)
+    {
+        if (i_element_count == 1)
+        {
+            p_sys->p_filename = (char *)calloc( 1, strlen( (const char *)p_path_element ) + 1 );
+            strcpy(p_sys->p_filename, p_path_element);
+
+        }
+        else
+        {
+            if( ftp_SendCommand( p_this, p_sys, "CWD %s", p_path_element ) < 0 )
+                goto error;
+            else
+            if( ftp_RecvCommand( p_this, p_sys, NULL, NULL ) != 2 )
+            {
+                msg_Err( p_this, "file or directory does not exist" );
+                goto error;
+            }
+        }
+        p_path_element = strtok(NULL, "/");
+        i_element_count --;
+    }
+
     /* get size */
     if( p_sys->url.psz_path == NULL )
         b_directory = true;
     else
-    if( ftp_SendCommand( p_this, p_sys, "SIZE %s", p_sys->url.psz_path ) < 0 )
+    if( ftp_SendCommand( p_this, p_sys, "SIZE %s", p_sys->p_filename ) < 0 )
         goto error;
     else
     if ( ftp_RecvCommand( p_this, p_sys, NULL, &psz_arg ) == 2 )
@@ -658,15 +706,6 @@ static int InOpen( vlc_object_t *p_this )
         msg_Dbg( p_access, "file size: %"PRIu64, p_sys->size );
     }
     else
-    if( ftp_SendCommand( p_this, p_sys, "CWD %s", p_sys->url.psz_path ) < 0 )
-        goto error;
-    else
-    if( ftp_RecvCommand( p_this, p_sys, NULL, NULL ) != 2 )
-    {
-        msg_Err( p_this, "file or directory does not exist" );
-        goto error;
-    }
-    else
         b_directory = true;
 
     if( b_directory )
@@ -693,7 +732,9 @@ error:
 
 exit_error:
     vlc_UrlClean( &p_sys->url );
+    free( p_sys->p_filename );
     free( p_sys );
+    free( p_temp_path );
     return VLC_EGENERIC;
 }
 
@@ -740,6 +781,7 @@ static int OutOpen( vlc_object_t *p_this )
 
 exit_error:
     vlc_UrlClean( &p_sys->url );
+    free( p_sys->p_filename );
     free( p_sys );
     return VLC_EGENERIC;
 }
@@ -767,6 +809,7 @@ static void Close( vlc_object_t *p_access, access_sys_t *p_sys )
 
     /* free memory */
     vlc_UrlClean( &p_sys->url );
+    free( p_sys->p_filename );
     free( p_sys );
 }
 
@@ -1080,10 +1123,10 @@ static int ftp_StartStream( vlc_object_t *p_access, access_sys_t *p_sys,
     else
     {
         /* "1xx" message */
-        assert( p_sys->url.psz_path );
+        assert( p_sys->p_filename );
         if( ftp_SendCommand( p_access, p_sys, "%s %s",
                              p_sys->out ? "STOR" : "RETR",
-                             p_sys->url.psz_path ) < 0
+                             p_sys->p_filename ) < 0
          || ftp_RecvCommand( p_access, p_sys, &i_answer, NULL ) > 2 )
         {
             msg_Err( p_access, "cannot retrieve file" );
-- 
2.4.9 (Apple Git-60)



More information about the vlc-devel mailing list