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