struct access_sys_t
{
- vlc_url_t url;
+ vlc_url_t url;
- int fd_cmd;
- int fd_data;
+ int fd_cmd;
+ int fd_data;
+
+ vlc_bool_t b_epsv;
};
static int ftp_SendCommand( access_t *, char *, ... );
goto exit_error;
}
+ /* Extended passive mode */
+ if( ftp_SendCommand( p_access, "EPSV ALL" ) < 0 )
+ {
+ msg_Err( p_access, "cannot request extended passive mode" );
+ goto exit_error;
+ }
+ if( ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 )
+ {
+ p_sys->b_epsv = VLC_FALSE;
+ msg_Warn( p_access, "Extended passive mode not supported" );
+ }
+ else
+ p_sys->b_epsv = VLC_TRUE;
+
/* binary mode */
if( ftp_SendCommand( p_access, "TYPE I" ) < 0 ||
ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 )
access_sys_t *p_sys = p_access->p_sys;
va_list args;
char *psz_cmd;
- int i_ret;
va_start( args, psz_fmt );
vasprintf( &psz_cmd, psz_fmt, args );
{
access_sys_t *p_sys = p_access->p_sys;
- char psz_ip[1000];
+ char psz_ipv4[16], *psz_ip;
int i_answer;
char *psz_arg, *psz_parser;
- int a1,a2,a3,a4;
- int p1,p2;
+ unsigned a1, a2, a3, a4, p1, p2;
int i_port;
- if( ftp_SendCommand( p_access, "PASV" ) < 0 ||
- ftp_ReadCommand( p_access, &i_answer, &psz_arg ) != 2 )
+ if( ( ftp_SendCommand( p_access, p_sys->b_epsv ? "EPSV" : "PASV" ) < 0 )
+ || ( ftp_ReadCommand( p_access, &i_answer, &psz_arg ) != 2 ) )
{
- msg_Err( p_access, "cannot set passive transfer mode" );
+ msg_Err( p_access, "cannot set passive mode" );
return VLC_EGENERIC;
}
psz_parser = strchr( psz_arg, '(' );
- if( !psz_parser ||
- sscanf( psz_parser, "(%d,%d,%d,%d,%d,%d", &a1, &a2, &a3,
- &a4, &p1, &p2 ) < 6 )
+ if( psz_parser == NULL )
{
free( psz_arg );
- msg_Err( p_access, "cannot get ip/port for passive transfer mode" );
+ msg_Err( p_access, "cannot parse passive mode response" );
return VLC_EGENERIC;
}
+
+ if( p_sys->b_epsv )
+ {
+ char psz_fmt[7] = "(|||%u";
+ psz_fmt[1] = psz_fmt[2] = psz_fmt[3] = psz_parser[1];
+
+ if( sscanf( psz_parser, psz_fmt, &i_port ) < 1 )
+ {
+ free( psz_arg );
+ msg_Err( p_access, "cannot parse passive mode response" );
+ return VLC_EGENERIC;
+ }
+ /* FIXME: if psz_ip is a hostname/DNS to a cluster of FTP servers,
+ * this may fail because we'll end up on another server :(
+ * getpeername() + getnameinfo() should be used instead.
+ */
+ psz_ip = p_sys->url.psz_host;
+ }
+ else
+ {
+ if( ( sscanf( psz_parser, "(%u,%u,%u,%u,%u,%u", &a1, &a2, &a3, &a4,
+ &p1, &p2 ) < 6 ) || ( a1 > 255 ) || ( a2 > 255 )
+ || ( a3 > 255 ) || ( a4 > 255 ) || ( p1 > 255 ) || ( p2 > 255 ) )
+ {
+ free( psz_arg );
+ msg_Err( p_access, "cannot parse passive mode response" );
+ return VLC_EGENERIC;
+ }
+
+ sprintf( psz_ipv4, "%u.%u.%u.%u", a1, a2, a3, a4 );
+ psz_ip = psz_ipv4;
+ i_port = (p1 << 8) | p2;
+ }
free( psz_arg );
- sprintf( psz_ip, "%d.%d.%d.%d", a1, a2, a3, a4 );
- i_port = p1 * 256 + p2;
msg_Dbg( p_access, "ip:%s port:%d", psz_ip, i_port );
if( ftp_SendCommand( p_access, "TYPE I" ) < 0 ||