#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <climits>
#include <iostream>
#include <map>
string HttpMethod::FailFile;
int HttpMethod::FailFd = -1;
time_t HttpMethod::FailTime = 0;
-unsigned long PipelineDepth = 10;
+unsigned long PipelineDepth = 0;
unsigned long TimeOut = 120;
bool AllowRedirect = false;
bool Debug = false;
if (Line.empty() == true)
return true;
- // The http server might be trying to do something evil.
- if (Line.length() >= MAXLEN)
- return _error->Error(_("Got a single header line over %u chars"),MAXLEN);
-
string::size_type Pos = Line.find(' ');
if (Pos == string::npos || Pos+1 > Line.length())
{
// Evil servers return no version
if (Line[4] == '/')
{
- int const elements = sscanf(Line.c_str(),"HTTP/%u.%u %u%[^\n]",&Major,&Minor,&Result,Code);
+ int const elements = sscanf(Line.c_str(),"HTTP/%3u.%3u %3u%359[^\n]",&Major,&Minor,&Result,Code);
if (elements == 3)
{
Code[0] = '\0';
{
Major = 0;
Minor = 9;
- if (sscanf(Line.c_str(),"HTTP %u%[^\n]",&Result,Code) != 2)
+ if (sscanf(Line.c_str(),"HTTP %3u%359[^\n]",&Result,Code) != 2)
return _error->Error(_("The HTTP server sent an invalid reply header"));
}
Persistent = false;
else
{
- if (Major == 1 && Minor <= 0)
+ if (Major == 1 && Minor == 0)
Persistent = false;
else
Persistent = true;
// The length is already set from the Content-Range header
if (StartPos != 0)
return true;
-
- if (sscanf(Val.c_str(),"%llu",&Size) != 1)
- return _error->Error(_("The HTTP server sent an invalid Content-Length header"));
+
+ Size = strtoull(Val.c_str(), NULL, 10);
+ if (Size >= std::numeric_limits<unsigned long long>::max())
+ return _error->Errno("HeaderLine", _("The HTTP server sent an invalid Content-Length header"));
return true;
}
// The HTTP server expects a hostname with a trailing :port
char Buf[1000];
- string ProperHost = Uri.Host;
+ string ProperHost;
+
+ if (Uri.Host.find(':') != string::npos)
+ ProperHost = '[' + Uri.Host + ']';
+ else
+ ProperHost = Uri.Host;
if (Uri.Port != 0)
{
sprintf(Buf,":%u",Uri.Port);
pass it on, HTTP/1.1 says the connection should default to keep alive
and we expect the proxy to do this */
if (Proxy.empty() == true || Proxy.Host.empty())
+ {
+ // see LP bugs #1003633 and #1086997. The "+" is encoded as a workaround
+ // for a amazon S3 bug
sprintf(Buf,"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n",
- QuoteString(Uri.Path,"~").c_str(),ProperHost.c_str());
+ QuoteString(Uri.Path,"+~ ").c_str(),ProperHost.c_str());
+ }
else
{
/* Generate a cache control header if necessary. We place a max
}
}
-
+ // If we ask for uncompressed files servers might respond with content-
+ // negotation which lets us end up with compressed files we do not support,
+ // see 657029, 657560 and co, so if we have no extension on the request
+ // ask for text only. As a sidenote: If there is nothing to negotate servers
+ // seem to be nice and ignore it.
+ if (_config->FindB("Acquire::http::SendAccept", true) == true)
+ {
+ size_t const filepos = Itm->Uri.find_last_of('/');
+ string const file = Itm->Uri.substr(filepos + 1);
+ if (flExtension(file) == file)
+ strcat(Buf,"Accept: text/*\r\n");
+ }
+
string Req = Buf;
// Check for a partial file
Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n";
}
Req += "User-Agent: " + _config->Find("Acquire::http::User-Agent",
- "Debian APT-HTTP/1.3 ("VERSION")") + "\r\n\r\n";
+ "Debian APT-HTTP/1.3 (" PACKAGE_VERSION ")") + "\r\n\r\n";
if (Debug == true)
cerr << Req << endl;
{
URI Uri = Queue->Uri;
if (Uri.Host.empty() == false)
- {
- if (Uri.Port != 0)
- strprintf(NextURI, "http://%s:%u", Uri.Host.c_str(), Uri.Port);
- else
- NextURI = "http://" + Uri.Host;
- }
+ NextURI = URI::SiteOnly(Uri);
else
NextURI.clear();
NextURI.append(DeQuoteString(Srv->Location));
else
{
NextURI = DeQuoteString(Srv->Location);
- return TRY_AGAIN_OR_REDIRECT;
+ URI tmpURI = NextURI;
+ // Do not allow a redirection to switch protocol
+ if (tmpURI.Access == "http")
+ return TRY_AGAIN_OR_REDIRECT;
}
/* else pass through for error message */
}
after the same URI is seen twice in a queue item. */
StringVector &R = Redirected[Queue->DestFile];
bool StopRedirects = false;
- if (R.size() == 0)
+ if (R.empty() == true)
R.push_back(Queue->Uri);
else if (R[0] == "STOP" || R.size() > 10)
StopRedirects = true;