Jump to content

FTP.au3


w0uter
 Share

Recommended Posts

Here is my code snippet (simplified from my bigger FTP app).

I started to play with _FtpFileFindFirst and _FtpFileFindNext but there was problems to get data in correct data format

- time and size are as 64 bit number stored in two 32 bit places and I didn't know how to convert them.

Then I havent time, so it stays unfinished ...

So you can take it as start point ...

#include <GuiConstants.au3>
#include <ftp.au3>

Dim $Handle, $DllRect

$dllhandle = DllOpen('wininet.dll')
$Open = _FTPOpen ('MyFTP Control',0) 
If @error Then Failed("Open")
$Conn = _FTPConnect ($Open, 'ftp.microsoft.com', 'anonymous', 'anonymous')
If @error Then Failed("Connect")

$FileInfo = _FtpFileFindFirst ($Conn, "/Products/frontpage/*.*", $Handle, $DllRect)
While $FileInfo[0]
    ConsoleWrite("Find: " & $FileInfo[1] & @CR & $FileInfo[2] & @CR & $FileInfo[3] & @CR & $FileInfo[4] & @CR & $FileInfo[5] & @CR & $FileInfo[6] & @CR & $FileInfo[7] & @CR & $FileInfo[8] & @CR & $FileInfo[9] & @CR & $FileInfo[10])
    ; The size of the file is equal to (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow. MAXDWORD = 0xffffffff
    $file_name = $FileInfo[10]
    $file_size = BitShift($FileInfo[8],-32) + $FileInfo[9]
;~  $file_size = $FileInfo[8] * 4294967296 + $FileInfo[9]
    $file_time = BitShift($FileInfo[7],-32) + $FileInfo[6] ; probably bad!! maybe is wrong uint[2]
;~  $file_time = $FileInfo[6] * 4294967296 + $FileInfo[7]
    ConsoleWrite("Final: " & $file_name & ' ' & $file_size & ' ' & $file_time & @CRLF)
    $FileInfo = _FtpFileFindNext ($Handle, $DllRect)
WEnd
_FtpFileFindClose ($Handle, $DllRect)

_FTPClose ($Open)
DllClose($dllhandle)

Func Failed($error)
    MsgBox(48, 'Error', $error)
    Exit
EndFunc
Link to comment
Share on other sites

  • Replies 283
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Added some new functions to FTP.au3

_FTPFindFirstFile()

_FTPFindNextFile()

_FTPGetLinkStringInfo()

_FileTimeToSystemTime()

There are comments in the code to see how to use these and what they do. The biggest change might be with the FTPFindFirstFile(), where it only returns the search hwnd and FTPFindNextFile() will return the filenames or an array of attributes. I think I solved the time converting problem with the high and low words but run the scripts and see if it works. I also add a few constants at the beginning.

Here is a run down of the new functions:

;===============================================================================
; Function Name:    _FTPFindFirstFile()
; Description:      Returns a search handle to be used with _FTPFindNextFile()
; Parameter(s):     $hConnect           - The long from _FTPConnect()
;                   $lpszSearchFile     - The remote Location for the file.
;                   $dwFlags            - use the dwFlags parameter to specify 1 for transferring the file in ASCII (Type A transfer method) or 2 for transferring the file in Binary (Type I transfer method).
;                   $dwContext          - lContext is used to identify the application context when using callbacks (Default: 0)
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - Returns Search Handle
;                   On Failure - 0; Sets @error = -1
; Comments:         Tested with Current Remote Directory only, use _FtpSetCurrentDir() to change directory before calling _FTPFindFirstFile()
;                   Remember to call _FTPClose($SearchHwnd) to close the search handle
;===============================================================================
Func _FTPFindFirstFile($hConnect, $lpszSearchFile = "",$dwFlags = 0, $dwContext = 0)
    
    $WIN32_FIND_DATA = DllStructCreate($s_WIN32_FIND_DATA)

    Local $ai_FTPFirstFile = DllCall('wininet.dll', 'hwnd', 'FtpFindFirstFile', _
                        'long', $hConnect, _                                ;HINTERNET hConnect
                        'str', $lpszSearchFile, _                           ;LPCTSTR lpszSearchFile
                        'ptr',DllStructGetPtr($WIN32_FIND_DATA), _  ;LPWIN32_FIND_DATA lpFindFileData
                        'long',$dwFlags, _                                  ;DWORD dwFlags
                        'long', $dwContext)                                 ;DWORD_PTR dwContext
                            
    If @error OR $ai_FTPFirstFile[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf
        
    Return $ai_FTPFirstFile[0]
    
EndFunc ;==> _FTPFindFirstFile()


;===============================================================================
; Function Name:    _FTPFindNextFile()
; Description:      Find Next File on an FTP server.
; Parameter(s):     $hFind      - The search hwnd returned by _FTPFindFirstFile()
;                   $sFilter    - Search Filter (Default = "*.*").
;                   $sFlag      - 0(Default) Return both files and folders names
;                               - 1 Return file names only (Folders are returned as -1)
;                               - 2 Return folder names only (Files are returned as -1)
;                               - 3 Return Attributes Array (includes file/folder name)
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - Filename or Attributes Array
;                   On Failure - Last Filename or Attributes Array and @error = -1
;===============================================================================
Func _FTPFindNextFile($hFind,$sFilter = "*.*", $sFlag = 0)


    Local $LastFilename
    Local $FileAttributes = DllStructGetData($WIN32_FIND_DATA, 1)    ; File Attributes
    
    Switch $sFlag
        Case 0
            
            $LastFilename = DllStructGetData($WIN32_FIND_DATA, 9)
            
        Case 1
            If $FileAttributes <> $FILE_ATTRIBUTE_DIRECTORY Then
                $LastFilename = DllStructGetData($WIN32_FIND_DATA, 9)
            Else
                $LastFilename = -1
            EndIf
            
        Case 2
            If $FileAttributes == $FILE_ATTRIBUTE_DIRECTORY Then
                $LastFilename = DllStructGetData($WIN32_FIND_DATA, 9)
            Else
                $LastFilename = -1
            EndIf
        Case 3
            Local Const $MAXDWORD = 4294967295
            Dim $a_FTPFileList[8]
            $a_FTPFileList[0] = 7
            $a_FTPFileList[1] = DllStructGetData($WIN32_FIND_DATA, 1)    ; File Attributes
            
            
            $FILETIME = DllStructCreate("dword;dword")
            DllStructSetData($FILETIME, 1, DllStructGetData($WIN32_FIND_DATA, 2, 1)); Creation Time Low
            DllStructSetData($FILETIME, 2, DllStructGetData($WIN32_FIND_DATA, 2, 2)); Creation Time High
            $a_FTPFileList[2] = _FileTimeToSystemTime(DllStructGetPtr($FILETIME))
            $FILETIME = 0
            
            
            $FILETIME = DllStructCreate("dword;dword")
            DllStructSetData($FILETIME, 1, DllStructGetData($WIN32_FIND_DATA, 3, 1)); Access Time Low
            DllStructSetData($FILETIME, 2, DllStructGetData($WIN32_FIND_DATA, 3, 2)); Access Time High
            $a_FTPFileList[3] = _FileTimeToSystemTime(DllStructGetPtr($FILETIME))
            $FILETIME = 0
            
            $FILETIME = DllStructCreate("dword;dword")
            DllStructSetData($FILETIME, 1, DllStructGetData($WIN32_FIND_DATA, 4, 1));  Last Write Time Low
            DllStructSetData($FILETIME, 2, DllStructGetData($WIN32_FIND_DATA, 4, 2));  Last Write Time High
            $a_FTPFileList[4] = _FileTimeToSystemTime(DllStructGetPtr($FILETIME))
            $FILETIME = 0
            
            ;The size of the file is equal to (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow
            $a_FTPFileList[5] = (DllStructGetData($WIN32_FIND_DATA, 5) * ($MAXDWORD + 1)) + DllStructGetData($WIN32_FIND_DATA, 6)
            
            $a_FTPFileList[6] = DllStructGetData($WIN32_FIND_DATA, 9); File Name
            $a_FTPFileList[7] = DllStructGetData($WIN32_FIND_DATA, 10)  ; Altername
            
;~          _ArrayDisplay($a_FTPFileList,"$a_FTPFileList")
            
    EndSwitch
    
    Local $ai_FTPNextFile = DllCall('wininet.dll', 'int', 'InternetFindNextFile', _
                        'long', $hFind, _                               ;HINTERNET hFind
                        'ptr',DllStructGetPtr($WIN32_FIND_DATA))        ;LPVOID lpvFindData
    

    If @error OR $ai_FTPNextFile[0] = 0 Then
        $WIN32_FIND_DATA = 0 ;free memory
        SetError(-1)
        If $sFlag == 3 Then
            Return $a_FTPFileList
        Else
            Return $LastFilename
        EndIf
    EndIf
    
    If $sFlag == 3 Then
        Return $a_FTPFileList
    Else
        Return $LastFilename
    EndIf
    
    
EndFunc ;==> _FTPFindNextFile()


;===============================================================================
; Function Name:    _FTPGetLinkStringInfo()
; Description:      Gets Information about an ftp string (ie. "ftp://user:pass@servername:port/path/"  or "servername:port/path"
; Parameter(s):     $s_FTPLink      - [in]The string to get the information from (ie. "ftp://user:pass@servername:port/")
;                   $s_ServerName   - [in/out] Name of the Server (ie. name.host.net)
;                   $s_Username     - [in/out] Name of the user if found in $s_FTPLink
;                   $s_Password     - [in/out] Password for user if found in $s_FTPLink
;                   $i_ServerPort   - [in/out] Port toi connect on if found in $s_FTPLink (Default: 21)
; Requirement(s):   None
; Return Value(s):  On Success  - Returns the path from $s_FTPLink
;                               - Sets Extended to 1 for $s_FTPLink to ahve form of "ftp://...../"
;                               - Sets Extended to 2 for $s_FTPLink to ahve form of " name.host.net...."
;                   On Failure  - 0 and @error = -1
;===============================================================================
Func _FTPGetLinkStringInfo($s_FTPLink,ByRef $s_ServerName, ByRef $s_Username, ByRef $s_Password, ByRef $i_ServerPort)
    
    Local $errFlag = 0,$extFlag = 0
    Local $s_ServerPort,$s_FTPPath
    
    If StringInStr($s_FTPLink,"ftp://") Then ;Written as Link ie. ftp://user:pass@servername:port/path/)
        $extFlag = 2
        If StringInStr($s_FTPLink,"@") Then ;has info about username and password (ie. ftp://user:pass@servername/)
            $s_Username = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,":",0,2) - StringInStr($s_FTPLink,"ftp://") - 6)
            $s_Password = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,2) + 1,StringInStr($s_FTPLink,"@") - StringInStr($s_FTPLink,":",0,2)-1)
            
            If StringInStr($s_FTPLink,":",0,3) Then ;has info about port (ftp://user:pass@servername:port or ftp://user:pass@servername:port/)
                If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://user:pass@servername:port/path/)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1,StringInStr($s_FTPLink,":",0,3) - StringInStr($s_FTPLink,"@") - 1)
                    $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,3) + 1,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-1)
                    $i_ServerPort = Number($s_ServerPort)
                    $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/"
                Else ;no trailing slash (ftp://user:pass@servername:port)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1,StringInStr($s_FTPLink,":",0,3) - StringInStr($s_FTPLink,"@")-1)
                    $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,3) + 1)
                    $i_ServerPort = Number($s_ServerPort)
                    $s_FTPPath = "/"
                EndIf
                
            Else ; no info about port assume default: 21 (ftp://user:pass@servername or ftp://user:pass@servername/)
                $i_ServerPort = 21
                If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://user:pass@servername/path/)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"@")-1)
                    $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/"
                Else ;no trailing slash (ftp://user:pass@servername)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1)
                    $s_FTPPath = "/"
                EndIf
            EndIf
        Else ;no info about username and password (ie. ftp://servername/ or ftp://servername:port)
            If StringInStr($s_FTPLink,":",0,2) Then ;has info about port (ftp://servername:port or ftp://servername:port/)
                If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://servername:port/path/)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,":",0,2) - StringInStr($s_FTPLink,"ftp://")-6)
                    $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,2) + 1,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-1)
                    $i_ServerPort = Number($s_ServerPort)
                    $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/"
                Else ;no trailing slash (ftp://servername:port)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,":",0,2) - StringInStr($s_FTPLink,"ftp://")-6)
                    $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,2) + 1)
                    $i_ServerPort = Number($s_ServerPort)
                    $s_FTPPath = "/"
                EndIf
            Else ; no info about port assume default: 21 (ie. ftp://servername or ftp://servername/)
                $i_ServerPort = 21
                If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://servername/path/)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-6)
                    $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/"
                Else ;no trailing slash (ftp://servername)
                    $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-6)
                    $s_FTPPath = "/"
                EndIf
            EndIf
        EndIf
        
        
    ElseIf StringInStr($s_FTPLink,".") Then ;Written with ftp servername not as Link ie. servername:port/path
        $extFlag = 1
        If StringInStr($s_FTPLink,":") Then ;port number exists servername:port or servername:port/path
            $s_ServerName = StringMid($s_FTPLink,1,StringInStr($s_FTPLink,":") - 1)
            If StringInStr($s_FTPLink,"/") Then ;path info exists servername:port/path
                $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":") + 1,StringInStr($s_FTPLink,"/") - StringInStr($s_FTPLink,":")-1)
                $i_ServerPort = Number($s_ServerPort)
                $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/"))
            Else ;no slash found servername:port
                $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":") + 1)
                $i_ServerPort = Number($s_ServerPort)
                $s_FTPPath = "/"
            EndIf
        Else ; no port info assume default: 21 (ie. servername or servername/path)
            $i_ServerPort = 21
            If StringInStr($s_FTPLink,"/") Then ;path info exists
                $s_ServerName = StringMid($s_FTPLink,1,StringInStr($s_FTPLink,"/") - 1)
                $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/"))
            Else
                $s_ServerName = $s_FTPLink
                $s_FTPPath = "/"
            EndIf
            
        EndIf
    Else ;might not be a string containg ftp information
        $extFlag = 0
        $errFlag = -1
        $s_FTPPath = 0
    EndIf
    
    SetExtended($extFlag)
    SetError($errFlag)
    Return $s_FTPPath
    
EndFunc


;===============================================================================
; Function Name:    _FileTimeToSystemTime()
; Description:      Converts the FILETIME struct to more useful information.
; Parameter(s):     $p_FILETIME     - [in] pointer to the FILETIME struct
; Requirement(s):   DllCall, Kernel32.dll
; Return Value(s):  On Success - A pipe delimited string (ie. Year|Month|DayOfWeek|Day|Hour|Minute|Second|Milliseconds|;
;                   On Failure - 0 and Sets @error = -1
;===============================================================================
Func _FileTimeToSystemTime($p_FILETIME) ;uses Kernel32.dll

    $SYSTEMTIME = DllStructCreate("short;short;short;short;short;short;short;short")

    Local $ai_FileTime = DllCall('Kernel32.dll', 'int', 'FileTimeToSystemTime', _
                        'ptr', $p_FILETIME, _                   ;const FILETIME* lpFileTime
                        'ptr',DllStructGetPtr($SYSTEMTIME))     ;LPSYSTEMTIME lpSystemTime
                        
    If @error OR $ai_FileTime[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Local $s_FileTime = ""
    For $i = 1 To 8
        If $i == 3 Then ;day of the week
            Switch DllStructGetData($SYSTEMTIME,$i)
                Case 0
                    $s_FileTime &= "Sunday" & "|"
                Case 1
                    $s_FileTime &= "Monday" & "|"
                Case 2
                    $s_FileTime &= "Tuesday" & "|"
                Case 3
                    $s_FileTime &= "Wednesday" & "|"
                Case 4
                    $s_FileTime &= "Thursday" & "|"
                Case 5
                    $s_FileTime &= "Friday" & "|"
                Case 6
                    $s_FileTime &= "Saturday" & "|"
            EndSwitch
        EndIf
        
        $s_FileTime &= DllStructGetData($SYSTEMTIME,$i) & "|"
        
    Next

    $SYSTEMTIME = 0 ;free memory
    
    Return $s_FileTime                  
    
    
EndFunc

FTP.au3

Link to comment
Share on other sites

joeyb1275 nice job!! :shocked:

I was trying to figure out how to do that on Friday, but didn't get to the point you did. thank you!

Guys, questions:

1. What does Time Low and Time High mean? I found http://msdn2.microsoft.com/en-us/library/ms724284.aspx, but I don't really understand what it means.

2. The return data for the times are

1601|1|Monday|1|1|0|0|0|0|
1601|1|Monday|1|1|0|0|0|0|
2001|3|Thursday|4|29|0|0|0|0|

what do the placements mean? I can't find a doc on MSDN (yet) that explains it.

Thanks!

A decision is a powerful thing
Link to comment
Share on other sites

Wrote too soon

This explains what the return time info is http://msdn2.microsoft.com/en-us/library/ms724950.aspx

;===============================================================================
; Function Name:    _FileTimeToSystemTime()
; Description:      Converts the FILETIME struct to more useful information.
; Parameter(s):     $p_FILETIME     - [in] pointer to the FILETIME struct
; Requirement(s):   DllCall, Kernel32.dll
; Return Value(s):  On Success - A pipe delimited string (ie. Year|Month|DayOfWeek|Day|Hour|Minute|Second|Milliseconds|;
;                   On Failure - 0 and Sets @error = -1
;
; Note(s):          Retruns _SYSTEMTIME {WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds} 
;===============================================================================
Edited by JohnBailey
A decision is a powerful thing
Link to comment
Share on other sites

Added some new functions to FTP.au3

_FTPFindFirstFile()

_FTPFindNextFile()

_FTPGetLinkStringInfo()

_FileTimeToSystemTime()

There are comments in the code to see how to use these and what they do. The biggest change might be with the FTPFindFirstFile(), where it only returns the search hwnd and FTPFindNextFile() will return the filenames or an array of attributes. I think I solved the time converting problem with the high and low words but run the scripts and see if it works. I also add a few constants at the beginning.

Here is a run down of the new functions:

Good work joeyb1275!! :shocked:

But I have some ideas:

1) _FileTimeToSystemTime() shouldn't return data your way. The worst is conversion DayOfWeek to English string. What about non English?

By me it could be good to use new DllStruct feature with named items. So in FTP.au3 UDF make global constants with definitions of structures, for example:

Global Const $s_SYSTEMTIME = "short Year;short Month;short DayOfWeek;short Day;short Hour;short Minute;short Second;short Milliseconds"

Func _FileTimeToSystemTime($p_FILETIME) ;uses Kernel32.dll

    $SYSTEMTIME = DllStructCreate($s_SYSTEMTIME)

    Local $ai_FileTime = DllCall('Kernel32.dll', 'int', 'FileTimeToSystemTime', _
                        'ptr', $p_FILETIME, _                   ;const FILETIME* lpFileTime
                        'ptr',DllStructGetPtr($SYSTEMTIME))     ;LPSYSTEMTIME lpSystemTime
                        
    If @error OR $ai_FileTime[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Return $SYSTEMTIME 
EndFunc
oÝ÷ ÙìZ^¡û¬y«­¢+Ø¥¹±Õ±ÐíÑÀ¹ÔÌÐì((ÀÌØíµå}Ñ¥µô}¥±Q¥µQ½MåÍѵQ¥µ ÀÌØíÁ}%1Q%5¤)
½¹Í½±]É¥Ñ ÀÌØíµå}Ñ¥µ¹eȵÀìÅÕ½Ðì´ÅÕ½ÐìµÀìµå}Ñ¥µ¹5½¹Ñ µÀìÅÕ½Ðì´ÅÕ½ÐìµÀìÀÌØíµå}Ñ¥µ¹ä¤)
½¹Í½±]É¥Ñ ÀÌØíµå}Ñ¥µ¹å=]¬µÀìÅÕ½Ðì´´ØÈìÅÕ½ÐìµÀì}
½¹ÙÉÑå=]­¹±¥Í  ÀÌØíµå}Ñ¥µ¹å=]¬¤¤(ÀÌØíµå}Ñ¥µôÀìÉÍÑÉÕеµ½Éä()Õ¹}
½¹ÙÉÑå=]­¹±¥Í  ÀÌØíå=]¬¤(%MÝ¥Ñ ÀÌØíå=]¬($%
ÍÀ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíMÕ¹äÅÕ½Ðì($%
ÍÄ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½Ðí5½¹äÅÕ½Ðì($%
ÍÈ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíQÕÍäÅÕ½Ðì($%
ÍÌ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½Ðí]¹ÍäÅÕ½Ðì($%
ÍÐ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíQ¡ÕÉÍäÅÕ½Ðì($%
ÍÔ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíÉ¥äÅÕ½Ðì($%
ÍØ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíMÑÕÉäÅÕ½Ðì(%¹MÝ¥Ñ ($(%IÑÕɸÀÌØíÍ}ÉÑÕɸ)¹Õ¹(oÝ÷ Ù*jǺw-ì­éxêÚú+jYiººh±ëÙÞÂ¥¥êߺw-ìq©Ûy§]y×è­ú+«b
u«ZÂëÞ¯'jü¢¸­ßÛ)ººh±ëÙ8^±©jeÉ©l¢ÅLñbÑb®ËEWÑS

Note: This code wasn't tested but I think this way it will be good general purpose functions for make them UDF

EDIT: corrected some bugs in code examples

Edited by Zedna
Link to comment
Share on other sites

So base functions remain general for all purposes and new helper functions can be added

for formating of data - which every can modify for it's purposes.

2) The same apply also on _FTPFindFirstFile()and _FTPFindNextFile()

So return rather whole struct with named items and let users to simply use whatever they want.

Here my NEW idea for defining structure for pairs of 32bit integers for Low/Hig as one 64bit item

something like this (only concept not tested):

Thanks for the feedback! I changed my code so that _FileTimeToSystemTime() doesn't handle the conversion to DayOfWeek, but I'm still kind of new to using structs in Autoit. I think the creation of a struct with elements and using the dot operator to refer to its elements is new to Autoit (ie. "$structvar.elementname"). It doesn't work for me because I'm not running the beta. The one thing I wonder with the idea of returning the whole stuct is, what is the memory management like when passing structs. For example if I call _FileTimeToSystemTime() in a for loop 1000 times or more and it is returning a struct everytime do I have to worry about filling my memory? However the new struct notation is nice "$structvar.elementname", it makes reading code maybe a little easier, but my experiance with structs in other languages is that the more you create the bigger and slower you program becomes. Maybe this is not a concern, I couldn't find anything about structs and memory management in the Autoit help file so I'm still researching...

I do have one question though, why do I need to call DllOpen('wininet.dll') before using FTP functions and then DllClose when I'm done? I was looking though the posts and saw that this was a solution so that the connection was not lost, but I didn't see why it solved the problem. I wondered if the DllOpen('wininet.dll') could be incorporated into the _FTPOpen() and DllClose into the _FTPClose() this way the user does not have to worry about opening and closing it. Is this not a good way to handle it?

Link to comment
Share on other sites

Thanks for the feedback! I changed my code so that _FileTimeToSystemTime() doesn't handle the conversion to DayOfWeek, but I'm still kind of new to using structs in Autoit. I think the creation of a struct with elements and using the dot operator to refer to its elements is new to Autoit (ie. "$structvar.elementname"). It doesn't work for me because I'm not running the beta. The one thing I wonder with the idea of returning the whole stuct is, what is the memory management like when passing structs. For example if I call _FileTimeToSystemTime() in a for loop 1000 times or more and it is returning a struct everytime do I have to worry about filling my memory? However the new struct notation is nice "$structvar.elementname", it makes reading code maybe a little easier, but my experiance with structs in other languages is that the more you create the bigger and slower you program becomes. Maybe this is not a concern, I couldn't find anything about structs and memory management in the Autoit help file so I'm still researching...

I do have one question though, why do I need to call DllOpen('wininet.dll') before using FTP functions and then DllClose when I'm done? I was looking though the posts and saw that this was a solution so that the connection was not lost, but I didn't see why it solved the problem. I wondered if the DllOpen('wininet.dll') could be incorporated into the _FTPOpen() and DllClose into the _FTPClose() this way the user does not have to worry about opening and closing it. Is this not a good way to handle it?

Really named struct items are new in one of latest betas: 3.2.3.0 (09th March, 2007) - Added: Struct variables

Don't worry about loop 1000 times. Struct is handled as ByRef parameter. So it's created/alocated inside this function and you must clear it after you use it, see this example:

Func _FormatTime($Time)
    $my_time = _FileTimeToSystemTime($Time)
    $result = $my_time.Year & "-" & my_time.Month & "-" & $my_time.Day & " " & my_time.Hour & ":" & my_time.Minute & ":" & $my_time.Second
    $my_time = 0
    Return $result
EndFunc

DllOpen('wininet.dll') is workaround to avoid problem with inposibility to open FTP connection after some internal AutoIt change with DllCall() functionality that has been done in some beta version of AutoIt after version 3.2.0. There are several ways to do this workaround. I used this one.

Link to comment
Share on other sites

this should work

$INTERNET_FLAG_PASSIVE = 0x08000000

;===============================================================================
;
; Function Name:    _FTPConnect()
; Description:      Connects to an FTP server.
; Parameter(s):     $l_InternetSession  - The Long from _FTPOpen()
;                   $s_ServerName       - Server name/ip.
;                   $s_Username         - Username.
;                   $s_Password         - Password.
;                   $i_Passive          - Passive connection
;                   $i_ServerPort       - Server port ( 0 is default (21) )
;                   $l_Service          - I dont got a clue what this does.
;                   $l_Flags            - Special flags.
;                   $l_Context          - I dont got a clue what this does.
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - Returns an indentifier.
;                   On Failure - 0  and sets @ERROR
; Author(s):        Wouter van Kesteren, nitro323
;
;===============================================================================

Func _FTPConnect($l_InternetSession, $s_ServerName, $s_Username, $s_Password, $i_Passive, $i_ServerPort = 0, $l_Service = 1, $l_Flags = 0, $l_Context = 0)

    If $i_Passive == 1 then $l_Flags = 0x08000000
    Local $ai_InternetConnect = DllCall('wininet.dll', 'long', 'InternetConnect', 'long', $l_InternetSession, 'str', $s_ServerName, 'int', $i_ServerPort, 'str', $s_Username, 'str', $s_Password, 'long', $l_Service, 'long', $l_Flags, 'long', $l_Context)

    If @error OR $ai_InternetConnect[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Return $ai_InternetConnect[0]

EndFunc;==> _FTPConnect()

Replace the old the previous one

Edited by JohnBailey
A decision is a powerful thing
Link to comment
Share on other sites

BTW, depending on what you're trying to do remember this is at the top

; define some constants - can be used with _FTPPutFile and _FTPGetFile and ftp open flags
Global Const $INTERNET_FLAG_PASSIVE = 0x08000000
Global Const $INTERNET_FLAG_TRANSFER_ASCII = 0x00000001
Global Const $INTERNET_FLAG_TRANSFER_BINARY = 0x00000002
Global Const $INTERNET_DEFAULT_FTP_PORT = 21
Global Const $INTERNET_SERVICE_FTP = 1


Global $INTERNET_OPEN_TYPE_PRECONFIG = 0
Global $INTERNET_OPEN_TYPE_DIRECT = 1
Global $INTERNET_OPEN_TYPE_PROXY = 3
A decision is a powerful thing
Link to comment
Share on other sites

Maybe I'm missing something basic, can someone look at this and tell me why it isn't working?

$passive = 0x08000000
$server = 'ftp.mozilla.org'
$username = 'anonymous'
$pass = 'anonymous'

$dllhandle = DllOpen('wininet.dll')
$Open = _FTPOpen('MyFTP Control')
$Conn = _FTPConnect($Open, $server, $username, $pass, 1)

If $Conn = 0 Then
    MsgBox (0, "Error", "Error! Can't connect to ftp.mozilla.org")
    Exit
EndIf

$Ftpp = _FtpGetFile($Conn, "/pub/mozilla.org/firefox/releases/2.0.0.3/win32/en-US/Firefox Setup 2.0.0.3.exe", @ScriptDir&"\Firefox Setup 2.0.0.3.exe", $passive, 0)
$Ftpc = _FTPClose($Open)

DllClose($dllhandle)
Link to comment
Share on other sites

#include <GuiConstants.au3>
#include "..\Include\OFTP.au3"

Dim $Handle, $DllRect

$server = 'ftp.mozilla.org'
$username = 'anonymous'
$pass = 'anonymous'

$dllhandle = DllOpen('wininet.dll')
$Open = _FTPOpen('MyFTP Control',0)
If @error Then Failed("Open")
$Conn = _FTPConnect($Open, $server, $username, $pass, 1)
If @error Then Failed("Connect")

$Ftpp = _FtpGetFile($Conn, "/pub/mozilla.org/firefox/releases/2.0.0.3/win32/en-US/Firefox Setup 2.0.0.3.exe", @ScriptDir&"\FirefoxSetup2003.exe", $INTERNET_FLAG_PASSIVE, 0) 
If $Ftpp = 0 Then Failed("Could not get")
$Ftpc = _FTPClose($Open)

_FTPClose ($Open)
DllClose($dllhandle)

Func Failed($error)
    MsgBox(48, 'Error', $error)
    Exit
EndFunc

the above works for me works

A decision is a powerful thing
Link to comment
Share on other sites

Anyone have any good ideas for building a progressbar for downloads and uploads? I'm researching it right now.

I did one such script for FTP downloads with progressbar (in Total Commander style also with speed and estimated time)

You can get size of file and use InetGet with download at background. Then in loop calculate all needed informations a show them.

Link to comment
Share on other sites

Just a few more functions to add to FTP.au3...

_FTPOpenFile()

_FTPReadFile()

_FTPCloseFile()

Here is the code...

Global Const $GENERIC_READ = 0x80000000
Global Const $GENERIC_WRITE = 0x40000000
Global Const $FTP_TRANSFER_TYPE_UNKNOWN = 0 ;Defaults to FTP_TRANSFER_TYPE_BINARY.
Global Const $FTP_TRANSFER_TYPE_ASCII = 1 ;Transfers the file using FTP's ASCII (Type A) transfer method. Control and formatting information is converted to local equivalents. 
Global Const $FTP_TRANSFER_TYPE_BINARY = 2 ;Transfers the file using FTP's Image (Type I) transfer method. The file is transferred exactly as it exists with no changes. This is the default transfer method. 

;===============================================================================
; Function Name:    _FTPOpenFile()
; Description:      Initiates access to a remote file on an FTP server for reading or writing. Use _FTPCloseFile()
;                   to close the ftp file.
; Parameter(s):     $hConnect       - The long from _FTPConnect()
;                   $lpszFileName   - String of the ftp file to open
;                   $dwAccess       - GENERIC_READ or GENERIC_WRITE (Default is GENERIC_READ)
;                   $dwFlags        - Settings for the transfer see notes below (Default is 2 for FTP_TRANSFER_TYPE_BINARY)
;                   $dwContext      - (Not Used) See notes below
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - Returns the handle to ftp file for read/write with _FTPReadFile()
;                   On Failure - 0 and Sets @error = -1
;Notes:
;~ hConnect 
;~      [in] Handle to an FTP session. 
;~ lpszFileName 
;~      [in] Pointer to a null-terminated string that contains the name of the file to be accessed. 
;~ dwAccess 
;~      [in] File access. This parameter can be GENERIC_READ or GENERIC_WRITE, but not both. 
;~ dwFlags 
;~      [in] Conditions under which the transfers occur. The application should select one transfer type and any of 
;               the flags that indicate how the caching of the file will be controlled.
;~ The transfer type can be one of the following values.
;~      FTP_TRANSFER_TYPE_ASCII Transfers the file using FTP's ASCII (Type A) transfer method. Control and 
;               formatting information is converted to local equivalents. 
;~      FTP_TRANSFER_TYPE_BINARY Transfers the file using FTP's Image (Type I) transfer method. The file is 
;               transferred exactly as it exists with no changes. This is the default transfer method. 
;~      FTP_TRANSFER_TYPE_UNKNOWN Defaults to FTP_TRANSFER_TYPE_BINARY. 
;~      INTERNET_FLAG_TRANSFER_ASCII Transfers the file as ASCII. 
;~      INTERNET_FLAG_TRANSFER_BINARY Transfers the file as binary. 
;~ The following values are used to control the caching of the file. The application can use one or more of these values.
;~      INTERNET_FLAG_HYPERLINK Forces a reload if there was no Expires time and no LastModified time returned from the server 
;               when determining whether to reload the item from the network. 
;~      INTERNET_FLAG_NEED_FILE Causes a temporary file to be created if the file cannot be cached. 
;~      INTERNET_FLAG_RELOAD Forces a download of the requested file, object, or directory listing from the origin server, 
;               not from the cache. 
;~      INTERNET_FLAG_RESYNCHRONIZE Reloads HTTP resources if the resource has been modified since the last time it was 
;               downloaded. All FTP and Gopher resources are reloaded. 
;~ dwContext 
;~      [in] Pointer to a variable that contains the application-defined value that associates this search with any 
;               application data. This is only used if the application has already called InternetSetStatusCallback to set 
;               up a status callback function. 
;===============================================================================
Func _FTPOpenFile($hConnect,$lpszFileName,$dwAccess = 0x80000000,$dwFlags = 2,$dwContext = 0)

    Local $ai_FTPOpenFile = DllCall('wininet.dll', 'hwnd', 'FtpOpenFile', _
                        'hwnd', $hConnect, _            ;HINTERNET hConnect
                        'str', $lpszFileName, _         ;LPCTSTR lpszFileName
                        'udword', $dwAccess , _     ;DWORD dwAccess
                        'dword', $dwFlags, _                        ;DWORD dwFlags
                        'dword',$dwContext)                     ;DWORD_PTR dwContext
                        
    If @error OR $ai_FTPOpenFile[0] == 0 Then
        SetError(-1)
        Return 0
    EndIf
    
    Return $ai_FTPOpenFile[0]
    
EndFunc

;===============================================================================
; Function Name:    _FTPReadFile()
; Description:      Reads data from a handle opened by _FTPOpenFile()
; Parameter(s):     $h_File                 - Handle returned by _FTPOpenFile to the ftp file
;                   $dwNumberOfBytesToRead  - Number of bytes to read
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - Returns the binary/string read.
;                   On Failure - 0 and Sets @error = -1 for end-of-file, @error = 1 for other errors
;Notes: (InternetReadFile() parameters)
;~ hFile 
;~      [in] Handle returned from a previous call to InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest. 
;~ lpBuffer 
;~      [out] Pointer to a buffer that receives the data. 
;~ dwNumberOfBytesToRead 
;~      [in] Number of bytes to be read. 
;~ lpdwNumberOfBytesRead 
;~      [out] Pointer to a variable that receives the number of bytes read. InternetReadFile sets this value to zero before doing any work or error checking. 
;===============================================================================
Func _FTPReadFile($h_File,$dwNumberOfBytesToRead)
    
    Local $s_FileRead = ""
    $lpBuffer = DllStructCreate("byte[" & $dwNumberOfBytesToRead & "]")
    $lpdwNumberOfBytesRead = DllStructCreate("long")
    
    Local $ai_FTPReadFile = DllCall('wininet.dll', 'int', 'InternetReadFile', _
                        'hwnd', $h_File, _                              ;HINTERNET hFile
                        'ptr', DllStructGetPtr($lpBuffer), _            ;LPVOID lpBuffer
                        'dword', $dwNumberOfBytesToRead, _              ;DWORD dwNumberOfBytesToRead
                        'ptr',DllStructGetPtr($lpdwNumberOfBytesRead))  ;LPDWORD lpdwNumberOfBytesRead
    If @error OR $ai_FTPReadFile[0] == 0 Then
        If DllStructGetData($lpdwNumberOfBytesRead,1) == 0 Then
            $lpBuffer = 0
            $lpdwNumberOfBytesRead = 0
            SetError(-1)
            Return 0
        Else
            $lpBuffer = 0
            $lpdwNumberOfBytesRead = 0
            SetError(1)
            Return 0
        EndIf
    EndIf
    $s_FileRead = DllStructGetData($lpBuffer,1) ;index is omitted so the entire array is written into $s_FileRead as a BinaryString

    $lpBuffer = 0
    $lpdwNumberOfBytesRead = 0

    Return $s_FileRead
    
EndFunc

;===============================================================================
; Function Name:    _FTPCloseFile()
; Description:      Closes the Handle returned by _FTPOpenFile.
; Parameter(s):     $l_InternetSession  - The handles from _FTPOpenFile.()
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - 1
;                   On Failure - 0 Sets @error = -1
;===============================================================================
Func _FTPCloseFile($l_InternetSession)
    
    Local $ai_InternetCloseHandle = DllCall('wininet.dll', 'int', 'InternetCloseHandle', 'hwnd', $l_InternetSession)
    
    
    If @error OR $ai_InternetCloseHandle[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf
    
    Return $ai_InternetCloseHandle[0]
    
EndFunc

I have test this for reading files only. I will test more and add an example scripts later. It should be easy to use acts like FileRead().

Link to comment
Share on other sites

Update for _FTPReadFile()

I found an error in my _FTPReadFile() function it only come out when you read a single byte. The following code will correct the error (see the return values for the fix)

;===============================================================================
; Function Name:    _FTPReadFile()
; Description:      Reads data from a handle opened by _FTPOpenFile()
; Parameter(s):     $h_File                 - Handle returned by _FTPOpenFile to the ftp file
;                   $dwNumberOfBytesToRead  - Number of bytes to read
; Requirement(s):   DllCall, wininet.dll
; Return Value(s):  On Success - Returns the binary/string read.
;                   On Failure - 0 and Sets @error = -1 for end-of-file, @error = 1 for other errors
;Notes: (InternetReadFile() parameters)
;~ hFile 
;~      [in] Handle returned from a previous call to InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest. 
;~ lpBuffer 
;~      [out] Pointer to a buffer that receives the data. 
;~ dwNumberOfBytesToRead 
;~      [in] Number of bytes to be read. 
;~ lpdwNumberOfBytesRead 
;~      [out] Pointer to a variable that receives the number of bytes read. InternetReadFile sets this value to zero before doing any work or error checking. 
;===============================================================================
Func _FTPReadFile($h_File,$dwNumberOfBytesToRead)
    
    Local $s_FileRead = "",$BytesRead = 0
    $lpBuffer = DllStructCreate("byte[" & $dwNumberOfBytesToRead & "]")
    $lpdwNumberOfBytesRead = DllStructCreate("long")
    
    Local $ai_FTPReadFile = DllCall('wininet.dll', 'int', 'InternetReadFile', _
                        'hwnd', $h_File, _                              ;HINTERNET hFile
                        'ptr', DllStructGetPtr($lpBuffer), _            ;LPVOID lpBuffer
                        'dword', $dwNumberOfBytesToRead, _              ;DWORD dwNumberOfBytesToRead
                        'ptr',DllStructGetPtr($lpdwNumberOfBytesRead))  ;LPDWORD lpdwNumberOfBytesRead
    $BytesRead = DllStructGetData($lpdwNumberOfBytesRead,1)
    If @error OR $ai_FTPReadFile[0] == 0 Then
        $lpBuffer = 0
        $lpdwNumberOfBytesRead = 0
        If $BytesRead == 0 Then
            SetError(-1)    ;end-of-file error
        Else
            SetError(1) ;general error
        EndIf
        Return 0
    EndIf
    $s_FileRead = DllStructGetData($lpBuffer,1);index is omitted so the entire array is written into $s_FileRead as a BinaryString

    $lpBuffer = 0
    $lpdwNumberOfBytesRead = 0

    If $BytesRead = 1 Then
        Return Chr($s_FileRead) ;without this a 1 byte read will return a decimal value of the 8 bits read
    Else
        Return $s_FileRead ;return as binarystring (character string where all 0-255 ASCII values are allowed)
    EndIf
        
EndFunc
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...