#DEFINE ERROR_FTP_TRANSFER_IN_PROGRESS 12110 #DEFINE INTERNET_OPEN_TYPE_DIRECT 1 #DEFINE INTERNET_SERVICE_FTP 1 #DEFINE INTERNET_INVALID_PORT_NUMBER 0 DO declare LOCAL oFtp * replace Init parameters with valid host, user and password * for a FTP server oFtp = CREATEOBJECT("TFtpDir",; "ftp.???.???", "anonymous", "ano@nymous.com") IF TYPE("oFtp") = "O" oFtp.ScanFiles ENDIF * end of main DEFINE CLASS TFtpDir As Custom hInternet=0 hConnect=0 PROCEDURE Init(lcHost, lcUser, lcPwd) THIS.hInternet = InternetOpen("VfpFtp", INTERNET_OPEN_TYPE_DIRECT, 0,0,0) IF THIS.hInternet <> 0 THIS.hConnect = InternetConnect(THIS.hInternet, lcHost,; INTERNET_INVALID_PORT_NUMBER, lcUser, lcPwd,; INTERNET_SERVICE_FTP, 0, 0) ENDIF IF THIS.hConnect = 0 RETURN .F. ENDIF PROCEDURE Destroy InternetCloseHandle(THIS.hConnect) InternetCloseHandle(THIS.hInternet) PROCEDURE ScanFiles THIS.EnumFiles WITH THIS DO WHILE .T. lnResult = .NextNode() DO CASE CASE lnResult = 0 LOOP CASE lnResult = 1 .EnumFiles CASE lnResult = -1 EXIT ENDCASE ENDDO ENDWITH FUNCTION NextNode * returns next unprocessed remote folder SELECT csResult LOCATE ALL FOR Not processed IF FOUND() IF FtpSetCurrentDirectory(THIS.hConnect, ALLTRIM(csResult.fpath)) <> 1 REPLACE processed WITH .T., accesserr WITH .T. RETURN 0 ELSE RETURN 1 ENDIF ELSE RETURN -1 ENDIF PROTECTED FUNCTION GetCurrentDir DECLARE INTEGER FtpGetCurrentDirectory IN wininet; INTEGER hFtpSession, STRING @lpszDir, INTEGER @lpdwCurDir LOCAL lcDirectory, lnLen, lnResult lcDirectory = SPACE(250) lnLen = Len(lcDirectory) lnResult = FtpGetCurrentDirectory(THIS.hConnect, @lcDirectory, @lnLen) RETURN Iif(lnResult=1, LEFT(lcDirectory, lnLen), "#error#") PROCEDURE EnumFiles #DEFINE FILE_ATTR_DIR 16 #DEFINE MAX_PATH 260 #DEFINE MAX_DWORD 0xffffffff + 1 #DEFINE FIND_DATA_SIZE 318 #DEFINE INTERNET_FLAG_NEED_FILE 16 LOCAL lcFPath lcFPath = THIS.GetCurrentDir() IF Not USED("csResult") CREATE CURSOR csResult (; fpath C(250),; fileattr I,; filecount I,; dircount I,; filesize N(12),; isfile L,; processed L,; accesserr L ) INSERT INTO csResult VALUES (; lcFPath, 0,0,0,0, .F., .F., .F.) ENDIF ? lcFPath LOCAL hFind, lcFBuff, lnFileattr, lcFilename, lnFileCount, lnDirCount,; lnFileSize, lProcessed, lIsFile STORE 0 TO lnDirCount, lnFileCount, lnFileSize lcFBuff = Repli(Chr(0), FIND_DATA_SIZE) hFind = FtpFindFirstFile(THIS.hConnect, lcFPath + "/*.*",; @lcFBuff, INTERNET_FLAG_NEED_FILE, 0) IF hFind <> 0 DO WHILE .T. lcFilename = SUBSTR(lcFBuff, 45,MAX_PATH) lcFilename = Left(lcFilename, AT(Chr(0),lcFilename)-1) lnFileattr = buf2dword(SUBSTR(lcFBuff, 1,4)) lnFileSize = buf2dword(SUBSTR(lcFBuff, 29,4)) * MAX_DWORD +; buf2dword(SUBSTR(lcFBuff, 33,4)) IF BitAnd(lnFileattr, FILE_ATTR_DIR) = FILE_ATTR_DIR * for a directory lnDirCount = lnDirCount + 1 lProcessed = (lcFilename==".." Or lcFilename==".") lIsFile = .F. ELSE * for a regular file lnFileCount = lnFileCount + 1 lProcessed = .T. lIsFile = .T. ENDIF lcFullpath = lcFPath + "/" + lcFilename lcFullpath = STRTRAN(lcFullpath, "//", "/") INSERT INTO csResult VALUES (lcFullpath,; lnFileattr, 0, 0, lnFilesize, lIsFile, lProcessed, .F.) IF InternetFindNextFile(hFind, @lcFBuff) = 0 EXIT ENDIF ENDDO ENDIF UPDATE csResult SET dircount = m.lnDirCount,; filecount = m.lnFileCount, filesize = m.lnFileSize,; processed = .T.; WHERE fpath == lcFPath = InternetCloseHandle(hFind) ENDDEFINE FUNCTION buf2dword(cBuffer) RETURN Asc(SUBSTR(cBuffer, 1,1)) + ; BitLShift(Asc(SUBSTR(cBuffer, 2,1)), 8) +; BitLShift(Asc(SUBSTR(cBuffer, 3,1)), 16) +; BitLShift(Asc(SUBSTR(cBuffer, 4,1)), 24) PROCEDURE declare DECLARE INTEGER InternetCloseHandle IN wininet INTEGER hInet DECLARE INTEGER InternetOpen IN wininet; STRING sAgent, INTEGER lAccessType, STRING sProxyName,; STRING sProxyBypass, STRING lFlags DECLARE INTEGER InternetConnect IN wininet; INTEGER hInternetSession, STRING sServerName, INTEGER nServerPort,; STRING sUsername, STRING sPassword, INTEGER lService,; INTEGER lFlags, INTEGER lContext DECLARE INTEGER FtpFindFirstFile IN wininet; INTEGER hFtpSession, STRING lpszSearchFile,; STRING @lpFindFileData, INTEGER dwFlags, INTEGER dwContent DECLARE INTEGER InternetFindNextFile IN wininet; INTEGER hFind, STRING @lpvFindData DECLARE INTEGER FtpSetCurrentDirectory IN wininet; INTEGER hFtpSession, STRING @lpszDirectory