[WININET] Fixes RETR on WinNT FTP servers.
Lionel Ulmer
lionel.ulmer at free.fr
Sat Jul 19 10:58:34 CDT 2003
Hi all,
This is the next step in getting Ragnarok Online patcher to work fine... I
now manage to download fine the first file. There is still a problem with
the second file, but that will be part of a second patch (because I feel the
change to be a bit more controversial than in this one).
If anyone wants to write some unit test code for the FTP functions, feel
free, I think that they need it :)
Lionel
Changelog:
- use SIZE command to retrieve the file size (as the file size is not part
of the WinNT acknowledgement string)
- frees the handle / close the socket on end of download
- fix InternetReadFile in the FTP case
- fix FTP_ReceiveResponse
--
Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
Index: dlls/wininet/ftp.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/ftp.c,v
retrieving revision 1.29
diff -u -r1.29 ftp.c
--- dlls/wininet/ftp.c 15 Jul 2003 20:51:02 -0000 1.29
+++ dlls/wininet/ftp.c 19 Jul 2003 15:50:54 -0000
@@ -72,6 +72,7 @@
FTP_CMD_STOR,
FTP_CMD_TYPE,
FTP_CMD_USER,
+ FTP_CMD_SIZE,
/* FTP commands without arguments. */
FTP_CMD_ABOR,
@@ -96,6 +97,7 @@
"STOR",
"TYPE",
"USER",
+ "SIZE",
"ABOR",
"LIST",
"NLST",
@@ -120,6 +122,7 @@
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 @@
if (nRecv >= 3)
{
- lpszResponse[nRecv] = '\0';
rc = atoi(lpszResponse);
if (lpfnStatusCB)
@@ -1896,7 +1898,7 @@
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 @@
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 @@
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 @@
*/
BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs)
{
+ TRACE("\n");
+
if (lpwfs->sndSocket != -1)
close(lpwfs->sndSocket);
@@ -2335,7 +2368,7 @@
/***********************************************************************
- * FTP_CloseSessionHandle (internal)
+ * FTP_CloseFindNextHandle (internal)
*
* Deallocate session handle
*
@@ -2362,6 +2395,28 @@
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)
Index: dlls/wininet/internet.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/internet.c,v
retrieving revision 1.61
diff -u -r1.61 internet.c
--- dlls/wininet/internet.c 9 Jul 2003 22:15:33 -0000 1.61
+++ dlls/wininet/internet.c 19 Jul 2003 15:50:55 -0000
@@ -701,6 +701,10 @@
retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
break;
+ case WH_HFILE:
+ retval = FTP_CloseFileTransferHandle((LPWININETFILE) lpwh);
+ break;
+
default:
break;
}
@@ -1331,12 +1335,6 @@
break;
}
- if (nSocket != -1)
- {
- int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0);
- retval = (res >= 0);
- *dwNumOfBytesRead = retval ? res : 0;
- }
return retval;
}
Index: dlls/wininet/internet.h
===================================================================
RCS file: /home/wine/wine/dlls/wininet/internet.h,v
retrieving revision 1.11
diff -u -r1.11 internet.h
--- dlls/wininet/internet.h 20 Jun 2003 23:26:56 -0000 1.11
+++ dlls/wininet/internet.h 19 Jul 2003 15:50:55 -0000
@@ -243,6 +243,7 @@
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);
More information about the wine-patches
mailing list