📄 ftpclnt.cxx
字号:
/* * ftpclnt.cxx * * FTP client class. * * Portable Windows Library * * Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): ______________________________________. * * $Log: ftpclnt.cxx,v $ * Revision 1.9 2000/06/21 01:14:23 robertj * AIX port, thanks Wolfgang Platzer (wolfgang.platzer@infonova.at). * * Revision 1.8 2000/04/07 06:29:46 rogerh * Add a short term workaround for an Internal Compiler Error on MAC OS X when * returning certain types of PString. Submitted by Kevin Packard. * * Revision 1.7 1998/12/23 00:34:55 robertj * Fixed normal TCP socket support after adding SOCKS support. * * Revision 1.6 1998/12/22 10:29:42 robertj * Added support for SOCKS based channels. * * Revision 1.5 1998/12/18 03:48:32 robertj * Fixed wanring on PPC linux compile * * Revision 1.4 1998/11/30 04:50:47 robertj * New directory structure * * Revision 1.3 1998/09/23 06:22:00 robertj * Added open source copyright license. * * Revision 1.2 1997/03/28 13:06:58 robertj * made STAT command more robust for getting file info from weird FTP servers. * * Revision 1.1 1996/09/14 13:02:18 robertj * Initial revision * */#include <ptlib.h>#include <ptlib/sockets.h>#include <ptclib/ftp.h>/////////////////////////////////////////////////////////// FTP ClientPFTPClient::PFTPClient(){}PFTPClient::~PFTPClient(){ Close();}BOOL PFTPClient::Close(){ if (!IsOpen()) return FALSE; BOOL ok = ExecuteCommand(QUIT)/100 == 2; return PFTP::Close() && ok;}BOOL PFTPClient::OnOpen(){ if (!ReadResponse() || lastResponseCode != 220) return FALSE; // the default data port for a server is the adjacent port PIPSocket::Address remoteHost; PIPSocket * socket = GetSocket(); if (socket == NULL) return FALSE; socket->GetPeerAddress(remoteHost, remotePort); remotePort--; return TRUE;}BOOL PFTPClient::LogIn(const PString & username, const PString & password){ if (ExecuteCommand(USER, username)/100 != 3) return FALSE; return ExecuteCommand(PASS, password)/100 == 2;}PString PFTPClient::GetSystemType(){ if (ExecuteCommand(SYST)/100 != 2) return PString(); return lastResponseInfo.Left(lastResponseInfo.Find(' '));}BOOL PFTPClient::SetType(RepresentationType type){ static const char * const typeCode[] = { "A", "E", "I" }; PAssert((PINDEX)type < PARRAYSIZE(typeCode), PInvalidParameter); return ExecuteCommand(TYPE, typeCode[type])/100 == 2;}BOOL PFTPClient::ChangeDirectory(const PString & dirPath){ return ExecuteCommand(CWD, dirPath)/100 == 2;}PString PFTPClient::GetCurrentDirectory(){ if (ExecuteCommand(PWD) != 257) return PString(); PINDEX quote1 = lastResponseInfo.Find('"'); if (quote1 == P_MAX_INDEX) return PString(); PINDEX quote2 = quote1 + 1; do { quote2 = lastResponseInfo.Find('"', quote2); if (quote2 == P_MAX_INDEX) return PString(); while (lastResponseInfo[quote2]=='"' && lastResponseInfo[quote2+1]=='"') quote2 += 2; } while (lastResponseInfo[quote2] != '"');#if defined(P_MACOSX) // make Apple's gnu compiler happy PString retval = lastResponseInfo(quote1+1, quote2-1); return retval;#else return lastResponseInfo(quote1+1, quote2-1);#endif}PStringArray PFTPClient::GetDirectoryNames(NameTypes type, DataChannelType ctype){ return GetDirectoryNames(PString(), type, ctype);}PStringArray PFTPClient::GetDirectoryNames(const PString & path, NameTypes type, DataChannelType ctype){ SetType(PFTP::ASCII); Commands lcmd = type == DetailedNames ? LIST : NLST; PTCPSocket * socket = ctype != Passive ? NormalClientTransfer(lcmd, path) : PassiveClientTransfer(lcmd, path); if (socket == NULL) return PStringArray(); PString response = lastResponseInfo; PString str; int count = 0; while(socket->Read(str.GetPointer(count+1000)+count, 1000)) count += socket->GetLastReadCount(); str.SetSize(count+1); delete socket; ReadResponse(); lastResponseInfo = response + '\n' + lastResponseInfo; return str.Lines();}PString PFTPClient::GetFileStatus(const PString & path, DataChannelType ctype){ if (ExecuteCommand(STATcmd, path)/100 == 2 && lastResponseInfo.Find(path) != P_MAX_INDEX) { PINDEX start = lastResponseInfo.Find('\n'); if (start != P_MAX_INDEX) { PINDEX end = lastResponseInfo.Find('\n', ++start); if (end != P_MAX_INDEX) return lastResponseInfo(start, end-1); } } PTCPSocket * socket = ctype != Passive ? NormalClientTransfer(LIST, path) : PassiveClientTransfer(LIST, path); if (socket == NULL) return PString(); PString str; socket->Read(str.GetPointer(200), 199); str[socket->GetLastReadCount()] = '\0'; delete socket; ReadResponse(); PINDEX end = str.FindOneOf("\r\n"); if (end != P_MAX_INDEX) str[end] = '\0'; return str;}PTCPSocket * PFTPClient::NormalClientTransfer(Commands cmd, const PString & args){ PIPSocket * socket = GetSocket(); if (socket == NULL) return NULL; // setup a socket so we can tell the host where to connect to PTCPSocket * listenSocket = (PTCPSocket *)socket->Clone(); listenSocket->SetPort(0); // Want new random port number listenSocket->Listen(); // The following is just used to automatically delete listenSocket PIndirectChannel autoDeleteSocket; autoDeleteSocket.Open(listenSocket); // get host address and port to send to other end WORD localPort = listenSocket->GetPort(); PIPSocket::Address localAddr; socket->GetLocalAddress(localAddr); // send PORT command to host if (!SendPORT(localAddr, localPort)) return NULL; if (ExecuteCommand(cmd, args)/100 != 1) return NULL; PTCPSocket * dataSocket = (PTCPSocket *)socket->Clone(); if (dataSocket->Accept(*listenSocket)) return dataSocket; delete dataSocket; return NULL;}PTCPSocket * PFTPClient::PassiveClientTransfer(Commands cmd, const PString & args){ PIPSocket::Address passiveAddress; WORD passivePort; if (ExecuteCommand(PASV) != 227) return NULL; PINDEX start = lastResponseInfo.FindOneOf("0123456789"); if (start == P_MAX_INDEX) return NULL; PStringArray bytes = lastResponseInfo(start, P_MAX_INDEX).Tokenise(','); if (bytes.GetSize() != 6) return NULL; passiveAddress = PIPSocket::Address((BYTE)bytes[0].AsInteger(), (BYTE)bytes[1].AsInteger(), (BYTE)bytes[2].AsInteger(), (BYTE)bytes[3].AsInteger()); passivePort = (WORD)(bytes[4].AsInteger()*256 + bytes[5].AsInteger()); PTCPSocket * socket = new PTCPSocket(passiveAddress, passivePort); if (socket->IsOpen()) if (ExecuteCommand(cmd, args)/100 == 1) return socket; delete socket; return NULL;}PTCPSocket * PFTPClient::GetFile(const PString & filename, DataChannelType channel){ return channel != Passive ? NormalClientTransfer(RETR, filename) : PassiveClientTransfer(RETR, filename);}PTCPSocket * PFTPClient::PutFile(const PString & filename, DataChannelType channel){ return channel != Passive ? NormalClientTransfer(STOR, filename) : PassiveClientTransfer(STOR, filename);}// End of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -