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