|
Post by James Grubbs (Jimmy) on Jan 2, 2024 17:03:12 GMT -5
I am having trouble using ftp4w32.dll to properly transfer a file. I can upload and download the file but it changes the contents of the file making it unusable. I can manually transfer the file using filezilla with no trouble. It adds bytes to the file every time. Any help would be greatly appreciated. I'm not against using another method to transfer the file but it needs to integrate into my program. Thank You
|
|
|
Post by Chris Iverson on Jan 2, 2024 21:53:15 GMT -5
Do you know what bytes are being added?
Going on the assumption that the bytes being added are end-of-line characters, what transfer method are you using to transfer the file?
I'm not sure how ftp4w32.dll transfers the file, but if it has a choice between ASCII/text and binary modes, use the binary mode.
|
|
|
Post by James Grubbs (Jimmy) on Jan 2, 2024 22:09:31 GMT -5
This is the info I found on the DLL on the wayback machine from the creator. This DLL was posted on alyce's website years ago. web.archive.org/web/20031217150635/http://membres.lycos.fr/phjounin/P_ftp4w.htmhere's the syntax for changing the the mode FtpSetType This function changes the default transfer type. Syntax: FtpSetType (char cType) Argument: cType new default transfer mode (either TYPE_A or TYPE_I) here's the code nomainwin
dim error$(6000)
error$( 0) ="No problem.." error$( 1003) ="user not connected to server" error$( 1004) ="cannot open file" error$( 1008) ="action not taken" error$( 1010) ="server cannot open file" error$( 3001) ="3001" error$( 5002) ="5002"
WindowWidth = 800 WindowHeight = 550
global parentftp, port, pasv, ftphost$, login$, password$, initpath$, upload$, serverFile$, backLocal$, TRUE, FALSE, ftpsession
port = 21 'port to use. pasv = 1 'PASV mode? 1 is yes, 0 is no. ftphost$ = "ftp.byethost11.com" 'ftp site address. login$ = "" 'ftp site username login. password$ = "" 'ftp site password. initpath$ = "htdocs" 'leave blank if you want the site's default. 'upload$ = DefaultDir$+"/testing.txt" 'full path & file info for local file to upload. NB could all be the same... serverFile$ = "decenc.enc" 'what file is called on the ftp server. backLocal$ = "decenc.enc" 'what to call the returned local downloaded file.
TRUE = 1 FALSE = 0
ftpsession = FALSE
button #w.b1, " Upload ", [upload], LR, 550, 50, 110, 30 button #w.b2, "Download", [download], LR, 400, 50, 110, 30 button #w.b3, "Server dir'y", [remoteDir], LR, 250, 50, 110, 30
texteditor #w.te, 10, 10, 740, 400
open "LB" for window as #w
#w "trapclose [quit.main]"
#w "font bold 12"
parentftp =hwnd( #w)
wait
[upload] filedialog "Open file", "*.*", upload$ if upload$<>"" then serverFile$=afterlast$(upload$, "\") else notice "No file chosen!" wait end if call action "upload" wait
[download] call action "download" wait
[remoteDir] call action "Server dir'y" wait
sub action command$ ' Implements at present file upload/download ( with renaming if you want) and remote direstory listing. open "ftp4w32.dll" for dll as #ftp ftpsession = TRUE calldll #ftp, "FtpInit", parentftp as long, res as long : #w.te "Initialising "; res; " "; error$( res) calldll #ftp, "FtpSetSynchronousMode", void as long : #w.te "Mode set async" calldll #ftp, "FtpSetDefaultPort", port as long, void as long : #w.te "Port set 21" calldll #ftp, "FtpSetPassiveMode", pasv as long, void as long : #w.te "Mode set passive" calldll #ftp, "FtpLogin", ftphost$ as struct, login$ as struct, password$ as struct, parentftp as long, 0 as long, res as long: #w.te "Logging in. Returned "; res calldll #ftp, "FtpCWD", initpath$ as struct, res as long : #w.te "Change remote working directory " ; res; " "; error$( res); " " 'calldll #ftp, "FtpSetType", <-------I Don't know how to add the mode if command$ ="upload" then calldll #ftp, "FtpSendFile", upload$ as struct, serverFile$ as_ struct, 0 as long, 0 as long, parentftp as long, 0 as long, res as long:_ #w.te "Sent file "; upload$; " as "; serverFile$; " & received error "; error$( res) end if
if command$ ="download" then calldll #ftp, "FtpRecvFile", serverFile$ as struct, backLocal$ as_ struct, 0 as long, 0 as long, parentftp as long, 0 as long, res as long:_ #w.te "Requesting file "; serverFile$; " for download as "; backLocal$;_ " error ="; res; " "; error$( res) end if
if command$ ="Server dir'y" then dirlist$ ="ftplist.tmp": argument$ ="" calldll #ftp, "FtpDir", argument$ as struct, dirlist$ as struct, 1 as long, parentftp as long, 0 as long, res as long:_ #w.te "Dir'y listing..": #w.te argument$ open dirlist$ for input as #fIn content$ =input$( #fIn, lof( #fIn)) close #fIn kill dirlist$ #w.te content$ end if
[closeftp] calldll #ftp, "FtpCloseConnection", void as long: #w.te "Connection closed... "; calldll #ftp, "FtpRelease", void as long : #w.te " .. and released." close #ftp ftpsession = FALSE
#w.te "__________________________________" #w.te ""
end sub
[quit.main] close #w if ftpsession = TRUE then calldll #ftp, "FtpCloseConnection", void as long calldll #ftp, "FtpRelease", void as long close #ftp end if end
' Initialising 0 No problem.. ' Mode set async ' Port set 21 ' Mode set passive ' Logging in. Returned 0 ' Sent file exampleN4.txt & received error No problem.. ' Dir'y listing..
' drwx------ 1 user group 138 Mar 09 16:06 My Documents ' drwx------ 1 user group 3093195 Mar 09 16:06 My Pictures ' drwx------ 1 user group 111 Mar 11 20:56 tenoch ' drwx------ 1 user group 24332 Mar 09 16:06 wwwhome ' drwx------ 1 user group 0 Mar 12 12:55 drivehqshare ' -rwx------ 1 user group 23 Mar 09 16:53 example.txt ' -rwx------ 1 user group 34 Mar 10 18:49 exampleN.txt ' -rwx------ 1 user group 33 Mar 10 19:32 exampleN2.txt ' -rwx------ 1 user group 44 Mar 11 21:47 exampleN3.txt ' -rwx------ 1 user group 129 Mar 12 12:54 exampleN4.txt ' -rwx------ 1 user group 129 Mar 12 12:55 exampleN4c.txt ' Requesting file exampleN4c.txt for download ; error =0 No problem.. ' Connection closed ' .. and released.
calldll #ftp, "FtpDeleteFile",_ del$ as struct,_ res as long
calldll #ftp, "FtpRMD",_ del$ as struct,_ res as long
|
|
|
Post by Chris Iverson on Jan 3, 2024 2:33:02 GMT -5
I was wondering why this seemed familiar.
I can't find the post now, but I've done the work before to figure out what needed to go there. Since the sample code and source code packages were lost(zips are missing from archive.org), I went to disassemble the DLL in ghidra to figure it out... and I found my already existing disassembly from when I did the same thing before.
The FtpSetType call sets the default transfer type, and the transfer type can also be changed each transfer using the third parameter of the FtpSendFile function.
According to the disassembly, the acceptable types are "A", "I", and "L". Not sure what "L" is, but considering what documentation IS available says to choose between TYPE_A and TYPE_I, I'm going to guess "I" is what's needed(since I'm also assuming "A" = "ASCII").
So, try this before sending/retrieving files:
CallDLL #ftp, "FtpSetType",_ "I" as char[1],_ ret as long
I think that should do it.
|
|
|
Post by metro on Jan 3, 2024 4:45:39 GMT -5
|
|
|
Post by James Grubbs (Jimmy) on Jan 3, 2024 23:36:40 GMT -5
|
|
|
Post by James Grubbs (Jimmy) on Jan 3, 2024 23:48:55 GMT -5
Chris, Thank you so much for your solution and it saved me. It didn't function exactly as you posted but it was enough for me to work with.
here's what worked
CallDLL #ftp, "FtpSetType", "I" as long, res as long
I, like you, assume "I" is for binary and "A" would be ascii
believe it or not, I'm certain this has been a major problem since 2003. I hope others see the solution.
Thank you again for saving me once again!!!!
|
|
|
Post by Chris Iverson on Jan 4, 2024 2:34:31 GMT -5
Interesting, I didn't think you'd be able to do "I" as long. I would thing you'd have to do ASC("I") to pass it as a long.
I'm also somewhat surprised that worked, but it might be because it's the last parameter.
The reason I'm surprised is because that parameter is declared as a CHAR, which is one byte. LB doesn't actually have a one-byte parameter. LONG passes four bytes. But with it being the last parameter, it winds up working out.
Also, for anyone interested, I was actually able to find that zip file mentioned on the website, with the original header file and sample files. It's not on archive.org, but there's literally ONE website on the internet that has archives of a bunch of mid-to-late-90's-era software, including this one. It does confirm that the letters are correct.
/* ASCII or binary transfer */ #define TYPE_A 'A' #define TYPE_I 'I' #define TYPE_L8 'L' #define TYPE_DEFAULT 0
I looked up more info, TYPE_L is actually a special FTP type that allows you to configure how many bits are in a byte. (L8 means 8 bits in a byte.) This is ANCIENT configuration info, dating back to the days when there were systems that didn't use 8-bit bytes.
It can just be ignored nowadays, and you can perform transfers with TYPE_A or TYPE_I. (Quite frankly, you'd probably be better off just doing all transfers with TYPE_I. If I get curious enough, I might make a modified version of the DLL that defaults to TYPE_I.)
|
|
|
Post by James Grubbs (Jimmy) on Jan 8, 2024 19:21:36 GMT -5
Sorry for the delayed response, I was out of town. Chris, I admit I had no clue here why that worked but for whatever reason it hasn't failed me since. I fooled around for several evenings with no luck until I asked you here. If you hadn't responded, I would have never got it working. I actually purchased Alyce's DLL guide for liberty basic a couple years ago when it was republished and need to study it again. I don't use DLL's often and have CRS disease LOL
|
|