I am running lftp on FreeBSD. I found recent lftp crashes when using
FTP over some HTTP proxies including Squid. The reason seems to be
not nul-terminated string is passed to sscanf() in HttpDir.cc.

In addition I implemented WWWOFFLE proxy server support. I'm not sure
the patch is correct but at least works. I attach an example of HTML
generated by WWWOFFLE.

Attachment: wwwoffle-sample.html.gz
Description: Binary data

diff -ru src.orig/HttpDir.cc src/HttpDir.cc
--- src.orig/HttpDir.cc Wed Feb 26 19:00:02 2003
+++ src/HttpDir.cc      Fri Apr  4 18:19:20 2003
@@ -536,6 +536,50 @@
    return true;
 }
 
+static bool try_wwwoffle_ftp(file_info &info,const char *buf,
+   const char *ext,const char **info_string,int *info_string_len)
+{
+   info.clear();
+
+   //   Perms Nlnk user [group] size Mon DD (YYYY or hh:mm)
+   int perms_code;
+   char year_or_time[6];
+   int consumed;
+
+   int n=sscanf(buf,"%11s %d %31s %31s %lld %3s %2d %5s%n",info.perms,&info.nlink,
+              info.user,info.group,&info.size,info.month_name,&info.day,
+              year_or_time,&consumed);
+   if(n==4) // bsd-like listing without group?
+   {
+      info.group[0]=0;
+      n=sscanf(buf,"%11s %d %31s %lld %3s %2d %5s%n",info.perms,&info.nlink,
+           info.user,&info.size,info.month_name,&info.day,year_or_time,&consumed);
+   }
+   if(n>=7 && -1!=(perms_code=parse_perms(info.perms+1))
+   && -1!=(info.month=parse_month(info.month_name))
+   && -1!=parse_year_or_time(year_or_time,&info.year,&info.hour,&info.minute))
+   {
+      sprintf(info.size_str,"%lld",info.size);
+      if(info.perms[0]=='d')
+        info.is_directory=true;
+      else if(info.perms[0]=='l')
+      {
+        info.is_sym_link=true;
+        char *p=strstr(ext,"-> ");
+        if(p)
+        {
+           info.sym_link=xstrdup(p+6);
+           info.free_sym_link=true;
+        }
+      }
+      *info_string=buf;
+      *info_string_len=consumed;
+      debug("wwwoffle ftp over http proxy listing matched");
+      return true;
+   }
+   return false;
+}
+
 
 // this procedure is highly inefficient in some cases,
 // esp. when it has to return for more data many times.
@@ -804,6 +848,11 @@
            strcpy(link_target,".");
            link_len=1;
         }
+        if(link_target[0]=='.' && link_target[1]=='/')
+        {
+           link_len-=2;
+           memmove(link_target,link_target+2,link_len+1);
+        }
       }
       else
       {
@@ -839,7 +888,7 @@
    if(list && show_in_list)
    {
       const char *more1;
-      char *str,*str_with_tags;
+      char *str,*str_with_tags, *str2;
       char *line_add=(char*)alloca(link_len+128+2*1024);
       const char *info_string=0;
       int         info_string_len=0;
@@ -903,12 +952,23 @@
         skip_len=eol-buf+eol_len;
         goto got_info;
       }
-      if(try_mini_proxy(info,buf)              && info.validate()) goto got_info;
-      if(try_apache_unixlike(info,buf,more,more1,&info_string,&info_string_len)
+      if(try_mini_proxy(info,str)              && info.validate()) goto got_info;
+      if(try_apache_unixlike(info,str,more,more1,&info_string,&info_string_len)
       && info.validate())
         goto got_info;
       if(try_roxen(info,str)                   && info.validate()) goto got_info;
       if(try_squid_ftp(info,str,str_with_tags) && info.validate())
+      {
+        // skip rest of line, because there may be href to link target.
+        skip_len=eol-buf+eol_len;
+        goto got_info;
+      }
+      // wwwoffle
+      str2=string_alloca(less-buf+1);
+      memcpy(str2,buf,less-buf);
+      str2[less-buf]=0;
+      if(try_wwwoffle_ftp(info,str2,str,&info_string,&info_string_len)
+      && info.validate())
       {
         // skip rest of line, because there may be href to link target.
         skip_len=eol-buf+eol_len;

Reply via email to