FFmpeg
Loading...
Searching...
No Matches
ftp.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 Lukasz Marek <lukasz.m.luki@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <string.h>
22#include <time.h>
23
24#include "libavutil/avstring.h"
25#include "libavutil/internal.h"
26#include "libavutil/mem.h"
28#include "avformat.h"
29#include "internal.h"
30#include "url.h"
31#include "urldecode.h"
32#include "libavutil/opt.h"
33#include "libavutil/bprint.h"
34
35#define CONTROL_BUFFER_SIZE 1024
36#define DIR_BUFFER_SIZE 4096
37
47
53
54typedef struct {
55 const AVClass *class;
56 URLContext *conn_control; /**< Control connection */
57 URLContext *conn_data; /**< Data connection, NULL when not connected */
58 uint8_t control_buffer[CONTROL_BUFFER_SIZE]; /**< Control connection buffer */
60 int server_data_port; /**< Data connection port opened by server, -1 on error. */
61 int server_control_port; /**< Control connection port, default is 21 */
62 char *hostname; /**< Server address. */
63 char *user; /**< Server user */
64 char *password; /**< Server user's password */
65 char *path; /**< Path to resource on server. */
66 int64_t filesize; /**< Size of file on server, -1 on error. */
67 int64_t position; /**< Current position, calculated. */
68 int rw_timeout; /**< Network timeout. */
69 const char *anonymous_password; /**< Password to be used for anonymous user. An email should be used. */
70 int write_seekable; /**< Control seekability, 0 = disable, 1 = enable. */
71 FTPState state; /**< State of data connection */
72 FTPListingMethod listing_method; /**< Called listing method */
73 char *features; /**< List of server's features represented as raw response */
77 int utf8;
78 const char *option_user; /**< User to be used if none given in the URL */
79 const char *option_password; /**< Password to be used if none given in the URL */
81
82#define OFFSET(x) offsetof(FTPContext, x)
83#define D AV_OPT_FLAG_DECODING_PARAM
84#define E AV_OPT_FLAG_ENCODING_PARAM
85static const AVOption options[] = {
86 {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
87 {"ftp-write-seekable", "control seekability of connection during encoding", OFFSET(write_seekable), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
88 {"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 },
89 {"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 },
90 {"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 },
91 {NULL}
92};
93
94static const AVClass ftp_context_class = {
95 .class_name = "ftp",
96 .item_name = av_default_item_name,
97 .option = options,
98 .version = LIBAVUTIL_VERSION_INT,
99};
100
101static int ftp_close(URLContext *h);
102
103static int is_bad_string(const unsigned char *s)
104{
105 while(*s) {
106 if (*s < 0x20 || *s == 0x7F || *s == 0xFF)
107 return 1;
108 s++;
109 }
110 return 0;
111}
112
114{
115 int len;
116 if (s->control_buf_ptr >= s->control_buf_end) {
117 len = ffurl_read(s->conn_control, s->control_buffer, CONTROL_BUFFER_SIZE);
118 if (len < 0) {
119 return len;
120 } else if (!len) {
121 return -1;
122 } else {
123 s->control_buf_ptr = s->control_buffer;
124 s->control_buf_end = s->control_buffer + len;
125 }
126 }
127 return *s->control_buf_ptr++;
128}
129
130static int ftp_get_line(FTPContext *s, char *line, int line_size)
131{
132 int ch;
133 char *q = line;
134
135 for (;;) {
136 ch = ftp_getc(s);
137 if (ch < 0) {
138 return ch;
139 }
140 if (ch == '\n') {
141 /* process line */
142 if (q > line && q[-1] == '\r')
143 q--;
144 *q = '\0';
145 return 0;
146 } else {
147 if ((q - line) < line_size - 1)
148 *q++ = ch;
149 }
150 }
151}
152
153/*
154 * This routine returns ftp server response code.
155 * Server may send more than one response for a certain command.
156 * First expected code is returned.
157 */
158static int ftp_status(FTPContext *s, char **line, const int response_codes[])
159{
160 int err, i, dash = 0, result = 0, code_found = 0, linesize;
161 char buf[CONTROL_BUFFER_SIZE];
162 AVBPrint line_buffer;
163
164 if (line)
166
167 while (!code_found || dash) {
168 if ((err = ftp_get_line(s, buf, sizeof(buf))) < 0) {
169 if (line)
170 av_bprint_finalize(&line_buffer, NULL);
171 return err;
172 }
173
174 av_log(s, AV_LOG_DEBUG, "%s\n", buf);
175
176 linesize = strlen(buf);
177 err = 0;
178 if (linesize >= 3) {
179 for (i = 0; i < 3; ++i) {
180 if (buf[i] < '0' || buf[i] > '9') {
181 err = 0;
182 break;
183 }
184 err *= 10;
185 err += buf[i] - '0';
186 }
187 }
188
189 if (!code_found) {
190 if (err >= 500) {
191 code_found = 1;
192 result = err;
193 } else
194 for (i = 0; response_codes[i]; ++i) {
195 if (err == response_codes[i]) {
196 code_found = 1;
197 result = err;
198 break;
199 }
200 }
201 }
202 if (code_found) {
203 if (line)
204 av_bprintf(&line_buffer, "%s\r\n", buf);
205 if (linesize >= 4) {
206 if (!dash && buf[3] == '-')
207 dash = err;
208 else if (err == dash && buf[3] == ' ')
209 dash = 0;
210 }
211 }
212 }
213
214 if (line)
215 av_bprint_finalize(&line_buffer, line);
216 return result;
217}
218
219static int ftp_send_command(FTPContext *s, const char *command,
220 const int response_codes[], char **response)
221{
222 int err;
223
224 ff_dlog(s, "%s", command);
225
226 if (response)
227 *response = NULL;
228
229 if (!s->conn_control)
230 return AVERROR(EIO);
231
232 if ((err = ffurl_write(s->conn_control, command, strlen(command))) < 0)
233 return err;
234 if (!err)
235 return -1;
236
237 /* return status */
238 if (response_codes) {
239 return ftp_status(s, response, response_codes);
240 }
241 return 0;
242}
243
245{
246 ffurl_closep(&s->conn_data);
247 s->state = DISCONNECTED;
248}
249
251{
252 ffurl_closep(&s->conn_control);
254}
255
257{
258 char buf[CONTROL_BUFFER_SIZE];
259 int err;
260 static const int user_codes[] = {331, 230, 0};
261 static const int pass_codes[] = {230, 0};
262
263 if (is_bad_string(s->user))
264 return AVERROR(EINVAL);
265 err = snprintf(buf, sizeof(buf), "USER %s\r\n", s->user);
266 if (err >= sizeof(buf))
267 return AVERROR(ENOSYS);
268
269 err = ftp_send_command(s, buf, user_codes, NULL);
270 if (err == 331) {
271 if (s->password) {
272 if (is_bad_string(s->password))
273 return AVERROR(EINVAL);
274 err = snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password);
275 if (err >= sizeof(buf))
276 return AVERROR(ENOSYS);
277
278 err = ftp_send_command(s, buf, pass_codes, NULL);
279 } else
280 return AVERROR(EACCES);
281 }
282 if (err != 230)
283 return AVERROR(EACCES);
284
285 return 0;
286}
287
289{
290 char *res = NULL, *start = NULL, *end = NULL;
291 int i;
292 static const char d = '|';
293 static const char *command = "EPSV\r\n";
294 static const int epsv_codes[] = {229, 0};
295
296 if (ftp_send_command(s, command, epsv_codes, &res) != 229 || !res)
297 goto fail;
298
299 for (i = 0; res[i]; ++i) {
300 if (res[i] == '(') {
301 start = res + i + 1;
302 } else if (res[i] == ')') {
303 end = res + i;
304 break;
305 }
306 }
307 if (!start || !end)
308 goto fail;
309
310 *end = '\0';
311 if (strlen(start) < 5)
312 goto fail;
313 if (start[0] != d || start[1] != d || start[2] != d || end[-1] != d)
314 goto fail;
315 start += 3;
316 end[-1] = '\0';
317
318 s->server_data_port = atoi(start);
319 ff_dlog(s, "Server data port: %d\n", s->server_data_port);
320
321 av_free(res);
322 return 0;
323
324 fail:
325 av_free(res);
326 s->server_data_port = -1;
327 return AVERROR(ENOSYS);
328}
329
331{
332 char *res = NULL, *start = NULL, *end = NULL;
333 int i;
334 static const char *command = "PASV\r\n";
335 static const int pasv_codes[] = {227, 0};
336
337 if (ftp_send_command(s, command, pasv_codes, &res) != 227 || !res)
338 goto fail;
339
340 for (i = 0; res[i]; ++i) {
341 if (res[i] == '(') {
342 start = res + i + 1;
343 } else if (res[i] == ')') {
344 end = res + i;
345 break;
346 }
347 }
348 if (!start || !end)
349 goto fail;
350
351 *end = '\0';
352 /* skip ip */
353 if (!av_strtok(start, ",", &end)) goto fail;
354 if (!av_strtok(NULL, ",", &end)) goto fail;
355 if (!av_strtok(NULL, ",", &end)) goto fail;
356 if (!av_strtok(NULL, ",", &end)) goto fail;
357
358 /* parse port number */
359 start = av_strtok(NULL, ",", &end);
360 if (!start) goto fail;
361 s->server_data_port = atoi(start) * 256;
362 start = av_strtok(NULL, ",", &end);
363 if (!start) goto fail;
364 s->server_data_port += atoi(start);
365 ff_dlog(s, "Server data port: %d\n", s->server_data_port);
366
367 av_free(res);
368 return 0;
369
370 fail:
371 av_free(res);
372 s->server_data_port = -1;
373 return AVERROR(EIO);
374}
375
377{
378 char *res = NULL, *start = NULL, *end = NULL;
379 int i;
380 static const char *command = "PWD\r\n";
381 static const int pwd_codes[] = {257, 0};
382
383 if (ftp_send_command(s, command, pwd_codes, &res) != 257 || !res)
384 goto fail;
385
386 for (i = 0; res[i]; ++i) {
387 if (res[i] == '"') {
388 if (!start) {
389 start = res + i + 1;
390 continue;
391 }
392 end = res + i;
393 break;
394 }
395 }
396
397 if (!end)
398 goto fail;
399
400 *end = '\0';
401 s->path = av_strdup(start);
402
403 av_free(res);
404
405 if (!s->path)
406 return AVERROR(ENOMEM);
407 return 0;
408
409 fail:
410 av_free(res);
411 return AVERROR(EIO);
412}
413
415{
417 char *res = NULL;
418 int ret;
419 static const int size_codes[] = {213, 0};
420
421 ret = snprintf(command, sizeof(command), "SIZE %s\r\n", s->path);
422 if (ret >= sizeof(command))
423 return AVERROR(ENOSYS);
424
425 if (ftp_send_command(s, command, size_codes, &res) == 213 && res && strlen(res) > 4) {
426 s->filesize = strtoll(&res[4], NULL, 10);
427 } else {
428 s->filesize = -1;
429 av_free(res);
430 return AVERROR(EIO);
431 }
432
433 av_free(res);
434 return 0;
435}
436
438{
440 static const int retr_codes[] = {150, 125, 0};
441 int resp_code, ret;
442
443 ret = snprintf(command, sizeof(command), "RETR %s\r\n", s->path);
444 if (ret >= sizeof(command))
445 return AVERROR(ENOSYS);
446
447 resp_code = ftp_send_command(s, command, retr_codes, NULL);
448 if (resp_code != 125 && resp_code != 150)
449 return AVERROR(EIO);
450
451 s->state = DOWNLOADING;
452
453 return 0;
454}
455
457{
459 static const int stor_codes[] = {150, 125, 0};
460 int resp_code, ret;
461
462 ret = snprintf(command, sizeof(command), "STOR %s\r\n", s->path);
463 if (ret >= sizeof(command))
464 return AVERROR(ENOSYS);
465
466 resp_code = ftp_send_command(s, command, stor_codes, NULL);
467 if (resp_code != 125 && resp_code != 150)
468 return AVERROR(EIO);
469
470 s->state = UPLOADING;
471
472 return 0;
473}
474
476{
477 static const char *command = "TYPE I\r\n";
478 static const int type_codes[] = {200, 0};
479
480 if (ftp_send_command(s, command, type_codes, NULL) != 200)
481 return AVERROR(EIO);
482
483 return 0;
484}
485
487{
489 static const int rest_codes[] = {350, 0};
490
491 snprintf(command, sizeof(command), "REST %"PRId64"\r\n", pos);
492 if (ftp_send_command(s, command, rest_codes, NULL) != 350)
493 return AVERROR(EIO);
494
495 return 0;
496}
497
499{
500 static const int cwd_codes[] = {250, 550, 0}; /* 550 is incorrect code */
501 char command[MAX_URL_SIZE];
502 int ret;
503
504 ret = snprintf(command, sizeof(command), "CWD %s\r\n", s->path);
505 if (ret >= sizeof(command))
506 return AVERROR(ENOSYS);
507
508 if (ftp_send_command(s, command, cwd_codes, NULL) != 250)
509 return AVERROR(EIO);
510 return 0;
511}
512
514{
515 static const char *command = "MLSD\r\n";
516 static const int mlsd_codes[] = {150, 125, 500, 0}; /* 500 is incorrect code */
517 int resp_code = ftp_send_command(s, command, mlsd_codes, NULL);
518
519 if (resp_code != 150 && resp_code != 125)
520 return AVERROR(ENOSYS);
521 s->listing_method = MLSD;
522 return 0;
523}
524
526{
527 static const char *command = "NLST\r\n";
528 static const int nlst_codes[] = {226, 425, 426, 451, 450, 550, 0};
529
530 if (ftp_send_command(s, command, nlst_codes, NULL) != 226)
531 return AVERROR(ENOSYS);
532 s->listing_method = NLST;
533 return 0;
534}
535
537{
538 int ret;
539 s->state = LISTING_DIR;
540
541 if ((ret = ftp_list_mlsd(s)) < 0)
543
544 return ret;
545}
546
547static int ftp_has_feature(FTPContext *s, const char *feature_name)
548{
549 if (!s->features)
550 return 0;
551
552 return av_stristr(s->features, feature_name) != NULL;
553}
554
556{
557 static const char *feat_command = "FEAT\r\n";
558 static const char *enable_utf8_command = "OPTS UTF8 ON\r\n";
559 static const int feat_codes[] = {211, 0};
560 static const int opts_codes[] = {200, 202, 451, 0};
561
562 av_freep(&s->features);
563 if (ftp_send_command(s, feat_command, feat_codes, &s->features) != 211) {
564 av_freep(&s->features);
565 }
566
567 if (ftp_has_feature(s, "UTF8")) {
568 int ret = ftp_send_command(s, enable_utf8_command, opts_codes, NULL);
569 if (ret == 200 || ret == 202)
570 s->utf8 = 1;
571 }
572
573 return 0;
574}
575
577{
578 char buf[CONTROL_BUFFER_SIZE], *response = NULL;
579 int err;
581 FTPContext *s = h->priv_data;
582 static const int connect_codes[] = {220, 0};
583
584 if (!s->conn_control) {
585 ff_url_join(buf, sizeof(buf), "tcp", NULL,
586 s->hostname, s->server_control_port, NULL);
587 if (s->rw_timeout != -1) {
588 av_dict_set_int(&opts, "timeout", s->rw_timeout, 0);
589 } /* if option is not given, don't pass it and let tcp use its own default */
590 err = ffurl_open_whitelist(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
591 &h->interrupt_callback, &opts,
592 h->protocol_whitelist, h->protocol_blacklist, h);
594 if (err < 0) {
595 av_log(h, AV_LOG_ERROR, "Cannot open control connection\n");
596 return err;
597 }
598
599 /* check if server is ready */
600 if (ftp_status(s, ((h->flags & AVIO_FLAG_WRITE) ? &response : NULL), connect_codes) != 220) {
601 av_log(h, AV_LOG_ERROR, "FTP server not ready for new users\n");
602 return AVERROR(EACCES);
603 }
604
605 if ((h->flags & AVIO_FLAG_WRITE) && av_stristr(response, "pure-ftpd")) {
606 av_log(h, AV_LOG_WARNING, "Pure-FTPd server is used as an output protocol. It is known issue this implementation may produce incorrect content and it cannot be fixed at this moment.");
607 }
608 av_free(response);
609
610 if ((err = ftp_auth(s)) < 0) {
611 av_log(h, AV_LOG_ERROR, "FTP authentication failed\n");
612 return err;
613 }
614
615 if ((err = ftp_type(s)) < 0) {
616 av_log(h, AV_LOG_ERROR, "Set content type failed\n");
617 return err;
618 }
619
621 }
622 return 0;
623}
624
626{
627 int err;
628 char buf[CONTROL_BUFFER_SIZE];
630 FTPContext *s = h->priv_data;
631
632 if (!s->conn_data) {
633 /* Enter passive mode */
634 if (ftp_passive_mode_epsv(s) < 0) {
635 /* Use PASV as fallback */
636 if ((err = ftp_passive_mode(s)) < 0)
637 return err;
638 }
639 /* Open data connection */
640 ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, s->server_data_port, NULL);
641 if (s->rw_timeout != -1) {
642 av_dict_set_int(&opts, "timeout", s->rw_timeout, 0);
643 } /* if option is not given, don't pass it and let tcp use its own default */
644 err = ffurl_open_whitelist(&s->conn_data, buf, h->flags,
645 &h->interrupt_callback, &opts,
646 h->protocol_whitelist, h->protocol_blacklist, h);
648 if (err < 0)
649 return err;
650
651 if (s->position)
652 if ((err = ftp_restart(s, s->position)) < 0)
653 return err;
654 }
655 s->state = READY;
656 return 0;
657}
658
660{
661 static const char *command = "ABOR\r\n";
662 int err;
663 static const int abor_codes[] = {225, 226, 0};
664 FTPContext *s = h->priv_data;
665
666 /* According to RCF 959:
667 "ABOR command tells the server to abort the previous FTP
668 service command and any associated transfer of data."
669
670 There are FTP server implementations that don't response
671 to any commands during data transfer in passive mode (including ABOR).
672
673 This implementation closes data connection by force.
674 */
675
676 if (ftp_send_command(s, command, NULL, NULL) < 0) {
678 if ((err = ftp_connect_control_connection(h)) < 0) {
679 av_log(h, AV_LOG_ERROR, "Reconnect failed.\n");
680 return err;
681 }
682 } else {
684 if (ftp_status(s, NULL, abor_codes) < 225) {
685 /* wu-ftpd also closes control connection after data connection closing */
686 ffurl_closep(&s->conn_control);
687 if ((err = ftp_connect_control_connection(h)) < 0) {
688 av_log(h, AV_LOG_ERROR, "Reconnect failed.\n");
689 return err;
690 }
691 }
692 }
693
694 return 0;
695}
696
697static int ftp_connect(URLContext *h, const char *url)
698{
699 char proto[10], path[MAX_URL_SIZE], credentials[MAX_URL_SIZE], hostname[MAX_URL_SIZE];
700 const char *tok_user = NULL, *tok_pass = NULL;
701 char *newpath = NULL;
702 int err;
703 FTPContext *s = h->priv_data;
704
705 s->state = DISCONNECTED;
706 s->listing_method = UNKNOWN_METHOD;
707 s->filesize = -1;
708 s->position = 0;
709 s->features = NULL;
710
711 av_url_split(proto, sizeof(proto),
712 credentials, sizeof(credentials),
713 hostname, sizeof(hostname),
714 &s->server_control_port,
715 path, sizeof(path),
716 url);
717
718 if (!*credentials) {
719 if (!s->option_user) {
720 tok_user = "anonymous";
721 tok_pass = av_x_if_null(s->anonymous_password, "nopassword");
722 } else {
723 tok_user = s->option_user;
724 tok_pass = s->option_password;
725 }
726 s->user = av_strdup(tok_user);
727 s->password = av_strdup(tok_pass);
728 } else {
729 char *pass = strchr(credentials, ':');
730 if (pass) {
731 *pass++ = '\0';
732 tok_pass = pass;
733 s->password = ff_urldecode(pass, 0);
734 } else {
735 tok_pass = s->option_password;
736 s->password = av_strdup(tok_pass);
737 }
738 s->user = ff_urldecode(credentials, 0);
739 }
740 s->hostname = av_strdup(hostname);
741 if (!s->hostname || !s->user || (tok_pass && !s->password)) {
742 return AVERROR(ENOMEM);
743 }
744
745 if (s->server_control_port < 0 || s->server_control_port > 65535)
746 s->server_control_port = 21;
747
748 if ((err = ftp_connect_control_connection(h)) < 0)
749 return err;
750
751 if ((err = ftp_current_dir(s)) < 0)
752 return err;
753
754 newpath = av_append_path_component(s->path, path);
755 if (!newpath)
756 return AVERROR(ENOMEM);
757 av_free(s->path);
758 s->path = newpath;
759
760 if (is_bad_string(s->path)) {
761 av_log(h, AV_LOG_ERROR, "Path contains non-printable characters\n");
762 return AVERROR(EINVAL);
763 }
764
765 return 0;
766}
767
768static int ftp_open(URLContext *h, const char *url, int flags)
769{
770 FTPContext *s = h->priv_data;
771 int err;
772
773 ff_dlog(h, "ftp protocol open\n");
774
775 if ((err = ftp_connect(h, url)) < 0)
776 goto fail;
777
778 if (ftp_restart(s, 0) < 0) {
779 h->is_streamed = 1;
780 } else {
782 if (s->write_seekable != 1 && flags & AVIO_FLAG_WRITE)
783 h->is_streamed = 1;
784 }
785
786 return 0;
787
788 fail:
789 av_log(h, AV_LOG_ERROR, "FTP open failed\n");
790 ftp_close(h);
791 return err;
792}
793
794static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
795{
796 FTPContext *s = h->priv_data;
797 int err;
798 int64_t new_pos;
799
800 ff_dlog(h, "ftp protocol seek %"PRId64" %d\n", pos, whence);
801
802 switch(whence) {
803 case AVSEEK_SIZE:
804 return s->filesize;
805 case SEEK_SET:
806 new_pos = pos;
807 break;
808 case SEEK_CUR:
809 new_pos = s->position + pos;
810 break;
811 case SEEK_END:
812 if (s->filesize < 0)
813 return AVERROR(EIO);
814 new_pos = s->filesize + pos;
815 break;
816 default:
817 return AVERROR(EINVAL);
818 }
819
820 if (h->is_streamed)
821 return AVERROR(EIO);
822
823 if (new_pos < 0) {
824 av_log(h, AV_LOG_ERROR, "Seeking to negative position.\n");
825 return AVERROR(EINVAL);
826 }
827
828 if (new_pos != s->position) {
829 if ((err = ftp_abort(h)) < 0)
830 return err;
831 s->position = new_pos;
832 }
833 return new_pos;
834}
835
836static int ftp_read(URLContext *h, unsigned char *buf, int size)
837{
838 FTPContext *s = h->priv_data;
839 int read, err, retry_done = 0;
840
841 ff_dlog(h, "ftp protocol read %d bytes\n", size);
842 retry:
843 if (s->state == ENDOFFILE)
844 return AVERROR_EOF;
845 if (s->state == DISCONNECTED) {
846 if ((err = ftp_connect_data_connection(h)) < 0)
847 return err;
848 }
849 if (s->state == READY) {
850 if ((err = ftp_retrieve(s)) < 0)
851 return err;
852 }
853 if (s->conn_data && s->state == DOWNLOADING) {
854 read = ffurl_read(s->conn_data, buf, size);
855 if (read >= 0) {
856 s->position += read;
857 s->filesize = FFMAX(s->filesize, s->position);
858 }
859 if (read == AVERROR_EOF) {
860 static const int retr_codes[] = {226, 250, 425, 426, 451, 0};
861 char *response = NULL;
862 err = ftp_status(s, &response, retr_codes);
863 if (err == 226) {
865 av_freep(&response);
866 s->state = ENDOFFILE;
867 return AVERROR_EOF;
868 }
869 /* 250 is not allowed, any other status means some kind of error */
870 av_log(h, AV_LOG_ERROR, "FTP transfer failed: %s\n", response ? response : (err < 0 ? av_err2str(err) : "?"));
871 av_freep(&response);
872 read = AVERROR(EIO);
873 }
874 if (read <= 0 && !h->is_streamed) {
875 /* Server closed connection. Probably due to inactivity */
876 av_log(h, AV_LOG_INFO, "Reconnect to FTP server.\n");
877 if ((err = ftp_abort(h)) < 0)
878 return err;
879 if (!retry_done) {
880 retry_done = 1;
881 goto retry;
882 }
883 }
884 return read;
885 }
886
887 av_log(h, AV_LOG_DEBUG, "FTP read failed\n");
888 return AVERROR(EIO);
889}
890
891static int ftp_write(URLContext *h, const unsigned char *buf, int size)
892{
893 int err;
894 FTPContext *s = h->priv_data;
895 int written;
896
897 ff_dlog(h, "ftp protocol write %d bytes\n", size);
898
899 if (s->state == DISCONNECTED) {
900 if ((err = ftp_connect_data_connection(h)) < 0)
901 return err;
902 }
903 if (s->state == READY) {
904 if ((err = ftp_store(s)) < 0)
905 return err;
906 }
907 if (s->conn_data && s->state == UPLOADING) {
908 written = ffurl_write(s->conn_data, buf, size);
909 if (written > 0) {
910 s->position += written;
911 s->filesize = FFMAX(s->filesize, s->position);
912 }
913 return written;
914 }
915
916 av_log(h, AV_LOG_ERROR, "FTP write failed\n");
917 return AVERROR(EIO);
918}
919
921{
922 FTPContext *s = h->priv_data;
923
924 ff_dlog(h, "ftp protocol close\n");
925
927 av_freep(&s->user);
928 av_freep(&s->password);
929 av_freep(&s->hostname);
930 av_freep(&s->path);
931 av_freep(&s->features);
932
933 return 0;
934}
935
937{
938 FTPContext *s = h->priv_data;
939
940 ff_dlog(h, "ftp protocol get_file_handle\n");
941
942 if (s->conn_data)
943 return ffurl_get_file_handle(s->conn_data);
944
945 return AVERROR(EIO);
946}
947
949{
950 FTPContext *s = h->priv_data;
951
952 ff_dlog(h, "ftp protocol shutdown\n");
953
954 if (s->conn_data)
955 return ffurl_shutdown(s->conn_data, flags);
956
957 return AVERROR(EIO);
958}
959
961{
962 FTPContext *s = h->priv_data;
963 int ret;
964
965 if ((ret = ftp_connect(h, h->filename)) < 0)
966 goto fail;
967 if ((ret = ftp_set_dir(s)) < 0)
968 goto fail;
969 if ((ret = ftp_connect_data_connection(h)) < 0)
970 goto fail;
971 if ((ret = ftp_list(s)) < 0)
972 goto fail;
973 s->dir_buffer = av_malloc(DIR_BUFFER_SIZE);
974 if (!s->dir_buffer) {
975 ret = AVERROR(ENOMEM);
976 goto fail;
977 }
978 s->dir_buffer[0] = 0;
979 if (s->conn_data && s->state == LISTING_DIR)
980 return 0;
981 fail:
982 ffurl_closep(&s->conn_control);
983 ffurl_closep(&s->conn_data);
984 return ret;
985}
986
987static int64_t ftp_parse_date(const char *date)
988{
989 struct tm tv;
990 memset(&tv, 0, sizeof(struct tm));
991 av_small_strptime(date, "%Y%m%d%H%M%S", &tv);
992 return INT64_C(1000000) * av_timegm(&tv);
993}
994
995static int ftp_parse_entry_nlst(char *line, AVIODirEntry *next)
996{
997 next->name = av_strdup(line);
998 return next->name ? 0 : AVERROR(ENOMEM);
999}
1000
1001static int ftp_parse_entry_mlsd(char *mlsd, AVIODirEntry *next)
1002{
1003 char *fact, *value;
1004 char *saveptr = NULL, *p = mlsd;
1005 ff_dlog(NULL, "%s\n", mlsd);
1006 while(fact = av_strtok(p, ";", &saveptr)) {
1007 p = NULL;
1008 if (fact[0] == ' ') {
1009 if (!(next->name = av_strdup(&fact[1])))
1010 return AVERROR(ENOMEM);
1011 continue;
1012 }
1013 fact = av_strtok(fact, "=", &value);
1014 if (!fact)
1015 continue;
1016 if (!av_strcasecmp(fact, "type")) {
1017 if (!av_strcasecmp(value, "cdir") || !av_strcasecmp(value, "pdir"))
1018 return 1;
1019 if (!av_strcasecmp(value, "dir"))
1020 next->type = AVIO_ENTRY_DIRECTORY;
1021 else if (!av_strcasecmp(value, "file"))
1022 next->type = AVIO_ENTRY_FILE;
1023 else if (!av_strcasecmp(value, "OS.unix=slink:"))
1025 } else if (!av_strcasecmp(fact, "modify")) {
1027 } else if (!av_strcasecmp(fact, "UNIX.mode")) {
1028 next->filemode = strtoumax(value, NULL, 8);
1029 } else if (!av_strcasecmp(fact, "UNIX.uid") || !av_strcasecmp(fact, "UNIX.owner"))
1030 next->user_id = strtoumax(value, NULL, 10);
1031 else if (!av_strcasecmp(fact, "UNIX.gid") || !av_strcasecmp(fact, "UNIX.group"))
1032 next->group_id = strtoumax(value, NULL, 10);
1033 else if (!av_strcasecmp(fact, "size") || !av_strcasecmp(fact, "sizd"))
1034 next->size = strtoll(value, NULL, 10);
1035 }
1036 return 0;
1037}
1038
1039/**
1040 * @return 0 on success, negative on error, positive on entry to discard.
1041 */
1043{
1044 FTPContext *s = h->priv_data;
1045
1046 switch (s->listing_method) {
1047 case MLSD:
1048 return ftp_parse_entry_mlsd(line, next);
1049 case NLST:
1050 return ftp_parse_entry_nlst(line, next);
1051 case UNKNOWN_METHOD:
1052 default:
1053 return -1;
1054 }
1055}
1056
1058{
1059 FTPContext *s = h->priv_data;
1060 char *start, *found;
1061 int ret, retried;
1062
1063 do {
1064 retried = 0;
1065 start = s->dir_buffer + s->dir_buffer_offset;
1066 while (!(found = strstr(start, "\n"))) {
1067 if (retried)
1068 return AVERROR(EIO);
1069 s->dir_buffer_size -= s->dir_buffer_offset;
1070 s->dir_buffer_offset = 0;
1071 if (s->dir_buffer_size)
1072 memmove(s->dir_buffer, start, s->dir_buffer_size);
1073 ret = ffurl_read(s->conn_data, s->dir_buffer + s->dir_buffer_size, DIR_BUFFER_SIZE - (s->dir_buffer_size + 1));
1074 if (ret < 0 && ret != AVERROR_EOF)
1075 return ret;
1076 if (ret <= 0) {
1077 *next = NULL;
1078 return 0;
1079 }
1080 s->dir_buffer_size += ret;
1081 s->dir_buffer[s->dir_buffer_size] = 0;
1082 start = s->dir_buffer;
1083 retried = 1;
1084 }
1085 s->dir_buffer_offset += (found + 1 - start);
1086 found[0] = 0;
1087 if (found > start && found[-1] == '\r')
1088 found[-1] = 0;
1089
1090 *next = ff_alloc_dir_entry();
1091 if (!*next)
1092 return AVERROR(ENOMEM);
1093 (*next)->utf8 = s->utf8;
1094 ret = ftp_parse_entry(h, start, *next);
1095 if (ret) {
1097 if (ret < 0)
1098 return ret;
1099 }
1100 } while (ret > 0);
1101 return 0;
1102}
1103
1105{
1106 FTPContext *s = h->priv_data;
1107 av_freep(&s->dir_buffer);
1108 ffurl_closep(&s->conn_control);
1109 ffurl_closep(&s->conn_data);
1110 return 0;
1111}
1112
1114{
1115 FTPContext *s = h->priv_data;
1116 char command[MAX_URL_SIZE];
1117 static const int del_codes[] = {250, 421, 450, 500, 501, 502, 530, 550, 0};
1118 static const int rmd_codes[] = {250, 421, 500, 501, 502, 530, 550, 0};
1119 int ret;
1120
1121 if ((ret = ftp_connect(h, h->filename)) < 0)
1122 goto cleanup;
1123
1124 ret = snprintf(command, sizeof(command), "DELE %s\r\n", s->path);
1125 if (ret >= sizeof(command)) {
1126 ret = AVERROR(ENOSYS);
1127 goto cleanup;
1128 }
1129
1130 if (ftp_send_command(s, command, del_codes, NULL) == 250) {
1131 ret = 0;
1132 goto cleanup;
1133 }
1134
1135 ret = snprintf(command, sizeof(command), "RMD %s\r\n", s->path);
1136 if (ret >= sizeof(command)) {
1137 ret = AVERROR(ENOSYS);
1138 goto cleanup;
1139 }
1140
1141 if (ftp_send_command(s, command, rmd_codes, NULL) == 250)
1142 ret = 0;
1143 else
1144 ret = AVERROR(EIO);
1145
1146cleanup:
1147 ftp_close(h);
1148 return ret;
1149}
1150
1151static int ftp_move(URLContext *h_src, URLContext *h_dst)
1152{
1153 FTPContext *s = h_src->priv_data;
1155 static const int rnfr_codes[] = {350, 421, 450, 500, 501, 502, 503, 530, 0};
1156 static const int rnto_codes[] = {250, 421, 500, 501, 502, 503, 530, 532, 553, 0};
1157 int ret;
1158
1159 if ((ret = ftp_connect(h_src, h_src->filename)) < 0)
1160 goto cleanup;
1161
1162 ret = snprintf(command, sizeof(command), "RNFR %s\r\n", s->path);
1163 if (ret >= sizeof(command)) {
1164 ret = AVERROR(ENOSYS);
1165 goto cleanup;
1166 }
1167
1168 if (ftp_send_command(s, command, rnfr_codes, NULL) != 350) {
1169 ret = AVERROR(EIO);
1170 goto cleanup;
1171 }
1172
1173 av_url_split(0, 0, 0, 0, 0, 0, 0,
1174 path, sizeof(path),
1175 h_dst->filename);
1176 if (is_bad_string(path)) {
1177 ret = AVERROR(EINVAL);
1178 goto cleanup;
1179 }
1180 ret = snprintf(command, sizeof(command), "RNTO %s\r\n", path);
1181 if (ret >= sizeof(command)) {
1182 ret = AVERROR(ENOSYS);
1183 goto cleanup;
1184 }
1185
1186 if (ftp_send_command(s, command, rnto_codes, NULL) == 250)
1187 ret = 0;
1188 else
1189 ret = AVERROR(EIO);
1190
1191cleanup:
1192 ftp_close(h_src);
1193 return ret;
1194}
1195
1197 .name = "ftp",
1198 .url_open = ftp_open,
1199 .url_read = ftp_read,
1200 .url_write = ftp_write,
1201 .url_seek = ftp_seek,
1202 .url_close = ftp_close,
1203 .url_get_file_handle = ftp_get_file_handle,
1204 .url_shutdown = ftp_shutdown,
1205 .priv_data_size = sizeof(FTPContext),
1206 .priv_data_class = &ftp_context_class,
1207 .url_open_dir = ftp_open_dir,
1208 .url_read_dir = ftp_read_dir,
1209 .url_close_dir = ftp_close_dir,
1210 .url_delete = ftp_delete,
1211 .url_move = ftp_move,
1213 .default_whitelist = "tcp",
1214};
static double fact(double i)
Definition af_aiir.c:936
static AVDictionary * opts
#define E
Definition avdct.c:34
#define D
Definition avdct.c:35
Main libavformat public API header.
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition avio.c:927
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
Definition avio.c:466
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition avio.c:663
void avio_free_directory_entry(AVIODirEntry **entry)
Free entry allocated by avio_read_dir().
Definition avio.c:871
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition avio.c:894
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
Definition avio.h:481
#define AVIO_FLAG_WRITE
write-only
Definition avio.h:631
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition avio.h:632
@ AVIO_ENTRY_SYMBOLIC_LINK
Definition avio.h:73
@ AVIO_ENTRY_DIRECTORY
Definition avio.h:71
@ AVIO_ENTRY_FILE
Definition avio.h:75
static uint32_t BS_FUNC read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:121
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
AVBPrint public header.
#define AV_BPRINT_SIZE_AUTOMATIC
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
double value
Definition eval.c:102
char * path
Definition ffplay.c:385
int ret
Definition ffplay.c:391
static av_cold void cleanup(FlashSV2Context *s)
static int ftp_connect(URLContext *h, const char *url)
Definition ftp.c:697
static const AVClass ftp_context_class
Definition ftp.c:94
static int ftp_shutdown(URLContext *h, int flags)
Definition ftp.c:948
static int ftp_read_dir(URLContext *h, AVIODirEntry **next)
Definition ftp.c:1057
static void ftp_close_data_connection(FTPContext *s)
Definition ftp.c:244
static int ftp_store(FTPContext *s)
Definition ftp.c:456
static int ftp_file_size(FTPContext *s)
Definition ftp.c:414
static int ftp_set_dir(FTPContext *s)
Definition ftp.c:498
static int ftp_close(URLContext *h)
Definition ftp.c:920
static int ftp_connect_data_connection(URLContext *h)
Definition ftp.c:625
static int ftp_getc(FTPContext *s)
Definition ftp.c:113
static int ftp_get_file_handle(URLContext *h)
Definition ftp.c:936
static int ftp_connect_control_connection(URLContext *h)
Definition ftp.c:576
static int ftp_passive_mode_epsv(FTPContext *s)
Definition ftp.c:288
static int ftp_passive_mode(FTPContext *s)
Definition ftp.c:330
static int ftp_auth(FTPContext *s)
Definition ftp.c:256
static int ftp_read(URLContext *h, unsigned char *buf, int size)
Definition ftp.c:836
static int ftp_current_dir(FTPContext *s)
Definition ftp.c:376
static int ftp_delete(URLContext *h)
Definition ftp.c:1113
static int ftp_status(FTPContext *s, char **line, const int response_codes[])
Definition ftp.c:158
static int ftp_list(FTPContext *s)
Definition ftp.c:536
FTPListingMethod
Definition ftp.c:48
@ NLST
Definition ftp.c:50
@ UNKNOWN_METHOD
Definition ftp.c:49
@ MLSD
Definition ftp.c:51
static int ftp_list_nlst(FTPContext *s)
Definition ftp.c:525
static int ftp_abort(URLContext *h)
Definition ftp.c:659
static int ftp_type(FTPContext *s)
Definition ftp.c:475
static int ftp_open(URLContext *h, const char *url, int flags)
Definition ftp.c:768
static int ftp_get_line(FTPContext *s, char *line, int line_size)
Definition ftp.c:130
static int ftp_write(URLContext *h, const unsigned char *buf, int size)
Definition ftp.c:891
static int is_bad_string(const unsigned char *s)
Definition ftp.c:103
static int ftp_parse_entry_nlst(char *line, AVIODirEntry *next)
Definition ftp.c:995
#define CONTROL_BUFFER_SIZE
Definition ftp.c:35
static int ftp_restart(FTPContext *s, int64_t pos)
Definition ftp.c:486
#define DIR_BUFFER_SIZE
Definition ftp.c:36
static int ftp_parse_entry_mlsd(char *mlsd, AVIODirEntry *next)
Definition ftp.c:1001
static int ftp_list_mlsd(FTPContext *s)
Definition ftp.c:513
static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
Definition ftp.c:794
static int64_t ftp_parse_date(const char *date)
Definition ftp.c:987
static int ftp_close_dir(URLContext *h)
Definition ftp.c:1104
#define OFFSET(x)
Definition ftp.c:82
static int ftp_move(URLContext *h_src, URLContext *h_dst)
Definition ftp.c:1151
static int ftp_parse_entry(URLContext *h, char *line, AVIODirEntry *next)
Definition ftp.c:1042
static int ftp_features(FTPContext *s)
Definition ftp.c:555
static void ftp_close_both_connections(FTPContext *s)
Definition ftp.c:250
static int ftp_retrieve(FTPContext *s)
Definition ftp.c:437
FTPState
Definition ftp.c:38
@ UPLOADING
Definition ftp.c:42
@ READY
Definition ftp.c:40
@ UNKNOWN
Definition ftp.c:39
@ LISTING_DIR
Definition ftp.c:43
@ ENDOFFILE
Definition ftp.c:45
@ DISCONNECTED
Definition ftp.c:44
@ DOWNLOADING
Definition ftp.c:41
static int ftp_has_feature(FTPContext *s, const char *feature_name)
Definition ftp.c:547
static int ftp_open_dir(URLContext *h)
Definition ftp.c:960
const URLProtocol ff_ftp_protocol
Definition ftp.c:1196
static int ftp_send_command(FTPContext *s, const char *command, const int response_codes[], char **response)
Definition ftp.c:219
#define fail
Definition test.h:479
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition utils.c:361
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:236
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:180
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:247
static void * av_x_if_null(const void *p, const void *x)
Return x default pointer in case p is NULL.
Definition avutil.h:311
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition avstring.c:58
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition avstring.c:179
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition avstring.c:295
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define MAX_URL_SIZE
Definition internal.h:30
common internal API header
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define av_strdup(s)
Definition ops_static.c:55
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition parseutils.c:494
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition parseutils.c:573
misc parsing utilities
unsigned int pos
Definition spdifenc.c:431
Describe the class of an AVClass context structure.
Definition log.h:76
Describes single entry of the directory.
Definition avio.h:87
int64_t user_id
User ID of owner, -1 if unknown.
Definition avio.h:99
int type
Type of the entry.
Definition avio.h:89
int64_t size
File size in bytes, -1 if unknown.
Definition avio.h:92
int64_t group_id
Group ID of owner, -1 if unknown.
Definition avio.h:100
char * name
Filename.
Definition avio.h:88
int64_t modification_timestamp
Time of last modification in microseconds since unix epoch, -1 if unknown.
Definition avio.h:93
int64_t filemode
Unix file mode, -1 if unknown.
Definition avio.h:101
AVOption.
Definition opt.h:428
uint8_t control_buffer[CONTROL_BUFFER_SIZE]
Control connection buffer.
Definition ftp.c:58
uint8_t * control_buf_ptr
Definition ftp.c:59
int write_seekable
Control seekability, 0 = disable, 1 = enable.
Definition ftp.c:70
int utf8
Definition ftp.c:77
const char * option_password
Password to be used if none given in the URL.
Definition ftp.c:79
char * features
List of server's features represented as raw response.
Definition ftp.c:73
int64_t filesize
Size of file on server, -1 on error.
Definition ftp.c:66
FTPState state
State of data connection.
Definition ftp.c:71
uint8_t * control_buf_end
Definition ftp.c:59
size_t dir_buffer_size
Definition ftp.c:75
char * password
Server user's password.
Definition ftp.c:64
URLContext * conn_control
Control connection.
Definition ftp.c:56
size_t dir_buffer_offset
Definition ftp.c:76
char * user
Server user.
Definition ftp.c:63
int rw_timeout
Network timeout.
Definition ftp.c:68
char * dir_buffer
Definition ftp.c:74
int server_control_port
Control connection port, default is 21.
Definition ftp.c:61
FTPListingMethod listing_method
Called listing method.
Definition ftp.c:72
int64_t position
Current position, calculated.
Definition ftp.c:67
int server_data_port
Data connection port opened by server, -1 on error.
Definition ftp.c:60
const char * option_user
User to be used if none given in the URL.
Definition ftp.c:78
char * hostname
Server address.
Definition ftp.c:62
URLContext * conn_data
Data connection, NULL when not connected.
Definition ftp.c:57
char * path
Path to resource on server.
Definition ftp.c:65
const char * anonymous_password
Password to be used for anonymous user.
Definition ftp.c:69
void * priv_data
Definition url.h:38
char * filename
specified URL
Definition url.h:39
#define av_free(p)
#define ff_dlog(a,...)
#define av_freep(p)
#define av_log(a,...)
int size
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition url.c:40
AVIODirEntry * ff_alloc_dir_entry(void)
Allocate directory entry with default values.
Definition url.c:327
unbuffered private I/O API
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition url.h:205
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition url.h:184
#define URL_PROTOCOL_FLAG_NETWORK
Definition url.h:33
char * ff_urldecode(const char *url, int decode_plus_sign)
Decodes an URL from its percent-encoded form back into normal representation.
Definition urldecode.c:80
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
int len