Problems with Indy 10 FTP component

Giganews Newsgroups
Subject: Problems with Indy 10 FTP component
Posted by:  Nikolay Samofatov (nickol…@sympatico.ca)
Date: Tue, 01 Nov 2005

Hi!

I am trying to implement a simple FTP server with Indy 10.0.52 with moderate success so far.

Problems so far:

1. ftp.proxy in monitoring mode dies when used against IdFTPServer. The reason for death is that PWD returns empty string.

The latter is caused by apparently missing line of code here:

--
procedure TIdFTPServerContext.ReInitialize; begin
  inherited; // Added by Nikolay Samofatov

  FDataType := ftASCII;
  // FDataMode := dmStream;
  FDataPort := 0;
  FDataStruct := dsFile;

  FPASV := False;
  FEPSVAll := false;

  FDataProtection := ftpdpsClear;
  DataPBSZCalled := False;
  FDataProtBufSize := 0;
end;
---

2. When I do "LIST -la" in Far Manager command line against my server the server dies with Access Violation at the following line of code:
---
procedure TIdFTPServer.CommandLIST(ASender: TIdCommand); ...
          //it should be safe to assume that the FDataChannel object exists because
          //we checked it earlier
          FDataChannel.Data := LStream;
          FDataChannel.FFtpOperation := ftpRetr;
          FDataChannel.OKReply.SetReply(226, RSFTPDataConnClosed);
          FDataChannel.ErrorReply.SetReply(426, RSFTPDataConnClosedAbnormally); ...

--

Access violation happens on the line right after the comment because FDataChannel is nil.

3. It is not straightforward to implement pipe access via IdFtpServer. The problem is that Indy makes use of TStream.Size for no good reasons.

To work it around I had to implement TStream.Seek like this:

--
const
  STREAM_GROWTH_INCREMENT = 65536;

function TCachedPublicationObject.SeekStream(
  Stream : TCachedStream; Offset: Integer; Origin : Word): Integer; var
  SavedSize : Integer;
begin
  case Origin of
    soFromBeginning:
      Stream.FPosition := Offset;
    soFromCurrent:
      Stream.FPosition := Stream.FPosition + Offset;
    soFromEnd:
      begin
        // Grow stream in increments of 64k. This keeps Indy 10 happy and parallelizm feature works.
        FDataStreamMutex.Enter;
        try
          SavedSize := FDataStream.Size;
          repeat
            if FDataStreamInvalid then
              raise EReadError.Create('Error creating replication delta package. Please examine log file for details');

            if FDataStreamComplete or (FDataStream.Size >= SavedSize + STREAM_GROWTH_INCREMENT) then
            begin
              Stream.FPosition := FDataStream.Size;
              break;
            end;

            FMoreDataEvents.Add(Stream.FWakeupEvent);
            FDataStreamMutex.Leave;

            Stream.FWakeupEvent.WaitFor(INFINITE);

            FDataStreamMutex.Enter;
          until False;
        finally
          FDataStreamMutex.Leave;
        end;
      end
  end;
  Result := Stream.FPosition;
  FAccessDateTime := Now;
end;

But this looks like a dirty hack if nothing else.

Nikolay Samofatov

Replies