| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- {
- $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.13 27.08.2004 22:04:00 Andreas Hausladen
- speed optimization ("const" for string parameters)
- Rev 1.12 2004.05.20 1:39:16 PM czhower
- Last of the IdStream updates
- Rev 1.11 2004.05.20 11:36:58 AM czhower
- IdStreamVCL
- Rev 1.10 2004.05.20 11:13:02 AM czhower
- More IdStream conversions
- Rev 1.9 2004.05.19 3:06:42 PM czhower
- IdStream / .NET fix
- Rev 1.8 2004.02.03 5:44:04 PM czhower
- Name changes
- Rev 1.7 2004.01.22 5:56:54 PM czhower
- TextIsSame
- Rev 1.6 1/21/2004 2:20:24 PM JPMugaas
- InitComponent
- Rev 1.5 1/21/2004 1:30:10 PM JPMugaas
- InitComponent
- Rev 1.4 10/17/2003 12:41:16 AM DSiders
- Added localization comments.
- Rev 1.3 26/09/2003 01:06:18 CCostelloe
- CodingType property added so caller can find out if it was UUE or XXE encoded
- Rev 1.2 6/14/2003 03:07:20 PM JPMugaas
- Fixed MessageDecoder so that DecodeBegin is called right after creation and
- DecodeEnd is called just before destruction. I also fixed where the code was
- always assuming that LDecode was always being created.
- Rev 1.1 6/13/2003 07:58:44 AM JPMugaas
- Should now compile with new decoder design.
- Rev 1.0 11/13/2002 07:57:14 AM JPMugaas
- 2003-Sep-20 Ciaran Costelloe
- CodingType property added so caller can find out if it was UUE or XXE encoded
- }
- unit IdMessageCoderUUE;
- interface
- {$i IdCompilerDefines.inc}
- uses
- Classes,
- IdCoder3to4,
- IdMessageCoder,
- IdMessage,
- IdGlobal;
- type
- TIdMessageDecoderUUE = class(TIdMessageDecoder)
- protected
- FCodingType: string;
- public
- function ReadBody(ADestStream: TStream; var AMsgEnd: Boolean): TIdMessageDecoder; override;
- property CodingType: string read FCodingType;
- end;
- TIdMessageDecoderInfoUUE = class(TIdMessageDecoderInfo)
- public
- function CheckForStart(ASender: TIdMessage; const ALine: string): TIdMessageDecoder; override;
- end;
- TIdMessageEncoderUUEBase = class(TIdMessageEncoder)
- protected
- FEncoderClass: TIdEncoder3to4Class; // TODO: change to "class of TIdEncoder00E" instead
- public
- procedure Encode(ASrc: TStream; ADest: TStream); override;
- end;
- TIdMessageEncoderUUE = class(TIdMessageEncoderUUEBase)
- public
- constructor Create(AOwner: TComponent); override;
- end;
- TIdMessageEncoderInfoUUE = class(TIdMessageEncoderInfo)
- public
- constructor Create; override;
- end;
- implementation
- uses
- IdCoderUUE, IdCoderXXE, IdException, IdGlobalProtocols, IdResourceStringsProtocols, SysUtils;
- { TIdMessageDecoderInfoUUE }
- function TIdMessageDecoderInfoUUE.CheckForStart(ASender: TIdMessage; const ALine: string): TIdMessageDecoder;
- var
- LUUE: TIdMessageDecoderUUE;
- begin
- Result := nil;
- if TextStartsWith(ALine, 'begin ') and CharEquals(ALine, 10, ' ') and IsNumeric(ALine, 3, 7) then begin {Do not Localize}
- LUUE := TIdMessageDecoderUUE.Create(ASender);
- LUUE.FFilename := Copy(ALine, 11, MaxInt);
- LUUE.FPartType := mcptAttachment;
- Result := LUUE;
- end;
- end;
- { TIdMessageDecoderUUE }
- function TIdMessageDecoderUUE.ReadBody(ADestStream: TStream; var AMsgEnd: Boolean): TIdMessageDecoder;
- var
- LDecoder: TIdDecoder4to3;
- LLine: string;
- LMsgEnd: Boolean;
- LEncoding: IIdTextEncoding;
- LFillCharStr: string;
- begin
- Result := nil;
- AMsgEnd := False;
- LEncoding := IndyTextEncoding_8Bit;
- LLine := ReadLnRFC(LMsgEnd, LEncoding);
- if LMsgEnd then begin
- Exit;
- end;
- LDecoder := nil;
- if LLine <> '' then
- begin
- case LLine[1] of
- #32..#85: begin {Do not Localize}
- // line length may be from 2 (first char + newline) to 65,
- // this is 0 useable to 63 usable bytes, + #32 gives this as a range.
- // (yes, the line length is encoded in the first bytes of each line!)
- // TODO: need to do a better job of differentiating between UUE and XXE.
- //
- // UUE and XXE both encode 45 bytes max per line. Each line starts with
- // an encoded character that indicates the number of encoded bytes in the
- // line, not counting padding.
- //
- // UUE encodes the byte count as one of the following characters:
- //
- // 0 1 2 3 4
- // 0123456789012345678901234567890123456789012345
- // `!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM
- //
- // XXE encodes the byte count as one of the following characters:
- //
- // 0 1 2 3 4
- // 0123456789012345678901234567890123456789012345
- // +-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh
- // (some encoders use [space] instead of +)
- //
- // Without external information to indicate the actual encoding, if we
- // get input whose encoded byte length is encoded as one of the following
- // characters:
- //
- // -0123456789ABCDEFGHIJKLM
- //
- // We will not know if it is actually UUE or XXE. About all we could do
- // is calculate the expected input length in both encodings based on the
- // starting character and then check if the input actually matches one
- // of them...
- LDecoder := TIdDecoderUUE.Create(nil);
- LDecoder.DecodeBegin(ADestStream);
- FCodingType := 'UUE'; {do not localize}
- end;
- 'h': begin {do not localize}
- LDecoder := TIdDecoderXXE.Create(nil);
- LDecoder.DecodeBegin(ADestStream);
- FCodingType := 'XXE'; {do not localize}
- end;
- else begin
- raise EIdException.Create(RSUnrecognizedUUEEncodingScheme); // TODO: create a new Exception class for this
- end;
- end;
- end;
- try
- if Assigned(LDecoder) then
- begin
- LFillCharStr := String(LDecoder.FillChar);
- repeat
- if (Trim(LLine) = '') or (LLine = LFillCharStr) then begin
- // UUE: Comes on the line before end. Supposed to be `, but some put a
- // blank line instead
- end else begin
- LDecoder.Decode(LLine);
- end;
- LLine := ReadLnRFC(LMsgEnd, LEncoding);
- until TextIsSame(Trim(LLine), 'end') or LMsgEnd; {Do not Localize}
- LDecoder.DecodeEnd;
- end;
- finally
- LDecoder.Free;
- end;
- end;
- { TIdMessageEncoderInfoUUE }
- constructor TIdMessageEncoderInfoUUE.Create;
- begin
- inherited;
- FMessageEncoderClass := TIdMessageEncoderUUE;
- end;
- { TIdMessageEncoderUUEBase }
- procedure TIdMessageEncoderUUEBase.Encode(ASrc: TStream; ADest: TStream);
- var
- LEncoder: TIdEncoder3to4;
- begin
- ASrc.Position := 0;
- WriteStringToStream(ADest, 'begin ' + IntToStr(PermissionCode) + ' ' + Filename + EOL); {Do not Localize}
- LEncoder := FEncoderClass.Create(nil);
- try
- while ASrc.Position < ASrc.Size do begin
- LEncoder.Encode(ASrc, ADest, 45);
- WriteStringToStream(ADest, EOL);
- end;
- WriteStringToStream(ADest, String(LEncoder.FillChar) + EOL + 'end' + EOL); {Do not Localize}
- finally
- LEncoder.Free;
- end;
- end;
- { TIdMessageEncoderUUE }
- constructor TIdMessageEncoderUUE.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FEncoderClass := TIdEncoderUUE;
- end;
- initialization
- TIdMessageDecoderList.RegisterDecoder('UUE', TIdMessageDecoderInfoUUE.Create); {Do not Localize}
- TIdMessageEncoderList.RegisterEncoder('UUE', TIdMessageEncoderInfoUUE.Create); {Do not Localize}
- end.
|