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:
al 2012-11-20 22:13:57 +00:00 committed by wm4
parent 73618d11d4
commit a04b35013a
1 changed files with 73 additions and 31 deletions

View File

@ -32,6 +32,8 @@
#include <winsock2.h>
#endif
#include <libavutil/avutil.h>
#include "core/mp_msg.h"
#include "network.h"
#include "stream.h"
@ -50,6 +52,7 @@ static struct stream_priv_s {
int handle;
int cavail,cleft;
char *buf;
char *cmd_buf;
} stream_priv_dflts = {
"anonymous","no@spam",
NULL,
@ -58,11 +61,14 @@ static struct stream_priv_s {
NULL,
NULL,
0,
-1,
0,0,
NULL
NULL,
NULL,
};
#define CMD_BUFSIZE 8192
#define BUFSIZE 2048
#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
*
* 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
*/
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;
int eof = 0;
if (max <= 0) {
return -1;
}
*bp = '\0';
do {
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);
if (end != NULL)
x = end - bp;
@ -134,8 +153,18 @@ static int readline(char *buf,int max,struct stream_priv_s *ctl)
}
}
if (max == 1) {
*buf = '\0';
break;
char *q = memchr(ctl->cget, '\n', ctl->cavail);
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) {
ctl->cput = ctl->cget = ctl->buf;
@ -179,13 +208,14 @@ static int readresp(struct stream_priv_s* ctl,char* rsp)
{
static char response[256];
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;
r = atoi(response)/100;
if(rsp) strcpy(rsp,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) {
struct stream_priv_s* p = s->priv;
int resp;
char str[256],rsp_txt[256];
char rsp_txt[256];
// Open a new connection
s->fd = FtpOpenPort(p);
@ -271,21 +301,21 @@ static int FtpOpenData(stream_t* s,int64_t newpos) {
if(s->fd < 0) return 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) {
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;
}
}
// Get the file
snprintf(str,255,"RETR %s",p->filename);
resp = FtpSendCmd(str,p,rsp_txt);
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"RETR %s",p->filename);
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
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;
}
@ -333,7 +363,7 @@ static int seek(stream_t *s,int64_t newpos) {
// First close the fd
closesocket(s->fd);
s->fd = 0;
s->fd = -1;
// 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(s->fd > 0) {
if(s->fd >= 0) {
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->cmd_buf);
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;
int64_t len = 0;
struct stream_priv_s* p = (struct stream_priv_s*)opts;
char str[256],rsp_txt[256];
char rsp_txt[256];
if(mode != STREAM_READ) {
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;
}
// 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
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
stream->fd = -1;
stream->priv = p;
p->buf = malloc(BUFSIZE);
if (readresp(p, NULL) == 0) {
close_f(stream);
@ -421,20 +463,20 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
}
// Login
snprintf(str,255,"USER %s",p->user);
resp = FtpSendCmd(str,p,rsp_txt);
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"USER %s",p->user);
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
// password needed
if(resp == 3) {
snprintf(str,255,"PASS %s",p->pass);
resp = FtpSendCmd(str,p,rsp_txt);
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"PASS %s",p->pass);
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
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);
return STREAM_ERROR;
}
} 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);
return STREAM_ERROR;
}
@ -448,10 +490,10 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
}
// Get the filesize
snprintf(str,255,"SIZE %s",p->filename);
resp = FtpSendCmd(str,p,rsp_txt);
snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"SIZE %s",p->filename);
resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
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 {
int dummy;
sscanf(rsp_txt,"%d %"SCNd64,&dummy,&len);