1 {==============================================================================|
2 | Project : Delphree - Synapse | 001.005.002 |
3 |==============================================================================|
4 | Content: MIME support procedures and functions |
5 |==============================================================================|
6 | The contents of this file are subject to the Mozilla Public License Ver. 1.1 |
7 | (the "License"); you may not use this file except in compliance with the |
8 | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
10 | Software distributed under the License is distributed on an "AS IS" basis, |
11 | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
12 | the specific language governing rights and limitations under the License. |
13 |==============================================================================|
14 | The Original Code is Synapse Delphi Library. |
15 |==============================================================================|
16 | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
17 | Portions created by Lukas Gebauer are Copyright (c)2000,2001. |
18 | All Rights Reserved. |
19 |==============================================================================|
21 |==============================================================================|
22 | History: see HISTORY.HTM from distribution package |
23 | (Found at URL: http://www.ararat.cz/synapse/) |
24 |==============================================================================}
31 KOL
,SynaChar
, SynaCode
, SynaUtil
, MIMEinLn
;
35 TMimePrimary
= (MP_TEXT
, MP_MULTIPART
,
36 MP_MESSAGE
, MP_BINARY
);
38 TMimeEncoding
= (ME_7BIT
, ME_8BIT
, ME_QUOTED_PRINTABLE
,
39 ME_BASE64
, ME_UU
, ME_XX
);
41 PMimePart
= ^TMimePart
;
42 TMimePart
= object(TObj
)
47 FPrimaryCode
: TMimePrimary
;
48 FEncodingCode
: TMimeEncoding
;
49 FCharsetCode
: TMimeChar
;
50 FTargetCharset
: TMimeChar
;
58 FDecodedLines
: PStream
;//TMemoryStream;
59 procedure SetPrimary(Value
: string);
60 procedure SetEncoding(Value
: string);
61 procedure SetCharset(Value
: string);
63 destructor Destroy
;virtual;
65 function ExtractPart(Value
: PStrList
; BeginLine
: Integer): Integer;
68 procedure MimeTypeFromExt(Value
: string);
69 property Primary
: string read FPrimary write SetPrimary
;
70 property Encoding
: string read FEncoding write SetEncoding
;
71 property Charset
: string read FCharset write SetCharset
;
72 property PrimaryCode
: TMimePrimary read FPrimaryCode Write FPrimaryCode
;
73 property EncodingCode
: TMimeEncoding read FEncodingCode Write FEncodingCode
;
74 property CharsetCode
: TMimeChar read FCharsetCode Write FCharsetCode
;
75 property TargetCharset
: TMimeChar read FTargetCharset Write FTargetCharset
;
76 property Secondary
: string read FSecondary Write FSecondary
;
77 property Description
: string read FDescription Write FDescription
;
78 property Disposition
: string read FDisposition Write FDisposition
;
79 property ContentID
: string read FContentID Write FContentID
;
80 property Boundary
: string read FBoundary Write FBoundary
;
81 property FileName
: string read FFileName Write FFileName
;
82 property Lines
: PStrList read FLines
;
83 property DecodedLines
: PStream read FDecodedLines
;
88 MimeType
: array[0..MaxMimeType
, 0..2] of string =
90 ('AU', 'audio', 'basic'),
91 ('AVI', 'video', 'x-msvideo'),
92 ('BMP', 'image', 'BMP'),
93 ('DOC', 'application', 'MSWord'),
94 ('EPS', 'application', 'Postscript'),
95 ('GIF', 'image', 'GIF'),
96 ('JPEG', 'image', 'JPEG'),
97 ('JPG', 'image', 'JPEG'),
98 ('MID', 'audio', 'midi'),
99 ('MOV', 'video', 'quicktime'),
100 ('MPEG', 'video', 'MPEG'),
101 ('MPG', 'video', 'MPEG'),
102 ('MP2', 'audio', 'mpeg'),
103 ('MP3', 'audio', 'mpeg'),
104 ('PDF', 'application', 'PDF'),
105 ('PNG', 'image', 'PNG'),
106 ('PS', 'application', 'Postscript'),
107 ('QT', 'video', 'quicktime'),
108 ('RA', 'audio', 'x-realaudio'),
109 ('RTF', 'application', 'RTF'),
110 ('SND', 'audio', 'basic'),
111 ('TIF', 'image', 'TIFF'),
112 ('TIFF', 'image', 'TIFF'),
113 ('WAV', 'audio', 'x-wav'),
114 ('WPD', 'application', 'Wordperfect5.1'),
115 ('ZIP', 'application', 'ZIP')
118 function NormalizeHeader(Value
: PStrList
; var Index
: Integer): string;
119 function GenerateBoundary
: string;
121 function NewMimePart
: PMimePart
;
125 function NormalizeHeader(Value
: PStrList
; var Index
: Integer): string;
130 s
:= Value
.Items
[Index
];
133 while (Value
.Count
- 1) > Index
do
135 t
:= Value
.Items
[Index
];
138 for n
:= 1 to Length(t
) do
145 s
:= s
+ ' ' + Trim(t
);
152 {==============================================================================}
155 function NewMimePart
: PMimePart
;
158 Result
.FLines
:= NewStrList
;//TStringList.Create;
159 Result
.FDecodedLines
:= NewMemoryStream
;//TMemoryStream.Create;
160 Result
.FTargetCharset
:= GetCurCP
;
163 destructor TMIMEPart
.Destroy
;
170 {==============================================================================}
172 procedure TMIMEPart
.Clear
;
177 FPrimaryCode
:= MP_TEXT
;
178 FEncodingCode
:= ME_7BIT
;
179 FCharsetCode
:= ISO_8859_1
;
180 FTargetCharset
:= GetCurCP
;
188 // FDecodedLines.Clear;
189 FDecodedLines
.Size
:= 0;
192 {==============================================================================}
194 function TMIMEPart
.ExtractPart(Value
: PStrList
; BeginLine
: Integer): Integer;
196 n
, x
, x1
, x2
: Integer;
203 t
:= NewStrList
;//TStringlist.Create;
208 FSecondary
:= 'plain';
210 Charset
:= 'US-ASCII';
217 { if multipart - skip pre-part }
219 while Value
.Count
> x
do
223 if Pos('--' + b
, s
) = 1 then
228 while Value
.Count
> x
do
230 s
:= NormalizeHeader(Value
, x
);
234 if Pos('CONTENT-TYPE:', su
) = 1 then
236 st
:= SeparateRight(su
, ':');
237 st2
:= SeparateLeft(st
, ';');
238 Primary
:= SeparateLeft(st2
, '/');
239 FSecondary
:= SeparateRight(st2
, '/');
240 if (FSecondary
= Primary
) and (Pos('/', st2
) < 1) then
245 Charset
:= UpperCase(GetParameter(s
, 'charset='));
246 FFileName
:= GetParameter(s
, 'name=');
249 FBoundary
:= GetParameter(s
, 'Boundary=');
254 FFileName
:= GetParameter(s
, 'name=');
257 if Pos('CONTENT-TRANSFER-ENCODING:', su
) = 1 then
258 Encoding
:= SeparateRight(su
, ':');
259 if Pos('CONTENT-DESCRIPTION:', su
) = 1 then
260 FDescription
:= SeparateRight(s
, ':');
261 if Pos('CONTENT-DISPOSITION:', su
) = 1 then
263 FDisposition
:= SeparateRight(su
, ':');
264 FDisposition
:= Trim(SeparateLeft(FDisposition
, ';'));
265 fn
:= GetParameter(s
, 'FileName=');
267 if Pos('CONTENT-ID:', su
) = 1 then
268 FContentID
:= SeparateRight(s
, ':');
271 if (PrimaryCode
= MP_BINARY
) and (FFileName
= '') then
273 FFileName
:= InlineDecode(FFileName
, getCurCP
);
274 FFileName
:= ExtractFileName(FFileName
);
276 { finding part content x1-begin x2-end }
278 x2
:= Value
.Count
- 1;
279 { if multipart - end is before next boundary }
282 for n
:= x
to Value
.Count
- 1 do
286 if Pos('--' + b
, s
) = 1 then
293 { if content is multipart - content is delimited by their boundaries }
294 if FPrimaryCode
= MP_MULTIPART
then
296 for n
:= x
to Value
.Count
- 1 do
299 if Pos('--' + FBoundary
, s
) = 1 then
305 for n
:= Value
.Count
- 1 downto x
do
308 if Pos('--' + FBoundary
, s
) = 1 then
317 FLines
.Add(Value
.Items
[n
]);
319 { if content is multipart - find real end }
320 if FPrimaryCode
= MP_MULTIPART
then
323 for n
:= x2
+ 1 to Value
.Count
- 1 do
324 if Pos('--' + b
, Value
.Items
[n
]) = 1 then
330 Result
:= Value
.Count
- 1;
332 { if multipart - skip ending postpart}
336 for n
:= x1
to Value
.Count
- 1 do
339 if Pos('--' + b
, s
) = 1 then
344 if (s
[x
] = '-') and (S
[x
-1] = '-') then
345 Result
:= Value
.Count
- 1;
355 {==============================================================================}
357 procedure TMIMEPart
.DecodePart
;
364 FDecodedLines
.Size
:= 0;// FDecodedLines.Clear;
365 for n
:= 0 to FLines
.Count
- 1 do
367 s
:= FLines
.Items
[n
];
368 case FEncodingCode
of
373 s
:= CharsetConversion(s
, FCharsetCode
, FTargetCharset
);
381 if s
[Length(s
)] <> '=' then
383 s
:= DecodeQuotedPrintable(s
);
384 if FPrimaryCode
= MP_TEXT
then
385 s
:= CharsetConversion(s
, FCharsetCode
, FTargetCharset
);
390 s
:= DecodeBase64(s
);
391 if FPrimaryCode
= MP_TEXT
then
392 s
:= CharsetConversion(s
, FCharsetCode
, FTargetCharset
);
401 FDecodedLines
.Write(Pointer(s
)^, Length(s
));
403 FDecodedLines
.Seek(0,spBegin
);
406 {==============================================================================}
408 procedure TMIMEPart
.EncodePart
;
414 if (FEncodingCode
= ME_UU
) or (FEncodingCode
= ME_XX
) then
415 Encoding
:= 'base64';
416 l
:= NewStrList
;//TStringList.Create;
418 FDecodedLines
.Seek(0, spBegin
);
421 MP_MULTIPART
, MP_MESSAGE
:
422 FLines
.LoadFromStream(FDecodedLines
,false);
424 if FEncodingCode
= ME_BASE64
then
426 while FDecodedLines
.Position
< FDecodedLines
.Size
do
430 x
:= FDecodedLines
.Read(pointer(Buff
)^, 54);
433 if FPrimaryCode
= MP_TEXT
then
434 s
:= CharsetConversion(s
, FTargetCharset
, FCharsetCode
);
435 s
:= EncodeBase64(s
);
441 l
.LoadFromStream(FDecodedLines
,false);
442 for n
:= 0 to l
.Count
- 1 do
445 if FPrimaryCode
= MP_TEXT
then
446 s
:= CharsetConversion(s
, FTargetCharset
, FCharsetCode
);
447 s
:= EncodeQuotedPrintable(s
);
454 FLines
.Insert(0, '');
455 if FSecondary
= '' then
458 FSecondary
:= 'plain';
460 FSecondary
:= 'mixed';
462 FSecondary
:= 'rfc822';
464 FSecondary
:= 'octet-stream';
466 if FDescription
<> '' then
467 FLines
.Insert(0, 'Content-Description: ' + FDescription
);
468 if FDisposition
<> '' then
471 if FFileName
<> '' then
472 s
:= '; FileName="' + FFileName
+ '"';
473 FLines
.Insert(0, 'Content-Disposition: ' + LowerCase(FDisposition
) + s
);
475 if FContentID
<> '' then
476 FLines
.Insert(0, 'Content-ID: ' + FContentID
);
478 case FEncodingCode
of
484 s
:= 'Quoted-printable';
490 MP_BINARY
: FLines
.Insert(0, 'Content-Transfer-Encoding: ' + s
);
494 s
:= FPrimary
+ '/' + FSecondary
+ '; charset=' + GetIDfromCP(FCharsetCode
);
496 s
:= FPrimary
+ '/' + FSecondary
+ '; boundary="' + FBoundary
+ '"';
498 s
:= FPrimary
+ '/' + FSecondary
+ '';
500 s
:= FPrimary
+ '/' + FSecondary
+ '; name="' + FFileName
+ '"';
502 FLines
.Insert(0, 'Content-type: ' + s
);
508 {==============================================================================}
510 procedure TMIMEPart
.MimeTypeFromExt(Value
: string);
517 s
:= UpperCase(ExtractFileExt(Value
));
519 s
:= UpperCase(Value
);
520 s
:= SeparateRight(s
, '.');
521 for n
:= 0 to MaxMimeType
do
522 if MimeType
[n
, 0] = s
then
524 Primary
:= MimeType
[n
, 1];
525 FSecondary
:= MimeType
[n
, 2];
529 Primary
:= 'application';
530 if FSecondary
= '' then
531 FSecondary
:= 'octet-string';
534 {==============================================================================}
536 procedure TMIMEPart
.SetPrimary(Value
: string);
541 s
:= UpperCase(Value
);
542 FPrimaryCode
:= MP_BINARY
;
543 if Pos('TEXT', s
) = 1 then
544 FPrimaryCode
:= MP_TEXT
;
545 if Pos('MULTIPART', s
) = 1 then
546 FPrimaryCode
:= MP_MULTIPART
;
547 if Pos('MESSAGE', s
) = 1 then
548 FPrimaryCode
:= MP_MESSAGE
;
551 procedure TMIMEPart
.SetEncoding(Value
: string);
556 s
:= UpperCase(Value
);
557 FEncodingCode
:= ME_7BIT
;
558 if Pos('8BIT', s
) = 1 then
559 FEncodingCode
:= ME_8BIT
;
560 if Pos('QUOTED-PRINTABLE', s
) = 1 then
561 FEncodingCode
:= ME_QUOTED_PRINTABLE
;
562 if Pos('BASE64', s
) = 1 then
563 FEncodingCode
:= ME_BASE64
;
564 if Pos('X-UU', s
) = 1 then
565 FEncodingCode
:= ME_UU
;
566 if Pos('X-XX', s
) = 1 then
567 FEncodingCode
:= ME_XX
;
570 procedure TMIMEPart
.SetCharset(Value
: string);
573 FCharsetCode
:= GetCPFromID(Value
);
576 {==============================================================================}
578 function GenerateBoundary
: string;
584 Result
:= '--' + Int2Hex(x
, 8) + '_Synapse_message_boundary--';