Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Overload einer Funktion der TIdTrivialFTP Komponente (https://www.delphipraxis.net/162876-overload-einer-funktion-der-tidtrivialftp-komponente.html)

schwa226 8. Sep 2011 11:33

Overload einer Funktion der TIdTrivialFTP Komponente
 
Hi,

ich habe eine Frage zu Overload/Override.

Ich habe die Funktion in der unit IdTrivialFTP:
Delphi-Quellcode:
procedure TIdTrivialFTP.CheckOptionAck(const OptionPacket: TIdBytes; Reading: Boolean);
var
  LOptName, LOptValue: String;
  LOffset, Idx, OptionIdx: Integer;
  LRequestedBlkSize: Integer;
begin
  LOffset := 2; // skip packet opcode

  try
    while LOffset < Length(OptionPacket) do
    begin
      Idx := ByteIndex(0, OptionPacket, LOffset);
      if Idx = -1 then begin
        raise EIdTFTPOptionNegotiationFailed.Create('');
      end;

      LOptName := BytesToString(OptionPacket, LOffset, Idx-LOffset, IndyASCIIEncoding);
      LOffset := Idx+1;

      OptionIdx := PosInStrArray(LOptName, [sBlockSize, sTransferSize], False);
      if OptionIdx = -1 then begin
        raise EIdTFTPOptionNegotiationFailed.CreateFmt(RSTFTPUnsupportedOption, [LOptName]);
      end;

      Idx := ByteIndex(0, OptionPacket, LOffset);
      if Idx = -1 then begin
        raise EIdTFTPOptionNegotiationFailed.Create('');
      end;

      LOptValue := BytesToString(OptionPacket, LOffset, Idx-LOffset, IndyASCIIEncoding);
      LOffset := Idx+1;

      case OptionIdx of
        0:
          begin
            LRequestedBlkSize := IndyStrToInt(LOptValue);
            if (LRequestedBlkSize < 8) or (LRequestedBlkSize > 65464) then begin
              raise EIdTFTPOptionNegotiationFailed.CreateFmt(RSTFTPUnsupportedOptionValue, [LOptValue, LOptName]);
            end;
            BufferSize := 4 + LRequestedBlkSize;
          end;
        1:
          begin
            if Reading then
            begin
              // TODO
              {
              if (IndyStrToInt(LOptValue) is not available) then begin
                raise raise EIdTFTPAllocationExceeded.Create('');
              end;
              }
            end;
          end;
      end;
    end;
  except
    on E: Exception do begin
      SendError(Self, FPeerIP, FPeerPort, E);
      raise;
    end;
  end;
end;
Nun habe ich eine Hardware hier, die aber einen anderen Offset hat.
So funktioniert es mit LOffset = 4:
Delphi-Quellcode:
procedure TIdTrivialFTP.CheckOptionAck(const OptionPacket: TIdBytes; Reading: Boolean);
var
  LOptName, LOptValue: String;
  LOffset, Idx, OptionIdx: Integer;
  LRequestedBlkSize: Integer;
begin
  LOffset := 2; // skip packet opcode

  LOffset := LOffset + 2; // skip packet opcode PicoMOD3

  try
    while LOffset < Length(OptionPacket) do
    begin
      Idx := ByteIndex(0, OptionPacket, LOffset);
      if Idx = -1 then begin
        raise EIdTFTPOptionNegotiationFailed.Create('');
      end;

      LOptName := BytesToString(OptionPacket, LOffset, Idx-LOffset, IndyASCIIEncoding);
      LOffset := Idx+1;

      OptionIdx := PosInStrArray(LOptName, [sBlockSize, sTransferSize], False);
      if OptionIdx = -1 then begin
        raise EIdTFTPOptionNegotiationFailed.CreateFmt(RSTFTPUnsupportedOption, [LOptName]);
      end;

      Idx := ByteIndex(0, OptionPacket, LOffset);
      if Idx = -1 then begin
        raise EIdTFTPOptionNegotiationFailed.Create('');
      end;

      LOptValue := BytesToString(OptionPacket, LOffset, Idx-LOffset, IndyASCIIEncoding);
      LOffset := Idx+1;

      case OptionIdx of
        0:
          begin
            LRequestedBlkSize := IndyStrToInt(LOptValue);
            if (LRequestedBlkSize < 8) or (LRequestedBlkSize > 65464) then begin
              raise EIdTFTPOptionNegotiationFailed.CreateFmt(RSTFTPUnsupportedOptionValue, [LOptValue, LOptName]);
            end;
            BufferSize := 4 + LRequestedBlkSize;
          end;
        1:
          begin
            if Reading then
            begin
              // TODO
              {
              if (IndyStrToInt(LOptValue) is not available) then begin
                raise raise EIdTFTPAllocationExceeded.Create('');
              end;
              }
            end;
          end;
      end;
    end;
  except
    on E: Exception do begin
      SendError(Self, FPeerIP, FPeerPort, E);
      raise;
    end;
  end;
end;
Keine Ahnung warum da ein anderer Offset ist, aber mit 2 geht es nicht. Die Optionen starten erst ab Offset 4.

Kann ich das irgendwie in meine eigene Unit einbauen damit die IdTrivalFTP Unit unangetastet bleibt?

DeddyH 8. Sep 2011 12:31

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Welche Sichtbarkeit hat denn die Methode? Wenn es mindestens protected ist, kannst Du Dir ja eine Ableitung schreiben und die Methode überladen.

schwa226 8. Sep 2011 13:45

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Delphi-Quellcode:
type
  TIdTrivialFTP = class(TIdUDPClient)
  protected
    FMode: TIdTFTPMode;
    FRequestedBlockSize: Integer;
    FPeerPort: TIdPort;
    FPeerIP: String;
    function ModeToStr: string;
    procedure CheckOptionAck(const OptionPacket: TIdBytes; Reading: Boolean);
  protected
    procedure SendAck(const BlockNumber: Word);
    procedure RaiseError(const ErrorPacket: TIdBytes);
    procedure InitComponent; override;
  public
    procedure Get(const ServerFile: String; DestinationStream: TStream); overload;
    procedure Get(const ServerFile, LocalFile: String); overload;
    procedure Put(SourceStream: TStream; const ServerFile: String); overload;
    procedure Put(const LocalFile, ServerFile: String); overload;
  published
    property TransferMode: TIdTFTPMode read FMode write FMode Default GTransferMode;
    property RequestedBlockSize: Integer read FRequestedBlockSize write FRequestedBlockSize default 1500;
    property OnWork;
    property OnWorkBegin;
    property OnWorkEnd;
  end;
Also Protected.
Ich rufe die Put Prozedur auf. In dieser wird die CheckOptionAck aufgerufen.

Wie müsste das Overload aussehen?

So vielleicht
Delphi-Quellcode:
type
  TMyIdTrivialFTP = class(TIdTrivialFTP)
    protected
      procedure CheckOptionAck(const OptionPacket: TIdBytes; Reading: Boolean); overload;
  end;
Und dann die Prozedur kopieren? Dann meldet er aber Fehler beim kompilieren. Mit dem einbinden weiterer Units bekomme ich die weg. Beim Kompilieren wird TMyIdTrivialFTP aber wegoptimiert...

DeddyH 8. Sep 2011 14:01

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Versuch einmal:
Delphi-Quellcode:
  TMyIdTrivialFTP = class(IdTrivialFTP.TIdTrivialFTP)
  protected
    procedure CheckOptionAck(const OptionPacket: TIdBytes; Reading: Boolean); overload;
    procedure CheckOptionAck(const OptionPacket: TIdBytes; Reading: Boolean; AdditionalOffset: integer = 2); overload;
  end;

...

procedure TMyIdTrivialFTP.CheckOptionAck(const OptionPacket: TIdBytes;
  Reading: Boolean);
begin
  inherited;
end;

procedure TMyIdTrivialFTP.CheckOptionAck(const OptionPacket: TIdBytes;
  Reading: Boolean; AdditionalOffset: integer);
var
  LOptName, LOptValue: String;
  LOffset, Idx, OptionIdx: Integer;
  LRequestedBlkSize: Integer;
begin
  LOffset := 2; // skip packet opcode

  LOffset := LOffset + AdditionalOffset; // skip packet opcode PicoMOD3

  //usw.

schwa226 8. Sep 2011 15:51

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Nicht ganz...

Ich rufe ja die Put(File :String,...) Prozedur auf, diese ruft die Put(Stream,...) auf und diese wieder die CheckOptionAck. Die orignalen Put von TIdTrivialFTP ruft mir natürlich auch die TIdTrivialFTP.CheckOptionAck auf und nicht meine.

Ich habe nun die Put Prozeduren auch mit Overload in meine TMyIdTrivialFTP übernommen und nun wird meine CheckOptionAck Version aufgerufen.

Mein IndyTFTP Client muss natürlich dann selber über TMyIdTrivialFTP erzeugt werden und nicht mehr über TIdTrivialFTP selber.

DeddyH 8. Sep 2011 15:55

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Sicher, das hätte ich vielleicht dazu schreiben sollen. Ganz glücklich bin ich selbst mit dieser Lösung nicht, aber mir fällt kein anderer Weg ein, wie man das Problem lösen könnte, es sei denn, die Indy-Entwickler nehmen sich der Sache an. Du kannst ja einmal ganz lieb bei Assertor anfragen, ob es evtl. möglich ist, das Offset als Property zu deklarieren oder so etwas.

schwa226 9. Sep 2011 06:16

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Ich bin auch nicht ganz Glücklich mit dieser Lösung. Aber zumindest kann ich jetzt Indy unangetastet lassen und bei einer Neuinstallation von Indy brauche ich nicht darauf dann keine Rücksicht mehr nehmen. Ausser natürlich die Funktionen von Indy ändern sich...

Warum der WinCE TFTP Server einen Offset von 4 statt 2 in den Optionen hat weis ich nicht. Vielleicht ist das irgendwie erkennbar und somit Automatisierbar!?

himitsu 9. Sep 2011 06:32

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Da es hier etwas durcheinander geht:

Overload: Es gibt zwei/mehrere Methoden, mit dem selben Namen und unterschiedlichen Parametern (Signaturen) und alle sind nutzbar.
An den alten Methoden wird aber nichts verändert.

Override: Eine Methode (mindestens Protected und Virtual/Dynamic) wird überschrieben/geändert.
Der alte Aufruf wird also "ersetzt", mit einer Methode mit der selben Signatur (Parameter).

DeddyH 9. Sep 2011 07:11

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Wo geht hier was durcheinander?

himitsu 9. Sep 2011 09:53

AW: Overload einer Funktion der TIdTrivialFTP Komponente
 
Komisch, ich dachte ich hätte "überschreiben" und overload in einem Satz gelesen. :gruebel:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:03 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz