Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Library: Internet / LAN / ASP.NET (https://www.delphipraxis.net/23-library-internet-lan-asp-net/)
-   -   Delphi WriteRFCStrings Fehler (https://www.delphipraxis.net/11705-writerfcstrings-fehler.html)

sakura 12. Nov 2003 10:34


WriteRFCStrings Fehler
 
Hi DP-ler,

jetzt will ich Euch auf einen bösen Fehler in procedure TIdTCPConnection.WriteRFCStrings hinweisen. RFC Strings werden in vielen Text-basierten TCP-Protokollen genutzt. Dabei wird dem Empfänger nicht gesagt, wie viele Bytes zu erwarten sind, jedoch stillschweigend vereinbart, daß die Übertragung der Daten durch ein <CRLF>.<CRLF> beendet wird.

Damit es nicht zu Mißverständnissen kommt, wenn eine Zeile übertragen wird, die lediglich einen Punkt . beinhaltet, werden, lt. Protokoll alle Zeilen, welche mit einem starten durch einen vorangestellten Punkt erweitert.

Die Indy-WriteRFCStrings Prozedur versucht dieses wie folgend zu lösen:
Delphi-Quellcode:
procedure TIdTCPConnection.WriteRFCStrings(AStrings: TStrings);
var
  i: Integer;
begin
  for i := 0 to AStrings.Count - 1 do
  begin
  // --- FEHLER !!!
    if AStrings[i] = '.' then
    begin
      WriteLn('..');
    end else
    begin
      WriteLn(AStrings[i]);
    end;
  end;
  WriteLn('.');
end;
Da liegt der Fehler einfach zu sehen. Das RFC gibt vor, daß alle Zeilen die mit einem Punkt starten einen weiteren vorangestellt bekommen, die Indy-Methode erweitert allerdings nur Zeilen, welche ausschließlich einen Punkt haben :shock:

Daß dieses wirklich ein Fehler ist, kann man an der Capture-Methode erkennen, dort werden nämlich alle Zeilen, welche mit zwei Punkten starten um einen gekürzt ;-)
Code:
procedure TIdTCPConnection.PerformCapture(ADest: TObject; out VLineCount: Integer;
 const ADelim: string; const AIsRFCMessage: Boolean);
const
  [color=#ff0024]wDoublePoint = ord('.') shl 8 + ord('.');[/color]
type
  PWord = ^Word;
var
  s: string;
begin
  VLineCount := 0;
  BeginWork(wmRead); try
    repeat
      s := ReadLn;
      if s = ADelim then
      begin
        Exit;
      end;
      // For RFC 822 retrieves
      // No length check necessary, if only one byte it will be byte x + #0.
      [color=#ff0000]if AIsRFCMessage and (PWord(PChar(S))^ = wDoublePoint) then
      begin
        Delete(s, 1, 1);[/color]
      end;
      // Write to output
      Inc(VLineCount);
      if ADest is TStrings then
      begin
        TStrings(ADest).Add(s);
      end else if ADest is TStream then
      begin
        TIdStream(ADest).WriteLn(s);
      end else if ADest <> nil then
      begin
        raise EIdObjectTypeNotSupported.Create(RSObjectTypeNotSupported);
      end;
    until False;
  finally EndWork(wmRead); end;
end;
Wie dem auch sei, da ihr ja die Source zu Indy habt, könnt Ihr die Methode WriteRFCStringsie folgend anpassen.
Code:
procedure TIdTCPConnection.WriteRFCStrings(AStrings: TStrings);
var
  i: Integer;
begin
  for i := 0 to AStrings.Count - 1 do
  begin
    [color=#f50000]if Copy(AStrings[i], 1, 1) = '.' then
    begin
      WriteLn('.' + AStrings[i]);[/color]
    end else
    begin
      WriteLn(AStrings[i]);
    end;
  end;
  WriteLn('.');
end;
Weiterhin viel Spass mit den kleinen Indianern :mrgreen:

...:cat:...

[edit=Chakotay1308]Titel angepasst. Mfg, Chakotay1308[/edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:20 Uhr.

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