diff --git a/configure b/configure index fac413e853..782d134630 100755 --- a/configure +++ b/configure @@ -172,6 +172,7 @@ Optional features: --disable-inet6 Disable IPv6 support [autodetect] --disable-gethostbyname2 gethostbyname() is not provided by the C library [autodetect] + --disable-ftp Disable ftp support [enabled] Codecs: --enable-gif enable gif support [autodetect] --enable-png enable png input/output support [autodetect] @@ -1139,6 +1140,7 @@ _fribidi=no _fribidiconfig='fribidi-config' _inet6=auto _gethostbyname2=auto +_ftp=yes for ac_option do case "$ac_option" in # Skip 1st pass @@ -1336,6 +1338,8 @@ for ac_option do --disable-freetype) _freetype=no ;; --enable-unrarlib) _unrarlib=yes ;; --disable-unrarlib) _unrarlib=no ;; + --enable-ftp) _ftp=yes ;; + --disable-ftp) _ftp=no ;; --enable-fribidi) _fribidi=yes ;; --disable-fribidi) _fribidi=no ;; @@ -4943,6 +4947,16 @@ else fi echores "$_network" +echocheck "ftp" +if test "$_ftp" != no ; then + _def_ftp='#define HAVE_FTP 1' + _inputmodules="ftp $_inputmodules" +else + _noinputmodules="ftp $_noinputmodules" + _def_ftp='#undef HAVE_FTP' +fi +echores "$_ftp" + # endian testing echocheck "byte order" if test "$_big_endian" = auto ; then @@ -5914,6 +5928,9 @@ $_def_faad_version /* enable network */ $_def_network +/* enable ftp support */ +$_def_ftp + /* enable winsock2 instead of Unix functions*/ $_def_winsock2 diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile index 06074416d1..8b911666a2 100644 --- a/libmpdemux/Makefile +++ b/libmpdemux/Makefile @@ -3,7 +3,7 @@ LIBNAME = libmpdemux.a include ../config.mak -SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c muxer.c muxer_avi.c muxer_mpeg.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_ty.c demux_ty_osd.c demux_pva.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c stream_file.c stream_netstream.c stream_vcd.c stream_null.c tv.c tvi_dummy.c tvi_v4l.c tvi_v4l2.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c demux_rawvideo.c cddb.c cdinfo.c demux_rawdv.c ai_alsa.c ai_oss.c audio_in.c demux_smjpeg.c cue_read.c extension.c demux_gif.c demux_ts.c demux_realaud.c +SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c muxer.c muxer_avi.c muxer_mpeg.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_ty.c demux_ty_osd.c demux_pva.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c stream_file.c stream_netstream.c stream_vcd.c stream_null.c stream_ftp.c tv.c tvi_dummy.c tvi_v4l.c tvi_v4l2.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c demux_rawvideo.c cddb.c cdinfo.c demux_rawdv.c ai_alsa.c ai_oss.c audio_in.c demux_smjpeg.c cue_read.c extension.c demux_gif.c demux_ts.c demux_realaud.c ifeq ($(XMMS_PLUGINS),yes) SRCS += demux_xmms.c endif diff --git a/libmpdemux/asf_mmst_streaming.c b/libmpdemux/asf_mmst_streaming.c index 4befcdc1fc..fe377698d0 100644 --- a/libmpdemux/asf_mmst_streaming.c +++ b/libmpdemux/asf_mmst_streaming.c @@ -447,7 +447,7 @@ int asf_mmst_streaming_start(stream_t *stream) path = strchr(url1->file,'/') + 1; url1->port=1755; - s = connect2Server( url1->hostname, url1->port ); + s = connect2Server( url1->hostname, url1->port, 1); if( s<0 ) { return s; } diff --git a/libmpdemux/asf_streaming.c b/libmpdemux/asf_streaming.c index 122cbb66e6..8d3886d3b8 100644 --- a/libmpdemux/asf_streaming.c +++ b/libmpdemux/asf_streaming.c @@ -656,7 +656,7 @@ asf_http_streaming_start( stream_t *stream, int *demuxer_type ) { } else { if( url->port==0 ) url->port = 80; } - fd = connect2Server( url->hostname, url->port ); + fd = connect2Server( url->hostname, url->port, 1); if( fd<0 ) return fd; http_hdr = asf_http_request( stream->streaming_ctrl ); diff --git a/libmpdemux/network.c b/libmpdemux/network.c index 69dcfdeff4..a5b2316dd4 100644 --- a/libmpdemux/network.c +++ b/libmpdemux/network.c @@ -184,7 +184,7 @@ char *af2String(int af) { // return -1 is unable to connect to a particular port int -connect2Server_with_af(char *host, int port, int af) { +connect2Server_with_af(char *host, int port, int af,int verb) { int socket_server_fd; int err, err_len; int ret,count = 0; @@ -236,7 +236,7 @@ connect2Server_with_af(char *host, int port, int af) { if ( inet_addr(host)==INADDR_NONE ) #endif { - mp_msg(MSGT_NETWORK,MSGL_STATUS,"Resolving %s for %s...\n", host, af2String(af)); + if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,"Resolving %s for %s...\n", host, af2String(af)); #ifdef HAVE_GETHOSTBYNAME2 hp=(struct hostent*)gethostbyname2( host, af ); @@ -244,7 +244,7 @@ connect2Server_with_af(char *host, int port, int af) { hp=(struct hostent*)gethostbyname( host ); #endif if( hp==NULL ) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't resolve name for %s: %s\n", af2String(af), host); + if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't resolve name for %s: %s\n", af2String(af), host); return -2; } @@ -280,7 +280,7 @@ connect2Server_with_af(char *host, int port, int af) { #else inet_ntop(af, our_s_addr, buf, 255); #endif - mp_msg(MSGT_NETWORK,MSGL_STATUS,"Connecting to server %s[%s]:%d ...\n", host, buf , port ); + if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,"Connecting to server %s[%s]:%d ...\n", host, buf , port ); // Turn the socket as non blocking so we can timeout on the connection #ifndef HAVE_WINSOCK2 @@ -295,7 +295,7 @@ connect2Server_with_af(char *host, int port, int af) { #else if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { #endif - mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to connect to server with %s\n", af2String(af)); + if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to connect to server with %s\n", af2String(af)); closesocket(socket_server_fd); return -1; } @@ -350,19 +350,19 @@ connect2Server_with_af(char *host, int port, int af) { int -connect2Server(char *host, int port) { +connect2Server(char *host, int port, int verb) { #ifdef HAVE_AF_INET6 int r; int s = -2; - r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6); + r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb); if (r > -1) return r; - s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET); + s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb); if (s == -2) return r; return s; #else - return connect2Server_with_af(host, port, AF_INET); + return connect2Server_with_af(host, port, AF_INET,verb); #endif @@ -452,11 +452,11 @@ http_send_request( URL_t *url ) { if( proxy ) { if( url->port==0 ) url->port = 8080; // Default port for the proxy server - fd = connect2Server( url->hostname, url->port ); + fd = connect2Server( url->hostname, url->port,1 ); url_free( server_url ); } else { if( server_url->port==0 ) server_url->port = 80; // Default port for the web server - fd = connect2Server( server_url->hostname, server_url->port ); + fd = connect2Server( server_url->hostname, server_url->port,1 ); } if( fd<0 ) { return -1; @@ -785,7 +785,7 @@ extension=NULL; return -1; } } else { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Unknown protocol '%s'\n", url->protocol ); + mp_msg(MSGT_NETWORK,MSGL_V,"Unknown protocol '%s'\n", url->protocol ); return -1; } } while( redirect ); @@ -916,7 +916,7 @@ pnm_streaming_start( stream_t *stream ) { if( stream==NULL ) return -1; fd = connect2Server( stream->streaming_ctrl->url->hostname, - stream->streaming_ctrl->url->port ? stream->streaming_ctrl->url->port : 7070 ); + stream->streaming_ctrl->url->port ? stream->streaming_ctrl->url->port : 7070,1 ); printf("PNM:// fd=%d\n",fd); if(fd<0) return -1; @@ -957,7 +957,7 @@ realrtsp_streaming_start( stream_t *stream ) { redirected = 0; fd = connect2Server( stream->streaming_ctrl->url->hostname, - port = (stream->streaming_ctrl->url->port ? stream->streaming_ctrl->url->port : 554) ); + port = (stream->streaming_ctrl->url->port ? stream->streaming_ctrl->url->port : 554),1 ); if(fd<0) return -1; mrl = malloc(sizeof(char)*(strlen(stream->streaming_ctrl->url->hostname)+strlen(stream->streaming_ctrl->url->file)+16)); diff --git a/libmpdemux/network.h b/libmpdemux/network.h index 9bf614e0c0..49675f2f8c 100644 --- a/libmpdemux/network.h +++ b/libmpdemux/network.h @@ -51,7 +51,7 @@ int streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int siz int nop_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ); int nop_streaming_seek( int fd, off_t pos, streaming_ctrl_t *stream_ctrl ); -int connect2Server(char *host, int port); +int connect2Server(char *host, int port,int verb); int http_send_request(URL_t *url); HTTP_header_t *http_read_response(int fd); diff --git a/libmpdemux/stream.c b/libmpdemux/stream.c index 13161a8c8e..eea82853c1 100644 --- a/libmpdemux/stream.c +++ b/libmpdemux/stream.c @@ -61,6 +61,9 @@ extern stream_info_t stream_info_netstream; #ifdef HAS_DVBIN_SUPPORT extern stream_info_t stream_info_dvb; #endif +#ifdef HAVE_FTP +extern stream_info_t stream_info_ftp; +#endif extern stream_info_t stream_info_null; extern stream_info_t stream_info_file; @@ -78,7 +81,9 @@ stream_info_t* auto_open_streams[] = { #ifdef HAS_DVBIN_SUPPORT &stream_info_dvb, #endif - +#ifdef HAVE_FTP + &stream_info_ftp, +#endif &stream_info_null, &stream_info_file, NULL diff --git a/libmpdemux/stream_ftp.c b/libmpdemux/stream_ftp.c new file mode 100644 index 0000000000..9862200f76 --- /dev/null +++ b/libmpdemux/stream_ftp.c @@ -0,0 +1,465 @@ + +#include "config.h" + +#ifdef HAVE_FTP + +#include +#include + +#include +#include +#include +#include +#include + +#include "mp_msg.h" +#include "stream.h" +#include "help_mp.h" +#include "../m_option.h" +#include "../m_struct.h" + +static struct stream_priv_s { + char* user; + char* pass; + char* host; + int port; + char* filename; + + char *cput,*cget; + int handle; + int cavail,cleft; + char *buf; +} stream_priv_dflts = { + "anonymous","no@spam", + NULL, + 21, + NULL, + NULL, + NULL, + + 0, + 0,0, + NULL +}; + +#define BUFSIZE 2048 + +#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) +/// URL definition +static m_option_t stream_opts_fields[] = { + {"username", ST_OFF(user), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + {"password", ST_OFF(pass), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + {"port", ST_OFF(port), CONF_TYPE_INT, 0, 0 ,65635, NULL}, + {"filename", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + { NULL, NULL, 0, 0, 0, 0, NULL } +}; +static struct m_struct_st stream_opts = { + "ftp", + sizeof(struct stream_priv_s), + &stream_priv_dflts, + stream_opts_fields +}; + +#define TELNET_IAC 255 /* interpret as command: */ +#define TELNET_IP 244 /* interrupt process--permanently */ +#define TELNET_SYNCH 242 /* for telfunc calls */ + +/* + * read a line of text + * + * return -1 on error or bytecount + */ +static int readline(char *buf,int max,struct stream_priv_s *ctl) +{ + int x,retval = 0; + char *end,*bp=buf; + int eof = 0; + + do { + if (ctl->cavail > 0) { + x = (max >= ctl->cavail) ? ctl->cavail : max-1; + end = memccpy(bp,ctl->cget,'\n',x); + if (end != NULL) + x = end - bp; + retval += x; + bp += x; + *bp = '\0'; + max -= x; + ctl->cget += x; + ctl->cavail -= x; + if (end != NULL) { + bp -= 2; + if (strcmp(bp,"\r\n") == 0) { + *bp++ = '\n'; + *bp++ = '\0'; + --retval; + } + break; + } + } + if (max == 1) { + *buf = '\0'; + break; + } + if (ctl->cput == ctl->cget) { + ctl->cput = ctl->cget = ctl->buf; + ctl->cavail = 0; + ctl->cleft = BUFSIZE; + } + if(eof) { + if (retval == 0) + retval = -1; + break; + } + if ((x = recv(ctl->handle,ctl->cput,ctl->cleft,0)) == -1) { + mp_msg(MSGT_STREAM,MSGL_ERR, "[ftp] read error: %s\n",strerror(errno)); + retval = -1; + break; + } + if (x == 0) + eof = 1; + ctl->cleft -= x; + ctl->cavail += x; + ctl->cput += x; + } while (1); + + return retval; +} + +/* + * read a response from the server + * + * return 0 if first char doesn't match + * return 1 if first char matches + */ +static int readresp(struct stream_priv_s* ctl,char* rsp) +{ + static char response[256]; + char match[5]; + int r; + + if (readline(response,256,ctl) == -1) + return 0; + + r = atoi(response)/100; + if(rsp) strcpy(rsp,response); + + mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response); + + if (response[3] == '-') { + strncpy(match,response,3); + match[3] = ' '; + match[4] = '\0'; + do { + if (readline(response,256,ctl) == -1) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Control socket read failed\n"); + return 0; + } + mp_msg(MSGT_OPEN,MSGL_V, "[ftp] < %s",response); + } while (strncmp(response,match,4)); + } + return r; +} + + +static int FtpSendCmd(const char *cmd, struct stream_priv_s *nControl,char* rsp) +{ + int l = strlen(cmd); + + mp_msg(MSGT_STREAM,MSGL_V, "[ftp] > %s",cmd); + while(l > 0) { + int s = send(nControl->handle,cmd,l,0); + + if(s <= 0) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] write error: %s\n",strerror(errno)); + return 0; + } + + cmd += s; + l -= s; + } + + return readresp(nControl,rsp); +} + +static int FtpOpenPort(struct stream_priv_s* p) { + int resp,fd; + char rsp_txt[256]; + char* par,str[128]; + int num[6]; + + resp = FtpSendCmd("PASV\r\n",p,rsp_txt); + if(resp != 2) { + mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'PASV' failed: %s\n",rsp_txt); + return 0; + } + + par = strchr(rsp_txt,'('); + + if(!par || !par[0] || !par[1]) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] invalid server response: %s ??\n",rsp_txt); + return 0; + } + + sscanf(par+1,"%u,%u,%u,%u,%u,%u",&num[0],&num[1],&num[2], + &num[3],&num[4],&num[5]); + snprintf(str,127,"%d.%d.%d.%d",num[0],num[1],num[2],num[3]); + fd = connect2Server(str,(num[4]<<8)+num[5],0); + + if(fd <= 0) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] failed to create data connection\n"); + return 0; + } + + return fd; +} + +static int fill_buffer(stream_t *s, char* buffer, int max_len){ + fd_set fds; + struct timeval tv; + int r; + + // Check if there is something to read. This avoid hang + // forever if the network stop responding. + FD_ZERO(&fds); + FD_SET(s->fd,&fds); + tv.tv_sec = 15; + tv.tv_usec = 0; + + if(select(s->fd+1, &fds, NULL, NULL, &tv) < 1) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n"); + return -1; + } + + r = recv(s->fd,buffer,max_len,0); + return (r <= 0) ? -1 : r; +} + +static int seek(stream_t *s,off_t newpos) { + struct stream_priv_s* p = s->priv; + int resp; + char str[256],rsp_txt[256]; + fd_set fds; + struct timeval tv; + + if(s->pos > s->end_pos) { + s->eof=1; + return 0; + } + + FD_ZERO(&fds); + FD_SET(p->handle,&fds); + tv.tv_sec = tv.tv_usec = 0; + + // Check to see if the server doesn't alredy terminated the transfert + if(select(p->handle+1, &fds, NULL, NULL, &tv) > 0) { + if(readresp(p,rsp_txt) != 2) + mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] Warning the server didn't finished the transfert correctly: %s\n",rsp_txt); + close(s->fd); + s->fd = -1; + } + + // Close current download + if(s->fd >= 0) { + static const char pre_cmd[]={TELNET_IAC,TELNET_IP,TELNET_IAC,TELNET_SYNCH}; + //int fl; + + // First close the fd + close(s->fd); + s->fd = 0; + + // Send send the telnet sequence needed to make the server react + + // Dunno if this is really needed, lftp have it. I let + // it here in case it turn out to be needed on some other OS + //fl=fcntl(p->handle,F_GETFL); + //fcntl(p->handle,F_SETFL,fl&~O_NONBLOCK); + + // send only first byte as OOB due to OOB braindamage in many unices + send(p->handle,pre_cmd,1,MSG_OOB); + send(p->handle,pre_cmd+1,sizeof(pre_cmd)-1,0); + + //fcntl(p->handle,F_SETFL,fl); + + // Get the 426 Transfer aborted + // Or the 226 Transfer complete + resp = readresp(p,rsp_txt); + if(resp != 4 && resp != 2) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Server didn't abort correctly: %s\n",rsp_txt); + s->eof = 1; + return 0; + } + // Send the ABOR command + // Ignore the return code as sometimes it fail with "nothing to abort" + FtpSendCmd("ABOR\n\r",p,rsp_txt); + } + + // Open a new connection + s->fd = FtpOpenPort(p); + + if(!s->fd) return 0; + + if(newpos > 0) { +#ifdef _LARGEFILE_SOURCE + snprintf(str,255,"REST %lld\r\n",newpos); +#else + snprintf(str,255,"REST %u\r\n",newpos); +#endif + + resp = FtpSendCmd(str,p,rsp_txt); + if(resp != 3) { + mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt); + newpos = 0; + } + } + + // Get the file + snprintf(str,255,"RETR %s\r\n",p->filename); + resp = FtpSendCmd(str,p,rsp_txt); + + if(resp != 1) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt); + return 0; + } + + s->pos = newpos; + return 1; +} + + +static void close_f(stream_t *s) { + struct stream_priv_s* p = s->priv; + + if(!p) return; + + if(s->fd > 0) { + close(s->fd); + s->fd = 0; + } + + FtpSendCmd("QUIT\r\n",p,NULL); + + if(p->handle) close(p->handle); + if(p->buf) free(p->buf); + + m_struct_free(&stream_opts,p); +} + + + +static int open_f(stream_t *stream,int mode, void* opts, int* file_format) { + int len = 0,resp; + struct stream_priv_s* p = (struct stream_priv_s*)opts; + char str[256],rsp_txt[256]; + + if(mode != STREAM_READ) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Unknown open mode %d\n",mode); + m_struct_free(&stream_opts,opts); + return STREAM_UNSUPORTED; + } + + if(!p->filename || !p->host) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Bad url\n"); + m_struct_free(&stream_opts,opts); + return STREAM_ERROR; + } + + // Open the control connection + p->handle = connect2Server(p->host,p->port,1); + + if(p->handle < 0) { + m_struct_free(&stream_opts,opts); + return STREAM_ERROR; + } + + // We got a connection, let's start serious things + stream->fd = -1; + stream->priv = p; + p->buf = malloc(BUFSIZE); + + if (readresp(p, NULL) == 0) { + close_f(stream); + m_struct_free(&stream_opts,opts); + return STREAM_ERROR; + } + + // Login + snprintf(str,255,"USER %s\r\n",p->user); + resp = FtpSendCmd(str,p,rsp_txt); + + // password needed + if(resp == 3) { + snprintf(str,255,"PASS %s\r\n",p->pass); + resp = FtpSendCmd(str,p,rsp_txt); + if(resp != 2) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt); + close_f(stream); + return STREAM_ERROR; + } + } else if(resp != 2) { + mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt); + close_f(stream); + return STREAM_ERROR; + } + + // Set the transfert type + resp = FtpSendCmd("TYPE I\r\n",p,rsp_txt); + if(resp != 2) { + mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'TYPE I' failed: %s\n",rsp_txt); + close_f(stream); + return STREAM_ERROR; + } + + // Get the filesize + snprintf(str,255,"SIZE %s\r\n",p->filename); + resp = FtpSendCmd(str,p,rsp_txt); + if(resp != 2) { + mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt); + } else { + int dummy; + sscanf(rsp_txt,"%d %d",&dummy,&len); + } + + // Start the data connection + stream->fd = FtpOpenPort(p); + if(stream->fd <= 0) { + close_f(stream); + return STREAM_ERROR; + } + + // Get the file + snprintf(str,255,"RETR %s\r\n",p->filename); + resp = FtpSendCmd(str,p,rsp_txt); + + if(resp != 1) { + mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt); + close_f(stream); + return STREAM_ERROR; + } + + + if(len > 0) { + stream->seek = seek; + stream->end_pos = len; + } + + stream->priv = p; + stream->fill_buffer = fill_buffer; + stream->close = close_f; + + return STREAM_OK; +} + +stream_info_t stream_info_ftp = { + "File Transfer Protocol", + "ftp", + "Albeu", + "reuse a bit of code from ftplib written by Thomas Pfau", + open_f, + { "ftp", NULL }, + &stream_opts, + 1 // Urls are an option string +}; + +#endif diff --git a/libmpdemux/stream_netstream.c b/libmpdemux/stream_netstream.c index 52ebece44d..720de98a75 100644 --- a/libmpdemux/stream_netstream.c +++ b/libmpdemux/stream_netstream.c @@ -252,7 +252,7 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { return STREAM_ERROR; } - f = connect2Server(p->host,p->port); + f = connect2Server(p->host,p->port,1); if(f < 0) { mp_msg(MSGT_OPEN,MSGL_ERR, "Connection to %s:%d failed\n",p->host,p->port); m_struct_free(&stream_opts,opts);