?? ftpdlib.c
字號(hào):
* when a halt is in progress, causing an error on the socket. * In this case, ignore the error and exit the command loop * to send a termination message to the connected client. */ if (ftpsShutdownFlag) { *pBuf = EOS; break; } /* * Send a final message if the control socket * closed unexpectedly. */ if (numRead == 0) ftpdCmdSend (pSlot, sock, 221, messages [MSG_NO_GOOD_BYE], 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return ERROR; } /* Skip the CR in the buffer. */ if ( *pBuf == '\r' ) continue; /* End Of Command delimeter. exit loop and process command */ /* also check buffer bounds */ if (( *pBuf == '\n' ) || (pBuf == pBufEnd)) { *pBuf = EOS; break; } pBuf++; /* Advance to next character to read */ } /* FOREVER - read line */ /* Reset Buffer Pointer before we use it */ pBuf = &pSlot->buf [0]; /* convert the command to upper-case */ for (upperCommand = pBuf; (*upperCommand != ' ') && (*upperCommand != EOS); upperCommand++) *upperCommand = toupper (*upperCommand); ftpdDebugMsg ("read command %s\n", (int)pBuf,0,0,0); /* * Send an abort message to the client if a server * shutdown was started while reading the next command. */ if (ftpsShutdownFlag) { ftpdCmdSend (pSlot, sock, 421, "Service not available, closing control connection", 0, 0, 0, 0, 0, 0); break; } if (strncmp (pBuf, "USER", 4) == 0) { /* check user name */ /* Actually copy the user name into a buffer and save it */ /* till the password comes in. Name is located one space */ /* character after USER string */ if ( *(pBuf + 4) == '\0' ) pSlot->curUserName[0] = '\0'; /* NOP user for null user */ else strncpy(pSlot->curUserName, pBuf+5, MAX_LOGIN_NAME_LEN); pSlot->status &= ~(FTPD_USER_OK | FTPD_ANONYMOUS); if( (strcmp(pSlot->curUserName, FTPD_ANONYMOUS_USER_1) ==0) || (strcmp(pSlot->curUserName, FTPD_ANONYMOUS_USER_2) ==0) || (strcmp(pSlot->curUserName, FTPD_ANONYMOUS_USER_3) ==0) ) { pSlot->status |= FTPD_ANONYMOUS ; /* tentative */ ftpdCmdSend (pSlot, sock, 331, messages [MSG_GUEST_PASS], 0, 0, 0, 0, 0, 0) ; continue; } if (ftpdCmdSend (pSlot, sock, 331, messages [MSG_PASSWORD_REQUIRED], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } else if (strncmp (pBuf, "PASS", 4) == 0) { /* check user passwd */ if( pSlot->status & FTPD_ANONYMOUS ) { if( (guestHomeDir[0] == EOS) || (pBuf[5]==EOS) ) { ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0); continue; } pSlot->status |= FTPD_USER_OK; /* current dir is allways internal absolute */ strcpy (pSlot->curDirName, guestHomeDir); if( guestHomeDir [ strlen(guestHomeDir) -1 ] != '/'); strcat(pSlot->curDirName, "/"); strcpy(newPath, writeDirName); if( writeDirName[0] == EOS ) ftpdCmdSend (pSlot, sock, 230, messages [MSG_GUEST_OK], 0, 0, 0, 0, 0, 0); else ftpdCmdSend (pSlot, sock, 230, messages [MSG_GUEST_UPLOAD_OK], (int) ftpdPathForPrint(pSlot, newPath), 0, 0, 0, 0, 0); continue; } /* Actually check it against earlier supplied user name */ if ( pLoginVrfyFunc != (FUNCPTR)NULL ) { ftpdDebugMsg ("Verifying login for user %s\n", (int)pSlot->curUserName,0,0,0); if ( (*pLoginVrfyFunc)(pSlot->curUserName, pBuf+5) != OK ) { if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; pSlot->status &= ~FTPD_USER_OK; continue; } } /* if there is no login verification call, but we got a anonymous * enabled, accept anonymous only, with said restrictions. */ if( guestHomeDir[0] != EOS ) { if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; pSlot->status &= ~FTPD_USER_OK; continue; } pSlot->status |= FTPD_USER_OK; if (ftpdCmdSend (pSlot, sock, 230, messages [MSG_USER_LOGGED_IN], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } else if (strncmp (pBuf, "QUIT", 4) == 0) { /* sayonara */ ftpdCmdSend (pSlot, sock, 221, messages [MSG_SEE_YOU_LATER], 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return OK; } else if (strncmp (pBuf, "SYST", 4) == 0) { ftpdCmdSend (pSlot, sock, 215, messages [MSG_SYST_REPLY], 0, 0, 0, 0, 0, 0); continue; } else if (strncmp (pBuf, "HELP", 4) == 0) { /* send list of supported commands with multiple line response */ if (ftpdCmdSend (pSlot, sock, FTPD_MULTI_LINE | 214, messages [MSG_COMMAND_LIST_BEGIN], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; if (write (pSlot->cmdSock, ftpdCommandList, strlen (ftpdCommandList)) <= 0) goto connectionLost; /* this signifies the end of the multiple line response */ if (ftpdCmdSend (pSlot, sock, 214, messages [MSG_COMMAND_LIST_END], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; /* All is well go wait for the next command */ } else if ((pSlot->status & FTPD_USER_OK) == 0) /* validated yet? */ { /* user is not validated yet. tell him to log in first */ if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_PASS_REQ], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; /* do not proceed further until he's legit */ continue; } if (strncmp (pBuf, "LIST", 4) == 0 || strncmp (pBuf, "NLST", 4) == 0) { STATUS retVal; /* client wants to list out the contents of a directory */ ftpPathNormalize ( pSlot, &pBuf[5], newPath, &dirName ); ftpdDebugMsg ("listing %s\n", (int)dirName,0,0,0); if( ftpPathAccessVerify(pSlot, dirName, O_RDONLY) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_GUEST_ACCESS], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } /* get a new data socket connection for the transmission of * the directory listing data */ if (ftpdDataConnGet (pSlot) == ERROR) { if (ftpdCmdSend (pSlot, sock, 426, messages [MSG_DATA_CONN_ERROR], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } /* print out the directory contents over the data connection */ retVal = ftpdDirListGet (pSlot->dataSock, dirName, (strncmp (pBuf, "LIST", 4) == 0)); if (retVal == ERROR) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_DIR_ERROR], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; } else { if (ftpdCmdSend (pSlot, sock, 226, messages [MSG_TRANS_COMPLETE], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; } /* free up the data socket */ ftpdSockFree (&pSlot->dataSock); } else if ( (strncmp (pBuf, "RETR", 4) == 0) || (strncmp (pBuf, "SIZE", 4) == 0) || (strncmp (pBuf, "MDTM", 4) == 0) ) { struct stat fileStat ; /* retrieve a file */ /* open the file to be sent to the client */ ftpPathNormalize ( pSlot, &pBuf[5], newPath, &pFileName ); ftpdDebugMsg ("accessing %s\n", (int)pFileName,0,0,0); if( ftpPathAccessVerify(pSlot, pFileName, O_RDONLY) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_GUEST_ACCESS], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } if(stat(pFileName, &fileStat) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_FILE_ERROR], (int)(&pBuf[5]), 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } if( ! S_ISREG (fileStat.st_mode) ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_FILE_NOTREG], (int)(&pBuf[5]), 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } /* decide what to do with the file according to the actual cmd */ if (strncmp (pBuf, "RETR", 4) == 0) { /* ship it away */ ftpdDataStreamSend (pSlot, pFileName); } else if (strncmp (pBuf, "SIZE", 4) == 0) { if (ftpdCmdSend (pSlot, sock, 213, "%lu", fileStat.st_size, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; } else if (strncmp (pBuf, "MDTM", 4) == 0) { struct tm fileDate; localtime_r (&fileStat.st_mtime, &fileDate); if (ftpdCmdSend (pSlot, sock, 213, "%04d%02d%02d%02d%02d%02d", fileDate.tm_year+1900, fileDate.tm_mon, fileDate.tm_mday, fileDate.tm_hour, fileDate.tm_min, fileDate.tm_sec ) == ERROR) goto connectionLost; } } else if (strncmp (pBuf, "STOR", 4) == 0) { STATUS retVal ; /* store a file */ ftpPathNormalize ( pSlot, &pBuf[5], newPath, &pFileName ); ftpdDebugMsg ("STOR %s\n", (int)pFileName,0,0,0); if( ftpPathAccessVerify(pSlot, pFileName, O_WRONLY) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_GUEST_ACCESS], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } /* create a local file */ if ((outStream = fopen (pFileName, "w")) == NULL) { if (ftpdCmdSend (pSlot, sock, 553, messages[MSG_CREATE_ERROR], (int)(&pBuf[5]), 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } /* receive the file */ retVal = ftpdDataStreamReceive (pSlot, outStream); (void) fclose (outStream); /* remove lame file */ if( retVal == ERROR ) { unlink( pFileName ); } } else if (strncmp (pBuf, "RNFR", 4) == 0) { struct stat st; /* for stat() system call */ ftpPathNormalize ( pSlot, &pBuf[5], newPath, &pFileName ); ftpdDebugMsg ("RNFR %s\n", (int)pFileName,0,0,0); if( ftpPathAccessVerify(pSlot, pFileName, O_RDWR) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_GUEST_ACCESS], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } if( stat( pFileName, &st ) != OK ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_FILE_ERROR], (int) pFileName, 0, 0, 0, 0, 0) == ERROR) goto connectionLost ; renFile[0] = EOS ; continue; } /* store file name for the next command which should be RNTO */ strncpy( renFile, pFileName, MAX_FILENAME_LENGTH ); if (ftpdCmdSend (pSlot, sock, 350, messages [MSG_RNFR_OK], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost ; } else if (strncmp (pBuf, "RNTO", 4) == 0) { ftpPathNormalize ( pSlot, &pBuf[5], newPath, &pFileName ); ftpdDebugMsg ("RNTO %s\n", (int)pFileName,0,0,0); if( ftpPathAccessVerify(pSlot, pFileName, O_WRONLY) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_GUEST_ACCESS], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } if( rename( renFile, pFileName ) != OK ) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -