264 lines
9.2 KiB
Plaintext
264 lines
9.2 KiB
Plaintext
|
{==============================================================================|
|
||
|
| Project : Ararat Synapse | 001.001.011 |
|
||
|
|==============================================================================|
|
||
|
| Content: Inline MIME support procedures and functions |
|
||
|
|==============================================================================|
|
||
|
| Copyright (c)1999-2006, Lukas Gebauer |
|
||
|
| All rights reserved. |
|
||
|
| |
|
||
|
| Redistribution and use in source and binary forms, with or without |
|
||
|
| modification, are permitted provided that the following conditions are met: |
|
||
|
| |
|
||
|
| Redistributions of source code must retain the above copyright notice, this |
|
||
|
| list of conditions and the following disclaimer. |
|
||
|
| |
|
||
|
| Redistributions in binary form must reproduce the above copyright notice, |
|
||
|
| this list of conditions and the following disclaimer in the documentation |
|
||
|
| and/or other materials provided with the distribution. |
|
||
|
| |
|
||
|
| Neither the name of Lukas Gebauer nor the names of its contributors may |
|
||
|
| be used to endorse or promote products derived from this software without |
|
||
|
| specific prior written permission. |
|
||
|
| |
|
||
|
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||
|
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||
|
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||
|
| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
|
||
|
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
||
|
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
||
|
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
||
|
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
||
|
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
||
|
| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|
||
|
| DAMAGE. |
|
||
|
|==============================================================================|
|
||
|
| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
|
||
|
| Portions created by Lukas Gebauer are Copyright (c)2000-2006. |
|
||
|
| All Rights Reserved. |
|
||
|
|==============================================================================|
|
||
|
| Contributor(s): |
|
||
|
|==============================================================================|
|
||
|
| History: see HISTORY.HTM from distribution package |
|
||
|
| (Found at URL: http://www.ararat.cz/synapse/) |
|
||
|
|==============================================================================}
|
||
|
|
||
|
{:@abstract(Utilities for inline MIME)
|
||
|
Support for Inline MIME encoding and decoding.
|
||
|
|
||
|
Used RFC: RFC-2047, RFC-2231
|
||
|
}
|
||
|
|
||
|
{$IFDEF FPC}
|
||
|
{$MODE DELPHI}
|
||
|
{$ENDIF}
|
||
|
{$H+}
|
||
|
|
||
|
{$IFDEF UNICODE}
|
||
|
{$WARN IMPLICIT_STRING_CAST OFF}
|
||
|
{$WARN IMPLICIT_STRING_CAST_LOSS OFF}
|
||
|
{$ENDIF}
|
||
|
|
||
|
unit mimeinln;
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
SysUtils, Classes,
|
||
|
synachar, synacode, synautil;
|
||
|
|
||
|
{:Decodes mime inline encoding (i.e. in headers) uses target characterset "CP".}
|
||
|
function InlineDecode(const Value: string; CP: TMimeChar): string;
|
||
|
|
||
|
{:Encodes string to MIME inline encoding. The source characterset is "CP", and
|
||
|
the target charset is "MimeP".}
|
||
|
function InlineEncode(const Value: string; CP, MimeP: TMimeChar): string;
|
||
|
|
||
|
{:Returns @true, if "Value" contains characters needed for inline coding.}
|
||
|
function NeedInline(const Value: AnsiString): boolean;
|
||
|
|
||
|
{:Inline mime encoding similar to @link(InlineEncode), but you can specify
|
||
|
source charset, and the target characterset is automatically assigned.}
|
||
|
function InlineCodeEx(const Value: string; FromCP: TMimeChar): string;
|
||
|
|
||
|
{:Inline MIME encoding similar to @link(InlineEncode), but the source charset
|
||
|
is automatically set to the system default charset, and the target charset is
|
||
|
automatically assigned from set of allowed encoding for MIME.}
|
||
|
function InlineCode(const Value: string): string;
|
||
|
|
||
|
{:Converts e-mail address to canonical mime form. You can specify source charset.}
|
||
|
function InlineEmailEx(const Value: string; FromCP: TMimeChar): string;
|
||
|
|
||
|
{:Converts e-mail address to canonical mime form. Source charser it system
|
||
|
default charset.}
|
||
|
function InlineEmail(const Value: string): string;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function InlineDecode(const Value: string; CP: TMimeChar): string;
|
||
|
var
|
||
|
s, su, v: string;
|
||
|
x, y, z, n: Integer;
|
||
|
ichar: TMimeChar;
|
||
|
c: Char;
|
||
|
|
||
|
function SearchEndInline(const Value: string; be: Integer): Integer;
|
||
|
var
|
||
|
n, q: Integer;
|
||
|
begin
|
||
|
q := 0;
|
||
|
Result := 0;
|
||
|
for n := be + 2 to Length(Value) - 1 do
|
||
|
if Value[n] = '?' then
|
||
|
begin
|
||
|
Inc(q);
|
||
|
if (q > 2) and (Value[n + 1] = '=') then
|
||
|
begin
|
||
|
Result := n;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := '';
|
||
|
v := Value;
|
||
|
x := Pos('=?', v);
|
||
|
y := SearchEndInline(v, x);
|
||
|
//fix for broken coding with begin, but not with end.
|
||
|
if (x > 0) and (y <= 0) then
|
||
|
y := Length(Result);
|
||
|
while (y > x) and (x > 0) do
|
||
|
begin
|
||
|
s := Copy(v, 1, x - 1);
|
||
|
if Trim(s) <> '' then
|
||
|
Result := Result + s;
|
||
|
s := Copy(v, x, y - x + 2);
|
||
|
Delete(v, 1, y + 1);
|
||
|
su := Copy(s, 3, Length(s) - 4);
|
||
|
z := Pos('?', su);
|
||
|
if (Length(su) >= (z + 2)) and (su[z + 2] = '?') then
|
||
|
begin
|
||
|
ichar := GetCPFromID(SeparateLeft(Copy(su, 1, z - 1), '*'));
|
||
|
c := UpperCase(su)[z + 1];
|
||
|
su := Copy(su, z + 3, Length(su) - z - 2);
|
||
|
if c = 'B' then
|
||
|
begin
|
||
|
s := DecodeBase64(su);
|
||
|
s := CharsetConversion(s, ichar, CP);
|
||
|
end;
|
||
|
if c = 'Q' then
|
||
|
begin
|
||
|
s := '';
|
||
|
for n := 1 to Length(su) do
|
||
|
if su[n] = '_' then
|
||
|
s := s + ' '
|
||
|
else
|
||
|
s := s + su[n];
|
||
|
s := DecodeQuotedPrintable(s);
|
||
|
s := CharsetConversion(s, ichar, CP);
|
||
|
end;
|
||
|
end;
|
||
|
Result := Result + s;
|
||
|
x := Pos('=?', v);
|
||
|
y := SearchEndInline(v, x);
|
||
|
end;
|
||
|
Result := Result + v;
|
||
|
end;
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function InlineEncode(const Value: string; CP, MimeP: TMimeChar): string;
|
||
|
var
|
||
|
s, s1, e: string;
|
||
|
n: Integer;
|
||
|
begin
|
||
|
s := CharsetConversion(Value, CP, MimeP);
|
||
|
s := EncodeSafeQuotedPrintable(s);
|
||
|
e := GetIdFromCP(MimeP);
|
||
|
s1 := '';
|
||
|
Result := '';
|
||
|
for n := 1 to Length(s) do
|
||
|
if s[n] = ' ' then
|
||
|
begin
|
||
|
// s1 := s1 + '=20';
|
||
|
s1 := s1 + '_';
|
||
|
if Length(s1) > 32 then
|
||
|
begin
|
||
|
if Result <> '' then
|
||
|
Result := Result + ' ';
|
||
|
Result := Result + '=?' + e + '?Q?' + s1 + '?=';
|
||
|
s1 := '';
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
s1 := s1 + s[n];
|
||
|
if s1 <> '' then
|
||
|
begin
|
||
|
if Result <> '' then
|
||
|
Result := Result + ' ';
|
||
|
Result := Result + '=?' + e + '?Q?' + s1 + '?=';
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function NeedInline(const Value: AnsiString): boolean;
|
||
|
var
|
||
|
n: Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
for n := 1 to Length(Value) do
|
||
|
if Value[n] in (SpecialChar + NonAsciiChar - ['_']) then
|
||
|
begin
|
||
|
Result := True;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function InlineCodeEx(const Value: string; FromCP: TMimeChar): string;
|
||
|
var
|
||
|
c: TMimeChar;
|
||
|
begin
|
||
|
if NeedInline(Value) then
|
||
|
begin
|
||
|
c := IdealCharsetCoding(Value, FromCP, IdealCharsets);
|
||
|
Result := InlineEncode(Value, FromCP, c);
|
||
|
end
|
||
|
else
|
||
|
Result := Value;
|
||
|
end;
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function InlineCode(const Value: string): string;
|
||
|
begin
|
||
|
Result := InlineCodeEx(Value, GetCurCP);
|
||
|
end;
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function InlineEmailEx(const Value: string; FromCP: TMimeChar): string;
|
||
|
var
|
||
|
sd, se: string;
|
||
|
begin
|
||
|
sd := GetEmailDesc(Value);
|
||
|
se := GetEmailAddr(Value);
|
||
|
if sd = '' then
|
||
|
Result := se
|
||
|
else
|
||
|
Result := '"' + InlineCodeEx(sd, FromCP) + '" <' + se + '>';
|
||
|
end;
|
||
|
|
||
|
{==============================================================================}
|
||
|
|
||
|
function InlineEmail(const Value: string): string;
|
||
|
begin
|
||
|
Result := InlineEmailEx(Value, GetCurCP);
|
||
|
end;
|
||
|
|
||
|
end.
|