X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/f8081133c528e8c91b533b4fab6f56ae42d51ecb..ff6bf1be3844bcda15303efc81e234ede7501e3c:/methods/ftp.cc diff --git a/methods/ftp.cc b/methods/ftp.cc index e0f71239f..0c2aa00a7 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -1,9 +1,9 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: ftp.cc,v 1.22 2001/02/23 05:45:27 jgg Exp $ +// $Id: ftp.cc,v 1.31.2.1 2004/01/16 18:58:50 mdz Exp $ /* ###################################################################### - HTTP Aquire Method - This is the FTP aquire method for APT. + FTP Aquire Method - This is the FTP aquire method for APT. This is a very simple implementation that does not try to optimize at all. Commands are sent syncronously with the FTP server (as the @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -28,6 +28,8 @@ #include #include #include +#include +#include // Internet stuff #include @@ -40,6 +42,8 @@ #include "ftp.h" /*}}}*/ +using namespace std; + /* This table is for the EPRT and EPSV commands, it maps the OS address family to the IETF address families */ struct AFMap @@ -153,19 +157,22 @@ bool FTPConn::Open(pkgAcqMethod *Owner) RotateDNS(); if (Connect(Host,Port,"ftp",21,ServerFd,TimeOut,Owner) == false) return false; + + // Login must be before getpeername otherwise dante won't work. + Owner->Status(_("Logging in")); + bool Res = Login(); // Get the remote server's address PeerAddrLen = sizeof(PeerAddr); if (getpeername(ServerFd,(sockaddr *)&PeerAddr,&PeerAddrLen) != 0) - return _error->Errno("getpeername","Unable to determine the peer name"); + return _error->Errno("getpeername",_("Unable to determine the peer name")); // Get the local machine's address ServerAddrLen = sizeof(ServerAddr); if (getsockname(ServerFd,(sockaddr *)&ServerAddr,&ServerAddrLen) != 0) - return _error->Errno("getsockname","Unable to determine the local name"); + return _error->Errno("getsockname",_("Unable to determine the local name")); - Owner->Status("Logging in"); - return Login(); + return Res; } /*}}}*/ // FTPConn::Login - Login to the remote server /*{{{*/ @@ -179,7 +186,7 @@ bool FTPConn::Login() // Setup the variables needed for authentication string User = "anonymous"; - string Pass = "apt_get_ftp_2.0@debian.linux.user"; + string Pass = "apt_get_ftp_2.1@debian.linux.user"; // Fill in the user/pass if (ServerName.User.empty() == false) @@ -194,19 +201,21 @@ bool FTPConn::Login() if (ReadResp(Tag,Msg) == false) return false; if (Tag >= 400) - return _error->Error("Server refused our connection and said: %s",Msg.c_str()); + return _error->Error(_("The server refused the connection and said: %s"),Msg.c_str()); // Send the user if (WriteMsg(Tag,Msg,"USER %s",User.c_str()) == false) return false; if (Tag >= 400) - return _error->Error("USER failed, server said: %s",Msg.c_str()); + return _error->Error(_("USER failed, server said: %s"),Msg.c_str()); - // Send the Password - if (WriteMsg(Tag,Msg,"PASS %s",Pass.c_str()) == false) - return false; - if (Tag >= 400) - return _error->Error("PASS failed, server said: %s",Msg.c_str()); + if (Tag == 331) { // 331 User name okay, need password. + // Send the Password + if (WriteMsg(Tag,Msg,"PASS %s",Pass.c_str()) == false) + return false; + if (Tag >= 400) + return _error->Error(_("PASS failed, server said: %s"),Msg.c_str()); + } // Enter passive mode if (_config->Exists("Acquire::FTP::Passive::" + ServerName.Host) == true) @@ -220,13 +229,13 @@ bool FTPConn::Login() if (ReadResp(Tag,Msg) == false) return false; if (Tag >= 400) - return _error->Error("Server refused our connection and said: %s",Msg.c_str()); + return _error->Error(_("The server refused the connection and said: %s"),Msg.c_str()); // Perform proxy script execution Configuration::Item const *Opts = _config->Tree("Acquire::ftp::ProxyLogin"); if (Opts == 0 || Opts->Child == 0) - return _error->Error("A proxy server was specified but no login " - "script, Acquire::ftp::ProxyLogin is empty."); + return _error->Error(_("A proxy server was specified but no login " + "script, Acquire::ftp::ProxyLogin is empty.")); Opts = Opts->Child; // Iterate over the entire login script @@ -253,7 +262,7 @@ bool FTPConn::Login() if (WriteMsg(Tag,Msg,"%s",Tmp.c_str()) == false) return false; if (Tag >= 400) - return _error->Error("Login script command '%s' failed, server said: %s",Tmp.c_str(),Msg.c_str()); + return _error->Error(_("Login script command '%s' failed, server said: %s"),Tmp.c_str(),Msg.c_str()); } // Enter passive mode @@ -279,7 +288,7 @@ bool FTPConn::Login() if (WriteMsg(Tag,Msg,"TYPE I") == false) return false; if (Tag >= 400) - return _error->Error("TYPE failed, server said: %s",Msg.c_str()); + return _error->Error(_("TYPE failed, server said: %s"),Msg.c_str()); return true; } @@ -317,23 +326,23 @@ bool FTPConn::ReadLine(string &Text) if (WaitFd(ServerFd,false,TimeOut) == false) { Close(); - return _error->Error("Connection timeout"); + return _error->Error(_("Connection timeout")); } // Suck it back int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len); if (Res == 0) - _error->Error("Server closed the connection"); + _error->Error(_("Server closed the connection")); if (Res <= 0) { - _error->Errno("read","Read error"); + _error->Errno("read",_("Read error")); Close(); return false; } Len += Res; } - return _error->Error("A response overflowed the buffer."); + return _error->Error(_("A response overflowed the buffer.")); } /*}}}*/ // FTPConn::ReadResp - Read a full response from the server /*{{{*/ @@ -350,7 +359,7 @@ bool FTPConn::ReadResp(unsigned int &Ret,string &Text) char *End; Ret = strtol(Msg.c_str(),&End,10); if (End - Msg.c_str() != 3) - return _error->Error("Protocol corruption"); + return _error->Error(_("Protocol corruption")); // All done ? Text = Msg.c_str()+4; @@ -362,7 +371,7 @@ bool FTPConn::ReadResp(unsigned int &Ret,string &Text) } if (*End != '-') - return _error->Error("Protocol corruption"); + return _error->Error(_("Protocol corruption")); /* Okay, here we do the continued message trick. This is foolish, but proftpd follows the protocol as specified and wu-ftpd doesn't, so @@ -428,13 +437,13 @@ bool FTPConn::WriteMsg(unsigned int &Ret,string &Text,const char *Fmt,...) if (WaitFd(ServerFd,true,TimeOut) == false) { Close(); - return _error->Error("Connection timeout"); + return _error->Error(_("Connection timeout")); } int Res = write(ServerFd,S + Start,Len); if (Res <= 0) { - _error->Errno("write","Write Error"); + _error->Errno("write",_("Write error")); Close(); return false; } @@ -675,24 +684,24 @@ bool FTPConn::CreateDataFd() // Get a socket if ((DataFd = socket(PasvAddr->ai_family,PasvAddr->ai_socktype, PasvAddr->ai_protocol)) < 0) - return _error->Errno("socket","Could not create a socket"); + return _error->Errno("socket",_("Could not create a socket")); // Connect to the server SetNonBlock(DataFd,true); if (connect(DataFd,PasvAddr->ai_addr,PasvAddr->ai_addrlen) < 0 && errno != EINPROGRESS) - return _error->Errno("socket","Could not create a socket"); + return _error->Errno("socket",_("Could not create a socket")); /* This implements a timeout for connect by opening the connection nonblocking */ if (WaitFd(DataFd,true,TimeOut) == false) - return _error->Error("Could not connect data socket, connection timed out"); + return _error->Error(_("Could not connect data socket, connection timed out")); unsigned int Err; unsigned int Len = sizeof(Err); if (getsockopt(DataFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0) - return _error->Errno("getsockopt","Failed"); + return _error->Errno("getsockopt",_("Failed")); if (Err != 0) - return _error->Error("Could not connect passive socket."); + return _error->Error(_("Could not connect passive socket.")); return true; } @@ -710,32 +719,33 @@ bool FTPConn::CreateDataFd() Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family; int Res; if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0) - return _error->Error("getaddrinfo was unable to get a listening socket"); + return _error->Error(_("getaddrinfo was unable to get a listening socket")); // Construct the socket if ((DataListenFd = socket(BindAddr->ai_family,BindAddr->ai_socktype, BindAddr->ai_protocol)) < 0) { freeaddrinfo(BindAddr); - return _error->Errno("socket","Could not create a socket"); + return _error->Errno("socket",_("Could not create a socket")); } // Bind and listen if (bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0) { freeaddrinfo(BindAddr); - return _error->Errno("bind","Could not bind a socket"); + return _error->Errno("bind",_("Could not bind a socket")); } freeaddrinfo(BindAddr); if (listen(DataListenFd,1) < 0) - return _error->Errno("listen","Could not listen on the socket"); + return _error->Errno("listen",_("Could not listen on the socket")); SetNonBlock(DataListenFd,true); // Determine the name to send to the remote struct sockaddr_storage Addr; socklen_t AddrLen = sizeof(Addr); if (getsockname(DataListenFd,(sockaddr *)&Addr,&AddrLen) < 0) - return _error->Errno("getsockname","Could not determine the socket's name"); + return _error->Errno("getsockname",_("Could not determine the socket's name")); + // Reverse the address. We need the server address and the data port. char Name[NI_MAXHOST]; @@ -766,7 +776,7 @@ bool FTPConn::CreateDataFd() (int)(Port >> 8) & 0xff, (int)(Port & 0xff)) == false) return false; if (Tag >= 400) - return _error->Error("Unable to send PORT command"); + return _error->Error(_("Unable to send PORT command")); return true; } @@ -776,7 +786,7 @@ bool FTPConn::CreateDataFd() if (AFMap[J].Family == ((struct sockaddr *)&Addr)->sa_family) Proto = AFMap[J].IETFFamily; if (Proto == 0) - return _error->Error("Unkonwn address family %u (AF_*)", + return _error->Error(_("Unknown address family %u (AF_*)"), ((struct sockaddr *)&Addr)->sa_family); // Send the EPRT command @@ -785,7 +795,7 @@ bool FTPConn::CreateDataFd() if (WriteMsg(Tag,Msg,"EPRT |%u|%s|%s|",Proto,Name,Service) == false) return false; if (Tag >= 400) - return _error->Error("EPRT failed, server said: %s",Msg.c_str()); + return _error->Error(_("EPRT failed, server said: %s"),Msg.c_str()); return true; } /*}}}*/ @@ -805,14 +815,14 @@ bool FTPConn::Finalize() // Wait for someone to connect.. if (WaitFd(DataListenFd,false,TimeOut) == false) - return _error->Error("Data socket connect timed out"); + return _error->Error(_("Data socket connect timed out")); // Accept the connection struct sockaddr_in Addr; socklen_t Len = sizeof(Addr); DataFd = accept(DataListenFd,(struct sockaddr *)&Addr,&Len); if (DataFd < 0) - return _error->Errno("accept","Unable to accept connection"); + return _error->Errno("accept",_("Unable to accept connection")); close(DataListenFd); DataListenFd = -1; @@ -825,7 +835,7 @@ bool FTPConn::Finalize() /* This opens a data connection, sends REST and RETR and then transfers the file over. */ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, - MD5Summation &MD5,bool &Missing) + Hashes &Hash,bool &Missing) { Missing = false; if (CreateDataFd() == false) @@ -849,9 +859,9 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, if (Resume != 0) { - if (MD5.AddFD(To.Fd(),Resume) == false) + if (Hash.AddFD(To.Fd(),Resume) == false) { - _error->Errno("read","Problem hashing file"); + _error->Errno("read",_("Problem hashing file")); return false; } } @@ -864,7 +874,7 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, { if (Tag == 550) Missing = true; - return _error->Error("Unable to fetch file, server said '%s'",Msg.c_str()); + return _error->Error(_("Unable to fetch file, server said '%s'"),Msg.c_str()); } // Finish off the data connection @@ -879,7 +889,7 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, if (WaitFd(DataFd,false,TimeOut) == false) { Close(); - return _error->Error("Data socket timed out"); + return _error->Error(_("Data socket timed out")); } // Read the data.. @@ -893,7 +903,7 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, break; } - MD5.Add(Buffer,Res); + Hash.Add(Buffer,Res); if (To.Write(Buffer,Res) == false) { Close(); @@ -909,7 +919,7 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, if (ReadResp(Tag,Msg) == false) return false; if (Tag >= 400) - return _error->Error("Data transfer failed, server said '%s'",Msg.c_str()); + return _error->Error(_("Data transfer failed, server said '%s'"),Msg.c_str()); return true; } /*}}}*/ @@ -984,7 +994,7 @@ bool FtpMethod::Fetch(FetchItem *Itm) } // Get the files information - Status("Query"); + Status(_("Query")); unsigned long Size; if (Server->Size(File,Size) == false || Server->ModTime(File,FailTime) == false) @@ -1022,7 +1032,7 @@ bool FtpMethod::Fetch(FetchItem *Itm) } // Open the file - MD5Summation MD5; + Hashes Hash; { FileFd Fd(Itm->DestFile,FileFd::WriteAny); if (_error->PendingError() == true) @@ -1035,7 +1045,7 @@ bool FtpMethod::Fetch(FetchItem *Itm) FailFd = Fd.Fd(); bool Missing; - if (Server->Get(File,Fd,Res.ResumePoint,MD5,Missing) == false) + if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing) == false) { Fd.Close(); @@ -1045,9 +1055,12 @@ bool FtpMethod::Fetch(FetchItem *Itm) UBuf.modtime = FailTime; utime(FailFile.c_str(),&UBuf); - // If the file is missing we hard fail otherwise transient fail - if (Missing == true) + // If the file is missing we hard fail and delete the destfile + // otherwise transient fail + if (Missing == true) { + unlink(FailFile.c_str()); return false; + } Fail(true); return true; } @@ -1056,7 +1069,7 @@ bool FtpMethod::Fetch(FetchItem *Itm) } Res.LastModified = FailTime; - Res.MD5Sum = MD5.Result(); + Res.TakeHashes(Hash); // Timestamp struct utimbuf UBuf; @@ -1073,19 +1086,14 @@ bool FtpMethod::Fetch(FetchItem *Itm) int main(int argc,const char *argv[]) { + setlocale(LC_ALL, ""); + /* See if we should be come the http client - we do this for http proxy urls */ if (getenv("ftp_proxy") != 0) { URI Proxy = string(getenv("ftp_proxy")); - // Parse no_proxy, a , separated list of domains - if (getenv("no_proxy") != 0) - { - if (CheckDomainList(Proxy.Host,getenv("no_proxy")) == true) - Proxy.Access = ""; - } - // Run the HTTP method if (Proxy.Access == "http") { @@ -1093,11 +1101,12 @@ int main(int argc,const char *argv[]) char S[300]; snprintf(S,sizeof(S),"http_proxy=%s",getenv("ftp_proxy")); putenv(S); + putenv("no_proxy="); // Run the http method - string Path = flNotFile(argv[0]) + "/http"; - execl(Path.c_str(),Path.c_str(),0); - cerr << "Unable to invoke " << Path << endl; + string Path = flNotFile(argv[0]) + "http"; + execl(Path.c_str(),Path.c_str(),(char *)NULL); + cerr << _("Unable to invoke ") << Path << endl; exit(100); } }