[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