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>
29 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(wininet
);
34 #define NOACCOUNT "noaccount"
35 #define DATA_PACKET_SIZE 0x2000
38 #define RESPONSE_TIMEOUT 30
41 /* FTP commands with arguments. */
56 /* FTP commands without arguments. */
64 static const CHAR
*szFtpCommands
[] = {
85 static const CHAR szMonths
[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
87 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
88 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
89 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
90 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
);
91 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
);
92 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
93 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
94 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
95 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
);
96 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
);
97 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
);
98 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
);
99 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
);
100 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
);
101 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
);
102 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
);
103 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
);
104 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
105 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
);
106 LPSTR
FTP_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
);
107 DWORD
FTP_SetResponseError(DWORD dwResponse
);
109 /***********************************************************************
110 * FtpPutFileA (WININET.43)
112 * Uploads a file to the FTP server
119 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
120 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
122 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
123 LPWININETAPPINFOA hIC
= NULL
;
125 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
127 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
131 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
132 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
134 WORKREQUEST workRequest
;
136 workRequest
.asyncall
= FTPPUTFILEA
;
137 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
138 workRequest
.LPSZLOCALFILE
= (DWORD
)strdup(lpszLocalFile
);
139 workRequest
.LPSZNEWREMOTEFILE
= (DWORD
)strdup(lpszNewRemoteFile
);
140 workRequest
.DWFLAGS
= dwFlags
;
141 workRequest
.DWCONTEXT
= dwContext
;
143 return INTERNET_AsyncCall(&workRequest
);
147 return FTP_FtpPutFileA(hConnect
, lpszLocalFile
,
148 lpszNewRemoteFile
, dwFlags
, dwContext
);
152 /***********************************************************************
153 * FTP_FtpPutFileA (Internal)
155 * Uploads a file to the FTP server
162 BOOL WINAPI
FTP_FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
163 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
165 HANDLE hFile
= (HANDLE
)NULL
;
166 BOOL bSuccess
= FALSE
;
167 LPWININETAPPINFOA hIC
= NULL
;
168 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
170 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile
, lpszNewRemoteFile
);
171 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
173 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
177 /* Clear any error information */
178 INTERNET_SetLastError(0);
180 /* Open file to be uploaded */
181 if (INVALID_HANDLE_VALUE
==
182 (hFile
= CreateFileA(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
184 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
188 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
189 if (hIC
->lpfnStatusCB
)
190 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
192 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
196 /* Accept connection from ftp server */
197 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
199 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
206 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
208 INTERNET_ASYNC_RESULT iar
;
210 iar
.dwResult
= (DWORD
)bSuccess
;
211 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
212 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
213 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
223 /***********************************************************************
224 * FtpSetCurrentDirectoryA (WININET.49)
226 * Change the working directory on the FTP server
233 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
235 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
236 LPWININETAPPINFOA hIC
= NULL
;
238 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
240 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
244 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
246 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
247 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
249 WORKREQUEST workRequest
;
251 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYA
;
252 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
253 workRequest
.LPSZDIRECTORY
= (DWORD
)strdup(lpszDirectory
);
255 return INTERNET_AsyncCall(&workRequest
);
259 return FTP_FtpSetCurrentDirectoryA(hConnect
, lpszDirectory
);
264 /***********************************************************************
265 * FTP_FtpSetCurrentDirectoryA (Internal)
267 * Change the working directory on the FTP server
274 BOOL WINAPI
FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
277 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
278 LPWININETAPPINFOA hIC
= NULL
;
279 DWORD bSuccess
= FALSE
;
281 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
283 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
285 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
289 /* Clear any error information */
290 INTERNET_SetLastError(0);
292 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
293 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
294 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
297 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
298 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
305 FTP_SetResponseError(nResCode
);
309 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
311 INTERNET_ASYNC_RESULT iar
;
313 iar
.dwResult
= (DWORD
)bSuccess
;
314 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
315 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
316 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
322 /***********************************************************************
323 * FtpCreateDirectoryA (WININET.31)
325 * Create new directory on the FTP server
332 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
334 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
335 LPWININETAPPINFOA hIC
= NULL
;
337 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
339 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
343 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
344 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
346 WORKREQUEST workRequest
;
348 workRequest
.asyncall
= FTPCREATEDIRECTORYA
;
349 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
350 workRequest
.LPSZDIRECTORY
= (DWORD
)strdup(lpszDirectory
);
352 return INTERNET_AsyncCall(&workRequest
);
356 return FTP_FtpCreateDirectoryA(hConnect
, lpszDirectory
);
361 /***********************************************************************
362 * FTP_FtpCreateDirectoryA (Internal)
364 * Create new directory on the FTP server
371 BOOL WINAPI
FTP_FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
374 BOOL bSuccess
= FALSE
;
375 LPWININETAPPINFOA hIC
= NULL
;
376 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
379 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
381 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
385 /* Clear any error information */
386 INTERNET_SetLastError(0);
388 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
391 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
392 MAX_REPLY_LEN
, 0, 0, 0);
398 FTP_SetResponseError(nResCode
);
402 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
403 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
405 INTERNET_ASYNC_RESULT iar
;
407 iar
.dwResult
= (DWORD
)bSuccess
;
408 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
409 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
410 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
417 /***********************************************************************
418 * FtpFindFirstFileA (WININET.35)
420 * Search the specified directory
423 * HINTERNET on success
427 INTERNETAPI HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
428 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
430 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
431 LPWININETAPPINFOA hIC
= NULL
;
433 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
435 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
439 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
440 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
442 WORKREQUEST workRequest
;
444 workRequest
.asyncall
= FTPFINDFIRSTFILEA
;
445 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
446 workRequest
.LPSZSEARCHFILE
= (DWORD
)strdup(lpszSearchFile
);
447 workRequest
.LPFINDFILEDATA
= (DWORD
)lpFindFileData
;
448 workRequest
.DWFLAGS
= dwFlags
;
449 workRequest
.DWCONTEXT
= dwContext
;
451 INTERNET_AsyncCall(&workRequest
);
456 return FTP_FtpFindFirstFileA(hConnect
, lpszSearchFile
, lpFindFileData
,
462 /***********************************************************************
463 * FTP_FtpFindFirstFileA (Internal)
465 * Search the specified directory
468 * HINTERNET on success
472 INTERNETAPI HINTERNET WINAPI
FTP_FtpFindFirstFileA(HINTERNET hConnect
,
473 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
476 LPWININETAPPINFOA hIC
= NULL
;
477 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
478 LPWININETFINDNEXTA hFindNext
= NULL
;
482 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
484 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
488 /* Clear any error information */
489 INTERNET_SetLastError(0);
491 if (!FTP_InitListenSocket(lpwfs
))
494 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
497 if (!FTP_SendPort(lpwfs
))
500 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
501 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, lpszSearchFile
,
502 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
505 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
506 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
509 if (nResCode
== 125 || nResCode
== 150)
513 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
515 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpFindFileData
, dwContext
);
517 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
518 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
519 if (nResCode
!= 226 && nResCode
!= 250)
520 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
526 FTP_SetResponseError(nResCode
);
530 if (lpwfs
->lstnSocket
!= INVALID_SOCKET
)
531 close(lpwfs
->lstnSocket
);
533 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
535 INTERNET_ASYNC_RESULT iar
;
539 iar
.dwResult
= (DWORD
)hFindNext
;
540 iar
.dwError
= ERROR_SUCCESS
;
541 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
542 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
545 iar
.dwResult
= (DWORD
)hFindNext
;
546 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
547 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
548 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
551 return (HINTERNET
)hFindNext
;
555 /***********************************************************************
556 * FtpGetCurrentDirectoryA (WININET.37)
558 * Retrieves the current directory
565 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
566 LPDWORD lpdwCurrentDirectory
)
568 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
569 LPWININETAPPINFOA hIC
= NULL
;
571 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
573 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
575 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
579 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
580 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
582 WORKREQUEST workRequest
;
584 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYA
;
585 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
586 workRequest
.LPSZDIRECTORY
= (DWORD
)lpszCurrentDirectory
;
587 workRequest
.LPDWDIRECTORY
= (DWORD
)lpdwCurrentDirectory
;
589 return INTERNET_AsyncCall(&workRequest
);
593 return FTP_FtpGetCurrentDirectoryA(hFtpSession
, lpszCurrentDirectory
,
594 lpdwCurrentDirectory
);
599 /***********************************************************************
600 * FTP_FtpGetCurrentDirectoryA (Internal)
602 * Retrieves the current directory
609 BOOL WINAPI
FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
610 LPDWORD lpdwCurrentDirectory
)
613 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
614 LPWININETAPPINFOA hIC
= NULL
;
615 DWORD bSuccess
= FALSE
;
617 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
619 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
621 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
625 /* Clear any error information */
626 INTERNET_SetLastError(0);
628 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
630 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
631 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
632 hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
))
635 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
636 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
);
639 if (nResCode
== 257) /* Extract directory name */
641 INT firstpos
, lastpos
, len
;
642 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
644 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
646 if ('"' == lpszResponseBuffer
[lastpos
])
655 len
= lastpos
- firstpos
- 1;
656 strncpy(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
657 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
658 *lpdwCurrentDirectory
= len
;
662 FTP_SetResponseError(nResCode
);
666 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
668 INTERNET_ASYNC_RESULT iar
;
670 iar
.dwResult
= (DWORD
)bSuccess
;
671 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
672 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
673 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
676 return (DWORD
) bSuccess
;
679 /***********************************************************************
680 * FtpOpenFileA (WININET.41)
682 * Open a remote file for writing or reading
685 * HINTERNET handle on success
689 INTERNETAPI HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
690 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
693 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
694 LPWININETAPPINFOA hIC
= NULL
;
696 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
698 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
702 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
703 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
705 WORKREQUEST workRequest
;
707 workRequest
.asyncall
= FTPOPENFILEA
;
708 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
709 workRequest
.LPSZFILENAME
= (DWORD
)strdup(lpszFileName
);
710 workRequest
.FDWACCESS
= fdwAccess
;
711 workRequest
.DWFLAGS
= dwFlags
;
712 workRequest
.DWCONTEXT
= dwContext
;
714 INTERNET_AsyncCall(&workRequest
);
719 return FTP_FtpOpenFileA(hFtpSession
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
724 /***********************************************************************
725 * FTP_FtpOpenFileA (Internal)
727 * Open a remote file for writing or reading
730 * HINTERNET handle on success
734 HINTERNET
FTP_FtpOpenFileA(HINTERNET hFtpSession
,
735 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
739 BOOL bSuccess
= FALSE
;
740 LPWININETFILE hFile
= NULL
;
741 LPWININETAPPINFOA hIC
= NULL
;
742 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
746 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
748 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
752 /* Clear any error information */
753 INTERNET_SetLastError(0);
755 if (GENERIC_READ
== fdwAccess
)
757 /* Set up socket to retrieve data */
758 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
760 else if (GENERIC_WRITE
== fdwAccess
)
762 /* Set up socket to send data */
763 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
766 /* Accept connection from server */
767 if (bSuccess
&& FTP_InitDataSocket(lpwfs
, &nDataSocket
))
769 hFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
770 hFile
->hdr
.htype
= WH_HFILE
;
771 hFile
->hdr
.dwFlags
= dwFlags
;
772 hFile
->hdr
.dwContext
= dwContext
;
773 hFile
->hdr
.lpwhparent
= hFtpSession
;
774 hFile
->nDataSocket
= nDataSocket
;
777 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
778 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
780 INTERNET_ASYNC_RESULT iar
;
784 iar
.dwResult
= (DWORD
)hFile
;
785 iar
.dwError
= ERROR_SUCCESS
;
786 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
787 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
790 iar
.dwResult
= (DWORD
)bSuccess
;
791 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
792 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
793 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
796 return (HINTERNET
)hFile
;
800 /***********************************************************************
801 * FtpGetFileA (WININET.39)
803 * Retrieve file from the FTP server
810 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
811 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
814 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
815 LPWININETAPPINFOA hIC
= NULL
;
817 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
819 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
823 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
824 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
826 WORKREQUEST workRequest
;
828 workRequest
.asyncall
= FTPGETFILEA
;
829 workRequest
.HFTPSESSION
= (DWORD
)hInternet
;
830 workRequest
.LPSZREMOTEFILE
= (DWORD
)strdup(lpszRemoteFile
);
831 workRequest
.LPSZNEWFILE
= (DWORD
)strdup(lpszNewFile
);
832 workRequest
.DWLOCALFLAGSATTRIBUTE
= dwLocalFlagsAttribute
;
833 workRequest
.FFAILIFEXISTS
= (DWORD
)fFailIfExists
;
834 workRequest
.DWFLAGS
= dwInternetFlags
;
835 workRequest
.DWCONTEXT
= dwContext
;
837 return INTERNET_AsyncCall(&workRequest
);
841 return FTP_FtpGetFileA(hInternet
, lpszRemoteFile
, lpszNewFile
,
842 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
847 /***********************************************************************
848 * FTP_FtpGetFileA (Internal)
850 * Retrieve file from the FTP server
857 BOOL WINAPI
FTP_FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
858 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
862 BOOL bSuccess
= FALSE
;
864 LPWININETAPPINFOA hIC
= NULL
;
865 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
867 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile
, lpszNewFile
);
868 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
870 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
874 /* Clear any error information */
875 INTERNET_SetLastError(0);
877 /* Ensure we can write to lpszNewfile by opening it */
878 hFile
= CreateFileA(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
879 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
880 if (INVALID_HANDLE_VALUE
== hFile
)
883 /* Set up socket to retrieve data */
884 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
890 /* Accept connection from ftp server */
891 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
896 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
897 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
898 MAX_REPLY_LEN
, 0, 0, 0);
904 FTP_SetResponseError(nResCode
);
914 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
915 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
917 INTERNET_ASYNC_RESULT iar
;
919 iar
.dwResult
= (DWORD
)bSuccess
;
920 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
921 hIC
->lpfnStatusCB(hInternet
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
922 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
929 /***********************************************************************
930 * FtpDeleteFileA (WININET.33)
932 * Delete a file on the ftp server
939 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
941 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
942 LPWININETAPPINFOA hIC
= NULL
;
944 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
946 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
950 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
951 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
953 WORKREQUEST workRequest
;
955 workRequest
.asyncall
= FTPRENAMEFILEA
;
956 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
957 workRequest
.LPSZFILENAME
= (DWORD
)strdup(lpszFileName
);
959 return INTERNET_AsyncCall(&workRequest
);
963 return FTP_FtpDeleteFileA(hFtpSession
, lpszFileName
);
968 /***********************************************************************
969 * FTP_FtpDeleteFileA (Internal)
971 * Delete a file on the ftp server
978 BOOL
FTP_FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
981 BOOL bSuccess
= FALSE
;
982 LPWININETAPPINFOA hIC
= NULL
;
983 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
985 TRACE("0x%08lx\n", (ULONG
) hFtpSession
);
986 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
988 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
992 /* Clear any error information */
993 INTERNET_SetLastError(0);
995 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
998 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
999 MAX_REPLY_LEN
, 0, 0, 0);
1002 if (nResCode
== 250)
1005 FTP_SetResponseError(nResCode
);
1008 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1009 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1011 INTERNET_ASYNC_RESULT iar
;
1013 iar
.dwResult
= (DWORD
)bSuccess
;
1014 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1015 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1016 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1023 /***********************************************************************
1024 * FtpRemoveDirectoryA (WININET.45)
1026 * Remove a directory on the ftp server
1033 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1035 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1036 LPWININETAPPINFOA hIC
= NULL
;
1038 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1040 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1044 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1045 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1047 WORKREQUEST workRequest
;
1049 workRequest
.asyncall
= FTPREMOVEDIRECTORYA
;
1050 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1051 workRequest
.LPSZDIRECTORY
= (DWORD
)strdup(lpszDirectory
);
1053 return INTERNET_AsyncCall(&workRequest
);
1057 return FTP_FtpRemoveDirectoryA(hFtpSession
, lpszDirectory
);
1062 /***********************************************************************
1063 * FTP_FtpRemoveDirectoryA (Internal)
1065 * Remove a directory on the ftp server
1072 BOOL
FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1075 BOOL bSuccess
= FALSE
;
1076 LPWININETAPPINFOA hIC
= NULL
;
1077 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1080 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1082 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1086 /* Clear any error information */
1087 INTERNET_SetLastError(0);
1089 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1092 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1093 MAX_REPLY_LEN
, 0, 0, 0);
1096 if (nResCode
== 250)
1099 FTP_SetResponseError(nResCode
);
1103 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1104 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1106 INTERNET_ASYNC_RESULT iar
;
1108 iar
.dwResult
= (DWORD
)bSuccess
;
1109 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1110 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1111 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1118 /***********************************************************************
1119 * FtpRenameFileA (WININET.47)
1121 * Rename a file on the ftp server
1128 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1130 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1131 LPWININETAPPINFOA hIC
= NULL
;
1133 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1135 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1139 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1140 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1142 WORKREQUEST workRequest
;
1144 workRequest
.asyncall
= FTPRENAMEFILEA
;
1145 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1146 workRequest
.LPSZSRCFILE
= (DWORD
)strdup(lpszSrc
);
1147 workRequest
.LPSZDESTFILE
= (DWORD
)strdup(lpszDest
);
1149 return INTERNET_AsyncCall(&workRequest
);
1153 return FTP_FtpRenameFileA(hFtpSession
, lpszSrc
, lpszDest
);
1157 /***********************************************************************
1158 * FTP_FtpRenameFileA (Internal)
1160 * Rename a file on the ftp server
1167 BOOL
FTP_FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1170 BOOL bSuccess
= FALSE
;
1171 LPWININETAPPINFOA hIC
= NULL
;
1172 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1175 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1177 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1181 /* Clear any error information */
1182 INTERNET_SetLastError(0);
1184 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1187 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1188 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1189 if (nResCode
== 350)
1191 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1194 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1195 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1198 if (nResCode
== 250)
1201 FTP_SetResponseError(nResCode
);
1204 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1205 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1207 INTERNET_ASYNC_RESULT iar
;
1209 iar
.dwResult
= (DWORD
)bSuccess
;
1210 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1211 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1212 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1219 /***********************************************************************
1220 * FTP_Connect (internal)
1222 * Connect to a ftp server
1225 * HINTERNET a session handle on success
1230 HINTERNET
FTP_Connect(HINTERNET hInternet
, LPCSTR lpszServerName
,
1231 INTERNET_PORT nServerPort
, LPCSTR lpszUserName
,
1232 LPCSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
)
1234 struct sockaddr_in socketAddr
;
1235 struct hostent
*phe
= NULL
;
1236 INT nsocket
= INVALID_SOCKET
;
1237 LPWININETAPPINFOA hIC
= NULL
;
1238 BOOL bSuccess
= FALSE
;
1239 LPWININETFTPSESSIONA lpwfs
= NULL
;
1241 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1242 (ULONG
) hInternet
, lpszServerName
,
1243 nServerPort
, lpszUserName
, lpszPassword
);
1245 if (((LPWININETHANDLEHEADER
)hInternet
)->htype
!= WH_HINIT
)
1248 hIC
= (LPWININETAPPINFOA
) hInternet
;
1250 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1252 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME
);
1256 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1257 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1259 if (hIC
->lpfnStatusCB
)
1260 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1261 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1263 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1265 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1269 if (hIC
->lpfnStatusCB
)
1270 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1271 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1273 if (INVALID_SOCKET
== (nsocket
= socket(AF_INET
,SOCK_STREAM
,0)))
1275 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1279 if (hIC
->lpfnStatusCB
)
1280 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1281 &socketAddr
, sizeof(struct sockaddr_in
));
1283 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1285 ERR("Unable to connect: errno(%d)\n", errno
);
1286 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1290 TRACE("Connected to server\n");
1291 if (hIC
->lpfnStatusCB
)
1292 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1293 &socketAddr
, sizeof(struct sockaddr_in
));
1295 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA
));
1298 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1302 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1303 lpwfs
->hdr
.dwFlags
= dwFlags
;
1304 lpwfs
->hdr
.dwContext
= dwContext
;
1305 lpwfs
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)hInternet
;
1306 lpwfs
->sndSocket
= nsocket
;
1307 memcpy(&lpwfs
->socketAddress
, &socketAddr
, sizeof(socketAddr
));
1308 lpwfs
->phostent
= phe
;
1310 if (NULL
== lpszUserName
)
1312 lpwfs
->lpszUserName
= strdup("anonymous");
1313 lpwfs
->lpszPassword
= strdup("user@server");
1317 lpwfs
->lpszUserName
= strdup(lpszUserName
);
1318 lpwfs
->lpszPassword
= strdup(lpszPassword
);
1321 if (FTP_ConnectToHost(lpwfs
))
1323 if (hIC
->lpfnStatusCB
)
1325 INTERNET_ASYNC_RESULT iar
;
1327 iar
.dwResult
= (DWORD
)lpwfs
;
1328 iar
.dwError
= ERROR_SUCCESS
;
1330 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1331 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1333 TRACE("Successfully logged into server\n");
1339 if (!bSuccess
&& INVALID_SOCKET
!= nsocket
)
1342 if (!bSuccess
&& lpwfs
)
1344 HeapFree(GetProcessHeap(), 0, lpwfs
);
1348 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1350 INTERNET_ASYNC_RESULT iar
;
1352 iar
.dwResult
= (DWORD
)lpwfs
;
1353 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1354 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1355 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1358 return (HINTERNET
) lpwfs
;
1362 /***********************************************************************
1363 * FTP_ConnectHost (internal)
1365 * Connect to a ftp server
1372 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
)
1375 BOOL bSuccess
= FALSE
;
1378 FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1380 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1383 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1384 MAX_REPLY_LEN
, 0, 0, 0);
1387 /* Login successful... */
1388 if (nResCode
== 230)
1390 /* User name okay, need password... */
1391 else if (nResCode
== 331)
1392 bSuccess
= FTP_SendPassword(lpwfs
);
1393 /* Need account for login... */
1394 else if (nResCode
== 332)
1395 bSuccess
= FTP_SendAccount(lpwfs
);
1397 FTP_SetResponseError(nResCode
);
1400 TRACE("Returning %d\n", bSuccess
);
1406 /***********************************************************************
1407 * FTP_SendCommand (internal)
1409 * Send command to server
1416 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1417 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1421 DWORD nBytesSent
= 0;
1425 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1428 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1430 bParamHasLen
= lpszParam
&& strlen(lpszParam
) > 0;
1431 len
= (bParamHasLen
? strlen(lpszParam
) : -1) + strlen(szFtpCommands
[ftpCmd
]) +
1433 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1435 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1438 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], bParamHasLen
? " " : "",
1439 bParamHasLen
? lpszParam
: "", szCRLF
);
1441 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1442 while((nBytesSent
< len
) && (nRC
!= SOCKET_ERROR
))
1444 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1448 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1451 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1452 &nBytesSent
, sizeof(DWORD
));
1454 TRACE("Sent %ld bytes\n", nBytesSent
);
1455 return (nRC
!= SOCKET_ERROR
);
1459 /***********************************************************************
1460 * FTP_ReceiveResponse (internal)
1462 * Receive response from server
1465 * Reply code on success
1470 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
1471 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1476 TRACE("socket(%d) \n", nSocket
);
1479 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1484 if (!FTP_GetNextLine(nSocket
, lpszResponse
, &nRecv
))
1487 if (nRecv
>= 3 && lpszResponse
[3] != '-')
1493 lpszResponse
[nRecv
] = '\0';
1494 rc
= atoi(lpszResponse
);
1497 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1498 &nRecv
, sizeof(DWORD
));
1502 TRACE("return %d\n", rc
);
1507 /***********************************************************************
1508 * FTP_SendPassword (internal)
1510 * Send password to ftp server
1517 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
)
1520 BOOL bSuccess
= FALSE
;
1523 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1526 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1527 MAX_REPLY_LEN
, 0, 0, 0);
1530 TRACE("Received reply code %d\n", nResCode
);
1531 /* Login successful... */
1532 if (nResCode
== 230)
1534 /* Command not implemented, superfluous at the server site... */
1535 /* Need account for login... */
1536 else if (nResCode
== 332)
1537 bSuccess
= FTP_SendAccount(lpwfs
);
1539 FTP_SetResponseError(nResCode
);
1543 TRACE("Returning %d\n", bSuccess
);
1548 /***********************************************************************
1549 * FTP_SendAccount (internal)
1558 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
)
1561 BOOL bSuccess
= FALSE
;
1564 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, NOACCOUNT
, 0, 0, 0))
1567 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1568 MAX_REPLY_LEN
, 0, 0, 0);
1572 FTP_SetResponseError(nResCode
);
1579 /***********************************************************************
1580 * FTP_SendStore (internal)
1582 * Send request to upload file to ftp server
1589 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1592 BOOL bSuccess
= FALSE
;
1595 if (!FTP_InitListenSocket(lpwfs
))
1598 if (!FTP_SendType(lpwfs
, dwType
))
1601 if (!FTP_SendPort(lpwfs
))
1604 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
1606 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1607 MAX_REPLY_LEN
, 0, 0, 0);
1610 if (nResCode
== 150)
1613 FTP_SetResponseError(nResCode
);
1617 if (!bSuccess
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1619 close(lpwfs
->lstnSocket
);
1620 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1627 /***********************************************************************
1628 * FTP_InitListenSocket (internal)
1630 * Create a socket to listen for server response
1637 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
)
1639 BOOL bSuccess
= FALSE
;
1640 size_t namelen
= sizeof(struct sockaddr_in
);
1644 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
1645 if (INVALID_SOCKET
== lpwfs
->lstnSocket
)
1647 TRACE("Unable to create listening socket\n");
1651 lpwfs
->lstnSocketAddress
.sin_family
= AF_INET
;
1652 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
1653 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
1654 if (SOCKET_ERROR
== bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)))
1656 TRACE("Unable to bind socket\n");
1660 if (SOCKET_ERROR
== listen(lpwfs
->lstnSocket
, MAX_BACKLOG
))
1662 TRACE("listen failed\n");
1666 if (SOCKET_ERROR
!= getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
))
1670 if (!bSuccess
&& INVALID_SOCKET
== lpwfs
->lstnSocket
)
1672 close(lpwfs
->lstnSocket
);
1673 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1680 /***********************************************************************
1681 * FTP_SendType (internal)
1683 * Tell server type of data being transfered
1690 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
)
1693 CHAR type
[2] = { "I\0" };
1694 BOOL bSuccess
= FALSE
;
1697 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
1700 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
1703 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1704 MAX_REPLY_LEN
, 0, 0, 0)/100;
1710 FTP_SetResponseError(nResCode
);
1718 /***********************************************************************
1719 * FTP_SendPort (internal)
1721 * Tell server which port to use
1728 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
)
1731 CHAR szIPAddress
[64];
1732 BOOL bSuccess
= FALSE
;
1736 sprintf(szIPAddress
, "%d,%d,%d,%d,%d,%d",
1737 lpwfs
->socketAddress
.sin_addr
.s_addr
&0x000000FF,
1738 (lpwfs
->socketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
1739 (lpwfs
->socketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
1740 (lpwfs
->socketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
1741 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
1742 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
1744 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
1747 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1748 MAX_REPLY_LEN
,0, 0, 0);
1751 if (nResCode
== 200)
1754 FTP_SetResponseError(nResCode
);
1762 /***********************************************************************
1763 * FTP_InitDataSocket (internal)
1772 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
)
1774 struct sockaddr_in saddr
;
1775 size_t addrlen
= sizeof(struct sockaddr
);
1778 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
1779 close(lpwfs
->lstnSocket
);
1780 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1782 return *nDataSocket
!= INVALID_SOCKET
;
1786 /***********************************************************************
1787 * FTP_SendData (internal)
1789 * Send data to the server
1796 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
)
1798 BY_HANDLE_FILE_INFORMATION fi
;
1799 DWORD nBytesRead
= 0;
1800 DWORD nBytesSent
= 0;
1801 DWORD nTotalSent
= 0;
1802 DWORD nBytesToSend
, nLen
, nRC
= 1;
1803 time_t s_long_time
, e_long_time
;
1808 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1809 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1811 /* Get the size of the file. */
1812 GetFileInformationByHandle(hFile
, &fi
);
1817 nBytesToSend
= nBytesRead
- nBytesSent
;
1819 if (nBytesToSend
<= 0)
1821 /* Read data from file. */
1823 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
1824 ERR("Failed reading from file\n");
1827 nBytesToSend
= nBytesRead
;
1832 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
1833 DATA_PACKET_SIZE
: nBytesToSend
;
1834 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
1836 if (nRC
!= SOCKET_ERROR
)
1842 /* Do some computation to display the status. */
1844 nSeconds
= e_long_time
- s_long_time
;
1845 if( nSeconds
/ 60 > 0 )
1847 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\t\t\r",
1848 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
1849 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1853 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\t\t\r",
1854 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
1855 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1857 } while (nRC
!= SOCKET_ERROR
);
1859 TRACE("file transfer complete!\n");
1861 if(lpszBuffer
!= NULL
)
1862 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
1868 /***********************************************************************
1869 * FTP_SendRetrieve (internal)
1871 * Send request to retrieve a file
1874 * Number of bytes to be received on success
1878 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1884 if (!FTP_InitListenSocket(lpwfs
))
1887 if (!FTP_SendType(lpwfs
, dwType
))
1890 if (!FTP_SendPort(lpwfs
))
1893 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
1896 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1897 MAX_REPLY_LEN
, 0, 0, 0);
1900 if (nResCode
== 125 || nResCode
== 150)
1902 /* Parse size of data to be retrieved */
1903 INT i
, sizepos
= -1;
1904 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
1905 for (i
= strlen(lpszResponseBuffer
) - 1; i
>= 0; i
--)
1907 if ('(' == lpszResponseBuffer
[i
])
1916 nResult
= atol(&lpszResponseBuffer
[sizepos
+1]);
1917 TRACE("Waiting to receive %ld bytes\n", nResult
);
1923 if (0 == nResult
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1925 close(lpwfs
->lstnSocket
);
1926 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1933 /***********************************************************************
1934 * FTP_RetrieveData (internal)
1936 * Retrieve data from server
1943 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
1945 DWORD nBytesWritten
;
1946 DWORD nBytesReceived
= 0;
1952 if (INVALID_HANDLE_VALUE
== hFile
)
1955 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1956 if (NULL
== lpszBuffer
)
1958 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1962 while (nBytesReceived
< nBytes
&& nRC
!= SOCKET_ERROR
)
1964 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
1965 if (nRC
!= SOCKET_ERROR
)
1967 /* other side closed socket. */
1970 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
1971 nBytesReceived
+= nRC
;
1974 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
1975 nBytesReceived
* 100 / nBytes
);
1978 TRACE("Data transfer complete\n");
1979 if (NULL
!= lpszBuffer
)
1980 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
1983 return (nRC
!= SOCKET_ERROR
);
1987 /***********************************************************************
1988 * FTP_CloseSessionHandle (internal)
1990 * Deallocate session handle
1997 BOOL
FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs
)
1999 if (INVALID_SOCKET
!= lpwfs
->sndSocket
)
2000 close(lpwfs
->sndSocket
);
2002 if (INVALID_SOCKET
!= lpwfs
->lstnSocket
)
2003 close(lpwfs
->lstnSocket
);
2005 if (lpwfs
->lpszPassword
)
2006 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2008 if (lpwfs
->lpszUserName
)
2009 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2011 HeapFree(GetProcessHeap(), 0, lpwfs
);
2017 /***********************************************************************
2018 * FTP_CloseSessionHandle (internal)
2020 * Deallocate session handle
2027 BOOL
FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn
)
2033 for (i
= 0; i
< lpwfn
->size
; i
++)
2035 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2036 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2039 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2040 HeapFree(GetProcessHeap(), 0, lpwfn
);
2046 /***********************************************************************
2047 * FTP_ReceiveFileList (internal)
2049 * Read file list from server
2052 * Handle to file list on success
2056 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
2057 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
)
2060 LPFILEPROPERTIESA lpafp
= NULL
;
2061 LPWININETFINDNEXTA lpwfn
= NULL
;
2065 if (FTP_ParseDirectory(lpwfs
, nSocket
, &lpafp
, &dwSize
))
2067 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2069 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTA
));
2072 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2073 lpwfn
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)lpwfs
;
2074 lpwfn
->hdr
.dwContext
= dwContext
;
2075 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2076 lpwfn
->size
= dwSize
;
2077 lpwfn
->lpafp
= lpafp
;
2081 TRACE("Matched %ld files\n", dwSize
);
2082 return (HINTERNET
)lpwfn
;
2086 /***********************************************************************
2087 * FTP_ConvertFileProp (internal)
2089 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2096 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp
, LPWIN32_FIND_DATAA lpFindFileData
)
2098 BOOL bSuccess
= FALSE
;
2100 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
2104 DWORD access
= mktime(&lpafp
->tmLastModified
);
2106 /* Not all fields are filled in */
2107 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= HIWORD(access
);
2108 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= LOWORD(access
);
2109 lpFindFileData
->nFileSizeHigh
= HIWORD(lpafp
->nSize
);
2110 lpFindFileData
->nFileSizeLow
= LOWORD(lpafp
->nSize
);
2112 if (lpafp
->bIsDirectory
)
2113 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2115 if (lpafp
->lpszName
)
2116 strncpy(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2125 /***********************************************************************
2126 * FTP_ParseDirectory (internal)
2128 * Parse string of directory information
2134 * FIXME: - This function needs serious clea-up
2135 * - We should consider both UNIX and NT list formats
2137 #define MAX_MONTH_LEN 10
2138 #define MIN_LEN_DIR_ENTRY 15
2140 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
)
2143 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2146 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2152 CHAR pszMonth
[MAX_MONTH_LEN
];
2154 BOOL bSuccess
= TRUE
;
2155 DWORD nBufLen
= MAX_REPLY_LEN
;
2156 LPFILEPROPERTIESA curFileProp
= NULL
;
2157 CHAR
* pszLine
= NULL
;
2158 CHAR
* pszToken
= NULL
;
2159 INT nTokenToSkip
= 3;
2167 INT sizeFilePropArray
= 20;
2168 INT indexFilePropArray
= 0;
2172 /* Allocate intial file properties array */
2173 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESA
)*(sizeFilePropArray
));
2180 while ((pszLine
= FTP_GetNextLine(nSocket
, INTERNET_GetResponseBuffer(), &nBufLen
)) != NULL
)
2182 if (sizeFilePropArray
<= indexFilePropArray
)
2184 LPFILEPROPERTIESA tmpafp
;
2186 sizeFilePropArray
*= 2;
2187 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2188 sizeof(FILEPROPERTIESA
)*sizeFilePropArray
);
2198 curFileProp
= &((*lpafp
)[indexFilePropArray
]);
2200 /* First Parse the permissions. */
2201 pszToken
= strtok(pszLine
, " \t" );
2203 /* HACK! If this is not a file listing skip the line */
2204 if (!pszToken
|| 10 != strlen(pszToken
) || nBufLen
<= MIN_LEN_DIR_ENTRY
)
2206 nBufLen
= MAX_REPLY_LEN
;
2210 FTP_ParsePermission(pszToken
, curFileProp
);
2216 pszToken
= strtok( NULL
, " \t" );
2218 } while( nCount
<= nTokenToSkip
);
2220 /* Store the size of the file in the param list. */
2221 TRACE("nSize-> %s\n", pszToken
);
2222 if (pszToken
!= NULL
)
2223 curFileProp
->nSize
= atol(pszToken
);
2225 /* Parse last modified time. */
2233 pszToken
= strtok( NULL
, " \t" );
2234 strncpy(pszMonth
, pszToken
, MAX_MONTH_LEN
);
2235 CharUpperA(pszMonth
);
2236 pszMatch
= strstr(szMonths
, pszMonth
);
2237 if( pszMatch
!= NULL
)
2238 nMonth
= (pszMatch
- szMonths
) / 3;
2240 pszToken
= strtok(NULL
, " \t");
2241 TRACE("nDay -> %s\n", pszToken
);
2242 if (pszToken
!= NULL
)
2243 nDay
= atoi(pszToken
);
2245 pszToken
= strtok(NULL
, " \t");
2246 pszMinutes
= strchr(pszToken
, ':');
2247 if( pszMinutes
!= NULL
)
2250 nMinutes
= atoi(pszMinutes
);
2251 pszHour
= pszMinutes
- 3;
2252 if (pszHour
!= NULL
)
2253 nHour
= atoi(pszHour
);
2255 apTM
= localtime( &aTime
);
2256 nYear
= apTM
->tm_year
;
2260 nYear
= atoi(pszToken
);
2265 curFileProp
->tmLastModified
.tm_sec
= nSeconds
;
2266 curFileProp
->tmLastModified
.tm_min
= nMinutes
;
2267 curFileProp
->tmLastModified
.tm_hour
= nHour
;
2268 curFileProp
->tmLastModified
.tm_mday
= nDay
;
2269 curFileProp
->tmLastModified
.tm_mon
= nMonth
;
2270 curFileProp
->tmLastModified
.tm_year
= nYear
;
2272 pszToken
= strtok(NULL
, " \t");
2273 if(pszToken
!= NULL
)
2275 curFileProp
->lpszName
= strdup(pszToken
);
2276 TRACE(": %s\n", curFileProp
->lpszName
);
2279 nBufLen
= MAX_REPLY_LEN
;
2280 indexFilePropArray
++;
2283 if (bSuccess
&& indexFilePropArray
)
2285 if (indexFilePropArray
< sizeFilePropArray
- 1)
2287 LPFILEPROPERTIESA tmpafp
;
2289 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2290 sizeof(FILEPROPERTIESA
)*indexFilePropArray
);
2294 *dwfp
= indexFilePropArray
;
2298 HeapFree(GetProcessHeap(), 0, *lpafp
);
2299 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2308 /***********************************************************************
2309 * FTP_ParsePermission (internal)
2311 * Parse permission string of directory information
2318 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
)
2320 BOOL bSuccess
= TRUE
;
2321 unsigned short nPermission
= 0;
2326 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
2332 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
2338 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
2341 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
2344 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
2347 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
2350 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
2353 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
2356 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
2359 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
2362 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
2366 }while (nPos
<= nLast
);
2368 lpfp
->permissions
= nPermission
;
2373 /***********************************************************************
2374 * FTP_GetNextLine (internal)
2376 * Parse next line in directory string listing
2379 * Pointer to begining of next line
2384 LPSTR
FTP_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
)
2388 BOOL bSuccess
= FALSE
;
2393 while (nRecv
< *dwBuffer
)
2396 FD_SET(nSocket
, &infd
);
2397 tv
.tv_sec
=RESPONSE_TIMEOUT
;
2400 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
))
2402 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
2404 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
2408 if (lpszBuffer
[nRecv
] == '\n')
2413 if (lpszBuffer
[nRecv
] != '\r')
2418 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
2426 lpszBuffer
[nRecv
] = '\0';
2427 *dwBuffer
= nRecv
- 1;
2428 TRACE(":%d %s\n", nRecv
, lpszBuffer
);
2438 /***********************************************************************
2439 * FTP_SetResponseError (internal)
2441 * Set the appropriate error code for a given response from the server
2446 DWORD
FTP_SetResponseError(DWORD dwResponse
)
2452 case 421: /* Service not available - Server may be shutting down. */
2453 dwCode
= ERROR_INTERNET_TIMEOUT
;
2456 case 425: /* Cannot open data connection. */
2457 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
2460 case 426: /* Connection closed, transer aborted. */
2461 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
2464 case 500: /* Syntax error. Command unrecognized. */
2465 case 501: /* Syntax error. Error in parameters or arguments. */
2466 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
2469 case 530: /* Not logged in. Login incorrect. */
2470 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
2473 case 550: /* File action not taken. File not found or no access. */
2474 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
2477 case 450: /* File action not taken. File may be busy. */
2478 case 451: /* Action aborted. Server error. */
2479 case 452: /* Action not taken. Insufficient storage space on server. */
2480 case 502: /* Command not implemented. */
2481 case 503: /* Bad sequence of command. */
2482 case 504: /* Command not implemented for that parameter. */
2483 case 532: /* Need account for storing files */
2484 case 551: /* Requested action aborted. Page type unknown */
2485 case 552: /* Action aborted. Exceeded storage allocation */
2486 case 553: /* Action not taken. File name not allowed. */
2489 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
2493 INTERNET_SetLastError(dwCode
);