]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/ftp.c
Merge commit 'a939e5b2527d0c4628815b1d3d8e29ee921227e8'
[ffmpeg] / libavformat / ftp.c
index 7faf4a5d66c44d8aa5dc218380a169a6a7496b24..27a172e8ad723b4092ca2508656ef0a849a5704a 100644 (file)
@@ -26,7 +26,6 @@
 #include "libavutil/bprint.h"
 
 #define CONTROL_BUFFER_SIZE 1024
-#define CREDENTIALS_BUFFER_SIZE 128
 
 typedef enum {
     UNKNOWN,
@@ -44,9 +43,10 @@ typedef struct {
     uint8_t *control_buf_ptr, *control_buf_end;
     int server_data_port;                        /**< Data connection port opened by server, -1 on error. */
     int server_control_port;                     /**< Control connection port, default is 21 */
-    char hostname[512];                          /**< Server address. */
-    char credencials[CREDENTIALS_BUFFER_SIZE];   /**< Authentication data */
-    char path[MAX_URL_SIZE];                     /**< Path to resource on server. */
+    char *hostname;                              /**< Server address. */
+    char *user;                                  /**< Server user */
+    char *password;                              /**< Server user's password */
+    char *path;                                  /**< Path to resource on server. */
     int64_t filesize;                            /**< Size of file on server, -1 on error. */
     int64_t position;                            /**< Current position, calculated. */
     int rw_timeout;                              /**< Network timeout. */
@@ -72,6 +72,8 @@ static const AVClass ftp_context_class = {
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
+static int ftp_close(URLContext *h);
+
 static int ftp_getc(FTPContext *s)
 {
     int len;
@@ -213,28 +215,16 @@ static void ftp_close_both_connections(FTPContext *s)
 
 static int ftp_auth(FTPContext *s)
 {
-    const char *user = NULL, *pass = NULL;
-    char *end = NULL, buf[CONTROL_BUFFER_SIZE], credencials[CREDENTIALS_BUFFER_SIZE];
+    char buf[CONTROL_BUFFER_SIZE];
     int err;
     static const int user_codes[] = {331, 230, 0};
     static const int pass_codes[] = {230, 0};
 
-    /* Authentication may be repeated, original string has to be saved */
-    av_strlcpy(credencials, s->credencials, sizeof(credencials));
-
-    user = av_strtok(credencials, ":", &end);
-    pass = av_strtok(end, ":", &end);
-
-    if (!user) {
-        user = "anonymous";
-        pass = s->anonymous_password ? s->anonymous_password : "nopassword";
-    }
-
-    snprintf(buf, sizeof(buf), "USER %s\r\n", user);
+    snprintf(buf, sizeof(buf), "USER %s\r\n", s->user);
     err = ftp_send_command(s, buf, user_codes, NULL);
     if (err == 331) {
-        if (pass) {
-            snprintf(buf, sizeof(buf), "PASS %s\r\n", pass);
+        if (s->password) {
+            snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password);
             err = ftp_send_command(s, buf, pass_codes, NULL);
         } else
             return AVERROR(EACCES);
@@ -361,9 +351,12 @@ static int ftp_current_dir(FTPContext *s)
         end[-1] = '\0';
     } else
         *end = '\0';
-    av_strlcpy(s->path, start, sizeof(s->path));
+    s->path = av_strdup(start);
 
     av_free(res);
+
+    if (!s->path)
+        return AVERROR(ENOMEM);
     return 0;
 
   fail:
@@ -579,8 +572,11 @@ static int ftp_abort(URLContext *h)
 
 static int ftp_open(URLContext *h, const char *url, int flags)
 {
-    char proto[10], path[MAX_URL_SIZE];
+    char proto[10], path[MAX_URL_SIZE], credencials[MAX_URL_SIZE], hostname[MAX_URL_SIZE];
+    const char *tok_user = NULL, *tok_pass = NULL;
+    char *end = NULL;
     int err;
+    size_t pathlen;
     FTPContext *s = h->priv_data;
 
     av_dlog(h, "ftp protocol open\n");
@@ -590,12 +586,26 @@ static int ftp_open(URLContext *h, const char *url, int flags)
     s->position = 0;
 
     av_url_split(proto, sizeof(proto),
-                 s->credencials, sizeof(s->credencials),
-                 s->hostname, sizeof(s->hostname),
+                 credencials, sizeof(credencials),
+                 hostname, sizeof(hostname),
                  &s->server_control_port,
                  path, sizeof(path),
                  url);
 
+    tok_user = av_strtok(credencials, ":", &end);
+    tok_pass = av_strtok(end, ":", &end);
+    if (!tok_user) {
+        tok_user = "anonymous";
+        tok_pass = av_x_if_null(s->anonymous_password, "nopassword");
+    }
+    s->user = av_strdup(tok_user);
+    s->password = av_strdup(tok_pass);
+    s->hostname = av_strdup(hostname);
+    if (!s->hostname || !s->user || (tok_pass && !s->password)) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
     if (s->server_control_port < 0 || s->server_control_port > 65535)
         s->server_control_port = 21;
 
@@ -604,7 +614,10 @@ static int ftp_open(URLContext *h, const char *url, int flags)
 
     if ((err = ftp_current_dir(s)) < 0)
         goto fail;
-    av_strlcat(s->path, path, sizeof(s->path));
+    pathlen = strlen(s->path) + strlen(path) + 1;
+    if ((err = av_reallocp(&s->path, pathlen)) < 0)
+        goto fail;
+    av_strlcat(s->path + strlen(s->path), path, pathlen);
 
     if (ftp_restart(s, 0) < 0) {
         h->is_streamed = 1;
@@ -619,8 +632,7 @@ static int ftp_open(URLContext *h, const char *url, int flags)
 
   fail:
     av_log(h, AV_LOG_ERROR, "FTP open failed\n");
-    ffurl_closep(&s->conn_control);
-    ffurl_closep(&s->conn_data);
+    ftp_close(h);
     return err;
 }
 
@@ -755,9 +767,15 @@ static int ftp_write(URLContext *h, const unsigned char *buf, int size)
 
 static int ftp_close(URLContext *h)
 {
+    FTPContext *s = h->priv_data;
+
     av_dlog(h, "ftp protocol close\n");
 
-    ftp_close_both_connections(h->priv_data);
+    ftp_close_both_connections(s);
+    av_freep(&s->user);
+    av_freep(&s->password);
+    av_freep(&s->hostname);
+    av_freep(&s->path);
 
     return 0;
 }