#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <time.h>
#include <math.h>
#include <limits.h>
#include "MYTCP.h"
#include "tcp.h"
#include <arpa/ftp.h>
#include <arpa/telnet.h>
#include "ftpc.h"
#include "url.h"
#include "log.h"
#include "FTPC_UT.h"
#define FTP_DEBUG
int debug_mode = 1;
#define TIME struct timeval
//=============UTIL==========================
#include <io.h>
#define DIM(x) (sizeof((x)) / sizeof((x)[0]))
extern FILE *OpenFile (char **name, const char *mode, int *overwrite);
extern FILE *AppendFile (char **name, DWORD *pos);
static FILE *current_file = NULL;
static char *DosName (char *name);
#define WARN1(fmt,a1) xprintf (WarnText, fmt, a1)
#define WARN2(fmt,a1,a2) xprintf (WarnText, fmt, a1, a2)
#define WARN3(fmt,a1,a2,a3) xprintf (WarnText, fmt, a1, a2, a3)
//===========================================
#define LIN_SIZE 8192
#define MAX_HOSTNAME 80
#define MAX_PORTS 100 /* # of listen ports to check */
#define NUM_DATA_SOCKS 4
#define MAX_DATA_BUF 16384 //資料線接收BUFFER
#define FTP_LOW_PORT 1025 /* range of empherical ports */
#define FTP_HIGH_PORT 5000 /* normally accepted by FTPD */
#define MAX_FILELIST_BUF 1000 //最大可接收檔案清單數
#define SLASH '/'
#define RANDPORT(lo,hi) ((lo) + (WORD)(rand() % ((hi)-(lo)+1)))
char local_home [_MAX_PATH]; //工作目錄,初始化工作目錄位置
void *ctrl_socket=0;
void *data_socket=0;
WORD initial_port = 0;
char *initial_url = NULL;
long FTPC_TimeCount;
static tcp_Socket c_sock; //控制線sock
static char line_buffer [LIN_SIZE]; //控制線接收BUFFER
static DWORD host_ip; //記憶伺服器ip位址host ip
static char host_name [MAX_HOSTNAME];
static char data_sockbuf[MAX_DATA_BUF]; //接收BUFFER
static int xfer_mode = TYPE_A; //記憶目前傳輸模式狀態
static date DateNow; //今天的日期
//static int xfer_mode = TYPE_A; //記憶現在傳輸模式
static int logged_in = 0; //記憶現在login狀態
static int FTPCtrlConnected = 0; //記憶現在連線狀態
static int closing = 0; //記憶現在是否要檢查控制線是否斷線
static int reply_code = 0; //記憶回應碼
static int trans_compl = 0; //資料傳輸完成狀態
static int data_error = 0; //資料傳輸發生錯誤
//static int sendport = 1; //指定資料線建立時要送PORT指令
static BYTE abort_cmd[] = { IAC,IP,IAC,DM,'A','B','O','R',0 };
FtpConfig ftpcfg;
static tcp_Socket sock_pool[NUM_DATA_SOCKS];
static time_t start_time;
//定義主流程程序--FTPCliMainStep-----------------------------------
#define FTPC_Idle 0
#define FTPC_Initial 1
#define FTPC_WaitCmd 2
#define FTPC_Connect 3
#define FTPC_Online 4
static int FTPCliMainStep = FTPC_Idle; //主流程STEP
int xprintf (TextDestination dest, const char *fmt, ...);
int Command (char *fmt, ...);
int SendCommand (void *sock, char *cmd);
void DoCSParse(void);
void DoCSResolve(void);
void DoCSSockOpen(void);
void DoCSWaitEatablish(void);
void DoCSGetReply(void);
void DoCSLoginUser(void);
void DoCSLoginUserReply(void);
void DoCSLoginPass(void);
void DoCSLoginPassReply(void);
void FTPC_GetReplyInit(int expect_eof);
int FTPC_GetReply(void);
int ctrl_sock_open (WORD port);
int ctrl_sock_wait_establish (void);
void Do_Ctrl_Sock_Link_Error(int status);
void CloseCtrlSocket(void);
void ClearPorts (void);
void ResetTimeCount(void);
int CheckTimeOut(int count);
char URLstr[_MAX_PATH]; //連線命令字串
WORD URLport; //連線指定PORT
URL FTPC_url;
//連線程序主流程================================================================
void DoFTPConnect(void);
//static int FTPC_ConnectStep = 0; //連線程序
int FTPC_ConnectStep = 0; //連線程序
#define FTPC_CS_Parse 0
#define FTPC_CS_Resolve 1
#define FTPC_CS_SockOpen 2
#define FTPC_CS_WaitEstablish 3
#define FTPC_CS_GetReply 4
#define FTPC_CS_LoginUser 5
#define FTPC_CS_LoginUserReply 6
#define FTPC_CS_LoginPass 7
#define FTPC_CS_LoginPassReply 9
//在線操作主流程================================================================
void DoFTPOnLine(void);
//static int FTPC_OnLineStep = 0;
int FTPC_OnLineStep = 0;
#define FTPC_OL_Wait 0 //等待命令
#define FTPC_OL_DirList 1 //下載目錄清單
#define FTPC_OL_WaitCmdReply 2 //等待伺服器回應訊息,(回應後直接回待命狀態),處理沒有下一步的回應
#define FTPC_OL_DownFile 3 //下載檔案
#define FTPC_OL_UpFile 4 //上傳檔案
//下載目錄清單流程==============================================================
void DoOLDirList(void);
//static int FTPC_DirListStep = 0;
int FTPC_DirListStep = 0;
#define FTPC_DL_Initial 0 //初始化下載目錄清單程序
#define FTPC_DL_PushMode 1 //儲存現在傳輸模式,並設定為ASCII模式
#define FTPC_DL_InitConn 2 //初始化資料連線
#define FTPC_DL_SendCmd 3 //傳送命令
#define FTPC_DL_WaitCmdReply 4 //等待伺服器回應訊息
#define FTPC_DL_WaitLink 5 //等待伺服器連線
#define FTPC_DL_WaitDirData 6 //等待目錄資料
#define FTPC_DL_DataClose 7 //關閉資料連線
#define FTPC_DL_PopMode 8 //回復至原來的傳輸模式
#define FTPC_DL_DataCloseErr 9 //關閉資料連線,不等待回應
void DoDLInitial(void);
void DoDLPushMode(void);
void DoDLInitConn(void);
void DoDLSendCmd(void);
void DoDLWaitCmdReply(void);
void DoDLWaitLink(void);
void DoDLWaitDirData(void);
void DoDLDataClose(void);
void DoDLDataCloseErr(void);
void DoDLPopMode(void);
void SetPushMode(int mode);
int DoPushMode(void);
int ftp_binary (void);
int ftp_ascii (void);
int DoPopMode(void);
void DoReSetInitConn(void);
int DoInitConn(void);
int InitConn (void);
int DataConn(void);
int DoDataClose(void); //等待伺服器回應
//不等待伺服器回應
void DoDataClose1(void);
int CheckPort (WORD port);
//目錄BUFFER管理模組===========================================================
static FtpFileList FileListBuf[MAX_FILELIST_BUF]; //記憶目錄清單
void ClearFileListPool(void);
int PushFileList(FtpFileList *fl);
//等待伺服器回應訊息===========================================================
void DoOLWaitCmdReply(void);
//下載檔案流程=================================================================
#define MAX_DIR_LENGTH PATH_MAX //此值為512
#define MAX_FILE_NAME_LENGTH MAX_DIR_LENGTH+13
static DWORD expect; //記錄傳輸檔案大小
static DWORD restart_pos = 0; //記錄再下載檔案位置
static TIME TransStartTime; //記錄傳輸起始時間
static DWORD TransTotal; //記錄總傳輸時間
static char *Remote_Name; //記錄下載檔名
static char TransBlock[2048]; //單一BLOCK傳輸用BUFFER
static char WorkDirectory[MAX_DIR_LENGTH]; //記錄工作目錄位置
int FTPC_DownFileStep=0;
#define FTPC_DF_Initial 0 //初始化下載準備工作
#define FTPC_DF_InitConn 1 //初始化資料連線
#define FTPC_DF_SendCmd 2 //輸出命令
#define FTPC_DF_WaitCmdReply 3 //等待伺服器回應訊息
#define FTPC_DF_WaitLink 4 //等待伺服器連線
#define FTPC_DF_WaitFileData 5 //等待檔案資料
#define FTPC_DF_DataClose 6 //關閉資料連線
#define FTPC_DF_CloseFile 7 //關閉檔案
#define FTPC_DF_DataCloseErr 8 //關閉資料連線,不等回應
void DoDownFile(void);
void DoDFInitConn(void);
void DoDFSendCmd(void);
void DoDFWaitCmdReply(void);
void DoDFWaitLink(void);
void DoDFWaitData(void);
void DoDFDataClose(void);
void DoDFDataCloseErr(void);
void DoDFCloseFile(void);
//get=1由伺服器回應訊息找出檔案大小,get=0由fil算出檔案大小
unsigned long ExpectSize (int get, F