AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

DllCall: Basic FTP Functions
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Tue May 29, 2007 5:07 am    Post subject: Reply with quote

Helpy wrote:
Aha, much better, thanks. I really can sense the difference in download time.
Wow, your connection sucks... Razz Razz
Back to top
View user's profile Send private message Visit poster's website
Tahoma
Guest





PostPosted: Fri Sep 14, 2007 11:48 am    Post subject: Error message when compiling Ace_NoOne's script Reply with quote

Dear Ace_NoOne,
thx for a simple example of a ftp connection. However, when I change the details (username, pass, host) to mine ftp and try to run the script, it ends up with this error message:

Error: Call to nonexistent function
Specifically: FtpOpen (FtpHost, FtpUsername, FtpPassword)

It does not work with your example either. Does it mean that I have to add more functions to my Autohotkey instalation? I got the newest version of Autohotkey btw.

Thank you for your time and help.
Tahoma
Back to top
Ace_NoOne



Joined: 10 Oct 2005
Posts: 333
Location: Germany

PostPosted: Fri Sep 14, 2007 11:49 am    Post subject: Re: Error message when compiling Ace_NoOne's script Reply with quote

Tahoma wrote:
when I change the details (username, pass, host) to mine ftp and try to run the script, it ends up with this error message:

Error: Call to nonexistent function
Specifically: FtpOpen (FtpHost, FtpUsername, FtpPassword)
Well, you have to include olfen's original FTP functions. My few lines of code there just provide sort of an interface for those functions.
_________________
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Thu Oct 18, 2007 5:27 pm    Post subject: Reply with quote

I haven't used it yet, but I feel it can be useful. I spotted a little issue: hModule must be declared global in two functions to be shared among them.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Sat Oct 20, 2007 2:30 pm    Post subject: Reply with quote

PhiLho wrote:
I haven't used it yet, but I feel it can be useful. I spotted a little issue: hModule must be declared global in two functions to be shared among them.
Thanks. I've fixed FtpOpen and FtpClose.
Back to top
View user's profile Send private message Visit poster's website
derjoo
Guest





PostPosted: Mon Oct 29, 2007 10:10 am    Post subject: Reply with quote

hey, i have a problem with these functions, but i think its more the problem of the server, i cant put or get files from the server with these functions nor with ftp.exe
i had the same problem wit filezilla, until i updated to the newest version. i think the error is, that the server cant answer port commands...
is there any workaround at the moment?
joe
Back to top
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Mon Oct 29, 2007 12:44 pm    Post subject: Reply with quote

I created a mod of your code do be more generic (actually, more oriented as a general WinINet.dll wrapper). I don't want to create a new post, since I started from your code to create this (thank you by the way, it save me lot of time for research Smile).
So all credits should be yours.
I have put lots of comments and a small example of how to upload a file on a FTP Server at the top of the file.
Code:
; Script Title:
;    INet.ahk
;    Requires AutoHotkey 1.0.47+
;
; Script Function:
;   Wraps usage of WinINet.dll functions.
;   For now, mostly only FTP functions are available.
;
; Sources:
;    WinINet Functions: http://msdn2.microsoft.com/en-us/library/aa385473.aspx
;    FTP Sessions: http://msdn2.microsoft.com/en-us/library/aa384180.aspx
;
; Example:
;   ; init internet resources
;   INetOpen()
;   ; connection to the FTP server
;   hFTP = INetConnect(Server, Port, User, Pwd, "ftp")
;   if(hFTP)
;   {
;      if(FtpPutFile(hFTP, "somefile.txt"))
;         Msgbox File uploaded successfuly
;      else
;         Msgbox "Upload failed: " %A_LastError%
;      ; close the FTP connection
;      INetCloseHandle(hFTP)
;   }
;   ; release internet resources
;   INetClose()
;
; ******************************************************************************

; ------------------------------------------------------------------------------
; This function loads and tells the Internet DLL to initialize internal data structures
; and prepare for future calls from the application.
;
; Internet functions are not available before this function is called.
;
; param Proxy [in]
;   Specifies an optional name of a proxy server.
; param ProxyBypass [in]
;   Specifies an optional list of host names or IP addresses, or both, that should not be routed
;   through the proxy when a proxy is used.
; param Agent [in]
;    Specifies the name of the application or entity calling the WinINet functions.
;    This name is used as the user agent in the HTTP protocol.
;    When empty, the name of the script is used
; return
;   [bool] true if the function succeeds, otherwise false
;
INetOpen(Proxy="", ProxyBypass="", Agent="")
{
   global
   ; get a handle to the WinINet library
   inet_hModule := DllCall("LoadLibrary", "str", "wininet.dll")
   if(!inet_hModule) {
      inet_hModule = 0
      return false
   }

;   INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
;   INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
;   INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
;   INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS
   inet_hInternet := DllCall("wininet\InternetOpenA"
      , "str", (Agent != "" ? Agent : A_ScriptName)
      , "UInt", (Proxy != "" ? 3 : 1)
      , "str", Proxy
      , "str", ProxyBypass
      , "UInt", 0)
   If(!inet_hInternet) {
      INetCloseHandle(inet_hModule)
      return false
   }
   return true
}

