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/in_systm.h>
24 #include <netinet/in.h>
25 #include <netinet/ip.h>
35 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(wininet
);
40 #define NOACCOUNT "noaccount"
41 #define DATA_PACKET_SIZE 0x2000
46 /* FTP commands with arguments. */
61 /* FTP commands without arguments. */
69 static const CHAR
*szFtpCommands
[] = {
90 static const CHAR szMonths
[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
92 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
93 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
94 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
95 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
);
96 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
);
97 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
98 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
99 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
100 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
);
101 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
);
102 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
);
103 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
);
104 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
);
105 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
);
106 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
);
107 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
);
108 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
);
109 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
110 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
);
111 DWORD
FTP_SetResponseError(DWORD dwResponse
);
113 inline static LPSTR
FTP_strdup( LPCSTR str
)
115 LPSTR ret
= HeapAlloc( GetProcessHeap(), 0, strlen(str
) + 1 );
116 if (ret
) strcpy( ret
, str
);
120 /***********************************************************************
121 * FtpPutFileA (WININET.43)
123 * Uploads a file to the FTP server
130 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
131 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
133 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
134 LPWININETAPPINFOA hIC
= NULL
;
136 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
138 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
142 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
143 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
145 WORKREQUEST workRequest
;
147 workRequest
.asyncall
= FTPPUTFILEA
;
148 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
149 workRequest
.LPSZLOCALFILE
= (DWORD
)FTP_strdup(lpszLocalFile
);
150 workRequest
.LPSZNEWREMOTEFILE
= (DWORD
)FTP_strdup(lpszNewRemoteFile
);
151 workRequest
.DWFLAGS
= dwFlags
;
152 workRequest
.DWCONTEXT
= dwContext
;
154 return INTERNET_AsyncCall(&workRequest
);
158 return FTP_FtpPutFileA(hConnect
, lpszLocalFile
,
159 lpszNewRemoteFile
, dwFlags
, dwContext
);
163 /***********************************************************************
164 * FTP_FtpPutFileA (Internal)
166 * Uploads a file to the FTP server
173 BOOL WINAPI
FTP_FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
174 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
176 HANDLE hFile
= (HANDLE
)NULL
;
177 BOOL bSuccess
= FALSE
;
178 LPWININETAPPINFOA hIC
= NULL
;
179 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
182 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile
, lpszNewRemoteFile
);
183 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
185 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
189 /* Clear any error information */
190 INTERNET_SetLastError(0);
192 /* Open file to be uploaded */
193 if (INVALID_HANDLE_VALUE
==
194 (hFile
= CreateFileA(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
196 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
200 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
201 if (hIC
->lpfnStatusCB
)
202 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
204 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
208 /* Accept connection from ftp server */
209 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
211 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
213 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
214 MAX_REPLY_LEN
,0, 0, 0);
220 FTP_SetResponseError(nResCode
);
226 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
228 INTERNET_ASYNC_RESULT iar
;
230 iar
.dwResult
= (DWORD
)bSuccess
;
231 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
232 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
233 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
243 /***********************************************************************
244 * FtpSetCurrentDirectoryA (WININET.49)
246 * Change the working directory on the FTP server
253 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
255 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
256 LPWININETAPPINFOA hIC
= NULL
;
258 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
260 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
264 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
266 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
267 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
269 WORKREQUEST workRequest
;
271 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYA
;
272 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
273 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
275 return INTERNET_AsyncCall(&workRequest
);
279 return FTP_FtpSetCurrentDirectoryA(hConnect
, lpszDirectory
);
284 /***********************************************************************
285 * FTP_FtpSetCurrentDirectoryA (Internal)
287 * Change the working directory on the FTP server
294 BOOL WINAPI
FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
297 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
298 LPWININETAPPINFOA hIC
= NULL
;
299 DWORD bSuccess
= FALSE
;
301 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
303 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
305 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
309 /* Clear any error information */
310 INTERNET_SetLastError(0);
312 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
313 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
314 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
317 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
318 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
325 FTP_SetResponseError(nResCode
);
329 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
331 INTERNET_ASYNC_RESULT iar
;
333 iar
.dwResult
= (DWORD
)bSuccess
;
334 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
335 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
336 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
342 /***********************************************************************
343 * FtpCreateDirectoryA (WININET.31)
345 * Create new directory on the FTP server
352 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
354 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
355 LPWININETAPPINFOA hIC
= NULL
;
357 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
359 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
363 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
364 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
366 WORKREQUEST workRequest
;
368 workRequest
.asyncall
= FTPCREATEDIRECTORYA
;
369 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
370 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
372 return INTERNET_AsyncCall(&workRequest
);
376 return FTP_FtpCreateDirectoryA(hConnect
, lpszDirectory
);
381 /***********************************************************************
382 * FTP_FtpCreateDirectoryA (Internal)
384 * Create new directory on the FTP server
391 BOOL WINAPI
FTP_FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
394 BOOL bSuccess
= FALSE
;
395 LPWININETAPPINFOA hIC
= NULL
;
396 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
399 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
401 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
405 /* Clear any error information */
406 INTERNET_SetLastError(0);
408 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
411 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
412 MAX_REPLY_LEN
, 0, 0, 0);
418 FTP_SetResponseError(nResCode
);
422 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
423 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
425 INTERNET_ASYNC_RESULT iar
;
427 iar
.dwResult
= (DWORD
)bSuccess
;
428 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
429 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
430 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
437 /***********************************************************************
438 * FtpFindFirstFileA (WININET.35)
440 * Search the specified directory
443 * HINTERNET on success
447 INTERNETAPI HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
448 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
450 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
451 LPWININETAPPINFOA hIC
= NULL
;
453 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
455 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
459 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
460 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
462 WORKREQUEST workRequest
;
464 workRequest
.asyncall
= FTPFINDFIRSTFILEA
;
465 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
466 workRequest
.LPSZSEARCHFILE
= (DWORD
)FTP_strdup(lpszSearchFile
);
467 workRequest
.LPFINDFILEDATA
= (DWORD
)lpFindFileData
;
468 workRequest
.DWFLAGS
= dwFlags
;
469 workRequest
.DWCONTEXT
= dwContext
;
471 INTERNET_AsyncCall(&workRequest
);
476 return FTP_FtpFindFirstFileA(hConnect
, lpszSearchFile
, lpFindFileData
,
482 /***********************************************************************
483 * FTP_FtpFindFirstFileA (Internal)
485 * Search the specified directory
488 * HINTERNET on success
492 INTERNETAPI HINTERNET WINAPI
FTP_FtpFindFirstFileA(HINTERNET hConnect
,
493 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
496 LPWININETAPPINFOA hIC
= NULL
;
497 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
498 LPWININETFINDNEXTA hFindNext
= NULL
;
502 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
504 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
508 /* Clear any error information */
509 INTERNET_SetLastError(0);
511 if (!FTP_InitListenSocket(lpwfs
))
514 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
517 if (!FTP_SendPort(lpwfs
))
520 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
521 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, lpszSearchFile
,
522 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
525 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
526 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
529 if (nResCode
== 125 || nResCode
== 150)
533 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
535 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpFindFileData
, dwContext
);
537 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
538 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
539 if (nResCode
!= 226 && nResCode
!= 250)
540 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
546 FTP_SetResponseError(nResCode
);
550 if (lpwfs
->lstnSocket
!= INVALID_SOCKET
)
551 close(lpwfs
->lstnSocket
);
553 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
555 INTERNET_ASYNC_RESULT iar
;
559 iar
.dwResult
= (DWORD
)hFindNext
;
560 iar
.dwError
= ERROR_SUCCESS
;
561 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
562 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
565 iar
.dwResult
= (DWORD
)hFindNext
;
566 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
567 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
568 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
571 return (HINTERNET
)hFindNext
;
575 /***********************************************************************
576 * FtpGetCurrentDirectoryA (WININET.37)
578 * Retrieves the current directory
585 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
586 LPDWORD lpdwCurrentDirectory
)
588 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
589 LPWININETAPPINFOA hIC
= NULL
;
591 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
593 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
595 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
599 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
600 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
602 WORKREQUEST workRequest
;
604 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYA
;
605 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
606 workRequest
.LPSZDIRECTORY
= (DWORD
)lpszCurrentDirectory
;
607 workRequest
.LPDWDIRECTORY
= (DWORD
)lpdwCurrentDirectory
;
609 return INTERNET_AsyncCall(&workRequest
);
613 return FTP_FtpGetCurrentDirectoryA(hFtpSession
, lpszCurrentDirectory
,
614 lpdwCurrentDirectory
);
619 /***********************************************************************
620 * FTP_FtpGetCurrentDirectoryA (Internal)
622 * Retrieves the current directory
629 BOOL WINAPI
FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
630 LPDWORD lpdwCurrentDirectory
)
633 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
634 LPWININETAPPINFOA hIC
= NULL
;
635 DWORD bSuccess
= FALSE
;
637 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
639 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
641 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
645 /* Clear any error information */
646 INTERNET_SetLastError(0);
648 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
650 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
651 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
652 hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
))
655 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
656 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
);
659 if (nResCode
== 257) /* Extract directory name */
661 INT firstpos
, lastpos
, len
;
662 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
664 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
666 if ('"' == lpszResponseBuffer
[lastpos
])
675 len
= lastpos
- firstpos
- 1;
676 strncpy(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
677 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
678 *lpdwCurrentDirectory
= len
;
682 FTP_SetResponseError(nResCode
);
686 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
688 INTERNET_ASYNC_RESULT iar
;
690 iar
.dwResult
= (DWORD
)bSuccess
;
691 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
692 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
693 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
696 return (DWORD
) bSuccess
;
699 /***********************************************************************
700 * FtpOpenFileA (WININET.41)
702 * Open a remote file for writing or reading
705 * HINTERNET handle on success
709 INTERNETAPI HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
710 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
713 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
714 LPWININETAPPINFOA hIC
= NULL
;
716 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
718 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
722 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
723 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
725 WORKREQUEST workRequest
;
727 workRequest
.asyncall
= FTPOPENFILEA
;
728 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
729 workRequest
.LPSZFILENAME
= (DWORD
)FTP_strdup(lpszFileName
);
730 workRequest
.FDWACCESS
= fdwAccess
;
731 workRequest
.DWFLAGS
= dwFlags
;
732 workRequest
.DWCONTEXT
= dwContext
;
734 INTERNET_AsyncCall(&workRequest
);
739 return FTP_FtpOpenFileA(hFtpSession
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
744 /***********************************************************************
745 * FTP_FtpOpenFileA (Internal)
747 * Open a remote file for writing or reading
750 * HINTERNET handle on success
754 HINTERNET
FTP_FtpOpenFileA(HINTERNET hFtpSession
,
755 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
759 BOOL bSuccess
= FALSE
;
760 LPWININETFILE hFile
= NULL
;
761 LPWININETAPPINFOA hIC
= NULL
;
762 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
766 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
768 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
772 /* Clear any error information */
773 INTERNET_SetLastError(0);
775 if (GENERIC_READ
== fdwAccess
)
777 /* Set up socket to retrieve data */
778 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
780 else if (GENERIC_WRITE
== fdwAccess
)
782 /* Set up socket to send data */
783 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
786 /* Accept connection from server */
787 if (bSuccess
&& FTP_InitDataSocket(lpwfs
, &nDataSocket
))
789 hFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
790 hFile
->hdr
.htype
= WH_HFILE
;
791 hFile
->hdr
.dwFlags
= dwFlags
;
792 hFile
->hdr
.dwContext
= dwContext
;
793 hFile
->hdr
.lpwhparent
= hFtpSession
;
794 hFile
->nDataSocket
= nDataSocket
;
797 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
798 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
800 INTERNET_ASYNC_RESULT iar
;
804 iar
.dwResult
= (DWORD
)hFile
;
805 iar
.dwError
= ERROR_SUCCESS
;
806 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
807 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
810 iar
.dwResult
= (DWORD
)bSuccess
;
811 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
812 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
813 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
816 return (HINTERNET
)hFile
;
820 /***********************************************************************
821 * FtpGetFileA (WININET.39)
823 * Retrieve file from the FTP server
830 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
831 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
834 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
835 LPWININETAPPINFOA hIC
= NULL
;
837 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
839 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
843 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
844 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
846 WORKREQUEST workRequest
;
848 workRequest
.asyncall
= FTPGETFILEA
;
849 workRequest
.HFTPSESSION
= (DWORD
)hInternet
;
850 workRequest
.LPSZREMOTEFILE
= (DWORD
)FTP_strdup(lpszRemoteFile
);
851 workRequest
.LPSZNEWFILE
= (DWORD
)FTP_strdup(lpszNewFile
);
852 workRequest
.DWLOCALFLAGSATTRIBUTE
= dwLocalFlagsAttribute
;
853 workRequest
.FFAILIFEXISTS
= (DWORD
)fFailIfExists
;
854 workRequest
.DWFLAGS
= dwInternetFlags
;
855 workRequest
.DWCONTEXT
= dwContext
;
857 return INTERNET_AsyncCall(&workRequest
);
861 return FTP_FtpGetFileA(hInternet
, lpszRemoteFile
, lpszNewFile
,
862 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
867 /***********************************************************************
868 * FTP_FtpGetFileA (Internal)
870 * Retrieve file from the FTP server
877 BOOL WINAPI
FTP_FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
878 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
882 BOOL bSuccess
= FALSE
;
884 LPWININETAPPINFOA hIC
= NULL
;
885 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
887 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile
, lpszNewFile
);
888 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
890 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
894 /* Clear any error information */
895 INTERNET_SetLastError(0);
897 /* Ensure we can write to lpszNewfile by opening it */
898 hFile
= CreateFileA(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
899 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
900 if (INVALID_HANDLE_VALUE
== hFile
)
903 /* Set up socket to retrieve data */
904 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
910 /* Accept connection from ftp server */
911 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
916 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
917 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
918 MAX_REPLY_LEN
, 0, 0, 0);
924 FTP_SetResponseError(nResCode
);
934 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
935 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
937 INTERNET_ASYNC_RESULT iar
;
939 iar
.dwResult
= (DWORD
)bSuccess
;
940 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
941 hIC
->lpfnStatusCB(hInternet
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
942 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
949 /***********************************************************************
950 * FtpDeleteFileA (WININET.33)
952 * Delete a file on the ftp server
959 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
961 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
962 LPWININETAPPINFOA hIC
= NULL
;
964 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
966 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
970 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
971 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
973 WORKREQUEST workRequest
;
975 workRequest
.asyncall
= FTPRENAMEFILEA
;
976 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
977 workRequest
.LPSZFILENAME
= (DWORD
)FTP_strdup(lpszFileName
);
979 return INTERNET_AsyncCall(&workRequest
);
983 return FTP_FtpDeleteFileA(hFtpSession
, lpszFileName
);
988 /***********************************************************************
989 * FTP_FtpDeleteFileA (Internal)
991 * Delete a file on the ftp server
998 BOOL
FTP_FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1001 BOOL bSuccess
= FALSE
;
1002 LPWININETAPPINFOA hIC
= NULL
;
1003 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1005 TRACE("0x%08lx\n", (ULONG
) hFtpSession
);
1006 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1008 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1012 /* Clear any error information */
1013 INTERNET_SetLastError(0);
1015 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1018 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1019 MAX_REPLY_LEN
, 0, 0, 0);
1022 if (nResCode
== 250)
1025 FTP_SetResponseError(nResCode
);
1028 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1029 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1031 INTERNET_ASYNC_RESULT iar
;
1033 iar
.dwResult
= (DWORD
)bSuccess
;
1034 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1035 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1036 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1043 /***********************************************************************
1044 * FtpRemoveDirectoryA (WININET.45)
1046 * Remove a directory on the ftp server
1053 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1055 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1056 LPWININETAPPINFOA hIC
= NULL
;
1058 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1060 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1064 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1065 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1067 WORKREQUEST workRequest
;
1069 workRequest
.asyncall
= FTPREMOVEDIRECTORYA
;
1070 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1071 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
1073 return INTERNET_AsyncCall(&workRequest
);
1077 return FTP_FtpRemoveDirectoryA(hFtpSession
, lpszDirectory
);
1082 /***********************************************************************
1083 * FTP_FtpRemoveDirectoryA (Internal)
1085 * Remove a directory on the ftp server
1092 BOOL
FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1095 BOOL bSuccess
= FALSE
;
1096 LPWININETAPPINFOA hIC
= NULL
;
1097 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1100 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1102 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1106 /* Clear any error information */
1107 INTERNET_SetLastError(0);
1109 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1112 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1113 MAX_REPLY_LEN
, 0, 0, 0);
1116 if (nResCode
== 250)
1119 FTP_SetResponseError(nResCode
);
1123 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1124 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1126 INTERNET_ASYNC_RESULT iar
;
1128 iar
.dwResult
= (DWORD
)bSuccess
;
1129 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1130 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1131 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1138 /***********************************************************************
1139 * FtpRenameFileA (WININET.47)
1141 * Rename a file on the ftp server
1148 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1150 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1151 LPWININETAPPINFOA hIC
= NULL
;
1153 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1155 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1159 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1160 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1162 WORKREQUEST workRequest
;
1164 workRequest
.asyncall
= FTPRENAMEFILEA
;
1165 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1166 workRequest
.LPSZSRCFILE
= (DWORD
)FTP_strdup(lpszSrc
);
1167 workRequest
.LPSZDESTFILE
= (DWORD
)FTP_strdup(lpszDest
);
1169 return INTERNET_AsyncCall(&workRequest
);
1173 return FTP_FtpRenameFileA(hFtpSession
, lpszSrc
, lpszDest
);
1177 /***********************************************************************
1178 * FTP_FtpRenameFileA (Internal)
1180 * Rename a file on the ftp server
1187 BOOL
FTP_FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1190 BOOL bSuccess
= FALSE
;
1191 LPWININETAPPINFOA hIC
= NULL
;
1192 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1195 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1197 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1201 /* Clear any error information */
1202 INTERNET_SetLastError(0);
1204 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1207 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1208 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1209 if (nResCode
== 350)
1211 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1214 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1215 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1218 if (nResCode
== 250)
1221 FTP_SetResponseError(nResCode
);
1224 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1225 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1227 INTERNET_ASYNC_RESULT iar
;
1229 iar
.dwResult
= (DWORD
)bSuccess
;
1230 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1231 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1232 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1239 /***********************************************************************
1240 * FTP_Connect (internal)
1242 * Connect to a ftp server
1245 * HINTERNET a session handle on success
1250 HINTERNET
FTP_Connect(HINTERNET hInternet
, LPCSTR lpszServerName
,
1251 INTERNET_PORT nServerPort
, LPCSTR lpszUserName
,
1252 LPCSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
)
1254 struct sockaddr_in socketAddr
;
1255 struct hostent
*phe
= NULL
;
1256 INT nsocket
= INVALID_SOCKET
, sock_namelen
;
1257 LPWININETAPPINFOA hIC
= NULL
;
1258 BOOL bSuccess
= FALSE
;
1259 LPWININETFTPSESSIONA lpwfs
= NULL
;
1261 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1262 (ULONG
) hInternet
, lpszServerName
,
1263 nServerPort
, lpszUserName
, lpszPassword
);
1265 if (((LPWININETHANDLEHEADER
)hInternet
)->htype
!= WH_HINIT
)
1268 hIC
= (LPWININETAPPINFOA
) hInternet
;
1270 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1272 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME
);
1276 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1277 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1279 if (hIC
->lpfnStatusCB
)
1280 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1281 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1283 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1285 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1289 if (hIC
->lpfnStatusCB
)
1290 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1291 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1293 if (INVALID_SOCKET
== (nsocket
= socket(AF_INET
,SOCK_STREAM
,0)))
1295 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1299 if (hIC
->lpfnStatusCB
)
1300 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1301 &socketAddr
, sizeof(struct sockaddr_in
));
1303 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1305 ERR("Unable to connect (%s)\n", strerror(errno
));
1306 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1310 TRACE("Connected to server\n");
1311 if (hIC
->lpfnStatusCB
)
1312 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1313 &socketAddr
, sizeof(struct sockaddr_in
));
1315 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA
));
1318 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1322 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1323 lpwfs
->hdr
.dwFlags
= dwFlags
;
1324 lpwfs
->hdr
.dwContext
= dwContext
;
1325 lpwfs
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)hInternet
;
1326 lpwfs
->sndSocket
= nsocket
;
1327 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1328 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1329 lpwfs
->phostent
= phe
;
1331 if (NULL
== lpszUserName
)
1333 lpwfs
->lpszUserName
= FTP_strdup("anonymous");
1334 lpwfs
->lpszPassword
= FTP_strdup("user@server");
1338 lpwfs
->lpszUserName
= FTP_strdup(lpszUserName
);
1339 lpwfs
->lpszPassword
= FTP_strdup(lpszPassword
);
1342 if (FTP_ConnectToHost(lpwfs
))
1344 if (hIC
->lpfnStatusCB
)
1346 INTERNET_ASYNC_RESULT iar
;
1348 iar
.dwResult
= (DWORD
)lpwfs
;
1349 iar
.dwError
= ERROR_SUCCESS
;
1351 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1352 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1354 TRACE("Successfully logged into server\n");
1360 if (!bSuccess
&& INVALID_SOCKET
!= nsocket
)
1363 if (!bSuccess
&& lpwfs
)
1365 HeapFree(GetProcessHeap(), 0, lpwfs
);
1369 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1371 INTERNET_ASYNC_RESULT iar
;
1373 iar
.dwResult
= (DWORD
)lpwfs
;
1374 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1375 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1376 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1379 return (HINTERNET
) lpwfs
;
1383 /***********************************************************************
1384 * FTP_ConnectHost (internal)
1386 * Connect to a ftp server
1393 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
)
1396 BOOL bSuccess
= FALSE
;
1399 FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1401 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1404 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1405 MAX_REPLY_LEN
, 0, 0, 0);
1408 /* Login successful... */
1409 if (nResCode
== 230)
1411 /* User name okay, need password... */
1412 else if (nResCode
== 331)
1413 bSuccess
= FTP_SendPassword(lpwfs
);
1414 /* Need account for login... */
1415 else if (nResCode
== 332)
1416 bSuccess
= FTP_SendAccount(lpwfs
);
1418 FTP_SetResponseError(nResCode
);
1421 TRACE("Returning %d\n", bSuccess
);
1427 /***********************************************************************
1428 * FTP_SendCommand (internal)
1430 * Send command to server
1437 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1438 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1442 DWORD nBytesSent
= 0;
1446 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1449 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1451 bParamHasLen
= lpszParam
&& strlen(lpszParam
) > 0;
1452 len
= (bParamHasLen
? strlen(lpszParam
) : -1) + strlen(szFtpCommands
[ftpCmd
]) +
1454 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1456 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1459 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], bParamHasLen
? " " : "",
1460 bParamHasLen
? lpszParam
: "", szCRLF
);
1462 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1463 while((nBytesSent
< len
) && (nRC
!= SOCKET_ERROR
))
1465 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1469 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1472 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1473 &nBytesSent
, sizeof(DWORD
));
1475 TRACE("Sent %ld bytes\n", nBytesSent
);
1476 return (nRC
!= SOCKET_ERROR
);
1480 /***********************************************************************
1481 * FTP_ReceiveResponse (internal)
1483 * Receive response from server
1486 * Reply code on success
1491 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
1492 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1496 char firstprefix
[5];
1497 BOOL multiline
= FALSE
;
1500 TRACE("socket(%d) \n", nSocket
);
1503 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1508 if (!INTERNET_GetNextLine(nSocket
, lpszResponse
, &nRecv
))
1515 if(lpszResponse
[3] != '-')
1518 { /* Start of multiline repsonse. Loop until we get "nnn " */
1520 memcpy(firstprefix
, lpszResponse
, 3);
1521 firstprefix
[3] = ' ';
1522 firstprefix
[4] = '\0';
1527 if(!memcmp(firstprefix
, lpszResponse
, 4))
1535 lpszResponse
[nRecv
] = '\0';
1536 rc
= atoi(lpszResponse
);
1539 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1540 &nRecv
, sizeof(DWORD
));
1544 TRACE("return %d\n", rc
);
1549 /***********************************************************************
1550 * FTP_SendPassword (internal)
1552 * Send password to ftp server
1559 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
)
1562 BOOL bSuccess
= FALSE
;
1565 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1568 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1569 MAX_REPLY_LEN
, 0, 0, 0);
1572 TRACE("Received reply code %d\n", nResCode
);
1573 /* Login successful... */
1574 if (nResCode
== 230)
1576 /* Command not implemented, superfluous at the server site... */
1577 /* Need account for login... */
1578 else if (nResCode
== 332)
1579 bSuccess
= FTP_SendAccount(lpwfs
);
1581 FTP_SetResponseError(nResCode
);
1585 TRACE("Returning %d\n", bSuccess
);
1590 /***********************************************************************
1591 * FTP_SendAccount (internal)
1600 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
)
1603 BOOL bSuccess
= FALSE
;
1606 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, NOACCOUNT
, 0, 0, 0))
1609 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1610 MAX_REPLY_LEN
, 0, 0, 0);
1614 FTP_SetResponseError(nResCode
);
1621 /***********************************************************************
1622 * FTP_SendStore (internal)
1624 * Send request to upload file to ftp server
1631 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1634 BOOL bSuccess
= FALSE
;
1637 if (!FTP_InitListenSocket(lpwfs
))
1640 if (!FTP_SendType(lpwfs
, dwType
))
1643 if (!FTP_SendPort(lpwfs
))
1646 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
1648 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1649 MAX_REPLY_LEN
, 0, 0, 0);
1652 if (nResCode
== 150)
1655 FTP_SetResponseError(nResCode
);
1659 if (!bSuccess
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1661 close(lpwfs
->lstnSocket
);
1662 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1669 /***********************************************************************
1670 * FTP_InitListenSocket (internal)
1672 * Create a socket to listen for server response
1679 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
)
1681 BOOL bSuccess
= FALSE
;
1682 size_t namelen
= sizeof(struct sockaddr_in
);
1686 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
1687 if (INVALID_SOCKET
== lpwfs
->lstnSocket
)
1689 TRACE("Unable to create listening socket\n");
1693 /* We obtain our ip addr from the name of the command channel socket */
1694 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
1696 /* and get the system to assign us a port */
1697 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
1699 if (SOCKET_ERROR
== bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)))
1701 TRACE("Unable to bind socket\n");
1705 if (SOCKET_ERROR
== listen(lpwfs
->lstnSocket
, MAX_BACKLOG
))
1707 TRACE("listen failed\n");
1711 if (SOCKET_ERROR
!= getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
))
1715 if (!bSuccess
&& INVALID_SOCKET
== lpwfs
->lstnSocket
)
1717 close(lpwfs
->lstnSocket
);
1718 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1725 /***********************************************************************
1726 * FTP_SendType (internal)
1728 * Tell server type of data being transfered
1735 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
)
1738 CHAR type
[2] = { "I\0" };
1739 BOOL bSuccess
= FALSE
;
1742 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
1745 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
1748 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1749 MAX_REPLY_LEN
, 0, 0, 0)/100;
1755 FTP_SetResponseError(nResCode
);
1763 /***********************************************************************
1764 * FTP_SendPort (internal)
1766 * Tell server which port to use
1773 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
)
1776 CHAR szIPAddress
[64];
1777 BOOL bSuccess
= FALSE
;
1780 sprintf(szIPAddress
, "%d,%d,%d,%d,%d,%d",
1781 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
1782 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
1783 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
1784 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
1785 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
1786 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
1788 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
1791 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1792 MAX_REPLY_LEN
,0, 0, 0);
1795 if (nResCode
== 200)
1798 FTP_SetResponseError(nResCode
);
1806 /***********************************************************************
1807 * FTP_InitDataSocket (internal)
1816 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
)
1818 struct sockaddr_in saddr
;
1819 size_t addrlen
= sizeof(struct sockaddr
);
1822 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
1823 close(lpwfs
->lstnSocket
);
1824 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1826 return *nDataSocket
!= INVALID_SOCKET
;
1830 /***********************************************************************
1831 * FTP_SendData (internal)
1833 * Send data to the server
1840 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
)
1842 BY_HANDLE_FILE_INFORMATION fi
;
1843 DWORD nBytesRead
= 0;
1844 DWORD nBytesSent
= 0;
1845 DWORD nTotalSent
= 0;
1846 DWORD nBytesToSend
, nLen
, nRC
= 1;
1847 time_t s_long_time
, e_long_time
;
1852 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1853 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1855 /* Get the size of the file. */
1856 GetFileInformationByHandle(hFile
, &fi
);
1861 nBytesToSend
= nBytesRead
- nBytesSent
;
1863 if (nBytesToSend
<= 0)
1865 /* Read data from file. */
1867 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
1868 ERR("Failed reading from file\n");
1871 nBytesToSend
= nBytesRead
;
1876 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
1877 DATA_PACKET_SIZE
: nBytesToSend
;
1878 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
1880 if (nRC
!= SOCKET_ERROR
)
1886 /* Do some computation to display the status. */
1888 nSeconds
= e_long_time
- s_long_time
;
1889 if( nSeconds
/ 60 > 0 )
1891 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
1892 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
1893 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1897 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
1898 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
1899 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1901 } while (nRC
!= SOCKET_ERROR
);
1903 TRACE("file transfer complete!\n");
1905 if(lpszBuffer
!= NULL
)
1906 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
1912 /***********************************************************************
1913 * FTP_SendRetrieve (internal)
1915 * Send request to retrieve a file
1918 * Number of bytes to be received on success
1922 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1928 if (!FTP_InitListenSocket(lpwfs
))
1931 if (!FTP_SendType(lpwfs
, dwType
))
1934 if (!FTP_SendPort(lpwfs
))
1937 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
1940 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1941 MAX_REPLY_LEN
, 0, 0, 0);
1944 if (nResCode
== 125 || nResCode
== 150)
1946 /* Parse size of data to be retrieved */
1947 INT i
, sizepos
= -1;
1948 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
1949 for (i
= strlen(lpszResponseBuffer
) - 1; i
>= 0; i
--)
1951 if ('(' == lpszResponseBuffer
[i
])
1960 nResult
= atol(&lpszResponseBuffer
[sizepos
+1]);
1961 TRACE("Waiting to receive %ld bytes\n", nResult
);
1967 if (0 == nResult
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1969 close(lpwfs
->lstnSocket
);
1970 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1977 /***********************************************************************
1978 * FTP_RetrieveData (internal)
1980 * Retrieve data from server
1987 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
1989 DWORD nBytesWritten
;
1990 DWORD nBytesReceived
= 0;
1996 if (INVALID_HANDLE_VALUE
== hFile
)
1999 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2000 if (NULL
== lpszBuffer
)
2002 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2006 while (nBytesReceived
< nBytes
&& nRC
!= SOCKET_ERROR
)
2008 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2009 if (nRC
!= SOCKET_ERROR
)
2011 /* other side closed socket. */
2014 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2015 nBytesReceived
+= nRC
;
2018 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2019 nBytesReceived
* 100 / nBytes
);
2022 TRACE("Data transfer complete\n");
2023 if (NULL
!= lpszBuffer
)
2024 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2027 return (nRC
!= SOCKET_ERROR
);
2031 /***********************************************************************
2032 * FTP_CloseSessionHandle (internal)
2034 * Deallocate session handle
2041 BOOL
FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs
)
2043 if (INVALID_SOCKET
!= lpwfs
->sndSocket
)
2044 close(lpwfs
->sndSocket
);
2046 if (INVALID_SOCKET
!= lpwfs
->lstnSocket
)
2047 close(lpwfs
->lstnSocket
);
2049 if (lpwfs
->lpszPassword
)
2050 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2052 if (lpwfs
->lpszUserName
)
2053 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2055 HeapFree(GetProcessHeap(), 0, lpwfs
);
2061 /***********************************************************************
2062 * FTP_CloseSessionHandle (internal)
2064 * Deallocate session handle
2071 BOOL
FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn
)
2077 for (i
= 0; i
< lpwfn
->size
; i
++)
2079 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2080 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2083 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2084 HeapFree(GetProcessHeap(), 0, lpwfn
);
2090 /***********************************************************************
2091 * FTP_ReceiveFileList (internal)
2093 * Read file list from server
2096 * Handle to file list on success
2100 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
2101 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
)
2104 LPFILEPROPERTIESA lpafp
= NULL
;
2105 LPWININETFINDNEXTA lpwfn
= NULL
;
2109 if (FTP_ParseDirectory(lpwfs
, nSocket
, &lpafp
, &dwSize
))
2111 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2113 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTA
));
2116 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2117 lpwfn
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)lpwfs
;
2118 lpwfn
->hdr
.dwContext
= dwContext
;
2119 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2120 lpwfn
->size
= dwSize
;
2121 lpwfn
->lpafp
= lpafp
;
2125 TRACE("Matched %ld files\n", dwSize
);
2126 return (HINTERNET
)lpwfn
;
2130 /***********************************************************************
2131 * FTP_ConvertFileProp (internal)
2133 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2140 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp
, LPWIN32_FIND_DATAA lpFindFileData
)
2142 BOOL bSuccess
= FALSE
;
2144 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
2148 DWORD access
= mktime(&lpafp
->tmLastModified
);
2150 /* Not all fields are filled in */
2151 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= HIWORD(access
);
2152 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= LOWORD(access
);
2153 lpFindFileData
->nFileSizeHigh
= HIWORD(lpafp
->nSize
);
2154 lpFindFileData
->nFileSizeLow
= LOWORD(lpafp
->nSize
);
2156 if (lpafp
->bIsDirectory
)
2157 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2159 if (lpafp
->lpszName
)
2160 strncpy(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2169 /***********************************************************************
2170 * FTP_ParseDirectory (internal)
2172 * Parse string of directory information
2178 * FIXME: - This function needs serious clea-up
2179 * - We should consider both UNIX and NT list formats
2181 #define MAX_MONTH_LEN 10
2182 #define MIN_LEN_DIR_ENTRY 15
2184 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
)
2187 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2190 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2196 CHAR pszMonth
[MAX_MONTH_LEN
];
2198 BOOL bSuccess
= TRUE
;
2199 DWORD nBufLen
= MAX_REPLY_LEN
;
2200 LPFILEPROPERTIESA curFileProp
= NULL
;
2201 CHAR
* pszLine
= NULL
;
2202 CHAR
* pszToken
= NULL
;
2203 INT nTokenToSkip
= 3;
2211 INT sizeFilePropArray
= 20;
2212 INT indexFilePropArray
= 0;
2216 /* Allocate intial file properties array */
2217 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESA
)*(sizeFilePropArray
));
2224 while ((pszLine
= INTERNET_GetNextLine(nSocket
, INTERNET_GetResponseBuffer(), &nBufLen
)) != NULL
)
2226 if (sizeFilePropArray
<= indexFilePropArray
)
2228 LPFILEPROPERTIESA tmpafp
;
2230 sizeFilePropArray
*= 2;
2231 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2232 sizeof(FILEPROPERTIESA
)*sizeFilePropArray
);
2242 curFileProp
= &((*lpafp
)[indexFilePropArray
]);
2244 /* First Parse the permissions. */
2245 pszToken
= strtok(pszLine
, " \t" );
2247 /* HACK! If this is not a file listing skip the line */
2248 if (!pszToken
|| 10 != strlen(pszToken
) || nBufLen
<= MIN_LEN_DIR_ENTRY
)
2250 nBufLen
= MAX_REPLY_LEN
;
2254 FTP_ParsePermission(pszToken
, curFileProp
);
2260 pszToken
= strtok( NULL
, " \t" );
2262 } while( nCount
<= nTokenToSkip
);
2264 /* Store the size of the file in the param list. */
2265 TRACE("nSize-> %s\n", pszToken
);
2266 if (pszToken
!= NULL
)
2267 curFileProp
->nSize
= atol(pszToken
);
2269 /* Parse last modified time. */
2277 pszToken
= strtok( NULL
, " \t" );
2278 strncpy(pszMonth
, pszToken
, MAX_MONTH_LEN
);
2279 CharUpperA(pszMonth
);
2280 pszMatch
= strstr(szMonths
, pszMonth
);
2281 if( pszMatch
!= NULL
)
2282 nMonth
= (pszMatch
- szMonths
) / 3;
2284 pszToken
= strtok(NULL
, " \t");
2285 TRACE("nDay -> %s\n", pszToken
);
2286 if (pszToken
!= NULL
)
2287 nDay
= atoi(pszToken
);
2289 pszToken
= strtok(NULL
, " \t");
2290 pszMinutes
= strchr(pszToken
, ':');
2291 if( pszMinutes
!= NULL
)
2294 nMinutes
= atoi(pszMinutes
);
2295 pszHour
= pszMinutes
- 3;
2296 if (pszHour
!= NULL
)
2297 nHour
= atoi(pszHour
);
2299 apTM
= localtime( &aTime
);
2300 nYear
= apTM
->tm_year
;
2304 nYear
= atoi(pszToken
);
2309 curFileProp
->tmLastModified
.tm_sec
= nSeconds
;
2310 curFileProp
->tmLastModified
.tm_min
= nMinutes
;
2311 curFileProp
->tmLastModified
.tm_hour
= nHour
;
2312 curFileProp
->tmLastModified
.tm_mday
= nDay
;
2313 curFileProp
->tmLastModified
.tm_mon
= nMonth
;
2314 curFileProp
->tmLastModified
.tm_year
= nYear
;
2316 pszToken
= strtok(NULL
, " \t");
2317 if(pszToken
!= NULL
)
2319 curFileProp
->lpszName
= FTP_strdup(pszToken
);
2320 TRACE(": %s\n", curFileProp
->lpszName
);
2323 nBufLen
= MAX_REPLY_LEN
;
2324 indexFilePropArray
++;
2327 if (bSuccess
&& indexFilePropArray
)
2329 if (indexFilePropArray
< sizeFilePropArray
- 1)
2331 LPFILEPROPERTIESA tmpafp
;
2333 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2334 sizeof(FILEPROPERTIESA
)*indexFilePropArray
);
2338 *dwfp
= indexFilePropArray
;
2342 HeapFree(GetProcessHeap(), 0, *lpafp
);
2343 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2352 /***********************************************************************
2353 * FTP_ParsePermission (internal)
2355 * Parse permission string of directory information
2362 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
)
2364 BOOL bSuccess
= TRUE
;
2365 unsigned short nPermission
= 0;
2370 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
2376 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
2382 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
2385 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
2388 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
2391 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
2394 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
2397 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
2400 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
2403 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
2406 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
2410 }while (nPos
<= nLast
);
2412 lpfp
->permissions
= nPermission
;
2417 /***********************************************************************
2418 * FTP_SetResponseError (internal)
2420 * Set the appropriate error code for a given response from the server
2425 DWORD
FTP_SetResponseError(DWORD dwResponse
)
2431 case 421: /* Service not available - Server may be shutting down. */
2432 dwCode
= ERROR_INTERNET_TIMEOUT
;
2435 case 425: /* Cannot open data connection. */
2436 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
2439 case 426: /* Connection closed, transer aborted. */
2440 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
2443 case 500: /* Syntax error. Command unrecognized. */
2444 case 501: /* Syntax error. Error in parameters or arguments. */
2445 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
2448 case 530: /* Not logged in. Login incorrect. */
2449 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
2452 case 550: /* File action not taken. File not found or no access. */
2453 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
2456 case 450: /* File action not taken. File may be busy. */
2457 case 451: /* Action aborted. Server error. */
2458 case 452: /* Action not taken. Insufficient storage space on server. */
2459 case 502: /* Command not implemented. */
2460 case 503: /* Bad sequence of command. */
2461 case 504: /* Command not implemented for that parameter. */
2462 case 532: /* Need account for storing files */
2463 case 551: /* Requested action aborted. Page type unknown */
2464 case 552: /* Action aborted. Exceeded storage allocation */
2465 case 553: /* Action not taken. File name not allowed. */
2468 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
2472 INTERNET_SetLastError(dwCode
);