Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Apr : Re: Indy9 idEncoderMIME problem

www.cryer.info
Managed Newsgroup Archive

Re: Indy9 idEncoderMIME problem

Subject:Re: Indy9 idEncoderMIME problem
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Tue, 25 Apr 2006 10:24:02

"Eddie Shipman" <mrbaseball34@No_Spam_gmail.com> wrote in message
news:MPG.1eb7fcdd2d3d6ae69897db@forums.borland.com...

> Why is the Encode function checking this:
> ((ABytes mod 3) > 0)

Because it is a bug that keeps creeping back into the code.  Someone takes
it out, then someone else puts it back in.

> How do I defeat this

Change the code and recompile Indy.  Try the following modified version:

    function TIdEncoder3to4.Encode(ASrcStream: TStream; const ABytes:
Integer = MaxInt): string;
        //TODO: Make this more efficient. Profile it to test, but maybe make
single
        // calls to ReadBuffer then pull from memory
    var
        LBuffer : String;
        LSize : Integer;
        LLen : integer;
        LBufSize : Integer;
        LPos : Integer;
        LIn1, LIn2, LIn3: Byte;
        LUnit: TIdCardinalBytes;
    begin
        Result := '';    {Do not Localize}
        // No no - this will read the whole thing into memory and what if
its MBs?
        // need to load it in smaller buffered chunks MaxInt is WAY too
big....
        LBufSize := Min(ASrcStream.Size - ASrcStream.Position, ABytes);
        if LBufSize <= 0 then begin
            Exit;
        end;
        SetLength(Result, ((LBufSize+2) div 3) * 4); // we know that the
string will grow by 4/3 adjusted to 3 boundary
        LLen := 0;
        SetLength(LBuffer, LBufSize);
        ASrcStream.ReadBuffer(LBuffer[1], LBufSize);
        LPos := 1;
        while (LPos <= LBufSize) do
         begin
            LIn1 := Byte(LBuffer[LPos]);
            Inc(LPos);
            if LPos <= LBufSize then
            begin
                LIn2 := Byte(LBuffer[LPos]);
                Inc(LPos);
                if LPos <= LBufSize then
                begin
                    LIn3 := Byte(LBuffer[LPos]);
                    Inc(LPos);
                    LSize := 3;
                end
                else
                begin
                    LIn3 := 0;
                    LSize := 2;
                end;
            end
            else
            begin
                LIn2 := 0;
                LIn3 := 0;
                LSize := 1;
            end;
            EncodeUnit(LIn1, LIn2, LIn3, LUnit.Whole);
            assert(LLen + 4 <= length(result), 'TIdEncoder3to4.Encode:
Calculated length exceeded (expected '+IntToStr(4 * trunc((LBufSize +
2)/3))+', about to go '+IntToStr(LLen + 4)+' at offset '+IntToStr(LPos)+' of
'+IntToStr(LBufSize));
            move(LUnit, Result[LLen + 1], 4);
            Inc(LLen, 4);
            if LSize < 3 then begin
                Result[LLen] := FillChar;
                if LSize = 1 then begin
                    Result[LLen-1] := FillChar;
                end;
            end;
        end;
        assert(LLen = 4 * trunc((LBufSize + 2)/3), 'TIdEncoder3to4.Encode:
Calculated length not met (expected '+IntToStr(4 * trunc((LBufSize +
2)/3))+', finished at '+IntToStr(LLen + 4)+', Bufsize =
'+IntToStr(LBufSize));
    end;

Otherwise, the only way to defeat it at runtime is to pad your data to make
it an even multiple.

> if passing a TFileStream to the Encode function like this
>
>   ss := TStringStream.Create(MIMEEncoder.Encode(AStream, AStream.Size));

You won't be able to defeat it when used that way.


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive