|
|
@@ -1,6 +1,6 @@
|
|
|
// -*- mode: cpp; mode: fold -*-
|
|
|
// Description /*{{{*/
|
|
|
-// $Id: http.cc,v 1.1 1998/11/01 05:30:47 jgg Exp $
|
|
|
+// $Id: http.cc,v 1.2 1998/11/01 08:07:13 jgg Exp $
|
|
|
/* ######################################################################
|
|
|
|
|
|
HTTP Aquire Method - This is the HTTP aquire method for APT.
|
|
|
@@ -253,19 +253,25 @@ string LastHost;
|
|
|
in_addr LastHostA;
|
|
|
bool ServerState::Open()
|
|
|
{
|
|
|
+ // Use the already open connection if possible.
|
|
|
+ if (ServerFd != -1)
|
|
|
+ return true;
|
|
|
+
|
|
|
Close();
|
|
|
|
|
|
- int Port;
|
|
|
+ int Port = 80;
|
|
|
string Host;
|
|
|
|
|
|
- if (Proxy.empty() == false)
|
|
|
+ if (Proxy.empty() == true)
|
|
|
{
|
|
|
- Port = ServerName.Port;
|
|
|
+ if (ServerName.Port != 0)
|
|
|
+ Port = ServerName.Port;
|
|
|
Host = ServerName.Host;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- Port = Proxy.Port;
|
|
|
+ if (Proxy.Port != 0)
|
|
|
+ Port = Proxy.Port;
|
|
|
Host = Proxy.Host;
|
|
|
}
|
|
|
|
|
|
@@ -276,7 +282,7 @@ bool ServerState::Open()
|
|
|
// Lookup the host
|
|
|
hostent *Addr = gethostbyname(Host.c_str());
|
|
|
if (Addr == 0)
|
|
|
- return _error->Errno("gethostbyname","Could not lookup host %s",Host.c_str());
|
|
|
+ return _error->Error("Could not resolve '%s'",Host.c_str());
|
|
|
LastHost = Host;
|
|
|
LastHostA = *(in_addr *)(Addr->h_addr_list[0]);
|
|
|
}
|
|
|
@@ -313,8 +319,9 @@ bool ServerState::Close()
|
|
|
/*}}}*/
|
|
|
// ServerState::RunHeaders - Get the headers before the data /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
|
-/* */
|
|
|
-bool ServerState::RunHeaders()
|
|
|
+/* Returns 0 if things are OK, 1 if an IO error occursed and 2 if a header
|
|
|
+ parse error occured */
|
|
|
+int ServerState::RunHeaders()
|
|
|
{
|
|
|
State = Header;
|
|
|
|
|
|
@@ -325,7 +332,8 @@ bool ServerState::RunHeaders()
|
|
|
Result = 0;
|
|
|
Size = 0;
|
|
|
StartPos = 0;
|
|
|
- Encoding = Closes;
|
|
|
+ Encoding = Closes;
|
|
|
+ HaveContent = false;
|
|
|
time(&Date);
|
|
|
|
|
|
do
|
|
|
@@ -339,14 +347,14 @@ bool ServerState::RunHeaders()
|
|
|
string::const_iterator J = I;
|
|
|
for (; J != Data.end() && *J != '\n' && *J != '\r';J++);
|
|
|
if (HeaderLine(string(I,J-I)) == false)
|
|
|
- return false;
|
|
|
+ return 2;
|
|
|
I = J;
|
|
|
}
|
|
|
- return true;
|
|
|
+ return 0;
|
|
|
}
|
|
|
while (Owner->Go(false,this) == true);
|
|
|
-
|
|
|
- return false;
|
|
|
+
|
|
|
+ return 1;
|
|
|
}
|
|
|
/*}}}*/
|
|
|
// ServerState::RunData - Transfer the data from the socket /*{{{*/
|
|
|
@@ -415,7 +423,7 @@ bool ServerState::RunData()
|
|
|
while ((Last = Owner->Go(false,this)) == true);
|
|
|
if (Last == false)
|
|
|
return false;
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -460,7 +468,7 @@ bool ServerState::HeaderLine(string Line)
|
|
|
string Tag = string(Line,0,Pos);
|
|
|
string Val = string(Line,Pos+1);
|
|
|
|
|
|
- if (stringcasecmp(Tag,"HTTP") == 0)
|
|
|
+ if (stringcasecmp(Tag.begin(),Tag.begin()+4,"HTTP") == 0)
|
|
|
{
|
|
|
// Evil servers return no version
|
|
|
if (Line[4] == '/')
|
|
|
@@ -480,10 +488,11 @@ bool ServerState::HeaderLine(string Line)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- if (stringcasecmp(Tag,"Content-Length:"))
|
|
|
+ if (stringcasecmp(Tag,"Content-Length:") == 0)
|
|
|
{
|
|
|
if (Encoding == Closes)
|
|
|
Encoding = Stream;
|
|
|
+ HaveContent = true;
|
|
|
|
|
|
// The length is already set from the Content-Range header
|
|
|
if (StartPos != 0)
|
|
|
@@ -494,8 +503,16 @@ bool ServerState::HeaderLine(string Line)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- if (stringcasecmp(Tag,"Content-Range:"))
|
|
|
+ if (stringcasecmp(Tag,"Content-Type:") == 0)
|
|
|
+ {
|
|
|
+ HaveContent = true;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stringcasecmp(Tag,"Content-Range:") == 0)
|
|
|
{
|
|
|
+ HaveContent = true;
|
|
|
+
|
|
|
if (sscanf(Val.c_str(),"bytes %lu-%*u/%lu",&StartPos,&Size) != 2)
|
|
|
return _error->Error("The http server sent an invalid Content-Range header");
|
|
|
if ((unsigned)StartPos > Size)
|
|
|
@@ -503,14 +520,16 @@ bool ServerState::HeaderLine(string Line)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- if (stringcasecmp(Tag,"Transfer-Encoding:"))
|
|
|
+ if (stringcasecmp(Tag,"Transfer-Encoding:") == 0)
|
|
|
{
|
|
|
- if (stringcasecmp(Val,"chunked"))
|
|
|
+ HaveContent = true;
|
|
|
+ if (stringcasecmp(Val,"chunked") == 0)
|
|
|
Encoding = Chunked;
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- if (stringcasecmp(Tag,"Last-Modified:"))
|
|
|
+ if (stringcasecmp(Tag,"Last-Modified:") == 0)
|
|
|
{
|
|
|
if (StrToTime(Val,Date) == false)
|
|
|
return _error->Error("Unknown date format");
|
|
|
@@ -568,6 +587,8 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out)
|
|
|
Req += string("Proxy-Authorization: Basic ") + Base64Encode(ProxyAuth) + "\r\n";*/
|
|
|
|
|
|
Req += "User-Agent: Debian APT-HTTP/1.2\r\n\r\n";
|
|
|
+// cout << Req << endl;
|
|
|
+
|
|
|
Out.Read(Req);
|
|
|
}
|
|
|
/*}}}*/
|
|
|
@@ -681,6 +702,8 @@ bool HttpMethod::Flush(ServerState *Srv)
|
|
|
{
|
|
|
if (Srv->In.Write(File->Fd()) == false)
|
|
|
return _error->Errno("write","Error writing to file");
|
|
|
+ if (Srv->In.IsLimit() == true)
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
if (Srv->In.IsLimit() == true || Srv->Encoding == ServerState::Closes)
|
|
|
@@ -702,6 +725,10 @@ bool HttpMethod::ServerDie(ServerState *Srv)
|
|
|
{
|
|
|
if (Srv->In.Write(File->Fd()) == false)
|
|
|
return _error->Errno("write","Error writing to the file");
|
|
|
+
|
|
|
+ // Done
|
|
|
+ if (Srv->In.IsLimit() == true)
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -735,7 +762,8 @@ bool HttpMethod::ServerDie(ServerState *Srv)
|
|
|
to do. Returns
|
|
|
0 - File is open,
|
|
|
1 - IMS hit
|
|
|
- 3 - Unrecoverable error */
|
|
|
+ 3 - Unrecoverable error
|
|
|
+ 4 - Error with error content page */
|
|
|
int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
|
|
|
{
|
|
|
// Not Modified
|
|
|
@@ -752,6 +780,8 @@ int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
|
|
|
if (Srv->Result < 200 || Srv->Result >= 300)
|
|
|
{
|
|
|
_error->Error("%u %s",Srv->Result,Srv->Code);
|
|
|
+ if (Srv->HaveContent == true)
|
|
|
+ return 4;
|
|
|
return 3;
|
|
|
}
|
|
|
|
|
|
@@ -801,8 +831,15 @@ int HttpMethod::Loop()
|
|
|
{
|
|
|
ServerState *Server = 0;
|
|
|
|
|
|
+ int FailCounter = 0;
|
|
|
while (1)
|
|
|
{
|
|
|
+ if (FailCounter >= 2)
|
|
|
+ {
|
|
|
+ Fail("Massive Server Brain Damage");
|
|
|
+ FailCounter = 0;
|
|
|
+ }
|
|
|
+
|
|
|
// We have no commands, wait for some to arrive
|
|
|
if (Queue == 0)
|
|
|
{
|
|
|
@@ -832,14 +869,32 @@ int HttpMethod::Loop()
|
|
|
}
|
|
|
|
|
|
// Queue the request
|
|
|
- SendReq(Queue,Server->In);
|
|
|
+ SendReq(Queue,Server->Out);
|
|
|
|
|
|
- // Handle the header data
|
|
|
- if (Server->RunHeaders() == false)
|
|
|
+ // Fetch the next URL header data from the server.
|
|
|
+ switch (Server->RunHeaders())
|
|
|
{
|
|
|
- Fail();
|
|
|
- continue;
|
|
|
- }
|
|
|
+ case 0:
|
|
|
+ break;
|
|
|
+
|
|
|
+ // The header data is bad
|
|
|
+ case 2:
|
|
|
+ {
|
|
|
+ _error->Error("Bad header Data");
|
|
|
+ Fail();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // The server closed a connection during the header get..
|
|
|
+ default:
|
|
|
+ case 1:
|
|
|
+ {
|
|
|
+ FailCounter++;
|
|
|
+ _error->DumpErrors();
|
|
|
+ Server->Close();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
// Decide what to do.
|
|
|
FetchResult Res;
|
|
|
@@ -853,8 +908,12 @@ int HttpMethod::Loop()
|
|
|
// Run the data
|
|
|
if (Server->RunData() == false)
|
|
|
Fail();
|
|
|
-
|
|
|
- Res.MD5Sum = Srv->In.MD5->Result();
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Res.MD5Sum = Server->In.MD5->Result();
|
|
|
+ URIDone(Res);
|
|
|
+ }
|
|
|
+
|
|
|
delete File;
|
|
|
File = 0;
|
|
|
break;
|
|
|
@@ -873,11 +932,26 @@ int HttpMethod::Loop()
|
|
|
Fail();
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ // We need to flush the data, the header is like a 404 w/ error text
|
|
|
+ case 4:
|
|
|
+ {
|
|
|
+ Fail();
|
|
|
+
|
|
|
+ // Send to content to dev/null
|
|
|
+ File = new FileFd("/dev/null",FileFd::WriteExists);
|
|
|
+ Server->RunData();
|
|
|
+ delete File;
|
|
|
+ File = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
default:
|
|
|
Fail("Internal error");
|
|
|
break;
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ FailCounter = 0;
|
|
|
}
|
|
|
|
|
|
return 0;
|