From 2429d51ff2956d9736ebc48b1e495fcd8d45eae6 Mon Sep 17 00:00:00 2001 From: Lionel Ulmer Date: Mon, 21 Jul 2003 19:59:03 +0000 Subject: [PATCH] - use SIZE command to retrieve the file size (as the file size is not part of the WinNT acknowledgement string) - free the handle / close the socket on end of download - fix InternetReadFile in the FTP case - fix FTP_ReceiveResponse --- dlls/wininet/ftp.c | 105 ++++++++++++++++++++++++++++++---------- dlls/wininet/internet.c | 10 ++-- dlls/wininet/internet.h | 1 + 3 files changed, 85 insertions(+), 31 deletions(-) diff --git a/dlls/wininet/ftp.c b/dlls/wininet/ftp.c index ab7243438db..2cea4581e17 100644 --- a/dlls/wininet/ftp.c +++ b/dlls/wininet/ftp.c @@ -72,6 +72,7 @@ typedef enum { FTP_CMD_STOR, FTP_CMD_TYPE, FTP_CMD_USER, + FTP_CMD_SIZE, /* FTP commands without arguments. */ FTP_CMD_ABOR, @@ -96,6 +97,7 @@ static const CHAR *szFtpCommands[] = { "STOR", "TYPE", "USER", + "SIZE", "ABOR", "LIST", "NLST", @@ -120,6 +122,7 @@ BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType); +BOOL FTP_GetFileSize(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD *dwSize); BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs); BOOL FTP_DoPassive(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONA lpwfs); @@ -1690,7 +1693,6 @@ INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse, if (nRecv >= 3) { - lpszResponse[nRecv] = '\0'; rc = atoi(lpszResponse); if (lpfnStatusCB) @@ -1896,7 +1898,7 @@ lend: BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType) { INT nResCode; - CHAR type[2] = { "I\0" }; + CHAR type[2] = { "I" }; BOOL bSuccess = FALSE; TRACE("\n"); @@ -1920,6 +1922,49 @@ lend: return bSuccess; } +/*********************************************************************** + * FTP_GetFileSize (internal) + * + * Retrieves from the server the size of the given file + * + * RETURNS + * TRUE on success + * FALSE on failure + * + */ +BOOL FTP_GetFileSize(LPWININETFTPSESSIONA lpwfs, LPCSTR 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->sndSocket, INTERNET_GetResponseBuffer(), + MAX_REPLY_LEN, 0, 0, 0); + 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) @@ -2210,33 +2255,19 @@ DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD if (!FTP_SendPortOrPasv(lpwfs)) goto lend; + if (!FTP_GetFileSize(lpwfs, lpszRemoteFile, &nResult)) + goto lend; + + TRACE("Waiting to receive %ld bytes\n", nResult); + if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0)) goto lend; nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0); - if (nResCode) - { - if (nResCode == 125 || nResCode == 150) - { - /* Parse size of data to be retrieved */ - INT i, sizepos = -1; - LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer(); - for (i = strlen(lpszResponseBuffer) - 1; i >= 0; i--) - { - if ('(' == lpszResponseBuffer[i]) - { - sizepos = i; - break; - } - } - - if (sizepos >= 0) - { - nResult = atol(&lpszResponseBuffer[sizepos+1]); - TRACE("Waiting to receive %ld bytes\n", nResult); - } - } + if ((nResCode != 125) && (nResCode != 150)) { + /* That means that we got an error getting the file. */ + nResult = 0; } lend: @@ -2316,6 +2347,8 @@ recv_end: */ BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs) { + TRACE("\n"); + if (lpwfs->sndSocket != -1) close(lpwfs->sndSocket); @@ -2335,7 +2368,7 @@ BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs) /*********************************************************************** - * FTP_CloseSessionHandle (internal) + * FTP_CloseFindNextHandle (internal) * * Deallocate session handle * @@ -2362,6 +2395,28 @@ BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn) return TRUE; } +/*********************************************************************** + * FTP_CloseFindNextHandle (internal) + * + * Closes the file transfer handle. This also 'cleans' the data queue of + * the 'transfer conplete' message (this is a bit of a hack though :-/ ) + * + * RETURNS + * TRUE on success + * FALSE on failure + * + */ +BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwh) +{ + TRACE("\n"); + + if (lpwh->nDataSocket != -1) + close(lpwh->nDataSocket); + + HeapFree(GetProcessHeap(), 0, lpwh); + + return TRUE; +} /*********************************************************************** * FTP_ReceiveFileList (internal) diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 0f72543bcdd..1d9232ef6b7 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -701,6 +701,10 @@ BOOL WINAPI InternetCloseHandle(HINTERNET hInternet) retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh); break; + case WH_HFILE: + retval = FTP_CloseFileTransferHandle((LPWININETFILE) lpwh); + break; + default: break; } @@ -1331,12 +1335,6 @@ BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer, break; } - if (nSocket != -1) - { - int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0); - retval = (res >= 0); - *dwNumOfBytesRead = retval ? res : 0; - } return retval; } diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index 6e8e0d90c98..1394f01c185 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -243,6 +243,7 @@ LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer); BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs); BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn); +BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwfn); BOOLAPI FTP_FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile, LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext); BOOLAPI FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory);