123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- { lNet MIME Wrapper
- CopyRight (C) 2007-2008 by Ales Katona
- This library is Free software; you can rediStribute it and/or modify it
- under the terms of the GNU Library General Public License as published by
- the Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- This program is diStributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; withOut even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
- for more details.
- You should have received a Copy of the GNU Library General Public License
- along with This library; if not, Write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- This license has been modified. See File LICENSE.ADDON for more inFormation.
- Should you find these sources without a LICENSE File, please contact
- me at [email protected]
- }
- unit lMimeWrapper;
- {$mode objfpc}{$H+}
- interface
- uses
- SysUtils, Classes, Contnrs, lMimeStreams;
-
- const
- MIME_VERSION = 'MIME-version: 1.0' + CRLF;
- type
- TMimeEncoding = (me8bit, meBase64);
- TMimeDisposition = (mdInline, mdAttachment);
- { TMimeSection }
- TMimeSection = class
- protected
- FContentType: string;
- FEncoding: TMimeEncoding;
- FActivated: Boolean;
- FDescription: string;
- FDisposition: TMimeDisposition;
- FBuffer: string;
- FEncodingStream: TStream;
- FOutputStream: TStream;
- FLocalStream: TBogusStream;
- function RecalculateSize(const OriginalSize: Integer): Integer;
- function GetSize: Integer; virtual; abstract;
- procedure SetDescription(const AValue: string);
- procedure SetDisposition(const AValue: TMimeDisposition);
- procedure SetEncoding(const AValue: TMimeEncoding);
- procedure CreateEncodingStream; virtual;
- function GetHeader: string; virtual;
- function ReadBuffer(const aSize: Integer): string;
- procedure FillBuffer(const aSize: Integer); virtual; abstract;
- public
- constructor Create(aOutputStream: TStream);
- destructor Destroy; override;
- function Read(const aSize: Integer): Integer;
- procedure Reset; virtual;
- public
- property ContentType: string read FContentType write FContentType;
- property Encoding: TMimeEncoding read FEncoding write SetEncoding;
- property Disposition: TMimeDisposition read FDisposition write SetDisposition;
- property Description: string read FDescription write SetDescription;
- property Header: string read GetHeader;
- property Size: Integer read GetSize;
- end;
-
- { TMimeTextSection }
- TMimeTextSection = class(TMimeSection)
- protected
- FOriginalData: string;
- FData: string;
- function GetSize: Integer; override;
- procedure SetData(const AValue: string);
- function GetCharset: string;
- procedure SetCharset(const AValue: string);
- procedure FillBuffer(const aSize: Integer); override;
- public
- constructor Create(aOutputStream: TStream; const aText: string);
- procedure Reset; override;
- public
- property Charset: string read GetCharset write SetCharset;
- property Text: string read FData write SetData;
- end;
-
- { TMimeStreamSection }
- TMimeStreamSection = class(TMimeSection)
- protected
- FStream: TStream;
- FOwnsStreams: Boolean;
- FOriginalPosition: Int64;
- function GetSize: Integer; override;
- procedure SetStream(aValue: TStream);
- procedure FillBuffer(const aSize: Integer); override;
- public
- constructor Create(aOutputStream: TStream; aStream: TStream);
- destructor Destroy; override;
- procedure Reset; override;
- public
- property Stream: TStream read FStream write SetStream;
- property OwnsStreams: Boolean read FOwnsStreams write FOwnsStreams;
- end;
-
- { TMimeFileSection }
- TMimeFileSection = class(TMimeStreamSection)
- protected
- FFileName: string;
- procedure SetFileName(const AValue: string);
- procedure SetContentType(const aFileName: string);
- function GetHeader: string; override;
- public
- constructor Create(aOutputStream: TStream; const aFileName: string);
- property FileName: string read FFileName write SetFileName;
- end;
- { TMimeStream }
- TMimeStream = class(TStream)
- protected
- FSections: TFPObjectList;
- FOutputStream: TMimeOutputStream;
- FBoundary: string;
- FActiveSection: Integer;
- FCalledRead: Boolean;
- FCalledWrite: Boolean;
- function GetBoundarySize: Integer;
- function GetSize: Int64; override;
- function GetCount: Integer;
- function GetBoundary: string;
- function GetSection(i: Integer): TMimeSection;
- function GetMimeHeader: string;
- procedure SetSection(i: Integer; const AValue: TMimeSection);
- procedure ActivateFirstSection;
- procedure ActivateNextSection;
- procedure DoRead(const aSize: Integer);
- public
- constructor Create;
- destructor Destroy; override;
- function Seek(Offset: Longint; Origin: Word): Longint; overload; override;
- function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; override;
- function Read(var Buffer; Count: Longint): Longint; override;
- function Write(const Buffer; Count: Longint): Longint; override;
- procedure AddTextSection(const aText: string; const aCharSet: string = 'UTF-8');
- procedure AddFileSection(const aFileName: string);
- procedure AddStreamSection(aStream: TStream; const FreeStream: Boolean = False);
- procedure Delete(const i: Integer);
- procedure Remove(aSection: TMimeSection);
- procedure Reset;
- public
- property Sections[i: Integer]: TMimeSection read GetSection write SetSection; default;
- property Count: Integer read GetCount;
- property Boundary: string read FBoundary;
- end;
-
- { EAlreadyActivatedException }
- EAlreadyActivatedException = class(Exception)
- public
- constructor Create;
- end;
-
- { EAlreadyCalledReadException }
- EAlreadyCalledReadException = class(Exception)
- public
- constructor Create;
- end;
- { EAlreadyCalledWriteException }
- EAlreadyCalledWriteException = class(Exception)
- public
- constructor Create;
- end;
-
- implementation
- uses
- Math, Base64;
-
- function EncodingToStr(const Encoding: TMimeEncoding): string;
- begin
- Result := '';
- case Encoding of
- me8bit : Result := '8bit';
- meBase64 : Result := 'base64';
- end;
- end;
- function DispositionToStr(const Disposition: TMimeDisposition): string;
- begin
- Result := '';
- case Disposition of
- mdInline : Result := 'inline';
- mdAttachment : Result := 'attachment';
- end;
- end;
- { TMimeSection }
- function TMimeSection.RecalculateSize(const OriginalSize: Integer): Integer;
- begin
- Result := 0;
- if OriginalSize = 0 then
- Exit;
-
- case FEncoding of
- me8bit : Result := OriginalSize;
- meBase64 : if OriginalSize mod 3 = 0 then
- Result := (OriginalSize div 3) * 4 // this is simple, 4 bytes per 3 bytes
- else
- Result := ((OriginalSize + 3) div 3) * 4; // add "padding" trupplet
- end;
- end;
- procedure TMimeSection.SetDescription(const AValue: string);
- begin
- if not FActivated then
- FDescription := AValue;
- end;
- procedure TMimeSection.SetDisposition(const AValue: TMimeDisposition);
- begin
- if not FActivated then
- FDisposition := AValue;
- end;
- procedure TMimeSection.SetEncoding(const AValue: TMimeEncoding);
- begin
- if not FActivated then begin
- FEncoding := aValue;
- if Assigned(FEncodingStream) then
- FEncodingStream.Free;
-
- CreateEncodingStream;
- end;
- end;
- procedure TMimeSection.CreateEncodingStream;
- begin
- case FEncoding of
- me8bit : FEncodingStream := nil;
- meBase64 : FEncodingStream := TBase64EncodingStream.Create(FLocalStream);
- end;
- end;
- function TMimeSection.GetHeader: string;
- begin
- Result := 'Content-Type: ' + FContentType + CRLF;
- Result := Result + 'Content-Transfer-Encoding: ' + EncodingToStr(FEncoding) + CRLF;
- Result := Result + 'Content-Disposition: ' + DispositionToStr(FDisposition) + CRLF;
- if Length(FDescription) > 0 then
- Result := Result + 'Content-Description: ' + FDescription + CRLF;
-
- Result := Result + CRLF;
- end;
- function TMimeSection.ReadBuffer(const aSize: Integer): string;
- begin
- Result := '';
- if aSize >= Length(FBuffer) then
- FillBuffer(aSize);
-
- Result := Copy(FBuffer, 1, aSize);
- end;
- constructor TMimeSection.Create(aOutputStream: TStream);
- begin
- FOutputStream := aOutputStream;
- FEncodingStream := nil;
- FLocalStream := TBogusStream.Create;
- end;
- destructor TMimeSection.Destroy;
- begin
- if Assigned(FEncodingStream) then
- FEncodingStream.Free;
-
- FLocalStream.Free;
- inherited Destroy;
- end;
- function TMimeSection.Read(const aSize: Integer): Integer;
- var
- s: string;
- begin
- Result := 0;
- if aSize <= 0 then
- Exit;
- if not FActivated then begin
- FActivated := True;
- FBuffer := GetHeader;
- end;
-
- if Length(FBuffer) < aSize then
- FillBuffer(aSize);
-
- s := ReadBuffer(aSize);
- if Length(s) >= aSize then begin
- Result := FOutputStream.Write(s[1], aSize);
- Delete(FBuffer, 1, Result);
- end else if Length(s) > 0 then begin
- Result := FOutputStream.Write(s[1], Length(s));
- Delete(FBuffer, 1, Result);
- end;
- end;
- procedure TMimeSection.Reset;
- begin
- FActivated := False;
- FBuffer := '';
- FLocalStream.Reset;
- SetEncoding(FEncoding);
- end;
- { TMimeTextSection }
- procedure TMimeTextSection.SetCharset(const aValue: string);
- begin
- if not FActivated then begin
- if Length(aValue) > 0 then
- FContentType := 'text/plain; charset="' + aValue + '"'
- else
- FContentType := 'text/plain';
- end;
- end;
- procedure TMimeTextSection.FillBuffer(const aSize: Integer);
- var
- s: string;
- n: Integer;
- begin
- s := Copy(FData, 1, aSize);
-
- if Length(s) = 0 then
- Exit;
-
- n := aSize;
- if Assigned(FEncodingStream) then begin
- n := FEncodingStream.Write(s[1], Length(s));
- Delete(FData, 1, n);
- if Length(FData) = 0 then begin
- FEncodingStream.Free; // to fill in the last bit
- CreateEncodingStream;
- FLocalStream.Write(CRLF[1], Length(CRLF));
- end;
-
- SetLength(s, FLocalStream.Size);
- SetLength(s, FLocalStream.Read(s[1], Length(s)));
- end else begin
- Delete(FData, 1, n);
- if Length(FData) = 0 then
- s := s + CRLF;
- end;
- FBuffer := FBuffer + s;
- end;
- function TMimeTextSection.GetSize: Integer;
- begin
- if FActivated then
- Result := Length(FBuffer) + RecalculateSize(Length(FData))
- else
- Result := Length(FBuffer) + Length(GetHeader) + RecalculateSize(Length(FData));
- if not FActivated
- or (Length(FBuffer) > 0)
- or (Length(FData) > 0) then
- if Length(FOriginalData) > 0 then
- Result := Result + Length(CRLF); // CRLF after each msg body
- end;
- procedure TMimeTextSection.SetData(const AValue: string);
- begin
- if not FActivated then begin
- FOriginalData := aValue;
- FData := aValue;
- end;
- end;
- function TMimeTextSection.GetCharset: string;
- var
- n: Integer;
- begin
- Result := '';
- n := Pos('=', FContentType);
- if n > 0 then
- Result := StringReplace(Copy(FContentType, n + 1, Length(FContentType)),
- '"', '', [rfReplaceAll]);
- end;
- constructor TMimeTextSection.Create(aOutputStream: TStream; const aText: string);
- begin
- inherited Create(aOutputStream);
- FContentType := 'text/plain; charset="UTF-8"';
- FOriginalData := aText;
- FData := FOriginalData;
- end;
- procedure TMimeTextSection.Reset;
- begin
- inherited Reset;
- FData := FOriginalData;
- end;
- { TMimeStreamSection }
- function TMimeStreamSection.GetSize: Integer;
- begin
- if FActivated then
- Result := Length(FBuffer) + RecalculateSize(FStream.Size - FStream.Position)
- else
- Result := Length(FBuffer) + Length(GetHeader) + RecalculateSize(FStream.Size - FStream.Position);
-
- if not FActivated
- or (Length(FBuffer) > 0)
- or (FStream.Size - FStream.Position > 0) then
- if FStream.Size - FOriginalPosition > 0 then
- Result := Result + Length(CRLF); // CRLF after each msg body
- end;
- procedure TMimeStreamSection.SetStream(aValue: TStream);
- begin
- if Assigned(FStream)
- and FOwnsStreams then begin
- FStream.Free;
- FStream := nil;
- end;
-
- FStream := aValue;
- FOriginalPosition := FStream.Position;
- end;
- procedure TMimeStreamSection.FillBuffer(const aSize: Integer);
- var
- s: string;
- n: Integer;
- begin
- SetLength(s, aSize);
- SetLength(s, FStream.Read(s[1], aSize));
-
- if Length(s) <= 0 then
- Exit;
-
- if Assigned(FEncodingStream) then begin
- n := FEncodingStream.Write(s[1], Length(s));
-
- if n < Length(s) then
- FStream.Position := FStream.Position - (n - Length(s));
-
- if FStream.Size - FStream.Position = 0 then begin
- FEncodingStream.Free; // to fill in the last bit
- CreateEncodingStream;
- FLocalStream.Write(CRLF[1], Length(CRLF));
- end;
-
- SetLength(s, FLocalStream.Size);
- SetLength(s, FLocalStream.Read(s[1], FLocalStream.Size));
- end else if FStream.Size - FStream.Position = 0 then
- s := s + CRLF;
- FBuffer := FBuffer + s;
- end;
- constructor TMimeStreamSection.Create(aOutputStream: TStream; aStream: TStream);
- begin
- inherited Create(aOutputStream);
-
- FDisposition := mdAttachment;
- FStream := aStream;
- FOriginalPosition := FStream.Position;
- FContentType := 'application/octet-stream';
- end;
- destructor TMimeStreamSection.Destroy;
- begin
- if FOwnsStreams then
- FStream.Free;
- inherited Destroy;
- end;
- procedure TMimeStreamSection.Reset;
- begin
- inherited Reset;
- FStream.Position := FOriginalPosition;
- end;
- { TMimeStream }
- function TMimeStream.GetBoundarySize: Integer;
- var
- n: Integer;
- begin
- Result := 0;
- if FSections.Count > 1 then begin
- n := Max(FActiveSection, 0);
- Result := (Length(FBoundary) + 4) * (FSections.Count - n) + 2;
- // # sections * (boundarylength + --CRLF +) ending --
- end;
- end;
- function TMimeStream.GetSize: Int64;
- var
- i: Integer;
- begin
- Result := 0;
-
- if FActiveSection > -2 then
- for i := 0 to Count - 1 do
- Result := Result + TMimeSection(FSections[i]).Size;
-
- if FActiveSection = -1 then // not yet active, must add header info
- Result := Result + Length(GetMimeHeader) + GetBoundarySize;
-
- Result := Result + FOutputStream.Size;
- end;
- function TMimeStream.GetCount: Integer;
- begin
- Result := FSections.Count;
- end;
- function TMimeStream.GetBoundary: string;
- var
- i: Integer;
- begin
- Result := '';
- for i := 1 to 25 + Random(15) do
- Result := Result + Char(Random(Ord('9') - Ord('0') + 1) + Ord('0'));
- end;
- function TMimeStream.GetSection(i: Integer): TMimeSection;
- begin
- Result := nil;
-
- if (i >= 0)
- and (i < FSections.Count) then
- Result := TMimeSection(FSections[i]);
- end;
- function TMimeStream.GetMimeHeader: string;
- const
- MIME_HEADER = 'Content-type: multipart/mixed; boundary="';
- begin
- Result := MIME_VERSION;
-
- if FSections.Count > 1 then
- Result := Result + MIME_HEADER + FBoundary + '"' + CRLF + CRLF +
- 'This is a multi-part message in MIME format.' + CRLF +
- '--' + FBoundary + CRLF;
- end;
- procedure TMimeStream.SetSection(i: Integer; const AValue: TMimeSection);
- begin
- if (i >= 0)
- and (i < FSections.Count) then
- FSections[i] := aValue;
- end;
- procedure TMimeStream.ActivateFirstSection;
- var
- s: string;
- begin
- if FActiveSection = -1 then
- if FSections.Count > 0 then begin
- FActiveSection := 0;
- s := GetMimeHeader;
- FOutputStream.Write(s[1], Length(s));
- end;
- end;
- procedure TMimeStream.ActivateNextSection;
- var
- s: string;
- begin
- Inc(FActiveSection);
- if FSections.Count > 1 then begin
- if FActiveSection >= FSections.Count then
- s := '--' + FBoundary + '--' + CRLF
- else
- s := '--' + FBoundary + CRLF;
-
- FOutputStream.Write(s[1], Length(s));
- end;
- if FActiveSection >= FSections.Count then
- FActiveSection := -2;
- end;
- procedure TMimeStream.DoRead(const aSize: Integer);
- begin
- ActivateFirstSection;
-
- if FActiveSection < 0 then
- Exit;
-
- TMimeSection(FSections[FActiveSection]).Read(aSize);
-
- if TMimeSection(FSections[FActiveSection]).Size = 0 then
- ActivateNextSection;
- end;
- constructor TMimeStream.Create;
- begin
- Randomize;
-
- FActiveSection := -1;
- FBoundary := GetBoundary;
- FSections := TFPObjectList.Create(True);
- FOutputStream := TMimeOutputStream.Create(@DoRead);
- end;
- destructor TMimeStream.Destroy;
- begin
- FSections.Free;
- FOutputStream.Free;
- inherited Destroy;
- end;
- function TMimeStream.Seek(Offset: Longint; Origin: Word): Longint;
- begin
- Result := Offset;
- end;
- function TMimeStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
- begin
- Result := Offset;
- end;
- function TMimeStream.Read(var Buffer; Count: Longint): Longint;
- begin
- if Count <= 0 then
- Exit(0);
-
- if FCalledWrite then
- raise EAlreadyCalledWriteException.Create;
- FCalledRead := True;
- Result := FOutputStream.Read(Buffer, Count);
- end;
- function TMimeStream.Write(const Buffer; Count: Longint): Longint;
- begin
- if Count <= 0 then
- Exit(0);
- if FCalledRead then
- raise EAlreadyCalledReadException.Create;
- Result := 0;
- FCalledWrite := True;
- raise Exception.Create('Not yet implemented');
- end;
- procedure TMimeStream.AddTextSection(const aText: string; const aCharSet: string = 'UTF-8');
- var
- s: TMimeTextSection;
- begin
- if FActiveSection >= 0 then
- raise EAlreadyActivatedException.Create;
-
- s := TMimeTextSection.Create(FOutputStream, aText);
-
- s.Charset := aCharSet;
- FSections.Add(s);
- end;
- procedure TMimeStream.AddFileSection(const aFileName: string);
- begin
- if FActiveSection >= 0 then
- raise EAlreadyActivatedException.Create;
- FSections.Add(TMimeFileSection.Create(FOutputStream, aFileName));
- end;
- procedure TMimeStream.AddStreamSection(aStream: TStream; const FreeStream: Boolean
- );
- var
- s: TMimeStreamSection;
- begin
- if FActiveSection >= 0 then
- raise EAlreadyActivatedException.Create;
- s := TMimeStreamSection.Create(FOutputStream, aStream);
- if FreeStream then
- s.OwnsStreams := True;
- FSections.Add(s);
- end;
- procedure TMimeStream.Delete(const i: Integer);
- begin
- if (i >= 0) and (i < Count) then
- FSections.Delete(i);
- end;
- procedure TMimeStream.Remove(aSection: TMimeSection);
- begin
- FSections.Remove(aSection);
- end;
- procedure TMimeStream.Reset;
- var
- i: Integer;
- begin
- FCalledRead := False;
- FCalledWrite := False;
-
- for i := 0 to FSections.Count - 1 do
- TMimeSection(FSections[i]).Reset;
-
- FOutputStream.Reset;
- FActiveSection := -1;
- end;
- { TMimeFileSection }
- procedure TMimeFileSection.SetFileName(const AValue: string);
- begin
- if not FActivated then begin
- FFileName := aValue;
- Stream := TFileStream.Create(aValue, fmOpenRead);
- SetContentType(aValue);
- end;
- end;
- procedure TMimeFileSection.SetContentType(const aFileName: string);
- var
- s: string;
- begin
- s := StringReplace(ExtractFileExt(aFileName), '.', '', [rfReplaceAll]);
- if (s = 'txt')
- or (s = 'pas')
- or (s = 'pp')
- or (s = 'pl')
- or (s = 'cpp')
- or (s = 'cc')
- or (s = 'h')
- or (s = 'hh')
- or (s = 'rb')
- or (s = 'pod')
- or (s = 'php')
- or (s = 'php3')
- or (s = 'php4')
- or (s = 'php5')
- or (s = 'c++') then FContentType := 'text/plain';
-
- if (s = 'html')
- or (s = 'shtml') then FContentType := 'text/html';
- if s = 'css' then FContentType := 'text/css';
-
- if s = 'png' then FContentType := 'image/x-png';
- if s = 'xpm' then FContentType := 'image/x-pixmap';
- if s = 'xbm' then FContentType := 'image/x-bitmap';
- if (s = 'tif')
- or (s = 'tiff') then FContentType := 'image/tiff';
- if s = 'mng' then FContentType := 'image/x-mng';
- if s = 'gif' then FContentType := 'image/gif';
- if s = 'rgb' then FContentType := 'image/rgb';
- if (s = 'jpg')
- or (s = 'jpeg') then FContentType := 'image/jpeg';
- if s = 'bmp' then FContentType := 'image/x-ms-bmp';
-
- if s = 'wav' then FContentType := 'audio/x-wav';
- if s = 'mp3' then FContentType := 'audio/x-mp3';
- if s = 'ogg' then FContentType := 'audio/x-ogg';
- if s = 'avi' then FContentType := 'video/x-msvideo';
- if (s = 'qt')
- or (s = 'mov') then FContentType := 'video/quicktime';
- if (s = 'mpg')
- or (s = 'mpeg') then FContentType := 'video/mpeg';
-
- if s = 'pdf' then FContentType := 'application/pdf';
- if s = 'rtf' then FContentType := 'application/rtf';
- if s = 'tex' then FContentType := 'application/x-tex';
- if s = 'latex' then FContentType := 'application/x-latex';
- if s = 'doc' then FContentType := 'application/msword';
- if s = 'gz' then FContentType := 'application/x-gzip';
- if s = 'zip' then FContentType := 'application/zip';
- if s = '7z' then FContentType := 'application/x-7zip';
- if s = 'rar' then FContentType := 'application/rar';
- if s = 'tar' then FContentType := 'application/x-tar';
- if s = 'arj' then FContentType := 'application/arj';
- end;
- function TMimeFileSection.GetHeader: string;
- begin
- Result := 'Content-Type: ' + FContentType + CRLF;
- Result := Result + 'Content-Transfer-Encoding: ' + EncodingToStr(FEncoding) + CRLF;
- Result := Result + 'Content-Disposition: ' + DispositionToStr(FDisposition) +
- '; filename="' + FFileName + '"' + CRLF;
- if Length(FDescription) > 0 then
- Result := Result + 'Content-Description: ' + FDescription + CRLF;
-
- Result := Result + CRLF;
- end;
- constructor TMimeFileSection.Create(aOutputStream: TStream; const aFileName: string);
- begin
- inherited Create(aOutputStream, TFileStream.Create(aFileName, fmOpenRead));
- SetContentType(aFileName);
- FDescription := ExtractFileName(aFileName);
- Encoding := meBase64;
- FFileName := ExtractFileName(aFileName);
- FOwnsStreams := True;
- end;
- { EAlreadyActivatedException }
- constructor EAlreadyActivatedException.Create;
- begin
- inherited Create('The stream or section has already been activated (by Read() or Write())');
- end;
- { EAlreadyCalledReadException }
- constructor EAlreadyCalledReadException.Create;
- begin
- inherited Create('The stream has already been used for reading');
- end;
- { EAlreadyCalledWriteException }
- constructor EAlreadyCalledWriteException.Create;
- begin
- inherited Create('The stream has already been used for writing');
- end;
- end.
|