From ebb461fdf02ee3e038d4b3a4ab1a0a60188edf9a Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 2 Feb 2009 12:14:36 +0100 Subject: [PATCH] * [ABI break] merge support for http redirects, thanks to Jeff Licquia and Anthony Towns * [ABI break] use int for the package IDs (thanks to Steve Cotton) - Galician updated. Closes: #509151 - Catalan updated. Closes: #509375 - Vietnamese updated. Closes: #509422 - Traditional Chinese added. Closes: #510664 * COPYING: - Actualized. Removed obsolete Qt section, added GPLv2 clause. (Closes: #440049, #509337) * Clarify the --help for 'purge' (LP: #243948) --- apt-pkg/acquire-method.cc | 32 ++++++++++++++++ apt-pkg/acquire-method.h | 2 + apt-pkg/acquire-worker.cc | 14 +++++++ apt-pkg/makefile | 2 +- apt-pkg/pkgcache.h | 8 ++-- debian/changelog | 44 ++++++++++------------ methods/http.cc | 78 ++++++++++++++++++++++++++++++++++++++- methods/http.h | 3 ++ methods/makefile | 2 +- 9 files changed, 153 insertions(+), 32 deletions(-) diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index 26f992bcf..150fbb77b 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -452,6 +452,38 @@ void pkgAcqMethod::Status(const char *Format,...) } /*}}}*/ +// AcqMethod::Redirect - Send a redirect message /*{{{*/ +// --------------------------------------------------------------------- +/* This method sends the redirect message and also manipulates the queue + to keep the pipeline synchronized. */ +void pkgAcqMethod::Redirect(const string &NewURI) +{ + string CurrentURI = ""; + if (Queue != 0) + CurrentURI = Queue->Uri; + + char S[1024]; + snprintf(S, sizeof(S)-50, "103 Redirect\nURI: %s\nNew-URI: %s\n\n", + CurrentURI.c_str(), NewURI.c_str()); + + if (write(STDOUT_FILENO,S,strlen(S)) != (ssize_t)strlen(S)) + exit(100); + + // Change the URI for the request. + Queue->Uri = NewURI; + + /* To keep the pipeline synchronized, move the current request to + the end of the queue, past the end of the current pipeline. */ + FetchItem *I; + for (I = Queue; I->Next != 0; I = I->Next) ; + I->Next = Queue; + Queue = Queue->Next; + I->Next->Next = 0; + if (QueueBack == 0) + QueueBack = I->Next; +} + /*}}}*/ + // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 18c2cf009..99a4605b1 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -86,6 +86,8 @@ class pkgAcqMethod void Log(const char *Format,...); void Status(const char *Format,...); + void Redirect(const string &NewURI); + int Run(bool Single = false); inline void SetFailReason(string Msg) {FailReason = Msg;}; inline void SetIP(string aIP) {IP = aIP;}; diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 1a754dae9..78c68737c 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -220,6 +220,20 @@ bool pkgAcquire::Worker::RunMessages() Status = LookupTag(Message,"Message"); break; + // 103 Redirect + case 103: + { + if (Itm == 0) + { + _error->Error("Method gave invalid 103 Redirect message"); + break; + } + + string NewURI = LookupTag(Message,"New-URI",URI.c_str()); + Itm->URI = NewURI; + break; + } + // 200 URI Start case 200: { diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 1b78c94f6..087f17740 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -13,7 +13,7 @@ include ../buildlib/defaults.mak # methods/makefile - FIXME LIBRARY=apt-pkg LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER) -MAJOR=4.6 +MAJOR=4.7 MINOR=0 SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil APT_DOMAIN:=libapt-pkg$(MAJOR) diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 59d5003bb..759e9a225 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -214,7 +214,7 @@ struct pkgCache::Package unsigned char InstState; // Flags unsigned char CurrentState; // State - unsigned short ID; + unsigned int ID; unsigned long Flags; }; @@ -235,7 +235,7 @@ struct pkgCache::PackageFile // Linked list map_ptrloc NextFile; // PackageFile - unsigned short ID; + unsigned int ID; time_t mtime; // Modification time for the file }; @@ -272,7 +272,7 @@ struct pkgCache::Version map_ptrloc Size; // These are the .deb size map_ptrloc InstalledSize; unsigned short Hash; - unsigned short ID; + unsigned int ID; unsigned char Priority; }; @@ -289,7 +289,7 @@ struct pkgCache::Description map_ptrloc NextDesc; // Description map_ptrloc ParentPkg; // Package - unsigned short ID; + unsigned int ID; }; struct pkgCache::Dependency diff --git a/debian/changelog b/debian/changelog index 478638a63..bfbe6be5c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,29 +6,11 @@ apt (0.7.19ubuntu3) jaunty; urgency=low * apt-inst/contrib/arfile.cc: - support members ending with '/' as well (thanks to Michal Cihr, closes: #500988) - * debian/apt.conf.autoremove: - - readd "linux-image" (and friends) to the auto-remove + * debian/apt.conf.autoremove: + - readd "linux-image" (and friends) to the auto-remove blacklist - * fix some i18n issues (thanks to Gabor Kelemen) - LP: #263089 - - [ Christian Perrier ] - * Translations: - - Galician updated. Closes: #509151 - - Catalan updated. Closes: #509375 - - Vietnamese updated. Closes: #509422 - - Traditional Chinese added. Closes: #510664 - - [ Eugene V. Lyubimkin ] - * COPYING: - - Actualized. Removed obsolete Qt section, added GPLv2 clause. - (Closes: #440049, #509337) - - -- Michael Vogt Mon, 05 Jan 2009 08:59:20 +0100 - -apt (0.7.19ubuntu2) jaunty; urgency=low - - [ Michael Vogt ] + * fix some i18n issues (thanks to Gabor Kelemen) + LP: #263089 * apt-pkg/deb/dpkgpm.cc: - filter "ENOMEM" errors when creating apport reports * cmdline/apt-get.cc: @@ -40,15 +22,27 @@ apt (0.7.19ubuntu2) jaunty; urgency=low - add new strprintf() function to make i18n strings easier * apt-pkg/dev/debsystem.cc: - add missing apti18n.h header - - [ Dereck Wonnacott ] - * Clarify the --help for 'purge' (LP: #243948) + * [ABI break] merge support for http redirects, thanks to + Jeff Licquia and Anthony Towns + * [ABI break] use int for the package IDs (thanks to Steve Cotton) [ Christian Perrier ] * Translations: + - Galician updated. Closes: #509151 + - Catalan updated. Closes: #509375 + - Vietnamese updated. Closes: #509422 + - Traditional Chinese added. Closes: #510664 - French corrected (remove awful use of first person) - Finnish updated. Closes: #508449 + [ Eugene V. Lyubimkin ] + * COPYING: + - Actualized. Removed obsolete Qt section, added GPLv2 clause. + (Closes: #440049, #509337) + + [ Dereck Wonnacott ] + * Clarify the --help for 'purge' (LP: #243948) + [ Eugene V. Lyubimkin ] * doc/examples/sources.list: - Removed obsolete commented non-us deb-src entry, replaced it with diff --git a/methods/http.cc b/methods/http.cc index b0fb89fda..44274bd78 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include // Internet stuff @@ -56,6 +57,7 @@ int HttpMethod::FailFd = -1; time_t HttpMethod::FailTime = 0; unsigned long PipelineDepth = 10; unsigned long TimeOut = 120; +bool AllowRedirect = false; bool Debug = false; URI Proxy; @@ -627,6 +629,12 @@ bool ServerState::HeaderLine(string Line) return true; } + if (stringcasecmp(Tag,"Location:") == 0) + { + Location = Val; + return true; + } + return true; } /*}}}*/ @@ -899,7 +907,9 @@ bool HttpMethod::ServerDie(ServerState *Srv) 1 - IMS hit 3 - Unrecoverable error 4 - Error with error content page - 5 - Unrecoverable non-server error (close the connection) */ + 5 - Unrecoverable non-server error (close the connection) + 6 - Try again with a new or changed URI + */ int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv) { // Not Modified @@ -911,6 +921,27 @@ int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv) return 1; } + /* Redirect + * + * Note that it is only OK for us to treat all redirection the same + * because we *always* use GET, not other HTTP methods. There are + * three redirection codes for which it is not appropriate that we + * redirect. Pass on those codes so the error handling kicks in. + */ + if (AllowRedirect + && (Srv->Result > 300 && Srv->Result < 400) + && (Srv->Result != 300 // Multiple Choices + && Srv->Result != 304 // Not Modified + && Srv->Result != 306)) // (Not part of HTTP/1.1, reserved) + { + if (!Srv->Location.empty()) + { + NextURI = Srv->Location; + return 6; + } + /* else pass through for error message */ + } + /* We have a reply we dont handle. This should indicate a perm server failure */ if (Srv->Result < 200 || Srv->Result >= 300) @@ -1028,6 +1059,7 @@ bool HttpMethod::Configuration(string Message) if (pkgAcqMethod::Configuration(Message) == false) return false; + AllowRedirect = _config->FindB("Acquire::http::AllowRedirect",true); TimeOut = _config->FindI("Acquire::http::Timeout",TimeOut); PipelineDepth = _config->FindI("Acquire::http::Pipeline-Depth", PipelineDepth); @@ -1041,6 +1073,10 @@ bool HttpMethod::Configuration(string Message) /* */ int HttpMethod::Loop() { + typedef vector StringVector; + typedef vector::iterator StringVectorIterator; + map Redirected; + signal(SIGTERM,SigTerm); signal(SIGINT,SigTerm); @@ -1227,6 +1263,46 @@ int HttpMethod::Loop() break; } + // Try again with a new URL + case 6: + { + // Clear rest of response if there is content + if (Server->HaveContent) + { + File = new FileFd("/dev/null",FileFd::WriteExists); + Server->RunData(); + delete File; + File = 0; + } + + /* Detect redirect loops. No more redirects are allowed + after the same URI is seen twice in a queue item. */ + StringVector &R = Redirected[Queue->DestFile]; + bool StopRedirects = false; + if (R.size() == 0) + R.push_back(Queue->Uri); + else if (R[0] == "STOP" || R.size() > 10) + StopRedirects = true; + else + { + for (StringVectorIterator I = R.begin(); I != R.end(); I++) + if (Queue->Uri == *I) + { + R[0] = "STOP"; + break; + } + + R.push_back(Queue->Uri); + } + + if (StopRedirects == false) + Redirect(NextURI); + else + Fail(); + + break; + } + default: Fail(_("Internal error")); break; diff --git a/methods/http.h b/methods/http.h index dec5cd80f..bc076e1f8 100644 --- a/methods/http.h +++ b/methods/http.h @@ -99,6 +99,7 @@ struct ServerState enum {Chunked,Stream,Closes} Encoding; enum {Header, Data} State; bool Persistent; + string Location; // This is a Persistent attribute of the server itself. bool Pipeline; @@ -145,6 +146,8 @@ class HttpMethod : public pkgAcqMethod protected: virtual bool Fetch(FetchItem *); + string NextURI; + public: friend class ServerState; diff --git a/methods/makefile b/methods/makefile index 5c4fa82bf..1d022be90 100644 --- a/methods/makefile +++ b/methods/makefile @@ -7,7 +7,7 @@ include ../buildlib/defaults.mak BIN := $(BIN)/methods # FIXME.. -LIB_APT_PKG_MAJOR = 4.6 +LIB_APT_PKG_MAJOR = 4.7 APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR) # The file method -- 2.45.2