📄 ftpcli.cpp
字号:
/* * by balancesli * balancesli@gmail.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/utsname.h>#include <netinet/in.h>#include <linux/ip.h>#include <errno.h>#include <netdb.h>#include <fcntl.h>#include <unistd.h>#include <fcntl.h>#include <assert.h>#include <ctype.h>#include <sys/time.h>#include <time.h>#include <linux/ip.h>#include <pthread.h>#include "Utils.h"#include "Socket.h"#include "Url.h"#include "Task.h"#include "FtpCli.h"#include "dget.h"/**************** class TFtpCli ******************************/#define UNIMPLEMENTED_CMD(a) ((a == 500) || (a == 502) || (a == 504))#define MAX_MSG_SIZE 1024TFtpCli :: TFtpCli(TUrl * up) : CtrlSkp(NULL), DataSkp(NULL), ListenSkp(NULL){ HostName = up->HostName; UserName = up->UserName; PassWord = up->PassWord; HostDirName = up->HostDirName; HostFileName = up->HostFileName; IsPasv = true; IsBinary = true; IsAscii = false;}TFtpCli :: ~TFtpCli(void){ if(CtrlSkp != NULL) { close(CtrlSkp->GetSockfd()); delete CtrlSkp; } if(DataSkp != NULL) { close(DataSkp->GetSockfd()); delete DataSkp; } if(ListenSkp != NULL) { close(ListenSkp->GetSockfd()); delete ListenSkp; }} void TFtpCli :: Disconnect(void){ if(CtrlSkp == NULL) { ShowMsg("Failed to Disconnect"); return; } close(CtrlSkp->GetSockfd()); ShowMsg("Logout Ok");}uerr_t TFtpCli :: Connect(void){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; if(CtrlSkp != NULL) { Disconnect(); delete CtrlSkp; } CtrlSkp = new TSocketCli(HostName); err = CtrlSkp->Connect(21); if (err != NOCONERROR) return err; CtrlSock = CtrlSkp->GetSockfd(); err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '2') return FTPCONREFUSED; return FTPOK;}/* * return the numeric response of the ftp server by reading the first 3 * characters in the buffer */int TFtpCli :: GetReturn(const char * szBuffer){ char Code[3]; strncpy(Code, szBuffer, 3); return atoi(Code);}int TFtpCli :: CheckMsg(int Sock, char * szBuffer, int Len){ int retval; if ((retval = Recv(Sock, szBuffer, Len, MSG_PEEK)) == -1) { ShowMsg("Error checking for ftp data-: %s", strerror(errno)); return retval; } return retval;}int TFtpCli :: ReadMsg(int Sock, char * szBuffer, int Len){ int retval; // Cancelation-point pthread_testcancel(); if ((retval = Recv(Sock, szBuffer, Len, 0)) == -1) { ShowMsg("Error Receiving ftp data-: %s", strerror(errno)); return retval; } pthread_testcancel(); return retval;}uerr_t TFtpCli :: SendMsg(int Sock, char * szBuffer, int Len){ if (Send(Sock, szBuffer, Len, 0) == -1) { ShowMsg("Error Sending ftp data-: %s", strerror(errno)); return FTPERR; } return FTPOK;}uerr_t TFtpCli :: GetLine(int Sock, char * szBuffer){ int iLen, iBuffLen = 0, ret = 0; char *szPtr = szBuffer, ch = 0; ret = CheckMsg(Sock, &ch, 1); while (iBuffLen < FTP_BUF_SIZE && ret > 0) { iLen = ReadMsg(Sock, &ch, 1); if (iLen != 1) return FTPERR; iBuffLen += iLen; *szPtr = ch; szPtr += iLen; if (ch == '\n') break; } if (ret == -1) return FTPERR; *(szPtr + 1) = '\0'; return FTPOK;}uerr_t TFtpCli :: GetReply(int Sock, char * szBuffer){ int done = 0; memset(szBuffer, 0, FTP_BUF_SIZE); while (!done) { if (GetLine(Sock, szBuffer) != FTPOK) return FTPERR; (void)strtok(szBuffer, "\r\n"); if (szBuffer[3] != '-' && GetReturn(szBuffer) > 0) done = 1; } return FTPOK;}uerr_t TFtpCli :: Ascii(void){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "TYPE A\r\n"); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '2') return FTPUNKNOWNTYPE; return FTPOK;}uerr_t TFtpCli :: Binary(void){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "TYPE I\r\n"); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '2') return FTPUNKNOWNTYPE; return FTPOK;}uerr_t TFtpCli :: Port(const char * Cmd){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); strcpy(szBuffer, Cmd); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '2') return FTPPORTERR; return FTPOK;}uerr_t TFtpCli :: List(const char * FileName){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "LIST %s\r\n", FileName); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer == '5') return FTPNSFOD; if (*szBuffer != '1') return FTPERR; return FTPOK;}uerr_t TFtpCli :: Retr(const char * FileName){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "RETR %s\r\n", FileName); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer == '5') return FTPNSFOD; if (*szBuffer != '1') return FTPERR; return FTPOK;}/* PASV command */uerr_t TFtpCli :: Pasv(unsigned char * addr){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; unsigned char *p; int i; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "PASV\r\n"); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '2') return FTPNOPASV; p = (unsigned char *)szBuffer; for (p += 4; *p && !isdigit(*p); p++); if (!*p) return FTPINVPASV; for (i = 0; i < 6; i++) { addr[i] = 0; for (; isdigit(*p); p++) addr[i] = (*p - '0') + 10 * addr[i]; if (*p == ',') p++; else if (i < 5) return FTPINVPASV; } return FTPOK;}uerr_t TFtpCli :: Rest(long Bytes){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "REST %ld\r\n", Bytes); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '3') return FTPRESTFAIL; return FTPOK;}/* * CWD command */uerr_t TFtpCli :: Cwd(const char * Dir){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "CWD %s\r\n", Dir); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; /* * check and see wether the CWD succeeded */ if (*szBuffer == '5') return FTPNSFOD; if (*szBuffer != '2') return CWDFAIL; return FTPOK;}/* * Returns the Current working directory in dir */uerr_t TFtpCli :: Pwd(char * Dir){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; char *r, *l; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "PWD\r\n"); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; /* * check and see wether the PWD succeeded */ if (*szBuffer == '5') return FTPPWDERR; if (*szBuffer != '2') return PWDFAIL; if ((r = strrchr(szBuffer, '"')) != NULL) { l = strchr(szBuffer, '"'); if ((l != NULL) && (l != r)) { *r = '\0'; ++l; strcpy(Dir, l); *r = '"'; } } else { if ((r = strchr(szBuffer, ' ')) != NULL) { *r = '\0'; strcpy(Dir, szBuffer); *r = ' '; } } ShowMsg(Dir); return FTPOK;}/* * this will call bind to return a bound socket then the ftp server * will be connected with a port request and asked to connect */uerr_t TFtpCli :: GetListenSocket(void){ uerr_t err; char Cmd[MAX_MSG_SIZE]; struct sockaddr_in TmpAddr; struct sockaddr_in SvrAddr; socklen_t Len; char *Ports, *IpAddr; int ListenSock; int CtrlSock; struct utsname ut; uname(&ut); if(ListenSkp != NULL) { close(ListenSkp->GetSockfd()); delete ListenSkp; } ListenSkp = new TSocketSvr(ut.sysname); err = ListenSkp->Bind(); ListenSock = ListenSkp->GetSockfd(); if (err != BINDOK) return LISTENERR; Len = sizeof(SvrAddr); if (getsockname(ListenSock, (struct sockaddr *)&SvrAddr, &Len) < 0) { perror("getsockname"); close(ListenSock); return CONPORTERR; } Len = sizeof(TmpAddr); CtrlSock = CtrlSkp->GetSockfd(); if (getsockname(CtrlSock, (struct sockaddr *)&TmpAddr, &Len) < 0) { perror("getsockname"); close(CtrlSock); return CONPORTERR; } IpAddr = (char *)&TmpAddr.sin_addr; Ports = (char *)&SvrAddr.sin_port;#define UC(b) (((int)b)&0xff) sprintf(Cmd, "PORT %d,%d,%d,%d,%d,%d\r\n", UC(IpAddr[0]), UC(IpAddr[1]), UC(IpAddr[2]), UC(IpAddr[3]), UC(Ports[0]), UC(Ports[1])); err = Port(Cmd); if (err != FTPOK) return err; return FTPOK;}uerr_t TFtpCli :: Login(void){ uerr_t err; char szBuffer[FTP_BUF_SIZE]; int CtrlSock; CtrlSock = CtrlSkp->GetSockfd(); sprintf(szBuffer, "USER %s\r\n", UserName); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; memset(szBuffer, 0, FTP_BUF_SIZE); err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer == '2') return FTPOK; if (*szBuffer != '3') return FTPLOGREFUSED; sprintf(szBuffer, "PASS %s\r\n", PassWord); err = SendMsg(CtrlSock, szBuffer, strlen(szBuffer)); if (err != FTPOK) return err; err = GetReply(CtrlSock, szBuffer); if (err != FTPOK) return err; if (*szBuffer != '2') return FTPLOGREFUSED; return FTPOK;}uerr_t TFtpCli :: RetrFileKnownSize(TThread * This){ long Total = 0, BytesRead = 0, Length; char szBuffer[FTP_BUF_SIZE];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -