ConnectSocket.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. /********************************************************************/
  2. /* */
  3. /* CONNECTSOCKET.CPP */
  4. /* */
  5. /* Implementation of the Connect Socket. */
  6. /* This class is a part of the CConnectThread which handles */
  7. /* socket connections. Incomming data is processed in OnReceive */
  8. /* */
  9. /* Programmed by LYFZ van der Meer */
  10. /* Based partially on and inspired by FileZilla Server. */
  11. /* */
  12. /* http://www.LYFZvandermeer.nl */
  13. /* */
  14. /* Last updated: 15 july 2002 */
  15. /* */
  16. /********************************************************************/
  17. //在ConnectSocket.cpp文件中实现连接套接字的创建,该类是CConnectThread类的
  18. //一部分,收到数据由函数OnReceive()完成处理。
  19. #include "stdafx.h"
  20. #include "CPhotoFTPReceiveApp.h"
  21. #include "CPhotoFTPReceive.h"
  22. #include "ConnectSocket.h"
  23. #include "ConnectThread.h"
  24. #include "ApplicationDlg.h"
  25. #include "DataSocket.h"
  26. extern CCPhotoFTPReceive theServer;
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. /********************************************************************/
  33. /* */
  34. /* Function name : CConnectSocket::CConnectSocket */
  35. /* Description : Constructor */
  36. /* */
  37. /********************************************************************/
  38. CConnectSocket::CConnectSocket()
  39. {
  40. m_bLoggedon = FALSE;
  41. m_bRenameFile = FALSE;
  42. m_pDataSocket = NULL;
  43. m_strRemoteHost = "";
  44. m_nRemotePort = -1;
  45. m_dwRestartOffset = 0;
  46. m_bPassiveMode = FALSE;
  47. }
  48. /********************************************************************/
  49. /* */
  50. /* Function name : CConnectSocket::~CConnectSocket */
  51. /* Description : Destructor */
  52. /* */
  53. /********************************************************************/
  54. CConnectSocket::~CConnectSocket()
  55. {
  56. DestroyDataConnection();
  57. // tell our thread we have been closed
  58. AfxGetThread()->PostThreadMessage(WM_QUIT,0,0);
  59. TRACE0("CConnectSocket destroyed.\n");
  60. }
  61. // Do not edit the following lines, which are needed by ClassWizard.
  62. #if 0
  63. BEGIN_MESSAGE_MAP(CConnectSocket, CSocket)
  64. //{{AFX_MSG_MAP(CConnectSocket)
  65. //}}AFX_MSG_MAP
  66. END_MESSAGE_MAP()
  67. #endif // 0
  68. /********************************************************************/
  69. /* */
  70. /* Function name : OnClose */
  71. /* Description : Send WM_QUIT message to the thread containing */
  72. /* the socket to shutdown once the connection is */
  73. /* closed. */
  74. /* */
  75. /********************************************************************/
  76. void CConnectSocket::OnClose(int nErrorCode)
  77. {
  78. Close();
  79. // destroy connection
  80. m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
  81. TRACE("CConnectSocket() OnClose()\n");
  82. CSocket::OnClose(nErrorCode);
  83. }
  84. #define BUFFERSIZE 4096
  85. /********************************************************************/
  86. /* */
  87. /* Function name : OnReceive */
  88. /* Description : Called by the framework to notify this socket */
  89. /* that there is data in the buffer. */
  90. /* */
  91. /********************************************************************/
  92. //由主窗口调用通知套接字缓冲区中有数据要接收
  93. void CConnectSocket::OnReceive(int nErrorCode)
  94. {
  95. TCHAR buff[BUFFERSIZE+1];
  96. //接收数据并放到缓冲区
  97. int nRead = Receive(buff, BUFFERSIZE);
  98. switch (nRead)
  99. {
  100. case 0:
  101. Close();
  102. break;
  103. case SOCKET_ERROR:
  104. if (GetLastError() != WSAEWOULDBLOCK)
  105. {
  106. TCHAR szError[256];
  107. wsprintf(szError, "OnReceive error: %d", GetLastError());
  108. // AfxMessageBox (szError);
  109. }
  110. break;
  111. default:
  112. if (nRead != SOCKET_ERROR && nRead != 0)
  113. {
  114. ((CConnectThread *)AfxGetThread())->IncReceivedBytes(nRead);
  115. // 结束字符串
  116. buff[nRead] = 0;
  117. m_RxBuffer += CString(buff);
  118. //获得命令行
  119. GetRxLine();
  120. }
  121. break;
  122. }
  123. CSocket::OnReceive(nErrorCode);
  124. }
  125. /********************************************************************/
  126. /* */
  127. /* Function name: GetRxCommand */
  128. /* Description : Get command from receiver buffer. */
  129. /* */
  130. /********************************************************************/
  131. //从接收缓冲区获得命令
  132. BOOL CConnectSocket::GetRxCommand(CString &strCommand, CString &strArguments)
  133. {
  134. if (!m_strCommands.IsEmpty())
  135. {
  136. CString strBuff = m_strCommands.RemoveHead();
  137. int nIndex = strBuff.Find(" ");
  138. if (nIndex != -1)
  139. {
  140. CString strPassword = strBuff;
  141. strPassword.MakeUpper();
  142. //使密码不可见
  143. if (strPassword.Left(5) == "PASS ")
  144. {
  145. for (int i=5; i < strPassword.GetLength(); i++)
  146. {
  147. strPassword.SetAt(i, '*');
  148. }
  149. FireStatusMessage(strPassword, 1);
  150. }
  151. else
  152. {
  153. FireStatusMessage(strBuff, 1);
  154. }
  155. strCommand = strBuff.Left(nIndex);
  156. strArguments = strBuff.Mid(nIndex+1);
  157. }
  158. else
  159. {
  160. FireStatusMessage(strBuff, 1);
  161. strCommand = strBuff;
  162. }
  163. if (strCommand != "")
  164. {
  165. strCommand.MakeUpper();
  166. // who screwed up ???
  167. if (strCommand.Right(4) == "ABOR")
  168. {
  169. strCommand = "ABOR";
  170. }
  171. TRACE2("COMMAND: %s, ARGS: %s\n", strCommand, strArguments);
  172. return TRUE;
  173. }
  174. }
  175. return FALSE;
  176. }
  177. /********************************************************************/
  178. /* */
  179. /* Function name: GetRxLine */
  180. /* Description : Parse complete command line */
  181. /* */
  182. /********************************************************************/
  183. //解析整个命令行
  184. void CConnectSocket::GetRxLine()
  185. {
  186. CString strTemp;
  187. int nIndex;
  188. while(!m_RxBuffer.IsEmpty())
  189. {
  190. //寻找换行符
  191. nIndex = m_RxBuffer.Find("\r\n");
  192. if (nIndex != -1)
  193. {
  194. strTemp = m_RxBuffer.Left(nIndex);
  195. m_RxBuffer = m_RxBuffer.Mid(nIndex + 2);
  196. if (!strTemp.IsEmpty())
  197. {
  198. m_strCommands.AddTail(strTemp);
  199. // 解析并执行命令
  200. ParseCommand();
  201. }
  202. }
  203. else
  204. break;
  205. }
  206. }
  207. /********************************************************************/
  208. /* */
  209. /* Function name: OnConnect */
  210. /* Description : Called by the framework to notify this connecting */
  211. /* socket that its connection attempt is completed. */
  212. /* */
  213. /********************************************************************/
  214. void CConnectSocket::OnConnect(int nErrorCode)
  215. {
  216. CSocket::OnConnect(nErrorCode);
  217. }
  218. /********************************************************************/
  219. /* */
  220. /* Function name: HasConnectionDropped */
  221. /* Description : Check if connection has been dropped. */
  222. /* Used to detect if client has crashed. */
  223. /* */
  224. /********************************************************************/
  225. BOOL CConnectSocket::HasConnectionDropped(void)
  226. {
  227. BOOL bConnDropped = FALSE;
  228. INT iRet = 0;
  229. BOOL bOK = TRUE;
  230. if (m_hSocket == INVALID_SOCKET)
  231. return TRUE;
  232. struct timeval timeout = { 0, 0 };
  233. fd_set readSocketSet;
  234. FD_ZERO(&readSocketSet);
  235. FD_SET(m_hSocket, &readSocketSet);
  236. iRet = ::select(0, &readSocketSet, NULL, NULL, &timeout);
  237. bOK = (iRet > 0);
  238. if(bOK)
  239. {
  240. bOK = FD_ISSET(m_hSocket, &readSocketSet);
  241. }
  242. if(bOK)
  243. {
  244. CHAR szBuffer[1] = "";
  245. iRet = ::recv(m_hSocket, szBuffer, 1, MSG_PEEK);
  246. bOK = (iRet > 0);
  247. if(!bOK)
  248. {
  249. INT iError = ::WSAGetLastError();
  250. bConnDropped = (( iError == WSAENETRESET) ||
  251. (iError == WSAECONNABORTED) ||
  252. (iError == WSAECONNRESET) ||
  253. (iError == WSAEINVAL) ||
  254. (iRet == 0));
  255. }
  256. }
  257. return(bConnDropped);
  258. }
  259. /********************************************************************/
  260. /* */
  261. /* Function name: SendResponse */
  262. /* Description : Send response to client. */
  263. /* */
  264. /********************************************************************/
  265. //发送响应给客户端
  266. BOOL CConnectSocket::SendResponse(LPCTSTR pstrFormat, ...)
  267. {
  268. CString str;
  269. // 格式化参数
  270. va_list args;
  271. va_start(args, pstrFormat);
  272. str.FormatV(pstrFormat, args);
  273. //判断连接是否在活动状态
  274. if (HasConnectionDropped())
  275. {
  276. FireStatusMessage("Could not send reply, disconnected.", 2);
  277. Close();
  278. // 通知线程已经停止,关闭连接
  279. m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
  280. return FALSE;
  281. }
  282. int nBytes = CSocket::Send(str + "\r\n", str.GetLength()+2);
  283. if (nBytes == SOCKET_ERROR)
  284. {
  285. Close();
  286. FireStatusMessage("Could not send reply, disconnected.", 2);
  287. //通知线程连接已经关闭
  288. m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
  289. return FALSE;
  290. }
  291. FireStatusMessage(str, 2);
  292. ((CConnectThread *)AfxGetThread())->IncSentBytes(nBytes);
  293. return TRUE;
  294. }
  295. /********************************************************************/
  296. /* */
  297. /* Function name: ParseCommand */
  298. /* Description : Parse and execute command from client. */
  299. /* */
  300. /* Based on code provided by FileZilla Server. */
  301. /* http://sourceforge.net/projects/filezilla */
  302. /* */
  303. /********************************************************************/
  304. //从客户端解析并执行命令
  305. void CConnectSocket::ParseCommand()
  306. {
  307. //命令列表
  308. static CFTPCommand commandList[] =
  309. {
  310. {TOK_ABOR, "ABOR", FALSE, "Abort transfer: ABOR"},
  311. {TOK_BYE, "BYE", FALSE, "Logout or break the connection: BYE"},
  312. {TOK_CDUP, "CDUP", FALSE, "Change to parent directory: CDUP"},
  313. {TOK_CWD, "CWD", TRUE, "Change working directory: CWD [directory-name]"},
  314. {TOK_DELE, "DELE", TRUE , "Delete file: DELE file-name"},
  315. {TOK_DIR, "DIR", FALSE, "Get directory listing: DIR [path-name]"},
  316. {TOK_HELP, "HELP", FALSE, "Show help: HELP [command]"},
  317. {TOK_LIST, "LIST", FALSE, "Get directory listing: LIST [path-name]"},
  318. {TOK_MKD, "MKD", TRUE, "Make directory: MKD path-name"},
  319. {TOK_NOOP, "NOOP", FALSE, "Do nothing: NOOP"},
  320. {TOK_PASS, "PASS", TRUE, "Supply a user password: PASS password"},
  321. {TOK_PASV, "PASV", FALSE, "Set server in passive mode: PASV"},
  322. {TOK_PORT, "PORT", TRUE, "Specify the client port number: PORT a0,a1,a2,a3,a4,a5"},
  323. {TOK_PWD, "PWD", FALSE, "Get current directory: PWD"},
  324. {TOK_QUIT, "QUIT", FALSE, "Logout or break the connection: QUIT"},
  325. {TOK_REST, "REST", TRUE, "Set restart transfer marker: REST marker"},
  326. {TOK_RETR, "RETR", TRUE, "Get file: RETR file-name"},
  327. {TOK_RMD, "RMD", TRUE, "Remove directory: RMD path-name"},
  328. {TOK_RNFR, "RNFR", TRUE, "Specify old path name of file to be renamed: RNFR file-name"},
  329. {TOK_RNTO, "RNTO", TRUE, "Specify new path name of file to be renamed: RNTO file-name"},
  330. {TOK_SIZE, "SIZE", TRUE, "Get filesize: SIZE file-name"},
  331. {TOK_STOR, "STOR", TRUE, "Store file: STOR file-name"},
  332. {TOK_SYST, "SYST", FALSE, "Get operating system type: SYST"},
  333. {TOK_TYPE, "TYPE", TRUE, "Set filetype: TYPE [A | I]"},
  334. {TOK_USER, "USER", TRUE, "Supply a username: USER username"},
  335. {TOK_ERROR, "", FALSE, ""},
  336. };
  337. // 解析命令
  338. CString strCommand, strArguments;
  339. if (!GetRxCommand(strCommand, strArguments))
  340. {
  341. return;
  342. }
  343. int nCommand;
  344. //在命令列表中查找命令
  345. for (nCommand = TOK_ABOR; nCommand < TOK_ERROR; nCommand++)
  346. {
  347. // 判断是否找到命令
  348. if (strCommand == commandList[nCommand].m_pszName)
  349. {
  350. if (commandList[nCommand].m_bHasArguments && (strArguments.IsEmpty()))
  351. {
  352. SendResponse("501 Syntax error: Invalid number of parameters.");
  353. return;
  354. }
  355. break;
  356. }
  357. }
  358. if (nCommand == TOK_ERROR)
  359. {
  360. // 命令不在我们的列表中
  361. SendResponse("501 Syntax error: Command not understood.");
  362. return;
  363. }
  364. //判断是否成功登录服务器
  365. if ((nCommand != TOK_USER && nCommand != TOK_PASS) && !m_bLoggedon)
  366. {
  367. SendResponse("530 Please login with USER and PASS.");
  368. return;
  369. }
  370. // 处理命令
  371. switch(nCommand)
  372. {
  373. //指定用户名
  374. case TOK_USER:
  375. {
  376. strArguments.MakeLower();
  377. m_bLoggedon = FALSE;
  378. m_strUserName = strArguments;
  379. CString strPeerAddress;
  380. UINT nPeerPort;
  381. //获得客户端IP地址和端口
  382. GetPeerName(strPeerAddress, nPeerPort);
  383. // 通知FTP服务器一个新的用户已经连接
  384. CConnectThread *pThread = (CConnectThread *)m_pThread;
  385. ((CCPhotoFTPReceive *)pThread->m_pWndServer)->m_pEventSink->OnFTPUserConnected(m_pThread->m_nThreadID, m_strUserName, strPeerAddress);
  386. SendResponse("331 User name ok, need password.");
  387. }
  388. break;
  389. // 指定密码
  390. case TOK_PASS:
  391. {
  392. //判断是否登录成功
  393. if (m_bLoggedon)
  394. {
  395. SendResponse("503 Login with USER first.");
  396. }
  397. else
  398. {
  399. // 用用户名和密码登录客户端
  400. CUser user;
  401. // 检查用户名
  402. if (theServer.m_UserManager.GetUser(m_strUserName, user))
  403. {
  404. // 检查密码
  405. if ((!user.m_strPassword.Compare(strArguments) || user.m_strPassword.IsEmpty()) && !user.m_bAccountDisabled)
  406. {
  407. // 设置用户路径
  408. m_strCurrentDir = "/";
  409. // 成功登录
  410. m_bLoggedon = TRUE;
  411. SendResponse("230 User successfully logged in.");
  412. break;
  413. }
  414. }
  415. SendResponse("530 Not logged in, user or password incorrect!");
  416. }
  417. }
  418. break;
  419. // 改变传输模式
  420. case TOK_TYPE:
  421. {
  422. SendResponse("200 Type set to %s", strArguments);
  423. }
  424. break;
  425. //打印当前路径
  426. case TOK_PWD:
  427. {
  428. SendResponse("257 \"%s\" is current directory.", m_strCurrentDir);
  429. }
  430. break;
  431. // 改变上层目录
  432. case TOK_CDUP:
  433. strArguments = "..";
  434. // 改变工作目录
  435. case TOK_CWD:
  436. {
  437. //改变到指定目录
  438. int nResult = theServer.m_UserManager.ChangeDirectory(m_strUserName, m_strCurrentDir, strArguments);
  439. switch(nResult)
  440. {
  441. case 0:
  442. SendResponse("250 CWD command successful. \"%s\" is current directory.", m_strCurrentDir);
  443. break;
  444. case 1:
  445. SendResponse("550 CWD command failed. \"%s\": Permission denied.", strArguments);
  446. break;
  447. default:
  448. SendResponse("550 CWD command failed. \"%s\": Directory not found.", strArguments);
  449. break;
  450. }
  451. }
  452. break;
  453. // 指定IP地址和端口
  454. case TOK_PORT:
  455. {
  456. CString strSub;
  457. int nCount=0;
  458. while (AfxExtractSubString(strSub, strArguments, nCount++, ','))
  459. {
  460. switch(nCount)
  461. {
  462. case 1:
  463. m_strRemoteHost = strSub;
  464. m_strRemoteHost += ".";
  465. break;
  466. case 2:
  467. m_strRemoteHost += strSub;
  468. m_strRemoteHost += ".";
  469. break;
  470. case 3:
  471. m_strRemoteHost += strSub;
  472. m_strRemoteHost += ".";
  473. break;
  474. case 4:
  475. m_strRemoteHost += strSub;
  476. break;
  477. case 5:
  478. m_nRemotePort = 256*atoi(strSub);
  479. break;
  480. case 6:
  481. m_nRemotePort += atoi(strSub);
  482. break;
  483. }
  484. }
  485. m_bPassiveMode = FALSE;
  486. SendResponse("200 Port command successful.");
  487. }
  488. // 改变到被动模式
  489. case TOK_PASV:
  490. {
  491. // 删除当前的数据连接
  492. DestroyDataConnection();
  493. // 创建新的数据套接字连接
  494. m_pDataSocket = new CDataSocket(this, -1);
  495. if (!m_pDataSocket->Create())
  496. {
  497. DestroyDataConnection();
  498. SendResponse("421 Failed to create socket.");
  499. break;
  500. }
  501. //开始侦听
  502. m_pDataSocket->Listen();
  503. m_pDataSocket->AsyncSelect();
  504. CString strIP, strTmp;
  505. UINT nPort;
  506. // 获得我们的IP地址
  507. GetSockName(strIP, nPort);
  508. //获得端口号
  509. m_pDataSocket->GetSockName(strTmp, nPort);
  510. // ss.Format ("11:%d", nPort);AfxMessageBox(ss);
  511. // 替换"."
  512. strIP.Replace(".",",");
  513. // 通知客户端要连接的IP地址和端口
  514. SendResponse("227 Entering Passive Mode (%s,%d,%d).", strIP, nPort/256, nPort%256);
  515. m_bPassiveMode = TRUE;
  516. break;
  517. }
  518. // 列出当前路径
  519. case TOK_LIST:
  520. case TOK_DIR:
  521. {
  522. // 如果不是被动模式,我们先需要PORT命令指定端口
  523. if(!m_bPassiveMode && (m_strRemoteHost == "" || m_nRemotePort == -1))
  524. {
  525. SendResponse("503 Bad sequence of commands.");
  526. }
  527. else
  528. {
  529. // 如果用户没有指定路径,用当前路径
  530. if (strArguments == "")
  531. {
  532. strArguments = m_strCurrentDir;
  533. }
  534. else
  535. {
  536. // 检查参数是文件名还是路径
  537. CString strResult;
  538. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_LIST, strResult);
  539. if (nResult == 0)
  540. {
  541. strArguments = strResult;
  542. }
  543. }
  544. CString strListing;
  545. int nResult = theServer.m_UserManager.GetDirectoryList(m_strUserName, strArguments, strListing);
  546. switch(nResult)
  547. {
  548. case 1:
  549. SendResponse("550 Permission denied.");
  550. break;
  551. case 2:
  552. SendResponse("550 Directory not found.");
  553. break;
  554. default:
  555. //创建套接字连接获得路径列表
  556. if (!CreateDataConnection(0, strListing))
  557. {
  558. DestroyDataConnection();
  559. }
  560. break;
  561. }
  562. }
  563. break;
  564. }
  565. // 获得文件
  566. case TOK_RETR:
  567. {
  568. // 如果不是被动模式,我们先需要PORT命令指定端口
  569. if(!m_bPassiveMode && (m_strRemoteHost == "" || m_nRemotePort == -1))
  570. {
  571. SendResponse("503 Bad sequence of commands.");
  572. break;
  573. }
  574. CString strResult;
  575. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_DOWNLOAD, strResult);
  576. switch(nResult)
  577. {
  578. case 1:
  579. SendResponse("550 Permission denied.");
  580. break;
  581. case 2:
  582. SendResponse("550 File not found.");
  583. break;
  584. default:
  585. //为文件传输创建一个套接字
  586. if (!CreateDataConnection(1, strResult))
  587. {
  588. DestroyDataConnection();
  589. }
  590. break;
  591. }
  592. break;
  593. }
  594. //客户端上传文件
  595. case TOK_STOR:
  596. {
  597. // 如果不是被动模式,我们先需要PORT命令指定端口
  598. if(!m_bPassiveMode && (m_strRemoteHost == "" || m_nRemotePort == -1))
  599. {
  600. SendResponse("503 Bad sequence of commands.");
  601. break;
  602. }
  603. /************************************************************************/
  604. /*
  605. 1.如果m_strCurrentDir包含域名字符串,表明下载的图片属于分店的,否则为本店在其他分店导入的订单相片;
  606. 2.一次只传一张相片,如果要写到增量表里的话,比较麻烦.只能先查询数据库是否有该分店的增量信息,如果有,且[opttime]仍为今天的,增量的content加上本次的相片名字;
  607. */
  608. /************************************************************************/
  609. CString strResult;
  610. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_UPLOAD, strResult);
  611. switch(nResult)
  612. {
  613. case 1:
  614. SendResponse("550 Permission denied.");
  615. break;
  616. case 2:
  617. SendResponse("550 Filename invalid.");
  618. break;
  619. default:
  620. //为文件传输创建一个套接字
  621. if (!CreateDataConnection(2, strResult))
  622. {
  623. DestroyDataConnection();
  624. }
  625. break;
  626. }
  627. }
  628. break;
  629. //获得文件大小
  630. case TOK_SIZE:
  631. {
  632. CString strResult;
  633. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_DOWNLOAD, strResult);
  634. switch(nResult)
  635. {
  636. case 1:
  637. SendResponse("550 Permission denied.");
  638. break;
  639. case 2:
  640. SendResponse("550 File not found.");
  641. break;
  642. default:
  643. {
  644. CFileStatus status;
  645. CFile::GetStatus(strResult, status);
  646. SendResponse("213 %d", status.m_size);
  647. break;
  648. }
  649. }
  650. }
  651. break;
  652. // 删除文件
  653. case TOK_DELE:
  654. {
  655. CString strResult;
  656. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_DELETE, strResult);
  657. switch(nResult)
  658. {
  659. case 1:
  660. SendResponse("550 Permission denied.");
  661. break;
  662. case 2:
  663. SendResponse("550 File not found.");
  664. break;
  665. default:
  666. //删除文件
  667. if (!DeleteFile(strResult))
  668. {
  669. SendResponse("450 Internal error deleting the file: \"%s\".", strArguments);
  670. }
  671. else
  672. {
  673. SendResponse("250 File \"%s\" was deleted successfully.", strArguments);
  674. }
  675. break;
  676. }
  677. }
  678. break;
  679. // 删除目录
  680. case TOK_RMD:
  681. {
  682. CString strResult;
  683. int nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_DELETE, strResult);
  684. switch(nResult)
  685. {
  686. case 1:
  687. SendResponse("550 Permission denied.");
  688. break;
  689. case 2:
  690. SendResponse("550 Directory not found.");
  691. break;
  692. default:
  693. // 删除目录
  694. if (!RemoveDirectory(strResult))
  695. {
  696. if (GetLastError() == ERROR_DIR_NOT_EMPTY)
  697. {
  698. SendResponse("550 Directory not empty.");
  699. }
  700. else
  701. {
  702. SendResponse("450 Internal error deleting the directory.");
  703. }
  704. }
  705. else
  706. {
  707. SendResponse("250 Directory deleted successfully.");
  708. }
  709. break;
  710. }
  711. }
  712. break;
  713. // 创建目录
  714. case TOK_MKD:
  715. {
  716. CString strResult;
  717. int nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_CREATE_DIR, strResult);
  718. switch(nResult)
  719. {
  720. case 0:
  721. SendResponse("550 Directory already exists.");
  722. break;
  723. case 1:
  724. SendResponse("550 Can't create directory. Permission denied.");
  725. break;
  726. default:
  727. //创建目录
  728. if (!MakeSureDirectoryPathExists(strResult))
  729. {
  730. SendResponse("450 Internal error creating the directory.");
  731. }
  732. else
  733. {
  734. SendResponse("250 Directory created successfully.");
  735. }
  736. break;
  737. }
  738. }
  739. break;
  740. //重命名文件名或者路径
  741. case TOK_RNFR:
  742. {
  743. CString strResult;
  744. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
  745. if (nResult == 0)
  746. {
  747. m_strRenameFile = strResult;
  748. m_bRenameFile = TRUE;
  749. SendResponse("350 File exists, ready for destination name.");
  750. break;
  751. }
  752. else
  753. {
  754. // 用户端重命名目录
  755. nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
  756. switch(nResult)
  757. {
  758. case 0:
  759. m_strRenameFile = strResult;
  760. m_bRenameFile = FALSE;
  761. SendResponse("350 Directory exists, ready for destination name.");
  762. break;
  763. case 1:
  764. SendResponse("550 Permission denied.");
  765. break;
  766. default:
  767. SendResponse("550 File/directory not found.");
  768. break;
  769. }
  770. }
  771. }
  772. break;
  773. // 重命名文件名或目录
  774. case TOK_RNTO:
  775. {
  776. if (m_strRenameFile.IsEmpty())
  777. {
  778. SendResponse("503 Bad sequence of commands.");
  779. break;
  780. }
  781. if (m_bRenameFile)
  782. {
  783. CString strResult;
  784. // 检查目标文件名
  785. int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
  786. switch(nResult)
  787. {
  788. case 0:
  789. SendResponse("550 File already exists.");
  790. break;
  791. case 1:
  792. SendResponse("550 Permission denied.");
  793. break;
  794. default:
  795. // 重命名文件
  796. if (!MoveFile(m_strRenameFile, strResult))
  797. {
  798. SendResponse("450 Internal error renaming the file: \"%s\".", m_strRenameFile);
  799. }
  800. else
  801. {
  802. SendResponse("250 File \"%s\" renamed successfully.", m_strRenameFile);
  803. }
  804. break;
  805. }
  806. }
  807. else
  808. {
  809. CString strResult;
  810. // 检查目标路径名
  811. int nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
  812. switch(nResult)
  813. {
  814. case 0:
  815. SendResponse("550 Directory already exists.");
  816. break;
  817. case 1:
  818. SendResponse("550 Permission denied.");
  819. break;
  820. case 3:
  821. SendResponse("550 Directory invalid.");
  822. break;
  823. default:
  824. // 重命名路径
  825. if (!MoveFile(m_strRenameFile, strResult))
  826. {
  827. SendResponse("450 Internal error renaming the directory: \"%s\".", m_strRenameFile);
  828. }
  829. else
  830. {
  831. SendResponse("250 Directory \"%s\" renamed successfully.", m_strRenameFile);
  832. }
  833. break;
  834. }
  835. }
  836. }
  837. break;
  838. // 取消传输
  839. case TOK_ABOR:
  840. {
  841. if (m_pDataSocket)
  842. {
  843. if (m_pDataSocket->GetStatus() != XFERMODE_IDLE)
  844. {
  845. SendResponse("426 Data connection closed.");
  846. }
  847. //销毁数据连接
  848. m_pThread->PostThreadMessage(WM_THREADMSG, 0, 0);
  849. }
  850. SendResponse("226 ABOR command successful.");
  851. break;
  852. }
  853. // 获得系统信息
  854. case TOK_SYST:
  855. SendResponse("215 UNIX emulated by LYFZ FTP Server.");
  856. break;
  857. // 关闭连接
  858. case TOK_QUIT:
  859. case TOK_BYE:
  860. {
  861. // 发送再见消息给客户机
  862. CConnectThread *pThread = (CConnectThread *)m_pThread;
  863. SendResponse("220 %s", ((CCPhotoFTPReceive *)pThread->m_pWndServer)->GetGoodbyeMessage());
  864. Close();
  865. //通知线程已经结束关闭连接
  866. m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
  867. break;
  868. }
  869. //重新启动传输
  870. case TOK_REST:
  871. {
  872. if (!IsNumeric(strArguments.GetBuffer(strArguments.GetLength())))
  873. {
  874. strArguments.ReleaseBuffer();
  875. SendResponse("501 Invalid parameter.");
  876. }
  877. else
  878. {
  879. strArguments.ReleaseBuffer();
  880. m_dwRestartOffset = atol(strArguments);
  881. SendResponse("350 Restarting at %d.", m_dwRestartOffset);
  882. }
  883. }
  884. break;
  885. //显示帮助信息
  886. case TOK_HELP:
  887. //如果客户端不指定命令名显示所有可有命令
  888. if (strArguments == "")
  889. {
  890. CString strResponse = "214-The following commands are recognized:\r\n";
  891. // 在命令列表中查找命令
  892. for (int i = TOK_ABOR; i < TOK_ERROR; i++)
  893. {
  894. strResponse += commandList[i].m_pszName;
  895. strResponse += "\r\n";
  896. }
  897. strResponse += "214 HELP command successful.";
  898. SendResponse(strResponse);
  899. }
  900. else
  901. {
  902. int nHelpCmd;
  903. // 在命令列表中查找命令
  904. for (nHelpCmd = TOK_ABOR; nHelpCmd < TOK_ERROR; nHelpCmd++)
  905. {
  906. //判断是否找到命令
  907. if (strArguments.CompareNoCase(commandList[nHelpCmd].m_pszName) == 0)
  908. {
  909. break;
  910. }
  911. }
  912. if (nHelpCmd != TOK_ERROR)
  913. {
  914. //显示命令帮助信息
  915. SendResponse("214 %s", commandList[nHelpCmd].m_pszDescription);
  916. }
  917. else
  918. {
  919. SendResponse("501 Unknown command %s", strArguments);
  920. }
  921. }
  922. break;
  923. // 空命令
  924. case TOK_NOOP:
  925. SendResponse("200 OK");
  926. break;
  927. default:
  928. SendResponse("502 Command not implemented - Try HELP.");
  929. break;
  930. }
  931. }
  932. /********************************************************************/
  933. /* */
  934. /* Function name: FireStatusMessage */
  935. /* Description : Fire status message. */
  936. /* */
  937. /********************************************************************/
  938. void CConnectSocket::FireStatusMessage(LPCTSTR lpszStatus, int nType)
  939. {
  940. CConnectThread *pThread = (CConnectThread *)m_pThread;
  941. ((CCPhotoFTPReceive *)pThread->m_pWndServer)->AddTraceLine(nType, "[%d] %s", m_pThread->m_nThreadID, lpszStatus);
  942. }
  943. /********************************************************************/
  944. /* */
  945. /* Function name: CreateDataConnection */
  946. /* Description : Create data transfer connection. */
  947. /* */
  948. /********************************************************************/
  949. BOOL CConnectSocket::CreateDataConnection(int nTransferType, LPCTSTR lpszData)
  950. {
  951. if (!m_bPassiveMode)
  952. {
  953. m_pDataSocket = new CDataSocket(this, nTransferType);
  954. if (m_pDataSocket->Create())
  955. {
  956. m_pDataSocket->AsyncSelect();
  957. m_pDataSocket->SetRestartOffset(m_dwRestartOffset);
  958. m_pDataSocket->SetData(lpszData);
  959. // connect to remote site
  960. if (m_pDataSocket->Connect(m_strRemoteHost, m_nRemotePort) == 0)
  961. {
  962. if (GetLastError() != WSAEWOULDBLOCK)
  963. {
  964. SendResponse("425 Can't open data connection.");
  965. return FALSE;
  966. }
  967. }
  968. switch(nTransferType)
  969. {
  970. case 0:
  971. SendResponse("150 Opening ASCII mode data connection for directory list.");
  972. break;
  973. case 1:
  974. case 2:
  975. SendResponse("150 Opening BINARY mode data connection for file transfer.");
  976. break;
  977. }
  978. }
  979. else
  980. {
  981. SendResponse("421 Failed to create data connection socket.");
  982. return FALSE;
  983. }
  984. }
  985. else
  986. {
  987. m_pDataSocket->SetRestartOffset(m_dwRestartOffset);
  988. m_pDataSocket->SetData(lpszData);
  989. m_pDataSocket->SetTransferType(nTransferType, TRUE);
  990. }
  991. return TRUE;
  992. }
  993. /********************************************************************/
  994. /* */
  995. /* Function name: DestroyDataConnection */
  996. /* Description : Close data transfer connection. */
  997. /* */
  998. /********************************************************************/
  999. void CConnectSocket::DestroyDataConnection()
  1000. {
  1001. if (!m_pDataSocket)
  1002. return;
  1003. /////////////////////////////xiao
  1004. SOCKET s=m_pDataSocket->Detach ();
  1005. closesocket( s) ;
  1006. //////////////////////////////
  1007. delete m_pDataSocket;
  1008. // reset transfer status
  1009. m_pDataSocket = NULL;
  1010. m_strRemoteHost = "";
  1011. m_nRemotePort = -1;
  1012. m_dwRestartOffset = 0;
  1013. m_bPassiveMode = FALSE;
  1014. }
  1015. //RETR