2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
9 * Copyright 2000 Andreas Mohr
18 #include <sys/types.h>
19 #ifdef HAVE_SYS_SOCKET_H
20 # include <sys/socket.h>
31 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(wininet
);
36 #define NOACCOUNT "noaccount"
37 #define DATA_PACKET_SIZE 0x2000
42 /* FTP commands with arguments. */
57 /* FTP commands without arguments. */
66 static const CHAR
*szFtpCommands
[] = {
88 static const CHAR szMonths
[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
90 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
91 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
92 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
93 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
);
94 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
);
95 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
96 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
97 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
98 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
);
99 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
);
100 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
);
101 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
);
102 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
);
103 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
);
104 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
);
105 BOOL
FTP_DoPassive(LPWININETFTPSESSIONA lpwfs
);
106 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONA lpwfs
);
107 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
);
108 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
);
109 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
110 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
);
111 DWORD
FTP_SetResponseError(DWORD dwResponse
);
113 inline static LPSTR
FTP_strdup( LPCSTR str
)
115 LPSTR ret
= HeapAlloc( GetProcessHeap(), 0, strlen(str
) + 1 );
116 if (ret
) strcpy( ret
, str
);
120 /***********************************************************************
121 * FtpPutFileA (WININET.@)
123 * Uploads a file to the FTP server
130 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
131 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
133 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
134 LPWININETAPPINFOA hIC
= NULL
;
136 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
138 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
142 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
143 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
145 WORKREQUEST workRequest
;
147 workRequest
.asyncall
= FTPPUTFILEA
;
148 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
149 workRequest
.LPSZLOCALFILE
= (DWORD
)FTP_strdup(lpszLocalFile
);
150 workRequest
.LPSZNEWREMOTEFILE
= (DWORD
)FTP_strdup(lpszNewRemoteFile
);
151 workRequest
.DWFLAGS
= dwFlags
;
152 workRequest
.DWCONTEXT
= dwContext
;
154 return INTERNET_AsyncCall(&workRequest
);
158 return FTP_FtpPutFileA(hConnect
, lpszLocalFile
,
159 lpszNewRemoteFile
, dwFlags
, dwContext
);
163 /***********************************************************************
164 * FTP_FtpPutFileA (Internal)
166 * Uploads a file to the FTP server
173 BOOL WINAPI
FTP_FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
174 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
176 HANDLE hFile
= (HANDLE
)NULL
;
177 BOOL bSuccess
= FALSE
;
178 LPWININETAPPINFOA hIC
= NULL
;
179 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
182 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile
, lpszNewRemoteFile
);
183 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
185 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
189 /* Clear any error information */
190 INTERNET_SetLastError(0);
192 /* Open file to be uploaded */
193 if (INVALID_HANDLE_VALUE
==
194 (hFile
= CreateFileA(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
196 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
200 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
201 if (hIC
->lpfnStatusCB
)
202 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
204 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
208 /* Get data socket to server */
209 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
211 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
213 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
214 MAX_REPLY_LEN
, 0, 0, 0);
220 FTP_SetResponseError(nResCode
);
226 if (lpwfs
->lstnSocket
!= -1)
227 close(lpwfs
->lstnSocket
);
229 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
231 INTERNET_ASYNC_RESULT iar
;
233 iar
.dwResult
= (DWORD
)bSuccess
;
234 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
235 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
236 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
246 /***********************************************************************
247 * FtpSetCurrentDirectoryA (WININET.@)
249 * Change the working directory on the FTP server
256 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
258 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
259 LPWININETAPPINFOA hIC
= NULL
;
261 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
263 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
267 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
269 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
270 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
272 WORKREQUEST workRequest
;
274 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYA
;
275 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
276 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
278 return INTERNET_AsyncCall(&workRequest
);
282 return FTP_FtpSetCurrentDirectoryA(hConnect
, lpszDirectory
);
287 /***********************************************************************
288 * FTP_FtpSetCurrentDirectoryA (Internal)
290 * Change the working directory on the FTP server
297 BOOL WINAPI
FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
300 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
301 LPWININETAPPINFOA hIC
= NULL
;
302 DWORD bSuccess
= FALSE
;
304 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
306 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
308 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
312 /* Clear any error information */
313 INTERNET_SetLastError(0);
315 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
316 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
317 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
320 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
321 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
328 FTP_SetResponseError(nResCode
);
332 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
334 INTERNET_ASYNC_RESULT iar
;
336 iar
.dwResult
= (DWORD
)bSuccess
;
337 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
338 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
339 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
345 /***********************************************************************
346 * FtpCreateDirectoryA (WININET.@)
348 * Create new directory on the FTP server
355 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
357 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
358 LPWININETAPPINFOA hIC
= NULL
;
360 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
362 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
366 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
367 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
369 WORKREQUEST workRequest
;
371 workRequest
.asyncall
= FTPCREATEDIRECTORYA
;
372 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
373 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
375 return INTERNET_AsyncCall(&workRequest
);
379 return FTP_FtpCreateDirectoryA(hConnect
, lpszDirectory
);
384 /***********************************************************************
385 * FTP_FtpCreateDirectoryA (Internal)
387 * Create new directory on the FTP server
394 BOOL WINAPI
FTP_FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
397 BOOL bSuccess
= FALSE
;
398 LPWININETAPPINFOA hIC
= NULL
;
399 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
402 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
404 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
408 /* Clear any error information */
409 INTERNET_SetLastError(0);
411 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
414 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
415 MAX_REPLY_LEN
, 0, 0, 0);
421 FTP_SetResponseError(nResCode
);
425 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
426 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
428 INTERNET_ASYNC_RESULT iar
;
430 iar
.dwResult
= (DWORD
)bSuccess
;
431 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
432 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
433 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
440 /***********************************************************************
441 * FtpFindFirstFileA (WININET.@)
443 * Search the specified directory
446 * HINTERNET on success
450 HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
451 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
453 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
454 LPWININETAPPINFOA hIC
= NULL
;
456 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
458 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
462 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
463 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
465 WORKREQUEST workRequest
;
467 workRequest
.asyncall
= FTPFINDFIRSTFILEA
;
468 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
469 workRequest
.LPSZSEARCHFILE
= (DWORD
)FTP_strdup(lpszSearchFile
);
470 workRequest
.LPFINDFILEDATA
= (DWORD
)lpFindFileData
;
471 workRequest
.DWFLAGS
= dwFlags
;
472 workRequest
.DWCONTEXT
= dwContext
;
474 INTERNET_AsyncCall(&workRequest
);
479 return FTP_FtpFindFirstFileA(hConnect
, lpszSearchFile
, lpFindFileData
,
485 /***********************************************************************
486 * FTP_FtpFindFirstFileA (Internal)
488 * Search the specified directory
491 * HINTERNET on success
495 HINTERNET WINAPI
FTP_FtpFindFirstFileA(HINTERNET hConnect
,
496 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
499 LPWININETAPPINFOA hIC
= NULL
;
500 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
501 LPWININETFINDNEXTA hFindNext
= NULL
;
505 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
507 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
511 /* Clear any error information */
512 INTERNET_SetLastError(0);
514 if (!FTP_InitListenSocket(lpwfs
))
517 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
520 if (!FTP_SendPortOrPasv(lpwfs
))
523 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
524 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, lpszSearchFile
,
525 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
528 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
529 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
532 if (nResCode
== 125 || nResCode
== 150)
536 /* Get data socket to server */
537 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
539 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpFindFileData
, dwContext
);
541 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
542 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
543 if (nResCode
!= 226 && nResCode
!= 250)
544 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
550 FTP_SetResponseError(nResCode
);
554 if (lpwfs
->lstnSocket
!= -1)
555 close(lpwfs
->lstnSocket
);
557 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
559 INTERNET_ASYNC_RESULT iar
;
563 iar
.dwResult
= (DWORD
)hFindNext
;
564 iar
.dwError
= ERROR_SUCCESS
;
565 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
566 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
569 iar
.dwResult
= (DWORD
)hFindNext
;
570 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
571 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
572 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
575 return (HINTERNET
)hFindNext
;
579 /***********************************************************************
580 * FtpGetCurrentDirectoryA (WININET.@)
582 * Retrieves the current directory
589 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
590 LPDWORD lpdwCurrentDirectory
)
592 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
593 LPWININETAPPINFOA hIC
= NULL
;
595 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
597 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
599 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
603 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
604 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
606 WORKREQUEST workRequest
;
608 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYA
;
609 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
610 workRequest
.LPSZDIRECTORY
= (DWORD
)lpszCurrentDirectory
;
611 workRequest
.LPDWDIRECTORY
= (DWORD
)lpdwCurrentDirectory
;
613 return INTERNET_AsyncCall(&workRequest
);
617 return FTP_FtpGetCurrentDirectoryA(hFtpSession
, lpszCurrentDirectory
,
618 lpdwCurrentDirectory
);
623 /***********************************************************************
624 * FTP_FtpGetCurrentDirectoryA (Internal)
626 * Retrieves the current directory
633 BOOL WINAPI
FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
634 LPDWORD lpdwCurrentDirectory
)
637 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
638 LPWININETAPPINFOA hIC
= NULL
;
639 DWORD bSuccess
= FALSE
;
641 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
643 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
645 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
649 /* Clear any error information */
650 INTERNET_SetLastError(0);
652 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
654 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
655 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
656 hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
))
659 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
660 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
);
663 if (nResCode
== 257) /* Extract directory name */
665 INT firstpos
, lastpos
, len
;
666 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
668 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
670 if ('"' == lpszResponseBuffer
[lastpos
])
679 len
= lastpos
- firstpos
- 1;
680 strncpy(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
681 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
682 *lpdwCurrentDirectory
= len
;
686 FTP_SetResponseError(nResCode
);
690 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
692 INTERNET_ASYNC_RESULT iar
;
694 iar
.dwResult
= (DWORD
)bSuccess
;
695 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
696 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
697 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
700 return (DWORD
) bSuccess
;
703 /***********************************************************************
704 * FtpOpenFileA (WININET.@)
706 * Open a remote file for writing or reading
709 * HINTERNET handle on success
713 HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
714 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
717 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
718 LPWININETAPPINFOA hIC
= NULL
;
720 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
722 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
726 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
727 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
729 WORKREQUEST workRequest
;
731 workRequest
.asyncall
= FTPOPENFILEA
;
732 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
733 workRequest
.LPSZFILENAME
= (DWORD
)FTP_strdup(lpszFileName
);
734 workRequest
.FDWACCESS
= fdwAccess
;
735 workRequest
.DWFLAGS
= dwFlags
;
736 workRequest
.DWCONTEXT
= dwContext
;
738 INTERNET_AsyncCall(&workRequest
);
743 return FTP_FtpOpenFileA(hFtpSession
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
748 /***********************************************************************
749 * FTP_FtpOpenFileA (Internal)
751 * Open a remote file for writing or reading
754 * HINTERNET handle on success
758 HINTERNET
FTP_FtpOpenFileA(HINTERNET hFtpSession
,
759 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
763 BOOL bSuccess
= FALSE
;
764 LPWININETFILE hFile
= NULL
;
765 LPWININETAPPINFOA hIC
= NULL
;
766 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
770 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
772 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
776 /* Clear any error information */
777 INTERNET_SetLastError(0);
779 if (GENERIC_READ
== fdwAccess
)
781 /* Set up socket to retrieve data */
782 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
784 else if (GENERIC_WRITE
== fdwAccess
)
786 /* Set up socket to send data */
787 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
790 /* Get data socket to server */
791 if (bSuccess
&& FTP_GetDataSocket(lpwfs
, &nDataSocket
))
793 hFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
794 hFile
->hdr
.htype
= WH_HFILE
;
795 hFile
->hdr
.dwFlags
= dwFlags
;
796 hFile
->hdr
.dwContext
= dwContext
;
797 hFile
->hdr
.lpwhparent
= hFtpSession
;
798 hFile
->nDataSocket
= nDataSocket
;
801 if (lpwfs
->lstnSocket
!= -1)
802 close(lpwfs
->lstnSocket
);
804 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
805 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
807 INTERNET_ASYNC_RESULT iar
;
811 iar
.dwResult
= (DWORD
)hFile
;
812 iar
.dwError
= ERROR_SUCCESS
;
813 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
814 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
817 iar
.dwResult
= (DWORD
)bSuccess
;
818 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
819 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
820 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
823 return (HINTERNET
)hFile
;
827 /***********************************************************************
828 * FtpGetFileA (WININET.@)
830 * Retrieve file from the FTP server
837 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
838 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
841 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
842 LPWININETAPPINFOA hIC
= NULL
;
844 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
846 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
850 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
851 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
853 WORKREQUEST workRequest
;
855 workRequest
.asyncall
= FTPGETFILEA
;
856 workRequest
.HFTPSESSION
= (DWORD
)hInternet
;
857 workRequest
.LPSZREMOTEFILE
= (DWORD
)FTP_strdup(lpszRemoteFile
);
858 workRequest
.LPSZNEWFILE
= (DWORD
)FTP_strdup(lpszNewFile
);
859 workRequest
.DWLOCALFLAGSATTRIBUTE
= dwLocalFlagsAttribute
;
860 workRequest
.FFAILIFEXISTS
= (DWORD
)fFailIfExists
;
861 workRequest
.DWFLAGS
= dwInternetFlags
;
862 workRequest
.DWCONTEXT
= dwContext
;
864 return INTERNET_AsyncCall(&workRequest
);
868 return FTP_FtpGetFileA(hInternet
, lpszRemoteFile
, lpszNewFile
,
869 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
874 /***********************************************************************
875 * FTP_FtpGetFileA (Internal)
877 * Retrieve file from the FTP server
884 BOOL WINAPI
FTP_FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
885 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
889 BOOL bSuccess
= FALSE
;
891 LPWININETAPPINFOA hIC
= NULL
;
892 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
894 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile
, lpszNewFile
);
895 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
897 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
901 /* Clear any error information */
902 INTERNET_SetLastError(0);
904 /* Ensure we can write to lpszNewfile by opening it */
905 hFile
= CreateFileA(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
906 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
907 if (INVALID_HANDLE_VALUE
== hFile
)
910 /* Set up socket to retrieve data */
911 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
917 /* Get data socket to server */
918 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
923 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
924 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
925 MAX_REPLY_LEN
, 0, 0, 0);
931 FTP_SetResponseError(nResCode
);
938 if (lpwfs
->lstnSocket
!= -1)
939 close(lpwfs
->lstnSocket
);
944 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
945 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
947 INTERNET_ASYNC_RESULT iar
;
949 iar
.dwResult
= (DWORD
)bSuccess
;
950 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
951 hIC
->lpfnStatusCB(hInternet
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
952 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
959 /***********************************************************************
960 * FtpDeleteFileA (WININET.@)
962 * Delete a file on the ftp server
969 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
971 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
972 LPWININETAPPINFOA hIC
= NULL
;
974 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
976 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
980 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
981 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
983 WORKREQUEST workRequest
;
985 workRequest
.asyncall
= FTPRENAMEFILEA
;
986 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
987 workRequest
.LPSZFILENAME
= (DWORD
)FTP_strdup(lpszFileName
);
989 return INTERNET_AsyncCall(&workRequest
);
993 return FTP_FtpDeleteFileA(hFtpSession
, lpszFileName
);
998 /***********************************************************************
999 * FTP_FtpDeleteFileA (Internal)
1001 * Delete a file on the ftp server
1008 BOOL
FTP_FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1011 BOOL bSuccess
= FALSE
;
1012 LPWININETAPPINFOA hIC
= NULL
;
1013 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1015 TRACE("0x%08lx\n", (ULONG
) hFtpSession
);
1016 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1018 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1022 /* Clear any error information */
1023 INTERNET_SetLastError(0);
1025 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1028 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1029 MAX_REPLY_LEN
, 0, 0, 0);
1032 if (nResCode
== 250)
1035 FTP_SetResponseError(nResCode
);
1038 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1039 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1041 INTERNET_ASYNC_RESULT iar
;
1043 iar
.dwResult
= (DWORD
)bSuccess
;
1044 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1045 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1046 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1053 /***********************************************************************
1054 * FtpRemoveDirectoryA (WININET.@)
1056 * Remove a directory on the ftp server
1063 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1065 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1066 LPWININETAPPINFOA hIC
= NULL
;
1068 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1070 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1074 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1075 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1077 WORKREQUEST workRequest
;
1079 workRequest
.asyncall
= FTPREMOVEDIRECTORYA
;
1080 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1081 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
1083 return INTERNET_AsyncCall(&workRequest
);
1087 return FTP_FtpRemoveDirectoryA(hFtpSession
, lpszDirectory
);
1092 /***********************************************************************
1093 * FTP_FtpRemoveDirectoryA (Internal)
1095 * Remove a directory on the ftp server
1102 BOOL
FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1105 BOOL bSuccess
= FALSE
;
1106 LPWININETAPPINFOA hIC
= NULL
;
1107 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1110 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1112 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1116 /* Clear any error information */
1117 INTERNET_SetLastError(0);
1119 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1122 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1123 MAX_REPLY_LEN
, 0, 0, 0);
1126 if (nResCode
== 250)
1129 FTP_SetResponseError(nResCode
);
1133 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1134 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1136 INTERNET_ASYNC_RESULT iar
;
1138 iar
.dwResult
= (DWORD
)bSuccess
;
1139 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1140 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1141 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1148 /***********************************************************************
1149 * FtpRenameFileA (WININET.@)
1151 * Rename a file on the ftp server
1158 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1160 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1161 LPWININETAPPINFOA hIC
= NULL
;
1163 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1165 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1169 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1170 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1172 WORKREQUEST workRequest
;
1174 workRequest
.asyncall
= FTPRENAMEFILEA
;
1175 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1176 workRequest
.LPSZSRCFILE
= (DWORD
)FTP_strdup(lpszSrc
);
1177 workRequest
.LPSZDESTFILE
= (DWORD
)FTP_strdup(lpszDest
);
1179 return INTERNET_AsyncCall(&workRequest
);
1183 return FTP_FtpRenameFileA(hFtpSession
, lpszSrc
, lpszDest
);
1187 /***********************************************************************
1188 * FTP_FtpRenameFileA (Internal)
1190 * Rename a file on the ftp server
1197 BOOL
FTP_FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1200 BOOL bSuccess
= FALSE
;
1201 LPWININETAPPINFOA hIC
= NULL
;
1202 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1205 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1207 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1211 /* Clear any error information */
1212 INTERNET_SetLastError(0);
1214 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1217 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1218 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1219 if (nResCode
== 350)
1221 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1224 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1225 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1228 if (nResCode
== 250)
1231 FTP_SetResponseError(nResCode
);
1234 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1235 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1237 INTERNET_ASYNC_RESULT iar
;
1239 iar
.dwResult
= (DWORD
)bSuccess
;
1240 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1241 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1242 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1249 /***********************************************************************
1250 * FTP_Connect (internal)
1252 * Connect to a ftp server
1255 * HINTERNET a session handle on success
1260 HINTERNET
FTP_Connect(HINTERNET hInternet
, LPCSTR lpszServerName
,
1261 INTERNET_PORT nServerPort
, LPCSTR lpszUserName
,
1262 LPCSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
)
1264 struct sockaddr_in socketAddr
;
1265 struct hostent
*phe
= NULL
;
1266 INT nsocket
= -1, sock_namelen
;
1267 LPWININETAPPINFOA hIC
= NULL
;
1268 BOOL bSuccess
= FALSE
;
1269 LPWININETFTPSESSIONA lpwfs
= NULL
;
1271 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1272 (ULONG
) hInternet
, lpszServerName
,
1273 nServerPort
, lpszUserName
, lpszPassword
);
1275 if (((LPWININETHANDLEHEADER
)hInternet
)->htype
!= WH_HINIT
)
1278 hIC
= (LPWININETAPPINFOA
) hInternet
;
1280 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1282 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME
);
1286 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1287 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1289 if (hIC
->lpfnStatusCB
)
1290 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1291 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1293 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1295 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1299 if (hIC
->lpfnStatusCB
)
1300 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1301 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1303 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
1306 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1310 if (hIC
->lpfnStatusCB
)
1311 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1312 &socketAddr
, sizeof(struct sockaddr_in
));
1314 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1316 ERR("Unable to connect (%s)\n", strerror(errno
));
1317 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1321 TRACE("Connected to server\n");
1322 if (hIC
->lpfnStatusCB
)
1323 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1324 &socketAddr
, sizeof(struct sockaddr_in
));
1326 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA
));
1329 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1333 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1334 lpwfs
->hdr
.dwFlags
= dwFlags
;
1335 lpwfs
->hdr
.dwContext
= dwContext
;
1336 lpwfs
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)hInternet
;
1337 lpwfs
->sndSocket
= nsocket
;
1338 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1339 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1340 lpwfs
->phostent
= phe
;
1342 if (NULL
== lpszUserName
)
1344 lpwfs
->lpszUserName
= FTP_strdup("anonymous");
1345 lpwfs
->lpszPassword
= FTP_strdup("user@server");
1349 lpwfs
->lpszUserName
= FTP_strdup(lpszUserName
);
1350 lpwfs
->lpszPassword
= FTP_strdup(lpszPassword
);
1353 if (FTP_ConnectToHost(lpwfs
))
1355 if (hIC
->lpfnStatusCB
)
1357 INTERNET_ASYNC_RESULT iar
;
1359 iar
.dwResult
= (DWORD
)lpwfs
;
1360 iar
.dwError
= ERROR_SUCCESS
;
1362 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1363 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1365 TRACE("Successfully logged into server\n");
1371 if (!bSuccess
&& nsocket
== -1)
1374 if (!bSuccess
&& lpwfs
)
1376 HeapFree(GetProcessHeap(), 0, lpwfs
);
1380 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1382 INTERNET_ASYNC_RESULT iar
;
1384 iar
.dwResult
= (DWORD
)lpwfs
;
1385 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1386 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1387 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1390 return (HINTERNET
) lpwfs
;
1394 /***********************************************************************
1395 * FTP_ConnectToHost (internal)
1397 * Connect to a ftp server
1404 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
)
1407 BOOL bSuccess
= FALSE
;
1410 FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1412 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1415 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1416 MAX_REPLY_LEN
, 0, 0, 0);
1419 /* Login successful... */
1420 if (nResCode
== 230)
1422 /* User name okay, need password... */
1423 else if (nResCode
== 331)
1424 bSuccess
= FTP_SendPassword(lpwfs
);
1425 /* Need account for login... */
1426 else if (nResCode
== 332)
1427 bSuccess
= FTP_SendAccount(lpwfs
);
1429 FTP_SetResponseError(nResCode
);
1432 TRACE("Returning %d\n", bSuccess
);
1438 /***********************************************************************
1439 * FTP_SendCommand (internal)
1441 * Send command to server
1448 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1449 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1453 DWORD nBytesSent
= 0;
1457 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1460 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1462 bParamHasLen
= lpszParam
&& strlen(lpszParam
) > 0;
1463 len
= (bParamHasLen
? strlen(lpszParam
) : -1) + strlen(szFtpCommands
[ftpCmd
]) +
1465 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1467 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1470 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], bParamHasLen
? " " : "",
1471 bParamHasLen
? lpszParam
: "", szCRLF
);
1473 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1474 while((nBytesSent
< len
) && (nRC
!= -1))
1476 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1480 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1483 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1484 &nBytesSent
, sizeof(DWORD
));
1486 TRACE("Sent %ld bytes\n", nBytesSent
);
1491 /***********************************************************************
1492 * FTP_ReceiveResponse (internal)
1494 * Receive response from server
1497 * Reply code on success
1502 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
1503 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1507 char firstprefix
[5];
1508 BOOL multiline
= FALSE
;
1511 TRACE("socket(%d) \n", nSocket
);
1514 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1519 if (!INTERNET_GetNextLine(nSocket
, lpszResponse
, &nRecv
))
1526 if(lpszResponse
[3] != '-')
1529 { /* Start of multiline repsonse. Loop until we get "nnn " */
1531 memcpy(firstprefix
, lpszResponse
, 3);
1532 firstprefix
[3] = ' ';
1533 firstprefix
[4] = '\0';
1538 if(!memcmp(firstprefix
, lpszResponse
, 4))
1546 lpszResponse
[nRecv
] = '\0';
1547 rc
= atoi(lpszResponse
);
1550 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1551 &nRecv
, sizeof(DWORD
));
1555 TRACE("return %d\n", rc
);
1560 /***********************************************************************
1561 * FTP_SendPassword (internal)
1563 * Send password to ftp server
1570 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
)
1573 BOOL bSuccess
= FALSE
;
1576 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1579 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1580 MAX_REPLY_LEN
, 0, 0, 0);
1583 TRACE("Received reply code %d\n", nResCode
);
1584 /* Login successful... */
1585 if (nResCode
== 230)
1587 /* Command not implemented, superfluous at the server site... */
1588 /* Need account for login... */
1589 else if (nResCode
== 332)
1590 bSuccess
= FTP_SendAccount(lpwfs
);
1592 FTP_SetResponseError(nResCode
);
1596 TRACE("Returning %d\n", bSuccess
);
1601 /***********************************************************************
1602 * FTP_SendAccount (internal)
1611 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
)
1614 BOOL bSuccess
= FALSE
;
1617 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, NOACCOUNT
, 0, 0, 0))
1620 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1621 MAX_REPLY_LEN
, 0, 0, 0);
1625 FTP_SetResponseError(nResCode
);
1632 /***********************************************************************
1633 * FTP_SendStore (internal)
1635 * Send request to upload file to ftp server
1642 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1645 BOOL bSuccess
= FALSE
;
1648 if (!FTP_InitListenSocket(lpwfs
))
1651 if (!FTP_SendType(lpwfs
, dwType
))
1654 if (!FTP_SendPortOrPasv(lpwfs
))
1657 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
1659 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1660 MAX_REPLY_LEN
, 0, 0, 0);
1663 if (nResCode
== 150)
1666 FTP_SetResponseError(nResCode
);
1670 if (!bSuccess
&& lpwfs
->lstnSocket
!= -1)
1672 close(lpwfs
->lstnSocket
);
1673 lpwfs
->lstnSocket
= -1;
1680 /***********************************************************************
1681 * FTP_InitListenSocket (internal)
1683 * Create a socket to listen for server response
1690 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
)
1692 BOOL bSuccess
= FALSE
;
1693 size_t namelen
= sizeof(struct sockaddr_in
);
1697 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
1698 if (lpwfs
->lstnSocket
== -1)
1700 TRACE("Unable to create listening socket\n");
1704 /* We obtain our ip addr from the name of the command channel socket */
1705 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
1707 /* and get the system to assign us a port */
1708 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
1710 if (bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)) == -1)
1712 TRACE("Unable to bind socket\n");
1716 if (listen(lpwfs
->lstnSocket
, MAX_BACKLOG
) == -1)
1718 TRACE("listen failed\n");
1722 if (getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
) != -1)
1726 if (!bSuccess
&& lpwfs
->lstnSocket
== -1)
1728 close(lpwfs
->lstnSocket
);
1729 lpwfs
->lstnSocket
= -1;
1736 /***********************************************************************
1737 * FTP_SendType (internal)
1739 * Tell server type of data being transferred
1745 * W98SE doesn't cache the type that's currently set
1746 * (i.e. it sends it always),
1747 * so we probably don't want to do that either.
1749 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
)
1752 CHAR type
[2] = { "I\0" };
1753 BOOL bSuccess
= FALSE
;
1756 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
1759 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
1762 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1763 MAX_REPLY_LEN
, 0, 0, 0)/100;
1769 FTP_SetResponseError(nResCode
);
1777 /***********************************************************************
1778 * FTP_SendPort (internal)
1780 * Tell server which port to use
1787 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
)
1790 CHAR szIPAddress
[64];
1791 BOOL bSuccess
= FALSE
;
1794 sprintf(szIPAddress
, "%d,%d,%d,%d,%d,%d",
1795 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
1796 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
1797 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
1798 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
1799 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
1800 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
1802 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
1805 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1806 MAX_REPLY_LEN
,0, 0, 0);
1809 if (nResCode
== 200)
1812 FTP_SetResponseError(nResCode
);
1820 /***********************************************************************
1821 * FTP_DoPassive (internal)
1823 * Tell server that we want to do passive transfers
1824 * and connect data socket
1831 BOOL
FTP_DoPassive(LPWININETFTPSESSIONA lpwfs
)
1834 BOOL bSuccess
= FALSE
;
1837 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASV
, NULL
, 0, 0, 0))
1840 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1841 MAX_REPLY_LEN
,0, 0, 0);
1844 if (nResCode
== 227)
1846 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
1850 char *pAddr
, *pPort
;
1852 struct sockaddr_in dataSocketAddress
;
1854 p
= lpszResponseBuffer
+4; /* skip status code */
1856 /* do a very strict check; we can improve that later. */
1858 if (strncmp(p
, "Entering Passive Mode", 21))
1860 ERR("unknown response '%.*s', aborting\n", 21, p
);
1863 p
+= 21; /* skip string */
1864 if ((*p
++ != ' ') || (*p
++ != '('))
1866 ERR("unknown response format, aborting\n");
1870 if (sscanf(p
, "%d,%d,%d,%d,%d,%d", &f
[0], &f
[1], &f
[2], &f
[3],
1873 ERR("unknown response address format '%s', aborting\n", p
);
1876 for (i
=0; i
< 6; i
++)
1879 dataSocketAddress
= lpwfs
->socketAddress
;
1880 pAddr
= (char *)&(dataSocketAddress
.sin_addr
.s_addr
);
1881 pPort
= (char *)&(dataSocketAddress
.sin_port
);
1889 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
1893 if (connect(nsocket
, (struct sockaddr
*)&dataSocketAddress
, sizeof(dataSocketAddress
)))
1895 ERR("can't connect passive FTP data port.\n");
1898 lpwfs
->pasvSocket
= nsocket
;
1902 FTP_SetResponseError(nResCode
);
1910 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONA lpwfs
)
1912 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
1914 if (!FTP_DoPassive(lpwfs
))
1919 if (!FTP_SendPort(lpwfs
))
1926 /***********************************************************************
1927 * FTP_GetDataSocket (internal)
1929 * Either accepts an incoming data socket connection from the server
1930 * or just returns the already opened socket after a PASV command
1931 * in case of passive FTP.
1939 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
)
1941 struct sockaddr_in saddr
;
1942 size_t addrlen
= sizeof(struct sockaddr
);
1945 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
1947 *nDataSocket
= lpwfs
->pasvSocket
;
1951 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
1952 close(lpwfs
->lstnSocket
);
1953 lpwfs
->lstnSocket
= -1;
1955 return *nDataSocket
!= -1;
1959 /***********************************************************************
1960 * FTP_SendData (internal)
1962 * Send data to the server
1969 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
)
1971 BY_HANDLE_FILE_INFORMATION fi
;
1972 DWORD nBytesRead
= 0;
1973 DWORD nBytesSent
= 0;
1974 DWORD nTotalSent
= 0;
1975 DWORD nBytesToSend
, nLen
, nRC
= 1;
1976 time_t s_long_time
, e_long_time
;
1981 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1982 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1984 /* Get the size of the file. */
1985 GetFileInformationByHandle(hFile
, &fi
);
1990 nBytesToSend
= nBytesRead
- nBytesSent
;
1992 if (nBytesToSend
<= 0)
1994 /* Read data from file. */
1996 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
1997 ERR("Failed reading from file\n");
2000 nBytesToSend
= nBytesRead
;
2005 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
2006 DATA_PACKET_SIZE
: nBytesToSend
;
2007 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
2015 /* Do some computation to display the status. */
2017 nSeconds
= e_long_time
- s_long_time
;
2018 if( nSeconds
/ 60 > 0 )
2020 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
2021 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
2022 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2026 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
2027 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
2028 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2030 } while (nRC
!= -1);
2032 TRACE("file transfer complete!\n");
2034 if(lpszBuffer
!= NULL
)
2035 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2041 /***********************************************************************
2042 * FTP_SendRetrieve (internal)
2044 * Send request to retrieve a file
2047 * Number of bytes to be received on success
2051 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
2057 if (!FTP_InitListenSocket(lpwfs
))
2060 if (!FTP_SendType(lpwfs
, dwType
))
2063 if (!FTP_SendPortOrPasv(lpwfs
))
2066 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
2069 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
2070 MAX_REPLY_LEN
, 0, 0, 0);
2073 if (nResCode
== 125 || nResCode
== 150)
2075 /* Parse size of data to be retrieved */
2076 INT i
, sizepos
= -1;
2077 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2078 for (i
= strlen(lpszResponseBuffer
) - 1; i
>= 0; i
--)
2080 if ('(' == lpszResponseBuffer
[i
])
2089 nResult
= atol(&lpszResponseBuffer
[sizepos
+1]);
2090 TRACE("Waiting to receive %ld bytes\n", nResult
);
2096 if (0 == nResult
&& lpwfs
->lstnSocket
!= -1)
2098 close(lpwfs
->lstnSocket
);
2099 lpwfs
->lstnSocket
= -1;
2106 /***********************************************************************
2107 * FTP_RetrieveData (internal)
2109 * Retrieve data from server
2116 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
2118 DWORD nBytesWritten
;
2119 DWORD nBytesReceived
= 0;
2125 if (INVALID_HANDLE_VALUE
== hFile
)
2128 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2129 if (NULL
== lpszBuffer
)
2131 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2135 while (nBytesReceived
< nBytes
&& nRC
!= -1)
2137 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2140 /* other side closed socket. */
2143 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2144 nBytesReceived
+= nRC
;
2147 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2148 nBytesReceived
* 100 / nBytes
);
2151 TRACE("Data transfer complete\n");
2152 if (NULL
!= lpszBuffer
)
2153 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2160 /***********************************************************************
2161 * FTP_CloseSessionHandle (internal)
2163 * Deallocate session handle
2170 BOOL
FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs
)
2172 if (lpwfs
->sndSocket
!= -1)
2173 close(lpwfs
->sndSocket
);
2175 if (lpwfs
->lstnSocket
!= -1)
2176 close(lpwfs
->lstnSocket
);
2178 if (lpwfs
->lpszPassword
)
2179 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2181 if (lpwfs
->lpszUserName
)
2182 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2184 HeapFree(GetProcessHeap(), 0, lpwfs
);
2190 /***********************************************************************
2191 * FTP_CloseSessionHandle (internal)
2193 * Deallocate session handle
2200 BOOL
FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn
)
2206 for (i
= 0; i
< lpwfn
->size
; i
++)
2208 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2209 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2212 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2213 HeapFree(GetProcessHeap(), 0, lpwfn
);
2219 /***********************************************************************
2220 * FTP_ReceiveFileList (internal)
2222 * Read file list from server
2225 * Handle to file list on success
2229 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
2230 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
)
2233 LPFILEPROPERTIESA lpafp
= NULL
;
2234 LPWININETFINDNEXTA lpwfn
= NULL
;
2238 if (FTP_ParseDirectory(lpwfs
, nSocket
, &lpafp
, &dwSize
))
2240 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2242 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTA
));
2245 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2246 lpwfn
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)lpwfs
;
2247 lpwfn
->hdr
.dwContext
= dwContext
;
2248 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2249 lpwfn
->size
= dwSize
;
2250 lpwfn
->lpafp
= lpafp
;
2254 TRACE("Matched %ld files\n", dwSize
);
2255 return (HINTERNET
)lpwfn
;
2259 /***********************************************************************
2260 * FTP_ConvertFileProp (internal)
2262 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2269 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp
, LPWIN32_FIND_DATAA lpFindFileData
)
2271 BOOL bSuccess
= FALSE
;
2273 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
2277 DWORD access
= mktime(&lpafp
->tmLastModified
);
2279 /* Not all fields are filled in */
2280 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= HIWORD(access
);
2281 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= LOWORD(access
);
2282 lpFindFileData
->nFileSizeHigh
= HIWORD(lpafp
->nSize
);
2283 lpFindFileData
->nFileSizeLow
= LOWORD(lpafp
->nSize
);
2285 if (lpafp
->bIsDirectory
)
2286 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2288 if (lpafp
->lpszName
)
2289 strncpy(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2298 /***********************************************************************
2299 * FTP_ParseDirectory (internal)
2301 * Parse string of directory information
2307 * FIXME: - This function needs serious clea-up
2308 * - We should consider both UNIX and NT list formats
2310 #define MAX_MONTH_LEN 10
2311 #define MIN_LEN_DIR_ENTRY 15
2313 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
)
2316 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2319 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2325 CHAR pszMonth
[MAX_MONTH_LEN
];
2327 BOOL bSuccess
= TRUE
;
2328 DWORD nBufLen
= MAX_REPLY_LEN
;
2329 LPFILEPROPERTIESA curFileProp
= NULL
;
2330 CHAR
* pszLine
= NULL
;
2331 CHAR
* pszToken
= NULL
;
2332 INT nTokenToSkip
= 3;
2340 INT sizeFilePropArray
= 20;
2341 INT indexFilePropArray
= 0;
2345 /* Allocate intial file properties array */
2346 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESA
)*(sizeFilePropArray
));
2353 while ((pszLine
= INTERNET_GetNextLine(nSocket
, INTERNET_GetResponseBuffer(), &nBufLen
)) != NULL
)
2355 if (sizeFilePropArray
<= indexFilePropArray
)
2357 LPFILEPROPERTIESA tmpafp
;
2359 sizeFilePropArray
*= 2;
2360 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2361 sizeof(FILEPROPERTIESA
)*sizeFilePropArray
);
2371 curFileProp
= &((*lpafp
)[indexFilePropArray
]);
2373 /* First Parse the permissions. */
2374 pszToken
= strtok(pszLine
, " \t" );
2376 /* HACK! If this is not a file listing skip the line */
2377 if (!pszToken
|| 10 != strlen(pszToken
) || nBufLen
<= MIN_LEN_DIR_ENTRY
)
2379 nBufLen
= MAX_REPLY_LEN
;
2383 FTP_ParsePermission(pszToken
, curFileProp
);
2389 pszToken
= strtok( NULL
, " \t" );
2391 } while( nCount
<= nTokenToSkip
);
2393 /* Store the size of the file in the param list. */
2394 TRACE("nSize-> %s\n", pszToken
);
2395 if (pszToken
!= NULL
)
2396 curFileProp
->nSize
= atol(pszToken
);
2398 /* Parse last modified time. */
2406 pszToken
= strtok( NULL
, " \t" );
2407 strncpy(pszMonth
, pszToken
, MAX_MONTH_LEN
);
2408 CharUpperA(pszMonth
);
2409 pszMatch
= strstr(szMonths
, pszMonth
);
2410 if( pszMatch
!= NULL
)
2411 nMonth
= (pszMatch
- szMonths
) / 3;
2413 pszToken
= strtok(NULL
, " \t");
2414 TRACE("nDay -> %s\n", pszToken
);
2415 if (pszToken
!= NULL
)
2416 nDay
= atoi(pszToken
);
2418 pszToken
= strtok(NULL
, " \t");
2419 pszMinutes
= strchr(pszToken
, ':');
2420 if( pszMinutes
!= NULL
)
2423 nMinutes
= atoi(pszMinutes
);
2424 pszHour
= pszMinutes
- 3;
2425 if (pszHour
!= NULL
)
2426 nHour
= atoi(pszHour
);
2428 apTM
= localtime( &aTime
);
2429 nYear
= apTM
->tm_year
;
2433 nYear
= atoi(pszToken
);
2438 curFileProp
->tmLastModified
.tm_sec
= nSeconds
;
2439 curFileProp
->tmLastModified
.tm_min
= nMinutes
;
2440 curFileProp
->tmLastModified
.tm_hour
= nHour
;
2441 curFileProp
->tmLastModified
.tm_mday
= nDay
;
2442 curFileProp
->tmLastModified
.tm_mon
= nMonth
;
2443 curFileProp
->tmLastModified
.tm_year
= nYear
;
2445 pszToken
= strtok(NULL
, " \t");
2446 if(pszToken
!= NULL
)
2448 curFileProp
->lpszName
= FTP_strdup(pszToken
);
2449 TRACE(": %s\n", curFileProp
->lpszName
);
2452 nBufLen
= MAX_REPLY_LEN
;
2453 indexFilePropArray
++;
2456 if (bSuccess
&& indexFilePropArray
)
2458 if (indexFilePropArray
< sizeFilePropArray
- 1)
2460 LPFILEPROPERTIESA tmpafp
;
2462 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2463 sizeof(FILEPROPERTIESA
)*indexFilePropArray
);
2467 *dwfp
= indexFilePropArray
;
2471 HeapFree(GetProcessHeap(), 0, *lpafp
);
2472 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2481 /***********************************************************************
2482 * FTP_ParsePermission (internal)
2484 * Parse permission string of directory information
2491 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
)
2493 BOOL bSuccess
= TRUE
;
2494 unsigned short nPermission
= 0;
2499 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
2505 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
2511 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
2514 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
2517 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
2520 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
2523 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
2526 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
2529 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
2532 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
2535 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
2539 }while (nPos
<= nLast
);
2541 lpfp
->permissions
= nPermission
;
2546 /***********************************************************************
2547 * FTP_SetResponseError (internal)
2549 * Set the appropriate error code for a given response from the server
2554 DWORD
FTP_SetResponseError(DWORD dwResponse
)
2560 case 421: /* Service not available - Server may be shutting down. */
2561 dwCode
= ERROR_INTERNET_TIMEOUT
;
2564 case 425: /* Cannot open data connection. */
2565 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
2568 case 426: /* Connection closed, transer aborted. */
2569 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
2572 case 500: /* Syntax error. Command unrecognized. */
2573 case 501: /* Syntax error. Error in parameters or arguments. */
2574 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
2577 case 530: /* Not logged in. Login incorrect. */
2578 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
2581 case 550: /* File action not taken. File not found or no access. */
2582 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
2585 case 450: /* File action not taken. File may be busy. */
2586 case 451: /* Action aborted. Server error. */
2587 case 452: /* Action not taken. Insufficient storage space on server. */
2588 case 502: /* Command not implemented. */
2589 case 503: /* Bad sequence of command. */
2590 case 504: /* Command not implemented for that parameter. */
2591 case 532: /* Need account for storing files */
2592 case 551: /* Requested action aborted. Page type unknown */
2593 case 552: /* Action aborted. Exceeded storage allocation */
2594 case 553: /* Action not taken. File name not allowed. */
2597 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
2601 INTERNET_SetLastError(dwCode
);