Page 1 of 1

FTP?

Posted: Tue Aug 25, 2020 10:10 pm
by arma
Hello everybody;

I have a sample ftp folder, When i use ftp software such as Filezilla there is no problem. Everything works fine. But when i need to directory list of my ftp folder on my purebasic. I cant get the directory list properly. By the was i use Ubuntu. I didnt try the same code on Windows nor Mac OSX. Maybe this is related to Ubuntu. Maybe all does the same. But i wonder if there is any way to get ftp list properly on purebasic (Ubuntu)
My sample code is below. Any solution for me?

InitNetwork()
If OpenFTP(0,"ftp.armacomputer.com.tr","test","denemeX1453")
If ExamineFTPDirectory(0)
While NextFTPDirectoryEntry(0)
Debug FTPDirectoryEntryName(0)
Wend
FinishFTPDirectory(0)
EndIf
Else
Debug "Can't connect to ftp"
EndIf

Re: FTP?

Posted: Wed Aug 26, 2020 6:51 am
by infratec
Your code results in:

Code: Select all

11911 7
11911 4
11911 11
On Win10 x64 with PB 5.72 x86

Re: FTP?

Posted: Wed Aug 26, 2020 10:08 am
by Wolfram
Same her, macOS 10.13.6.

Code: Select all

11911 7
11911 4
11911 11
EDIT: But if I use my FTP Client I see 11 files with the name 1 to 11. So something must be wrong on the PB code.

Re: FTP?

Posted: Wed Aug 26, 2020 10:36 am
by NicTheQuick
Really a strange behaviour. I guess this is a bug from Purebasic.

Re: FTP?

Posted: Wed Aug 26, 2020 11:19 am
by ChrisR
I have the same result with the 3 files listed on win10 x64 (19041).
With Filezilla (unknown certificate to approve) or with ftp.exe cmdline, I have the 11 files listed.
Very strange indeed and the code is the same as in the help!

Re: FTP?

Posted: Wed Aug 26, 2020 11:44 am
by infratec
Even more strange:

Code: Select all

InitNetwork()
ftp = OpenFTP(#PB_Any, "ftp.armacomputer.com.tr","test","denemeX1453")
If ftp
  If ExamineFTPDirectory(ftp)
    While NextFTPDirectoryEntry(ftp)
      Debug FTPDirectoryEntryName(ftp)
      Debug FTPDirectoryEntryRaw(ftp)
    Wend
    FinishFTPDirectory(ftp)
  EndIf
Else
  Debug "Can't connect to ftp"
EndIf
Just checked with WireShark:
the ftp connection itself is Ok.
The LIST command results in 11 entries:

Code: Select all

Line-based text data (11 lines)
    08-25-20  11:59PM                11911 1\r\n
    08-25-20  11:59PM                11911 10\r\n
    08-25-20  11:59PM                11911 11\r\n
    08-25-20  11:59PM                11911 2\r\n
    08-25-20  11:59PM                11911 3\r\n
    08-25-20  11:59PM                11911 4\r\n
    08-25-20  11:59PM                11911 5\r\n
    08-25-20  11:59PM                11911 6\r\n
    08-25-20  11:59PM                11911 7\r\n
    08-25-20  11:59PM                11911 8\r\n
    08-25-20  11:59PM                11911 9\r\n
But the result is like above starting with 11911 7 if I use FTPDirectoryEntryName(ftp)
and starting with 11911 5 if I use FTPDirectoryEntryRaw(ftp)

But ....

It is a 'Microsoft FTP service' and not a unix one.
Read the help for ExamineFTPDirectory()

Maybe the 'structure' of the list result differs.

Re: FTP?

Posted: Wed Aug 26, 2020 11:18 pm
by arma
So? If server is Microsofts? Cant get proper directory list? All the ftp software works fine... Maybe this is purebasic bug?

Re: FTP?

Posted: Thu Aug 27, 2020 9:40 am
by BarryG
Screenshot showing PureBasic debug output result, and FileZilla list -> https://i.imgur.com/38LBpiD.png

Re: FTP?

Posted: Thu Aug 27, 2020 10:57 am
by ChrisR
As the Help says ExamineFTPDirectory() does not seem to be implemented for non-Unix/Linux servers.

However, the 11 files are well listed, if I use the Flype code that uses WinINet API (InternetOpen, InternetConnect, FtpFindFirstFile, InternetFindNextFile,...)

Code: Select all

EnableExplicit

#FTP_TRANSFER_ASCII  = 1
#FTP_TRANSFER_BINARY = 2

#INTERNET_SERVICE_FTP = 1
#INTERNET_OPEN_TYPE_DIRECT = 1

Import "shlwapi.lib"
StrFormatByteSize64A(Size.q, *BufStr, BufSize.l)
EndImport

Procedure.s StrByteSize(nBytes.q)
  
  Protected string.s{64}
  
  If StrFormatByteSize64A(nBytes, @string, 64)
    ProcedureReturn PeekS(@string, -1, #PB_Ascii)
  EndIf
  
EndProcedure

;============================================
Structure FILESIZE
  High.l
  Low.l
EndStructure
Structure WIN32_FIND_DATA_2
  dwFileAttributes.l
  ftCreationTime.FILETIME
  ftLastAccessTime.FILETIME
  ftLastWriteTime.FILETIME
  nFileSizeLow.l
  nFileSizeHigh.l
  dwReserved0.l
  dwReserved1.l
  cFileName.s{260} ; replaced by fixed string
  cAlternate.s{14} ; replaced by fixed string
  dummy.w
EndStructure

Macro FtpOpen(Proxy = "", ProxyBypass = "")
  InternetOpen_("FTP", #INTERNET_OPEN_TYPE_DIRECT, Proxy, ProxyBypass, 0)
EndMacro
Macro FtpClose(hInternet)
  InternetCloseHandle_(hInternet)
EndMacro
Macro FtpConnect(hInternet, Host, User, Pwd, Port = 21)
  InternetConnect_(hInternet, Host, Port, User, Pwd, #INTERNET_SERVICE_FTP, 0, 0)
EndMacro
Macro FtpDisconnect(hConnect)
  InternetCloseHandle_(hConnect)
EndMacro

;============================================
Procedure.l FtpListAll(hConnect.l, folder.s = "/", depth.l = 0)
  
  Protected hFind.l, Size.q, NewList find.WIN32_FIND_DATA_2()
  
  If FtpSetCurrentDirectory_(hConnect, folder) And AddElement(find())
    hFind = FtpFindFirstFile_(hConnect, 0, find(), 0, 0)
    If hFind
      While AddElement(find()) And InternetFindNextFile_(hFind, find())
        ; Delay(1)
      Wend
      InternetCloseHandle_(hFind)
      DeleteElement(find())
    EndIf
  EndIf
  
  ForEach find()
    If find()\dwFileAttributes & #FILE_ATTRIBUTE_DIRECTORY
      AddGadgetItem(0, -1, "[DIR] " + find()\cFileName, 0, depth)
      FtpListAll(hConnect, folder + find()\cFileName + "/", depth + 1)
    Else
      PokeL(@Size + 4, find()\nFileSizeLow)
      PokeL(@Size + 0, find()\nFileSizeHigh)
      AddGadgetItem(0, -1, "[FILE] " + find()\cFileName + " (" + StrByteSize(Size) + ")", 0, depth)
    EndIf
  Next
  
EndProcedure

;============================================
Define ftp.l, conn.l

If OpenWindow(0, 0, 0, 640, 480, "Ftp", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 620, 460, #PB_Tree_AlwaysShowSelection)
  
  ftp = FtpOpen()
  If ftp
    ;conn = FtpConnect(ftp, "localhost", "user", "pwd")
    conn = FtpConnect(ftp, "ftp.armacomputer.com.tr", "test", "denemeX1453")
    If conn
      FtpListAll(conn, "/") ; <---- recursive proc
      FtpDisconnect(conn)
    EndIf
    FtpClose(ftp)
  EndIf
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow: Break
      Case #PB_Event_SizeWindow:  ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0)-20, WindowHeight(0)-20)
    EndSelect
  ForEver
  
EndIf

Re: FTP?

Posted: Thu Aug 27, 2020 4:50 pm
by Paul
Is no one questioning why Debug FTPDirectoryEntryName(0) is returning the filesize plus filename ?

If the filename is "1" why is FTPDirectoryEntryName(0) returning "11911 1" instead of "1"
and why does FTPDirectoryEntrySize(0) return "11" instead of "11911"

I would guess that whatever FTP server you are connecting to is returning data that PB is not expecting so it is not able to parse the data correctly.
If I access my own FTP server the PB code works as expected.

Re: FTP?

Posted: Fri Aug 28, 2020 10:54 am
by NicTheQuick
Yes, that's the issue. I thought everybody had understood that. The output of the FTP LIST command is different on a Microsoft FTP server. Purebasic simply parses the result of the LIST command but assumes it is in the style of UNIX FTP-Server.

Re: FTP?

Posted: Sat Aug 29, 2020 1:42 am
by arma
so? what is the solution? I use linux... the code is upside doesnt work for me...

Re: FTP?

Posted: Sat Aug 29, 2020 10:49 am
by infratec
With Linux you can use libcurl.
Also in Windows if you use the external libcurl.dll.

Use libcurl.pbi

and

Code: Select all

IncludeFile "LibCurl.pbi"

curl = curl_easy_init()
If curl
  curl_easy_setopt_str(curl, #CURLOPT_URL, "ftp://test:denemeX1453@ftp.armacomputer.com.tr/")
  
  curl_easy_setopt(curl, #CURLOPT_WRITEFUNCTION, @LibCurl_WriteFunction())
  
  ; List only
  curl_easy_setopt(curl, #CURLOPT_DIRLISTONLY, 1)
  
  If curl_easy_perform(curl) = #CURLE_OK
    result$ = LibCurl_GetData()
    
    MessageRequester("", result$)
  EndIf
  
  curl_easy_cleanup(curl)
EndIf
viewtopic.php?p=591235

The libcurl.pbi inside the zip file should work in Linux.

P.S.: It works, just tested it via RDP to our company Debian 10 developping linux server.
Had to correct libcurl.pbi to LibCurl.pbi (done in the listing above)

Re: FTP?

Posted: Sat Aug 29, 2020 11:49 am
by ChrisR
Thanks for libcurl.pbi
I have better results with aria2c for some files that fail to download with libcurl (I don't remember why, I would have to look for).
I use via cmdline: aria2c.exe --log-level=notice --log="%Temp%\Aria2c_Download.log" -x16 -s16 --allow-overwrite=true --auto-file-renaming=false -d"PATH" -o"FILENAME" "URL"
Is there a module already made that uses aria: The ultra fast download utility ?