; ------------------------------------------------------------------------------
; Terminates the application's use of WinINet functions and unloads the Internet DLL.
;
; Internet functions are not available after this function call is called.
;
INetClose()
{
   global
   INetCloseHandle(inet_hInternet)
   DllCall("FreeLibrary", "UInt", inet_hModule)
   inet_hModule = inet_hInternet = 0
}

; ------------------------------------------------------------------------------
; Closes a single Internet handle, previously opened by INetConnect, FtpOpenFile, ...
;
; param hConnection [in]
;   The connection handle to be closed.
; return
;   [bool] true if the function succeeds, otherwise false
;
INetCloseHandle(hInternet)
{
   return DllCall("wininet\InternetCloseHandle", "UInt", hInternet)
}

; ------------------------------------------------------------------------------
; Opens an File Transfer Protocol (FTP), Gopher, or HTTP session for a given site.
;
; FtpPassive [in]
;   The value 1 causes the application to use passive FTP semantics
;
; param Server [in]
;   The host name or IP number of a server.
; param Server [in]
;   The TCP/IP port to connect to.
; param Username [in]
;   The name of the user to log on (default is anonymous)
; param Password [in]
;   The password to use to log on (default is anonymous)
; param Service [in]
;   Type of service to access. Must be of the following value: http (default), ftp, url or gopher
; param FtpPassive [in]
;   Option specific to ftp service. Setting 1 causes the application to use passive FTP semantics.
; return
;   the handle of the opened connection
;
INetConnect(Server, Port, Username="anonymous", Password="anonymous", Service="http", FtpPassive=0)
{
   global inet_hInternet
   hConnection := DllCall("wininet\InternetConnectA"
      , "uint", inet_hInternet
      , "str", Server
      , "uint", Port
      , "str", Username
      , "str", Password
      , "uint", (Service = "ftp" ? 1 : (Service = "gopher" ? 2 : 3)) ; INTERNET_SERVICE_xxx
      , "uint", (FtpPassive != 0 ? 0x08000000 : 0) ; INTERNET_FLAG_PASSIVE
      , "uint", 0)
   return hConnection
}

; ------------------------------------------------------------------------------
; Creates a directory on a FTP server.
;
; param hConnection [in]
;   A valid connection handle returned by an INetConnect call (using Type="ftp").
; param Directory [in]
;   The name of the directory to be created. This can be a fully qualified path
;   or a name relative to the current directory.
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpCreateDirectory(hConnection, Directory)
{
   return DllCall("wininet\FtpCreateDirectoryA", "uint", hConnection, "str", Directory)
}

; ------------------------------------------------------------------------------
; Removes a directory on a FTP server.
;
; param hConnection [in]
;   A valid connection handle returned by an INetConnect call (using Type="ftp").
; param Directory [in]
;   The name of the directory to be deleted. This can be a fully qualified path
;   or a name relative to the current directory.
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpRemoveDirectory(hConnection, Directory)
{
   return DllCall("wininet\FtpRemoveDirectoryA", "uint", hConnection, "str", Directory)
}

; ------------------------------------------------------------------------------
; Sets the current working directory for a specified FTP session.
;
; param hConnection [in]
;   A valid connection handle returned by an INetConnect call (using Type="ftp").
; param Directory [in]
;   The name of the directory to become the current working directory. This can be a fully qualified path
;   or a name relative to the current directory.
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpSetCurrentDirectory(hConnection, Directory)
{
   return DllCall("wininet\FtpSetCurrentDirectoryA", "uint", hConnection, "str", Directory)
}

; ------------------------------------------------------------------------------
; Gets the current working directory of a specified FTP session.
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param Directory [in]
;   a variable that receives the absolute path of the current directory
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpGetCurrentDirectory(hConnection, ByRef Directory)
{
   len := 261   ; MAX_PATH 260
   VarSetCapacity(Directory, len)
   result := DllCall("wininet\FtpGetCurrentDirectoryA", "uint", hConnection, "str", Directory, "uint*", len)
   VarSetCapacity(Directory, -1)
   return result
}

; ------------------------------------------------------------------------------
; Uploads a file to a FTP server (the remote file is overwritten if it already exists).
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param LocalFile [in]
;   name of the local file to upload
; param RemoteFile [in]
;   name of the remote file to create (when empty, the remote file created will have the same name than the local one)
; param TransferType [in]
;   "A" for ascii transfert or "B" (default) for binary mode
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpPutFile(hConnection, LocalFile, RemoteFile="", TransferType="B")
{
   return DllCall("wininet\FtpPutFileA"
      , "uint", hConnection
      , "str", LocalFile
      , "str", (RemoteFile != "" ? RemoteFile : LocalFile)
      , "uint", (TransferType == "A" ? 1 : 2)   ; FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY
      , "uint", 0)
}

; ------------------------------------------------------------------------------
; Downloads a file from a FTP server and stores it localy.
; No caching options for now.
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param RemoteFile [in]
;   name of the remote file to download
; param LocalFile [in]
;   name of the local file to create (when empty, the local file created will have the same name than the remote one)
; param TransferType [in]
;   "A" for ascii transfert or "B" (default) for binary mode
; param OverWrite [in]
;   0 (default) or 1 to allow the function to proceed if a local file with the specified name already exist
; param LocalAttrib [in]
;   File attributes for the new file. This parameter can be any combination of the FILE_ATTRIBUTE_* below.
;   FILE_ATTRIBUTE_READONLY         1      0x0001 
;   FILE_ATTRIBUTE_HIDDEN           2      0x0002 
;   FILE_ATTRIBUTE_SYSTEM           4      0x0004 
;   FILE_ATTRIBUTE_NORMAL         128      0x0080
;   FILE_ATTRIBUTE_TEMPORARY      256      0x0100
;   FILE_ATTRIBUTE_ENCRYPTED      16384   0x4000
; return
;   [bool] true if the function succeeds, otherwise false
;
; Caching option:
;    INTERNET_FLAG_HYPERLINK         0x00000400  // asking wininet to do hyperlinking semantic which works right for scripts
;    INTERNET_FLAG_NEED_FILE         0x00000010  // need a file for this request
;    INTERNET_FLAG_RELOAD            0x80000000  // retrieve the original item
;    INTERNET_FLAG_RESYNCHRONIZE     0x00000800  // asking wininet to update an item if it is newer
FtpGetFile(hConnection, RemoteFile, LocalFile="", TransferType="B", OverWrite=0, LocalAttrib=0)
{
   return DllCall("wininet\FtpGetFileA"
      , "uint", hConnection
      , "str", RemoteFile
      , "str", (LocalFile != "" ? LocalFile : RemoteFile)
      , "int", !OverWrite
      , "uint", LocalAttrib
      , "uint", (TransferType == "A" ? 1 : 2)   ; FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY
      , "uint", 0)
}

; ------------------------------------------------------------------------------
; Gets the size in bytes of a file stored on a FTP server
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param File [in]
;   name of the remote file
; param TransferType [in]
;   "A" for ascii transfert or "B" (default) for binary mode
; return
;   [uint] the size in bytes of the remote file
;
FtpGetFileSize(hConnection, File, TransferType="B")
{
   hFile := DllCall("wininet\FtpOpenFileA"
      , "uint", hConnection
      , "str", File
      , "uint", 0x80000000 ; GENERIC_READ
      , "uint", (TransferType = "A" ? 1 : 2)   ; FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY
      , "uint", 0)
   if(!hFile)
      return -1
   size := DllCall("wininet\FtpGetFileSize", "uint", hFile, "uint*", size)
   INetCloseHandle(hFile)
   return size
}

; ------------------------------------------------------------------------------
; Renames (or moves) a file stored on a FTP server
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param ExistingName [in]
;   name of the remote file to be renamed (can be a relative path from the current working directory)
; param NewName [in]
;   new name of the remote file (can be a relative path from the current working directory)
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpRenameFile(hConnection, ExistingName, NewName)
{
   return DllCall("wininet\FtpRenameFileA", "uint", hConnection, "str", ExistingName, "str", NewName)
}

; ------------------------------------------------------------------------------
; Deletes a file stored on a FTP server
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param File [in]
;   the name of the file to be deleted
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpDeleteFile(hConnection, File)
{
   return DllCall("wininet\FtpDeleteFileA", "uint", hConnection, "str", File)
}

Note: the code is not stdlib compliant
Back to top
View user's profile Send private message
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Wed Oct 31, 2007 6:04 pm    Post subject: Reply with quote

Thanks Andreone. FtpFindFirstFile and FtpCommand would be nice to have, too. Smile
Back to top
View user's profile Send private message Visit poster's website
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Wed Oct 31, 2007 7:02 pm    Post subject: Reply with quote

olfen wrote:
Thanks Andreone. FtpFindFirstFile and FtpCommand would be nice to have, too. Smile
Ok, I'll add them (but don't be too hurry Wink )
Back to top
View user's profile Send private message
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Thu Nov 08, 2007 3:44 pm    Post subject: Reply with quote

I have added enumeration capabilities:
- FtpFindFirstFile
- FtpFindNextFile
- FtpGetFileInfo

Arrow I also renamed INetOpen() and INetClose() to INetStart() and INetStop(). So it's less confusing (INetOpen() doesn't actually open a connection).

I have not wrapped FtpCommand because it needs a socket to listen to asynchronous responses. And since all Ftp functions are now wrapped, all common actions can done.

Exclamation There's one thing that doesn't work: getting creation, last access and last write times. The FILETIME structure must be converted to a SYSTEMTIME structure. I have done that using "FileTimeToSystemTime", but I always get "1/1/1601 0:0:0.0".
I don't know what I miss. Maybe something related to time zones.
If somebody could take a look at that, it would be great.

I have done some testing, not intensive though. So let me know if there're bugs (or any kind of amelioration).

