⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp-server-code.txt

📁 实现简单文件上传
💻 TXT
📖 第 1 页 / 共 3 页
字号:
BOOL   UnixPathToDosPath(const   char   unixFullPath[MAX_PATH],   char   dosFullPath[MAX_PATH])   
  {   
  if(   unixFullPath[0]=='/'   &&   isalpha(unixFullPath[1])   &&   unixFullPath[2]   ==   '/'   )   
  {   
  sprintf(dosFullPath,   "%c:\\%s",   unixFullPath[1],   unixFullPath+3);   
  for(int   i   =   strlen(dosFullPath)-1;   i>=0;   i--)   
  if(   dosFullPath[i]   ==   '/'   )   dosFullPath[i]   =   '\\';   
  return   TRUE;   
  }   
  else   
  return   FALSE;   
  }   
    
  BOOL   DosPathToUnixPath(const   char   dosFullPath[MAX_PATH],   char   unixFullPath[MAX_PATH])   
  {   
  if(   isalpha(dosFullPath[0])   &&   memcmp(dosFullPath+1,   ":\\",   2)==0   )   
  {   
  sprintf(unixFullPath,   "/%c/%s",   dosFullPath[0],   dosFullPath+3);   
  for(int   i   =   strlen(unixFullPath)-1;   i>=0;   i--)   
  if(   unixFullPath[i]   ==   '\\'   )   unixFullPath[i]   =   '/';   
  return   TRUE;   
  }   
  else   
  return   FALSE;   
  }   
    
  BOOL   GetFullUnixPath(const   char   unixPath[MAX_PATH],   const   char   unixWorkDir[MAX_PATH],     
    char   unixFullPath[MAX_PATH])   
  {   
  //get   full   path   that   may   be   redundant,   saying   include   .   or   ..   
  if(   unixPath[0]   ==   '/'   )   //it's   full   now   
  {   
  strcpy(unixFullPath,   unixPath);   
  }   
  else   if(   strcmp(unixWorkDir,   "/")==0   )   //unixWorkDir   is   root   dir   
  {   
  sprintf(unixFullPath,   "/%s",   unixPath);   
  }   
  else   
  {   
  sprintf(unixFullPath,   "%s/%s",   unixWorkDir,   unixPath);   
  }   
    
  if(   strcmp(unixFullPath,   "")   ==   0   )   
  strcpy(unixFullPath,   "/");   
    
  //get   pure   full   path,   get   rid   of   .   or   ..   
  char   unixPureFullPath[MAX_PATH];   
  strcpy(unixPureFullPath,   "");   
  char   *p1,   *p2;   
  for(p1=unixFullPath,   p2=unixFullPath+1;;p2++)   
  {   
  if(   *p2   ==   0   ||   *p2   ==   '/'   )   
  {   
  char   unit[MAX_PATH];   
  memcpy(unit,   p1,   p2-p1);   
  unit[p2-p1]   =   0;   
  p1   =   p2;   
  if(   strcmp(unit,   "/.")   ==   0   )     
  {   
  //keep   directory   not   changed   
  if(   *p2   ==   0   )   
  break;   
  else   
  continue;   
  }   
  else   if(   strcmp(unit,   "/..")   ==   0   )   
  {   
  //come   back   to   parent   directory   
  //look   for   the   last   '/',   and   set   it   to   0   
  for(int   i=strlen(unixPureFullPath)-1;   i>=0   &&   unixPureFullPath[i]!='/';   i--)NULL;     
  if(   i>=0   )   
  unixPureFullPath[i]   =   0;   
  }   
  else     //add   a   subdir   to   unixPureFullPath   
  {   
  strcat(unixPureFullPath,   unit);   
  }   
  }   
    
  if(   *p2   ==   0   )   
  break;   
  }   
    
  if(   strcmp(unixPureFullPath,   "")   ==   0   )   
  strcpy(unixPureFullPath,   "/");   
    
  strcpy(unixFullPath,   unixPureFullPath);   
  return   TRUE;   
  }   
    
    
  BOOL   GetParentUnixPath(const   char   unixFullPath[MAX_PATH],   char   parentPath[MAX_PATH])   
  {   
  if(   strcmp(unixFullPath,   "/")   ==   0   )   
  strcpy(parentPath,   "/");   
  else   
  {   
  //look   for   the   last   '/'   
  for(int   i=strlen(unixFullPath)-1;   i>=0   &&   unixFullPath[i]   !=   '/';   i--)NULL;     
  if(   i<=0   )   
  strcpy(parentPath,   "/");   
  else   
  {   
  memcpy(parentPath,   unixFullPath,   i);   
  parentPath[i]   =   0;   
  }   
  }   
  return   TRUE;   
  }   
    
    
  enum   FTP_TRANSLATE_TYPE   {TYPE_RETR,   TYPE_STOR,   TYPE_APPE};   
  struct   FTP_CONTROL_BLOCK   
  {   
  //input   
  SOCKET   sockCtrl;   
  SOCKET   sockData;   
  char   filename[MAX_PATH];   
  enum   FTP_TRANSLATE_TYPE   translateType;   
  DWORD   dwStartPos;   
  BOOL   bDeleteFileAfterCompletion;   
  BOOL   bAbort;   
    
  //output   
  BOOL   bThreadExited;   
  };   
    
  DWORD   WINAPI   FtpDataThreadProc(LPVOID   lpParam)   
  {   
  char   replyStr[FTP_MAX_LINE_BUFFER];   
  BYTE   buffer[FTP_TRANSFER_FILE_BUFFER_LENGTH];   
  char   szError[MAX_SOCKET_ERROR_STRING];   
    
  //init   
  FTP_CONTROL_BLOCK*   pBlock   =   (FTP_CONTROL_BLOCK*)lpParam;   
  pBlock->bThreadExited   =   FALSE;   
  BOOL   bSocketError   =   FALSE;   
  BOOL   bFileError   =   FALSE;   
  BOOL   bComplete   =   FALSE;   
    
  //send   150   reply   string   
  sprintf(replyStr,   "150   openning   data   connection\r\n");   
  BlockingSendToSocket(pBlock->sockCtrl,   replyStr,   strlen(replyStr),   &pBlock->bAbort,   szError);   
    
  //open   file   to   receive   or   send   
  FILE*   fp   =   NULL;   
  if(   pBlock->translateType   ==   TYPE_RETR   )   
  {   
  fp   =   fopen(pBlock->filename,   "rb");   
  if(   fseek(fp,   pBlock->dwStartPos,   SEEK_SET)   !=   0   )   
  {   
  fclose(fp);   
  fp   =   NULL;   
  }   
  }   
  else   if(   pBlock->translateType   ==   TYPE_STOR   )   
  {   
  if(   ExistFile(pBlock->filename)   )   
  {   
  fp   =   fopen(pBlock->filename,   "r+b");   
  if(   fseek(fp,   pBlock->dwStartPos,   SEEK_SET)   !=0   )   //seek   failed   
  {   
  fclose(fp);   
  fp   =   NULL;   
  }   
  }   
  else   
  {   
  if(   pBlock->dwStartPos   !=   0   )   //cannot   write   to   it   from   place   that   isn't   begin   (0)   
  bFileError   =   TRUE;   
  else   
  fp   =   fopen(pBlock->filename,   "wb");   
  }   
  }   
  else   if(   pBlock->translateType   ==   TYPE_APPE   )   
  fp   =   fopen(pBlock->filename,   "ab");   
    
  if(   fp   )   
  {   
  DWORD   dwCount;   
  while(   !pBlock->bAbort   &&   !bSocketError   &&   !bFileError   &&   !bComplete   )   
  {   
  if(   pBlock->translateType   ==   TYPE_RETR   )   
  {   
  dwCount   =   fread(buffer,   1,   sizeof(buffer),   fp);   
  if(   !BlockingSendToSocket(pBlock->sockData,   (char*)buffer,   dwCount,   &pBlock->bAbort,   szError)   )   
  {   
  if(   !pBlock->bAbort   )   
  bSocketError   =   TRUE;   
  }   
  if(   dwCount   ==   0   )   
  bComplete   =   TRUE;   
  }   
  else   
  {   
  FD_SET   fds;   
  timeval   timeout   =   {1,0};   
  FD_ZERO(&fds);   
  FD_SET(pBlock->sockData,   &fds);   
  int   nReady   =   select(pBlock->sockData+1,   &fds,   NULL,   NULL,   &timeout);   
  if(   nReady   ==   SOCKET_ERROR   )   
  {   
  debug_printf("FtpDataThreadProc:   select   %d\n",   WSAGetLastError()   );   
  bSocketError   =   TRUE;   
  continue;   
  }   
  else   if(   nReady   ==   0   )   
  continue;   
  int   nRead   =   recv(pBlock->sockData,   (char*)buffer,   sizeof(buffer),   0);   
  if(   nRead   <   0   )   
  {   
  debug_printf("CFtpServer::Run():   recv   %d\n",   WSAGetLastError()   );   
  bSocketError   =   TRUE;   
  }   
  else   if(   nRead   ==   0   )   
  {   
  bComplete   =   TRUE;   
  }   
  else   
  {   
  int   nWrite   =   fwrite(buffer,   1,   nRead,   fp);   
  if(   nWrite   !=   nRead   )   
  bFileError   =   TRUE;   
  }   
  }   
  }   
  fclose(fp);   
  }   
  else   
  bFileError   =   TRUE;   
    
  //delete   file   if   neccesary   
  if(   pBlock->bDeleteFileAfterCompletion   )   
  DeleteFile(pBlock->filename);   
    
  //create   reply   code   string   
  if(   bComplete   )   
  sprintf(replyStr,   "226   transfer   complete\r\n");   
  if(   bFileError   )   
  sprintf(replyStr,   "450   access   to   %s   failed\r\n",   pBlock->filename);   
  if(   bSocketError   )   
  sprintf(replyStr,   "420   network   error   %s\r\n",   szError);   
  if(   pBlock->bAbort   )   
  sprintf(replyStr,   "226   ABOR   command   successful\r\n");   
    
  //send   reply   code   
  BOOL   bShouldExit   =   FALSE;   
  BlockingSendToSocket(pBlock->sockCtrl,   replyStr,   strlen(replyStr),   &bShouldExit,   szError);   
  debug_printf("%s",   replyStr);   
    
  //close   data   socket   
  if(   pBlock->translateType   ==   TYPE_RETR   )   
  {   
  shutdown(pBlock->sockData,   SD_SEND);   
  //wait   for   the   peer   to   close   
  while(recv(pBlock->sockData,   (char*)buffer,   sizeof(buffer),   0)>0)NULL;     
  closesocket(pBlock->sockData);   
  }   
  else   
  {   
  shutdown(pBlock->sockData,   SD_SEND);   
  closesocket(pBlock->sockData);   
  }   
  pBlock->sockData   =   INVALID_SOCKET;   
  pBlock->dwStartPos   =   0;   
    
  //set   exit   flag   
  pBlock->bThreadExited   =   TRUE;   
  return   0;   
  }   
    
    
  BOOL   GetListRootResult(BOOL   bNameList,   FILE*fp)   
  {   
  char   rootPath[4]   =   "A:\\";   
  char   name[2]   =   "A";   
  char   item[MAX_PATH+100];   
  for(int   i=0;   i<26;   i++)   
  {   
  rootPath[0]   =   'A'   +   i;   
  if(   GetDriveType(rootPath)   !=   DRIVE_NO_ROOT_DIR   )   //this   driver   exists   
  {   
  name[0]   =   'A'   +   i;   
  if(   bNameList   )   
  {   
  sprintf(item,   "%s\r\n",   name);   
  fwrite(item,   1,   strlen(item),   fp);   
  }   
  else   
  {   
  sprintf(item,   "drwxrwxrwx         1   owner         group                               0   Jul   11   20:40   %s\r\n",   name);   
  fwrite(item,   1,   strlen(item),   fp);   
  }   
  }   
  }   
  return   TRUE;   
  }   
    
  BOOL   GetListResult(const   char   szListCommand[MAX_PATH],   const   char   unixWorkDir[MAX_PATH],     
        FILE*fp)   
  {   
  if(   memicmp(szListCommand,   "LIST",   4)   !=   0   &&   memicmp(szListCommand,   "NLST",   4)   !=   0   )   
  return   FALSE;   
  BOOL   bNameList   =   FALSE;   
  if(   memicmp(szListCommand,   "NLST",   4)   ==   0   )   
  bNameList   =   TRUE;   
    
  //extract   out   unixFullPath   
  int   i;   
  char   unixFullPath[MAX_PATH];   
  for(i=4;   '   '   ==   szListCommand[i];   i++)NULL;   //skip   white   space   
  if(   szListCommand[i]==0   )   //no   parameter   
  strcpy(unixFullPath,   unixWorkDir);   
  else   //has   parameter   
  GetFullUnixPath(szListCommand+i,   unixWorkDir,   unixFullPath);   
    
  //root   dir   is   treated   specially   
  if(   strcmp(unixFullPath,   "/")   ==   0   )   
  {   
  return   GetListRootResult(bNameList,   fp);   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -