mirror of https://github.com/mpv-player/mpv
stream_ftp: support longer filenames
This change was split into 8 patches. Squash them together, as they affect stream_ftp.c only. stream ftp: readline: Fix off-by-one error Even if max bytes are available read at most max - 1 bytes. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35427 b3059339-0415-0410-9bf9-f77b7e298cf2 Conflicts: stream/stream_ftp.c stream ftp: readline: Always initialize output parameter buf Only exception if passed parameter max is less than or equal to zero. That cannot happen with the current code. Additionally change readresp function to always copy the first response line if the parameter rsp is non-NULL. This fixes some error reporting that used uninitialized stack arrays. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35428 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: readline: Always try to read complete lines If there is not enough space in the provided line buffer just skip the remaining bytes until reaching EOL. Usually we are only interested in the first 5 characters and for everything else the (on-stack) response buffer should still be big enough. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35429 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Revise file descriptor usage * Set unbound descriptor variables to -1 * Always test >= 0 to see if a variable refers to a valid descriptor git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35430 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Only send QUIT command if connected Do not attempt to send commands without control connections. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35431 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Create buffers before opening control connection git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35432 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Allocate command buffer on-heap git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35433 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Increase command buffer size Allow for more longish file names (be it because of length or more lengthy characters). git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35434 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
73618d11d4
commit
a04b35013a
|
@ -32,6 +32,8 @@
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
|
||||||
#include "core/mp_msg.h"
|
#include "core/mp_msg.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
@ -50,6 +52,7 @@ static struct stream_priv_s {
|
||||||
int handle;
|
int handle;
|
||||||
int cavail,cleft;
|
int cavail,cleft;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
char *cmd_buf;
|
||||||
} stream_priv_dflts = {
|
} stream_priv_dflts = {
|
||||||
"anonymous","no@spam",
|
"anonymous","no@spam",
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -58,11 +61,14 @@ static struct stream_priv_s {
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
||||||
0,
|
-1,
|
||||||
0,0,
|
0,0,
|
||||||
NULL
|
NULL,
|
||||||
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CMD_BUFSIZE 8192
|
||||||
|
|
||||||
#define BUFSIZE 2048
|
#define BUFSIZE 2048
|
||||||
|
|
||||||
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
|
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
|
||||||
|
@ -103,6 +109,14 @@ static int fd_can_read(int fd,int timeout) {
|
||||||
/*
|
/*
|
||||||
* read a line of text
|
* read a line of text
|
||||||
*
|
*
|
||||||
|
* If the line is too long to fit in the buffer, provided via parameters
|
||||||
|
* buf and max, the remaining characters are skipped. So the next call to
|
||||||
|
* this function is synchronized to the start of the following response
|
||||||
|
* line.
|
||||||
|
*
|
||||||
|
* The parameter buf will always be initialized as long as max is bigger
|
||||||
|
* then 1. If nothing is read it will contain an empty string.
|
||||||
|
*
|
||||||
* return -1 on error or bytecount
|
* return -1 on error or bytecount
|
||||||
*/
|
*/
|
||||||
static int readline(char *buf,int max,struct stream_priv_s *ctl)
|
static int readline(char *buf,int max,struct stream_priv_s *ctl)
|
||||||
|
@ -111,9 +125,14 @@ static int readline(char *buf,int max,struct stream_priv_s *ctl)
|
||||||
char *end,*bp=buf;
|
char *end,*bp=buf;
|
||||||
int eof = 0;
|
int eof = 0;
|
||||||
|
|
||||||
|
if (max <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*bp = '\0';
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (ctl->cavail > 0) {
|
if (ctl->cavail > 0) {
|
||||||
x = (max >= ctl->cavail) ? ctl->cavail : max-1;
|
x = FFMIN(ctl->cavail, max-1);
|
||||||
end = memccpy(bp,ctl->cget,'\n',x);
|
end = memccpy(bp,ctl->cget,'\n',x);
|
||||||
if (end != NULL)
|
if (end != NULL)
|
||||||
x = end - bp;
|
x = end - bp;
|
||||||
|
@ -134,8 +153,18 @@ static int readline(char *buf,int max,struct stream_priv_s *ctl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max == 1) {
|
if (max == 1) {
|
||||||
*buf = '\0';
|
char *q = memchr(ctl->cget, '\n', ctl->cavail);
|
||||||
break;
|
|
||||||
|
if (q) { // found EOL: update state and return
|
||||||
|
++q;
|
||||||
|
ctl->cavail -= q - ctl->cget;
|
||||||
|
ctl->cget = q;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive more data to find end of current line
|
||||||
|
ctl->cget = ctl->cput;
|
||||||
}
|
}
|
||||||
if (ctl->cput == ctl->cget) {
|
if (ctl->cput == ctl->cget) {
|
||||||
ctl->cput = ctl->cget = ctl->buf;
|
ctl->cput = ctl->cget = ctl->buf;
|
||||||
|
@ -179,13 +208,14 @@ static int readresp(struct stream_priv_s* ctl,char* rsp)
|
||||||
{
|
{
|
||||||
static char response[256];
|
static char response[256];
|
||||||
char match[5];
|
char match[5];
|
||||||
int r;
|
int r, len;
|
||||||
|
|
||||||
if (readline(response,256,ctl) == -1)
|
len = readline(response,256,ctl);
|
||||||
|
if (rsp) strcpy(rsp,response);
|
||||||
|
if (len == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = atoi(response)/100;
|
r = atoi(response)/100;
|
||||||
if(rsp) strcpy(rsp,response);
|
|
||||||
|
|
||||||
mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response);
|
mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response);
|
||||||
|
|
||||||
|
@ -263,7 +293,7 @@ static int FtpOpenPort(struct stream_priv_s* p) {
|
||||||
static int FtpOpenData(stream_t* s,int64_t newpos) {
|
static int FtpOpenData(stream_t* s,int64_t newpos) {
|
||||||
struct stream_priv_s* p = s->priv;
|
struct stream_priv_s* p = s->priv;
|
||||||
int resp;
|
int resp;
|
||||||
char str[256],rsp_txt[256];
|
char rsp_txt[256];
|
||||||
|
|
||||||
// Open a new connection
|
// Open a new connection
|
||||||
s->fd = FtpOpenPort(p);
|
s->fd = FtpOpenPort(p);
|
||||||
|
@ -271,21 +301,21 @@ static int FtpOpenData(stream_t* s,int64_t newpos) {
|
||||||
if(s->fd < 0) return 0;
|
if(s->fd < 0) return 0;
|
||||||
|
|
||||||
if(newpos > 0) {
|
if(newpos > 0) {
|
||||||
snprintf(str,255,"REST %"PRId64, (int64_t)newpos);
|
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"REST %"PRId64, (int64_t)newpos);
|
||||||
|
|
||||||
resp = FtpSendCmd(str,p,rsp_txt);
|
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
|
||||||
if(resp != 3) {
|
if(resp != 3) {
|
||||||
mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
|
mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
|
||||||
newpos = 0;
|
newpos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the file
|
// Get the file
|
||||||
snprintf(str,255,"RETR %s",p->filename);
|
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"RETR %s",p->filename);
|
||||||
resp = FtpSendCmd(str,p,rsp_txt);
|
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
|
||||||
|
|
||||||
if(resp != 1) {
|
if(resp != 1) {
|
||||||
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
|
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +363,7 @@ static int seek(stream_t *s,int64_t newpos) {
|
||||||
|
|
||||||
// First close the fd
|
// First close the fd
|
||||||
closesocket(s->fd);
|
closesocket(s->fd);
|
||||||
s->fd = 0;
|
s->fd = -1;
|
||||||
|
|
||||||
// Send send the telnet sequence needed to make the server react
|
// Send send the telnet sequence needed to make the server react
|
||||||
|
|
||||||
|
@ -369,15 +399,18 @@ static void close_f(stream_t *s) {
|
||||||
|
|
||||||
if(!p) return;
|
if(!p) return;
|
||||||
|
|
||||||
if(s->fd > 0) {
|
if(s->fd >= 0) {
|
||||||
closesocket(s->fd);
|
closesocket(s->fd);
|
||||||
s->fd = 0;
|
s->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FtpSendCmd("QUIT",p,NULL);
|
if (p->handle >= 0) {
|
||||||
|
FtpSendCmd("QUIT", p, NULL);
|
||||||
|
closesocket(p->handle);
|
||||||
|
}
|
||||||
|
|
||||||
if(p->handle) closesocket(p->handle);
|
|
||||||
free(p->buf);
|
free(p->buf);
|
||||||
|
free(p->cmd_buf);
|
||||||
|
|
||||||
m_struct_free(&stream_opts,p);
|
m_struct_free(&stream_opts,p);
|
||||||
}
|
}
|
||||||
|
@ -388,7 +421,7 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||||
int resp;
|
int resp;
|
||||||
int64_t len = 0;
|
int64_t len = 0;
|
||||||
struct stream_priv_s* p = (struct stream_priv_s*)opts;
|
struct stream_priv_s* p = (struct stream_priv_s*)opts;
|
||||||
char str[256],rsp_txt[256];
|
char rsp_txt[256];
|
||||||
|
|
||||||
if(mode != STREAM_READ) {
|
if(mode != STREAM_READ) {
|
||||||
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Unknown open mode %d\n",mode);
|
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Unknown open mode %d\n",mode);
|
||||||
|
@ -402,6 +435,16 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||||
return STREAM_ERROR;
|
return STREAM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate buffers
|
||||||
|
p->buf = malloc(BUFSIZE);
|
||||||
|
p->cmd_buf = malloc(CMD_BUFSIZE);
|
||||||
|
|
||||||
|
if (!p->buf || !p->cmd_buf) {
|
||||||
|
close_f(stream);
|
||||||
|
m_struct_free(&stream_opts,opts);
|
||||||
|
return STREAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// Open the control connection
|
// Open the control connection
|
||||||
p->handle = connect2Server(p->host,p->port,1);
|
p->handle = connect2Server(p->host,p->port,1);
|
||||||
|
|
||||||
|
@ -413,7 +456,6 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||||
// We got a connection, let's start serious things
|
// We got a connection, let's start serious things
|
||||||
stream->fd = -1;
|
stream->fd = -1;
|
||||||
stream->priv = p;
|
stream->priv = p;
|
||||||
p->buf = malloc(BUFSIZE);
|
|
||||||
|
|
||||||
if (readresp(p, NULL) == 0) {
|
if (readresp(p, NULL) == 0) {
|
||||||
close_f(stream);
|
close_f(stream);
|
||||||
|
@ -421,20 +463,20 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
snprintf(str,255,"USER %s",p->user);
|
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"USER %s",p->user);
|
||||||
resp = FtpSendCmd(str,p,rsp_txt);
|
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
|
||||||
|
|
||||||
// password needed
|
// password needed
|
||||||
if(resp == 3) {
|
if(resp == 3) {
|
||||||
snprintf(str,255,"PASS %s",p->pass);
|
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"PASS %s",p->pass);
|
||||||
resp = FtpSendCmd(str,p,rsp_txt);
|
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
|
||||||
if(resp != 2) {
|
if(resp != 2) {
|
||||||
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
|
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
|
||||||
close_f(stream);
|
close_f(stream);
|
||||||
return STREAM_ERROR;
|
return STREAM_ERROR;
|
||||||
}
|
}
|
||||||
} else if(resp != 2) {
|
} else if(resp != 2) {
|
||||||
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
|
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
|
||||||
close_f(stream);
|
close_f(stream);
|
||||||
return STREAM_ERROR;
|
return STREAM_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -448,10 +490,10 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the filesize
|
// Get the filesize
|
||||||
snprintf(str,255,"SIZE %s",p->filename);
|
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"SIZE %s",p->filename);
|
||||||
resp = FtpSendCmd(str,p,rsp_txt);
|
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
|
||||||
if(resp != 2) {
|
if(resp != 2) {
|
||||||
mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
|
mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
|
||||||
} else {
|
} else {
|
||||||
int dummy;
|
int dummy;
|
||||||
sscanf(rsp_txt,"%d %"SCNd64,&dummy,&len);
|
sscanf(rsp_txt,"%d %"SCNd64,&dummy,&len);
|
||||||
|
|
Loading…
Reference in New Issue