{ $Project$ $Workfile$ $Revision$ $DateUTC$ $Id$ This file is part of the Indy (Internet Direct) project, and is offered under the dual-licensing agreement described on the Indy website. (http://www.indyproject.org/) Copyright: (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved. } { $Log$ } { Rev 1.3 26/03/2005 19:19:30 CCostelloe Fixes for "uneven size" exception Rev 1.2 2004.01.21 1:04:54 PM czhower InitComponenet Rev 1.1 10/6/2003 5:37:02 PM SGrobety Bug fix in decoders. Rev 1.0 11/14/2002 02:14:54 PM JPMugaas } unit IdCoderMIME; interface {$i IdCompilerDefines.inc} uses Classes, IdCoder3to4, IdGlobal; type TIdEncoderMIME = class(TIdEncoder3to4) protected procedure InitComponent; override; {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} public constructor Create(AOwner: TComponent); reintroduce; overload; {$ENDIF} end; TIdDecoderMIME = class(TIdDecoder4to3) protected procedure InitComponent; override; {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} public constructor Create(AOwner: TComponent); reintroduce; overload; {$ENDIF} end; {WARNING: This is not a general-purpose decoder. It is used, for example, by IdMessageCoderMIME for line-by-line decoding of base64 encoded parts that are processed on a line-by-line basis, as against the complete encoded block.} TIdDecoderMIMELineByLine = class(TIdDecoderMIME) protected FLeftFromLastTime: TIdBytes; public procedure DecodeBegin(ADestStream: TStream); override; procedure DecodeEnd; override; procedure Decode(ASrcStream: TStream; const ABytes: Integer = -1); override; end; const GBase64CodeTable: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; {Do not Localize} var GBase64DecodeTable: TIdDecodeTable; implementation uses {$IFDEF DOTNET} IdStreamNET, {$ELSE} IdStreamVCL, {$ENDIF} SysUtils; { TIdDecoderMIMELineByLine } procedure TIdDecoderMIMELineByLine.DecodeBegin(ADestStream: TStream); begin inherited DecodeBegin(ADestStream); {Clear out any bytes that may be left from a previous decode...} SetLength(FLeftFromLastTime, 0); end; procedure TIdDecoderMIMELineByLine.DecodeEnd; var LStream: TMemoryStream; LPos: Integer; begin if Length(FLeftFromLastTime) > 0 then begin LPos := Length(FLeftFromLastTime); SetLength(FLeftFromLastTime, 4); while LPos < 4 do begin FLeftFromLastTime[LPos] := Ord(FFillChar); Inc(LPos); end; LStream := TMemoryStream.Create; try WriteTIdBytesToStream(LStream, FLeftFromLastTime); LStream.Position := 0; inherited Decode(LStream); finally FreeAndNil(LStream); SetLength(FLeftFromLastTime, 0); end; end; inherited DecodeEnd; end; procedure TIdDecoderMIMELineByLine.Decode(ASrcStream: TStream; const ABytes: Integer = -1); var LMod, LDiv: integer; LIn, LSrc: TIdBytes; LStream: TMemoryStream; begin LIn := FLeftFromLastTime; if ReadTIdBytesFromStream(ASrcStream, LSrc, ABytes) > 0 then begin AppendBytes(LIn, LSrc); end; LMod := Length(LIn) mod 4; if LMod <> 0 then begin LDiv := (Length(LIn) div 4) * 4; FLeftFromLastTime := Copy(LIn, LDiv, Length(LIn)-LDiv); LIn := Copy(LIn, 0, LDiv); end else begin SetLength(FLeftFromLastTime, 0); end; LStream := TMemoryStream.Create; try WriteTIdBytesToStream(LStream, LIn); LStream.Position := 0; inherited Decode(LStream, ABytes); finally FreeAndNil(LStream); end; end; { TIdDecoderMIME } {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} constructor TIdDecoderMIME.Create(AOwner: TComponent); begin inherited Create(AOwner); end; {$ENDIF} procedure TIdDecoderMIME.InitComponent; begin inherited InitComponent; FDecodeTable := GBase64DecodeTable; FCodingTable := ToBytes(GBase64CodeTable); FFillChar := '='; {Do not Localize} end; { TIdEncoderMIME } {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} constructor TIdEncoderMIME.Create(AOwner: TComponent); begin inherited Create(AOwner); end; {$ENDIF} procedure TIdEncoderMIME.InitComponent; begin inherited InitComponent; FCodingTable := ToBytes(GBase64CodeTable); FFillChar := '='; {Do not Localize} end; initialization TIdDecoder4to3.ConstructDecodeTable(GBase64CodeTable, GBase64DecodeTable); end.