 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
corrupt
Joined: 29 Dec 2004 Posts: 2393
|
Posted: Tue May 29, 2007 5:07 am Post subject: |
|
|
| Helpy wrote: | | Aha, much better, thanks. I really can sense the difference in download time. | Wow, your connection sucks...  |
|
| Back to top |
|
 |
Tahoma Guest
|
Posted: Fri Sep 14, 2007 11:48 am Post subject: Error message when compiling Ace_NoOne's script |
|
|
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
|
Posted: Fri Sep 14, 2007 11:49 am Post subject: Re: Error message when compiling Ace_NoOne's script |
|
|
| 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 |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Thu Oct 18, 2007 5:27 pm Post subject: |
|
|
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 |
|
 |
olfen
Joined: 04 Jun 2005 Posts: 99 Location: Stuttgart, Germany
|
Posted: Sat Oct 20, 2007 2:30 pm Post subject: |
|
|
| 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 |
|
 |
derjoo Guest
|
Posted: Mon Oct 29, 2007 10:10 am Post subject: |
|
|
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
|
Posted: Mon Oct 29, 2007 12:44 pm Post subject: |
|
|
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 ).
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 |
|
 |
olfen
Joined: 04 Jun 2005 Posts: 99 Location: Stuttgart, Germany
|
Posted: Wed Oct 31, 2007 6:04 pm Post subject: |
|
|
Thanks Andreone. FtpFindFirstFile and FtpCommand would be nice to have, too.  |
|
| Back to top |
|
 |
Andreone
Joined: 20 Jul 2007 Posts: 257 Location: Paris, France
|
Posted: Wed Oct 31, 2007 7:02 pm Post subject: |
|
|
| olfen wrote: | Thanks Andreone. FtpFindFirstFile and FtpCommand would be nice to have, too.  | Ok, I'll add them (but don't be too hurry ) |
|
| Back to top |
|
 |
Andreone
Joined: 20 Jul 2007 Posts: 257 Location: Paris, France
|
Posted: Thu Nov 08, 2007 3:44 pm Post subject: |
|
|
I have added enumeration capabilities:
- FtpFindFirstFile
- FtpFindNextFile
- FtpGetFileInfo
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.
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 |
|
 |
Guest
|
Posted: Sat Nov 10, 2007 2:30 pm Post subject: |
|
|
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
|
Posted: Sat Nov 10, 2007 2:31 pm Post subject: |
|
|
| That was me. |
|
| Back to top |
|
 |
Andreone
Joined: 20 Jul 2007 Posts: 257 Location: Paris, France
|
Posted: Sat Nov 10, 2007 3:00 pm Post subject: |
|
|
| 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.
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 |
|
 |
olfen
Joined: 04 Jun 2005 Posts: 99 Location: Stuttgart, Germany
|
Posted: Sat Nov 10, 2007 4:04 pm Post subject: |
|
|
| Andreone wrote: | 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 |
|
 |
Andreone
Joined: 20 Jul 2007 Posts: 257 Location: Paris, France
|
Posted: Mon Nov 12, 2007 5:56 pm Post subject: |
|
|
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 |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|