2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
19 #include <sys/types.h>
20 #ifdef HAVE_SYS_SOCKET_H
21 # include <sys/socket.h>
25 #include <netinet/in_systm.h>
26 #ifdef HAVE_NETINET_IH_H
27 # include <netinet/in.h>
29 #include <netinet/in.h>
30 #include <netinet/ip.h>
40 #include "debugtools.h"
43 DEFAULT_DEBUG_CHANNEL(wininet
);
45 #define NOACCOUNT "noaccount"
46 #define DATA_PACKET_SIZE 0x2000
51 /* FTP commands with arguments. */
66 /* FTP commands without arguments. */
74 static const CHAR
*szFtpCommands
[] = {
95 static const CHAR szMonths
[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
97 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
98 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
99 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
100 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
);
101 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
);
102 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
103 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
104 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
);
105 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
);
106 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
);
107 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
);
108 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
);
109 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
);
110 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
);
111 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
);
112 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
);
113 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
);
114 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
115 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
);
116 DWORD
FTP_SetResponseError(DWORD dwResponse
);
118 inline static LPSTR
FTP_strdup( LPCSTR str
)
120 LPSTR ret
= HeapAlloc( GetProcessHeap(), 0, strlen(str
) + 1 );
121 if (ret
) strcpy( ret
, str
);
125 /***********************************************************************
126 * FtpPutFileA (WININET.43)
128 * Uploads a file to the FTP server
135 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
136 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
138 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
139 LPWININETAPPINFOA hIC
= NULL
;
141 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
143 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
147 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
148 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
150 WORKREQUEST workRequest
;
152 workRequest
.asyncall
= FTPPUTFILEA
;
153 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
154 workRequest
.LPSZLOCALFILE
= (DWORD
)FTP_strdup(lpszLocalFile
);
155 workRequest
.LPSZNEWREMOTEFILE
= (DWORD
)FTP_strdup(lpszNewRemoteFile
);
156 workRequest
.DWFLAGS
= dwFlags
;
157 workRequest
.DWCONTEXT
= dwContext
;
159 return INTERNET_AsyncCall(&workRequest
);
163 return FTP_FtpPutFileA(hConnect
, lpszLocalFile
,
164 lpszNewRemoteFile
, dwFlags
, dwContext
);
168 /***********************************************************************
169 * FTP_FtpPutFileA (Internal)
171 * Uploads a file to the FTP server
178 BOOL WINAPI
FTP_FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
179 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
181 HANDLE hFile
= (HANDLE
)NULL
;
182 BOOL bSuccess
= FALSE
;
183 LPWININETAPPINFOA hIC
= NULL
;
184 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
187 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile
, lpszNewRemoteFile
);
188 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
190 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
194 /* Clear any error information */
195 INTERNET_SetLastError(0);
197 /* Open file to be uploaded */
198 if (INVALID_HANDLE_VALUE
==
199 (hFile
= CreateFileA(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
201 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
205 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
206 if (hIC
->lpfnStatusCB
)
207 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
209 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
213 /* Accept connection from ftp server */
214 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
216 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
218 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
219 MAX_REPLY_LEN
,0, 0, 0);
225 FTP_SetResponseError(nResCode
);
231 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
233 INTERNET_ASYNC_RESULT iar
;
235 iar
.dwResult
= (DWORD
)bSuccess
;
236 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
237 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
238 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
248 /***********************************************************************
249 * FtpSetCurrentDirectoryA (WININET.49)
251 * Change the working directory on the FTP server
258 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
260 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
261 LPWININETAPPINFOA hIC
= NULL
;
263 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
265 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
269 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
271 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
272 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
274 WORKREQUEST workRequest
;
276 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYA
;
277 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
278 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
280 return INTERNET_AsyncCall(&workRequest
);
284 return FTP_FtpSetCurrentDirectoryA(hConnect
, lpszDirectory
);
289 /***********************************************************************
290 * FTP_FtpSetCurrentDirectoryA (Internal)
292 * Change the working directory on the FTP server
299 BOOL WINAPI
FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
302 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
303 LPWININETAPPINFOA hIC
= NULL
;
304 DWORD bSuccess
= FALSE
;
306 TRACE("lpszDirectory(%s)\n", lpszDirectory
);
308 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
310 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
314 /* Clear any error information */
315 INTERNET_SetLastError(0);
317 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
318 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
319 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
322 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
323 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
330 FTP_SetResponseError(nResCode
);
334 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
336 INTERNET_ASYNC_RESULT iar
;
338 iar
.dwResult
= (DWORD
)bSuccess
;
339 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
340 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
341 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
347 /***********************************************************************
348 * FtpCreateDirectoryA (WININET.31)
350 * Create new directory on the FTP server
357 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
359 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
360 LPWININETAPPINFOA hIC
= NULL
;
362 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
364 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
368 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
369 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
371 WORKREQUEST workRequest
;
373 workRequest
.asyncall
= FTPCREATEDIRECTORYA
;
374 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
375 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
377 return INTERNET_AsyncCall(&workRequest
);
381 return FTP_FtpCreateDirectoryA(hConnect
, lpszDirectory
);
386 /***********************************************************************
387 * FTP_FtpCreateDirectoryA (Internal)
389 * Create new directory on the FTP server
396 BOOL WINAPI
FTP_FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
399 BOOL bSuccess
= FALSE
;
400 LPWININETAPPINFOA hIC
= NULL
;
401 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
404 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
406 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
410 /* Clear any error information */
411 INTERNET_SetLastError(0);
413 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
416 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
417 MAX_REPLY_LEN
, 0, 0, 0);
423 FTP_SetResponseError(nResCode
);
427 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
428 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
430 INTERNET_ASYNC_RESULT iar
;
432 iar
.dwResult
= (DWORD
)bSuccess
;
433 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
434 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
435 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
442 /***********************************************************************
443 * FtpFindFirstFileA (WININET.35)
445 * Search the specified directory
448 * HINTERNET on success
452 INTERNETAPI HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
453 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
455 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
456 LPWININETAPPINFOA hIC
= NULL
;
458 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
460 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
464 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
465 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
467 WORKREQUEST workRequest
;
469 workRequest
.asyncall
= FTPFINDFIRSTFILEA
;
470 workRequest
.HFTPSESSION
= (DWORD
)hConnect
;
471 workRequest
.LPSZSEARCHFILE
= (DWORD
)FTP_strdup(lpszSearchFile
);
472 workRequest
.LPFINDFILEDATA
= (DWORD
)lpFindFileData
;
473 workRequest
.DWFLAGS
= dwFlags
;
474 workRequest
.DWCONTEXT
= dwContext
;
476 INTERNET_AsyncCall(&workRequest
);
481 return FTP_FtpFindFirstFileA(hConnect
, lpszSearchFile
, lpFindFileData
,
487 /***********************************************************************
488 * FTP_FtpFindFirstFileA (Internal)
490 * Search the specified directory
493 * HINTERNET on success
497 INTERNETAPI HINTERNET WINAPI
FTP_FtpFindFirstFileA(HINTERNET hConnect
,
498 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
501 LPWININETAPPINFOA hIC
= NULL
;
502 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hConnect
;
503 LPWININETFINDNEXTA hFindNext
= NULL
;
507 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
509 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
513 /* Clear any error information */
514 INTERNET_SetLastError(0);
516 if (!FTP_InitListenSocket(lpwfs
))
519 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
522 if (!FTP_SendPort(lpwfs
))
525 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
526 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, lpszSearchFile
,
527 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
530 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
531 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
534 if (nResCode
== 125 || nResCode
== 150)
538 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
540 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpFindFileData
, dwContext
);
542 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
543 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
);
544 if (nResCode
!= 226 && nResCode
!= 250)
545 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
551 FTP_SetResponseError(nResCode
);
555 if (lpwfs
->lstnSocket
!= INVALID_SOCKET
)
556 close(lpwfs
->lstnSocket
);
558 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
560 INTERNET_ASYNC_RESULT iar
;
564 iar
.dwResult
= (DWORD
)hFindNext
;
565 iar
.dwError
= ERROR_SUCCESS
;
566 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
567 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
570 iar
.dwResult
= (DWORD
)hFindNext
;
571 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
572 hIC
->lpfnStatusCB(hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
573 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
576 return (HINTERNET
)hFindNext
;
580 /***********************************************************************
581 * FtpGetCurrentDirectoryA (WININET.37)
583 * Retrieves the current directory
590 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
591 LPDWORD lpdwCurrentDirectory
)
593 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
594 LPWININETAPPINFOA hIC
= NULL
;
596 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
598 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
600 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
604 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
605 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
607 WORKREQUEST workRequest
;
609 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYA
;
610 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
611 workRequest
.LPSZDIRECTORY
= (DWORD
)lpszCurrentDirectory
;
612 workRequest
.LPDWDIRECTORY
= (DWORD
)lpdwCurrentDirectory
;
614 return INTERNET_AsyncCall(&workRequest
);
618 return FTP_FtpGetCurrentDirectoryA(hFtpSession
, lpszCurrentDirectory
,
619 lpdwCurrentDirectory
);
624 /***********************************************************************
625 * FTP_FtpGetCurrentDirectoryA (Internal)
627 * Retrieves the current directory
634 BOOL WINAPI
FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
635 LPDWORD lpdwCurrentDirectory
)
638 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
639 LPWININETAPPINFOA hIC
= NULL
;
640 DWORD bSuccess
= FALSE
;
642 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
644 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
646 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
650 /* Clear any error information */
651 INTERNET_SetLastError(0);
653 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
655 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
656 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
657 hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
))
660 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
661 MAX_REPLY_LEN
, hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
);
664 if (nResCode
== 257) /* Extract directory name */
666 INT firstpos
, lastpos
, len
;
667 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
669 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
671 if ('"' == lpszResponseBuffer
[lastpos
])
680 len
= lastpos
- firstpos
- 1;
681 strncpy(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
682 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
683 *lpdwCurrentDirectory
= len
;
687 FTP_SetResponseError(nResCode
);
691 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
693 INTERNET_ASYNC_RESULT iar
;
695 iar
.dwResult
= (DWORD
)bSuccess
;
696 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
697 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
698 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
701 return (DWORD
) bSuccess
;
704 /***********************************************************************
705 * FtpOpenFileA (WININET.41)
707 * Open a remote file for writing or reading
710 * HINTERNET handle on success
714 INTERNETAPI HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
715 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
718 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
719 LPWININETAPPINFOA hIC
= NULL
;
721 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
723 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
727 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
728 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
730 WORKREQUEST workRequest
;
732 workRequest
.asyncall
= FTPOPENFILEA
;
733 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
734 workRequest
.LPSZFILENAME
= (DWORD
)FTP_strdup(lpszFileName
);
735 workRequest
.FDWACCESS
= fdwAccess
;
736 workRequest
.DWFLAGS
= dwFlags
;
737 workRequest
.DWCONTEXT
= dwContext
;
739 INTERNET_AsyncCall(&workRequest
);
744 return FTP_FtpOpenFileA(hFtpSession
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
749 /***********************************************************************
750 * FTP_FtpOpenFileA (Internal)
752 * Open a remote file for writing or reading
755 * HINTERNET handle on success
759 HINTERNET
FTP_FtpOpenFileA(HINTERNET hFtpSession
,
760 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
764 BOOL bSuccess
= FALSE
;
765 LPWININETFILE hFile
= NULL
;
766 LPWININETAPPINFOA hIC
= NULL
;
767 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
771 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
773 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
777 /* Clear any error information */
778 INTERNET_SetLastError(0);
780 if (GENERIC_READ
== fdwAccess
)
782 /* Set up socket to retrieve data */
783 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
785 else if (GENERIC_WRITE
== fdwAccess
)
787 /* Set up socket to send data */
788 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
791 /* Accept connection from server */
792 if (bSuccess
&& FTP_InitDataSocket(lpwfs
, &nDataSocket
))
794 hFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
795 hFile
->hdr
.htype
= WH_HFILE
;
796 hFile
->hdr
.dwFlags
= dwFlags
;
797 hFile
->hdr
.dwContext
= dwContext
;
798 hFile
->hdr
.lpwhparent
= hFtpSession
;
799 hFile
->nDataSocket
= nDataSocket
;
802 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
803 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
805 INTERNET_ASYNC_RESULT iar
;
809 iar
.dwResult
= (DWORD
)hFile
;
810 iar
.dwError
= ERROR_SUCCESS
;
811 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
812 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
815 iar
.dwResult
= (DWORD
)bSuccess
;
816 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
817 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
818 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
821 return (HINTERNET
)hFile
;
825 /***********************************************************************
826 * FtpGetFileA (WININET.39)
828 * Retrieve file from the FTP server
835 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
836 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
839 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
840 LPWININETAPPINFOA hIC
= NULL
;
842 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
844 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
848 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
849 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
851 WORKREQUEST workRequest
;
853 workRequest
.asyncall
= FTPGETFILEA
;
854 workRequest
.HFTPSESSION
= (DWORD
)hInternet
;
855 workRequest
.LPSZREMOTEFILE
= (DWORD
)FTP_strdup(lpszRemoteFile
);
856 workRequest
.LPSZNEWFILE
= (DWORD
)FTP_strdup(lpszNewFile
);
857 workRequest
.DWLOCALFLAGSATTRIBUTE
= dwLocalFlagsAttribute
;
858 workRequest
.FFAILIFEXISTS
= (DWORD
)fFailIfExists
;
859 workRequest
.DWFLAGS
= dwInternetFlags
;
860 workRequest
.DWCONTEXT
= dwContext
;
862 return INTERNET_AsyncCall(&workRequest
);
866 return FTP_FtpGetFileA(hInternet
, lpszRemoteFile
, lpszNewFile
,
867 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
872 /***********************************************************************
873 * FTP_FtpGetFileA (Internal)
875 * Retrieve file from the FTP server
882 BOOL WINAPI
FTP_FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
883 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
887 BOOL bSuccess
= FALSE
;
889 LPWININETAPPINFOA hIC
= NULL
;
890 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hInternet
;
892 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile
, lpszNewFile
);
893 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
895 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
899 /* Clear any error information */
900 INTERNET_SetLastError(0);
902 /* Ensure we can write to lpszNewfile by opening it */
903 hFile
= CreateFileA(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
904 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
905 if (INVALID_HANDLE_VALUE
== hFile
)
908 /* Set up socket to retrieve data */
909 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
915 /* Accept connection from ftp server */
916 if (FTP_InitDataSocket(lpwfs
, &nDataSocket
))
921 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
922 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
923 MAX_REPLY_LEN
, 0, 0, 0);
929 FTP_SetResponseError(nResCode
);
939 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
940 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
942 INTERNET_ASYNC_RESULT iar
;
944 iar
.dwResult
= (DWORD
)bSuccess
;
945 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
946 hIC
->lpfnStatusCB(hInternet
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
947 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
954 /***********************************************************************
955 * FtpDeleteFileA (WININET.33)
957 * Delete a file on the ftp server
964 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
966 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
967 LPWININETAPPINFOA hIC
= NULL
;
969 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
971 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
975 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
976 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
978 WORKREQUEST workRequest
;
980 workRequest
.asyncall
= FTPRENAMEFILEA
;
981 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
982 workRequest
.LPSZFILENAME
= (DWORD
)FTP_strdup(lpszFileName
);
984 return INTERNET_AsyncCall(&workRequest
);
988 return FTP_FtpDeleteFileA(hFtpSession
, lpszFileName
);
993 /***********************************************************************
994 * FTP_FtpDeleteFileA (Internal)
996 * Delete a file on the ftp server
1003 BOOL
FTP_FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1006 BOOL bSuccess
= FALSE
;
1007 LPWININETAPPINFOA hIC
= NULL
;
1008 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1010 TRACE("0x%08lx\n", (ULONG
) hFtpSession
);
1011 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1013 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1017 /* Clear any error information */
1018 INTERNET_SetLastError(0);
1020 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1023 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1024 MAX_REPLY_LEN
, 0, 0, 0);
1027 if (nResCode
== 250)
1030 FTP_SetResponseError(nResCode
);
1033 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1034 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1036 INTERNET_ASYNC_RESULT iar
;
1038 iar
.dwResult
= (DWORD
)bSuccess
;
1039 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1040 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1041 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1048 /***********************************************************************
1049 * FtpRemoveDirectoryA (WININET.45)
1051 * Remove a directory on the ftp server
1058 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1060 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1061 LPWININETAPPINFOA hIC
= NULL
;
1063 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1065 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1069 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1070 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1072 WORKREQUEST workRequest
;
1074 workRequest
.asyncall
= FTPREMOVEDIRECTORYA
;
1075 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1076 workRequest
.LPSZDIRECTORY
= (DWORD
)FTP_strdup(lpszDirectory
);
1078 return INTERNET_AsyncCall(&workRequest
);
1082 return FTP_FtpRemoveDirectoryA(hFtpSession
, lpszDirectory
);
1087 /***********************************************************************
1088 * FTP_FtpRemoveDirectoryA (Internal)
1090 * Remove a directory on the ftp server
1097 BOOL
FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1100 BOOL bSuccess
= FALSE
;
1101 LPWININETAPPINFOA hIC
= NULL
;
1102 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1105 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1107 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1111 /* Clear any error information */
1112 INTERNET_SetLastError(0);
1114 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1117 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1118 MAX_REPLY_LEN
, 0, 0, 0);
1121 if (nResCode
== 250)
1124 FTP_SetResponseError(nResCode
);
1128 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1129 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1131 INTERNET_ASYNC_RESULT iar
;
1133 iar
.dwResult
= (DWORD
)bSuccess
;
1134 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1135 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1136 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1143 /***********************************************************************
1144 * FtpRenameFileA (WININET.47)
1146 * Rename a file on the ftp server
1153 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1155 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1156 LPWININETAPPINFOA hIC
= NULL
;
1158 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1160 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1164 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1165 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1167 WORKREQUEST workRequest
;
1169 workRequest
.asyncall
= FTPRENAMEFILEA
;
1170 workRequest
.HFTPSESSION
= (DWORD
)hFtpSession
;
1171 workRequest
.LPSZSRCFILE
= (DWORD
)FTP_strdup(lpszSrc
);
1172 workRequest
.LPSZDESTFILE
= (DWORD
)FTP_strdup(lpszDest
);
1174 return INTERNET_AsyncCall(&workRequest
);
1178 return FTP_FtpRenameFileA(hFtpSession
, lpszSrc
, lpszDest
);
1182 /***********************************************************************
1183 * FTP_FtpRenameFileA (Internal)
1185 * Rename a file on the ftp server
1192 BOOL
FTP_FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1195 BOOL bSuccess
= FALSE
;
1196 LPWININETAPPINFOA hIC
= NULL
;
1197 LPWININETFTPSESSIONA lpwfs
= (LPWININETFTPSESSIONA
) hFtpSession
;
1200 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1202 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1206 /* Clear any error information */
1207 INTERNET_SetLastError(0);
1209 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1212 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1213 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1214 if (nResCode
== 350)
1216 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1219 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
,
1220 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1223 if (nResCode
== 250)
1226 FTP_SetResponseError(nResCode
);
1229 hIC
= (LPWININETAPPINFOA
) lpwfs
->hdr
.lpwhparent
;
1230 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1232 INTERNET_ASYNC_RESULT iar
;
1234 iar
.dwResult
= (DWORD
)bSuccess
;
1235 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1236 hIC
->lpfnStatusCB(hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1237 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1244 /***********************************************************************
1245 * FTP_Connect (internal)
1247 * Connect to a ftp server
1250 * HINTERNET a session handle on success
1255 HINTERNET
FTP_Connect(HINTERNET hInternet
, LPCSTR lpszServerName
,
1256 INTERNET_PORT nServerPort
, LPCSTR lpszUserName
,
1257 LPCSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
)
1259 struct sockaddr_in socketAddr
;
1260 struct hostent
*phe
= NULL
;
1261 INT nsocket
= INVALID_SOCKET
, sock_namelen
;
1262 LPWININETAPPINFOA hIC
= NULL
;
1263 BOOL bSuccess
= FALSE
;
1264 LPWININETFTPSESSIONA lpwfs
= NULL
;
1266 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1267 (ULONG
) hInternet
, lpszServerName
,
1268 nServerPort
, lpszUserName
, lpszPassword
);
1270 if (((LPWININETHANDLEHEADER
)hInternet
)->htype
!= WH_HINIT
)
1273 hIC
= (LPWININETAPPINFOA
) hInternet
;
1275 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1277 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME
);
1281 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1282 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1284 if (hIC
->lpfnStatusCB
)
1285 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1286 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1288 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1290 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1294 if (hIC
->lpfnStatusCB
)
1295 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1296 (LPSTR
) lpszServerName
, strlen(lpszServerName
));
1298 if (INVALID_SOCKET
== (nsocket
= socket(AF_INET
,SOCK_STREAM
,0)))
1300 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1304 if (hIC
->lpfnStatusCB
)
1305 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1306 &socketAddr
, sizeof(struct sockaddr_in
));
1308 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1310 ERR("Unable to connect (%s)\n", strerror(errno
));
1311 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1315 TRACE("Connected to server\n");
1316 if (hIC
->lpfnStatusCB
)
1317 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1318 &socketAddr
, sizeof(struct sockaddr_in
));
1320 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA
));
1323 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1327 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1328 lpwfs
->hdr
.dwFlags
= dwFlags
;
1329 lpwfs
->hdr
.dwContext
= dwContext
;
1330 lpwfs
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)hInternet
;
1331 lpwfs
->sndSocket
= nsocket
;
1332 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1333 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1334 lpwfs
->phostent
= phe
;
1336 if (NULL
== lpszUserName
)
1338 lpwfs
->lpszUserName
= FTP_strdup("anonymous");
1339 lpwfs
->lpszPassword
= FTP_strdup("user@server");
1343 lpwfs
->lpszUserName
= FTP_strdup(lpszUserName
);
1344 lpwfs
->lpszPassword
= FTP_strdup(lpszPassword
);
1347 if (FTP_ConnectToHost(lpwfs
))
1349 if (hIC
->lpfnStatusCB
)
1351 INTERNET_ASYNC_RESULT iar
;
1353 iar
.dwResult
= (DWORD
)lpwfs
;
1354 iar
.dwError
= ERROR_SUCCESS
;
1356 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1357 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1359 TRACE("Successfully logged into server\n");
1365 if (!bSuccess
&& INVALID_SOCKET
!= nsocket
)
1368 if (!bSuccess
&& lpwfs
)
1370 HeapFree(GetProcessHeap(), 0, lpwfs
);
1374 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1376 INTERNET_ASYNC_RESULT iar
;
1378 iar
.dwResult
= (DWORD
)lpwfs
;
1379 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1380 hIC
->lpfnStatusCB(hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1381 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1384 return (HINTERNET
) lpwfs
;
1388 /***********************************************************************
1389 * FTP_ConnectHost (internal)
1391 * Connect to a ftp server
1398 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs
)
1401 BOOL bSuccess
= FALSE
;
1404 FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN
, 0, 0, 0);
1406 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1409 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1410 MAX_REPLY_LEN
, 0, 0, 0);
1413 /* Login successful... */
1414 if (nResCode
== 230)
1416 /* User name okay, need password... */
1417 else if (nResCode
== 331)
1418 bSuccess
= FTP_SendPassword(lpwfs
);
1419 /* Need account for login... */
1420 else if (nResCode
== 332)
1421 bSuccess
= FTP_SendAccount(lpwfs
);
1423 FTP_SetResponseError(nResCode
);
1426 TRACE("Returning %d\n", bSuccess
);
1432 /***********************************************************************
1433 * FTP_SendCommand (internal)
1435 * Send command to server
1442 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1443 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1447 DWORD nBytesSent
= 0;
1451 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1454 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1456 bParamHasLen
= lpszParam
&& strlen(lpszParam
) > 0;
1457 len
= (bParamHasLen
? strlen(lpszParam
) : -1) + strlen(szFtpCommands
[ftpCmd
]) +
1459 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1461 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1464 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], bParamHasLen
? " " : "",
1465 bParamHasLen
? lpszParam
: "", szCRLF
);
1467 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1468 while((nBytesSent
< len
) && (nRC
!= SOCKET_ERROR
))
1470 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1474 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1477 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1478 &nBytesSent
, sizeof(DWORD
));
1480 TRACE("Sent %ld bytes\n", nBytesSent
);
1481 return (nRC
!= SOCKET_ERROR
);
1485 /***********************************************************************
1486 * FTP_ReceiveResponse (internal)
1488 * Receive response from server
1491 * Reply code on success
1496 INT
FTP_ReceiveResponse(INT nSocket
, LPSTR lpszResponse
, DWORD dwResponse
,
1497 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1501 char firstprefix
[5];
1502 BOOL multiline
= FALSE
;
1505 TRACE("socket(%d) \n", nSocket
);
1508 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1513 if (!INTERNET_GetNextLine(nSocket
, lpszResponse
, &nRecv
))
1520 if(lpszResponse
[3] != '-')
1523 { /* Start of multiline repsonse. Loop until we get "nnn " */
1525 memcpy(firstprefix
, lpszResponse
, 3);
1526 firstprefix
[3] = ' ';
1527 firstprefix
[4] = '\0';
1532 if(!memcmp(firstprefix
, lpszResponse
, 4))
1540 lpszResponse
[nRecv
] = '\0';
1541 rc
= atoi(lpszResponse
);
1544 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1545 &nRecv
, sizeof(DWORD
));
1549 TRACE("return %d\n", rc
);
1554 /***********************************************************************
1555 * FTP_SendPassword (internal)
1557 * Send password to ftp server
1564 BOOL
FTP_SendPassword(LPWININETFTPSESSIONA lpwfs
)
1567 BOOL bSuccess
= FALSE
;
1570 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1573 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1574 MAX_REPLY_LEN
, 0, 0, 0);
1577 TRACE("Received reply code %d\n", nResCode
);
1578 /* Login successful... */
1579 if (nResCode
== 230)
1581 /* Command not implemented, superfluous at the server site... */
1582 /* Need account for login... */
1583 else if (nResCode
== 332)
1584 bSuccess
= FTP_SendAccount(lpwfs
);
1586 FTP_SetResponseError(nResCode
);
1590 TRACE("Returning %d\n", bSuccess
);
1595 /***********************************************************************
1596 * FTP_SendAccount (internal)
1605 BOOL
FTP_SendAccount(LPWININETFTPSESSIONA lpwfs
)
1608 BOOL bSuccess
= FALSE
;
1611 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, NOACCOUNT
, 0, 0, 0))
1614 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1615 MAX_REPLY_LEN
, 0, 0, 0);
1619 FTP_SetResponseError(nResCode
);
1626 /***********************************************************************
1627 * FTP_SendStore (internal)
1629 * Send request to upload file to ftp server
1636 BOOL
FTP_SendStore(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1639 BOOL bSuccess
= FALSE
;
1642 if (!FTP_InitListenSocket(lpwfs
))
1645 if (!FTP_SendType(lpwfs
, dwType
))
1648 if (!FTP_SendPort(lpwfs
))
1651 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
1653 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1654 MAX_REPLY_LEN
, 0, 0, 0);
1657 if (nResCode
== 150)
1660 FTP_SetResponseError(nResCode
);
1664 if (!bSuccess
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1666 close(lpwfs
->lstnSocket
);
1667 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1674 /***********************************************************************
1675 * FTP_InitListenSocket (internal)
1677 * Create a socket to listen for server response
1684 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs
)
1686 BOOL bSuccess
= FALSE
;
1687 size_t namelen
= sizeof(struct sockaddr_in
);
1691 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
1692 if (INVALID_SOCKET
== lpwfs
->lstnSocket
)
1694 TRACE("Unable to create listening socket\n");
1698 /* We obtain our ip addr from the name of the command channel socket */
1699 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
1701 /* and get the system to assign us a port */
1702 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
1704 if (SOCKET_ERROR
== bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)))
1706 TRACE("Unable to bind socket\n");
1710 if (SOCKET_ERROR
== listen(lpwfs
->lstnSocket
, MAX_BACKLOG
))
1712 TRACE("listen failed\n");
1716 if (SOCKET_ERROR
!= getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
))
1720 if (!bSuccess
&& INVALID_SOCKET
== lpwfs
->lstnSocket
)
1722 close(lpwfs
->lstnSocket
);
1723 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1730 /***********************************************************************
1731 * FTP_SendType (internal)
1733 * Tell server type of data being transfered
1740 BOOL
FTP_SendType(LPWININETFTPSESSIONA lpwfs
, DWORD dwType
)
1743 CHAR type
[2] = { "I\0" };
1744 BOOL bSuccess
= FALSE
;
1747 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
1750 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
1753 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1754 MAX_REPLY_LEN
, 0, 0, 0)/100;
1760 FTP_SetResponseError(nResCode
);
1768 /***********************************************************************
1769 * FTP_SendPort (internal)
1771 * Tell server which port to use
1778 BOOL
FTP_SendPort(LPWININETFTPSESSIONA lpwfs
)
1781 CHAR szIPAddress
[64];
1782 BOOL bSuccess
= FALSE
;
1785 sprintf(szIPAddress
, "%d,%d,%d,%d,%d,%d",
1786 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
1787 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
1788 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
1789 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
1790 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
1791 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
1793 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
1796 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1797 MAX_REPLY_LEN
,0, 0, 0);
1800 if (nResCode
== 200)
1803 FTP_SetResponseError(nResCode
);
1811 /***********************************************************************
1812 * FTP_InitDataSocket (internal)
1821 BOOL
FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs
, LPINT nDataSocket
)
1823 struct sockaddr_in saddr
;
1824 size_t addrlen
= sizeof(struct sockaddr
);
1827 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
1828 close(lpwfs
->lstnSocket
);
1829 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1831 return *nDataSocket
!= INVALID_SOCKET
;
1835 /***********************************************************************
1836 * FTP_SendData (internal)
1838 * Send data to the server
1845 BOOL
FTP_SendData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, HANDLE hFile
)
1847 BY_HANDLE_FILE_INFORMATION fi
;
1848 DWORD nBytesRead
= 0;
1849 DWORD nBytesSent
= 0;
1850 DWORD nTotalSent
= 0;
1851 DWORD nBytesToSend
, nLen
, nRC
= 1;
1852 time_t s_long_time
, e_long_time
;
1857 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1858 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
1860 /* Get the size of the file. */
1861 GetFileInformationByHandle(hFile
, &fi
);
1866 nBytesToSend
= nBytesRead
- nBytesSent
;
1868 if (nBytesToSend
<= 0)
1870 /* Read data from file. */
1872 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
1873 ERR("Failed reading from file\n");
1876 nBytesToSend
= nBytesRead
;
1881 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
1882 DATA_PACKET_SIZE
: nBytesToSend
;
1883 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
1885 if (nRC
!= SOCKET_ERROR
)
1891 /* Do some computation to display the status. */
1893 nSeconds
= e_long_time
- s_long_time
;
1894 if( nSeconds
/ 60 > 0 )
1896 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
1897 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
1898 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1902 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
1903 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
1904 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
1906 } while (nRC
!= SOCKET_ERROR
);
1908 TRACE("file transfer complete!\n");
1910 if(lpszBuffer
!= NULL
)
1911 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
1917 /***********************************************************************
1918 * FTP_SendRetrieve (internal)
1920 * Send request to retrieve a file
1923 * Number of bytes to be received on success
1927 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs
, LPCSTR lpszRemoteFile
, DWORD dwType
)
1933 if (!FTP_InitListenSocket(lpwfs
))
1936 if (!FTP_SendType(lpwfs
, dwType
))
1939 if (!FTP_SendPort(lpwfs
))
1942 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
1945 nResCode
= FTP_ReceiveResponse(lpwfs
->sndSocket
, INTERNET_GetResponseBuffer(),
1946 MAX_REPLY_LEN
, 0, 0, 0);
1949 if (nResCode
== 125 || nResCode
== 150)
1951 /* Parse size of data to be retrieved */
1952 INT i
, sizepos
= -1;
1953 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
1954 for (i
= strlen(lpszResponseBuffer
) - 1; i
>= 0; i
--)
1956 if ('(' == lpszResponseBuffer
[i
])
1965 nResult
= atol(&lpszResponseBuffer
[sizepos
+1]);
1966 TRACE("Waiting to receive %ld bytes\n", nResult
);
1972 if (0 == nResult
&& INVALID_SOCKET
!= lpwfs
->lstnSocket
)
1974 close(lpwfs
->lstnSocket
);
1975 lpwfs
->lstnSocket
= INVALID_SOCKET
;
1982 /***********************************************************************
1983 * FTP_RetrieveData (internal)
1985 * Retrieve data from server
1992 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
1994 DWORD nBytesWritten
;
1995 DWORD nBytesReceived
= 0;
2001 if (INVALID_HANDLE_VALUE
== hFile
)
2004 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2005 if (NULL
== lpszBuffer
)
2007 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2011 while (nBytesReceived
< nBytes
&& nRC
!= SOCKET_ERROR
)
2013 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2014 if (nRC
!= SOCKET_ERROR
)
2016 /* other side closed socket. */
2019 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2020 nBytesReceived
+= nRC
;
2023 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2024 nBytesReceived
* 100 / nBytes
);
2027 TRACE("Data transfer complete\n");
2028 if (NULL
!= lpszBuffer
)
2029 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2032 return (nRC
!= SOCKET_ERROR
);
2036 /***********************************************************************
2037 * FTP_CloseSessionHandle (internal)
2039 * Deallocate session handle
2046 BOOL
FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs
)
2048 if (INVALID_SOCKET
!= lpwfs
->sndSocket
)
2049 close(lpwfs
->sndSocket
);
2051 if (INVALID_SOCKET
!= lpwfs
->lstnSocket
)
2052 close(lpwfs
->lstnSocket
);
2054 if (lpwfs
->lpszPassword
)
2055 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2057 if (lpwfs
->lpszUserName
)
2058 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2060 HeapFree(GetProcessHeap(), 0, lpwfs
);
2066 /***********************************************************************
2067 * FTP_CloseSessionHandle (internal)
2069 * Deallocate session handle
2076 BOOL
FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn
)
2082 for (i
= 0; i
< lpwfn
->size
; i
++)
2084 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2085 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2088 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2089 HeapFree(GetProcessHeap(), 0, lpwfn
);
2095 /***********************************************************************
2096 * FTP_ReceiveFileList (internal)
2098 * Read file list from server
2101 * Handle to file list on success
2105 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs
, INT nSocket
,
2106 LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwContext
)
2109 LPFILEPROPERTIESA lpafp
= NULL
;
2110 LPWININETFINDNEXTA lpwfn
= NULL
;
2114 if (FTP_ParseDirectory(lpwfs
, nSocket
, &lpafp
, &dwSize
))
2116 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2118 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTA
));
2121 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2122 lpwfn
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)lpwfs
;
2123 lpwfn
->hdr
.dwContext
= dwContext
;
2124 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2125 lpwfn
->size
= dwSize
;
2126 lpwfn
->lpafp
= lpafp
;
2130 TRACE("Matched %ld files\n", dwSize
);
2131 return (HINTERNET
)lpwfn
;
2135 /***********************************************************************
2136 * FTP_ConvertFileProp (internal)
2138 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2145 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp
, LPWIN32_FIND_DATAA lpFindFileData
)
2147 BOOL bSuccess
= FALSE
;
2149 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
2153 DWORD access
= mktime(&lpafp
->tmLastModified
);
2155 /* Not all fields are filled in */
2156 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= HIWORD(access
);
2157 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= LOWORD(access
);
2158 lpFindFileData
->nFileSizeHigh
= HIWORD(lpafp
->nSize
);
2159 lpFindFileData
->nFileSizeLow
= LOWORD(lpafp
->nSize
);
2161 if (lpafp
->bIsDirectory
)
2162 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2164 if (lpafp
->lpszName
)
2165 strncpy(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2174 /***********************************************************************
2175 * FTP_ParseDirectory (internal)
2177 * Parse string of directory information
2183 * FIXME: - This function needs serious clea-up
2184 * - We should consider both UNIX and NT list formats
2186 #define MAX_MONTH_LEN 10
2187 #define MIN_LEN_DIR_ENTRY 15
2189 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs
, INT nSocket
, LPFILEPROPERTIESA
*lpafp
, LPDWORD dwfp
)
2192 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2195 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2201 CHAR pszMonth
[MAX_MONTH_LEN
];
2203 BOOL bSuccess
= TRUE
;
2204 DWORD nBufLen
= MAX_REPLY_LEN
;
2205 LPFILEPROPERTIESA curFileProp
= NULL
;
2206 CHAR
* pszLine
= NULL
;
2207 CHAR
* pszToken
= NULL
;
2208 INT nTokenToSkip
= 3;
2216 INT sizeFilePropArray
= 20;
2217 INT indexFilePropArray
= 0;
2221 /* Allocate intial file properties array */
2222 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESA
)*(sizeFilePropArray
));
2229 while ((pszLine
= INTERNET_GetNextLine(nSocket
, INTERNET_GetResponseBuffer(), &nBufLen
)) != NULL
)
2231 if (sizeFilePropArray
<= indexFilePropArray
)
2233 LPFILEPROPERTIESA tmpafp
;
2235 sizeFilePropArray
*= 2;
2236 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2237 sizeof(FILEPROPERTIESA
)*sizeFilePropArray
);
2247 curFileProp
= &((*lpafp
)[indexFilePropArray
]);
2249 /* First Parse the permissions. */
2250 pszToken
= strtok(pszLine
, " \t" );
2252 /* HACK! If this is not a file listing skip the line */
2253 if (!pszToken
|| 10 != strlen(pszToken
) || nBufLen
<= MIN_LEN_DIR_ENTRY
)
2255 nBufLen
= MAX_REPLY_LEN
;
2259 FTP_ParsePermission(pszToken
, curFileProp
);
2265 pszToken
= strtok( NULL
, " \t" );
2267 } while( nCount
<= nTokenToSkip
);
2269 /* Store the size of the file in the param list. */
2270 TRACE("nSize-> %s\n", pszToken
);
2271 if (pszToken
!= NULL
)
2272 curFileProp
->nSize
= atol(pszToken
);
2274 /* Parse last modified time. */
2282 pszToken
= strtok( NULL
, " \t" );
2283 strncpy(pszMonth
, pszToken
, MAX_MONTH_LEN
);
2284 CharUpperA(pszMonth
);
2285 pszMatch
= strstr(szMonths
, pszMonth
);
2286 if( pszMatch
!= NULL
)
2287 nMonth
= (pszMatch
- szMonths
) / 3;
2289 pszToken
= strtok(NULL
, " \t");
2290 TRACE("nDay -> %s\n", pszToken
);
2291 if (pszToken
!= NULL
)
2292 nDay
= atoi(pszToken
);
2294 pszToken
= strtok(NULL
, " \t");
2295 pszMinutes
= strchr(pszToken
, ':');
2296 if( pszMinutes
!= NULL
)
2299 nMinutes
= atoi(pszMinutes
);
2300 pszHour
= pszMinutes
- 3;
2301 if (pszHour
!= NULL
)
2302 nHour
= atoi(pszHour
);
2304 apTM
= localtime( &aTime
);
2305 nYear
= apTM
->tm_year
;
2309 nYear
= atoi(pszToken
);
2314 curFileProp
->tmLastModified
.tm_sec
= nSeconds
;
2315 curFileProp
->tmLastModified
.tm_min
= nMinutes
;
2316 curFileProp
->tmLastModified
.tm_hour
= nHour
;
2317 curFileProp
->tmLastModified
.tm_mday
= nDay
;
2318 curFileProp
->tmLastModified
.tm_mon
= nMonth
;
2319 curFileProp
->tmLastModified
.tm_year
= nYear
;
2321 pszToken
= strtok(NULL
, " \t");
2322 if(pszToken
!= NULL
)
2324 curFileProp
->lpszName
= FTP_strdup(pszToken
);
2325 TRACE(": %s\n", curFileProp
->lpszName
);
2328 nBufLen
= MAX_REPLY_LEN
;
2329 indexFilePropArray
++;
2332 if (bSuccess
&& indexFilePropArray
)
2334 if (indexFilePropArray
< sizeFilePropArray
- 1)
2336 LPFILEPROPERTIESA tmpafp
;
2338 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2339 sizeof(FILEPROPERTIESA
)*indexFilePropArray
);
2343 *dwfp
= indexFilePropArray
;
2347 HeapFree(GetProcessHeap(), 0, *lpafp
);
2348 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2357 /***********************************************************************
2358 * FTP_ParsePermission (internal)
2360 * Parse permission string of directory information
2367 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESA lpfp
)
2369 BOOL bSuccess
= TRUE
;
2370 unsigned short nPermission
= 0;
2375 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
2381 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
2387 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
2390 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
2393 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
2396 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
2399 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
2402 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
2405 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
2408 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
2411 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
2415 }while (nPos
<= nLast
);
2417 lpfp
->permissions
= nPermission
;
2422 /***********************************************************************
2423 * FTP_SetResponseError (internal)
2425 * Set the appropriate error code for a given response from the server
2430 DWORD
FTP_SetResponseError(DWORD dwResponse
)
2436 case 421: /* Service not available - Server may be shutting down. */
2437 dwCode
= ERROR_INTERNET_TIMEOUT
;
2440 case 425: /* Cannot open data connection. */
2441 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
2444 case 426: /* Connection closed, transer aborted. */
2445 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
2448 case 500: /* Syntax error. Command unrecognized. */
2449 case 501: /* Syntax error. Error in parameters or arguments. */
2450 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
2453 case 530: /* Not logged in. Login incorrect. */
2454 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
2457 case 550: /* File action not taken. File not found or no access. */
2458 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
2461 case 450: /* File action not taken. File may be busy. */
2462 case 451: /* Action aborted. Server error. */
2463 case 452: /* Action not taken. Insufficient storage space on server. */
2464 case 502: /* Command not implemented. */
2465 case 503: /* Bad sequence of command. */
2466 case 504: /* Command not implemented for that parameter. */
2467 case 532: /* Need account for storing files */
2468 case 551: /* Requested action aborted. Page type unknown */
2469 case 552: /* Action aborted. Exceeded storage allocation */
2470 case 553: /* Action not taken. File name not allowed. */
2473 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
2477 INTERNET_SetLastError(dwCode
);