On Mon, Aug 10, 2015 at 6:41 PM, Michael Niedermayer <mich...@niedermayer.cc
> wrote:

> On Sun, Aug 09, 2015 at 02:38:12AM +0200, Mariusz Szczepańczyk wrote:
> > ---
> >  libavformat/ftp.c | 98
> +++++++++++++++++++++++++++++++++++++++++++++++--------
> >  1 file changed, 84 insertions(+), 14 deletions(-)
> >
> > diff --git a/libavformat/ftp.c b/libavformat/ftp.c
> > index 542cf6a..5a312b9 100644
> > --- a/libavformat/ftp.c
> > +++ b/libavformat/ftp.c
> > @@ -38,6 +38,12 @@ typedef enum {
> >      DISCONNECTED
> >  } FTPState;
> >
> > +typedef enum {
> > +    UNKNOWN_METHOD,
> > +    NLST,
> > +    MLSD
> > +} FTPListingMethod;
> > +
> >  typedef struct {
> >      const AVClass *class;
> >      URLContext *conn_control;                    /**< Control
> connection */
> > @@ -56,6 +62,8 @@ typedef struct {
> >      const char *anonymous_password;              /**< Password to be
> used for anonymous user. An email should be used. */
> >      int write_seekable;                          /**< Control
> seekability, 0 = disable, 1 = enable. */
> >      FTPState state;                              /**< State of data
> connection */
> > +    FTPListingMethod listing_method;             /**< Called listing
> method */
> > +    char *features;                              /**< List of server's
> features represented as raw response */
> >      char *dir_buffer;
> >      size_t dir_buffer_size;
> >      size_t dir_buffer_offset;
> > @@ -192,6 +200,8 @@ static int ftp_send_command(FTPContext *s, const
> char *command,
> >  {
> >      int err;
> >
> > +    av_dlog(s, "%s", command);
> > +
> >      if (response)
> >          *response = NULL;
> >
> > @@ -449,32 +459,68 @@ static int ftp_set_dir(FTPContext *s)
> >      return 0;
> >  }
> >
> > -static int ftp_list(FTPContext *s)
> > +static int ftp_list_mlsd(FTPContext *s)
> >  {
> >      static const char *command = "MLSD\r\n";
> >      static const int mlsd_codes[] = {150, 500, 0}; /* 500 is incorrect
> code */
> >
> >      if (ftp_send_command(s, command, mlsd_codes, NULL) != 150)
> >          return AVERROR(ENOSYS);
> > -    s->state = LISTING_DIR;
> > +    s->listing_method = MLSD;
> > +    return 0;
> > +}
> > +
> > +static int ftp_list_nlst(FTPContext *s)
> > +{
> > +    static const char *command = "NLST\r\n";
> > +    static const int nlst_codes[] = {226, 425, 426, 451, 450, 550, 0};
> > +
> > +    if (ftp_send_command(s, command, nlst_codes, NULL) != 226)
> > +        return AVERROR(ENOSYS);
> > +    s->listing_method = NLST;
> >      return 0;
> >  }
> >
> > +static int ftp_has_feature(FTPContext *s, const char *feature_name);
> > +
> > +static int ftp_list(FTPContext *s)
> > +{
> > +    s->state = LISTING_DIR;
> > +
> > +    if (ftp_has_feature(s, "MLSD"))
> > +        return ftp_list_mlsd(s);
> > +
> > +    return ftp_list_nlst(s);
> > +}
> > +
> > +static int ftp_has_feature(FTPContext *s, const char *feature_name)
> > +{
> > +    if (!s->features)
> > +        return 0;
> > +
> > +    return av_stristr(s->features, feature_name) != NULL;
> > +}
> > +
> >  static int ftp_features(FTPContext *s)
> >  {
> >      static const char *feat_command        = "FEAT\r\n";
> >      static const char *enable_utf8_command = "OPTS UTF8 ON\r\n";
> >      static const int feat_codes[] = {211, 0};
> >      static const int opts_codes[] = {200, 451, 0};
> > -    char *feat = NULL;
>
> > +    if (s->features) {
> > +        av_freep(&s->features);
> > +        s->features = NULL;
> > +    }
>
> the if and NULL setting is uneeded
>
>
fixed


> also please explain how each patch can be tested
>
>
For now I'm using local ftp servers, and netcat to test "wrong" responses.
I'd like to write some blackbox tests (list of input commands + expected
responses) but I'm still thinking how to fit them into the current
architecture.


> >
> > -    if (ftp_send_command(s, feat_command, feat_codes, &feat) == 211) {
> > -        if (av_stristr(feat, "UTF8")) {
> > -            if (ftp_send_command(s, enable_utf8_command, opts_codes,
> NULL) == 200)
> > -                s->utf8 = 1;
> > -        }
> > +    if (ftp_send_command(s, feat_command, feat_codes, &s->features) !=
> 211) {
>
> > +        av_freep(&s->features);
> > +        s->features = NULL;
>
> same
>

fixed


>


> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Old school: Use the lowest level language in which you can solve the
> problem
>             conveniently.
> New school: Use the highest level language in which the latest
> supercomputer
>             can solve the problem without the user falling asleep waiting.
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>
From f682cc6da7fc21f8ae5d646ccc3ffd7fb6c3a993 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mariusz=20Szczepa=C5=84czyk?= <mszczepanc...@gmail.com>
Date: Tue, 16 Jun 2015 20:41:31 +0200
Subject: [PATCH 3/3] lavf/ftp: implement NLST method

---
 libavformat/ftp.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 80 insertions(+), 14 deletions(-)

diff --git a/libavformat/ftp.c b/libavformat/ftp.c
index 542cf6a..e3052cc 100644
--- a/libavformat/ftp.c
+++ b/libavformat/ftp.c
@@ -38,6 +38,12 @@ typedef enum {
     DISCONNECTED
 } FTPState;
 
+typedef enum {
+    UNKNOWN_METHOD,
+    NLST,
+    MLSD
+} FTPListingMethod;
+
 typedef struct {
     const AVClass *class;
     URLContext *conn_control;                    /**< Control connection */
@@ -56,6 +62,8 @@ typedef struct {
     const char *anonymous_password;              /**< Password to be used for anonymous user. An email should be used. */
     int write_seekable;                          /**< Control seekability, 0 = disable, 1 = enable. */
     FTPState state;                              /**< State of data connection */
+    FTPListingMethod listing_method;             /**< Called listing method */
+    char *features;                              /**< List of server's features represented as raw response */
     char *dir_buffer;
     size_t dir_buffer_size;
     size_t dir_buffer_offset;
@@ -192,6 +200,8 @@ static int ftp_send_command(FTPContext *s, const char *command,
 {
     int err;
 
+    av_dlog(s, "%s", command);
+
     if (response)
         *response = NULL;
 
@@ -449,32 +459,64 @@ static int ftp_set_dir(FTPContext *s)
     return 0;
 }
 
-static int ftp_list(FTPContext *s)
+static int ftp_list_mlsd(FTPContext *s)
 {
     static const char *command = "MLSD\r\n";
     static const int mlsd_codes[] = {150, 500, 0}; /* 500 is incorrect code */
 
     if (ftp_send_command(s, command, mlsd_codes, NULL) != 150)
         return AVERROR(ENOSYS);
-    s->state = LISTING_DIR;
+    s->listing_method = MLSD;
+    return 0;
+}
+
+static int ftp_list_nlst(FTPContext *s)
+{
+    static const char *command = "NLST\r\n";
+    static const int nlst_codes[] = {226, 425, 426, 451, 450, 550, 0};
+
+    if (ftp_send_command(s, command, nlst_codes, NULL) != 226)
+        return AVERROR(ENOSYS);
+    s->listing_method = NLST;
     return 0;
 }
 
+static int ftp_has_feature(FTPContext *s, const char *feature_name);
+
+static int ftp_list(FTPContext *s)
+{
+    s->state = LISTING_DIR;
+
+    if (ftp_has_feature(s, "MLSD"))
+        return ftp_list_mlsd(s);
+
+    return ftp_list_nlst(s);
+}
+
+static int ftp_has_feature(FTPContext *s, const char *feature_name)
+{
+    if (!s->features)
+        return 0;
+
+    return av_stristr(s->features, feature_name) != NULL;
+}
+
 static int ftp_features(FTPContext *s)
 {
     static const char *feat_command        = "FEAT\r\n";
     static const char *enable_utf8_command = "OPTS UTF8 ON\r\n";
     static const int feat_codes[] = {211, 0};
     static const int opts_codes[] = {200, 451, 0};
-    char *feat = NULL;
 
-    if (ftp_send_command(s, feat_command, feat_codes, &feat) == 211) {
-        if (av_stristr(feat, "UTF8")) {
-            if (ftp_send_command(s, enable_utf8_command, opts_codes, NULL) == 200)
-                s->utf8 = 1;
-        }
+    av_freep(&s->features);
+    if (ftp_send_command(s, feat_command, feat_codes, &s->features) != 211) {
+        av_freep(&s->features);
+    }
+
+    if (ftp_has_feature(s, "UTF8")) {
+        if (ftp_send_command(s, enable_utf8_command, opts_codes, NULL) == 200)
+            s->utf8 = 1;
     }
-    av_freep(&feat);
 
     return 0;
 }
@@ -607,8 +649,10 @@ static int ftp_connect(URLContext *h, const char *url)
     FTPContext *s = h->priv_data;
 
     s->state = DISCONNECTED;
+    s->listing_method = UNKNOWN;
     s->filesize = -1;
     s->position = 0;
+    s->features = NULL;
 
     av_url_split(proto, sizeof(proto),
                  credencials, sizeof(credencials),
@@ -815,6 +859,7 @@ static int ftp_close(URLContext *h)
     av_freep(&s->password);
     av_freep(&s->hostname);
     av_freep(&s->path);
+    av_freep(&s->features);
 
     return 0;
 }
@@ -878,10 +923,13 @@ static int64_t ftp_parse_date(const char *date)
     return INT64_C(1000000) * av_timegm(&tv);
 }
 
-/**
- * @return 0 on success, negative on error, positive on entry to discard.
- */
-static int ftp_parse_entry(char *mlsd, AVIODirEntry *next)
+static int ftp_parse_entry_nlst(char *line, AVIODirEntry *next)
+{
+    next->name = av_strdup(line);
+    return 0;
+}
+
+static int ftp_parse_entry_mlsd(char *mlsd, AVIODirEntry *next)
 {
     char *fact, *value;
     av_dlog(NULL, "%s\n", mlsd);
@@ -914,6 +962,24 @@ static int ftp_parse_entry(char *mlsd, AVIODirEntry *next)
     return 0;
 }
 
+/**
+ * @return 0 on success, negative on error, positive on entry to discard.
+ */
+static int ftp_parse_entry(URLContext *h, char *line, AVIODirEntry *next)
+{
+    FTPContext *s = h->priv_data;
+
+    switch (s->listing_method) {
+    case MLSD:
+        return ftp_parse_entry_mlsd(line, next);
+    case NLST:
+        return ftp_parse_entry_nlst(line, next);
+    case UNKNOWN_METHOD:
+    default:
+        return -1;
+    }
+}
+
 static int ftp_read_dir(URLContext *h, AVIODirEntry **next)
 {
     FTPContext *s = h->priv_data;
@@ -951,7 +1017,7 @@ static int ftp_read_dir(URLContext *h, AVIODirEntry **next)
         if (!*next)
             return AVERROR(ENOMEM);
         (*next)->utf8 = s->utf8;
-        ret = ftp_parse_entry(start, *next);
+        ret = ftp_parse_entry(h, start, *next);
         if (ret) {
             avio_free_directory_entry(next);
             if (ret < 0)
-- 
2.4.6

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to