]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/ftp.c
avformat: Forward errors where possible
[ffmpeg] / libavformat / ftp.c
index 9aa7a45629ff6e67e6d65672bc7a6394bf2034a9..97ad80de0bac5fbf10822f9c8bad75ebdcb3ad87 100644 (file)
@@ -69,6 +69,8 @@ typedef struct {
     size_t dir_buffer_size;
     size_t dir_buffer_offset;
     int utf8;
+    const char *option_user;                     /**< User to be used if none given in the URL */
+    const char *option_password;                 /**< Password to be used if none given in the URL */
 } FTPContext;
 
 #define OFFSET(x) offsetof(FTPContext, x)
@@ -78,6 +80,8 @@ static const AVOption options[] = {
     {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
     {"ftp-write-seekable", "control seekability of connection during encoding", OFFSET(write_seekable), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
     {"ftp-anonymous-password", "password for anonymous login. E-mail address should be used.", OFFSET(anonymous_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
+    {"ftp-user", "user for FTP login. Overridden by whatever is in the URL.", OFFSET(option_user), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
+    {"ftp-password", "password for FTP login. Overridden by whatever is in the URL.", OFFSET(option_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
     {NULL}
 };
 
@@ -389,7 +393,7 @@ static int ftp_file_size(FTPContext *s)
     static const int size_codes[] = {213, 0};
 
     snprintf(command, sizeof(command), "SIZE %s\r\n", s->path);
-    if (ftp_send_command(s, command, size_codes, &res) == 213 && res) {
+    if (ftp_send_command(s, command, size_codes, &res) == 213 && res && strlen(res) > 4) {
         s->filesize = strtoll(&res[4], NULL, 10);
     } else {
         s->filesize = -1;
@@ -489,8 +493,6 @@ static int ftp_list_nlst(FTPContext *s)
     return 0;
 }
 
-static int ftp_has_feature(FTPContext *s, const char *feature_name);
-
 static int ftp_list(FTPContext *s)
 {
     int ret;
@@ -515,7 +517,7 @@ static int ftp_features(FTPContext *s)
     static const char *feat_command        = "FEAT\r\n";
     static const char *enable_utf8_command = "OPTS UTF8 ON\r\n";
     static const int feat_codes[] = {211, 0};
-    static const int opts_codes[] = {200, 451, 0};
+    static const int opts_codes[] = {200, 202, 451, 0};
 
     av_freep(&s->features);
     if (ftp_send_command(s, feat_command, feat_codes, &s->features) != 211) {
@@ -523,7 +525,8 @@ static int ftp_features(FTPContext *s)
     }
 
     if (ftp_has_feature(s, "UTF8")) {
-        if (ftp_send_command(s, enable_utf8_command, opts_codes, NULL) == 200)
+        int ret = ftp_send_command(s, enable_utf8_command, opts_codes, NULL);
+        if (ret == 200 || ret == 202)
             s->utf8 = 1;
     }
 
@@ -653,7 +656,7 @@ static int ftp_abort(URLContext *h)
 
 static int ftp_connect(URLContext *h, const char *url)
 {
-    char proto[10], path[MAX_URL_SIZE], credencials[MAX_URL_SIZE], hostname[MAX_URL_SIZE];
+    char proto[10], path[MAX_URL_SIZE], credentials[MAX_URL_SIZE], hostname[MAX_URL_SIZE];
     const char *tok_user = NULL, *tok_pass = NULL;
     char *end = NULL, *newpath = NULL;
     int err;
@@ -666,17 +669,24 @@ static int ftp_connect(URLContext *h, const char *url)
     s->features = NULL;
 
     av_url_split(proto, sizeof(proto),
-                 credencials, sizeof(credencials),
+                 credentials, sizeof(credentials),
                  hostname, sizeof(hostname),
                  &s->server_control_port,
                  path, sizeof(path),
                  url);
 
-    tok_user = av_strtok(credencials, ":", &end);
+    tok_user = av_strtok(credentials, ":", &end);
     tok_pass = av_strtok(end, ":", &end);
     if (!tok_user) {
-        tok_user = "anonymous";
-        tok_pass = av_x_if_null(s->anonymous_password, "nopassword");
+        if (!s->option_user) {
+            tok_user = "anonymous";
+            tok_pass = av_x_if_null(s->anonymous_password, "nopassword");
+        } else {
+            tok_user = s->option_user;
+        }
+    }
+    if (!tok_pass) {
+        tok_pass = s->option_password;
     }
     s->user = av_strdup(tok_user);
     s->password = av_strdup(tok_pass);
@@ -783,13 +793,13 @@ static int ftp_read(URLContext *h, unsigned char *buf, int size)
     if (s->state == DISCONNECTED) {
         /* optimization */
         if (s->position >= s->filesize)
-            return 0;
+            return AVERROR_EOF;
         if ((err = ftp_connect_data_connection(h)) < 0)
             return err;
     }
     if (s->state == READY) {
         if (s->position >= s->filesize)
-            return 0;
+            return AVERROR_EOF;
         if ((err = ftp_retrieve(s)) < 0)
             return err;
     }