Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2017-11

Getting strange FTP error using Indy 10 idFTP

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

I am writing a simple Delphi7/FPC compatible console application in order to use in a daily task to transfer a backup zipfile from a server to my Windows 7 laptop. The task is a bat script that does a lot of other stuff as well as the FTP and it has been a struggle setting ftp up for batch file operation so I decided to write this console app to better integrate into the bat file.

To this end I have the following code (only showing the relevant stuff:

uses
SysUtils,
Classes,
IdFTP,
IdComponent,

  IniFiles;
var
  FTP: TIdFTP;
  FTPHost,
  FTPUser,
  FTPPwd: string;
  FTPPort: word;
  FList: TStringList;
...
function ConnectFTP: boolean;
begin
  Result := false;
  try
    if FTP.Connected then
    begin
      LogMessage('Already connected to ' + FTPHost);
      Result := true;
      exit;
    end;
    FTP.Host := FTPHost;  //remote server by computer name
    FTP.Port := FTPPort;  //remote port is 2121
    FTP.Username := FTPUser;  //Windows username
    FTP.Password := FTPPwd;   //Windows password
    FTP.Connect;
    if not FTP.Connected then
    begin
      LogError('Could not connect by FTP');
    end
    else
      LogMessage('Connected to ' + FTPHost);
    Result := FTP.Connected;
  except
    on E: Exception do
      LogException(E.Message);
  end;
end;
procedure ListFiles(var Lst: TStringList);
{Get a directory listing of remote ftp server's current dir}
var
  Res: string;
begin
  if not FTP.Connected then
    ConnectFTP;
  if not FTP.Connected then
    exit;
  try
    FTP.List(Res); // <== EXCEPTION HERE!
    Lst.Text := Res;
    LogMessage(Lst.Text);
  except
    on E: Exception do
      LogException(E.Message);
  end;
end;

....

begin
  FTP := TIdFTP.Create;
  FList := TStringList.Create;
  try
    GetConfig; //Retrieve configuration from ini file
    LogMessage('Starting FTP transfer from ' + FTPHost);
    if not ConnectFTP then
    begin
      LogError('Could not connect to ' + FTPHost + ' on port ' +
IntToStr(FTPPort));
      ExitCode := 1;
      Exit;
    end;
  //Now read directory on target
  ListFiles(FList);
.... more code here ....
  LogMessage('Finished transfer');
  finally
    FList.Free;
    if FTP.Connected then
      FTP.Disconnect;
    FTP.Free;
  end;
end.

What I get is an exception in my logfile saying:

20:14:01.018 EXCEPTION: Invalid PORT Command.

I have tried to trace it into the Indy sources but I get lost there and as soon as I release the execution I have the exception trigger.

The FTP server is on a Windows Server 2003 and it works OK using FileZilla and the Windows built-in FTP client as well as a FTP testing utility I have build years ago.

From this utility I have basically cut the code shown above and yet I

get the error when trying FTP.List()...

Normally when dealing with Indy errors I post on the Embarcadero Forum Delphi.Internet.Winsock using a newsreader. THen I usually get replies from Remy Lebeau.
But now it seems like the Embarcadero servers have crashed again so the forums are down.
Hence I am hoping for some help here...

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Zoë Peterson
Zoë Peterson wrote 9 lines
On 11/22/2017 1:50 PM, Bo Berglund wrote: > 20:14:01.018 EXCEPTION: Invalid PORT Command. Set FTP.Passive := True. PORT is used for active connections, where the server opens a connection to the client computer for the data stream. PASV is used for passive connections, where the client opens a second connection to the server. https://stackoverflow.com/questions/1699145/what-is-the-difference-between-active-and-passive-ftp#1699163

Thanks!
That did the trick!
I was looking down the Windows Firewall settings to see if something there blocked the communications...

It turned out that the old code *had* an FTP.Passive := true;
statement hidden away where I did not notice..

And my code for retrieving the list was also incorrect, I needed FTP.Listresult for that.

Question:
---------
The result off of this Windows server looks very much like a Linux ls -l command result:

-rwxrwxrwx 1 owner group 1572 Sep 28 15:30 Config_2017-09-28.zip
drwxrwxrwx 1 owner group 0 Nov 13 19:30 AGIENG drwxrwxrwx 1 owner group 0 Nov 22 1:05 CVSREPOS drwxrwxrwx 1 owner group 0 Nov 11 15:44 FULLREPO

Is this how it always looks like or is there a way to format the list into something less Linux-ish?

I need to get a list of the files that match a specific format like: <name>_<date>.zip
I could of course traverse the supplied TStrings and look at the first char (discard all d entries) and check if the last part is .zip. But it would be a lot easier if the list could be limited to the filenames only.

The FTP.List() command has a number of overloaded versions and I have yet to find a working documentation of these. So in the absence of Remy Lebeau I am hard pressed to figure it out. And tracing down the Indy sources is not an easy task.
Maybe one of them will produce a simple file list only?

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Bo Berglund
Bo Berglund wrote 6 lines
I need to get a list of the files that match a specific format like: <name>_<date>.zip I could of course traverse the supplied TStrings and look at the first char (discard all d entries) and check if the last part is .zip. But it would be a lot easier if the list could be limited to the filenames only.

In fact the windows7 command line ftp client can do this:

ftp> ls CVS*.zip
200 PORT command successful.
150 Opening ASCII mode data connection for file list. CVS_Config_2017-09-28.zip
226 Transfer complete.

Is there a corresponding way for IdFTP to perform a wildcard list and returning just the matching files?

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Bo Berglund
Bo Berglund wrote 20 lines
On Thu, 23 Nov 2017 00:09:36 +0100, Bo Berglund wrote: >I need to get a list of the files that match a specific format like: ><name>_<date>.zip >I could of course traverse the supplied TStrings and look at the first >char (discard all d entries) and check if the last part is .zip. >But it would be a lot easier if the list could be limited to the >filenames only. In fact the windows7 command line ftp client can do this: ftp> ls CVS*.zip 200 PORT command successful. 150 Opening ASCII mode data connection for file list. CVS_Config_2017-09-28.zip 226 Transfer complete. Is there a corresponding way for IdFTP to perform a wildcard list and returning just the matching files?

For completeness:
-----------------
I received help on the Embarcadero forum which is back on-line, and the following command does what I need:

FTP.List('CVS*.zip', false);

The first argument is a file name specifier string including wildcard
* and the second is a flag to supply full information (true) or only the file names (false).
With this in place my utility works and the code is now much cleaner.

Bo Berglund Developer in Sweden

Reply by email