2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
17 #include <sys/types.h>
18 #ifdef HAVE_SYS_SOCKET_H
19 # include <sys/socket.h>
23 #include <netinet/ip.h>
33 #include "debugtools.h"
36 DEFAULT_DEBUG_CHANNEL(wininet
);
38 #define NOACCOUNT "noaccount"
39 #define DATA_PACKET_SIZE 0x2000
44 /* FTP commands with arguments. */
59 /* FTP commands without arguments. */
67 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_InitDataSocket(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_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
);
106 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
);
107 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
108 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
);
109 DWORD
FTP_SetResponseError(DWORD dwResponse
);
111 /***********************************************************************
112 * FtpPutFileA (WININET.43)
114 * Uploads a file to the FTP server
121 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
122 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
124 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
125 LPWININETAPPINFOA hIC
= NULL
;
127 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
129 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
133 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
134 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
136 WORKREQUEST workRequest
;
138 workRequest
.asyncall
= FTPPUTFILEA
;
139 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
140 workRequest
.LPSZLOCALFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszLocalFile
);
141 workRequest
.LPSZNEWREMOTEFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszNewRemoteFile
);
142 workRequest
.DWFLAGS
= dwFlags
;
143 workRequest
.DWCONTEXT
= dwContext
;
145 return INTERNET_AsyncCall(&workRequest
);
149 return FTP_FtpPutFileA(hConnect
, lpszLocalFile
,
150 lpszNewRemoteFile
, dwFlags
, dwContext
);
154 /***********************************************************************
155 * FTP_FtpPutFileA (Internal)
157 * Uploads a file to the FTP server
164 BOOL WINAPI
FTP_FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
165 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
167 HANDLE hFile
= (HANDLE
)NULL
;
168 BOOL bSuccess
= FALSE
;
169 LPWININETAPPINFOA hIC
= NULL
;
170 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
173 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile
, lpszNewRemoteFile
);
174 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
176 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
180 /* Clear any error information */
181 INTERNET_SetLastError(0);
183 /* Open file to be uploaded */
184 if (INVALID_HANDLE_VALUE
==
185 (hFile
= CreateFileA(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
187 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
191 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
192 if (hIC
->lpfnStatusCB
)
193 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
195 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
199 /* Accept connection from ftp server */
200 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
202 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
204 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
205 MAX_REPLY_LEN
,0, 0, 0);
211 FTP_SetResponseError(nResCode
);
217 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
219 INTERNET_ASYNC_RESULT iar
;
221 iar
.dwResult
= (DWORD
)bSuccess
;
222 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
223 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
224 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
234 /***********************************************************************
235 * FtpSetCurrentDirectoryA (WININET.49)
237 * Change the working directory on the FTP server
244 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
246 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
247 LPWININETAPPINFOA hIC
= NULL
;
249 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
251 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
255 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
257 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
258 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
260 WORKREQUEST workRequest
;
262 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYA
;
263 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
264 workRequest
.LPSZDIRECTORY
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszDirectory
);
266 return INTERNET_AsyncCall(&workRequest
);
270 return FTP_FtpSetCurrentDirectoryA(hConnect
, lpszDirectory
);
275 /***********************************************************************
276 * FTP_FtpSetCurrentDirectoryA (Internal)
278 * Change the working directory on the FTP server
285 BOOL WINAPI
FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
288 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
289 LPWININETAPPINFOA hIC
= NULL
;
290 DWORD bSuccess
= FALSE
;
292 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
294 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
296 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
300 /* Clear any error information */
301 INTERNET_SetLastError(0);
303 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
304 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
305 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
308 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
309 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
316 FTP_SetResponseError(nResCode
);
320 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
322 INTERNET_ASYNC_RESULT iar
;
324 iar
.dwResult
= (DWORD
)bSuccess
;
325 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
326 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
327 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
333 /***********************************************************************
334 * FtpCreateDirectoryA (WININET.31)
336 * Create new directory on the FTP server
343 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
345 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
346 LPWININETAPPINFOA hIC
= NULL
;
348 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
350 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
354 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
355 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
357 WORKREQUEST workRequest
;
359 workRequest
.asyncall
= FTPCREATEDIRECTORYA
;
360 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
361 workRequest
.LPSZDIRECTORY
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszDirectory
);
363 return INTERNET_AsyncCall(&workRequest
);
367 return FTP_FtpCreateDirectoryA(hConnect
, lpszDirectory
);
372 /***********************************************************************
373 * FTP_FtpCreateDirectoryA (Internal)
375 * Create new directory on the FTP server
382 BOOL WINAPI
FTP_FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
385 BOOL bSuccess
= FALSE
;
386 LPWININETAPPINFOA hIC
= NULL
;
387 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
390 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
392 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
396 /* Clear any error information */
397 INTERNET_SetLastError(0);
399 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
402 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
403 MAX_REPLY_LEN
, 0, 0, 0);
409 FTP_SetResponseError(nResCode
);
413 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
414 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
416 INTERNET_ASYNC_RESULT iar
;
418 iar
.dwResult
= (DWORD
)bSuccess
;
419 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
420 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
421 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
428 /***********************************************************************
429 * FtpFindFirstFileA (WININET.35)
431 * Search the specified directory
434 * HINTERNET on success
438 INTERNETAPI HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
439 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
441 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
442 LPWININETAPPINFOA hIC
= NULL
;
444 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
446 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
450 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
451 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
453 WORKREQUEST workRequest
;
455 workRequest
.asyncall
= FTPFINDFIRSTFILEA
;
456 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
457 workRequest
.LPSZSEARCHFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszSearchFile
);
458 workRequest
.LPFINDFILEDATA
= (DWORD
)lpFindFileData
;
459 workRequest
.DWFLAGS
= dwFlags
;
460 workRequest
.DWCONTEXT
= dwContext
;
462 INTERNET_AsyncCall(&workRequest
);
467 return FTP_FtpFindFirstFileA(hConnect
, lpszSearchFile
, lpFindFileData
,
473 /***********************************************************************
474 * FTP_FtpFindFirstFileA (Internal)
476 * Search the specified directory
479 * HINTERNET on success
483 INTERNETAPI HINTERNET WINAPI
FTP_FtpFindFirstFileA(HINTERNET hConnect
,
484 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
487 LPWININETAPPINFOA hIC
= NULL
;
488 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
489 LPWININETFINDNEXTA hFindNext
= NULL
;
493 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
495 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
499 /* Clear any error information */
500 INTERNET_SetLastError(0);
502 if (!FTP_InitListenSocket(lpwfs
))
505 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
508 if (!FTP_SendPort(lpwfs
))
511 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
512 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, lpszSearchFile
,
513 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
516 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
517 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
520 if (nResCode
== 125 || nResCode
== 150)
524 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
526 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpFindFileData
, dwContext
);
528 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
529 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
530 if (nResCode
!= 226 && nResCode
!= 250)
531 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
537 FTP_SetResponseError(nResCode
);
541 if (lpwfs
->lstnSocket
!= INVALID_SOCKET
)
542 close(lpwfs
->lstnSocket
);
544 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
546 INTERNET_ASYNC_RESULT iar
;
550 iar
.dwResult
= (DWORD
)hFindNext
;
551 iar
.dwError
= ERROR_SUCCESS
;
552 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
553 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
556 iar
.dwResult
= (DWORD
)hFindNext
;
557 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
558 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
559 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
562 return (HINTERNET
)hFindNext
;
566 /***********************************************************************
567 * FtpGetCurrentDirectoryA (WININET.37)
569 * Retrieves the current directory
576 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
577 LPDWORD lpdwCurrentDirectory
)
579 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
580 LPWININETAPPINFOA hIC
= NULL
;
582 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
584 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
586 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
590 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
591 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
593 WORKREQUEST workRequest
;
595 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYA
;
596 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
597 workRequest
.LPSZDIRECTORY
= (DWORD
)lpszCurrentDirectory
;
598 workRequest
.LPDWDIRECTORY
= (DWORD
)lpdwCurrentDirectory
;
600 return INTERNET_AsyncCall(&workRequest
);
604 return FTP_FtpGetCurrentDirectoryA(hFtpSession
, lpszCurrentDirectory
,
605 lpdwCurrentDirectory
);
610 /***********************************************************************
611 * FTP_FtpGetCurrentDirectoryA (Internal)
613 * Retrieves the current directory
620 BOOL WINAPI
FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
621 LPDWORD lpdwCurrentDirectory
)
624 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
625 LPWININETAPPINFOA hIC
= NULL
;
626 DWORD bSuccess
= FALSE
;
628 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
630 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
632 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
636 /* Clear any error information */
637 INTERNET_SetLastError(0);
639 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
641 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
642 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
643 hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
))
646 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
647 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
);
650 if (nResCode
== 257) /* Extract directory name */
652 INT firstpos
, lastpos
, len
;
653 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
655 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
657 if ('"' == lpszResponseBuffer
[lastpos
])
666 len
= lastpos
- firstpos
- 1;
667 strncpy(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
668 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
669 *lpdwCurrentDirectory
= len
;
673 FTP_SetResponseError(nResCode
);
677 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
679 INTERNET_ASYNC_RESULT iar
;
681 iar
.dwResult
= (DWORD
)bSuccess
;
682 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
683 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
684 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
687 return (DWORD
) bSuccess
;
690 /***********************************************************************
691 * FtpOpenFileA (WININET.41)
693 * Open a remote file for writing or reading
696 * HINTERNET handle on success
700 INTERNETAPI HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
701 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
704 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
705 LPWININETAPPINFOA hIC
= NULL
;
707 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
709 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
713 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
714 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
716 WORKREQUEST workRequest
;
718 workRequest
.asyncall
= FTPOPENFILEA
;
719 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
720 workRequest
.LPSZFILENAME
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszFileName
);
721 workRequest
.FDWACCESS
= fdwAccess
;
722 workRequest
.DWFLAGS
= dwFlags
;
723 workRequest
.DWCONTEXT
= dwContext
;
725 INTERNET_AsyncCall(&workRequest
);
730 return FTP_FtpOpenFileA(hFtpSession
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
735 /***********************************************************************
736 * FTP_FtpOpenFileA (Internal)
738 * Open a remote file for writing or reading
741 * HINTERNET handle on success
745 HINTERNET
FTP_FtpOpenFileA(HINTERNET hFtpSession
,
746 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
750 BOOL bSuccess
= FALSE
;
751 LPWININETFILE hFile
= NULL
;
752 LPWININETAPPINFOA hIC
= NULL
;
753 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
757 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
759 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
763 /* Clear any error information */
764 INTERNET_SetLastError(0);
766 if (GENERIC_READ
== fdwAccess
)
768 /* Set up socket to retrieve data */
769 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
771 else if (GENERIC_WRITE
== fdwAccess
)
773 /* Set up socket to send data */
774 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
777 /* Accept connection from server */
778 if (bSuccess
&& FTP_InitDataSocket(lpwfs
, &nDataSocket
))
780 hFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
781 hFile
->hdr
.htype
= WH_HFILE
;
782 hFile
->hdr
.dwFlags
= dwFlags
;
783 hFile
->hdr
.dwContext
= dwContext
;
784 hFile
->hdr
.lpwhparent
= hFtpSession
;
785 hFile
->nDataSocket
= nDataSocket
;
788 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
789 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
791 INTERNET_ASYNC_RESULT iar
;
795 iar
.dwResult
= (DWORD
)hFile
;
796 iar
.dwError
= ERROR_SUCCESS
;
797 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
798 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
801 iar
.dwResult
= (DWORD
)bSuccess
;
802 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
803 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
804 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
807 return (HINTERNET
)hFile
;
811 /***********************************************************************
812 * FtpGetFileA (WININET.39)
814 * Retrieve file from the FTP server
821 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
822 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
825 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
826 LPWININETAPPINFOA hIC
= NULL
;
828 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
830 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
834 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
835 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
837 WORKREQUEST workRequest
;
839 workRequest
.asyncall
= FTPGETFILEA
;
840 workRequest
.HFTPSESSION
= (DWORD
)hInternet
;
841 workRequest
.LPSZREMOTEFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszRemoteFile
);
842 workRequest
.LPSZNEWFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszNewFile
);
843 workRequest
.DWLOCALFLAGSATTRIBUTE
= dwLocalFlagsAttribute
;
844 workRequest
.FFAILIFEXISTS
= (DWORD
)fFailIfExists
;
845 workRequest
.DWFLAGS
= dwInternetFlags
;
846 workRequest
.DWCONTEXT
= dwContext
;
848 return INTERNET_AsyncCall(&workRequest
);
852 return FTP_FtpGetFileA(hInternet
, lpszRemoteFile
, lpszNewFile
,
853 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
858 /***********************************************************************
859 * FTP_FtpGetFileA (Internal)
861 * Retrieve file from the FTP server
868 BOOL WINAPI
FTP_FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
869 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
873 BOOL bSuccess
= FALSE
;
875 LPWININETAPPINFOA hIC
= NULL
;
876 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
878 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile
, lpszNewFile
);
879 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
881 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
885 /* Clear any error information */
886 INTERNET_SetLastError(0);
888 /* Ensure we can write to lpszNewfile by opening it */
889 hFile
= CreateFileA(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
890 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
891 if (INVALID_HANDLE_VALUE
== hFile
)
894 /* Set up socket to retrieve data */
895 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
901 /* Accept connection from ftp server */
902 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
907 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
908 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
909 MAX_REPLY_LEN
, 0, 0, 0);
915 FTP_SetResponseError(nResCode
);
925 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
926 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
928 INTERNET_ASYNC_RESULT iar
;
930 iar
.dwResult
= (DWORD
)bSuccess
;
931 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
932 hIC
->lpfnStatusCB(hInternet
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
933 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
940 /***********************************************************************
941 * FtpDeleteFileA (WININET.33)
943 * Delete a file on the ftp server
950 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
952 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
953 LPWININETAPPINFOA hIC
= NULL
;
955 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
957 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
961 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
962 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
964 WORKREQUEST workRequest
;
966 workRequest
.asyncall
= FTPRENAMEFILEA
;
967 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
968 workRequest
.LPSZFILENAME
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszFileName
);
970 return INTERNET_AsyncCall(&workRequest
);
974 return FTP_FtpDeleteFileA(hFtpSession
, lpszFileName
);
979 /***********************************************************************
980 * FTP_FtpDeleteFileA (Internal)
982 * Delete a file on the ftp server
989 BOOL
FTP_FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
992 BOOL bSuccess
= FALSE
;
993 LPWININETAPPINFOA hIC
= NULL
;
994 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
996 TRACE("0x%08lx\n", (ULONG
) hFtpSession
);
997 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
999 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1003 /* Clear any error information */
1004 INTERNET_SetLastError(0);
1006 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1009 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1010 MAX_REPLY_LEN
, 0, 0, 0);
1013 if (nResCode
== 250)
1016 FTP_SetResponseError(nResCode
);
1019 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1020 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1022 INTERNET_ASYNC_RESULT iar
;
1024 iar
.dwResult
= (DWORD
)bSuccess
;
1025 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1026 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1027 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1034 /***********************************************************************
1035 * FtpRemoveDirectoryA (WININET.45)
1037 * Remove a directory on the ftp server
1044 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1046 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1047 LPWININETAPPINFOA hIC
= NULL
;
1049 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1051 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1055 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1056 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1058 WORKREQUEST workRequest
;
1060 workRequest
.asyncall
= FTPREMOVEDIRECTORYA
;
1061 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1062 workRequest
.LPSZDIRECTORY
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszDirectory
);
1064 return INTERNET_AsyncCall(&workRequest
);
1068 return FTP_FtpRemoveDirectoryA(hFtpSession
, lpszDirectory
);
1073 /***********************************************************************
1074 * FTP_FtpRemoveDirectoryA (Internal)
1076 * Remove a directory on the ftp server
1083 BOOL
FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1086 BOOL bSuccess
= FALSE
;
1087 LPWININETAPPINFOA hIC
= NULL
;
1088 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1091 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1093 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1097 /* Clear any error information */
1098 INTERNET_SetLastError(0);
1100 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1103 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1104 MAX_REPLY_LEN
, 0, 0, 0);
1107 if (nResCode
== 250)
1110 FTP_SetResponseError(nResCode
);
1114 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1115 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1117 INTERNET_ASYNC_RESULT iar
;
1119 iar
.dwResult
= (DWORD
)bSuccess
;
1120 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1121 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1122 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1129 /***********************************************************************
1130 * FtpRenameFileA (WININET.47)
1132 * Rename a file on the ftp server
1139 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1141 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1142 LPWININETAPPINFOA hIC
= NULL
;
1144 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1146 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1150 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1151 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1153 WORKREQUEST workRequest
;
1155 workRequest
.asyncall
= FTPRENAMEFILEA
;
1156 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1157 workRequest
.LPSZSRCFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszSrc
);
1158 workRequest
.LPSZDESTFILE
= (DWORD
)HEAP_strdupA(GetProcessHeap(),0,lpszDest
);
1160 return INTERNET_AsyncCall(&workRequest
);
1164 return FTP_FtpRenameFileA(hFtpSession
, lpszSrc
, lpszDest
);
1168 /***********************************************************************
1169 * FTP_FtpRenameFileA (Internal)
1171 * Rename a file on the ftp server
1178 BOOL
FTP_FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1181 BOOL bSuccess
= FALSE
;
1182 LPWININETAPPINFOA hIC
= NULL
;
1183 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1186 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1188 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1192 /* Clear any error information */
1193 INTERNET_SetLastError(0);
1195 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1198 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1199 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1200 if (nResCode
== 350)
1202 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1205 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1206 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1209 if (nResCode
== 250)
1212 FTP_SetResponseError(nResCode
);
1215 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1216 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1218 INTERNET_ASYNC_RESULT iar
;
1220 iar
.dwResult
= (DWORD
)bSuccess
;
1221 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1222 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1223 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1230 /***********************************************************************
1231 * FTP_Connect (internal)
1233 * Connect to a ftp server
1236 * HINTERNET a session handle on success
1241 HINTERNET
FTP_Connect(HINTERNET hInternet
, LPCSTR lpszServerName
,
1242 INTERNET_PORT nServerPort
, LPCSTR lpszUserName
,
1243 LPCSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
)
1245 struct sockaddr_in socketAddr
;
1246 struct hostent
*phe
= NULL
;
1247 INT nsocket
= INVALID_SOCKET
, sock_namelen
;
1248 LPWININETAPPINFOA hIC
= NULL
;
1249 BOOL bSuccess
= FALSE
;
1250 LPWININETFTPSESSIONA lpwfs
= NULL
;
1252 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1253 (ULONG
) hInternet
, lpszServerName
,
1254 nServerPort
, lpszUserName
, lpszPassword
);
1256 if (((LPWININETHANDLEHEADER
)hInternet
)->htype
!= WH_HINIT
)
1259 hIC
= (LPWININETAPPINFOA
) hInternet
;
1261 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1263 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME
);
1267 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1268 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1270 if (hIC
->lpfnStatusCB
)
1271 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1272 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1274 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1276 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1280 if (hIC
->lpfnStatusCB
)
1281 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1282 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1284 if (INVALID_SOCKET
== (nsocket
= socket(AF_INET
,SOCK_STREAM
,0)))
1286 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1290 if (hIC
->lpfnStatusCB
)
1291 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1292 &socketAddr
, sizeof(struct sockaddr_in
));
1294 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1296 ERR("Unable to connect (%s)\n", strerror(errno
));
1297 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1301 TRACE("Connected to server\n");
1302 if (hIC
->lpfnStatusCB
)
1303 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1304 &socketAddr
, sizeof(struct sockaddr_in
));
1306 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA
));
1309 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1313 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1314 lpwfs
->hdr
.dwFlags
= dwFlags
;
1315 lpwfs
->hdr
.dwContext
= dwContext
;
1316 lpwfs
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)hInternet
;
1317 lpwfs
->sndSocket
= nsocket
;
1318 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1319 getsockname(nsocket
, &lpwfs
->socketAddress
, &sock_namelen
);
1320 lpwfs
->phostent
= phe
;
1322 if (NULL
== lpszUserName
)
1324 lpwfs
->lpszUserName
= HEAP_strdupA(GetProcessHeap(),0,"anonymous");
1325 lpwfs
->lpszPassword
= HEAP_strdupA(GetProcessHeap(),0,"user@server");
1329 lpwfs
->lpszUserName
= HEAP_strdupA(GetProcessHeap(),0,lpszUserName
);
1330 lpwfs
->lpszPassword
= HEAP_strdupA(GetProcessHeap(),0,lpszPassword
);
1333 if (FTP_ConnectToHost(lpwfs
))
1335 if (hIC
->lpfnStatusCB
)
1337 INTERNET_ASYNC_RESULT iar
;
1339 iar
.dwResult
= (DWORD
)lpwfs
;
1340 iar
.dwError
= ERROR_SUCCESS
;
1342 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1343 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1345 TRACE("Successfully logged into server\n");
1351 if (!bSuccess
&& INVALID_SOCKET
!= nsocket
)
1354 if (!bSuccess
&& lpwfs
)
1356 HeapFree(GetProcessHeap(), 0, lpwfs
);
1360 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1362 INTERNET_ASYNC_RESULT iar
;
1364 iar
.dwResult
= (DWORD
)lpwfs
;
1365 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1366 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1367 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1370 return (HINTERNET
) lpwfs
;
1374 /***********************************************************************
1375 * FTP_ConnectHost (internal)
1377 * Connect to a ftp server
1384 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
)
1387 BOOL bSuccess
= FALSE
;
1390 FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1392 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1395 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1396 MAX_REPLY_LEN
, 0, 0, 0);
1399 /* Login successful... */
1400 if (nResCode
== 230)
1402 /* User name okay, need password... */
1403 else if (nResCode
== 331)
1404 bSuccess
= FTP_SendPassword(lpwfs
);
1405 /* Need account for login... */
1406 else if (nResCode
== 332)
1407 bSuccess
= FTP_SendAccount(lpwfs
);
1409 FTP_SetResponseError(nResCode
);
1412 TRACE("Returning %d\n", bSuccess
);
1418 /***********************************************************************
1419 * FTP_SendCommand (internal)
1421 * Send command to server
1428 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1429 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1433 DWORD nBytesSent
= 0;
1437 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1440 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1442 bParamHasLen
= lpszParam
&& strlen(lpszParam
) > 0;
1443 len
= (bParamHasLen
? strlen(lpszParam
) : -1) + strlen(szFtpCommands
[ftpCmd
]) +
1445 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1447 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1450 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], bParamHasLen
? " " : "",
1451 bParamHasLen
? lpszParam
: "", szCRLF
);
1453 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1454 while((nBytesSent
< len
) && (nRC
!= SOCKET_ERROR
))
1456 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1460 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1463 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1464 &nBytesSent
, sizeof(DWORD
));
1466 TRACE("Sent %ld bytes\n", nBytesSent
);
1467 return (nRC
!= SOCKET_ERROR
);
1471 /***********************************************************************
1472 * FTP_ReceiveResponse (internal)
1474 * Receive response from server
1477 * Reply code on success
1482 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
1483 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1487 char firstprefix
[5];
1488 BOOL multiline
= FALSE
;
1491 TRACE("socket(%d) \n", nSocket
);
1494 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1499 if (!INTERNET_GetNextLine(nSocket
, lpszResponse
, &nRecv
))
1506 if(lpszResponse
[3] != '-')
1509 { /* Start of multiline repsonse. Loop until we get "nnn " */
1511 memcpy(firstprefix
, lpszResponse
, 3);
1512 firstprefix
[3] = ' ';
1513 firstprefix
[4] = '\0';
1518 if(!memcmp(firstprefix
, lpszResponse
, 4))
1526 lpszResponse
[nRecv
] = '\0';
1527 rc
= atoi(lpszResponse
);
1530 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1531 &nRecv
, sizeof(DWORD
));
1535 TRACE("return %d\n", rc
);
1540 /***********************************************************************
1541 * FTP_SendPassword (internal)
1543 * Send password to ftp server
1550 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
)
1553 BOOL bSuccess
= FALSE
;
1556 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1559 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1560 MAX_REPLY_LEN
, 0, 0, 0);
1563 TRACE("Received reply code %d\n", nResCode
);
1564 /* Login successful... */
1565 if (nResCode
== 230)
1567 /* Command not implemented, superfluous at the server site... */
1568 /* Need account for login... */
1569 else if (nResCode
== 332)
1570 bSuccess
= FTP_SendAccount(lpwfs
);
1572 FTP_SetResponseError(nResCode
);
1576 TRACE("Returning %d\n", bSuccess
);
1581 /***********************************************************************
1582 * FTP_SendAccount (internal)
1591 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
)
1594 BOOL bSuccess
= FALSE
;
1597 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, NOACCOUNT
, 0, 0, 0))
1600 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1601 MAX_REPLY_LEN
, 0, 0, 0);
1605 FTP_SetResponseError(nResCode
);
1612 /***********************************************************************
1613 * FTP_SendStore (internal)
1615 * Send request to upload file to ftp server
1622 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1625 BOOL bSuccess
= FALSE
;
1628 if (!FTP_InitListenSocket(lpwfs
))
1631 if (!FTP_SendType(lpwfs
, dwType
))
1634 if (!FTP_SendPort(lpwfs
))
1637 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
1639 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1640 MAX_REPLY_LEN
, 0, 0, 0);
1643 if (nResCode
== 150)
1646 FTP_SetResponseError(nResCode
);
1650 if (!bSuccess
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1652 close(lpwfs
->lstnSocket
);
1653 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1660 /***********************************************************************
1661 * FTP_InitListenSocket (internal)
1663 * Create a socket to listen for server response
1670 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
)
1672 BOOL bSuccess
= FALSE
;
1673 size_t namelen
= sizeof(struct sockaddr_in
);
1677 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
1678 if (INVALID_SOCKET
== lpwfs
->lstnSocket
)
1680 TRACE("Unable to create listening socket\n");
1684 /* We obtain our ip addr from the name of the command channel socket */
1685 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
1687 /* and get the system to assign us a port */
1688 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
1690 if (SOCKET_ERROR
== bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)))
1692 TRACE("Unable to bind socket\n");
1696 if (SOCKET_ERROR
== listen(lpwfs
->lstnSocket
, MAX_BACKLOG
))
1698 TRACE("listen failed\n");
1702 if (SOCKET_ERROR
!= getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
))
1706 if (!bSuccess
&& INVALID_SOCKET
== lpwfs
->lstnSocket
)
1708 close(lpwfs
->lstnSocket
);
1709 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1716 /***********************************************************************
1717 * FTP_SendType (internal)
1719 * Tell server type of data being transfered
1726 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
)
1729 CHAR type
[2] = { "I\0" };
1730 BOOL bSuccess
= FALSE
;
1733 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
1736 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
1739 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1740 MAX_REPLY_LEN
, 0, 0, 0)/100;
1746 FTP_SetResponseError(nResCode
);
1754 /***********************************************************************
1755 * FTP_SendPort (internal)
1757 * Tell server which port to use
1764 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
)
1767 CHAR szIPAddress
[64];
1768 BOOL bSuccess
= FALSE
;
1771 sprintf(szIPAddress
, "%d,%d,%d,%d,%d,%d",
1772 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
1773 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
1774 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
1775 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
1776 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
1777 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
1779 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
1782 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1783 MAX_REPLY_LEN
,0, 0, 0);
1786 if (nResCode
== 200)
1789 FTP_SetResponseError(nResCode
);
1797 /***********************************************************************
1798 * FTP_InitDataSocket (internal)
1807 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
)
1809 struct sockaddr_in saddr
;
1810 size_t addrlen
= sizeof(struct sockaddr
);
1813 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
1814 close(lpwfs
->lstnSocket
);
1815 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1817 return *nDataSocket
!= INVALID_SOCKET
;
1821 /***********************************************************************
1822 * FTP_SendData (internal)
1824 * Send data to the server
1831 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
)
1833 BY_HANDLE_FILE_INFORMATION fi
;
1834 DWORD nBytesRead
= 0;
1835 DWORD nBytesSent
= 0;
1836 DWORD nTotalSent
= 0;
1837 DWORD nBytesToSend
, nLen
, nRC
= 1;
1838 time_t s_long_time
, e_long_time
;
1843 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1844 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1846 /* Get the size of the file. */
1847 GetFileInformationByHandle(hFile
, &fi
);
1852 nBytesToSend
= nBytesRead
- nBytesSent
;
1854 if (nBytesToSend
<= 0)
1856 /* Read data from file. */
1858 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
1859 ERR("Failed reading from file\n");
1862 nBytesToSend
= nBytesRead
;
1867 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
1868 DATA_PACKET_SIZE
: nBytesToSend
;
1869 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
1871 if (nRC
!= SOCKET_ERROR
)
1877 /* Do some computation to display the status. */
1879 nSeconds
= e_long_time
- s_long_time
;
1880 if( nSeconds
/ 60 > 0 )
1882 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
1883 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
1884 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1888 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
1889 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
1890 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1892 } while (nRC
!= SOCKET_ERROR
);
1894 TRACE("file transfer complete!\n");
1896 if(lpszBuffer
!= NULL
)
1897 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
1903 /***********************************************************************
1904 * FTP_SendRetrieve (internal)
1906 * Send request to retrieve a file
1909 * Number of bytes to be received on success
1913 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1919 if (!FTP_InitListenSocket(lpwfs
))
1922 if (!FTP_SendType(lpwfs
, dwType
))
1925 if (!FTP_SendPort(lpwfs
))
1928 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
1931 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1932 MAX_REPLY_LEN
, 0, 0, 0);
1935 if (nResCode
== 125 || nResCode
== 150)
1937 /* Parse size of data to be retrieved */
1938 INT i
, sizepos
= -1;
1939 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
1940 for (i
= strlen(lpszResponseBuffer
) - 1; i
>= 0; i
--)
1942 if ('(' == lpszResponseBuffer
[i
])
1951 nResult
= atol(&lpszResponseBuffer
[sizepos
+1]);
1952 TRACE("Waiting to receive %ld bytes\n", nResult
);
1958 if (0 == nResult
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1960 close(lpwfs
->lstnSocket
);
1961 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1968 /***********************************************************************
1969 * FTP_RetrieveData (internal)
1971 * Retrieve data from server
1978 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
1980 DWORD nBytesWritten
;
1981 DWORD nBytesReceived
= 0;
1987 if (INVALID_HANDLE_VALUE
== hFile
)
1990 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1991 if (NULL
== lpszBuffer
)
1993 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1997 while (nBytesReceived
< nBytes
&& nRC
!= SOCKET_ERROR
)
1999 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2000 if (nRC
!= SOCKET_ERROR
)
2002 /* other side closed socket. */
2005 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2006 nBytesReceived
+= nRC
;
2009 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2010 nBytesReceived
* 100 / nBytes
);
2013 TRACE("Data transfer complete\n");
2014 if (NULL
!= lpszBuffer
)
2015 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2018 return (nRC
!= SOCKET_ERROR
);
2022 /***********************************************************************
2023 * FTP_CloseSessionHandle (internal)
2025 * Deallocate session handle
2032 BOOL
FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs
)
2034 if (INVALID_SOCKET
!= lpwfs
->sndSocket
)
2035 close(lpwfs
->sndSocket
);
2037 if (INVALID_SOCKET
!= lpwfs
->lstnSocket
)
2038 close(lpwfs
->lstnSocket
);
2040 if (lpwfs
->lpszPassword
)
2041 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2043 if (lpwfs
->lpszUserName
)
2044 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2046 HeapFree(GetProcessHeap(), 0, lpwfs
);
2052 /***********************************************************************
2053 * FTP_CloseSessionHandle (internal)
2055 * Deallocate session handle
2062 BOOL
FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn
)
2068 for (i
= 0; i
< lpwfn
->size
; i
++)
2070 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2071 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2074 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2075 HeapFree(GetProcessHeap(), 0, lpwfn
);
2081 /***********************************************************************
2082 * FTP_ReceiveFileList (internal)
2084 * Read file list from server
2087 * Handle to file list on success
2091 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
2092 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
)
2095 LPFILEPROPERTIESA lpafp
= NULL
;
2096 LPWININETFINDNEXTA lpwfn
= NULL
;
2100 if (FTP_ParseDirectory(lpwfs
, nSocket
, &lpafp
, &dwSize
))
2102 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2104 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTA
));
2107 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2108 lpwfn
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)lpwfs
;
2109 lpwfn
->hdr
.dwContext
= dwContext
;
2110 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2111 lpwfn
->size
= dwSize
;
2112 lpwfn
->lpafp
= lpafp
;
2116 TRACE("Matched %ld files\n", dwSize
);
2117 return (HINTERNET
)lpwfn
;
2121 /***********************************************************************
2122 * FTP_ConvertFileProp (internal)
2124 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2131 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp
, LPWIN32_FIND_DATAA lpFindFileData
)
2133 BOOL bSuccess
= FALSE
;
2135 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
2139 DWORD access
= mktime(&lpafp
->tmLastModified
);
2141 /* Not all fields are filled in */
2142 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= HIWORD(access
);
2143 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= LOWORD(access
);
2144 lpFindFileData
->nFileSizeHigh
= HIWORD(lpafp
->nSize
);
2145 lpFindFileData
->nFileSizeLow
= LOWORD(lpafp
->nSize
);
2147 if (lpafp
->bIsDirectory
)
2148 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2150 if (lpafp
->lpszName
)
2151 strncpy(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2160 /***********************************************************************
2161 * FTP_ParseDirectory (internal)
2163 * Parse string of directory information
2169 * FIXME: - This function needs serious clea-up
2170 * - We should consider both UNIX and NT list formats
2172 #define MAX_MONTH_LEN 10
2173 #define MIN_LEN_DIR_ENTRY 15
2175 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
)
2178 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2181 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2187 CHAR pszMonth
[MAX_MONTH_LEN
];
2189 BOOL bSuccess
= TRUE
;
2190 DWORD nBufLen
= MAX_REPLY_LEN
;
2191 LPFILEPROPERTIESA curFileProp
= NULL
;
2192 CHAR
* pszLine
= NULL
;
2193 CHAR
* pszToken
= NULL
;
2194 INT nTokenToSkip
= 3;
2202 INT sizeFilePropArray
= 20;
2203 INT indexFilePropArray
= 0;
2207 /* Allocate intial file properties array */
2208 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESA
)*(sizeFilePropArray
));
2215 while ((pszLine
= INTERNET_GetNextLine(nSocket
, INTERNET_GetResponseBuffer(), &nBufLen
)) != NULL
)
2217 if (sizeFilePropArray
<= indexFilePropArray
)
2219 LPFILEPROPERTIESA tmpafp
;
2221 sizeFilePropArray
*= 2;
2222 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2223 sizeof(FILEPROPERTIESA
)*sizeFilePropArray
);
2233 curFileProp
= &((*lpafp
)[indexFilePropArray
]);
2235 /* First Parse the permissions. */
2236 pszToken
= strtok(pszLine
, " \t" );
2238 /* HACK! If this is not a file listing skip the line */
2239 if (!pszToken
|| 10 != strlen(pszToken
) || nBufLen
<= MIN_LEN_DIR_ENTRY
)
2241 nBufLen
= MAX_REPLY_LEN
;
2245 FTP_ParsePermission(pszToken
, curFileProp
);
2251 pszToken
= strtok( NULL
, " \t" );
2253 } while( nCount
<= nTokenToSkip
);
2255 /* Store the size of the file in the param list. */
2256 TRACE("nSize-> %s\n", pszToken
);
2257 if (pszToken
!= NULL
)
2258 curFileProp
->nSize
= atol(pszToken
);
2260 /* Parse last modified time. */
2268 pszToken
= strtok( NULL
, " \t" );
2269 strncpy(pszMonth
, pszToken
, MAX_MONTH_LEN
);
2270 CharUpperA(pszMonth
);
2271 pszMatch
= strstr(szMonths
, pszMonth
);
2272 if( pszMatch
!= NULL
)
2273 nMonth
= (pszMatch
- szMonths
) / 3;
2275 pszToken
= strtok(NULL
, " \t");
2276 TRACE("nDay -> %s\n", pszToken
);
2277 if (pszToken
!= NULL
)
2278 nDay
= atoi(pszToken
);
2280 pszToken
= strtok(NULL
, " \t");
2281 pszMinutes
= strchr(pszToken
, ':');
2282 if( pszMinutes
!= NULL
)
2285 nMinutes
= atoi(pszMinutes
);
2286 pszHour
= pszMinutes
- 3;
2287 if (pszHour
!= NULL
)
2288 nHour
= atoi(pszHour
);
2290 apTM
= localtime( &aTime
);
2291 nYear
= apTM
->tm_year
;
2295 nYear
= atoi(pszToken
);
2300 curFileProp
->tmLastModified
.tm_sec
= nSeconds
;
2301 curFileProp
->tmLastModified
.tm_min
= nMinutes
;
2302 curFileProp
->tmLastModified
.tm_hour
= nHour
;
2303 curFileProp
->tmLastModified
.tm_mday
= nDay
;
2304 curFileProp
->tmLastModified
.tm_mon
= nMonth
;
2305 curFileProp
->tmLastModified
.tm_year
= nYear
;
2307 pszToken
= strtok(NULL
, " \t");
2308 if(pszToken
!= NULL
)
2310 curFileProp
->lpszName
= HEAP_strdupA(GetProcessHeap(),0,pszToken
);
2311 TRACE(": %s\n", curFileProp
->lpszName
);
2314 nBufLen
= MAX_REPLY_LEN
;
2315 indexFilePropArray
++;
2318 if (bSuccess
&& indexFilePropArray
)
2320 if (indexFilePropArray
< sizeFilePropArray
- 1)
2322 LPFILEPROPERTIESA tmpafp
;
2324 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2325 sizeof(FILEPROPERTIESA
)*indexFilePropArray
);
2329 *dwfp
= indexFilePropArray
;
2333 HeapFree(GetProcessHeap(), 0, *lpafp
);
2334 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2343 /***********************************************************************
2344 * FTP_ParsePermission (internal)
2346 * Parse permission string of directory information
2353 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
)
2355 BOOL bSuccess
= TRUE
;
2356 unsigned short nPermission
= 0;
2361 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
2367 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
2373 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
2376 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
2379 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
2382 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
2385 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
2388 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
2391 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
2394 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
2397 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
2401 }while (nPos
<= nLast
);
2403 lpfp
->permissions
= nPermission
;
2408 /***********************************************************************
2409 * FTP_SetResponseError (internal)
2411 * Set the appropriate error code for a given response from the server
2416 DWORD
FTP_SetResponseError(DWORD dwResponse
)
2422 case 421: /* Service not available - Server may be shutting down. */
2423 dwCode
= ERROR_INTERNET_TIMEOUT
;
2426 case 425: /* Cannot open data connection. */
2427 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
2430 case 426: /* Connection closed, transer aborted. */
2431 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
2434 case 500: /* Syntax error. Command unrecognized. */
2435 case 501: /* Syntax error. Error in parameters or arguments. */
2436 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
2439 case 530: /* Not logged in. Login incorrect. */
2440 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
2443 case 550: /* File action not taken. File not found or no access. */
2444 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
2447 case 450: /* File action not taken. File may be busy. */
2448 case 451: /* Action aborted. Server error. */
2449 case 452: /* Action not taken. Insufficient storage space on server. */
2450 case 502: /* Command not implemented. */
2451 case 503: /* Bad sequence of command. */
2452 case 504: /* Command not implemented for that parameter. */
2453 case 532: /* Need account for storing files */
2454 case 551: /* Requested action aborted. Page type unknown */
2455 case 552: /* Action aborted. Exceeded storage allocation */
2456 case 553: /* Action not taken. File name not allowed. */
2459 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
2463 INTERNET_SetLastError(dwCode
);