Code:
; Script Title:
;    INet.ahk
;    Requires AutoHotkey 1.0.47+
;
; Script Function:
;   Wraps usage of WinINet.dll functions.
;   For now, mostly only FTP functions are available.
;
; Notes:
;   Getting times with FtpGetFileInfo doesn't work. It's always "1/1/1601 0:0:0.0".
;
; Sources:
;    WinINet Functions: http://msdn2.microsoft.com/en-us/library/aa385473.aspx
;    FTP Sessions: http://msdn2.microsoft.com/en-us/library/aa384180.aspx
;
; Examples:
;   ; init internet resources
;   INetStart()
;   ; connection to the FTP server
;   hFTP := INetConnect(Server, Port, User, Pwd, "ftp")
;   if(hFTP)
;   {
;      if(FtpPutFile(hFTP, "somefile.txt"))
;         Msgbox File uploaded successfuly
;      else
;         Msgbox "Upload failed: " %A_LastError%
;      ; close the FTP connection
;      INetCloseHandle(hFTP)
;   }
;   ; release internet resources
;   INetStop()
;   ______________________________________________________________
;
;    if((hEnum := FtpFindFirstFile(hFTP, "*.*", FTPData)))
;    {
;       Loop
;       {
;          FileName := FtpGetFileInfo(FTPData, "Name")
;          Size := FtpGetFileInfo(FTPData, "Size")
;          IsDir := FtpGetFileInfo(FTPData, "IsDirectory")
;          Attrib := FtpGetFileInfo(FTPData, "Attrib")
;          CreationTime := FtpGetFileInfo(FTPData, "CreationTime")
;          msgbox FileName=%FileName%`nSize=%Size%`nDir=%IsDir%`nAttrib=%Attrib%`nCreationTime=%CreationTime%
;          if(!FtpFindNextFile(hEnum, FTPData))
;             break
;       }
;    }
;    INetCloseHandle(hEnum)

; ******************************************************************************

; ------------------------------------------------------------------------------
; This function loads and tells the Internet DLL to initialize internal data structures
; and prepare for future calls from the application.
;
; Internet functions are not available before this function is called.
;
; param Proxy [in]
;   Specifies an optional name of a proxy server.
; param ProxyBypass [in]
;   Specifies an optional list of host names or IP addresses, or both, that should not be routed
;   through the proxy when a proxy is used.
; param Agent [in]
;    Specifies the name of the application or entity calling the WinINet functions.
;    This name is used as the user agent in the HTTP protocol.
;    When empty, the name of the script is used
; return
;   [bool] true if the function succeeds, otherwise false
;
INetStart(Proxy="", ProxyBypass="", Agent="")
{
   global
   ; get a handle to the WinINet library
   inet_hModule := DllCall("LoadLibrary", "str", "wininet.dll")
   if(!inet_hModule) {
      inet_hModule = 0
      return false
   }

;   INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
;   INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
;   INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
;   INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS
   inet_hInternet := DllCall("wininet\InternetOpenA"
      , "str", (Agent != "" ? Agent : A_ScriptName)
      , "UInt", (Proxy != "" ? 3 : 1)
      , "str", Proxy
      , "str", ProxyBypass
      , "UInt", 0)
   If(!inet_hInternet) {
      INetCloseHandle(inet_hModule)
      return false
   }
   return true
}

; ------------------------------------------------------------------------------
; Terminates the application's use of WinINet functions and unloads the Internet DLL.
;
; Internet functions are not available after this function call is called.
;
INetStop()
{
   global
   INetCloseHandle(inet_hInternet)
   DllCall("FreeLibrary", "UInt", inet_hModule)
   inet_hModule = inet_hInternet = 0
}

; ------------------------------------------------------------------------------
; Closes a single Internet handle, previously opened by INetConnect, FtpOpenFile, ...
;
; param hConnection [in]
;   The connection handle to be closed.
; return
;   [bool] true if the function succeeds, otherwise false
;
INetCloseHandle(hInternet)
{
   return DllCall("wininet\InternetCloseHandle", "UInt", hInternet)
}

; ------------------------------------------------------------------------------
; Opens an File Transfer Protocol (FTP), Gopher, or HTTP session for a given site.
;
; FtpPassive [in]
;   The value 1 causes the application to use passive FTP semantics
;
; param Server [in]
;   The host name or IP number of a server.
; param Server [in]
;   The TCP/IP port to connect to.
; param Username [in]
;   The name of the user to log on (default is anonymous)
; param Password [in]
;   The password to use to log on (default is anonymous)
; param Service [in]
;   Type of service to access. Must be of the following value: http (default), ftp, url or gopher
; param FtpPassive [in]
;   Option specific to ftp service. Setting 1 causes the application to use passive FTP semantics.
; return
;   the handle of the opened connection
;
INetConnect(Server, Port, Username="anonymous", Password="anonymous", Service="http", FtpPassive=0)
{
   global inet_hInternet
   hConnection := DllCall("wininet\InternetConnectA"
      , "uint", inet_hInternet
      , "str", Server
      , "uint", Port
      , "str", Username
      , "str", Password
      , "uint", (Service = "ftp" ? 1 : (Service = "gopher" ? 2 : 3)) ; INTERNET_SERVICE_xxx
      , "uint", (FtpPassive != 0 ? 0x08000000 : 0) ; INTERNET_FLAG_PASSIVE
      , "uint", 0)
   return hConnection
}

