mirror of https://github.com/mpv-player/mpv
ftp support. The change on connect2Server is needed bcs we need 2
different level of verbosity for control and data connections. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10626 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
38a2fa46fd
commit
755e127c26
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,465 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_FTP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue