Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Indy9 idEncoderMIME problem

27 views
Skip to first unread message

Eddie Shipman

unread,
Apr 25, 2006, 11:31:45 AM4/25/06
to
Why is the Encode function checking this:
((ABytes mod 3) > 0)

Not all file sizes will be evenly divisible by 3.

How do I defeat this if passing a TFileStream to the Encode
function like this: (AStream is a TFileStream)

ss := TStringStream.Create(MIMEEncoder.Encode(AStream, AStream.Size));

Remy Lebeau (TeamB)

unread,
Apr 25, 2006, 1:24:02 PM4/25/06
to

"Eddie Shipman" <mrbaseball34@No_Spam_gmail.com> wrote in message
news:MPG.1eb7fcdd2...@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


Eddie Shipman

unread,
Apr 25, 2006, 3:13:13 PM4/25/06
to
In article <444e5bcc$1...@newsgroups.borland.com>, no....@no.spam.com
says...

>
> "Eddie Shipman" <mrbaseball34@No_Spam_gmail.com> wrote in message
> news:MPG.1eb7fcdd2...@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.
>
<SNIP>

Nice source control, then. I thought you guys had it on the ball!!! ;-)

0 new messages