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.
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;