📄 ftp.c
字号:
int nRC = 0;
DWORD dwParamLen;
TRACE("%d: (%s) %d\n", ftpCmd, lpszParam, nSocket);
if (lpfnStatusCB)
{
HINTERNET hHandle = WININET_FindHandle( hdr );
if( hHandle )
{
lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
WININET_Release( hdr );
}
}
dwParamLen = lpszParam?strlen(lpszParam)+1:0;
len = dwParamLen + strlen(szFtpCommands[ftpCmd]) + strlen(szCRLF);
if (NULL == (buf = HeapAlloc(GetProcessHeap(), 0, len+1)))
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], dwParamLen ? " " : "",
dwParamLen ? lpszParam : "", szCRLF);
TRACE("Sending (%s) len(%ld)\n", buf, len);
while((nBytesSent < len) && (nRC != -1))
{
nRC = send(nSocket, buf+nBytesSent, len - nBytesSent, 0);
nBytesSent += nRC;
}
HeapFree(GetProcessHeap(), 0, (LPVOID)buf);
if (lpfnStatusCB)
{
HINTERNET hHandle = WININET_FindHandle( hdr );
if( hHandle )
{
lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT,
&nBytesSent, sizeof(DWORD));
WININET_Release( hdr );
}
}
TRACE("Sent %ld bytes\n", nBytesSent);
return (nRC != -1);
}
/***********************************************************************
* FTP_SendCommand (internal)
*
* Send command to server
*
* RETURNS
* TRUE on success
* NULL on failure
*
*/
static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext)
{
BOOL ret;
LPSTR lpszParamA = lpszParam?WININET_strdup_WtoA(lpszParam):NULL;
ret = FTP_SendCommandA(nSocket, ftpCmd, lpszParamA, lpfnStatusCB, hdr, dwContext);
HeapFree(GetProcessHeap(), 0, lpszParamA);
return ret;
}
/***********************************************************************
* FTP_ReceiveResponse (internal)
*
* Receive response from server
*
* RETURNS
* Reply code on success
* 0 on failure
*
*/
INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD dwContext)
{
LPSTR lpszResponse = INTERNET_GetResponseBuffer();
DWORD nRecv;
INT rc = 0;
char firstprefix[5];
BOOL multiline = FALSE;
LPWININETAPPINFOW hIC = NULL;
TRACE("socket(%d)\n", lpwfs->sndSocket);
hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
SendAsyncCallback(&lpwfs->hdr, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
while(1)
{
if (!INTERNET_GetNextLine(lpwfs->sndSocket, &nRecv))
goto lerror;
if (nRecv >= 3)
{
if(!multiline)
{
if(lpszResponse[3] != '-')
break;
else
{ /* Start of multiline repsonse. Loop until we get "nnn " */
multiline = TRUE;
memcpy(firstprefix, lpszResponse, 3);
firstprefix[3] = ' ';
firstprefix[4] = '\0';
}
}
else
{
if(!memcmp(firstprefix, lpszResponse, 4))
break;
}
}
}
if (nRecv >= 3)
{
rc = atoi(lpszResponse);
SendAsyncCallback(&lpwfs->hdr, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&nRecv, sizeof(DWORD));
}
lerror:
TRACE("return %d\n", rc);
return rc;
}
/***********************************************************************
* FTP_SendPassword (internal)
*
* Send password to ftp server
*
* RETURNS
* TRUE on success
* NULL on failure
*
*/
static BOOL FTP_SendPassword(LPWININETFTPSESSIONW lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
TRACE("\n");
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASS, lpwfs->lpszPassword, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
if (nResCode)
{
TRACE("Received reply code %d\n", nResCode);
/* Login successful... */
if (nResCode == 230)
bSuccess = TRUE;
/* Command not implemented, superfluous at the server site... */
/* Need account for login... */
else if (nResCode == 332)
bSuccess = FTP_SendAccount(lpwfs);
else
FTP_SetResponseError(nResCode);
}
lend:
TRACE("Returning %d\n", bSuccess);
return bSuccess;
}
/***********************************************************************
* FTP_SendAccount (internal)
*
*
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
static BOOL FTP_SendAccount(LPWININETFTPSESSIONW lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
TRACE("\n");
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_ACCT, szNoAccount, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
if (nResCode)
bSuccess = TRUE;
else
FTP_SetResponseError(nResCode);
lend:
return bSuccess;
}
/***********************************************************************
* FTP_SendStore (internal)
*
* Send request to upload file to ftp server
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
static BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
{
INT nResCode;
BOOL bSuccess = FALSE;
TRACE("\n");
if (!FTP_InitListenSocket(lpwfs))
goto lend;
if (!FTP_SendType(lpwfs, dwType))
goto lend;
if (!FTP_SendPortOrPasv(lpwfs))
goto lend;
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_STOR, lpszRemoteFile, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
if (nResCode)
{
if (nResCode == 150)
bSuccess = TRUE;
else
FTP_SetResponseError(nResCode);
}
lend:
if (!bSuccess && lpwfs->lstnSocket != -1)
{
closesocket(lpwfs->lstnSocket);
lpwfs->lstnSocket = -1;
}
return bSuccess;
}
/***********************************************************************
* FTP_InitListenSocket (internal)
*
* Create a socket to listen for server response
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs)
{
BOOL bSuccess = FALSE;
size_t namelen = sizeof(struct sockaddr_in);
TRACE("\n");
lpwfs->lstnSocket = socket(PF_INET, SOCK_STREAM, 0);
if (lpwfs->lstnSocket == -1)
{
TRACE("Unable to create listening socket\n");
goto lend;
}
/* We obtain our ip addr from the name of the command channel socket */
lpwfs->lstnSocketAddress = lpwfs->socketAddress;
/* and get the system to assign us a port */
lpwfs->lstnSocketAddress.sin_port = htons((u_short) 0);
if (bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(struct sockaddr_in)) == -1)
{
TRACE("Unable to bind socket\n");
goto lend;
}
if (listen(lpwfs->lstnSocket, MAX_BACKLOG) == -1)
{
TRACE("listen failed\n");
goto lend;
}
if (getsockname(lpwfs->lstnSocket, (struct sockaddr *) &lpwfs->lstnSocketAddress, &namelen) != -1)
bSuccess = TRUE;
lend:
if (!bSuccess && lpwfs->lstnSocket == -1)
{
closesocket(lpwfs->lstnSocket);
lpwfs->lstnSocket = -1;
}
return bSuccess;
}
/***********************************************************************
* FTP_SendType (internal)
*
* Tell server type of data being transferred
*
* RETURNS
* TRUE on success
* FALSE on failure
*
* W98SE doesn't cache the type that's currently set
* (i.e. it sends it always),
* so we probably don't want to do that either.
*/
static BOOL FTP_SendType(LPWININETFTPSESSIONW lpwfs, DWORD dwType)
{
INT nResCode;
WCHAR type[] = { 'I','\0' };
BOOL bSuccess = FALSE;
TRACE("\n");
if (dwType & INTERNET_FLAG_TRANSFER_ASCII)
type[0] = 'A';
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_TYPE, type, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext)/100;
if (nResCode)
{
if (nResCode == 2)
bSuccess = TRUE;
else
FTP_SetResponseError(nResCode);
}
lend:
return bSuccess;
}
/***********************************************************************
* FTP_GetFileSize (internal)
*
* Retrieves from the server the size of the given file
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
static BOOL FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD *dwSize)
{
INT nResCode;
BOOL bSuccess = FALSE;
TRACE("\n");
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_SIZE, lpszRemoteFile, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
if (nResCode)
{
if (nResCode == 213) {
/* Now parses the output to get the actual file size */
int i;
LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
for (i = 0; (lpszResponseBuffer[i] != ' ') && (lpszResponseBuffer[i] != '\0'); i++) ;
if (lpszResponseBuffer[i] == '\0') return FALSE;
*dwSize = atol(&(lpszResponseBuffer[i + 1]));
bSuccess = TRUE;
} else {
FTP_SetResponseError(nResCode);
}
}
lend:
return bSuccess;
}
/***********************************************************************
* FTP_SendPort (internal)
*
* Tell server which port to use
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
static BOOL FTP_SendPort(LPWININETFTPSESSIONW lpwfs)
{
static const WCHAR szIPFormat[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
INT nResCode;
WCHAR szIPAddress[64];
BOOL bSuccess = FALSE;
TRACE("\n");
sprintfW(szIPAddress, szIPFormat,
lpwfs->lstnSocketAddress.sin_addr.s_addr&0x000000FF,
(lpwfs->lstnSocketAddress.sin_addr.s_addr&0x0000FF00)>>8,
(lpwfs->lstnSocketAddress.sin_addr.s_addr&0x00FF0000)>>16,
(lpwfs->lstnSocketAddress.sin_addr.s_addr&0xFF000000)>>24,
lpwfs->lstnSocketAddress.sin_port & 0xFF,
(lpwfs->lstnSocketAddress.sin_port & 0xFF00)>>8);
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PORT, szIPAddress, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
if (nResCode)
{
if (nResCode == 200)
bSuccess = TRUE;
else
FTP_SetResponseError(nResCode);
}
lend:
return bSuccess;
}
/***********************************************************************
* FTP_DoPassive (internal)
*
* Tell server that we want to do passive transfers
* and connect data socket
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
static BOOL FTP_DoPassive(LPWININETFTPSESSIONW lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
TRACE("\n");
if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASV, NULL, 0, 0, 0))
goto lend;
nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
if (nResCode)
{
if (nResCode == 227)
{
LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
LPSTR p;
int f[6];
int i;
char *pAddr, *pPort;
INT nsocket = -1;
struct sockaddr_in dataSocket
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -