03-19-2023, 06:16 AM
Okay, after whole dramas where I lost all Embarcadero Indy10 files, and had to re-install the entire IDE, I now managed to have a copy of Indy10 which I can actually edit.
Remy,
The problem seems to be that a record called TIdIOHandler.FInputBuffer is empty, after the Stream is loaded.
Please see the following pieces of code ( view from top to bottom)
The FInputBuffer is only 5 bytes big. The loaded Stream is the original email file.
My Debug Log shows this:
[12:18:34/555] D3: IdMessageClient.ProcessMessage (Stream): Stream.Size=107825
[12:18:34/555] D3: IdIOHandlerStreamMsg.Create: AReceiveStream.Size=107825
[12:18:34/555] D3: IdMessageClient.ProcessMessage...
[12:18:34/571] D3: IdIOHandler.ReadLn: FInputBuffer.Size=5
[12:18:34/571] D3: IdIOHandler.ReadLn: length(LResult)=2
[12:18:34/586] D3: IdIOHandler.ReadLn: Line okay
[12:18:34/586] D3: IdIOHandler.ReadLn: Result=
[12:18:34/602] D3: IdMessageClient.ReceiveHeader: 1
[12:18:34/602] D3: IdMessageClient.ProcessMessage: ReceiveHeader=""
[12:18:34/624] D3: IdIOHandler.ReadLn: FInputBuffer.Size=3
[12:18:34/624] D3: IdIOHandler.ReadLn: length(LResult)=3
[12:18:34/640] D3: IdIOHandler.ReadLn: Line okay
[12:18:34/640] D3: IdIOHandler.ReadLn: Result=.
[12:18:34/655] D3: IdMessageClient.ProcessMessage: Done. AMsg.Headers.Count=0
Remy,
The problem seems to be that a record called TIdIOHandler.FInputBuffer is empty, after the Stream is loaded.
Please see the following pieces of code ( view from top to bottom)
Code:
procedure TIdMessageClient.ProcessMessage(AMsg: TIdMessage; AStream: TStream; AHeaderOnly: Boolean = False);
var
LIOHandler: TIdIOHandlerStreamMsg;
begin
Log('IdMessageClient.ProcessMessage (Stream): Stream.Size='+AStream.Size.ToString);
LIOHandler := TIdIOHandlerStreamMsg.Create(nil, AStream); // Here the Stream is copied into the "FReceiveStream" and it is complete.
try
LIOHandler.FreeStreams := False;
LIOHandler.MaxLineLength := MaxInt;
IOHandler := LIOHandler;
// LIOHandler.
try
IOHandler.Open; // BART: Here it calls "FInputBuffer.Clear";
ProcessMessage(AMsg, AHeaderOnly);
---
Procedure TIdMessageClient.ProcessMessage(AMsg: TIdMessage; AHeaderOnly: Boolean = False);
begin
if IOHandler <> nil then begin
Log('IdMessageClient.ProcessMessage...');
//Don't call ReceiveBody if the message ended at the end of the headers
//(ReceiveHeader() would have returned '.' in that case)...
BeginWork(wmRead);
try
if ReceiveHeader(AMsg) = '' then begin
---
Function TIdMessageClient.ReceiveHeader(AMsg: TIdMessage; const AAltTerm: string = ''): string;
var
LMsgEnd: Boolean;
begin
BeginWork(wmRead);
try
repeat
// BART
// Result := IOHandler.ReadLnRFC(LMsgEnd);
result := IOHandler.ReadLn; // Bart: I called ReadLn direct for testing, but not the problem.
---
And now: Where is the FInputBuffer data loaded? I may be blind but I do not see it.
The Stream is loaded into the IoHandler; But how is the FInputbuffer loaded??Code:
function TIdIOHandler.ReadLn(ATerminator: string; ATimeout: Integer = IdTimeoutDefault;
AMaxLineLength: Integer = -1; AByteEncoding: IIdTextEncoding = nil
{$IFDEF STRING_IS_ANSI}; ADestEncoding: IIdTextEncoding = nil{$ENDIF}
): string;
var
LInputBufferSize: Integer;
LStartPos: Integer;
LTermPos: Integer;
LReadLnStartTime: TIdTicks;
LTerm, LResult: TIdBytes;
begin
AByteEncoding := iif(AByteEncoding, FDefStringEncoding);
{$IFDEF STRING_IS_ANSI}
ADestEncoding := iif(ADestEncoding, FDefAnsiEncoding, encOSDefault);
{$ENDIF}
if AMaxLineLength < 0 then begin
AMaxLineLength := MaxLineLength;
end;
// User may pass '' if they need to pass arguments beyond the first.
if ATerminator = '' then begin
ATerminator := LF;
end;
// snip comments
LTerm := ToBytes(ATerminator, AByteEncoding
{$IFDEF STRING_IS_ANSI}, ADestEncoding{$ENDIF}
);
FReadLnSplit := False;
FReadLnTimedOut := False;
LTermPos := -1;
LStartPos := 0;
LReadLnStartTime := Ticks64;
repeat
LInputBufferSize := FInputBuffer.Size;
if LInputBufferSize > 0 then begin
if LStartPos < LInputBufferSize then begin
LTermPos := FInputBuffer.IndexOf(LTerm, LStartPos);
end else begin
LTermPos := -1;
end;
LStartPos := IndyMax(LInputBufferSize-(Length(LTerm)-1), 0);
end;
// if the line length is limited and terminator is found after the limit or not found and the limit is exceeded
if (AMaxLineLength > 0) and ((LTermPos > AMaxLineLength) or ((LTermPos = -1) and (LStartPos > AMaxLineLength))) then begin
if MaxLineAction = maException then begin
raise EIdReadLnMaxLineLengthExceeded.Create(RSReadLnMaxLineLengthExceeded);
end;
FReadLnSplit := True;
Result := FInputBuffer.ExtractToString(AMaxLineLength, AByteEncoding
{$IFDEF STRING_IS_ANSI}, ADestEncoding{$ENDIF}
);
Exit;
end
// ReadFromSource blocks - do not call unless we need to
else if LTermPos = -1 then begin
// ReadLn needs to call this as data may exist in the buffer, but no EOL yet disconnected
CheckForDisconnect(True, True);
// Can only return -1 if timeout
FReadLnTimedOut := ReadFromSource(True, ATimeout, False) = -1;
if (not FReadLnTimedOut) and (ATimeout >= 0) then begin
if GetElapsedTicks(LReadLnStartTime) >= UInt32(ATimeout) then begin
FReadLnTimedOut := True;
end;
end;
if FReadLnTimedOut then begin
Result := '';
Exit;
end;
end;
until LTermPos > -1;
// Extract actual data
// snip comments
Result := FInputBuffer.Extract(LTermPos + Length(ATerminator), AEncoding);
LTermPos := IndyMin(LTermPos, Length(Result));
if (ATerminator = LF) and (LTermPos > 0) then begin
if Result[LTermPos] = CR then begin
Dec(LTermPos);
end;
end;
SetLength(Result, LTermPos);
}
Log('IdIOHandler.ReadLn: FInputBuffer.Size='+FInputBuffer.Size.ToString); // Its size = 5.
FInputBuffer.ExtractToBytes(LResult, LTermPos + Length(LTerm));
Log('IdIOHandler.ReadLn: length(LResult)='+length(LResult).ToString);
if (ATerminator = LF) and (LTermPos > 0) then begin
Log('IdIOHandler.ReadLn: Line okay');
if LResult[LTermPos-1] = Ord(CR) then begin
Dec(LTermPos);
end;
end;
Result := BytesToString(LResult, 0, LTermPos, AByteEncoding
{$IFDEF STRING_IS_ANSI}, ADestEncoding{$ENDIF}
);
Log('IdIOHandler.ReadLn: Result='+result); // Its empty because the FInputBuffer is empty.
end;The FInputBuffer is only 5 bytes big. The loaded Stream is the original email file.
My Debug Log shows this:
[12:18:34/555] D3: IdMessageClient.ProcessMessage (Stream): Stream.Size=107825
[12:18:34/555] D3: IdIOHandlerStreamMsg.Create: AReceiveStream.Size=107825
[12:18:34/555] D3: IdMessageClient.ProcessMessage...
[12:18:34/571] D3: IdIOHandler.ReadLn: FInputBuffer.Size=5
[12:18:34/571] D3: IdIOHandler.ReadLn: length(LResult)=2
[12:18:34/586] D3: IdIOHandler.ReadLn: Line okay
[12:18:34/586] D3: IdIOHandler.ReadLn: Result=
[12:18:34/602] D3: IdMessageClient.ReceiveHeader: 1
[12:18:34/602] D3: IdMessageClient.ProcessMessage: ReceiveHeader=""
[12:18:34/624] D3: IdIOHandler.ReadLn: FInputBuffer.Size=3
[12:18:34/624] D3: IdIOHandler.ReadLn: length(LResult)=3
[12:18:34/640] D3: IdIOHandler.ReadLn: Line okay
[12:18:34/640] D3: IdIOHandler.ReadLn: Result=.
[12:18:34/655] D3: IdMessageClient.ProcessMessage: Done. AMsg.Headers.Count=0