; ------------------------------------------------------------------------------
; Creates a directory on a FTP server.
;
; param hConnection [in]
;   A valid connection handle returned by an INetConnect call (using Type="ftp").
; param Directory [in]
;   The name of the directory to be created. This can be a fully qualified path
;   or a name relative to the current directory.
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpCreateDirectory(hConnection, Directory)
{
   return DllCall("wininet\FtpCreateDirectoryA", "uint", hConnection, "str", Directory)
}

; ------------------------------------------------------------------------------
; Removes a directory on a FTP server.
;
; param hConnection [in]
;   A valid connection handle returned by an INetConnect call (using Type="ftp").
; param Directory [in]
;   The name of the directory to be deleted. This can be a fully qualified path
;   or a name relative to the current directory.
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpRemoveDirectory(hConnection, Directory)
{
   return DllCall("wininet\FtpRemoveDirectoryA", "uint", hConnection, "str", Directory)
}

; ------------------------------------------------------------------------------
; Sets the current working directory for a specified FTP session.
;
; param hConnection [in]
;   A valid connection handle returned by an INetConnect call (using Type="ftp").
; param Directory [in]
;   The name of the directory to become the current working directory. This can be a fully qualified path
;   or a name relative to the current directory.
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpSetCurrentDirectory(hConnection, Directory)
{
   return DllCall("wininet\FtpSetCurrentDirectoryA", "uint", hConnection, "str", Directory)
}

; ------------------------------------------------------------------------------
; Gets the current working directory of a specified FTP session.
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param Directory [in]
;   a variable that receives the absolute path of the current directory
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpGetCurrentDirectory(hConnection, ByRef @Directory)
{
   len := 261   ; MAX_PATH 260
   VarSetCapacity(@Directory, len)
   result := DllCall("wininet\FtpGetCurrentDirectoryA", "uint", hConnection, "str", @Directory, "uint*", len)
   VarSetCapacity(@Directory, -1)
   return result
}

; ------------------------------------------------------------------------------
; Uploads a file to a FTP server (the remote file is overwritten if it already exists).
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param LocalFile [in]
;   name of the local file to upload
; param RemoteFile [in]
;   name of the remote file to create (when empty, the remote file created will have the same name than the local one)
; param TransferType [in]
;   "A" for ascii transfert or "B" (default) for binary mode
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpPutFile(hConnection, LocalFile, RemoteFile="", TransferType="B")
{
   return DllCall("wininet\FtpPutFileA"
      , "uint", hConnection
      , "str", LocalFile
      , "str", (RemoteFile != "" ? RemoteFile : LocalFile)
      , "uint", (TransferType == "A" ? 1 : 2)   ; FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY
      , "uint", 0)
}

; ------------------------------------------------------------------------------
; Downloads a file from a FTP server and stores it localy.
; No caching options for now.
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param RemoteFile [in]
;   name of the remote file to download
; param LocalFile [in]
;   name of the local file to create (when empty, the local file created will have the same name than the remote one)
; param TransferType [in]
;   "A" for ascii transfert or "B" (default) for binary mode
; param OverWrite [in]
;   0 (default) or 1 to allow the function to proceed if a local file with the specified name already exist
; param LocalAttrib [in]
;   File attributes for the new file. This parameter can be any combination of the FILE_ATTRIBUTE_* below.
;   FILE_ATTRIBUTE_READONLY         1      0x0001 
;   FILE_ATTRIBUTE_HIDDEN           2      0x0002 
;   FILE_ATTRIBUTE_SYSTEM           4      0x0004 
;   FILE_ATTRIBUTE_NORMAL         128      0x0080
;   FILE_ATTRIBUTE_TEMPORARY      256      0x0100
;   FILE_ATTRIBUTE_ENCRYPTED      16384   0x4000
; return
;   [bool] true if the function succeeds, otherwise false
;
; Caching option:
;    INTERNET_FLAG_HYPERLINK         0x00000400  // asking wininet to do hyperlinking semantic which works right for scripts
;    INTERNET_FLAG_NEED_FILE         0x00000010  // need a file for this request
;    INTERNET_FLAG_RELOAD            0x80000000  // retrieve the original item
;    INTERNET_FLAG_RESYNCHRONIZE     0x00000800  // asking wininet to update an item if it is newer
FtpGetFile(hConnection, RemoteFile, LocalFile="", TransferType="B", OverWrite=0, LocalAttrib=0)
{
   return DllCall("wininet\FtpGetFileA"
      , "uint", hConnection
      , "str", RemoteFile
      , "str", (LocalFile != "" ? LocalFile : RemoteFile)
      , "int", !OverWrite
      , "uint", LocalAttrib
      , "uint", (TransferType == "A" ? 1 : 2)   ; FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY
      , "uint", 0)
}

; ------------------------------------------------------------------------------
; Gets the size in bytes of a file stored on a FTP server
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param File [in]
;   name of the remote file
; param TransferType [in]
;   "A" for ascii transfert or "B" (default) for binary mode
; return
;   [uint] the size in bytes of the remote file
;
FtpGetFileSize(hConnection, File, TransferType="B")
{
   hFile := DllCall("wininet\FtpOpenFileA"
      , "uint", hConnection
      , "str", File
      , "uint", 0x80000000 ; GENERIC_READ
      , "uint", (TransferType = "A" ? 1 : 2)   ; FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY
      , "uint", 0)
   if(!hFile)
      return -1
   size := DllCall("wininet\FtpGetFileSize", "uint", hFile, "uint*", size)
   INetCloseHandle(hFile)
   return size
}

; ------------------------------------------------------------------------------
; Renames (or moves) a file stored on a FTP server
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param ExistingName [in]
;   name of the remote file to be renamed (can be a relative path from the current working directory)
; param NewName [in]
;   new name of the remote file (can be a relative path from the current working directory)
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpRenameFile(hConnection, ExistingName, NewName)
{
   return DllCall("wininet\FtpRenameFileA", "uint", hConnection, "str", ExistingName, "str", NewName)
}

; ------------------------------------------------------------------------------
; Deletes a file stored on a FTP server
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param File [in]
;   the name of the file to be deleted
; return
;   [bool] true if the function succeeds, otherwise false
;
FtpDeleteFile(hConnection, File)
{
   return DllCall("wininet\FtpDeleteFileA", "uint", hConnection, "str", File)
}

; ------------------------------------------------------------------------------
; Initiates an enumration of files and directories existing on a FTP server.
;
; Note: After calling FtpFindFirstFile and until calling INetCloseHandle, the application cannot call
;      FtpFindFirstFile again on the given FTP session handle (or the call will fail)
;
; param hConnection [in]
;   a valid connection handle returned by an INetConnect call (using Type="ftp")
; param SearchFile [in]
;   Specifies a valid directory path or file name for the FTP server's file system.
;   The string can contain wildcards, but no blank spaces are allowed.
;   If the value is an empty string, the function finds the first file in the current directory on the server.
; param @FindData [out]
;   a variable that will contain raw information about the found item
; return
;   [HANDLE] a non-zero handle if a match is found, otherwise 0
;
FtpFindFirstFile(hConnection, SearchFile, ByRef @FindData)
{
   ; WIN32_FIND_DATA structure size is 4 + 3*8 + 4*4 + 260*4 + 14*4 = 1140
   VarSetCapacity(@FindData, 1140, 0)
   
   hEnum := DllCall("wininet\FtpFindFirstFileA"
      , "uint", hConnection
      , "str", SearchFile
      , "uint", &@FindData
      , "uint", 0
      , "uint", 0)
      
   if(!hEnum)
      VarSetCapacity(@FindData, 0)
   return hEnum
}

; ------------------------------------------------------------------------------
; Continues an enumeration of files and directories initiated with FtpFindFirstFile.
;
; param hEnum [in]
;   a valid enumeration handle returned by a previous call to FtpFindFirstFile or FtpFindNextFile
; param @FindData [out]
;   the variable that will contain raw information about the found item already used by FtpFindFirstFile or FtpFindNextFile
; return
;   [HANDLE] a non-zero handle if a match is found, otherwise 0
;
FtpFindNextFile(hEnum, ByRef @FindData)
{
   return DllCall("wininet\InternetFindNextFileA"
      , "uint", hEnum
      , "uint", &@FindData)
}

; ------------------------------------------------------------------------------
; Extracts a specified information about a file or directory found on a FTP server
;
; param @FindData [in]
;   The variable that contain raw information filled by FtpFindFirstFile or FtpFindNextFile
;   ByRef is used only to prevent a useless copy of a large structure.
; param InfoName [in]
;   Specifies which information to retrieve. Can be one of the following:
;      - "Name"
;      - "Size" (in bytes)
;      - "CreationTime"   (MM/DD/YYYY hh:mm:se.ms)
;      - "LastAccessTime"   (MM/DD/YYYY hh:mm:se.ms)
;      - "LastWriteTime"   (MM/DD/YYYY hh:mm:se.ms)
;      - "Attrib"   return a string containing attributes
;         N = normal
;         D = directory
;         R = read-only
;         H = hidden
;         S = system
;         A = archive
;         T = temporary
;         E = encrypted
;         C = compressed
;         V = virtual
;      - "IsNormal"
;      - "IsDirectory"
;      - "IsReadOnly"
;      - "IsHidden"
;      - "IsSystem"
;      - "IsArchive"
;      - "IsTemp"
;      - "IsEncrypted"
;      - "IsCompressed"
;      - "IsVirtual"
;         
; return
;   [string] the information or empty string
;
FtpGetFileInfo(ByRef @FindData, InfoName)
{
   if(InfoName == "Name")
   {
      VarSetCapacity(value, 1040, 0)
      DllCall("RtlMoveMemory", "str", value, "uint", &@FindData + 44, "uint", 1040)
      VarSetCapacity(value, -1)
   }
   else if(InfoName == "CreationTime")
   {
      value := NumGet(@FindData, 4) << 32 | NumGet(@FindData, 8)
      value := FileTimeToStr(value)
   }
   else if(InfoName == "LastAccessTime")
   {
      value := NumGet(@FindData, 12) << 32 | NumGet(@FindData, 16)
      value := FileTimeToStr(value)
   }
   else if(InfoName == "LastWriteTime")
   {
      value := NumGet(@FindData, 20) << 32 | NumGet(@FindData, 24)
      value := FileTimeToStr(value)
   }
   else if(InfoName == "Size")
   {
      value := NumGet(@FindData, 28) << 32 | NumGet(@FindData, 32)
   }
   else if(InfoName == "Attrib")
   {
      if(FtpGetFileInfo(@FindData, "IsNormal"))
         value .= "N"
      if(FtpGetFileInfo(@FindData, "IsDirectory"))
         value .= "D"
      if(FtpGetFileInfo(@FindData, "IsReadOnly"))
         value .= "R"
      if(FtpGetFileInfo(@FindData, "IsHidden"))
         value .= "H"
      if(FtpGetFileInfo(@FindData, "IsSystem"))
         value .= "S"
      if(FtpGetFileInfo(@FindData, "IsArchive"))
         value .= "A"
      if(FtpGetFileInfo(@FindData, "IsTemp"))
         value .= "T"
      if(FtpGetFileInfo(@FindData, "IsEncrypted"))
         value .= "E"
      if(FtpGetFileInfo(@FindData, "IsCompressed"))
         value .= "C"
      if(FtpGetFileInfo(@FindData, "IsVirtual"))
         value .= "V"
   }
   else if(InfoName == "IsReadOnly")
   {
      value := (NumGet(@FindData, 0) & 1) != 0 ; FILE_ATTRIBUTE_READONLY
   }
   else if(InfoName == "IsHidden")
   {
      value := (NumGet(@FindData, 0) & 2) != 0 ; FILE_ATTRIBUTE_HIDDEN
   }
   else if(InfoName == "IsSystem")
   {
      value := (NumGet(@FindData, 0) & 4) != 0 ; FILE_ATTRIBUTE_SYSTEM
   }
   else if(InfoName == "IsDirectory")
   {
      value := (NumGet(@FindData, 0) & 16) != 0 ; FILE_ATTRIBUTE_DIRECTORY
   }
   else if(InfoName == "IsArchive")
   {
      value := (NumGet(@FindData, 0) & 32) != 0 ; FILE_ATTRIBUTE_ARCHIVE
   }
   else if(InfoName == "IsNormal")
   {
      value := (NumGet(@FindData, 0) & 128) != 0 ; FILE_ATTRIBUTE_NORMAL
   }
   else if(InfoName == "IsTemp")
   {
      value := (NumGet(@FindData, 0) & 256) != 0 ; FILE_ATTRIBUTE_TEMPORARY
   }
   else if(InfoName == "IsEncrypted")
   {
      value := (NumGet(@FindData, 0) & 2048) != 0 ; FILE_ATTRIBUTE_OFFLINE
   }
   else if(InfoName == "IsOffline") O
   {
      value := (NumGet(@FindData, 0) & 4096) != 0 ; FILE_ATTRIBUTE_ENCRYPTED
   }
   else if(InfoName == "IsCompressed") C
   {
      value := (NumGet(@FindData, 0) & 16384) != 0 ; FILE_ATTRIBUTE_COMPRESSED
   }
   else if(InfoName == "IsVirtual") V
   {
      value := (NumGet(@FindData, 0) & 65536) != 0 ; FILE_ATTRIBUTE_VIRTUAL
   }

   return value
}

; FileTimeToSystemTime: http://msdn2.microsoft.com/en-us/library/ms724280.aspx
FileTimeToStr(FileTime)
{
   VarSetCapacity(SystemTime, 16, 0)
   DllCall("FileTimeToSystemTime", "uint", &FileTime, "uint", &SystemTime)
   return NumGet(SystemTime,2,"short")
      . "/" . NumGet(SystemTime,6,"short")
      . "/" . NumGet(SystemTime,0,"short")
      . " " . NumGet(SystemTime,8,"short")
      . ":" . NumGet(SystemTime,10,"short")
      . ":" . NumGet(SystemTime,12,"short")
      . "." . NumGet(SystemTime,14,"short")
}


Edited to fix typo in example, thanks olfen


Last edited by Andreone on Sat Nov 10, 2007 2:51 pm; edited 1 time in total
Back to top
View user's profile Send private message
Guest






PostPosted: Sat Nov 10, 2007 2:30 pm    Post subject: Reply with quote

Nicely done!
I'll take a look at the filetime problem.
There's a typo in your example:
Code:
hFTP = INetConnect(Server, Port, User, Pwd, "ftp")
Back to top
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Sat Nov 10, 2007 2:31 pm    Post subject: Reply with quote

That was me.
Back to top
View user's profile Send private message Visit poster's website
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Sat Nov 10, 2007 3:00 pm    Post subject: Reply with quote

Quote:
There's a typo in your example:
Code:
hFTP = INetConnect(Server, Port, User, Pwd, "ftp")

Thank you. I have updated the post above to fix this. The correct line is
Code:
hFTP := INetConnect(Server, Port, User, Pwd, "ftp")

Quote:
I'll take a look at the filetime problem.
Thanks, it would be great if everything was working.

Arrow I have forgot to specify something about attributes:
I don't have mapped all possible values. There's still left a few values (3 or 4), like REPARSE_POINT. But, I never see these kind of attributes and I don't think anybody would be interested by them.
It's very easy to add them if needed.
Back to top
View user's profile Send private message
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Sat Nov 10, 2007 4:04 pm    Post subject: Reply with quote

Andreone wrote:
Exclamation There's one thing that doesn't work: getting creation, last access and last write times. The FILETIME structure must be converted to a SYSTEMTIME structure. I have done that using "FileTimeToSystemTime", but I always get "1/1/1601 0:0:0.0".
I don't know what I miss. Maybe something related to time zones.
If somebody could take a look at that, it would be great.

I couldn't find anything suspicious in your code. Maybe FTP servers return only specific times, depending on configuration. In the example below only LastWriteTime ist returned. Memory for the other two values is filled with zeros (see screenshot), thus FileTimeToSystemTime" returns "1/1/1601 0:0:0.0", which is correct.
It think to confirm this, it would be best to test with a FTP server run locally.
Code:
INetStart()

hFTP := INetConnect("ftp.adobe.com", 21, "anonymous", "anonymous", "ftp")

if(hFTP)
{
if((hEnum := FtpFindFirstFile(hFTP, "license.txt", FTPData)))
{
   Loop
   {
      FileName := FtpGetFileInfo(FTPData, "Name")
      Size := FtpGetFileInfo(FTPData, "Size")
      IsDir := FtpGetFileInfo(FTPData, "IsDirectory")
      Attrib := FtpGetFileInfo(FTPData, "Attrib")
      CreationTime := FtpGetFileInfo(FTPData, "CreationTime")
      msgbox FileName=%FileName%`nSize=%Size%`nDir=%IsDir%`nAttrib=%Attrib%`nCreationTime=%CreationTime%
      MsgBox % FtpGetFileInfo(FTPData, "LastWriteTime")
      if(!FtpFindNextFile(hEnum, FTPData))
         break
   }
}
INetCloseHandle(hEnum)
INetCloseHandle(hFTP)
}

INetStop()

Back to top
View user's profile Send private message Visit poster's website
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Mon Nov 12, 2007 5:56 pm    Post subject: Reply with quote

AAARRRRRGGGGGG!
After a lot and a lot of tests, a lot of research, I'm still unable to get correct time values. There is clearly something wrong in the code because a C++/MFC application that use wininet.dll is able to provide times. I've look into the c++ code but cannot find hints. This is a nightmare.

Here's a new version of FileTimeToStr(ByRef @FileTime) that works fine (I tested it using Skan's post http://www.autohotkey.com/forum/topic8728-60.html ProcessCreationTime() (This is how I realize that binaries values MUST be passed as ByRef arguments).
The returned date/time is also compatible with ahk function FormatTime.

Code:

; FileTimeToSystemTime: http://msdn2.microsoft.com/en-us/library/ms724280.aspx
;~ typedef struct _SYSTEMTIME {
;~   WORD wYear;
;~   WORD wMonth;
;~   WORD wDayOfWeek;
;~   WORD wDay;
;~   WORD wHour;
;~   WORD wMinute;
;~   WORD wSecond;
;~   WORD wMilliseconds;
;~ } SYSTEMTIME;
FileTimeToStr(ByRef @FileTime)
{
   VarSetCapacity(SystemTime, 16, 0)
   DllCall("FileTimeToLocalFileTime", "uint", &@FileTime, "uint", &@FileTime)
   DllCall("FileTimeToSystemTime", "uint", &@FileTime, "uint", &SystemTime)

   str .= NumGet(SystemTime, 0, "ushort")
   str .= StrLen(Word := NumGet(SystemTime,  2,"ushort")) == 1 ? ("0" . Word) : Word
   str .= StrLen(Word := NumGet(SystemTime,  6,"ushort")) == 1 ? ("0" . Word) : Word
   str .= StrLen(Word := NumGet(SystemTime,  8,"ushort")) == 1 ? ("0" . Word) : Word
   str .= StrLen(Word := NumGet(SystemTime, 10,"ushort")) == 1 ? ("0" . Word) : Word
   str .= StrLen(Word := NumGet(SystemTime, 12,"ushort")) == 1 ? ("0" . Word) : Word
   return str
}
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group