Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:SilvioMoioli:tools
lftp
fix-issue-235.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fix-issue-235.patch of Package lftp
From 764c5a3057357abdf6c272b0e67ff26c07e272f0 Mon Sep 17 00:00:00 2001 From: "Alexander V. Lukyanov" <lavv17f@gmail.com> Date: Tue, 10 May 2016 17:09:37 +0300 Subject: [PATCH] Squashed patches for issue 235 --- src/FileCopy.cc | 6 ++-- src/FileSet.cc | 21 +++++------ src/FileSet.h | 10 ++++-- src/Http.cc | 107 +++++++++++++++++++++++++++++++++---------------------- src/Http.h | 1 + src/MirrorJob.cc | 3 +- src/NetAccess.cc | 87 +++++++++++++++++++++++++++++++++++++++++--- src/NetAccess.h | 7 ++++ src/xstring.h | 3 ++ 9 files changed, 182 insertions(+), 63 deletions(-) diff --git a/src/FileCopy.cc b/src/FileCopy.cc index c71df2e..46de066 100644 --- a/src/FileCopy.cc +++ b/src/FileCopy.cc @@ -1238,8 +1238,10 @@ int FileCopyPeerFA::Get_LL(int len) file.set(loc); } - size=NO_SIZE_YET; - date=NO_DATE_YET; + if(want_size || size!=NO_SIZE) + WantSize(); + if(want_date || date!=NO_DATE) + WantDate(); upload_state.Clear(); current->Timeout(0); // retry with new location. diff --git a/src/FileSet.cc b/src/FileSet.cc index 54afc89..2c7197e 100644 --- a/src/FileSet.cc +++ b/src/FileSet.cc @@ -50,10 +50,16 @@ void FileInfo::Merge(const FileInfo& f) { if(strcmp(basename_ptr(name),basename_ptr(f.name))) return; -// int sim=defined&f.defined; - int dif=(~defined)&f.defined; - if(dif&MODE) + MergeInfo(f,~defined); +} +void FileInfo::MergeInfo(const FileInfo& f,unsigned dif) +{ + dif&=f.defined; + if(dif&MODE) { SetMode(f.mode); + if(mode!=SYMLINK && mode!=REDIRECT) + symlink.unset(); + } if(dif&DATE || (defined&DATE && f.defined&DATE && f.date.ts_prec<date.ts_prec)) SetDate(f.date,f.date.ts_prec); if(dif&SIZE) @@ -484,7 +490,7 @@ void FileSet::Count(int *d,int *f,int *s,int *o) const if(f) (*f)++; break; case(FileInfo::SYMLINK): if(s) (*s)++; break; - case(FileInfo::UNKNOWN): + default: if(o) (*o)++; } } @@ -720,12 +726,6 @@ FileInfo::FileInfo(const FileInfo &fi) nlinks=fi.nlinks; longname.set(fi.longname); } -FileInfo::FileInfo(const char *n) -{ - Init(); - SetName(n); -} - FileInfo::~FileInfo() { } @@ -1004,6 +1004,7 @@ void FileInfo::MakeLongName() case UNKNOWN: break; case DIRECTORY: filetype_c='d'; break; case SYMLINK: filetype_c='l'; break; + case REDIRECT: filetype_c='L'; break; } int mode1=(defined&MODE?mode: (filetype_c=='d'?0755:(filetype_c=='l'?0777:0644))); diff --git a/src/FileSet.h b/src/FileSet.h index 6771fa9..7f456d0 100644 --- a/src/FileSet.h +++ b/src/FileSet.h @@ -51,6 +51,7 @@ public: xstring name; xstring longname; xstring_c symlink; + xstring_c uri; mode_t mode; FileTimestamp date; off_t size; @@ -63,7 +64,8 @@ public: UNKNOWN=0, DIRECTORY, SYMLINK, - NORMAL + NORMAL, + REDIRECT, }; type filetype; @@ -85,7 +87,8 @@ public: void Init(); FileInfo() { Init(); } FileInfo(const FileInfo &fi); - FileInfo(const char *n); + FileInfo(const char *n) { Init(); SetName(n); } + FileInfo(const xstring& n) { Init(); SetName(n); } ~FileInfo(); void SetName(const char *n) { name.set(n); def(NAME); } @@ -100,10 +103,13 @@ public: void SetDate(time_t t,int prec) { date.set(t,prec); def(DATE); } void SetType(type t) { filetype=t; def(TYPE); } void SetSymlink(const char *s) { symlink.set(s); filetype=SYMLINK; def(TYPE|SYMLINK_DEF); } + void SetRedirect(const char *s) { symlink.set(s); filetype=REDIRECT; def(TYPE|SYMLINK_DEF); } + const char *GetRedirect() const { return symlink; } void SetSize(off_t s) { size=s; def(SIZE); } void SetNlink(int n) { nlinks=n; def(NLINKS); } void Merge(const FileInfo&); + void MergeInfo(const FileInfo& f,unsigned mask); bool SameAs(const FileInfo *,int ignore) const; bool OlderThan(time_t t) const; diff --git a/src/Http.cc b/src/Http.cc index 6591fc2..4ca83bd 100644 --- a/src/Http.cc +++ b/src/Http.cc @@ -222,6 +222,7 @@ void Http::MoveConnectionHere(Http *o) void Http::DisconnectLL() { + Enter(this); rate_limit=0; if(conn) { @@ -247,6 +248,7 @@ void Http::DisconnectLL() last_url.unset(); ResetRequestData(); state=DISCONNECTED; + Leave(this); } void Http::ResetRequestData() @@ -877,6 +879,10 @@ int Http::SendArrayInfoRequest() name=&xstring::get_tmp(*name); name->append('/'); } + if(fi->uri) + file_url.set(dir_file(GetConnectURL(),fi->uri)); + else + file_url.unset(); SendRequest(array_send==fileset_for_info->count()-1 ? 0 : "keep-alive", *name); req_count++; } @@ -1578,6 +1584,14 @@ int Http::Do() } goto pre_RECEIVING_BODY; } + FileInfo *fi=fileset_for_info->curr(); + if(H_REDIRECTED(status_code)) { + HandleRedirection(); + if(location) + fi->SetRedirect(location); + } else if(H_2XX(status_code) && !fi->Has(fi->TYPE)) { + fi->SetType(last_uri.last_char()=='/'?fi->DIRECTORY:fi->NORMAL); + } ProceedArrayInfo(); return MOVED; } @@ -1736,49 +1750,7 @@ int Http::Do() if(H_REDIRECTED(status_code)) { - bool is_url=(location && url::is_url(location)); - if(location && !is_url - && mode==QUOTE_CMD && !strncasecmp(file,"POST ",5) - && tunnel_state!=TUNNEL_WAITING) - { - const char *the_file=file; - - const char *scan=file+5; - while(*scan==' ') - scan++; - char *the_post_file=alloca_strdup(scan); - char *space=strchr(the_post_file,' '); - if(space) - *space=0; - the_file=the_post_file; - - char *new_location=alloca_strdup2(GetConnectURL(), - strlen(the_file)+strlen(location)); - int p_ind=url::path_index(new_location); - if(location[0]=='/') - strcpy(new_location+p_ind,location); - else - { - if(the_file[0]=='/') - strcpy(new_location+p_ind,the_file); - else - { - char *slash=strrchr(new_location,'/'); - strcpy(slash+1,the_file); - } - char *slash=strrchr(new_location,'/'); - strcpy(slash+1,location); - } - location.set(new_location); - } else if(is_url && !hftp) { - ParsedURL url(location); - if(url.proto.eq(GetProto()) && !xstrcasecmp(url.host,hostname) - && user && !url.user) { - // use the same user name after redirect to the same site. - url.user.set(user); - location.set_allocated(url.Combine()); - } - } + HandleRedirection(); err.setf("%s (%s -> %s)",status+status_consumed,file.get(), location?location.get():"nowhere"); code=FILE_MOVED; @@ -1927,6 +1899,53 @@ system_error: return MOVED; } +void Http::HandleRedirection() +{ + bool is_url=(location && url::is_url(location)); + if(location && !is_url + && mode==QUOTE_CMD && !strncasecmp(file,"POST ",5) + && tunnel_state!=TUNNEL_WAITING) + { + const char *the_file=file; + + const char *scan=file+5; + while(*scan==' ') + scan++; + char *the_post_file=alloca_strdup(scan); + char *space=strchr(the_post_file,' '); + if(space) + *space=0; + the_file=the_post_file; + + char *new_location=alloca_strdup2(GetConnectURL(), + strlen(the_file)+strlen(location)); + int p_ind=url::path_index(new_location); + if(location[0]=='/') + strcpy(new_location+p_ind,location); + else + { + if(the_file[0]=='/') + strcpy(new_location+p_ind,the_file); + else + { + char *slash=strrchr(new_location,'/'); + strcpy(slash+1,the_file); + } + char *slash=strrchr(new_location,'/'); + strcpy(slash+1,location); + } + location.set(new_location); + } else if(is_url && !hftp) { + ParsedURL url(location); + if(url.proto.eq(GetProto()) && !xstrcasecmp(url.host,hostname) + && user && !url.user) { + // use the same user name after redirect to the same site. + url.user.set(user); + location.set_allocated(url.Combine()); + } + } +} + FileAccess *Http::New() { return new Http(); } FileAccess *HFtp::New() { return new HFtp(); } @@ -1964,6 +1983,7 @@ int Http::Read(Buffer *buf,int size) int res=DO_AGAIN; if(state==RECEIVING_BODY && real_pos>=0) { + Enter(this); res=_Read(buf,size); if(res>0) { @@ -1972,6 +1992,7 @@ int Http::Read(Buffer *buf,int size) rate_limit->BytesGot(res); TrySuccess(); } + Leave(this); } return res; } diff --git a/src/Http.h b/src/Http.h index ad19912..6633f52 100644 --- a/src/Http.h +++ b/src/Http.h @@ -109,6 +109,7 @@ class Http : public NetAccess int status_code; void HandleHeaderLine(const char *name,const char *value); static const xstring& extract_quoted_header_value(const char *value,const char **end=0); + void HandleRedirection(); void GetBetterConnection(int level); void SetCookie(const char *val); void MakeCookie(xstring &cookie,const char *host,const char *path); diff --git a/src/MirrorJob.cc b/src/MirrorJob.cc index 776e350..8697259 100644 --- a/src/MirrorJob.cc +++ b/src/MirrorJob.cc @@ -273,6 +273,7 @@ void MirrorJob::HandleFile(FileInfo *file) switch(filetype) { case(FileInfo::NORMAL): + case(FileInfo::REDIRECT): { bool remove_target=false; bool cont_this=false; @@ -1215,7 +1216,7 @@ int MirrorJob::Do() break; // all jobs finished. - if(remove_source_dirs) { + if(remove_source_dirs && source_dir.last_char()!='/') { // remove source directory once. remove_source_dirs=false; if(script) diff --git a/src/NetAccess.cc b/src/NetAccess.cc index 18a9fdd..9d55473 100644 --- a/src/NetAccess.cc +++ b/src/NetAccess.cc @@ -404,6 +404,31 @@ do_again: if(done) return m; + if(redir_resolution) { + if(redir_session && redir_session->OpenMode()==FA::ARRAY_INFO) { + res=redir_session->Done(); + if(res==FA::DO_AGAIN || res==FA::IN_PROGRESS) + return m; + redir_session->Close(); + redir_fs->rewind(); + FileInfo *fi=redir_fs->curr(); + if(ResolveRedirect(fi)) + return MOVED; + result->curr()->MergeInfo(*fi,~0U); + result->next(); + } + redir_count=0; + for(FileInfo *fi=result->curr(); fi; fi=result->next()) { + if(ResolveRedirect(fi)) + return MOVED; + } + + FileAccess::cache->UpdateFileSet(session,"",FA::MP_LIST,result); + FileAccess::cache->UpdateFileSet(session,"",FA::LONG_LIST,result); + done=true; + return MOVED; + } + if(session->OpenMode()==FA::ARRAY_INFO) { res=session->Done(); @@ -412,10 +437,11 @@ do_again: if(res==FA::IN_PROGRESS) return m; session->Close(); - FileAccess::cache->UpdateFileSet(session,"",FA::MP_LIST,result); - FileAccess::cache->UpdateFileSet(session,"",FA::LONG_LIST,result); - done=true; - return MOVED; + // start redirection resolution. + redir_resolution=true; + result->rewind(); + m=MOVED; + goto do_again; } if(!ubuf) @@ -567,8 +593,59 @@ got_fileset: return m; } +bool GenericParseListInfo::ResolveRedirect(const FileInfo *fi) +{ + if(fi->filetype!=fi->REDIRECT || redir_count>=max_redir) + return false; + + redir_count++; + Log::global->Format(9,"ListInfo: resolving redirection %s -> %s\n",fi->name.get(),fi->GetRedirect()); + + Ref<FileInfo> redir_fi(new FileInfo()); + redir_fi->Need(fi->need); + + xstring loc(fi->GetRedirect()); + ParsedURL u(loc,true); + if(!u.proto) { + // relative URI + redir_session=session->Clone(); + if(loc[0]=='/' || fi->uri) { + if(loc[0]!='/') { + const char *slash=strrchr(fi->uri,'/'); + if(slash) + loc.prepend(fi->uri,slash+1-fi->uri); + } + redir_fi->uri.set(loc); + redir_fi->name.set(loc); + redir_fi->name.url_decode(); + } else { + loc.url_decode(); + const char *slash=strrchr(fi->name,'/'); + if(slash) + redir_fi->name.nset(fi->name,slash+1-fi->name); + redir_fi->name.append(loc); + } + } else { // u.proto + // absolute URL + redir_session=FileAccess::New(&u); + redir_fi->name.set(u.path?u.path.get():"/"); + redir_fi->uri.set(url::path_ptr(u.orig_url)); + } + + if(!redir_fs) + redir_fs=new FileSet(); + else + redir_fs->Empty(); + redir_fs->Add(redir_fi.borrow()); + redir_session->GetInfoArray(redir_fs.get_non_const()); + redir_session->Roll(); + + return true; +} + GenericParseListInfo::GenericParseListInfo(FileAccess *s,const char *p) - : ListInfo(s,p) + : ListInfo(s,p), redir_resolution(false), redir_count(0), + max_redir(ResMgr::Query("xfer:max-redirections",0)) { get_time_for_dirs=true; can_get_prec_time=true; diff --git a/src/NetAccess.h b/src/NetAccess.h index 28e33ab..4972849 100644 --- a/src/NetAccess.h +++ b/src/NetAccess.h @@ -109,6 +109,13 @@ public: class GenericParseListInfo : public ListInfo { + bool redir_resolution; + int redir_count; + int max_redir; + FileAccessRef redir_session; + Ref<FileSet> redir_fs; + bool ResolveRedirect(const FileInfo *fi); + protected: int mode; SMTaskRef<IOBuffer> ubuf; diff --git a/src/xstring.h b/src/xstring.h index 8bba5db..55918ba 100644 --- a/src/xstring.h +++ b/src/xstring.h @@ -145,6 +145,7 @@ public: bool eq_nc(const char *s) const { return !xstrcasecmp(buf,s); } size_t length() const { return xstrlen(buf); } void set_length(size_t n) { if(buf) buf[n]=0; } + char last_char() const { size_t len=length(); return len>0?buf[len-1]:0; } void unset() { xfree(buf); buf=0; } void _set(const char *s) { buf=xstrdup(s); } @@ -205,6 +206,8 @@ public: xstring& set_substr(int start,size_t sublen,const char *,size_t); xstring& set_substr(int start,size_t sublen,const char *); xstring& set_substr(int start,size_t sublen,const xstring &s) { return set_substr(start,sublen,s.get(),s.length()); } + xstring& prepend(const char *s,size_t len) { return set_substr(0,0,s,len); } + xstring& prepend(const xstring &s) { return prepend(s.get(),s.length()); } xstring& append(const char *s); xstring& append(char c); -- 2.8.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor