Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

DllCall: Basic FTP Functions


  • Please log in to reply
33 replies to this topic
olfen
  • Members
  • 115 posts
  • Last active: Dec 25 2012 09:48 AM
  • Joined: 04 Jun 2005
Not heavily tested. Feel free to revise and add more.
I think the call to InternetOpenA needs refinement regarding the proxy settings. I don't have the knowledge to do so.

/*
http://msdn.microsoft.com/library/en-us/wininet/wininet/ftp_sessions.asp
http://msdn.microsoft.com/library/en-us/wininet/wininet/internetopen.asp
http://msdn.microsoft.com/library/en-us/wininet/wininet/internetconnect.asp
*/

FtpCreateDirectory(DirName) {
global ic_hInternet
r := DllCall("wininet\FtpCreateDirectoryA", "uint", ic_hInternet, "str", DirName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpRemoveDirectory(DirName) {
global ic_hInternet
r := DllCall("wininet\FtpRemoveDirectoryA", "uint", ic_hInternet, "str", DirName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpSetCurrentDirectory(DirName) {
global ic_hInternet
r := DllCall("wininet\FtpSetCurrentDirectoryA", "uint", ic_hInternet, "str", DirName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpPutFile(LocalFile, NewRemoteFile="", Flags=0) {
;Flags:
;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY)
;FTP_TRANSFER_TYPE_ASCII = 1
;FTP_TRANSFER_TYPE_BINARY = 2
If NewRemoteFile=
NewRemoteFile := LocalFile
global ic_hInternet
r := DllCall("wininet\FtpPutFileA"
, "uint", ic_hInternet
, "str", LocalFile
, "str", NewRemoteFile
, "uint", Flags
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpGetFile(RemoteFile, NewFile="", Flags=0) {
;Flags:
;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY)
;FTP_TRANSFER_TYPE_ASCII = 1
;FTP_TRANSFER_TYPE_BINARY = 2
If NewFile=
NewFile := RemoteFile
global ic_hInternet
r := DllCall("wininet\FtpGetFileA"
, "uint", ic_hInternet
, "str", RemoteFile
, "str", NewFile
, "int", 1 ;do not overwrite existing files
, "uint", 0 ;dwFlagsAndAttributes
, "uint", Flags
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpGetFileSize(FileName, Flags=0) {
;Flags:
;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY)
;FTP_TRANSFER_TYPE_ASCII = 1
;FTP_TRANSFER_TYPE_BINARY = 2
global ic_hInternet
fof_hInternet := DllCall("wininet\FtpOpenFileA"
, "uint", ic_hInternet
, "str", FileName
, "uint", 0x80000000 ;dwAccess: GENERIC_READ
, "uint", Flags
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or fof_hInternet = 0)
return -1

FileSize := DllCall("wininet\FtpGetFileSize", "uint", fof_hInternet, "uint", 0)
DllCall("wininet\InternetCloseHandle",  "UInt", fof_hInternet)
return, FileSize
}


FtpDeleteFile(FileName) {
global ic_hInternet
r :=  DllCall("wininet\FtpDeleteFileA", "uint", ic_hInternet, "str", FileName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpRenameFile(Existing, New) {
global ic_hInternet
r := DllCall("wininet\FtpRenameFileA", "uint", ic_hInternet, "str", Existing, "str", New)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}

FtpOpen(Server, Port=21, Username=0, Password=0 ,Proxy="", ProxyBypass="") {
IfEqual, Username, 0, SetEnv, Username, anonymous
IfEqual, Password, 0, SetEnv, Password, anonymous

If (Proxy != "")
AccessType=3
Else
AccessType=1
;#define INTERNET_OPEN_TYPE_PRECONFIG                    0   // use registry configuration
;#define INTERNET_OPEN_TYPE_DIRECT                       1   // direct to net
;#define INTERNET_OPEN_TYPE_PROXY                        3   // via named proxy
;#define INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  4   // prevent using java/script/INS

global ic_hInternet, io_hInternet, hModule
hModule := DllCall("LoadLibrary", "str", "wininet.dll")

io_hInternet := DllCall("wininet\InternetOpenA"
, "str", A_ScriptName ;lpszAgent
, "UInt", AccessType
, "str", Proxy
, "str", ProxyBypass
, "UInt", 0) ;dwFlags

If (ErrorLevel != 0 or io_hInternet = 0) {
FtpClose()
return 0
}

ic_hInternet := DllCall("wininet\InternetConnectA"
, "uint", io_hInternet
, "str", Server
, "uint", Port
, "str", Username
, "str", Password
, "uint" , 1 ;dwService (INTERNET_SERVICE_FTP = 1)
, "uint", 0 ;dwFlags
, "uint", 0) ;dwContext

If (ErrorLevel != 0 or ic_hInternet = 0)
return 0
else
return 1
}

FtpClose() {
global ic_hInternet, io_hInternet, hModule
DllCall("wininet\InternetCloseHandle",  "UInt", ic_hInternet)
DllCall("wininet\InternetCloseHandle",  "UInt", io_hInternet)
DllCall("FreeLibrary", "UInt", hModule)
}
Edit 20071020: Added global hModule in FtpOpen and FtpClose

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
For most purposes, this method seems superior to the FileAppend + Ftp method. Thanks for posting it.

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004
Thanks :) . Very handy.

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
For general use this is a great solution I was searching for!

But be shure not to use this with your ftp-settings in a freeware (or similar).
2 days ago I heard from a game that updates it's highscore via FTP.
A friend of me was asked to test the game from the author and sent him back servername, username and even password for full access!
The password was encrypted, but this is no problem even for low-level-debugger. (The game isn't online any more until finishing development ^^)

Thalon

Veovis
  • Members
  • 389 posts
  • Last active: Mar 17 2009 12:24 AM
  • Joined: 13 Feb 2006
LOL
Posted Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."

olfen
  • Members
  • 115 posts
  • Last active: Dec 25 2012 09:48 AM
  • Joined: 04 Jun 2005
I fully agree with your security related objections, Thalon.
But even if the hardcoded access data were protected by means of encryption or even anti-debugging code (which is not an obstacle for some people), it still would be easy enough to sniff the relevant data using a network protocol analyzer.

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
I suppose that's why SFTP was invented...
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

olfen
  • Members
  • 115 posts
  • Last active: Dec 25 2012 09:48 AM
  • Joined: 04 Jun 2005

I suppose that's why SFTP was invented...

Good guess :wink:

As for anti-debugging: This will detect OllyDbg and probably some others:
;http://msdn.microsoft.com/library/en-us/debug/base/isdebuggerpresent.asp
r := DllCall("IsDebuggerPresent")
IfEqual, r, 0, MsgBox No debugger present.
IfEqual, r, 1, MsgBox Debugger detected.

Edit: Google references tell me that many debuggers can be hidden from this function, so can OllyDbg :?

Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005
Great job, olfen; very useful!

I just noticed that a return value of 1 means success while 0 means failure.
ErrorLevel values are usually the other way round; any special reason for choosing to do it this way?
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey

Elevator_Hazard
  • Members
  • 297 posts
  • Last active: Feb 07 2011 12:10 AM
  • Joined: 28 Oct 2006
Although this post is a little old, can someone show me an example usage that would work? Like no variables in the params so I know what the domain name should look like and such, because I always get confused about that. Of course you can omit the password, I just need to know how to work it.
Changed siggy at request of ahklerner :D

Ace_NoOne
  • Members
  • 299 posts
  • Last active: May 02 2008 08:19 AM
  • Joined: 10 Oct 2005

can someone show me an example usage that would work?

Sure; below are three essential (though very simple) routines, pulled from my FtpUploader script, which makes heavy use of these functions. I've also included some sample values for the variables used; that should give you everything you need to get started.
; sample values
FtpHost = autohotkey.net
FtpPort = 21
FtpUsername = AhkH4x0r
FtpPassword = Ahk1337
localFile = C:\FtpTest.txt
remoteFile = test/FtpTest.txt

; establish connection to FTP server
connect:
	FtpConnection := FtpOpen(FtpHost, FtpPort, FtpUsername, FtpPassword)
	If (FtpConnection != 1)
	{
		MsgBox, Error connecting to FTP server.
		GoSub, quit
	}
Return

; upload file
uploadFile:
    ; establish connection to FTP server
	GoSub, connect
	; store file on FTP server
	fileTransfer := FtpPutFile(localFile, remoteFile)
	If (fileTransfer != 1)
	{
		MsgBox, Error uploading file.
		GoSub, quit
	}
	; close connection
	FtpClose()
	; confirmation message
	MsgBox, Upload complete.
	; terminate script
	GoSub, quit
Return

; download file
downloadFile:
    ; establish connection to FTP server
	GoSub, connect
	; retrieve file from FTP server
	fileTransfer := FtpGetFile(remoteFile, localFile)
	If (fileTransfer != 1)
	{
		MsgBox, Error downloading file.
		GoSub, quit
	}
	; close connection
	FtpClose()
	; confirmation message
	MsgBox, Download complete.
	; terminate script
	GoSub, quit
Return
HTH.


PS: That "Windows XP Scream" logo in your sig is awesome! (Though hotlinking it, that's evil... :p )
Improving my world, one script at a time.
Join the AutoHotkey IRC channel: irc.freenode.net #autohotkey

Elevator_Hazard
  • Members
  • 297 posts
  • Last active: Feb 07 2011 12:10 AM
  • Joined: 28 Oct 2006
Oops I forgot to say thanks yesterday. Thanks :D It really helped. And I didn't want to discredit the people who used that picture that is my siggy :D

Again thanks.
Changed siggy at request of ahklerner :D

Helpy
  • Guests
  • Last active:
  • Joined: --

And I didn't want to discredit the people who used that picture that is my siggy :D

I am not sure to understand this sentence.
Anyway, what Ace_NoOne meant is that you get the picture directly from apcmag.com site, which is stealing their bandwidth.

Even worse, this picture is quite heavy: 32KB, compare to size of most other avatars here. Sometime the loading of a topic is slow down because you posted there. Seriously (I am on broadband, not on dialup!).

Elevator_Hazard
  • Members
  • 297 posts
  • Last active: Feb 07 2011 12:10 AM
  • Joined: 28 Oct 2006
Oopsies... I'll change it to .gif and put it on some site of mine. Thanks for bringing this up.
Changed siggy at request of ahklerner :D

Helpy
  • Guests
  • Last active:
  • Joined: --
Aha, much better, thanks. I really can sense the difference in download time. It seems AHK isn't a very fast server (but good enough, mind you).
Sorry, olfen, for being off topic, although netiquette is an important aspect of the Web, so not far from FTP, somehow...