Author: jgg
Date: 1998-11-01 08:07:11 GMT
HTTP bugs
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: acquire-method.cc,v 1.2 1998/11/01 05:27:30 jgg Exp $
+// $Id: acquire-method.cc,v 1.3 1998/11/01 08:07:11 jgg Exp $
/* ######################################################################
Acquire Method
/* ######################################################################
Acquire Method
exit(100);
SetNonBlock(STDIN_FILENO,true);
exit(100);
SetNonBlock(STDIN_FILENO,true);
}
/*}}}*/
// AcqMethod::Fail - A fetch has failed /*{{{*/
}
/*}}}*/
// AcqMethod::Fail - A fetch has failed /*{{{*/
if (Single == false)
if (WaitFd(STDIN_FILENO) == false)
return 0;
if (Single == false)
if (WaitFd(STDIN_FILENO) == false)
return 0;
- }
-
- if (ReadMessages(STDIN_FILENO,Messages) == false)
- return 0;
+ if (ReadMessages(STDIN_FILENO,Messages) == false)
+ return 0;
+ }
+
// Single mode exits if the message queue is empty
if (Single == true && Messages.empty() == true)
return 0;
// Single mode exits if the message queue is empty
if (Single == true && Messages.empty() == true)
return 0;
// Append it to the list
FetchItem **I = &Queue;
// Append it to the list
FetchItem **I = &Queue;
- for (; *I != 0 && (*I)->Next != 0; I = &(*I)->Next);
+ for (; *I != 0; I = &(*I)->Next);
+ cout << "GOT " << Tmp->Uri << endl;
if (Fetch(Tmp) == false)
Fail();
if (Fetch(Tmp) == false)
Fail();
// sprintf the description
char S[1024];
// sprintf the description
char S[1024];
- unsigned int Len = snprintf(S,sizeof(S),"101 Log\nURI: %s\n"
+ unsigned int Len = snprintf(S,sizeof(S),"101 Status\nURI: %s\n"
"Message: ",CurrentURI.c_str());
vsnprintf(S+Len,sizeof(S)-Len,Format,args);
"Message: ",CurrentURI.c_str());
vsnprintf(S+Len,sizeof(S)-Len,Format,args);
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: strutl.cc,v 1.10 1998/11/01 05:27:37 jgg Exp $
+// $Id: strutl.cc,v 1.11 1998/11/01 08:07:12 jgg Exp $
/* ######################################################################
String Util - Some usefull string functions.
/* ######################################################################
String Util - Some usefull string functions.
// Locate the single / that starts the path
for (; I < U.end(); I++)
{
// Locate the single / that starts the path
for (; I < U.end(); I++)
{
- if (*I == '/' && I[1] == '/')
+ if (*I == '/' && I+1 < U.end() && I[1] == '/')
I += 2;
else
if (*I == '/')
I += 2;
else
if (*I == '/')
// We can now write the access and path specifiers
Access = string(U,0,FirstColon - U.begin());
if (SingleSlash != U.end())
// We can now write the access and path specifiers
Access = string(U,0,FirstColon - U.begin());
if (SingleSlash != U.end())
- Path = string(U,SingleSlash - U.begin() + 1);
-
+ Path = string(U,SingleSlash - U.begin());
+ if (Path.empty() == true)
+ Path = "/";
+
// Now we attempt to locate a user:pass@host fragment
FirstColon += 3;
if (FirstColon >= U.end())
// Now we attempt to locate a user:pass@host fragment
FirstColon += 3;
if (FirstColon >= U.end())
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// -*- 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.
/* ######################################################################
HTTP Aquire Method - This is the HTTP aquire method for APT.
in_addr LastHostA;
bool ServerState::Open()
{
in_addr LastHostA;
bool ServerState::Open()
{
+ // Use the already open connection if possible.
+ if (ServerFd != -1)
+ return true;
+
- if (Proxy.empty() == false)
+ if (Proxy.empty() == true)
- Port = ServerName.Port;
+ if (ServerName.Port != 0)
+ Port = ServerName.Port;
Host = ServerName.Host;
}
else
{
Host = ServerName.Host;
}
else
{
+ if (Proxy.Port != 0)
+ Port = Proxy.Port;
// Lookup the host
hostent *Addr = gethostbyname(Host.c_str());
if (Addr == 0)
// 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]);
}
LastHost = Host;
LastHostA = *(in_addr *)(Addr->h_addr_list[0]);
}
/*}}}*/
// ServerState::RunHeaders - Get the headers before the data /*{{{*/
// ---------------------------------------------------------------------
/*}}}*/
// 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()
Result = 0;
Size = 0;
StartPos = 0;
Result = 0;
Size = 0;
StartPos = 0;
+ Encoding = Closes;
+ HaveContent = false;
string::const_iterator J = I;
for (; J != Data.end() && *J != '\n' && *J != '\r';J++);
if (HeaderLine(string(I,J-I)) == false)
string::const_iterator J = I;
for (; J != Data.end() && *J != '\n' && *J != '\r';J++);
if (HeaderLine(string(I,J-I)) == false)
}
while (Owner->Go(false,this) == true);
}
while (Owner->Go(false,this) == true);
}
/*}}}*/
// ServerState::RunData - Transfer the data from the socket /*{{{*/
}
/*}}}*/
// ServerState::RunData - Transfer the data from the socket /*{{{*/
while ((Last = Owner->Go(false,this)) == true);
if (Last == false)
return false;
while ((Last = Owner->Go(false,this)) == true);
if (Last == false)
return false;
string Tag = string(Line,0,Pos);
string Val = string(Line,Pos+1);
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] == '/')
{
// Evil servers return no version
if (Line[4] == '/')
- if (stringcasecmp(Tag,"Content-Length:"))
+ if (stringcasecmp(Tag,"Content-Length:") == 0)
{
if (Encoding == Closes)
Encoding = Stream;
{
if (Encoding == Closes)
Encoding = Stream;
// The length is already set from the Content-Range header
if (StartPos != 0)
// The length is already set from the Content-Range header
if (StartPos != 0)
- if (stringcasecmp(Tag,"Content-Range:"))
+ if (stringcasecmp(Tag,"Content-Type:") == 0)
+ {
+ HaveContent = true;
+ return true;
+ }
+
+ if (stringcasecmp(Tag,"Content-Range:") == 0)
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)
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)
- if (stringcasecmp(Tag,"Transfer-Encoding:"))
+ if (stringcasecmp(Tag,"Transfer-Encoding:") == 0)
- if (stringcasecmp(Val,"chunked"))
+ HaveContent = true;
+ if (stringcasecmp(Val,"chunked") == 0)
- if (stringcasecmp(Tag,"Last-Modified:"))
+ if (stringcasecmp(Tag,"Last-Modified:") == 0)
{
if (StrToTime(Val,Date) == false)
return _error->Error("Unknown date format");
{
if (StrToTime(Val,Date) == false)
return _error->Error("Unknown date format");
Req += string("Proxy-Authorization: Basic ") + Base64Encode(ProxyAuth) + "\r\n";*/
Req += "User-Agent: Debian APT-HTTP/1.2\r\n\r\n";
Req += string("Proxy-Authorization: Basic ") + Base64Encode(ProxyAuth) + "\r\n";*/
Req += "User-Agent: Debian APT-HTTP/1.2\r\n\r\n";
+// cout << Req << endl;
+
{
if (Srv->In.Write(File->Fd()) == false)
return _error->Errno("write","Error writing to file");
{
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)
}
if (Srv->In.IsLimit() == true || Srv->Encoding == ServerState::Closes)
{
if (Srv->In.Write(File->Fd()) == false)
return _error->Errno("write","Error writing to the file");
{
if (Srv->In.Write(File->Fd()) == false)
return _error->Errno("write","Error writing to the file");
+
+ // Done
+ if (Srv->In.IsLimit() == true)
+ return true;
to do. Returns
0 - File is open,
1 - IMS hit
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
int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
{
// Not Modified
if (Srv->Result < 200 || Srv->Result >= 300)
{
_error->Error("%u %s",Srv->Result,Srv->Code);
if (Srv->Result < 200 || Srv->Result >= 300)
{
_error->Error("%u %s",Srv->Result,Srv->Code);
+ if (Srv->HaveContent == true)
+ return 4;
{
ServerState *Server = 0;
{
ServerState *Server = 0;
+ if (FailCounter >= 2)
+ {
+ Fail("Massive Server Brain Damage");
+ FailCounter = 0;
+ }
+
// We have no commands, wait for some to arrive
if (Queue == 0)
{
// We have no commands, wait for some to arrive
if (Queue == 0)
{
- 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;
// Decide what to do.
FetchResult Res;
// Run the data
if (Server->RunData() == false)
Fail();
// 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;
delete File;
File = 0;
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;
default:
Fail("Internal error");
break;
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: http.h,v 1.1 1998/11/01 05:30:47 jgg Exp $
+// $Id: http.h,v 1.2 1998/11/01 08:07:14 jgg Exp $
/* ######################################################################
HTTP Aquire Method - This is the HTTP aquire method for APT.
/* ######################################################################
HTTP Aquire Method - This is the HTTP aquire method for APT.
unsigned int Result;
char Code[MAXLEN];
unsigned int Result;
char Code[MAXLEN];
- // These are some statistics from the last parsed get line
+ // These are some statistics from the last parsed header lines
unsigned long Size;
signed long StartPos;
time_t Date;
unsigned long Size;
signed long StartPos;
time_t Date;
enum {Chunked,Stream,Closes} Encoding;
enum {Header, Data} State;
enum {Chunked,Stream,Closes} Encoding;
enum {Header, Data} State;
bool Comp(URI Other) {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
void Reset() {Major = 0; Minor = 0; Result = 0; Size = 0; StartPos = 0;
Encoding = Closes; time(&Date); ServerFd = -1;};
bool Comp(URI Other) {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
void Reset() {Major = 0; Minor = 0; Result = 0; Size = 0; StartPos = 0;
Encoding = Closes; time(&Date); ServerFd = -1;};
bool RunData();
bool Open();
bool RunData();
bool Open();
public:
friend ServerState;
public:
friend ServerState;
HttpMethod() : pkgAcqMethod("1.2",SingleInstance | Pipeline | SendConfig)
{
Depth = 0;
HttpMethod() : pkgAcqMethod("1.2",SingleInstance | Pipeline | SendConfig)
{
Depth = 0;
{
signal(SIGPIPE,SIG_IGN);
{
signal(SIGPIPE,SIG_IGN);
cout << Foo.Access << '\'' << endl;
cout << Foo.Host << '\'' << endl;
cout << Foo.Path << '\'' << endl;
cout << Foo.Access << '\'' << endl;
cout << Foo.Host << '\'' << endl;
cout << Foo.Path << '\'' << endl;
cout << Foo.Password << '\'' << endl;
cout << Foo.Port << endl;
cout << Foo.Password << '\'' << endl;
cout << Foo.Port << endl;
pkgInitialize(*_config);
pkgSourceList List;
pkgInitialize(*_config);
pkgSourceList List;