Board index » delphi » Bugs fixed in IdMessageClient.pas and IdMessage.pas

Bugs fixed in IdMessageClient.pas and IdMessage.pas

Hello, I have discovered and fixed some bugs in Indy 9.0.2 B.

Please let me if my fix can generate new errors in other points !

After the fix, headers and content-type work fine on TIdText and
TIdAttachment.

Thanks

Francesco

=========================================================
IdMessageClient.pas
=========================================================

  function ProcessTextPart(ADecoder: TIdMessageDecoder): TIdMessageDecoder;
  var
    LDestStream: TStringStream;
  begin
    LDestStream := TStringStream.Create(''); try
      Result := ADecoder.ReadBody(LDestStream, MsgEnd);
      // START MODIFY 2001-12-01 by Francesco Pucino
      //ADecoder.Free;
      with TIdText.Create(AMsg.MessageParts) do begin
        Body.Text := LDestStream.DataString;
        Headers.Assign(ADecoder.Headers);
      end;
      ADecoder.Free;
      // END MODIFY 2001-12-01 by Francesco Pucino
    finally FreeAndNil(LDestStream); end;
  end;

 function ProcessAttachment(ADecoder: TIdMessageDecoder): TIdMessageDecoder;
  var
    LDestStream: TFileStream;
    LTempPathname: string;
  begin
    LTempPathname := MakeTempFilename;
    LDestStream := TFileStream.Create(LTempPathname, fmCreate); try
      Result := ADecoder.ReadBody(LDestStream, MsgEnd);
      with TIdAttachment.Create(AMsg.MessageParts) do begin
        Filename := ADecoder.Filename;
        StoredPathname := LTempPathname;
        // START MODIFY 2001-12-01 by Francesco Pucino
        Headers.Assign(ADecoder.Headers);
        // END MODIFY 2001-12-01 by Francesco Pucino
      end;
      ADecoder.Free;
    finally FreeAndNil(LDestStream); end;
  end;

=========================================================
IdMessage.pas
=========================================================

constructor TIdMessagePart.Create(Collection: TCollection);
begin
  if ClassType = TIdMessagePart then begin
    raise EIdCanNotCreateMessagePart.Create(RSTIdMessagePartCreate);
  end;
  inherited;
  FIsEncoded := False;
  FHeaders := TIdHeaderList.Create;
  // START MODIFY 2001-12-01 by Francesco Pucino
  FHeaders.NameValueSeparator:='=';
  // END MODIFY 2001-12-01 bt Francesco Pucino
  FExtraHeaders := TIdHeaderList.Create;
end;

 

Re:Bugs fixed in IdMessageClient.pas and IdMessage.pas


I have discovered a new bug filling your temp dir...

Please let me if my fix can generate new errors in other points !

Thanks,

Francesco

To fix:

=========================================================
IdMessage.pas
=========================================================

destructor TIdAttachment.Destroy;
begin
  if FileIsTempFile then begin
    // START MODIFY 2001-12-01 Francesco Pucino
    //DeleteFile(Filename);
    DeleteFile(FStoredPathname);
    // END MODIFY 2001-12-01 Francesco Pucino
  end;
  inherited;
end;

=========================================================
IdMessageClient.pas
=========================================================

  function ProcessAttachment(ADecoder: TIdMessageDecoder):
TIdMessageDecoder;
  var
    LDestStream: TFileStream;
    LTempPathname: string;
  begin
    LTempPathname := MakeTempFilename;
    LDestStream := TFileStream.Create(LTempPathname, fmCreate); try
      Result := ADecoder.ReadBody(LDestStream, MsgEnd);
      with TIdAttachment.Create(AMsg.MessageParts) do begin
        Filename := ADecoder.Filename;
        StoredPathname := LTempPathname;
        // START MODIFY 2001-12-01 Francesco Pucino
        FileIsTempFile:=True;
        Headers.Assign(ADecoder.Headers);
        // END MODIFY 2001-12-01 Francesco Pucino
      end;
      ADecoder.Free;
    finally FreeAndNil(LDestStream); end;
  end;

"Francesco Pucino" <fpuc...@mclink.it> ha scritto nel messaggio
news:3c08fdb5_1@dnews...

Quote
> Hello, I have discovered and fixed some bugs in Indy 9.0.2 B.

> Please let me if my fix can generate new errors in other points !

> After the fix, headers and content-type work fine on TIdText and
> TIdAttachment.

> Thanks

> Francesco

> =========================================================
> IdMessageClient.pas
> =========================================================

>   function ProcessTextPart(ADecoder: TIdMessageDecoder):
TIdMessageDecoder;
>   var
>     LDestStream: TStringStream;
>   begin
>     LDestStream := TStringStream.Create(''); try
>       Result := ADecoder.ReadBody(LDestStream, MsgEnd);
>       // START MODIFY 2001-12-01 by Francesco Pucino
>       //ADecoder.Free;
>       with TIdText.Create(AMsg.MessageParts) do begin
>         Body.Text := LDestStream.DataString;
>         Headers.Assign(ADecoder.Headers);
>       end;
>       ADecoder.Free;
>       // END MODIFY 2001-12-01 by Francesco Pucino
>     finally FreeAndNil(LDestStream); end;
>   end;

>  function ProcessAttachment(ADecoder: TIdMessageDecoder):
TIdMessageDecoder;
>   var
>     LDestStream: TFileStream;
>     LTempPathname: string;
>   begin
>     LTempPathname := MakeTempFilename;
>     LDestStream := TFileStream.Create(LTempPathname, fmCreate); try
>       Result := ADecoder.ReadBody(LDestStream, MsgEnd);
>       with TIdAttachment.Create(AMsg.MessageParts) do begin
>         Filename := ADecoder.Filename;
>         StoredPathname := LTempPathname;
>         // START MODIFY 2001-12-01 by Francesco Pucino
>         Headers.Assign(ADecoder.Headers);
>         // END MODIFY 2001-12-01 by Francesco Pucino
>       end;
>       ADecoder.Free;
>     finally FreeAndNil(LDestStream); end;
>   end;

> =========================================================
> IdMessage.pas
> =========================================================

> constructor TIdMessagePart.Create(Collection: TCollection);
> begin
>   if ClassType = TIdMessagePart then begin
>     raise EIdCanNotCreateMessagePart.Create(RSTIdMessagePartCreate);
>   end;
>   inherited;
>   FIsEncoded := False;
>   FHeaders := TIdHeaderList.Create;
>   // START MODIFY 2001-12-01 by Francesco Pucino
>   FHeaders.NameValueSeparator:='=';
>   // END MODIFY 2001-12-01 bt Francesco Pucino
>   FExtraHeaders := TIdHeaderList.Create;
> end;

Re:Bugs fixed in IdMessageClient.pas and IdMessage.pas


Hello Francesco,

I found the same bug, but use this alternate fix:

 =========================================================
 IdMessageClient.pas
 =========================================================

  function ProcessTextPart(ADecoder: TIdMessageDecoder): TIdMessageDecoder;
  var
    LDestStream: TStringStream;
  begin
    // Torsten : Apply then decoded header
   LDestStream := TStringStream.Create(''); try
      Result := ADecoder.ReadBody(LDestStream, MsgEnd);
      with TIdText.Create(AMsg.MessageParts) do begin
        Body.Text := LDestStream.DataString;
        Headers.AddStdValues(ADecoder.Headers);
        // Torsten : Apply then MIME Boundary
        if ADecoder is TIdMessageDecoderMIME then
          Boundary := (ADecoder as TIdMessageDecoderMIME).MIMEBoundary;
      end;
      ADecoder.Free;
    finally FreeAndNil(LDestStream); end;
  end;

  function ProcessAttachment(ADecoder: TIdMessageDecoder):
TIdMessageDecoder;
  var
    LDestStream: TFileStream;
    LTempPathname: string;
  begin
    LTempPathname := MakeTempFilename;
    LDestStream := TFileStream.Create(LTempPathname, fmCreate); try
      Result := ADecoder.ReadBody(LDestStream, MsgEnd);
      with TIdAttachment.Create(AMsg.MessageParts) do begin
        Filename := ADecoder.Filename;
        StoredPathname := LTempPathname;
        // Torsten : Apply then decoded header
        Headers.AddStdValues(ADecoder.Headers);
         // Torsten : Apply then MIME Boundary
        if ADecoder is TIdMessageDecoderMIME then
          Boundary := (ADecoder as TIdMessageDecoderMIME).MIMEBoundary;
      end;
      ADecoder.Free;
    finally FreeAndNil(LDestStream); end;
  end;

To display the embedded images of a html mail I have to scan then boundary
string for then "CONTENT-ID" part.
Therefore I assign then decoded boundary string to the MessageParts too.
There are a couple of bugs (or design errors) in the
IdCoderHeader.EncodeHeader procedure. They only work
correct with ISO8859-1 charsets. A lot of  emails from windows mail clients
use US_ASCII or WINDOWS-1252
charsets. I've replace the original procedure by the following code:

 =========================================================
 IdCoderHeader.pas
 =========================================================

uses
  ...
 windows,
 ...

function DecodeQuotedPrintable(const CodedStr : string) : string;
var i, l : integer;
begin
  result := '';
  i := 1; l := length(CodedStr);
  while (i <= l) do begin
    if CodedStr[i] = '_' then begin
      result := result + ' '
    end else
    if CodedStr[i] = '=' then begin
      result := result + chr(StrToInt('$' + CodedStr[i + 1] + CodedStr[i +
2]));
      inc(i, 2);
    end else
    if ord(CodedStr[i]) > 32 then
      result := result + CodedStr[i];
    inc(i);
  end;
end;

function DecodeBase64(const CodedStr : string) : string;
var
  a3 : array[1..3] of byte;
  a4 : array[1..4] of byte;
  i,j  : integer;
begin
  result := '';
  i := 0;

  while (i < (Length(CodedStr)-4)) do begin
    a4[1] := b64(CodedStr[i+1]);
    a4[2] := b64(CodedStr[i+2]);
    a4[3] := b64(CodedStr[i+3]);
    a4[4] := b64(CodedStr[i+4]);

    a3[1] := (a4[1] shl 2) or (a4[2] shr 4);
    a3[2] := (a4[2] shl 4) or (a4[3] shr 2);
    a3[3] := (a4[3] shl 6) or (a4[4] shr 0);
    //>> Torsten :  eventuell abschlie?ende #0 entfernen
    for j := 1 to 3 do
      if a3[j] <> 0 then result := result+chr(a3[j]);
    inc(i,4);
  end;
end;

function DecodeUSASCII(HeaderEncoding : char; const CodedStr : string) :
string;
begin
  case HeaderEncoding of
    'Q' : result := DecodeQuotedPrintable(CodedStr);
    'B' : result := DecodeBase64(CodedStr);
    else result := CodedStr; //Unbekannte Kodierung, undekodiert zurck
  end;
  OEMToChar(pChar(result),pChar(result));
end;

function DecodeISO8859(HeaderEncoding : char; const CodedStr : string) :
string;
begin
  case HeaderEncoding of
    'Q' : result := DecodeQuotedPrintable(CodedStr);
    'B' : result := DecodeBase64(CodedStr);
    else result := CodedStr; //Unbekannte Kodierung, undekodiert zurck
  end;
end;

function DecodeHeader(Header: string): string;
var
  k : Integer;
  HeaderCharSet  : string;
  CodedStr       : string;
  HeaderEncoding : char;
begin
  result := '';
  if Header = '' then exit;
  //>> Torsten 06.12.2000

  // Codec ?
  k := Pos('=?',Header);
  if k = 0 then begin
    // keine Codierung
    Result := Header;
    exit;
  end;
  // Sonst Dekodieren

  // Nicht Kodierter Begin der Nachricht, Whitespace l?schen
  result := Trim(Copy(Header,1,k-1));
  System.Delete(Header,1,k+1);

  // Den zu Dekodierend Bereich bestimmen
  k := Pos('?=',Header);
  if k = 0 then k := length(Header)+1;
  CodedStr := Copy(Header,1,k-1);
  // und aus dem Header entfernen
  System.Delete(Header,1,k+1);

  // den Characterset bestimmen
  k := Pos('?',CodedStr);
  if k = 0 then begin
    // Fehler, uncodiert zurckliefern
    result := result + CodedStr+ Header;
    exit;
  end;

  HeaderCharSet := UpperCase(Copy(CodedStr,1,k-1));
  System.Delete( CodedStr,1,k);

  // Encoding bestimmen
  if (length(CodedStr) < 2) or (CodedStr[2] <> '?') then begin
    // Fehler, uncodiert zurckliefern
    result := result + CodedStr + Header;
    exit;
  end;
  HeaderEncoding := UpCase(CodedStr[1]);
  System.Delete( CodedStr,1,2);

  // Je nach Format den richtigen Decoder Aufrufen
  if AnsiSameText(HeaderCharSet, 'ISO-2022-JP') then begin
    result := result + Decode2022JP(CodedStr)
  end else
  if AnsiSameText(HeaderCharSet,'ISO-8859-1') then begin
    result := result + DecodeISO8859(HeaderEncoding,CodedStr)
  end else
  if AnsiSameText(HeaderCharSet,'WINDOWS-1252') then begin
    result := result + DecodeISO8859(HeaderEncoding,CodedStr)
  end else
  if AnsiSameText(HeaderCharSet,'US_ASCII') then begin
    result := result + DecodeUSASCII(HeaderEncoding,CodedStr)
  end else
    result := result + CodedStr;

  // ggf. den Rest dekodieren
  result := result+DecodeHeader(Header);
end;

Torsten

"Francesco Pucino" <fpuc...@mclink.it> schrieb im Newsbeitrag
news:3c08fdb5_1@dnews...

Quote
> Hello, I have discovered and fixed some bugs in Indy 9.0.2 B.

> Please let me if my fix can generate new errors in other points !

> After the fix, headers and content-type work fine on TIdText and
> TIdAttachment.

> Thanks

> Francesco

> =========================================================
> IdMessageClient.pas
> =========================================================

>   function ProcessTextPart(ADecoder: TIdMessageDecoder):
TIdMessageDecoder;
>   var
>     LDestStream: TStringStream;
>   begin
>     LDestStream := TStringStream.Create(''); try
>       Result := ADecoder.ReadBody(LDestStream, MsgEnd);
>       // START MODIFY 2001-12-01 by Francesco Pucino
>       //ADecoder.Free;
>       with TIdText.Create(AMsg.MessageParts) do begin
>         Body.Text := LDestStream.DataString;
>         Headers.Assign(ADecoder.Headers);
>       end;
>       ADecoder.Free;
>       // END MODIFY 2001-12-01 by Francesco Pucino
>     finally FreeAndNil(LDestStream); end;
>   end;

>  function ProcessAttachment(ADecoder: TIdMessageDecoder):
TIdMessageDecoder;
>   var
>     LDestStream: TFileStream;
>     LTempPathname: string;
>   begin
>     LTempPathname := MakeTempFilename;
>     LDestStream := TFileStream.Create(LTempPathname, fmCreate); try
>       Result := ADecoder.ReadBody(LDestStream, MsgEnd);
>       with TIdAttachment.Create(AMsg.MessageParts) do begin
>         Filename := ADecoder.Filename;
>         StoredPathname := LTempPathname;
>         // START MODIFY 2001-12-01 by Francesco Pucino
>         Headers.Assign(ADecoder.Headers);
>         // END MODIFY 2001-12-01 by Francesco Pucino
>       end;
>       ADecoder.Free;
>     finally FreeAndNil(LDestStream); end;
>   end;

> =========================================================
> IdMessage.pas
> =========================================================

> constructor TIdMessagePart.Create(Collection: TCollection);
> begin
>   if ClassType = TIdMessagePart then begin
>     raise EIdCanNotCreateMessagePart.Create(RSTIdMessagePartCreate);
>   end;
>   inherited;
>   FIsEncoded := False;
>   FHeaders := TIdHeaderList.Create;
>   // START MODIFY 2001-12-01 by Francesco Pucino
>   FHeaders.NameValueSeparator:='=';
>   // END MODIFY 2001-12-01 bt Francesco Pucino
>   FExtraHeaders := TIdHeaderList.Create;
> end;

Other Threads