diff --git a/asn1util.pas b/asn1util.pas index ca71913..ba713a0 100644 --- a/asn1util.pas +++ b/asn1util.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.003.002 | +| Project : Delphree - Synapse | 001.003.003 | |==============================================================================| | Content: support for ASN.1 coding and decoding | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -26,6 +26,7 @@ |==============================================================================} {$Q-} +{$WEAKPACKAGEUNIT ON} unit ASN1Util; @@ -46,204 +47,202 @@ const ASN1_TIMETICKS = $43; ASN1_OPAQUE = $44; -function ASNEncOIDitem(Value: integer): string; -function ASNDecOIDitem(var Start: integer; Buffer: string): integer; -function ASNEncLen(Len: integer): string; -function ASNDecLen(var Start: integer; Buffer: string): integer; -function ASNEncInt(Value: integer): string; -function ASNEncUInt(Value: integer): string; -function ASNObject(Data: string; ASNType: integer): string; -function ASNItem(var Start: integer; Buffer: string; var ValueType:integer): string; -Function MibToId(mib:string):string; -Function IdToMib(id:string):string; -Function IntMibToStr(int:string):string; +function ASNEncOIDItem(Value: Integer): string; +function ASNDecOIDItem(var Start: Integer; const Buffer: string): Integer; +function ASNEncLen(Len: Integer): string; +function ASNDecLen(var Start: Integer; const Buffer: string): Integer; +function ASNEncInt(Value: Integer): string; +function ASNEncUInt(Value: Integer): string; +function ASNObject(const Data: string; ASNType: Integer): string; +function ASNItem(var Start: Integer; const Buffer: string; + var ValueType: Integer): string; +function MibToId(Mib: string): string; +function IdToMib(const Id: string): string; +function IntMibToStr(const Value: string): string; function IPToID(Host: string): string; implementation {==============================================================================} -{ASNEncOIDitem} -function ASNEncOIDitem(Value: integer): string; + +function ASNEncOIDItem(Value: Integer): string; var - x,xm:integer; - b:boolean; + x, xm: Integer; + b: Boolean; begin - x:=value; - b:=false; - result:=''; + x := Value; + b := False; + Result := ''; repeat - xm:=x mod 128; - x:=x div 128; + xm := x mod 128; + x := x div 128; if b then - xm:=xm or $80; - if x>0 - then b:=true; - result:=char(xm)+result; - until x=0; + xm := xm or $80; + if x > 0 then + b := True; + Result := Char(xm) + Result; + until x = 0; end; {==============================================================================} -{ASNDecOIDitem} -function ASNDecOIDitem(var Start: integer; Buffer: string): integer; + +function ASNDecOIDItem(var Start: Integer; const Buffer: string): Integer; var - x:integer; - b:boolean; + x: Integer; + b: Boolean; begin - result:=0; + Result := 0; repeat - result:=result*128; + Result := Result * 128; x := Ord(Buffer[Start]); - inc(start); - b:=x>$7f; - x:=x and $7f; - result:=result+x; - if not b - then break; - until false + Inc(Start); + b := x > $7F; + x := x and $7F; + Result := Result + x; + until not b; end; {==============================================================================} -{ASNEncLen} -function ASNEncLen(Len: integer): string; + +function ASNEncLen(Len: Integer): string; var - x, y: integer; + x, y: Integer; begin - if (len<$80) - then result:=char(len) - else - begin - x:=len; - result:=''; - repeat - y:=x mod 256; - x:=x div 256; - result:=char(y)+result; - until x=0; - y:=length(result); - y:=y or $80; - result:=char(y)+result; - end; + if Len < $80 then + Result := Char(Len) + else + begin + x := Len; + Result := ''; + repeat + y := x mod 256; + x := x div 256; + Result := Char(y) + Result; + until x = 0; + y := Length(Result); + y := y or $80; + Result := Char(y) + Result; + end; end; {==============================================================================} -{ASNDecLen} -function ASNDecLen(var Start: integer; Buffer: string): integer; + +function ASNDecLen(var Start: Integer; const Buffer: string): Integer; var - x,n: integer; + x, n: Integer; begin - x:=Ord(Buffer[Start]); + x := Ord(Buffer[Start]); Inc(Start); - if (x<$80) - then Result:=x - else - begin - result:=0; - x:=x and $7f; - for n:=1 to x do - begin - result:=result*256; - x:=Ord(Buffer[Start]); - Inc(Start); - result:=result+x; - end; - end; + if x < $80 then + Result := x + else + begin + Result := 0; + x := x and $7F; + for n := 1 to x do + begin + Result := Result * 256; + x := Ord(Buffer[Start]); + Inc(Start); + Result := Result + x; + end; + end; end; {==============================================================================} -{ASNEncInt} -function ASNEncInt(Value: integer): string; + +function ASNEncInt(Value: Integer): string; var - x,y:cardinal; - neg:boolean; + x, y: Cardinal; + neg: Boolean; begin - neg:=value<0; - x:=abs(Value); + neg := Value < 0; + x := Abs(Value); if neg then - x:=not (x-1); - result:=''; + x := not (x - 1); + Result := ''; repeat - y:=x mod 256; - x:=x div 256; - result:=char(y)+result; - until x=0; - if (not neg) and (result[1]>#$7F) - then result:=#0+result; + y := x mod 256; + x := x div 256; + Result := Char(y) + Result; + until x = 0; + if (not neg) and (Result[1] > #$7F) then + Result := #0 + Result; end; {==============================================================================} -{ASNEncUInt} -function ASNEncUInt(Value: integer): string; + +function ASNEncUInt(Value: Integer): string; var - x,y:integer; - neg:boolean; + x, y: Integer; + neg: Boolean; begin - neg:=value<0; - x:=Value; - if neg - then x:=x and $7FFFFFFF; - result:=''; + neg := Value < 0; + x := Value; + if neg then + x := x and $7FFFFFFF; + Result := ''; repeat - y:=x mod 256; - x:=x div 256; - result:=char(y)+result; - until x=0; - if neg - then result[1]:=char(ord(result[1]) or $80); + y := x mod 256; + x := x div 256; + Result := Char(y) + Result; + until x = 0; + if neg then + Result[1] := Char(Ord(Result[1]) or $80); end; {==============================================================================} -{ASNObject} -function ASNObject(Data: string; ASNType: integer): string; + +function ASNObject(const Data: string; ASNType: Integer): string; begin Result := Char(ASNType) + ASNEncLen(Length(Data)) + Data; end; {==============================================================================} -{ASNItem} -function ASNItem(var Start: integer; Buffer: string; var ValueType:integer): string; + +function ASNItem(var Start: Integer; const Buffer: string; + var ValueType: Integer): string; var - ASNType: integer; - ASNSize: integer; - y,n: integer; + ASNType: Integer; + ASNSize: Integer; + y, n: Integer; x: byte; s: string; c: char; - neg: boolean; - l:integer; + neg: Boolean; + l: Integer; begin - Result:=''; - ValueType:=ASN1_NULL; - l:=length(buffer); - if l<(start+1) - then exit; + Result := ''; + ValueType := ASN1_NULL; + l := Length(Buffer); + if l < (Start + 1) then + Exit; ASNType := Ord(Buffer[Start]); - Valuetype:=ASNType; - Inc(start); + ValueType := ASNType; + Inc(Start); ASNSize := ASNDecLen(Start, Buffer); - if (Start+ASNSize-1)>l - then exit; - if ((ASNType and $20) > 0) then - begin - Result := '$' + IntToHex(ASNType, 2); - end + if (Start + ASNSize - 1) > l then + Exit; + if (ASNType and $20) > 0 then + Result := '$' + IntToHex(ASNType, 2) else case ASNType of ASN1_INT: begin y := 0; - neg:=false; + neg := False; for n := 1 to ASNSize do begin - x:=Ord(Buffer[Start]); - if (n=1) and (x>$7F) - then neg:=true; - if neg - then x:=not x; + x := Ord(Buffer[Start]); + if (n = 1) and (x > $7F) then + neg := True; + if neg then + x := not x; y := y * 256 + x; Inc(Start); end; - if neg - then y:=-(y+1); + if neg then + y := -(y + 1); Result := IntToStr(y); end; ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS: @@ -299,101 +298,95 @@ begin end; {==============================================================================} -{MibToId} -function MibToId(mib:string):string; -var - x:integer; - Function walkInt(var s:string):integer; +function MibToId(Mib: string): string; +var + x: Integer; + + function WalkInt(var s: string): Integer; var - x:integer; - t:string; + x: Integer; + t: string; begin - x:=pos('.',s); - if x<1 then - begin - t:=s; - s:=''; - end - else - begin - t:=copy(s,1,x-1); - s:=copy(s,x+1,length(s)-x); - end; - result:=StrToIntDef(t,0); + x := Pos('.', s); + if x < 1 then + begin + t := s; + s := ''; + end + else + begin + t := Copy(s, 1, x - 1); + s := Copy(s, x + 1, Length(s) - x); + end; + Result := StrToIntDef(t, 0); end; + begin - result:=''; - x:=walkint(mib); - x:=x*40+walkint(mib); - result:=ASNEncOIDItem(x); - while mib<>'' do - begin - x:=walkint(mib); - result:=result+ASNEncOIDItem(x); - end; + Result := ''; + x := WalkInt(Mib); + x := x * 40 + WalkInt(Mib); + Result := ASNEncOIDItem(x); + while Mib <> '' do + begin + x := WalkInt(Mib); + Result := Result + ASNEncOIDItem(x); + end; end; {==============================================================================} -{IdToMib} -Function IdToMib(id:string):string; + +function IdToMib(const Id: string): string; var - x,y,n:integer; + x, y, n: Integer; begin - result:=''; - n:=1; - while length(id)+1>n do + Result := ''; + n := 1; + while Length(Id) + 1 > n do + begin + x := ASNDecOIDItem(n, Id); + if (n - 1) = 1 then begin - x:=ASNDecOIDItem(n,id); - if (n-1)=1 then - begin - y:=x div 40; - x:=x mod 40; - result:=IntTostr(y); - end; - result:=result+'.'+IntToStr(x); + y := x div 40; + x := x mod 40; + Result := IntToStr(y); end; + Result := Result + '.' + IntToStr(x); + end; end; {==============================================================================} -{IntMibToStr} -Function IntMibToStr(int:string):string; -Var - n,y:integer; + +function IntMibToStr(const Value: string): string; +var + n, y: Integer; begin - y:=0; - for n:=1 to length(int)-1 do - y:=y*256+ord(int[n]); - result:=IntToStr(y); + y := 0; + for n := 1 to Length(Value) - 1 do + y := y * 256 + Ord(Value[n]); + Result := IntToStr(y); end; {==============================================================================} -{IPToID} //Hernan Sanchez +//Hernan Sanchez + function IPToID(Host: string): string; var s, t: string; - i, x: integer; + i, x: Integer; begin Result := ''; - for x:= 1 to 3 do - begin - t := ''; - s := StrScan(PChar(Host), '.'); - t := Copy(Host, 1, (Length(Host) - Length(s))); - Delete(Host, 1, (Length(Host) - Length(s) + 1)); - i := StrTointDef(t, 0); - Result := Result + Chr(i); - end; - i := StrTointDef(Host, 0); + for x := 1 to 3 do + begin + t := ''; + s := StrScan(PChar(Host), '.'); + t := Copy(Host, 1, (Length(Host) - Length(s))); + Delete(Host, 1, (Length(Host) - Length(s) + 1)); + i := StrToIntDef(t, 0); + Result := Result + Chr(i); + end; + i := StrToIntDef(Host, 0); Result := Result + Chr(i); end; -{==============================================================================} - -begin - exit; - asm - db 'Synapse ASN.1 library by Lukas Gebauer',0 - end; end. - diff --git a/blcksck2.pas b/blcksck2.pas deleted file mode 100644 index ca9be4d..0000000 --- a/blcksck2.pas +++ /dev/null @@ -1,134 +0,0 @@ -{==============================================================================| -| Project : Delphree - Synapse | 002.000.000 | -|==============================================================================| -| Content: Library base for RAW sockets | -|==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | -| (the "License"); you may not use this file except in compliance with the | -| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | -| | -| Software distributed under the License is distributed on an "AS IS" basis, | -| WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | -| the specific language governing rights and limitations under the License. | -|==============================================================================| -| The Original Code is Synapse Delphi Library. | -|==============================================================================| -| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| -| Portions created by Lukas Gebauer are Copyright (c)2000. | -| All Rights Reserved. | -|==============================================================================| -| Contributor(s): | -|==============================================================================| -| History: see HISTORY.HTM from distribution package | -| (Found at URL: http://www.ararat.cz/synapse/) | -|==============================================================================} - -{ -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Remember, this unit work only on Linux or Windows with Winsock2! - (on Win98 and WinNT 4.0 or higher) -If you must use this unit on Win95, download Wínsock2 from Microsoft -and distribute it with your application! - -In spite of I use Winsock level version 1.1, RAW sockets work in this level only -if Winsock2 is installed on your computer!!! - -On WinNT standardly RAW sockets work if program is running under user with -administrators provilegies. To use RAW sockets under another users, you must -create the following registry variable and set its value to DWORD 1: - -HKLM\System\CurrentControlSet\Services\Afd\Parameters\DisableRawSecurity - -After you change the registry, you need to restart your computer! - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -} - -unit blcksck2; - -interface - -uses - synsock, SysUtils, blcksock, -{$IFDEF LINUX} - libc, kernelioctl; -{$ELSE} - winsock, windows; -{$ENDIF} - -type - -{TICMPBlockSocket} -TICMPBlockSocket = class (TBlockSocket) -public - procedure CreateSocket; override; -end; - -{TRAWBlockSocket} -TRAWBlockSocket = class (TBlockSocket) -public - procedure CreateSocket; override; -end; - -TIPHeader = Record - VerLen : Byte; - TOS : Byte; - TotalLen : Word; - Identifer : Word; - FragOffsets : Word; - TTL : Byte; - Protocol : Byte; - CheckSum : Word; - SourceIp : Dword; - DestIp : Dword; - Options : Dword; - End; - -function SetTimeout(Sock:TSocket;Timeout:integer):Boolean; - - -implementation - -{======================================================================} - -{TICMPBlockSocket.CreateSocket} -Procedure TICMPBlockSocket.CreateSocket; -begin - FSocket:=synsock.socket(PF_INET,integer(SOCK_RAW),IPPROTO_ICMP); - FProtocol:=IPPROTO_ICMP; - inherited createSocket; -end; - - -{======================================================================} - -{TRAWBlockSocket.CreateSocket} -Procedure TRAWBlockSocket.CreateSocket; -begin - FSocket:=synsock.socket(PF_INET,integer(SOCK_RAW),IPPROTO_RAW); - FProtocol:=IPPROTO_RAW; - inherited createSocket; -end; - - -{======================================================================} - -function SetTimeout(Sock:TSocket;Timeout:integer):Boolean; -var - len,Value,res:integer; - r1,r2:Boolean; -begin - Result:=False; - r1:=False; - r2:=False; - Value:=Timeout; - len:=SizeOf(Value); - Res:=synsock.setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,@Value,len); - r1:=res<>SOCKET_ERROR; - Res:=synsock.setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,@Value,len); - r2:=res<>SOCKET_ERROR; - Result:=r1 and r2; -end; - -end. diff --git a/blcksock.pas b/blcksock.pas index e4e60d8..10faf75 100644 --- a/blcksock.pas +++ b/blcksock.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 003.001.000 | +| Project : Delphree - Synapse | 003.002.000 | |==============================================================================| | Content: Library base | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -23,813 +23,943 @@ | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} +{$WEAKPACKAGEUNIT ON} + unit blcksock; interface uses - synsock, SysUtils, classes, + SysUtils, Classes, {$IFDEF LINUX} - libc, kernelioctl; + Libc, kernelioctl, {$ELSE} - winsock, windows; + Windows, WinSock, {$ENDIF} + synsock; + +const + cLocalhost = 'localhost'; type -ESynapseError = class (Exception) -Public - ErrorCode:integer; - ErrorMessage:string; -end; + ESynapseError = class(Exception) + public + ErrorCode: Integer; + ErrorMessage: string; + end; -{TBlockSocket} -TBlockSocket = class (TObject) -Protected - FSocket:TSocket; - FLocalSin:TSockAddrIn; - FRemoteSin:TSockAddrIn; - FLastError:integer; - FProtocol:integer; - FBuffer:string; - FRaiseExcept:boolean; + TBlockSocket = class(TObject) + private + FWsaData: TWSADATA; + FLocalSin: TSockAddrIn; + FRemoteSin: TSockAddrIn; + FLastError: Integer; + FBuffer: string; + FRaiseExcept: Boolean; + function GetSizeRecvBuffer: Integer; + procedure SetSizeRecvBuffer(Size: Integer); + function GetSizeSendBuffer: Integer; + procedure SetSizeSendBuffer(Size: Integer); + protected + FSocket: TSocket; + FProtocol: Integer; + procedure CreateSocket; virtual; + procedure SetSin(var Sin: TSockAddrIn; IP, Port: string); + function GetSinIP(Sin: TSockAddrIn): string; + function GetSinPort(Sin: TSockAddrIn): Integer; + public + constructor Create; + constructor CreateAlternate(Stub: string); + destructor Destroy; override; + procedure CloseSocket; virtual; + procedure Bind(IP, Port: string); + procedure Connect(IP, Port: string); + function SendBuffer(Buffer: Pointer; Length: Integer): Integer; virtual; + procedure SendByte(Data: Byte); virtual; + procedure SendString(const Data: string); virtual; + function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; virtual; + function RecvBufferEx(Buffer: Pointer; Length: Integer; + Timeout: Integer): Integer; virtual; + function RecvByte(Timeout: Integer): Byte; virtual; + function RecvString(Timeout: Integer): string; virtual; + function PeekBuffer(Buffer: Pointer; Length: Integer): Integer; virtual; + function PeekByte(Timeout: Integer): Byte; virtual; + function WaitingData: Integer; + procedure SetLinger(Enable: Boolean; Linger: Integer); + procedure GetSins; + function SockCheck(SockResult: Integer): Integer; + procedure ExceptCheck; + function LocalName: string; + procedure ResolveNameToIP(Name: string; IPList: TStrings); + function GetLocalSinIP: string; + function GetRemoteSinIP: string; + function GetLocalSinPort: Integer; + function GetRemoteSinPort: Integer; + function CanRead(Timeout: Integer): Boolean; + function CanWrite(Timeout: Integer): Boolean; + function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; + function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; + function GroupCanRead(const SocketList: TList; Timeout: Integer; + const CanReadList: TList): Boolean; - procedure SetSin (var sin:TSockAddrIn;ip,port:string); - function GetSinIP (sin:TSockAddrIn):string; - function GetSinPort (sin:TSockAddrIn):integer; - function GetSizeRecvBuffer:integer; - procedure SetSizeRecvBuffer(size:integer); - function GetSizeSendBuffer:integer; - procedure SetSizeSendBuffer(size:integer); -public - FWsaData : TWSADATA; + //See 'winsock2.txt' file in distribute package! + function SetTimeout(Timeout: Integer): Boolean; - constructor Create; - constructor CreateAlternate(stub:string); - destructor Destroy; override; + property LocalSin: TSockAddrIn read FLocalSin; + property RemoteSin: TSockAddrIn read FRemoteSin; + published + class function GetErrorDesc(ErrorCode: Integer): string; + property Socket: TSocket read FSocket write FSocket; + property LastError: Integer read FLastError; + property Protocol: Integer read FProtocol; + property LineBuffer: string read FBuffer write FBuffer; + property RaiseExcept: Boolean read FRaiseExcept write FRaiseExcept; + property SizeRecvBuffer: Integer read GetSizeRecvBuffer write SetSizeRecvBuffer; + property SizeSendBuffer: Integer read GetSizeSendBuffer write SetSizeSendBuffer; + property WSAData: TWSADATA read FWsaData; + end; - Procedure CreateSocket; virtual; - Procedure CloseSocket; - procedure Bind(ip,port:string); - procedure Connect(ip,port:string); - function SendBuffer(buffer:pointer;length:integer):integer; virtual; - procedure SendByte(data:byte); virtual; - procedure SendString(data:string); virtual; - function RecvBuffer(buffer:pointer;length:integer):integer; virtual; - function RecvBufferEx(buffer:pointer;length:integer;timeout:integer):integer; virtual; - function RecvByte(timeout:integer):byte; virtual; - function Recvstring(timeout:integer):string; virtual; - function PeekBuffer(buffer:pointer;length:integer):integer; virtual; - function PeekByte(timeout:integer):byte; virtual; - function WaitingData:integer; - procedure SetLinger(enable:boolean;Linger:integer); - procedure GetSins; - function SockCheck(SockResult:integer):integer; - procedure ExceptCheck; - function LocalName:string; - procedure ResolveNameToIP(Name:string;IPlist:TStringlist); - function GetLocalSinIP:string; - function GetRemoteSinIP:string; - function GetLocalSinPort:integer; - function GetRemoteSinPort:integer; - function CanRead(Timeout:integer):boolean; - function CanWrite(Timeout:integer):boolean; - function SendBufferTo(buffer:pointer;length:integer):integer; - function RecvBufferFrom(buffer:pointer;length:integer):integer; + TUDPBlockSocket = class(TBlockSocket) + public + procedure CreateSocket; override; + function EnableBroadcast(Value: Boolean): Boolean; + end; - property LocalSin:TSockAddrIn read FLocalSin; - property RemoteSin:TSockAddrIn read FRemoteSin; -published - property socket:TSocket read FSocket write FSocket; - property LastError:integer read FLastError; - property Protocol:integer read FProtocol; - property LineBuffer:string read FBuffer write FBuffer; - property RaiseExcept:boolean read FRaiseExcept write FRaiseExcept; - property SizeRecvBuffer:integer read GetSizeRecvBuffer write SetSizeRecvBuffer; - property SizeSendBuffer:integer read GetSizeSendBuffer write SetSizeSendBuffer; -end; + TTCPBlockSocket = class(TBlockSocket) + public + procedure CreateSocket; override; + procedure CloseSocket; override; + procedure Listen; + function Accept: TSocket; + end; -{TUDPBlockSocket} -TUDPBlockSocket = class (TBlockSocket) -public - procedure CreateSocket; override; - function EnableBroadcast(Value:Boolean):Boolean; -end; + //See 'winsock2.txt' file in distribute package! + TICMPBlockSocket = class(TBlockSocket) + public + procedure CreateSocket; override; + end; -{TTCPBlockSocket} -TTCPBlockSocket = class (TBlockSocket) -public - procedure CreateSocket; override; - procedure Listen; - function Accept:TSocket; -end; + //See 'winsock2.txt' file in distribute package! + TRAWBlockSocket = class(TBlockSocket) + public + procedure CreateSocket; override; + end; -function GetErrorDesc(ErrorCode:integer): string; + TIPHeader = record + VerLen: Byte; + TOS: Byte; + TotalLen: Word; + Identifer: Word; + FragOffsets: Word; + TTL: Byte; + Protocol: Byte; + CheckSum: Word; + SourceIp: DWORD; + DestIp: DWORD; + Options: DWORD; + end; implementation -{TBlockSocket.Create} constructor TBlockSocket.Create; var - e:ESynapseError; + e: ESynapseError; begin - inherited create; - FRaiseExcept:=false; - FSocket:=INVALID_SOCKET; - FProtocol:=IPPROTO_IP; - Fbuffer:=''; - if not InitSocketInterface('') - then - begin - e:=ESynapseError.Create('Error loading Winsock DLL!'); - e.ErrorCode:=0; - e.ErrorMessage:='Error loading Winsock DLL!'; - raise e; - end; + inherited Create; + FRaiseExcept := False; + FSocket := INVALID_SOCKET; + FProtocol := IPPROTO_IP; + FBuffer := ''; + if not InitSocketInterface('') then + begin + e := ESynapseError.Create('Error loading Winsock DLL!'); + e.ErrorCode := 0; + e.ErrorMessage := 'Error loading Winsock DLL!'; + raise e; + end; SockCheck(synsock.WSAStartup($101, FWsaData)); ExceptCheck; end; -{TBlockSocket.CreateAlternate} -constructor TBlockSocket.CreateAlternate(stub:string); +constructor TBlockSocket.CreateAlternate(Stub: string); var - e:ESynapseError; + e: ESynapseError; begin - inherited create; - FRaiseExcept:=false; - FSocket:=INVALID_SOCKET; - FProtocol:=IPPROTO_IP; - Fbuffer:=''; - if not InitSocketInterface(stub) - then - begin - e:=ESynapseError.Create('Error loading alternate Winsock DLL ('+stub+')!'); - e.ErrorCode:=0; - e.ErrorMessage:='Error loading Winsock DLL ('+stub+')!'; - raise e; - end; + inherited Create; + FRaiseExcept := False; + FSocket := INVALID_SOCKET; + FProtocol := IPPROTO_IP; + FBuffer := ''; + if not InitSocketInterface(Stub) then + begin + e := ESynapseError.Create('Error loading alternate Winsock DLL (' + Stub + ')!'); + e.ErrorCode := 0; + e.ErrorMessage := 'Error loading Winsock DLL (' + Stub + ')!'; + raise e; + end; SockCheck(synsock.WSAStartup($101, FWsaData)); ExceptCheck; end; -{TBlockSocket.Destroy} destructor TBlockSocket.Destroy; begin CloseSocket; DestroySocketInterface; - inherited destroy; + inherited Destroy; end; -{TBlockSocket.SetSin} -procedure TBlockSocket.SetSin (var sin:TSockAddrIn;ip,port:string); +procedure TBlockSocket.SetSin(var Sin: TSockAddrIn; IP, Port: string); var ProtoEnt: PProtoEnt; ServEnt: PServEnt; HostEnt: PHostEnt; begin - FillChar(sin,Sizeof(sin),0); - sin.sin_family := AF_INET; - ProtoEnt:= synsock.getprotobynumber(FProtocol); - ServEnt:=nil; - If ProtoEnt <> nil then - ServEnt:= synsock.getservbyname(PChar(port), ProtoEnt^.p_name); + FillChar(Sin, Sizeof(Sin), 0); + Sin.sin_family := AF_INET; + ProtoEnt := synsock.GetProtoByNumber(FProtocol); + ServEnt := nil; + if ProtoEnt <> nil then + ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name); if ServEnt = nil then - Sin.sin_port:= synsock.htons(StrToIntDef(Port,0)) + Sin.sin_port := synsock.htons(StrToIntDef(Port, 0)) else - Sin.sin_port:= ServEnt^.s_port; - if ip='255.255.255.255' - then Sin.sin_addr.s_addr:=u_long(INADDR_BROADCAST) - else - begin - Sin.sin_addr.s_addr:= synsock.inet_addr(PChar(ip)); - if SIn.sin_addr.s_addr = u_long(INADDR_NONE) then - begin - HostEnt:= synsock.gethostbyname(PChar(ip)); - if HostEnt <> nil then - SIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^); - end; - end; + Sin.sin_port := ServEnt^.s_port; + if IP = '255.255.255.255' then + Sin.sin_addr.s_addr := u_long(INADDR_BROADCAST) + else + begin + Sin.sin_addr.s_addr := synsock.inet_addr(PChar(IP)); + if SIn.sin_addr.s_addr = u_long(INADDR_NONE) then + begin + HostEnt := synsock.GetHostByName(PChar(IP)); + if HostEnt <> nil then + SIn.sin_addr.S_addr := Longint(PLongint(HostEnt^.h_addr_list^)^); + end; + end; end; -{TBlockSocket.GetSinIP} -function TBlockSocket.GetSinIP (sin:TSockAddrIn):string; +function TBlockSocket.GetSinIP(Sin: TSockAddrIn): string; var - p:pchar; + p: PChar; begin - p:=synsock.inet_ntoa(Sin.sin_addr); - if p=nil then result:='' - else result:=p; + p := synsock.inet_ntoa(Sin.sin_addr); + if p = nil then + Result := '' + else + Result := p; end; -{TBlockSocket.GetSinPort} -function TBlockSocket.GetSinPort (sin:TSockAddrIn):integer; +function TBlockSocket.GetSinPort(Sin: TSockAddrIn): Integer; begin - result:=synsock.ntohs(Sin.sin_port); + Result := synsock.ntohs(Sin.sin_port); end; -{TBlockSocket.CreateSocket} -Procedure TBlockSocket.CreateSocket; +procedure TBlockSocket.CreateSocket; begin - Fbuffer:=''; - if FSocket=INVALID_SOCKET then FLastError:=synsock.WSAGetLastError - else FLastError:=0; + FBuffer := ''; + if FSocket = INVALID_SOCKET then + FLastError := synsock.WSAGetLastError + else + FLastError := 0; ExceptCheck; end; - -{TBlockSocket.CloseSocket} -Procedure TBlockSocket.CloseSocket; +procedure TBlockSocket.CloseSocket; begin synsock.CloseSocket(FSocket); end; -{TBlockSocket.Bind} -procedure TBlockSocket.Bind(ip,port:string); +procedure TBlockSocket.Bind(IP, Port: string); var - sin:TSockAddrIn; - len:integer; + Sin: TSockAddrIn; + Len: Integer; begin - SetSin(sin,ip,port); - SockCheck(synsock.bind(FSocket,sin,sizeof(sin))); - len:=sizeof(FLocalSin); - synsock.GetSockName(FSocket,FLocalSin,Len); - Fbuffer:=''; + SetSin(Sin, IP, Port); + SockCheck(synsock.Bind(FSocket, Sin, SizeOf(Sin))); + Len := SizeOf(FLocalSin); + synsock.GetSockName(FSocket, FLocalSin, Len); + FBuffer := ''; ExceptCheck; end; -{TBlockSocket.Connect} -procedure TBlockSocket.Connect(ip,port:string); +procedure TBlockSocket.Connect(IP, Port: string); var - sin:TSockAddrIn; + Sin: TSockAddrIn; begin - SetSin(sin,ip,port); - SockCheck(synsock.connect(FSocket,sin,sizeof(sin))); + SetSin(Sin, IP, Port); + SockCheck(synsock.Connect(FSocket, Sin, SizeOf(Sin))); GetSins; - Fbuffer:=''; + FBuffer := ''; ExceptCheck; end; -{TBlockSocket.GetSins} procedure TBlockSocket.GetSins; var - len:integer; + Len: Integer; begin - len:=sizeof(FLocalSin); - synsock.GetSockName(FSocket,FLocalSin,Len); - len:=sizeof(FRemoteSin); - synsock.GetPeerName(FSocket,FremoteSin,Len); + Len := SizeOf(FLocalSin); + synsock.GetSockName(FSocket, FLocalSin, Len); + Len := SizeOf(FRemoteSin); + synsock.GetPeerName(FSocket, FremoteSin, Len); end; -{TBlockSocket.SendBuffer} -function TBlockSocket.SendBuffer(buffer:pointer;length:integer):integer; +function TBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer; begin - result:=synsock.send(FSocket,buffer^,length,0); - sockcheck(result); + Result := synsock.Send(FSocket, Buffer^, Length, 0); + SockCheck(Result); ExceptCheck; end; -{TBlockSocket.SendByte} -procedure TBlockSocket.SendByte(data:byte); +procedure TBlockSocket.SendByte(Data: Byte); begin - sockcheck(synsock.send(FSocket,data,1,0)); + sockcheck(synsock.Send(FSocket, Data, 1, 0)); ExceptCheck; end; -{TBlockSocket.SendString} -procedure TBlockSocket.SendString(data:string); +procedure TBlockSocket.SendString(const Data: string); begin - sockcheck(synsock.send(FSocket,pchar(data)^,length(data),0)); + SockCheck(synsock.Send(FSocket, PChar(Data)^, Length(Data), 0)); ExceptCheck; end; -{TBlockSocket.RecvBuffer} -function TBlockSocket.RecvBuffer(buffer:pointer;length:integer):integer; +function TBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer; begin - result:=synsock.recv(FSocket,buffer^,length,0); - if result=0 - then FLastError:=WSAENOTCONN - else sockcheck(result); + Result := synsock.Recv(FSocket, Buffer^, Length, 0); + if Result = 0 then + FLastError := WSAENOTCONN + else + SockCheck(Result); ExceptCheck; end; -{TBlockSocket.RecvBufferEx} -function TBlockSocket.RecvBufferEx(buffer:pointer;length:integer;timeout:integer):integer; +function TBlockSocket.RecvBufferEx(Buffer: Pointer; Length: Integer; + Timeout: Integer): Integer; var - s,ss,st:string; - x,l,lss:integer; - fb,fs:integer; - max:integer; + s, ss, st: string; + x, l, lss: Integer; + fb, fs: Integer; + max: Integer; begin - FLastError:=0; - x:=system.length(FBuffer); - if length<=x - then - begin - fb:=length; - fs:=0; - end - else - begin - fb:=x; - fs:=length-x; - end; - ss:=''; - if fb>0 then + FLastError := 0; + x := System.Length(FBuffer); + if Length <= x then + begin + fb := Length; + fs := 0; + end + else + begin + fb := x; + fs := Length - x; + end; + ss := ''; + if fb > 0 then + begin + s := Copy(FBuffer, 1, fb); + Delete(FBuffer, 1, fb); + end; + if fs > 0 then + begin + Max := GetSizeRecvBuffer; + ss := ''; + while System.Length(ss) < fs do begin - s:=copy(FBuffer,1,fb); - delete(Fbuffer,1,fb); - end; - if fs>0 then - begin - Max:=GetSizeRecvBuffer; - ss:=''; - while system.length(ss)max - then l:=max; - if (system.length(ss)+l)>fs - then l:=fs-system.length(ss); - setlength(st,l); - x:=synsock.recv(FSocket,pointer(st)^,l,0); - if x=0 - then FLastError:=WSAENOTCONN - else sockcheck(x); - if Flasterror<>0 - then break; - lss:=system.length(ss); - setlength(ss,lss+x); - Move(pointer(st)^,Pointer(@ss[lss+1])^, x); - {It is 3x faster then ss:=ss+copy(st,1,x);} - sleep(0); - end - else FLastError:=WSAETIMEDOUT; - if Flasterror<>0 - then break; - end; - fs:=system.length(ss); - end; - result:=fb+fs; - s:=s+ss; - move(pointer(s)^,buffer^,result); - ExceptCheck; -end; - -{TBlockSocket.RecvByte} -function TBlockSocket.RecvByte(timeout:integer):byte; -var - y:integer; - data:byte; -begin - data:=0; - result:=0; - if CanRead(timeout) then - begin - y:=synsock.recv(FSocket,data,1,0); - if y=0 then FLastError:=WSAENOTCONN - else sockcheck(y); - result:=data; - end - else FLastError:=WSAETIMEDOUT; - ExceptCheck; -end; - -{TBlockSocket.Recvstring} -function TBlockSocket.Recvstring(timeout:integer):string; -const - maxbuf=1024; -var - x:integer; - s:string; - c:char; - r:integer; -begin - s:=''; - FLastError:=0; - c:=#0; - repeat - if FBuffer='' then + if CanRead(Timeout) then begin - x:=waitingdata; - if x=0 then x:=1; - if x>maxbuf then x:=maxbuf; - if x=1 then - begin - c:=char(RecvByte(timeout)); - if FLastError<>0 then break; - Fbuffer:=c; - end + l := WaitingData; + if l > max then + l := max; + if (system.Length(ss) + l) > fs then + l := fs - system.Length(ss); + SetLength(st, l); + x := synsock.Recv(FSocket, Pointer(st)^, l, 0); + if x = 0 then + FLastError := WSAENOTCONN else - begin - setlength(Fbuffer,x); - r:=synsock.recv(FSocket,pointer(FBuffer)^,x,0); - SockCheck(r); - if r=0 then FLastError:=WSAENOTCONN; - if FLastError<>0 then break; - if r 0 then + Break; + lss := system.Length(ss); + SetLength(ss, lss + x); + Move(Pointer(st)^, Pointer(@ss[lss + 1])^, x); + {It is 3x faster then ss:=ss+copy(st,1,x);} + Sleep(0); + end + else + FLastError := WSAETIMEDOUT; + if FLastError <> 0 then + Break; + end; + fs := system.Length(ss); + end; + Result := fb + fs; + s := s + ss; + Move(Pointer(s)^, Buffer^, Result); + ExceptCheck; +end; + +function TBlockSocket.RecvByte(Timeout: Integer): Byte; +var + y: Integer; + Data: Byte; +begin + Data := 0; + Result := 0; + if CanRead(Timeout) then + begin + y := synsock.Recv(FSocket, Data, 1, 0); + if y = 0 then + FLastError := WSAENOTCONN + else + SockCheck(y); + Result := Data; + end + else + FLastError := WSAETIMEDOUT; + ExceptCheck; +end; + +function TBlockSocket.RecvString(Timeout: Integer): string; +const + MaxBuf = 1024; +var + x: Integer; + s: string; + c: Char; + r: Integer; +begin + s := ''; + FLastError := 0; + c := #0; + repeat + if FBuffer = '' then + begin + x := WaitingData; + if x = 0 then + x := 1; + if x > MaxBuf then + x := MaxBuf; + if x = 1 then + begin + c := Char(RecvByte(Timeout)); + if FLastError <> 0 then + Break; + FBuffer := c; + end + else + begin + SetLength(FBuffer, x); + r := synsock.Recv(FSocket, Pointer(FBuffer)^, x, 0); + SockCheck(r); + if r = 0 then + FLastError := WSAENOTCONN; + if FLastError <> 0 then + Break; + if r < x then + SetLength(FBuffer, r); end; - x:=pos(#10,Fbuffer); - if x<1 then x:=length(Fbuffer); - s:=s+copy(Fbuffer,1,x-1); - c:=Fbuffer[x]; - delete(Fbuffer,1,x); - s:=s+c; + end; + x := Pos(#10, FBuffer); + if x < 1 then x := Length(FBuffer); + s := s + Copy(FBuffer, 1, x - 1); + c := FBuffer[x]; + Delete(FBuffer, 1, x); + s := s + c; until c = #10; - if FLastError=0 then - begin + if FLastError = 0 then + begin {$IFDEF LINUX} - s:=AdjustLineBreaks(s,tlbsCRLF); + s := AdjustLineBreaks(s, tlbsCRLF); {$ELSE} - s:=AdjustLineBreaks(s); + s := AdjustLineBreaks(s); {$ENDIF} - x:=pos(#13+#10,s); - if x>0 then s:=copy(s,1,x-1); - result:=s; - end - else result:=''; + x := Pos(#13 + #10, s); + if x > 0 then + s := Copy(s, 1, x - 1); + Result := s; + end + else + Result := ''; ExceptCheck; end; -{TBlockSocket.PeekBuffer} -function TBlockSocket.PeekBuffer(buffer:pointer;length:integer):integer; +function TBlockSocket.PeekBuffer(Buffer: Pointer; Length: Integer): Integer; begin - result:=synsock.recv(FSocket,buffer^,length,MSG_PEEK); - sockcheck(result); + Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK); + SockCheck(Result); ExceptCheck; end; -{TBlockSocket.PeekByte} -function TBlockSocket.PeekByte(timeout:integer):byte; +function TBlockSocket.PeekByte(Timeout: Integer): Byte; var - y:integer; - data:byte; + y: Integer; + Data: Byte; begin - data:=0; - result:=0; - if CanRead(timeout) then - begin - y:=synsock.recv(FSocket,data,1,MSG_PEEK); - if y=0 then FLastError:=WSAENOTCONN; - sockcheck(y); - result:=data; - end - else FLastError:=WSAETIMEDOUT; + Data := 0; + Result := 0; + if CanRead(Timeout) then + begin + y := synsock.Recv(FSocket, Data, 1, MSG_PEEK); + if y = 0 then + FLastError := WSAENOTCONN; + SockCheck(y); + Result := Data; + end + else + FLastError := WSAETIMEDOUT; ExceptCheck; end; -{TBlockSocket.SockCheck} -function TBlockSocket.SockCheck(SockResult:integer):integer; +function TBlockSocket.SockCheck(SockResult: Integer): Integer; begin - if SockResult=SOCKET_ERROR then result:=synsock.WSAGetLastError - else result:=0; - FLastError:=result; + if SockResult = SOCKET_ERROR then + Result := synsock.WSAGetLastError + else + Result := 0; + FLastError := Result; end; -{TBlockSocket.ExceptCheck} procedure TBlockSocket.ExceptCheck; var - e:ESynapseError; - s:string; + e: ESynapseError; + s: string; begin - if FRaiseExcept and (LastError<>0) then - begin - s:=GetErrorDesc(LastError); - e:=ESynapseError.CreateFmt('TCP/IP socket error %d: %s',[LastError,s]); - e.ErrorCode:=LastError; - e.ErrorMessage:=s; - raise e; - end; + if FRaiseExcept and (LastError <> 0) then + begin + s := GetErrorDesc(LastError); + e := ESynapseError.CreateFmt('TCP/IP Socket error %d: %s', [LastError, s]); + e.ErrorCode := LastError; + e.ErrorMessage := s; + raise e; + end; end; -{TBlockSocket.WaitingData} -function TBlockSocket.WaitingData:integer; +function TBlockSocket.WaitingData: Integer; var - x:integer; + x: Integer; begin - synsock.ioctlsocket(FSocket,FIONREAD,u_long(x)); - result:=x; + synsock.IoctlSocket(FSocket, FIONREAD, u_long(x)); + Result := x; end; -{TBlockSocket.SetLinger} -procedure TBlockSocket.SetLinger(enable:boolean;Linger:integer); +procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer); var - li:TLinger; + li: TLinger; begin - li.l_onoff := ord(enable); + li.l_onoff := Ord(Enable); li.l_linger := Linger div 1000; SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_LINGER, @li, SizeOf(li))); ExceptCheck; end; -{TBlockSocket.LocalName} -function TBlockSocket.LocalName:string; +function TBlockSocket.LocalName: string; var - buf:array[0..255] of char; - Pbuf:pchar; - RemoteHost:PHostEnt; + buf: array[0..255] of Char; + BufPtr: PChar; + RemoteHost: PHostEnt; begin - pbuf:=buf; - result:=''; - synsock.gethostname(pbuf,255); - if pbuf<>'' then - begin - //try get Fully Qualified Domain Name - RemoteHost:=synsock.GetHostByName(pbuf); - if remoteHost<>nil then - result:=pchar(RemoteHost^.h_name); - end; - if result='' then result:='127.0.0.1'; + BufPtr := buf; + Result := ''; + synsock.GetHostName(BufPtr, SizeOf(buf)); + if BufPtr[0] <> #0 then + begin + // try get Fully Qualified Domain Name + RemoteHost := synsock.GetHostByName(BufPtr); + if RemoteHost <> nil then + Result := PChar(RemoteHost^.h_name); + end; + if Result = '' then + Result := '127.0.0.1'; end; -{TBlockSocket.ResolveNameToIP} -procedure TBlockSocket.ResolveNameToIP(Name:string;IPlist:TStringlist); +procedure TBlockSocket.ResolveNameToIP(Name: string; IPList: TStrings); type - TaPInAddr = Array[0..250] of PInAddr; + TaPInAddr = array[0..250] of PInAddr; PaPInAddr = ^TaPInAddr; var - RemoteHost:PHostEnt; - IP:u_long; - PAdrPtr:PaPInAddr; - i:integer; - s:string; - InAddr:TInAddr; + RemoteHost: PHostEnt; + IP: u_long; + PAdrPtr: PaPInAddr; + i: Integer; + s: string; + InAddr: TInAddr; begin IPList.Clear; - IP := synsock.inet_addr(PChar(name)); - if IP = u_long(INADDR_NONE) - then + IP := synsock.inet_addr(PChar(Name)); + if IP = u_long(INADDR_NONE) then + begin + RemoteHost := synsock.GetHostByName(PChar(Name)); + if RemoteHost <> nil then + begin + PAdrPtr := PAPInAddr(RemoteHost^.h_addr_list); + i := 0; + while PAdrPtr^[i] <> nil do begin - RemoteHost:=synsock.gethostbyname(PChar(name)); - if RemoteHost <> nil then - begin - PAdrPtr:=PAPInAddr(remoteHost^.h_addr_list); - i:=0; - while PAdrPtr^[i]<>nil do - begin - InAddr:=PAdrPtr^[i]^; - with InAddr.S_un_b do - s:=IntToStr(Ord(s_b1))+'.'+IntToStr(Ord(s_b2))+'.' - +IntToStr(Ord(s_b3))+'.'+IntToStr(Ord(s_b4)); - IPList.Add(s); - Inc(i); - end; - end; - end - else IPList.Add(name); + InAddr := PAdrPtr^[i]^; + with InAddr.S_un_b do + s := Format('%d.%d.%d.%d', + [Ord(s_b1), Ord(s_b2), Ord(s_b3), Ord(s_b4)]); + IPList.Add(s); + Inc(i); + end; + end; + end + else + IPList.Add(Name); end; -{TBlockSocket.GetLocalSinIP} -function TBlockSocket.GetLocalSinIP:string; +function TBlockSocket.GetLocalSinIP: string; begin - result:=GetSinIP(FLocalSin); + Result := GetSinIP(FLocalSin); end; -{TBlockSocket.GetRemoteSinIP} -function TBlockSocket.GetRemoteSinIP:string; +function TBlockSocket.GetRemoteSinIP: string; begin - result:=GetSinIP(FRemoteSin); + Result := GetSinIP(FRemoteSin); end; -{TBlockSocket.GetLocalSinPort} -function TBlockSocket.GetLocalSinPort:integer; +function TBlockSocket.GetLocalSinPort: Integer; begin - result:=GetSinPort(FLocalSin); + Result := GetSinPort(FLocalSin); end; -{TBlockSocket.GetRemoteSinPort} -function TBlockSocket.GetRemoteSinPort:integer; +function TBlockSocket.GetRemoteSinPort: Integer; begin - result:=GetSinPort(FRemoteSin); + Result := GetSinPort(FRemoteSin); end; -{TBlockSocket.CanRead} -function TBlockSocket.CanRead(Timeout:integer):boolean; +function TBlockSocket.CanRead(Timeout: Integer): Boolean; var - FDSet:TFDSet; - TimeVal:PTimeVal; - TimeV:tTimeval; - x:integer; + FDSet: TFDSet; + TimeVal: PTimeVal; + TimeV: TTimeVal; + x: Integer; begin - Timev.tv_usec:=(Timeout mod 1000)*1000; - Timev.tv_sec:=Timeout div 1000; - TimeVal:=@TimeV; - if timeout = -1 then Timeval:=nil; - FD_Zero(FDSet); - FD_Set(FSocket,FDSet); - x:=synsock.Select(FSocket+1,@FDSet,nil,nil,TimeVal); + TimeV.tv_usec := (Timeout mod 1000) * 1000; + TimeV.tv_sec := Timeout div 1000; + TimeVal := @TimeV; + if Timeout = -1 then + TimeVal := nil; + FD_ZERO(FDSet); + FD_SET(FSocket, FDSet); + x := synsock.Select(FSocket + 1, @FDSet, nil, nil, TimeVal); SockCheck(x); - If FLastError<>0 then x:=0; - result:=x>0; + if FLastError <> 0 then + x := 0; + Result := x > 0; ExceptCheck; end; -{TBlockSocket.CanWrite} -function TBlockSocket.CanWrite(Timeout:integer):boolean; +function TBlockSocket.CanWrite(Timeout: Integer): Boolean; var - FDSet:TFDSet; - TimeVal:PTimeVal; - TimeV:tTimeval; - x:integer; + FDSet: TFDSet; + TimeVal: PTimeVal; + TimeV: TTimeVal; + x: Integer; begin - Timev.tv_usec:=(Timeout mod 1000)*1000; - Timev.tv_sec:=Timeout div 1000; - TimeVal:=@TimeV; - if timeout = -1 then Timeval:=nil; - FD_Zero(FDSet); - FD_Set(FSocket,FDSet); - x:=synsock.Select(FSocket+1,nil,@FDSet,nil,TimeVal); + TimeV.tv_usec := (Timeout mod 1000) * 1000; + TimeV.tv_sec := Timeout div 1000; + TimeVal := @TimeV; + if Timeout = -1 then + TimeVal := nil; + FD_ZERO(FDSet); + FD_SET(FSocket, FDSet); + x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal); SockCheck(x); - If FLastError<>0 then x:=0; - result:=x>0; + if FLastError <> 0 then + x := 0; + Result := x > 0; ExceptCheck; end; -{TBlockSocket.SendBufferTo} -function TBlockSocket.SendBufferTo(buffer:pointer;length:integer):integer; +function TBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer; var - len:integer; + Len: Integer; begin - len:=sizeof(FRemoteSin); - result:=synsock.sendto(FSocket,buffer^,length,0,FRemoteSin,len); - sockcheck(result); + Len := SizeOf(FRemoteSin); + Result := synsock.SendTo(FSocket, Buffer^, Length, 0, FRemoteSin, Len); + SockCheck(Result); ExceptCheck; end; -{TBlockSocket.RecvBufferFrom} -function TBlockSocket.RecvBufferFrom(buffer:pointer;length:integer):integer; +function TBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; var - len:integer; + Len: Integer; begin - len:=sizeof(FRemoteSin); - result:=synsock.recvfrom(FSocket,buffer^,length,0,FRemoteSin,len); - sockcheck(result); + Len := SizeOf(FRemoteSin); + Result := synsock.RecvFrom(FSocket, Buffer^, Length, 0, FRemoteSin, Len); + SockCheck(Result); ExceptCheck; end; -{TBlockSocket.GetSizeRecvBuffer} -function TBlockSocket.GetSizeRecvBuffer:integer; +function TBlockSocket.GetSizeRecvBuffer: Integer; var - l:integer; + l: Integer; begin - l:=SizeOf(result); - SockCheck(synsock.getSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @result, l)); - if Flasterror<>0 - then result:=1024; + l := SizeOf(Result); + SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l)); + if FLastError <> 0 then + Result := 1024; ExceptCheck; end; -{TBlockSocket.SetSizeRecvBuffer} -procedure TBlockSocket.SetSizeRecvBuffer(size:integer); +procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer); begin - SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @size, SizeOf(size))); + SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Size, SizeOf(Size))); ExceptCheck; end; -{TBlockSocket.GetSizeSendBuffer} -function TBlockSocket.GetSizeSendBuffer:integer; +function TBlockSocket.GetSizeSendBuffer: Integer; var - l:integer; + l: Integer; begin - l:=SizeOf(result); - SockCheck(synsock.getSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @result, l)); - if Flasterror<>0 - then result:=1024; + l := SizeOf(Result); + SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l)); + if FLastError <> 0 then + Result := 1024; ExceptCheck; end; -{TBlockSocket.SetSizeSendBuffer} -procedure TBlockSocket.SetSizeSendBuffer(size:integer); +procedure TBlockSocket.SetSizeSendBuffer(Size: Integer); begin - SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @size, SizeOf(size))); + SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Size, SizeOf(Size))); ExceptCheck; end; +//See 'winsock2.txt' file in distribute package! + +function TBlockSocket.SetTimeout(Timeout: Integer): Boolean; +begin + Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, + SO_RCVTIMEO, @Timeout, SizeOf(Timeout)) <> SOCKET_ERROR; + Result := Result and (synsock.SetSockOpt(FSocket, SOL_SOCKET, + SO_SNDTIMEO, @Timeout, SizeOf(Timeout)) <> SOCKET_ERROR); +end; + +function TBlockSocket.GroupCanRead(const SocketList: TList; Timeout: Integer; + const CanReadList: TList): boolean; +var + FDSet: TFDSet; + TimeVal: PTimeVal; + TimeV: TTimeVal; + x, n: Integer; + Max: Integer; +begin + TimeV.tv_usec := (Timeout mod 1000) * 1000; + TimeV.tv_sec := Timeout div 1000; + TimeVal := @TimeV; + if Timeout = -1 then + TimeVal := nil; + FD_ZERO(FDSet); + Max := 0; + for n := 0 to SocketList.Count - 1 do + if TObject(SocketList.Items[n]) is TBlockSocket then + begin + if TBlockSocket(SocketList.Items[n]).Socket > Max then + Max := TBlockSocket(SocketList.Items[n]).Socket; + FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet); + end; + x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal); + SockCheck(x); + ExceptCheck; + if FLastError <> 0 then + x := 0; + Result := x > 0; + CanReadList.Clear; + if Result then + for n := 0 to SocketList.Count - 1 do + if TObject(SocketList.Items[n]) is TBlockSocket then + if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then + CanReadList.Add(TBlockSocket(SocketList.Items[n])); +end; + +class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string; +begin + case ErrorCode of + 0: + Result := 'OK'; + WSAEINTR: {10004} + Result := 'Interrupted system call'; + WSAEBADF: {10009} + Result := 'Bad file number'; + WSAEACCES: {10013} + Result := 'Permission denied'; + WSAEFAULT: {10014} + Result := 'Bad address'; + WSAEINVAL: {10022} + Result := 'Invalid argument'; + WSAEMFILE: {10024} + Result := 'Too many open files'; + WSAEWOULDBLOCK: {10035} + Result := 'Operation would block'; + WSAEINPROGRESS: {10036} + Result := 'Operation now in progress'; + WSAEALREADY: {10037} + Result := 'Operation already in progress'; + WSAENOTSOCK: {10038} + Result := 'Socket operation on nonsocket'; + WSAEDESTADDRREQ: {10039} + Result := 'Destination address required'; + WSAEMSGSIZE: {10040} + Result := 'Message too long'; + WSAEPROTOTYPE: {10041} + Result := 'Protocol wrong type for Socket'; + WSAENOPROTOOPT: {10042} + Result := 'Protocol not available'; + WSAEPROTONOSUPPORT: {10043} + Result := 'Protocol not supported'; + WSAESOCKTNOSUPPORT: {10044} + Result := 'Socket not supported'; + WSAEOPNOTSUPP: {10045} + Result := 'Operation not supported on Socket'; + WSAEPFNOSUPPORT: {10046} + Result := 'Protocol family not supported'; + WSAEAFNOSUPPORT: {10047} + Result := 'Address family not supported'; + WSAEADDRINUSE: {10048} + Result := 'Address already in use'; + WSAEADDRNOTAVAIL: {10049} + Result := 'Can''t assign requested address'; + WSAENETDOWN: {10050} + Result := 'Network is down'; + WSAENETUNREACH: {10051} + Result := 'Network is unreachable'; + WSAENETRESET: {10052} + Result := 'Network dropped connection on reset'; + WSAECONNABORTED: {10053} + Result := 'Software caused connection abort'; + WSAECONNRESET: {10054} + Result := 'Connection reset by peer'; + WSAENOBUFS: {10055} + Result := 'No Buffer space available'; + WSAEISCONN: {10056} + Result := 'Socket is already connected'; + WSAENOTCONN: {10057} + Result := 'Socket is not connected'; + WSAESHUTDOWN: {10058} + Result := 'Can''t send after Socket shutdown'; + WSAETOOMANYREFS: {10059} + Result := 'Too many references:can''t splice'; + WSAETIMEDOUT: {10060} + Result := 'Connection timed out'; + WSAECONNREFUSED: {10061} + Result := 'Connection refused'; + WSAELOOP: {10062} + Result := 'Too many levels of symbolic links'; + WSAENAMETOOLONG: {10063} + Result := 'File name is too long'; + WSAEHOSTDOWN: {10064} + Result := 'Host is down'; + WSAEHOSTUNREACH: {10065} + Result := 'No route to host'; + WSAENOTEMPTY: {10066} + Result := 'Directory is not empty'; + WSAEPROCLIM: {10067} + Result := 'Too many processes'; + WSAEUSERS: {10068} + Result := 'Too many users'; + WSAEDQUOT: {10069} + Result := 'Disk quota exceeded'; + WSAESTALE: {10070} + Result := 'Stale NFS file handle'; + WSAEREMOTE: {10071} + Result := 'Too many levels of remote in path'; + WSASYSNOTREADY: {10091} + Result := 'Network subsystem is unusable'; + WSAVERNOTSUPPORTED: {10092} + Result := 'Winsock DLL cannot support this application'; + WSANOTINITIALISED: {10093} + Result := 'Winsock not initialized'; + WSAEDISCON: {10101} + Result := 'WSAEDISCON-10101'; + WSAHOST_NOT_FOUND: {11001} + Result := 'Host not found'; + WSATRY_AGAIN: {11002} + Result := 'Non authoritative - host not found'; + WSANO_RECOVERY: {11003} + Result := 'Non recoverable error'; + WSANO_DATA: {11004} + Result := 'Valid name, no data record of requested type' + else + Result := 'Not a Winsock error (' + IntToStr(ErrorCode) + ')'; + end; +end; {======================================================================} -{TUDPBlockSocket.CreateSocket} -Procedure TUDPBlockSocket.CreateSocket; +procedure TUDPBlockSocket.CreateSocket; begin - FSocket:=synsock.socket(PF_INET,integer(SOCK_DGRAM),IPPROTO_UDP); - FProtocol:=IPPROTO_UDP; - inherited createSocket; + FSocket := synsock.Socket(PF_INET, Integer(SOCK_DGRAM), IPPROTO_UDP); + FProtocol := IPPROTO_UDP; + inherited CreateSocket; end; -{TUDPBlockSocket.EnableBroadcast} -function TUDPBlockSocket.EnableBroadcast(Value:Boolean):Boolean; +function TUDPBlockSocket.EnableBroadcast(Value: Boolean): Boolean; var - Opt:integer; - Res:integer; + Opt: Integer; + Res: Integer; begin - opt:=Ord(Value); - Res:=synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, @opt, SizeOf(opt)); + opt := Ord(Value); + Res := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, @Opt, SizeOf(opt)); SockCheck(Res); - Result:=res=0; + Result := res = 0; ExceptCheck; end; - {======================================================================} -{TTCPBlockSocket.CreateSocket} -Procedure TTCPBlockSocket.CreateSocket; +procedure TTCPBlockSocket.CreateSocket; begin - FSocket:=synsock.socket(PF_INET,integer(SOCK_STREAM),IPPROTO_TCP); - FProtocol:=IPPROTO_TCP; - inherited createSocket; + FSocket := synsock.Socket(PF_INET, Integer(SOCK_STREAM), IPPROTO_TCP); + FProtocol := IPPROTO_TCP; + inherited CreateSocket; +end; + +procedure TTCPBlockSocket.CloseSocket; +begin + synsock.Shutdown(FSocket, 1); + inherited CloseSocket; end; -{TTCPBlockSocket.Listen} procedure TTCPBlockSocket.Listen; begin - SockCheck(synsock.listen(FSocket,SOMAXCONN)); + SockCheck(synsock.Listen(FSocket, SOMAXCONN)); GetSins; ExceptCheck; end; -{TTCPBlockSocket.Accept} -function TTCPBlockSocket.Accept:TSocket; +function TTCPBlockSocket.Accept: TSocket; var - len:integer; + Len: Integer; begin - len:=sizeof(FRemoteSin); - result:=synsock.accept(FSocket,@FRemoteSin,@len); - SockCheck(result); + Len := SizeOf(FRemoteSin); + Result := synsock.Accept(FSocket, @FRemoteSin, @Len); + SockCheck(Result); ExceptCheck; end; +{======================================================================} + +//See 'winsock2.txt' file in distribute package! + +procedure TICMPBlockSocket.CreateSocket; +begin + FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_ICMP); + FProtocol := IPPROTO_ICMP; + inherited CreateSocket; +end; {======================================================================} -{GetErrorDesc} -function GetErrorDesc(ErrorCode:integer): string; +//See 'winsock2.txt' file in distribute package! + +procedure TRAWBlockSocket.CreateSocket; begin - case ErrorCode of - 0 : Result:= 'OK'; - WSAEINTR :{10004} Result:= 'Interrupted system call'; - WSAEBADF :{10009} Result:= 'Bad file number'; - WSAEACCES :{10013} Result:= 'Permission denied'; - WSAEFAULT :{10014} Result:= 'Bad address'; - WSAEINVAL :{10022} Result:= 'Invalid argument'; - WSAEMFILE :{10024} Result:= 'Too many open files'; - WSAEWOULDBLOCK :{10035} Result:= 'Operation would block'; - WSAEINPROGRESS :{10036} Result:= 'Operation now in progress'; - WSAEALREADY :{10037} Result:= 'Operation already in progress'; - WSAENOTSOCK :{10038} Result:= 'Socket operation on nonsocket'; - WSAEDESTADDRREQ :{10039} Result:= 'Destination address required'; - WSAEMSGSIZE :{10040} Result:= 'Message too long'; - WSAEPROTOTYPE :{10041} Result:= 'Protocol wrong type for socket'; - WSAENOPROTOOPT :{10042} Result:= 'Protocol not available'; - WSAEPROTONOSUPPORT :{10043} Result:= 'Protocol not supported'; - WSAESOCKTNOSUPPORT :{10044} Result:= 'Socket not supported'; - WSAEOPNOTSUPP :{10045} Result:= 'Operation not supported on socket'; - WSAEPFNOSUPPORT :{10046} Result:= 'Protocol family not supported'; - WSAEAFNOSUPPORT :{10047} Result:= 'Address family not supported'; - WSAEADDRINUSE :{10048} Result:= 'Address already in use'; - WSAEADDRNOTAVAIL :{10049} Result:= 'Can''t assign requested address'; - WSAENETDOWN :{10050} Result:= 'Network is down'; - WSAENETUNREACH :{10051} Result:= 'Network is unreachable'; - WSAENETRESET :{10052} Result:= 'Network dropped connection on reset'; - WSAECONNABORTED :{10053} Result:= 'Software caused connection abort'; - WSAECONNRESET :{10054} Result:= 'Connection reset by peer'; - WSAENOBUFS :{10055} Result:= 'No buffer space available'; - WSAEISCONN :{10056} Result:= 'Socket is already connected'; - WSAENOTCONN :{10057} Result:= 'Socket is not connected'; - WSAESHUTDOWN :{10058} Result:= 'Can''t send after socket shutdown'; - WSAETOOMANYREFS :{10059} Result:= 'Too many references:can''t splice'; - WSAETIMEDOUT :{10060} Result:= 'Connection timed out'; - WSAECONNREFUSED :{10061} Result:= 'Connection refused'; - WSAELOOP :{10062} Result:= 'Too many levels of symbolic links'; - WSAENAMETOOLONG :{10063} Result:= 'File name is too long'; - WSAEHOSTDOWN :{10064} Result:= 'Host is down'; - WSAEHOSTUNREACH :{10065} Result:= 'No route to host'; - WSAENOTEMPTY :{10066} Result:= 'Directory is not empty'; - WSAEPROCLIM :{10067} Result:= 'Too many processes'; - WSAEUSERS :{10068} Result:= 'Too many users'; - WSAEDQUOT :{10069} Result:= 'Disk quota exceeded'; - WSAESTALE :{10070} Result:= 'Stale NFS file handle'; - WSAEREMOTE :{10071} Result:= 'Too many levels of remote in path'; - WSASYSNOTREADY :{10091} Result:= 'Network subsystem is unusable'; - WSAVERNOTSUPPORTED :{10092} Result:= 'Winsock DLL cannot support this application'; - WSANOTINITIALISED :{10093} Result:= 'Winsock not initialized'; - WSAEDISCON :{10101} Result:= 'WSAEDISCON-10101'; - WSAHOST_NOT_FOUND :{11001} Result:= 'Host not found'; - WSATRY_AGAIN :{11002} Result:= 'Non authoritative - host not found'; - WSANO_RECOVERY :{11003} Result:= 'Non recoverable error'; - WSANO_DATA :{11004} Result:= 'Valid name, no data record of requested type' - else - Result:= 'Not a Winsock error ('+IntToStr(ErrorCode)+')'; - end; + FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_RAW); + FProtocol := IPPROTO_RAW; + inherited CreateSocket; end; -begin - exit; - asm - db 'Synapse TCP/IP library by Lukas Gebauer',0 - end; end. diff --git a/dnssend.pas b/dnssend.pas index 72faae4..e9f19ec 100644 --- a/dnssend.pas +++ b/dnssend.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.001.001 | +| Project : Delphree - Synapse | 001.001.002 | |==============================================================================| | Content: DNS client | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -14,7 +14,7 @@ | The Original Code is Synapse Delphi Library. | |==============================================================================| | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| -| Portions created by Lukas Gebauer are Copyright (c)2000. | +| Portions created by Lukas Gebauer are Copyright (c)2000,2001. | | All Rights Reserved. | |==============================================================================| | Contributor(s): | @@ -23,351 +23,342 @@ | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} -//RFC-1035, RFC-1183, RFC1706, RFC1712, RFC2163, RFC2230 +// RFC-1035, RFC-1183, RFC1706, RFC1712, RFC2163, RFC2230 {$Q-} +{$WEAKPACKAGEUNIT ON} unit DNSsend; interface + uses - Blcksock, sysutils, classes, SynaUtil; + SysUtils, Classes, + blcksock, SynaUtil; const - Qtype_A =1; - Qtype_NS =2; - Qtype_MD =3; - Qtype_MF =4; - Qtype_CNAME =5; - Qtype_SOA =6; - Qtype_MB =7; - Qtype_MG =8; - Qtype_MR =9; - Qtype_NULL =10; - Qtype_WKS =11; // - Qtype_PTR =12; - Qtype_HINFO =13; - Qtype_MINFO =14; - Qtype_MX =15; - Qtype_TXT =16; + cDnsProtocol = 'Domain'; - Qtype_RP =17; - Qtype_AFSDB =18; - Qtype_X25 =19; - Qtype_ISDN =20; - Qtype_RT =21; - Qtype_NSAP =22; - Qtype_NSAPPTR=23; - Qtype_SIG =24; //RFC-2065 - Qtype_KEY =25; //RFC-2065 - Qtype_PX =26; - Qtype_GPOS =27; - Qtype_AAAA =28; //IP6 Address [Susan Thomson] - Qtype_LOC =29; //RFC-1876 - Qtype_NXT =30; //RFC-2065 + QTYPE_A = 1; + QTYPE_NS = 2; + QTYPE_MD = 3; + QTYPE_MF = 4; + QTYPE_CNAME = 5; + QTYPE_SOA = 6; + QTYPE_MB = 7; + QTYPE_MG = 8; + QTYPE_MR = 9; + QTYPE_NULL = 10; + QTYPE_WKS = 11; // + QTYPE_PTR = 12; + QTYPE_HINFO = 13; + QTYPE_MINFO = 14; + QTYPE_MX = 15; + QTYPE_TXT = 16; - Qtype_SRV =33; //RFC-2052 - Qtype_NAPTR =35; //RFC-2168 - Qtype_KX =36; + QTYPE_RP = 17; + QTYPE_AFSDB = 18; + QTYPE_X25 = 19; + QTYPE_ISDN = 20; + QTYPE_RT = 21; + QTYPE_NSAP = 22; + QTYPE_NSAPPTR = 23; + QTYPE_SIG = 24; // RFC-2065 + QTYPE_KEY = 25; // RFC-2065 + QTYPE_PX = 26; + QTYPE_GPOS = 27; + QTYPE_AAAA = 28; // IP6 Address [Susan Thomson] + QTYPE_LOC = 29; // RFC-1876 + QTYPE_NXT = 30; // RFC-2065 - Qtype_AXFR =252; // - Qtype_MAILB =253; // - Qtype_MAILA =254; // - Qtype_ALL =255; // + QTYPE_SRV = 33; // RFC-2052 + QTYPE_NAPTR = 35; // RFC-2168 + QTYPE_KX = 36; + + QTYPE_AXFR = 252; // + QTYPE_MAILB = 253; // + QTYPE_MAILA = 254; // + QTYPE_ALL = 255; // type - TDNSSend = class + TDNSSend = class(TObject) private - Buffer:string; - Sock:TUDPBlockSocket; - function CompressName(Value:string):string; - function CodeHeader:string; - function CodeQuery(Name:string; Qtype:integer):string; - function DecodeLabels(var From:integer):string; - function DecodeResource(var i:integer; Name:string; Qtype:integer):string; + FTimeout: Integer; + FDNSHost: string; + FRCode: Integer; + FBuffer: string; + FSock: TUDPBlockSocket; + function CompressName(const Value: string): string; + function CodeHeader: string; + function CodeQuery(const Name: string; QType: Integer): string; + function DecodeLabels(var From: Integer): string; + function DecodeResource(var i: Integer; const Name: string; + QType: Integer): string; public - timeout:integer; - DNSHost:string; - RCode:integer; - Constructor Create; - Destructor Destroy; override; - Function DNSQuery(Name:string;Qtype:integer;Reply:TStrings):Boolean; + constructor Create; + destructor Destroy; override; + function DNSQuery(Name: string; QType: Integer; + const Reply: TStrings): Boolean; + published + property Timeout: Integer read FTimeout Write FTimeout; + property DNSHost: string read FDNSHost Write FDNSHost; + property RCode: Integer read FRCode; end; -function GetMailServers (DNSHost, domain:string; servers:TStringList):Boolean; +function GetMailServers(const DNSHost, Domain: string; + const Servers: TStrings): Boolean; implementation -{TDNSSend.Create} -Constructor TDNSSend.Create; +constructor TDNSSend.Create; begin inherited Create; - sock:=TUDPBlockSocket.create; - sock.CreateSocket; - timeout:=5000; - DNShost:='localhost'; + FSock := TUDPBlockSocket.Create; + FSock.CreateSocket; + FTimeout := 5000; + FDNSHost := cLocalhost; end; -{TDNSSend.Destroy} -Destructor TDNSSend.Destroy; +destructor TDNSSend.Destroy; begin - Sock.free; - inherited destroy; + FSock.Free; + inherited Destroy; end; -{TDNSSend.ComressName} -function TDNSSend.CompressName(Value:string):string; +function TDNSSend.CompressName(const Value: string): string; var - n:integer; - s:String; + n: Integer; + s: string; begin - Result:=''; - if Value='' then Result:=char(0) - else + Result := ''; + if Value = '' then + Result := #0 + else + begin + s := ''; + for n := 1 to Length(Value) do + if Value[n] = '.' then begin - s:=''; - for n:=1 to Length(Value) do - if Value[n]='.' then - begin - Result:=Result+char(Length(s))+s; - s:=''; - end - else s:=s+Value[n]; - if s<>'' then Result:=Result+char(Length(s))+s; - Result:=Result+char(0); - end; + Result := Result + Char(Length(s)) + s; + s := ''; + end + else + s := s + Value[n]; + if s <> '' then + Result := Result + Char(Length(s)) + s; + Result := Result + #0; + end; end; -{TDNSSend.CodeHeader} -function TDNSSend.CodeHeader:string; +function TDNSSend.CodeHeader: string; begin Randomize; - Result:=Codeint(Random(32767)); //ID - Result:=Result+Codeint($0100); //flags - Result:=Result+Codeint(1); //QDCount - Result:=Result+Codeint(0); //ANCount - Result:=Result+Codeint(0); //NSCount - Result:=Result+Codeint(0); //ARCount + Result := CodeInt(Random(32767)); // ID + Result := Result + CodeInt($0100); // flags + Result := Result + CodeInt(1); // QDCount + Result := Result + CodeInt(0); // ANCount + Result := Result + CodeInt(0); // NSCount + Result := Result + CodeInt(0); // ARCount end; -{TDNSSend.CodeQuery} -function TDNSSend.CodeQuery(Name:string; Qtype:integer):string; +function TDNSSend.CodeQuery(const Name: string; QType: Integer): string; begin - Result:=Compressname(Name); - Result:=Result+Codeint(Qtype); - Result:=Result+Codeint(1); //Type INTERNET + Result := CompressName(Name); + Result := Result + CodeInt(QType); + Result := Result + CodeInt(1); // Type INTERNET end; -{TDNSSend.DecodeLabels} -function TDNSSend.DecodeLabels(var From:integer):string; +function TDNSSend.DecodeLabels(var From: Integer): string; var - l,f:integer; + l, f: Integer; begin - Result:=''; + Result := ''; while True do + begin + l := Ord(FBuffer[From]); + Inc(From); + if l = 0 then + Break; + if Result <> '' then + Result := Result + '.'; + if (l and $C0) = $C0 then begin - l:=Ord(Buffer[From]); + f := l and $3F; + f := f * 256 + Ord(FBuffer[From]) + 1; Inc(From); - if l=0 then break; - if Result<>'' then Result:=Result+'.'; - if (l and $C0)=$C0 - then - begin - f:=l and $3F; - f:=f*256+Ord(Buffer[From])+1; - Inc(From); - Result:=Result+Self.decodelabels(f); - break; - end - else - begin - Result:=Result+Copy(Buffer,From,l); - Inc(From,l); - end; - end; -end; - -{TDNSSend.DecodeResource} -function TDNSSend.DecodeResource(var i:integer; Name:string; -Qtype:integer):string; -var - Rname:string; - RType,Len,j,x,n:integer; -begin - Result:=''; - Rname:=decodelabels(i); - Rtype:=DeCodeint(Buffer,i); - Inc(i,8); - Len:=DeCodeint(Buffer,i); - Inc(i,2); //i point to begin of data - j:=i; - i:=i+len; //i point to next record - if (Name=Rname) and (Qtype=RType) then + Result := Result + DecodeLabels(f); + Break; + end + else begin - case Rtype of - Qtype_A : - begin - Result:=IntToStr(Ord(Buffer[j])); - Inc(j); - Result:=Result+'.'+IntToStr(Ord(Buffer[j])); - Inc(j); - Result:=Result+'.'+IntToStr(Ord(Buffer[j])); - Inc(j); - Result:=Result+'.'+IntToStr(Ord(Buffer[j])); - end; - Qtype_NS, - Qtype_MD, - Qtype_MF, - Qtype_CNAME, - Qtype_MB, - Qtype_MG, - Qtype_MR, - Qtype_PTR, - Qtype_X25, - Qtype_NSAP, - Qtype_NSAPPTR: - begin - Result:=Decodelabels(j); - end; - Qtype_SOA : - begin - Result:=Decodelabels(j); - Result:=Result+','+Decodelabels(j); - for n:=1 to 5 do - begin - x:=DecodeInt(Buffer,j)*65536+DecodeInt(Buffer,j+2); - Inc(j,4); - Result:=Result+','+IntToStr(x); - end; - end; - Qtype_NULL : - begin - end; - Qtype_WKS : - begin - end; - Qtype_HINFO, - Qtype_MINFO, - Qtype_RP, - Qtype_ISDN : - begin - Result:=Decodelabels(j); - Result:=Result+','+Decodelabels(j); - end; - Qtype_MX, - Qtype_AFSDB, - Qtype_RT, - Qtype_KX : - begin - x:=DecodeInt(Buffer,j); - Inc(j,2); - Result:=IntToStr(x); - Result:=Result+','+Decodelabels(j); - end; - Qtype_TXT : - begin - Result:=Decodelabels(j); - end; - Qtype_GPOS : - begin - Result:=Decodelabels(j); - Result:=Result+','+Decodelabels(j); - Result:=Result+','+Decodelabels(j); - end; - Qtype_PX : - begin - x:=DecodeInt(Buffer,j); - Inc(j,2); - Result:=IntToStr(x); - Result:=Result+','+Decodelabels(j); - Result:=Result+','+Decodelabels(j); - end; - end; + Result := Result + Copy(FBuffer, From, l); + Inc(From, l); end; + end; end; -{TDNSSend.DNSQuery} -Function TDNSSend.DNSQuery(Name:string;Qtype:integer;Reply:TStrings):Boolean; +function TDNSSend.DecodeResource(var i: Integer; const Name: string; + QType: Integer): string; var - x,n,i:integer; - flag,qdcount, ancount, nscount, arcount:integer; - s:string; + Rname: string; + RType, Len, j, x, n: Integer; begin - Result:=False; - Reply.Clear; - if IsIP(Name) then Name:=ReverseIP(Name)+'.in-addr.arpa'; - Buffer:=Codeheader+CodeQuery(Name,QType); - sock.connect(DNSHost,'domain'); -// dump(Buffer,'c:\dnslog.Txt'); - sock.sendstring(Buffer); - if sock.canread(timeout) - then begin - x:=sock.waitingdata; - setlength(Buffer,x); - sock.recvbuffer(Pointer(Buffer),x); -// dump(Buffer,'c:\dnslogr.Txt'); - flag:=DeCodeint(Buffer,3); - RCode:=Flag and $000F; - if RCode=0 then + Result := ''; + Rname := DecodeLabels(i); + RType := DecodeInt(FBuffer, i); + Inc(i, 8); + Len := DecodeInt(FBuffer, i); + Inc(i, 2); // i point to begin of data + j := i; + i := i + len; // i point to next record + if (Name = Rname) and (QType = RType) then + begin + case RType of + QTYPE_A: begin - qdcount:=DeCodeint(Buffer,5); - ancount:=DeCodeint(Buffer,7); - nscount:=DeCodeint(Buffer,9); - arcount:=DeCodeint(Buffer,11); - i:=13; //begin of body - if qdcount>0 then //skip questions - for n:=1 to qdcount do - begin - while (Buffer[i]<>#0) and ((Ord(Buffer[i]) and $C0)<>$C0) do - Inc(i); - Inc(i,5); - end; - if ancount>0 then - for n:=1 to ancount do - begin - s:=DecodeResource(i, Name, Qtype); - if s<>'' then - Reply.Add(s); - end; - Result:=True; + Result := IntToStr(Ord(FBuffer[j])); + Inc(j); + Result := Result + '.' + IntToStr(Ord(FBuffer[j])); + Inc(j); + Result := Result + '.' + IntToStr(Ord(FBuffer[j])); + Inc(j); + Result := Result + '.' + IntToStr(Ord(FBuffer[j])); + end; + QTYPE_NS, QTYPE_MD, QTYPE_MF, QTYPE_CNAME, QTYPE_MB, + QTYPE_MG, QTYPE_MR, QTYPE_PTR, QTYPE_X25, QTYPE_NSAP, + QTYPE_NSAPPTR: + Result := DecodeLabels(j); + QTYPE_SOA: + begin + Result := DecodeLabels(j); + Result := Result + ',' + DecodeLabels(j); + for n := 1 to 5 do + begin + x := DecodeInt(FBuffer, j) * 65536 + DecodeInt(FBuffer, j + 2); + Inc(j, 4); + Result := Result + ',' + IntToStr(x); + end; + end; + QTYPE_NULL: + begin + end; + QTYPE_WKS: + begin + end; + QTYPE_HINFO, QTYPE_MINFO, QTYPE_RP, QTYPE_ISDN: + begin + Result := DecodeLabels(j); + Result := Result + ',' + DecodeLabels(j); + end; + QTYPE_MX, QTYPE_AFSDB, QTYPE_RT, QTYPE_KX: + begin + x := DecodeInt(FBuffer, j); + Inc(j, 2); + Result := IntToStr(x); + Result := Result + ',' + DecodeLabels(j); + end; + QTYPE_TXT: + Result := DecodeLabels(j); + QTYPE_GPOS: + begin + Result := DecodeLabels(j); + Result := Result + ',' + DecodeLabels(j); + Result := Result + ',' + DecodeLabels(j); + end; + QTYPE_PX: + begin + x := DecodeInt(FBuffer, j); + Inc(j, 2); + Result := IntToStr(x); + Result := Result + ',' + DecodeLabels(j); + Result := Result + ',' + DecodeLabels(j); end; end; + end; +end; + +function TDNSSend.DNSQuery(Name: string; QType: Integer; + const Reply: TStrings): Boolean; +var + x, n, i: Integer; + flag, qdcount, ancount, nscount, arcount: Integer; + s: string; +begin + Result := False; + Reply.Clear; + if IsIP(Name) then + Name := ReverseIP(Name) + '.in-addr.arpa'; + FBuffer := CodeHeader + CodeQuery(Name, QType); + FSock.Connect(FDNSHost, cDnsProtocol); + FSock.SendString(FBuffer); + if FSock.CanRead(FTimeout) then + begin + x := FSock.WaitingData; + SetLength(FBuffer, x); + FSock.RecvBuffer(Pointer(FBuffer), x); + flag := DecodeInt(FBuffer, 3); + FRCode := Flag and $000F; + if FRCode = 0 then + begin + qdcount := DecodeInt(FBuffer, 5); + ancount := DecodeInt(FBuffer, 7); + nscount := DecodeInt(FBuffer, 9); + arcount := DecodeInt(FBuffer, 11); + i := 13; //begin of body + if qdcount > 0 then //skip questions + for n := 1 to qdcount do + begin + while (FBuffer[i] <> #0) and ((Ord(FBuffer[i]) and $C0) <> $C0) do + Inc(i); + Inc(i, 5); + end; + if ancount > 0 then + for n := 1 to ancount do + begin + s := DecodeResource(i, Name, QType); + if s <> '' then + Reply.Add(s); + end; + Result := True; + end; + end; end; {==============================================================================} -function GetMailServers (DNSHost, domain:string; servers:TStringList):Boolean; +function GetMailServers(const DNSHost, Domain: string; + const Servers: TStrings): Boolean; var - DNS:TDNSSend; - t:TStringList; - n,m,x:integer; + DNS: TDNSSend; + t: TStringList; + n, m, x: Integer; begin - Result:=False; - servers.Clear; - t:=TStringList.Create; - DNS:=TDNSSend.Create; + Result := False; + Servers.Clear; + t := TStringList.Create; + DNS := TDNSSend.Create; try - DNS.DNSHost:=DNSHost; - if DNS.DNSQuery(domain,QType_MX,t) then + DNS.DNSHost := DNSHost; + if DNS.DNSQuery(Domain, QType_MX, t) then + begin + { normalize preference number to 5 digits } + for n := 0 to t.Count - 1 do begin - {normalize preference number to 5 digits} - for n:=0 to t.Count-1 do - begin - x:=Pos(',',t[n]); - if x>0 then - for m:=1 to 6-x do - t[n]:='0'+t[n]; - end; - {sort server list} - t.Sorted:=True; - {result is sorted list without preference numbers} - for n:=0 to t.Count-1 do - begin - x:=Pos(',',t[n]); - servers.Add(Copy(t[n],x+1,Length(t[n])-x)); - end; - Result:=True; + x := Pos(',', t[n]); + if x > 0 then + for m := 1 to 6 - x do + t[n] := '0' + t[n]; end; + { sort server list } + t.Sorted := True; + { result is sorted list without preference numbers } + for n := 0 to t.Count - 1 do + begin + x := Pos(',', t[n]); + Servers.Add(Copy(t[n], x + 1, Length(t[n]) - x)); + end; + Result := True; + end; finally DNS.Free; t.Free; @@ -375,5 +366,3 @@ begin end; end. - - diff --git a/httpsend.pas b/httpsend.pas index 2f9e0ed..c2627b0 100644 --- a/httpsend.pas +++ b/httpsend.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.001.000 | +| Project : Delphree - Synapse | 002.001.001 | |==============================================================================| | Content: HTTP client | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -23,423 +23,432 @@ | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} +{$WEAKPACKAGEUNIT ON} + unit HTTPSend; interface + uses - Blcksock, sysutils, classes, SynaUtil, SynaCode; + SysUtils, Classes, + blcksock, SynaUtil, SynaCode; const - CRLF=#13+#10; + cHttpProtocol = '80'; type - TTransferEncoding=(TE_UNKNOWN, - TE_IDENTITY, - TE_CHUNKED); + TTransferEncoding = (TE_UNKNOWN, TE_IDENTITY, TE_CHUNKED); - THTTPSend = class + THTTPSend = class(TObject) private - Sock:TTCPBlockSocket; - TransferEncoding:TTransferEncoding; - AliveHost:string; - AlivePort:string; - function ReadUnknown:boolean; - function ReadIdentity(size:integer):boolean; - function ReadChunked:boolean; + FSock: TTCPBlockSocket; + FTransferEncoding: TTransferEncoding; + FAliveHost: string; + FAlivePort: string; + FHeaders: TStringList; + FDocument: TMemoryStream; + FMimeType: string; + FProtocol: string; + FKeepAlive: Boolean; + FTimeout: Integer; + FHTTPHost: string; + FHTTPPort: string; + FProxyHost: string; + FProxyPort: string; + FProxyUser: string; + FProxyPass: string; + FResultCode: Integer; + FResultString: string; + function ReadUnknown: Boolean; + function ReadIdentity(Size: Integer): Boolean; + function ReadChunked: Boolean; public - headers:TStringlist; - Document:TMemoryStream; - MimeType:string; - Protocol:string; - KeepAlive:boolean; - Timeout:integer; - HTTPHost:string; - HTTPPort:string; - ProxyHost:string; - ProxyPort:string; - ProxyUser:string; - ProxyPass:string; - ResultCode:integer; - ResultString:string; - Constructor Create; - Destructor Destroy; override; - procedure clear; - procedure DecodeStatus(value:string); - function HTTPmethod(method,URL:string):boolean; + constructor Create; + destructor Destroy; override; + procedure Clear; + procedure DecodeStatus(const Value: string); + function HTTPMethod(const Method, URL: string): Boolean; + published + property Headers: TStringList read FHeaders Write FHeaders; + property Document: TMemoryStream read FDocument Write FDocument; + property MimeType: string read FMimeType Write FMimeType; + property Protocol: string read FProtocol Write FProtocol; + property KeepAlive: Boolean read FKeepAlive Write FKeepAlive; + property Timeout: Integer read FTimeout Write FTimeout; + property HTTPHost: string read FHTTPHost; + property HTTPPort: string read FHTTPPort; + property ProxyHost: string read FProxyHost Write FProxyHost; + property ProxyPort: string read FProxyPort Write FProxyPort; + property ProxyUser: string read FProxyUser Write FProxyUser; + property ProxyPass: string read FProxyPass Write FProxyPass; + property ResultCode: Integer read FResultCode; + property ResultString: string read FResultString; end; -function HttpGetText(URL:string;Response:TStrings):Boolean; -function HttpGetBinary(URL:string;Response:TStream):Boolean; -function HttpPostBinary(URL:string;Data:TStream):Boolean; -function HttpPostURL(URL:string;URLData:string;Data:TStream):Boolean; +function HttpGetText(const URL: string; const Response: TStrings): Boolean; +function HttpGetBinary(const URL: string; const Response: TStream): Boolean; +function HttpPostBinary(const URL: string; const Data: TStream): Boolean; +function HttpPostURL(const URL, URLData: string; const Data: TStream): Boolean; implementation -{THTTPSend.Create} -Constructor THTTPSend.Create; +const + CRLF = #13#10; + +constructor THTTPSend.Create; begin inherited Create; - Headers:=TStringList.create; - Document:=TMemoryStream.Create; - sock:=TTCPBlockSocket.create; - sock.SizeRecvBuffer:=65536; - sock.SizeSendBuffer:=65536; - timeout:=300000; - HTTPhost:='localhost'; - HTTPPort:='80'; - ProxyHost:=''; - ProxyPort:='8080'; - ProxyUser:=''; - ProxyPass:=''; - AliveHost:=''; - AlivePort:=''; - Protocol:='1.1'; - KeepAlive:=true; + FHeaders := TStringList.Create; + FDocument := TMemoryStream.Create; + FSock := TTCPBlockSocket.Create; + FSock.SizeRecvBuffer := 65536; + FSock.SizeSendBuffer := 65536; + FTimeout := 300000; + FHTTPHost := cLocalhost; + FHTTPPort := cHttpProtocol; + FProxyHost := ''; + FProxyPort := '8080'; + FProxyUser := ''; + FProxyPass := ''; + FAliveHost := ''; + FAlivePort := ''; + FProtocol := '1.1'; + FKeepAlive := True; Clear; end; -{THTTPSend.Destroy} -Destructor THTTPSend.Destroy; +destructor THTTPSend.Destroy; begin - Sock.free; - Document.free; - headers.free; - inherited destroy; + FSock.Free; + FDocument.Free; + FHeaders.Free; + inherited Destroy; end; -{THTTPSend.Clear} procedure THTTPSend.Clear; begin - Document.Clear; - Headers.Clear; - MimeType:='text/html'; + FDocument.Clear; + FHeaders.Clear; + FMimeType := 'text/html'; end; -{THTTPSend.DecodeStatus} -procedure THTTPSend.DecodeStatus(value:string); +procedure THTTPSend.DecodeStatus(const Value: string); var - s,su:string; + s, su: string; begin - s:=separateright(value,' '); - su:=separateleft(s,' '); - ResultCode:=StrToIntDef(su,0); - ResultString:=separateright(s,' '); - if ResultString=s - then ResultString:=''; + s := SeparateRight(Value, ' '); + su := SeparateLeft(s, ' '); + FResultCode := StrToIntDef(su, 0); + FResultString := SeparateRight(s, ' '); + if FResultString = s then + FResultString := ''; end; -{THTTPSend.HTTPmethod} -function THTTPSend.HTTPmethod(method,URL:string):boolean; +function THTTPSend.HTTPMethod(const Method, URL: string): Boolean; var - sending,receiving:boolean; - status100:boolean; - status100error:string; - ToClose:boolean; - size:integer; - Prot,User,Pass,Host,Port,Path,Para,URI:string; - n:integer; - s,su:string; + Sending, Receiving: Boolean; + status100: Boolean; + status100error: string; + ToClose: Boolean; + Size: Integer; + Prot, User, Pass, Host, Port, Path, Para, URI: string; + n: Integer; + s, su: string; begin {initial values} - result:=false; - ResultCode:=500; - ResultString:=''; + Result := False; + FResultCode := 500; + FResultString := ''; - URI:=ParseURL(URL,Prot,User,Pass,Host,Port,Path,Para); - sending:=Document.Size>0; - {headers for sending data} - status100:=sending and (protocol='1.1'); - if status100 - then Headers.insert(0,'Expect: 100-continue'); - if sending then - begin - Headers.insert(0,'Content-Length: '+inttostr(Document.size)); - if MimeType<>'' - then Headers.insert(0,'Content-Type: '+MimeType); - end; - {seting KeepAlives} - if not KeepAlive - then Headers.insert(0,'Connection: close'); - {set target servers/proxy, authorisations, etc...} - if User<>'' - then Headers.insert(0,'Authorization: Basic '+EncodeBase64(user+':'+pass)); - if (proxyhost<>'') and (proxyUser<>'') - then Headers.insert(0,'Proxy-Authorization: Basic '+EncodeBase64(Proxyuser+':'+Proxypass)); - Headers.insert(0,'Host: '+host+':'+port); - if proxyHost<>'' - then URI:=prot+'://'+host+':'+port+URI; - if URI='/*' - then URI:='*'; - if protocol='0.9' - then Headers.insert(0,uppercase(method)+' '+URI) - else Headers.insert(0,uppercase(method)+' '+URI+' HTTP/'+protocol); - if proxyhost='' - then - begin - HttpHost:=host; - HttpPort:=port; - end - else - begin - HttpHost:=Proxyhost; - HttpPort:=Proxyport; - end; - if headers[headers.count-1]<>'' - then headers.add(''); - - {connect} - if (Alivehost<>HTTPhost) or (AlivePort<>HTTPport) - then - begin - sock.CloseSocket; - sock.CreateSocket; - sock.Connect(HTTPHost,HTTPPort); - if sock.lasterror<>0 then Exit; - Alivehost:=HTTPhost; - AlivePort:=HTTPport; - end - else - begin - if sock.canread(0) then - begin - sock.CloseSocket; - sock.createsocket; - sock.Connect(HTTPHost,HTTPPort); - if sock.lasterror<>0 then Exit; - end; - end; - - {send headers} - Sock.SendString(Headers[0]+CRLF); - if protocol<>'0.9' then - for n:=1 to Headers.Count-1 do - Sock.SendString(Headers[n]+CRLF); - if sock.lasterror<>0 then Exit; - - {reading Status} - Status100Error:=''; + URI := ParseURL(URL, Prot, User, Pass, Host, Port, Path, Para); + Sending := Document.Size > 0; + {Headers for Sending data} + status100 := Sending and (FProtocol = '1.1'); if status100 then + FHeaders.Insert(0, 'Expect: 100-continue'); + if Sending then + begin + FHeaders.Insert(0, 'Content-Length: ' + IntToStr(FDocument.Size)); + if FMimeType <> '' then + FHeaders.Insert(0, 'Content-Type: ' + FMimeType); + end; + { setting KeepAlives } + if not FKeepAlive then + FHeaders.Insert(0, 'Connection: close'); + { set target servers/proxy, authorisations, etc... } + if User <> '' then + FHeaders.Insert(0, 'Authorization: Basic ' + EncodeBase64(user + ':' + pass)); + if (FProxyHost <> '') and (FProxyUser <> '') then + FHeaders.Insert(0, 'Proxy-Authorization: Basic ' + + EncodeBase64(FProxyUser + ':' + FProxyPass)); + FHeaders.Insert(0, 'Host: ' + Host + ':' + Port); + if FProxyHost <> '' then + URI := Prot + '://' + Host + ':' + Port + URI; + if URI = '/*' then + URI := '*'; + if FProtocol = '0.9' then + FHeaders.Insert(0, UpperCase(Method) + ' ' + URI) + else + FHeaders.Insert(0, UpperCase(Method) + ' ' + URI + ' HTTP/' + FProtocol); + if FProxyHost = '' then + begin + FHTTPHost := Host; + FHTTPPort := Port; + end + else + begin + FHTTPHost := FProxyHost; + FHTTPPort := FProxyPort; + end; + if FHeaders[FHeaders.Count - 1] <> '' then + FHeaders.Add(''); + + { connect } + if (FAliveHost <> FHTTPHost) or (FAlivePort <> FHTTPPort) then + begin + FSock.CloseSocket; + FSock.CreateSocket; + FSock.Connect(FHTTPHost, FHTTPPort); + if FSock.LastError <> 0 then + Exit; + FAliveHost := FHTTPHost; + FAlivePort := FHTTPPort; + end + else + begin + if FSock.CanRead(0) then begin - repeat - s:=sock.recvstring(timeout); - if s<>'' then break; - until sock.lasterror<>0; - DecodeStatus(s); - if (ResultCode>=100) and (ResultCode<200) - then - begin - repeat - s:=sock.recvstring(timeout); - if s='' then break; - until sock.lasterror<>0; - end - else - begin - sending:=false; - Status100Error:=s; - end; + FSock.CloseSocket; + FSock.CreateSocket; + FSock.Connect(FHTTPHost, FHTTPPort); + if FSock.LastError <> 0 then + Exit; end; + end; - {send document} - if sending then - begin - Sock.SendBuffer(Document.memory,Document.size); - if sock.lasterror<>0 then Exit; - end; + { send Headers } + FSock.SendString(Headers[0] + CRLF); + if FProtocol <> '0.9' then + for n := 1 to FHeaders.Count - 1 do + FSock.SendString(FHeaders[n] + CRLF); + if FSock.LastError <> 0 then + Exit; - clear; - size:=-1; - TransferEncoding:=TE_UNKNOWN; - - {read status} - If Status100Error='' - then - begin - repeat - s:=sock.recvstring(timeout); - if s<>'' then break; - until sock.lasterror<>0; - if pos('HTTP/',uppercase(s))=1 - then - begin - Headers.add(s); - decodeStatus(s); - end - else - begin - {old HTTP 0.9 and some buggy servers not send result} - s:=s+CRLF; - document.Write(pointer(s)^,length(s)); - ResultCode:=0; - end; - end - else Headers.add(Status100Error); - - {if need receive hedaers, receive and parse it} - ToClose:=protocol<>'1.1'; - if Headers.count>0 then + { reading Status } + Status100Error := ''; + if status100 then + begin repeat - s:=sock.recvstring(timeout); - Headers.Add(s); - if s='' - then break; - su:=uppercase(s); - if pos('CONTENT-LENGTH:',su)=1 then - begin - size:=strtointdef(separateright(s,' '),-1); - TransferEncoding:=TE_IDENTITY; - end; - if pos('CONTENT-TYPE:',su)=1 then - MimeType:=separateright(s,' '); - if pos('TRANSFER-ENCODING:',su)=1 then - begin - s:=separateright(su,' '); - if pos('CHUNKED',s)>0 then - TransferEncoding:=TE_CHUNKED; - end; - if pos('CONNECTION: CLOSE',su)=1 then - ToClose:=true; - until sock.lasterror<>0; + s := FSock.RecvString(FTimeout); + if s <> '' then + Break; + until FSock.LastError <> 0; + DecodeStatus(s); + if (FResultCode >= 100) and (FResultCode < 200) then + repeat + s := FSock.recvstring(FTimeout); + if s = '' then + Break; + until FSock.LastError <> 0 + else + begin + Sending := False; + Status100Error := s; + end; + end; + + { send document } + if Sending then + begin + FSock.SendBuffer(FDocument.Memory, FDocument.Size); + if FSock.LastError <> 0 then + Exit; + end; + + Clear; + Size := -1; + FTransferEncoding := TE_UNKNOWN; + + { read status } + if Status100Error = '' then + begin + repeat + s := FSock.RecvString(FTimeout); + if s <> '' then + Break; + until FSock.LastError <> 0; + if Pos('HTTP/', UpperCase(s)) = 1 then + begin + FHeaders.Add(s); + DecodeStatus(s); + end + else + begin + { old HTTP 0.9 and some buggy servers not send result } + s := s + CRLF; + FDocument.Write(Pointer(s)^, Length(s)); + FResultCode := 0; + end; + end + else + FHeaders.Add(Status100Error); + + { if need receive hedaers, receive and parse it } + ToClose := FProtocol <> '1.1'; + if FHeaders.Count > 0 then + repeat + s := FSock.RecvString(FTimeout); + FHeaders.Add(s); + if s = '' then + Break; + su := UpperCase(s); + if Pos('CONTENT-LENGTH:', su) = 1 then + begin + Size := StrToIntDef(SeparateRight(s, ' '), -1); + FTransferEncoding := TE_IDENTITY; + end; + if Pos('CONTENT-TYPE:', su) = 1 then + FMimeType := SeparateRight(s, ' '); + if Pos('TRANSFER-ENCODING:', su) = 1 then + begin + s := SeparateRight(su, ' '); + if Pos('CHUNKED', s) > 0 then + FTransferEncoding := TE_CHUNKED; + end; + if Pos('CONNECTION: CLOSE', su) = 1 then + ToClose := True; + until FSock.LastError <> 0; {if need receive response body, read it} - Receiving:=Method<>'HEAD'; - Receiving:=Receiving and (ResultCode<>204); - Receiving:=Receiving and (ResultCode<>304); + Receiving := Method <> 'HEAD'; + Receiving := Receiving and (FResultCode <> 204); + Receiving := Receiving and (FResultCode <> 304); if Receiving then - case TransferEncoding of - TE_UNKNOWN : readunknown; - TE_IDENTITY: readidentity(size); - TE_CHUNKED : readChunked; + case FTransferEncoding of + TE_UNKNOWN: + ReadUnknown; + TE_IDENTITY: + ReadIdentity(Size); + TE_CHUNKED: + ReadChunked; end; - Document.Seek(0,soFromBeginning); - result:=true; + FDocument.Seek(0, soFromBeginning); + Result := True; if ToClose then - begin - sock.closesocket; - Alivehost:=''; - AlivePort:=''; - end; -end; - -{THTTPSend.ReadUnknown} -function THTTPSend.ReadUnknown:boolean; -var - s:string; -begin - result:=false; - repeat - s:=sock.recvstring(timeout); - s:=s+CRLF; - document.Write(pointer(s)^,length(s)); - until sock.lasterror<>0; - result:=true; -end; - -{THTTPSend.ReadIdentity} -function THTTPSend.ReadIdentity(size:integer):boolean; -var - mem:TMemoryStream; -begin - mem:=TMemoryStream.create; - try - mem.SetSize(size); - sock.RecvBufferEx(mem.memory,size,timeout); - result:=sock.lasterror=0; - document.CopyFrom(mem,0); - finally - mem.free; + begin + FSock.CloseSocket; + FAliveHost := ''; + FAlivePort := ''; end; end; -{THTTPSend.ReadChunked} -function THTTPSend.ReadChunked:boolean; +function THTTPSend.ReadUnknown: Boolean; var - s:string; - size:integer; + s: string; +begin + repeat + s := FSock.RecvString(FTimeout); + s := s + CRLF; + FDocument.Write(Pointer(s)^, Length(s)); + until FSock.LastError <> 0; + Result := True; +end; + +function THTTPSend.ReadIdentity(Size: Integer): Boolean; +var + mem: TMemoryStream; +begin + mem := TMemoryStream.Create; + try + mem.SetSize(Size); + FSock.RecvBufferEx(mem.Memory, Size, FTimeout); + Result := FSock.LastError = 0; + FDocument.CopyFrom(mem, 0); + finally + mem.Free; + end; +end; + +function THTTPSend.ReadChunked: Boolean; +var + s: string; + Size: Integer; begin repeat repeat - s:=sock.recvstring(timeout); - until s<>''; - if sock.lasterror<>0 - then break; - s:=separateleft(s,' '); - size:=strtointdef('$'+s,0); - if size=0 then break; - ReadIdentity(size); - until false; - result:=sock.lasterror=0; + s := FSock.RecvString(FTimeout); + until s <> ''; + if FSock.LastError <> 0 then + Break; + s := SeparateLeft(s, ' '); + Size := StrToIntDef('$' + s, 0); + if Size = 0 then + Break; + ReadIdentity(Size); + until False; + Result := FSock.LastError = 0; end; {==============================================================================} -{HttpGetText} -function HttpGetText(URL:string;Response:TStrings):Boolean; +function HttpGetText(const URL: string; const Response: TStrings): Boolean; var - HTTP:THTTPSend; + HTTP: THTTPSend; begin - Result:=False; - HTTP:=THTTPSend.Create; + HTTP := THTTPSend.Create; try - Result:=HTTP.HTTPmethod('GET',URL); - response.LoadFromStream(HTTP.document); + Result := HTTP.HTTPMethod('GET', URL); + Response.LoadFromStream(HTTP.Document); finally HTTP.Free; end; end; -{HttpGetBinary} -function HttpGetBinary(URL:string;Response:TStream):Boolean; +function HttpGetBinary(const URL: string; const Response: TStream): Boolean; var - HTTP:THTTPSend; + HTTP: THTTPSend; begin - Result:=False; - HTTP:=THTTPSend.Create; + HTTP := THTTPSend.Create; try - Result:=HTTP.HTTPmethod('GET',URL); - Response.Seek(0,soFromBeginning); - Response.CopyFrom(HTTP.document,0); + Result := HTTP.HTTPMethod('GET', URL); + Response.Seek(0, soFromBeginning); + Response.CopyFrom(HTTP.Document, 0); finally HTTP.Free; end; end; -{HttpPostBinary} -function HttpPostBinary(URL:string;Data:TStream):Boolean; +function HttpPostBinary(const URL: string; const Data: TStream): Boolean; var - HTTP:THTTPSend; + HTTP: THTTPSend; begin - Result:=False; - HTTP:=THTTPSend.Create; + HTTP := THTTPSend.Create; try - HTTP.Document.CopyFrom(data,0); - HTTP.MimeType:='Application/octet-stream'; - Result:=HTTP.HTTPmethod('POST',URL); - data.Seek(0,soFromBeginning); - data.CopyFrom(HTTP.document,0); + HTTP.Document.CopyFrom(Data, 0); + HTTP.MimeType := 'Application/octet-stream'; + Result := HTTP.HTTPMethod('POST', URL); + Data.Seek(0, soFromBeginning); + Data.CopyFrom(HTTP.Document, 0); finally HTTP.Free; end; end; -{HttpPostURL} -function HttpPostURL(URL:string;URLData:string;Data:TStream):Boolean; +function HttpPostURL(const URL, URLData: string; const Data: TStream): Boolean; var - HTTP:THTTPSend; + HTTP: THTTPSend; begin - Result:=False; - HTTP:=THTTPSend.Create; + HTTP := THTTPSend.Create; try - HTTP.Document.Write(pointer(URLData)^,Length(URLData)); - HTTP.MimeType:='application/x-url-encoded'; - Result:=HTTP.HTTPmethod('POST',URL); - data.Seek(0,soFromBeginning); - data.CopyFrom(HTTP.document,0); + HTTP.Document.Write(Pointer(URLData)^, Length(URLData)); + HTTP.MimeType := 'application/x-url-encoded'; + Result := HTTP.HTTPMethod('POST', URL); + Data.Seek(0, soFromBeginning); + Data.CopyFrom(HTTP.Document, 0); finally HTTP.Free; end; end; - end. diff --git a/mimechar.pas b/mimechar.pas deleted file mode 100644 index e8a7c78..0000000 --- a/mimechar.pas +++ /dev/null @@ -1,1135 +0,0 @@ -{==============================================================================| -| Project : Delphree - Synapse | 003.000.000 | -|==============================================================================| -| Content: MIME support character conversion tables | -|==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | -| (the "License"); you may not use this file except in compliance with the | -| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | -| | -| Software distributed under the License is distributed on an "AS IS" basis, | -| WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | -| the specific language governing rights and limitations under the License. | -|==============================================================================| -| The Original Code is Synapse Delphi Library. | -|==============================================================================| -| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| -| Portions created by Lukas Gebauer are Copyright (c)2000. | -| All Rights Reserved. | -|==============================================================================| -| Contributor(s): | -|==============================================================================| -| History: see HISTORY.HTM from distribution package | -| (Found at URL: http://www.ararat.cz/synapse/) | -|==============================================================================} - -{$Q-} - -unit MIMEchar; - -interface - -{$IFDEF LINUX} -uses - libc; -{$ENDIF} - -type - -TMimeChar=( - ISO_8859_1, - ISO_8859_2, - ISO_8859_3, - ISO_8859_4, - ISO_8859_5, - ISO_8859_6, - ISO_8859_7, - ISO_8859_8, - ISO_8859_9, - ISO_8859_10, - CP1250, - CP1251, - CP1252, - CP1253, - CP1254, - CP1255, - CP1256, - CP1257, - CP1258, - KOI8_R, - UCS_2, - UCS_4, - UTF_8, - UTF_7 - ); - -TSetChar=set of TMimeChar; - -var - SetTwo:set of TMimeChar=[UCS_2, UTF_7]; - SetFour:set of TMimeChar=[UCS_4, UTF_8]; - -const - -NotFoundChar='_'; - -//character transcoding tables X to UCS-2 -{ -//dummy table -$0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, -$0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, -$0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, -$0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, -$00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, -$00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, -$00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, -$00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, -$00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, -$00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, -$00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, -$00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, -$00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, -$00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, -$00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, -$00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF -} - -{Latin-1 -Danish, Dutch, English, Faeroese, Finnish, French, German, Icelandic, Irish, -Italian, Norwegian, Portuguese, Spanish and Swedish. -} - CharISO_8859_1:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, - $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, - $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, - $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, - $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, - $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, - $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, - $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, - $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, - $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, - $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, - $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF - ); - -{Latin-2 -Albanian, Czech, English, German, Hungarian, Polish, Rumanian, Serbo-Croatian, -Slovak, Slovene and Swedish. -} - CharISO_8859_2:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $0104, $02d8, $0141, $00a4, $013d, $015a, $00a7, - $00a8, $0160, $015e, $0164, $0179, $00ad, $017d, $017b, - $00b0, $0105, $02db, $0142, $00b4, $013e, $015b, $02c7, - $00b8, $0161, $015f, $0165, $017a, $02dd, $017e, $017c, - $0154, $00c1, $00c2, $0102, $00c4, $0139, $0106, $00c7, - $010c, $00c9, $0118, $00cb, $011a, $00cd, $00ce, $010e, - $0110, $0143, $0147, $00d3, $00d4, $0150, $00d6, $00d7, - $0158, $016e, $00da, $0170, $00dc, $00dd, $0162, $00df, - $0155, $00e1, $00e2, $0103, $00e4, $013a, $0107, $00e7, - $010d, $00e9, $0119, $00eb, $011b, $00ed, $00ee, $010f, - $0111, $0144, $0148, $00f3, $00f4, $0151, $00f6, $00f7, - $0159, $016f, $00fa, $0171, $00fc, $00fd, $0163, $02d9 - ); - -{Latin-3 -Afrikaans, Catalan, English, Esperanto, French, Galician, German, Italian, -Maltese and Turkish. -} - CharISO_8859_3:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $0126, $02d8, $00a3, $00a4, $fffd, $0124, $00a7, - $00a8, $0130, $015e, $011e, $0134, $00ad, $fffd, $017b, - $00b0, $0127, $00b2, $00b3, $00b4, $00b5, $0125, $00b7, - $00b8, $0131, $015f, $011f, $0135, $00bd, $fffd, $017c, - $00c0, $00c1, $00c2, $fffd, $00c4, $010a, $0108, $00c7, - $00c8, $00c9, $00ca, $00cb, $00cc, $00cd, $00ce, $00cf, - $fffd, $00d1, $00d2, $00d3, $00d4, $0120, $00d6, $00d7, - $011c, $00d9, $00da, $00db, $00dc, $016c, $015c, $00df, - $00e0, $00e1, $00e2, $fffd, $00e4, $010b, $0109, $00e7, - $00e8, $00e9, $00ea, $00eb, $00ec, $00ed, $00ee, $00ef, - $fffd, $00f1, $00f2, $00f3, $00f4, $0121, $00f6, $00f7, - $011d, $00f9, $00fa, $00fb, $00fc, $016d, $015d, $02d9 - ); - -{Latin-4 -Danish, English, Estonian, Finnish, German, Greenlandic, Lappish, Latvian, -Lithuanian, Norwegian and Swedish. -} - CharISO_8859_4:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $0104, $0138, $0156, $00a4, $0128, $013b, $00a7, - $00a8, $0160, $0112, $0122, $0166, $00ad, $017d, $00af, - $00b0, $0105, $02db, $0157, $00b4, $0129, $013c, $02c7, - $00b8, $0161, $0113, $0123, $0167, $014a, $017e, $014b, - $0100, $00c1, $00c2, $00c3, $00c4, $00c5, $00c6, $012e, - $010c, $00c9, $0118, $00cb, $0116, $00cd, $00ce, $012a, - $0110, $0145, $014c, $0136, $00d4, $00d5, $00d6, $00d7, - $00d8, $0172, $00da, $00db, $00dc, $0168, $016a, $00df, - $0101, $00e1, $00e2, $00e3, $00e4, $00e5, $00e6, $012f, - $010d, $00e9, $0119, $00eb, $0117, $00ed, $00ee, $012b, - $0111, $0146, $014d, $0137, $00f4, $00f5, $00f6, $00f7, - $00f8, $0173, $00fa, $00fb, $00fc, $0169, $016b, $02d9 - ); - -{CYRILLIC -Bulgarian, Bielorussian, English, Macedonian, Russian, Serbo-Croatian -and Ukrainian. -} - CharISO_8859_5:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $0401, $0402, $0403, $0404, $0405, $0406, $0407, - $0408, $0409, $040a, $040b, $040c, $00ad, $040e, $040f, - $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417, - $0418, $0419, $041a, $041b, $041c, $041d, $041e, $041f, - $0420, $0421, $0422, $0423, $0424, $0425, $0426, $0427, - $0428, $0429, $042a, $042b, $042c, $042d, $042e, $042f, - $0430, $0431, $0432, $0433, $0434, $0435, $0436, $0437, - $0438, $0439, $043a, $043b, $043c, $043d, $043e, $043f, - $0440, $0441, $0442, $0443, $0444, $0445, $0446, $0447, - $0448, $0449, $044a, $044b, $044c, $044d, $044e, $044f, - $2116, $0451, $0452, $0453, $0454, $0455, $0456, $0457, - $0458, $0459, $045a, $045b, $045c, $00a7, $045e, $045f - ); - -{ARABIC -} - CharISO_8859_6:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $fffd, $fffd, $fffd, $00a4, $fffd, $fffd, $fffd, - $fffd, $fffd, $fffd, $fffd, $060c, $00ad, $fffd, $fffd, - $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, - $fffd, $fffd, $fffd, $061b, $fffd, $fffd, $fffd, $061f, - $fffd, $0621, $0622, $0623, $0624, $0625, $0626, $0627, - $0628, $0629, $062a, $062b, $062c, $062d, $062e, $062f, - $0630, $0631, $0632, $0633, $0634, $0635, $0636, $0637, - $0638, $0639, $063a, $fffd, $fffd, $fffd, $fffd, $fffd, - $0640, $0641, $0642, $0643, $0644, $0645, $0646, $0647, - $0648, $0649, $064a, $064b, $064c, $064d, $064e, $064f, - $0650, $0651, $0652, $fffd, $fffd, $fffd, $fffd, $fffd, - $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd - ); - -{GREEK -} - CharISO_8859_7:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $2018, $2019, $00a3, $fffd, $fffd, $00a6, $00a7, - $00a8, $00a9, $fffd, $00ab, $00ac, $00ad, $fffd, $2015, - $00b0, $00b1, $00b2, $00b3, $0384, $0385, $0386, $00b7, - $0388, $0389, $038a, $00bb, $038c, $00bd, $038e, $038f, - $0390, $0391, $0392, $0393, $0394, $0395, $0396, $0397, - $0398, $0399, $039a, $039b, $039c, $039d, $039e, $039f, - $03a0, $03a1, $fffd, $03a3, $03a4, $03a5, $03a6, $03a7, - $03a8, $03a9, $03aa, $03ab, $03ac, $03ad, $03ae, $03af, - $03b0, $03b1, $03b2, $03b3, $03b4, $03b5, $03b6, $03b7, - $03b8, $03b9, $03ba, $03bb, $03bc, $03bd, $03be, $03bf, - $03c0, $03c1, $03c2, $03c3, $03c4, $03c5, $03c6, $03c7, - $03c8, $03c9, $03ca, $03cb, $03cc, $03cd, $03ce, $fffd - ); - -{HEBREW -} - CharISO_8859_8:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $fffd, $00a2, $00a3, $00a4, $00a5, $00a6, $00a7, - $00a8, $00a9, $00d7, $00ab, $00ac, $00ad, $00ae, $00af, - $00b0, $00b1, $00b2, $00b3, $00b4, $00b5, $00b6, $00b7, - $00b8, $00b9, $00f7, $00bb, $00bc, $00bd, $00be, $fffd, - $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, - $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, - $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, - $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $2017, - $05d0, $05d1, $05d2, $05d3, $05d4, $05d5, $05d6, $05d7, - $05d8, $05d9, $05da, $05db, $05dc, $05dd, $05de, $05df, - $05e0, $05e1, $05e2, $05e3, $05e4, $05e5, $05e6, $05e7, - $05e8, $05e9, $05ea, $fffd, $fffd, $200e, $200f, $fffd - ); - -{Latin-5 -English, Finnish, French, German, Irish, Italian, Norwegian, Portuguese, -Spanish, Swedish and Turkish. -} - CharISO_8859_9:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $0104, $02d8, $0141, $00a4, $013d, $015a, $00a7, - $00a8, $0160, $015e, $0164, $0179, $00ad, $017d, $017b, - $00b0, $0105, $02db, $0142, $00b4, $013e, $015b, $02c7, - $00b8, $0161, $015f, $0165, $017a, $02dd, $017e, $017c, - $0154, $00c1, $00c2, $0102, $00c4, $0139, $0106, $00c7, - $010c, $00c9, $0118, $00cb, $011a, $00cd, $00ce, $010e, - $011e, $00d1, $00d2, $00d3, $00d4, $00d5, $00d6, $00d7, - $00d8, $00d9, $00da, $00db, $00dc, $0130, $015e, $00df, - $00e0, $00e1, $00e2, $00e3, $00e4, $00e5, $00e6, $00e7, - $00e8, $00e9, $00ea, $00eb, $00ec, $00ed, $00ee, $00ef, - $011f, $00f1, $00f2, $00f3, $00f4, $00f5, $00f6, $00f7, - $00f8, $00f9, $00fa, $00fb, $00fc, $0131, $015f, $00ff - ); - -{Latin-6 -Danish, English, Estonian, Faeroese, Finnish, German, Greenlandic, Icelandic, -Lappish, Latvian, Lithuanian, Norwegian and Swedish. -} - CharISO_8859_10:array [128..255] of word = - ( - $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, - $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, - $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, - $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, - $00a0, $0104, $0112, $0122, $012a, $0128, $0136, $00a7, - $013b, $0110, $0160, $0166, $017d, $00ad, $016a, $014a, - $00b0, $0105, $0113, $0123, $012b, $0129, $0137, $00b7, - $013c, $0111, $0161, $0167, $017e, $2015, $016b, $014b, - $0100, $00c1, $00c2, $00c3, $00c4, $00c5, $00c6, $012e, - $010c, $00c9, $0118, $00cb, $0116, $00cd, $00ce, $00cf, - $00d0, $0145, $014c, $00d3, $00d4, $00d5, $00d6, $0168, - $00d8, $0172, $00da, $00db, $00dc, $00dd, $00de, $00df, - $0101, $00e1, $00e2, $00e3, $00e4, $00e5, $00e6, $012f, - $010d, $00e9, $0119, $00eb, $0117, $00ed, $00ee, $00ef, - $00f0, $0146, $014d, $00f3, $00f4, $00f5, $00f6, $0169, - $00f8, $0173, $00fa, $00fb, $00fc, $00fd, $00fe, $0138 - ); - -{Eastern European -} - CharCP_1250:array [128..255] of word = - ( - $20ac, $fffd, $201a, $fffd, $201e, $2026, $2020, $2021, - $fffd, $2030, $0160, $2039, $015a, $0164, $017d, $0179, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $fffd, $2122, $0161, $203a, $015b, $0165, $017e, $017a, - $00a0, $02c7, $02d8, $0141, $00a4, $0104, $00a6, $00a7, - $00a8, $00a9, $015e, $00ab, $00ac, $00ad, $00ae, $017b, - $00b0, $00b1, $02db, $0142, $00b4, $00b5, $00b6, $00b7, - $00b8, $0105, $015f, $00bb, $013d, $02dd, $013e, $017c, - $0154, $00c1, $00c2, $0102, $00c4, $0139, $0106, $00c7, - $010c, $00c9, $0118, $00cb, $011a, $00cd, $00ce, $010e, - $0110, $0143, $0147, $00d3, $00d4, $0150, $00d6, $00d7, - $0158, $016e, $00da, $0170, $00dc, $00dd, $0162, $00df, - $0155, $00e1, $00e2, $0103, $00e4, $013a, $0107, $00e7, - $010d, $00e9, $0119, $00eb, $011b, $00ed, $00ee, $010f, - $0111, $0144, $0148, $00f3, $00f4, $0151, $00f6, $00f7, - $0159, $016f, $00fa, $0171, $00fc, $00fd, $0163, $02d9 - ); - -{Cyrillic -} - CharCP_1251:array [128..255] of word = - ( - $0402, $0403, $201a, $0453, $201e, $2026, $2020, $2021, - $20ac, $2030, $0409, $2039, $040a, $040c, $040b, $040f, - $0452, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $fffd, $2122, $0459, $203a, $045a, $045c, $045b, $045f, - $00a0, $040e, $045e, $0408, $00a4, $0490, $00a6, $00a7, - $0401, $00a9, $0404, $00ab, $00ac, $00ad, $00ae, $0407, - $00b0, $00b1, $0406, $0456, $0491, $00b5, $00b6, $00b7, - $0451, $2116, $0454, $00bb, $0458, $0405, $0455, $0457, - $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417, - $0418, $0419, $041a, $041b, $041c, $041d, $041e, $041f, - $0420, $0421, $0422, $0423, $0424, $0425, $0426, $0427, - $0428, $0429, $042a, $042b, $042c, $042d, $042e, $042f, - $0430, $0431, $0432, $0433, $0434, $0435, $0436, $0437, - $0438, $0439, $043a, $043b, $043c, $043d, $043e, $043f, - $0440, $0441, $0442, $0443, $0444, $0445, $0446, $0447, - $0448, $0449, $044a, $044b, $044c, $044d, $044e, $044f - ); - -{Latin-1 (US, Western Europe) -} - CharCP_1252:array [128..255] of word = - ( - $20ac, $fffd, $201a, $0192, $201e, $2026, $2020, $2021, - $02c6, $2030, $0160, $2039, $0152, $fffd, $017d, $fffd, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $02dc, $2122, $0161, $203a, $0153, $fffd, $017e, $0178, - $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, - $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, - $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, - $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, - $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, - $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, - $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, - $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, - $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, - $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, - $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, - $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF - ); - -{Greek -} - CharCP_1253:array [128..255] of word = - ( - $20ac, $fffd, $201a, $0192, $201e, $2026, $2020, $2021, - $fffd, $2030, $fffd, $2039, $fffd, $fffd, $fffd, $fffd, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $fffd, $2122, $fffd, $203a, $fffd, $fffd, $fffd, $fffd, - $00a0, $0385, $0386, $00a3, $00a4, $00a5, $00a6, $00a7, - $00a8, $00a9, $fffd, $00ab, $00ac, $00ad, $00ae, $2015, - $00b0, $00b1, $00b2, $00b3, $0384, $00b5, $00b6, $00b7, - $0388, $0389, $038a, $00bb, $038c, $00bd, $038e, $038f, - $0390, $0391, $0392, $0393, $0394, $0395, $0396, $0397, - $0398, $0399, $039a, $039b, $039c, $039d, $039e, $039f, - $03a0, $03a1, $fffd, $03a3, $03a4, $03a5, $03a6, $03a7, - $03a8, $03a9, $03aa, $03ab, $03ac, $03ad, $03ae, $03af, - $03b0, $03b1, $03b2, $03b3, $03b4, $03b5, $03b6, $03b7, - $03b8, $03b9, $03ba, $03bb, $03bc, $03bd, $03be, $03bf, - $03c0, $03c1, $03c2, $03c3, $03c4, $03c5, $03c6, $03c7, - $03c8, $03c9, $03ca, $03cb, $03cc, $03cd, $03ce, $fffd - ); - -{Turkish -} - CharCP_1254:array [128..255] of word = - ( - $20ac, $fffd, $201a, $0192, $201e, $2026, $2020, $2021, - $02c6, $2030, $0160, $2039, $0152, $fffd, $fffd, $fffd, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $02dc, $2122, $0161, $203a, $0153, $fffd, $fffd, $0178, - $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, - $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, - $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, - $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, - $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, - $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, - $011e, $00d1, $00d2, $00d3, $00d4, $00d5, $00d6, $00d7, - $00d8, $00d9, $00da, $00db, $00dc, $0130, $015e, $00df, - $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, - $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, - $011f, $00f1, $00f2, $00f3, $00f4, $00f5, $00f6, $00f7, - $00f8, $00f9, $00fa, $00fb, $00fc, $0131, $015f, $00ff - ); - -{Hebrew -} - CharCP_1255:array [128..255] of word = - ( - $20ac, $fffd, $201a, $0192, $201e, $2026, $2020, $2021, - $02c6, $2030, $fffd, $2039, $fffd, $fffd, $fffd, $fffd, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $02dc, $2122, $fffd, $203a, $fffd, $fffd, $fffd, $fffd, - $00a0, $00a1, $00a2, $00a3, $20aa, $00a5, $00a6, $00a7, - $00a8, $00a9, $00d7, $00ab, $00ac, $00ad, $00ae, $00af, - $00b0, $00b1, $00b2, $00b3, $00b4, $00b5, $00b6, $00b7, - $00b8, $00b9, $00f7, $00bb, $00bc, $00bd, $00be, $00bf, - $05b0, $05b1, $05b2, $05b3, $05b4, $05b5, $05b6, $05b7, - $05b8, $05b9, $fffd, $05bb, $05bc, $05bd, $05be, $05bf, - $05c0, $05c1, $05c2, $05c3, $05f0, $05f1, $05f2, $05f3, - $05f4, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, $fffd, - $05d0, $05d1, $05d2, $05d3, $05d4, $05d5, $05d6, $05d7, - $05d8, $05d9, $05da, $05db, $05dc, $05dd, $05de, $05df, - $05e0, $05e1, $05e2, $05e3, $05e4, $05e5, $05e6, $05e7, - $05e8, $05e9, $05ea, $fffd, $fffd, $200e, $200f, $fffd - ); - -{Arabic -} - CharCP_1256:array [128..255] of word = - ( - $20ac, $067e, $201a, $0192, $201e, $2026, $2020, $2021, - $02c6, $2030, $0679, $2039, $0152, $0686, $0698, $0688, - $06af, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $06a9, $2122, $0691, $203a, $0153, $200c, $200d, $06ba, - $00a0, $060c, $00a2, $00a3, $00a4, $00a5, $00a6, $00a7, - $00a8, $00a9, $06be, $00ab, $00ac, $00ad, $00ae, $00af, - $00b0, $00b1, $00b2, $00b3, $00b4, $00b5, $00b6, $00b7, - $00b8, $00b9, $061b, $00bb, $00bc, $00bd, $00be, $061f, - $06c1, $0621, $0622, $0623, $0624, $0625, $0626, $0627, - $0628, $0629, $062a, $062b, $062c, $062d, $062e, $062f, - $0630, $0631, $0632, $0633, $0634, $0635, $0636, $00d7, - $0637, $0638, $0639, $063a, $0640, $0641, $0642, $0643, - $00e0, $0644, $00e2, $0645, $0646, $0647, $0648, $00e7, - $00e8, $00e9, $00ea, $00eb, $0649, $064a, $00ee, $00ef, - $064b, $064c, $064d, $064e, $00f4, $064f, $0650, $00f7, - $0651, $00f9, $0652, $00fb, $00fc, $200e, $200f, $06d2 - ); - -{Baltic -} - CharCP_1257:array [128..255] of word = - ( - $20ac, $fffd, $201a, $fffd, $201e, $2026, $2020, $2021, - $fffd, $2030, $fffd, $2039, $fffd, $00a8, $02c7, $00b8, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $fffd, $2122, $fffd, $203a, $fffd, $00af, $02db, $fffd, - $00a0, $fffd, $00a2, $00a3, $00a4, $fffd, $00a6, $00a7, - $00d8, $00a9, $0156, $00ab, $00ac, $00ad, $00ae, $00c6, - $00b0, $00b1, $00b2, $00b3, $00b4, $00b5, $00b6, $00b7, - $00f8, $00b9, $0157, $00bb, $00bc, $00bd, $00be, $00e6, - $0104, $012e, $0100, $0106, $00c4, $00c5, $0118, $0112, - $010c, $00c9, $0179, $0116, $0122, $0136, $012a, $013b, - $0160, $0143, $0145, $00d3, $014c, $00d5, $00d6, $00d7, - $0172, $0141, $015a, $016a, $00dc, $017b, $017d, $00df, - $0105, $012f, $0101, $0107, $00e4, $00e5, $0119, $0113, - $010d, $00e9, $017a, $0117, $0123, $0137, $012b, $013c, - $0161, $0144, $0146, $00f3, $014d, $00f5, $00f6, $00f7, - $0173, $0142, $015b, $016b, $00fc, $017c, $017e, $02d9 - ); - -{?? -} - CharCP_1258:array [128..255] of word = - ( - $20ac, $fffd, $201a, $0192, $201e, $2026, $2020, $2021, - $02c6, $2030, $fffd, $2039, $0152, $fffd, $fffd, $fffd, - $fffd, $2018, $2019, $201c, $201d, $2022, $2013, $2014, - $02dc, $2122, $fffd, $203a, $0153, $fffd, $fffd, $0178, - $00a0, $00a1, $00a2, $00a3, $00a4, $00a5, $00a6, $00a7, - $00a8, $00a9, $00aa, $00ab, $00ac, $00ad, $00ae, $00af, - $00b0, $00b1, $00b2, $00b3, $00b4, $00b5, $00b6, $00b7, - $00b8, $00b9, $00ba, $00bb, $00bc, $00bd, $00be, $00bf, - $00c0, $00c1, $00c2, $0102, $00c4, $00c5, $00c6, $00c7, - $00c8, $00c9, $00ca, $00cb, $0300, $00cd, $00ce, $00cf, - $0110, $00d1, $0309, $00d3, $00d4, $01a0, $00d6, $00d7, - $00d8, $00d9, $00da, $00db, $00dc, $01af, $0303, $00df, - $00e0, $00e1, $00e2, $0103, $00e4, $00e5, $00e6, $00e7, - $00e8, $00e9, $00ea, $00eb, $0301, $00ed, $00ee, $00ef, - $0111, $00f1, $0323, $00f3, $00f4, $01a1, $00f6, $00f7, - $00f8, $00f9, $00fa, $00fb, $00fc, $01b0, $20ab, $00ff - ); - -{Cyrillic -} - CharKOI8_R:array [128..255] of word = - ( - $2500, $2502, $250c, $2510, $2514, $2518, $251c, $2524, - $252c, $2534, $253c, $2580, $2584, $2588, $258c, $2590, - $2591, $2592, $2593, $2320, $25a0, $2219, $221a, $2248, - $2264, $2265, $00a0, $2321, $00b0, $00b2, $00b7, $00f7, - $2550, $2551, $2552, $0451, $2553, $2554, $2555, $2556, - $2557, $2558, $2559, $255a, $255b, $255c, $255d, $255e, - $255f, $2560, $2561, $0401, $2562, $2563, $2564, $2565, - $2566, $2567, $2568, $2569, $256a, $256b, $256c, $00a9, - $044e, $0430, $0431, $0446, $0434, $0435, $0444, $0433, - $0445, $0438, $0439, $043a, $043b, $043c, $043d, $043e, - $043f, $044f, $0440, $0441, $0442, $0443, $0436, $0432, - $044c, $044b, $0437, $0448, $044d, $0449, $0447, $044a, - $042e, $0410, $0411, $0426, $0414, $0415, $0424, $0413, - $0425, $0418, $0419, $041a, $041b, $041c, $041d, $041e, - $041f, $042f, $0420, $0421, $0422, $0423, $0416, $0412, - $042c, $042b, $0417, $0428, $042d, $0429, $0427, $042a - ); - -{==============================================================================} -Function UTF8toUCS4 (value:string):string; -Function UCS4toUTF8 (value:string):string; -Function UTF7toUCS2 (value:string):string; -Function UCS2toUTF7 (value:string):string; -Function DecodeChar(value:string;CharFrom:TMimeChar;CharTo:TMimeChar):string; -Function GetCurCP:TMimeChar; -Function GetCPfromID(value:string):TMimeChar; -Function GetIDfromCP(value:TMimeChar):string; -Function NeedEncode(value:string):boolean; -Function IdealCoding(value:string;CharFrom:TMimeChar;CharTo:TSetChar):TMimeChar; - -{==============================================================================} -implementation - -uses -{$IFNDEF LINUX} - windows, -{$ENDIF} - sysutils, synautil, synacode; - -{==============================================================================} -procedure CopyArray(const SourceTable:array of word; var TargetTable:array of word); -var - n:integer; -begin - for n:=0 to 127 do - TargetTable[n]:=SourceTable[n]; -end; - -{==============================================================================} -procedure GetArray(CharSet:TMimeChar; var result:array of word); -begin - case CharSet of - ISO_8859_1: CopyArray(CharISO_8859_1,Result); - ISO_8859_2: CopyArray(CharISO_8859_2,Result); - ISO_8859_3: CopyArray(CharISO_8859_3,Result); - ISO_8859_4: CopyArray(CharISO_8859_4,Result); - ISO_8859_5: CopyArray(CharISO_8859_5,Result); - ISO_8859_6: CopyArray(CharISO_8859_6,Result); - ISO_8859_7: CopyArray(CharISO_8859_7,Result); - ISO_8859_8: CopyArray(CharISO_8859_8,Result); - ISO_8859_9: CopyArray(CharISO_8859_9,Result); - ISO_8859_10: CopyArray(CharISO_8859_10,Result); - CP1250: CopyArray(CharCP_1250,Result); - CP1251: CopyArray(CharCP_1251,Result); - CP1252: CopyArray(CharCP_1252,Result); - CP1253: CopyArray(CharCP_1253,Result); - CP1254: CopyArray(CharCP_1254,Result); - CP1255: CopyArray(CharCP_1255,Result); - CP1256: CopyArray(CharCP_1256,Result); - CP1257: CopyArray(CharCP_1257,Result); - CP1258: CopyArray(CharCP_1258,Result); - KOI8_R: CopyArray(CharKOI8_R,Result); - end; -end; - -{==============================================================================} -procedure ReadMulti(value:string; var index:integer; mb:byte; - var b1,b2,b3,b4:byte); -var - b:array[0..3] of byte; - n:integer; - s:string; -begin - b[0]:=0; - b[1]:=0; - b[2]:=0; - b[3]:=0; - if (length(value)+1)=n do - begin - x:=ord(value[n]); - inc(n); - if x<128 - then result:=result+writemulti(x,0,0,0,4) - else - begin - m:=0; - if (x and $E0)=$C0 then m:=$1F; - if (x and $F0)=$E0 then m:=$0F; - if (x and $F8)=$F0 then m:=$07; - if (x and $FC)=$F8 then m:=$03; - if (x and $FE)=$FC then m:=$01; - ul:=x and m; - s:=inttobin(ul,0); - while length(value)>=n do - begin - x:=ord(value[n]); - inc(n); - if (x and $C0)=$80 - then s:=s+inttobin(x and $3F, 6) - else - begin - dec(n); - break; - end; - end; - ul:=bintoint(s); - w1:=ul div 65536; - w2:=ul mod 65536; - result:=result+writemulti(lo(w2),hi(w2),lo(w1),hi(w1),4); - end; - end; -end; - -{==============================================================================} -function UCS4toUTF8 (value:string):string; -var - s,l,k:string; - b1,b2,b3,b4:byte; - n,m,x,y:integer; - b:byte; -begin - result:=''; - n:=1; - while length(value)>=n do - begin - readmulti(value,n,4,b1,b2,b3,b4); - if (b2=0) and (b3=0) and (b4=0) - then result:=result+char(b1) - else - begin - x:=(b1+256*b2)+(b3+256*b4)*65536; - l:=inttobin(x,0); - y:=length(l) div 6; - s:=''; - for m:=1 to y do - begin - k:=copy(l,length(l)-5,6); - l:=copy(l,1,length(l)-6); - b:=bintoint(k) or $80; - s:=char(b)+s; - end; - b:=bintoint(l); - case y of - 5: b:=b or $FC; - 4: b:=b or $F8; - 3: b:=b or $F0; - 2: b:=b or $E0; - 1: b:=b or $C0; - end; - s:=char(b)+s; - result:=result+s; - end; - end; -end; - -{==============================================================================} -function UTF7toUCS2(value:string):string; -var - n:integer; - c:char; - s:string; -begin - result:=''; - n:=1; - while length(value)>=n do - begin - c:=value[n]; - inc(n); - if c<>'+' - then result:=result+writemulti(ord(c),0,0,0,2) - else - begin - s:=''; - while length(value)>=n do - begin - c:=value[n]; - inc(n); - if c='-' - then break; - if (c='=') or (pos(c,TableBase64)<1) then - begin - dec(n); - break; - end; - s:=s+c; - end; - if s='' - then s:='+' - else s:=DecodeBase64(s); - result:=result+s; - end; - end; -end; - -{==============================================================================} -Function UCS2toUTF7 (value:string):string; -var - s:string; - b1,b2,b3,b4:byte; - n,m:integer; -begin - result:=''; - n:=1; - while length(value)>=n do - begin - readmulti(value,n,2,b1,b2,b3,b4); - if (b2=0) - then if char(b1)='+' - then result:=result+'+-' - else result:=result+char(b1) - else - begin - s:=char(b2)+char(b1); - while length(value)>=n do - begin - readmulti(value,n,2,b1,b2,b3,b4); - if b2=0 then - begin - dec(n,2); - break; - end; - s:=s+char(b2)+char(b1); - end; - s:=EncodeBase64(s); - m:=pos('=',s); - if m>0 then - s:=copy(s,1,m-1); - result:=result+'+'+s+'-'; - end; - end; -end; - -{==============================================================================} -{DecodeChar} -Function DecodeChar(value:string;CharFrom:TMimeChar;CharTo:TMimeChar):string; -var - uni:word; - n,m:integer; - b:byte; - b1,b2,b3,b4:byte; - SourceTable,TargetTable:array [128..255] of word; - mbf,mbt:byte; -begin - GetArray(CharFrom,SourceTable); - GetArray(CharTo,TargetTable); - mbf:=1; - if CharFrom in SetTwo - then mbf:=2; - if CharFrom in SetFour - then mbf:=4; - mbt:=1; - if CharTo in SetTwo - then mbt:=2; - if CharTo in SetFour - then mbt:=4; - - if Charfrom=UTF_8 - then value:=UTF8toUCS4(value); - if Charfrom=UTF_7 - then value:=UTF7toUCS2(value); - result:=''; - - n:=1; - while length(value)>=n do - begin - Readmulti(value,n,mbf,b1,b2,b3,b4); - if mbf=1 then - if b1>127 then - begin - uni:=SourceTable[b1]; - b1:=lo(uni); - b2:=hi(uni); - end; - //b1..b4 - unicode char - uni:=b2*256+b1; - if (b3<>0) or (b4<>0) - then - begin - b1:=ord(NotFoundChar); - b2:=0; - b3:=0; - b4:=0; - end - else - if mbt=1 then - if uni>127 then - begin - b:=ord(NotFoundChar); - for m:=128 to 255 do - if TargetTable[m]=uni - then - begin - b:=m; - break; - end; - b1:=b; - b2:=0; - end - else b1:=lo(uni); - result:=result+writemulti(b1,b2,b3,b4,mbt) - end; - - if CharTo=UTF_7 - then result:=UCS2toUTF7(result); - if CharTo=UTF_8 - then result:=UCS4toUTF8(result); - -end; - -{==============================================================================} -{GetCurChar} -Function GetCurCP:TMimeChar; -{$IFDEF LINUX} -begin - result:=GetCPFromID(nl_langinfo(_NL_CTYPE_CODESET_NAME)); -{$ELSE} -var - x:integer; -begin - x:=getACP; - result:=CP1252; - if x=1250 then result:=CP1250; - if x=1251 then result:=CP1251; - if x=1253 then result:=CP1253; - if x=1254 then result:=CP1254; - if x=1255 then result:=CP1255; - if x=1256 then result:=CP1256; - if x=1257 then result:=CP1257; - if x=1258 then result:=CP1258; -{$ENDIF} -end; - -{==============================================================================} -{GetCpfromID} -Function GetCPfromID(value:string):TMimeChar; -begin - value:=uppercase(value); - Result:=ISO_8859_1; - if Pos('ISO-8859-10',value)=1 then - begin - Result:=ISO_8859_10; - exit; - end; - if Pos('ISO-8859-2',value)=1 then - begin - Result:=ISO_8859_2; - exit; - end; - if Pos('ISO-8859-3',value)=1 then - begin - Result:=ISO_8859_3; - exit; - end; - if Pos('ISO-8859-4',value)=1 then - begin - Result:=ISO_8859_4; - exit; - end; - if Pos('ISO-8859-5',value)=1 then - begin - Result:=ISO_8859_5; - exit; - end; - if Pos('ISO-8859-6',value)=1 then - begin - Result:=ISO_8859_6; - exit; - end; - if Pos('ISO-8859-7',value)=1 then - begin - Result:=ISO_8859_7; - exit; - end; - if Pos('ISO-8859-8',value)=1 then - begin - Result:=ISO_8859_8; - exit; - end; - if Pos('ISO-8859-9',value)=1 then - begin - Result:=ISO_8859_9; - exit; - end; - if (Pos('WINDOWS-1250',value)=1) or - (Pos('X-CP1250',value)=1) then - begin - Result:=CP1250; - exit; - end; - if (Pos('WINDOWS-1251',value)=1) or - (Pos('X-CP1251',value)=1) then - begin - Result:=CP1251; - exit; - end; - if (Pos('WINDOWS-1252',value)=1) or - (Pos('X-CP1252',value)=1) then - begin - Result:=CP1252; - exit; - end; - if (Pos('WINDOWS-1253',value)=1) or - (Pos('X-CP1253',value)=1) then - begin - Result:=CP1253; - exit; - end; - if (Pos('WINDOWS-1254',value)=1) or - (Pos('X-CP1254',value)=1) then - begin - Result:=CP1254; - exit; - end; - if (Pos('WINDOWS-1255',value)=1) or - (Pos('X-CP1255',value)=1) then - begin - Result:=CP1255; - exit; - end; - if (Pos('WINDOWS-1256',value)=1) or - (Pos('X-CP1256',value)=1) then - begin - Result:=CP1256; - exit; - end; - if (Pos('WINDOWS-1257',value)=1) or - (Pos('X-CP1257',value)=1) then - begin - Result:=CP1257; - exit; - end; - if (Pos('WINDOWS-1258',value)=1) or - (Pos('X-CP1258',value)=1) then - begin - Result:=CP1258; - exit; - end; - if Pos('KOI8-R',value)=1 then - begin - Result:=KOI8_R; - exit; - end; - if Pos('UTF-7',value)=1 then - begin - Result:=UTF_7; - exit; - end; - if Pos('UTF-8',value)>0 then - begin - Result:=UTF_8; - exit; - end; - if Pos('UCS-4',value)>0 then - begin - Result:=UCS_4; - exit; - end; - if Pos('UCS-2',value)>0 then - begin - Result:=UCS_2; - exit; - end; - if Pos('UNICODE',value)=1 then - begin - Result:=UCS_2; - exit; - end; -end; - -{==============================================================================} -Function GetIDfromCP(value:TMimeChar):string; -begin - case Value of - ISO_8859_2 : result:='ISO-8859-2'; - ISO_8859_3 : result:='ISO-8859-3'; - ISO_8859_4 : result:='ISO-8859-4'; - ISO_8859_5 : result:='ISO-8859-5'; - ISO_8859_6 : result:='ISO-8859-6'; - ISO_8859_7 : result:='ISO-8859-7'; - ISO_8859_8 : result:='ISO-8859-8'; - ISO_8859_9 : result:='ISO-8859-9'; - ISO_8859_10: result:='ISO-8859-10'; - CP1250 : result:='WINDOWS-1250'; - CP1251 : result:='WINDOWS-1251'; - CP1252 : result:='WINDOWS-1252'; - CP1253 : result:='WINDOWS-1253'; - CP1254 : result:='WINDOWS-1254'; - CP1255 : result:='WINDOWS-1255'; - CP1256 : result:='WINDOWS-1256'; - CP1257 : result:='WINDOWS-1257'; - CP1258 : result:='WINDOWS-1258'; - KOI8_R : result:='KOI8-R'; - UCS_2 : result:='Unicode-1-1-UCS-2'; - UCS_4 : result:='Unicode-1-1-UCS-4'; - UTF_8 : result:='UTF-8'; - UTF_7 : result:='UTF-7'; - else result:='ISO-8859-1'; - end; -end; - -{==============================================================================} -Function NeedEncode(value:string):boolean; -var - n:integer; -begin - result:=false; - for n:=1 to length(value) do - if ord(value[n])>127 then - begin - result:=true; - break; - end; -end; - -{==============================================================================} -Function IdealCoding(value:string;CharFrom:TMimeChar;CharTo:TSetChar):TMimeChar; -var - n,m:integer; - min,x:integer; - s,t:string; -begin - result:=ISO_8859_1; - s:=''; - for n:=1 to length(value) do - if ord(value[n])>127 then - s:=s+value[n]; - min:=128; - for n:=ord(low(TMimeChar)) to ord(high(TMimeChar)) do - if TMimechar(n) in CharTo then - begin - t:=Decodechar(s,CharFrom,TMimechar(n)); - x:=0; - for m:=1 to length(t) do - if t[m]=NotFoundChar - then inc(x); - if x 2) and (Value[n + 1] = '=') then begin - inc(q); - if (q>2) and (value[n+1]='=') then - begin - result:=n; - break; - end; + Result := n; + Break; end; + end; end; begin - result:=value; - x:=pos('=?',result); - y:=SearchEndInline(result,x); - while y>x do + Result := Value; + x := Pos('=?', Result); + y := SearchEndInline(Result, x); + while y > x do + begin + s := Copy(Result, x, y - x + 2); + su := Copy(s, 3, Length(s) - 4); + ichar := GetCPFromID(su); + z := Pos('?', su); + if (Length(su) >= (z + 2)) and (su[z + 2] = '?') then begin - s:=copy(result,x,y-x+2); - su:=copy(s,3,length(s)-4); - ichar:=GetCPfromID(su); - z:=pos('?',su); - if (length(su)>=(z+2)) and (su[z+2]='?') then - begin - c:=uppercase(su)[z+1]; - su:=copy(su,z+3,length(su)-z-2); - if c='B' then - begin - s:=DecodeBase64(su); - s:=DecodeChar(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:=DecodeChar(s,ichar,CP); - end; - end; - result:=copy(result,1,x-1)+s+copy(result,y+2,length(result)-y-1); - x:=pos('=?',result); - y:=SearchEndInline(result,x); + 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 := Copy(Result, 1, x - 1) + s + + Copy(Result, y + 2, Length(Result) - y - 1); + x := Pos('=?', Result); + y := SearchEndInline(Result, x); + end; +end; + +{==============================================================================} + +function InlineEncode(const Value: string; CP, MimeP: TMimeChar): string; +var + s, s1: string; + n: Integer; +begin + s := CharsetConversion(Value, CP, MimeP); + s := EncodeQuotedPrintable(s); + s1 := ''; + for n := 1 to Length(s) do + if s[n] = ' ' then + s1 := s1 + '=20' + else + s1 := s1 + s[n]; + Result := '=?' + GetIdFromCP(MimeP) + '?Q?' + s1 + '?='; +end; + +{==============================================================================} + +function NeedInline(const Value: string): boolean; +var + n: Integer; +begin + Result := False; + for n := 1 to Length(Value) do + if Value[n] in (SpecialChar + [Char(1)..Char(31), Char(128)..Char(255)]) then + begin + Result := True; + Break; end; end; {==============================================================================} -{InlineEncode} -function InlineEncode(value:string;CP,MimeP:TMimeChar):string; -var - s,s1:string; - n:integer; -begin - s:=DecodeChar(value,CP,MimeP); - s:=EncodeQuotedPrintable(s); - s1:=''; - for n:=1 to length(s) do - if s[n]=' ' - then s1:=s1+'=20' - else s1:=s1+s[n]; - result:='=?'+GetIdFromCP(MimeP)+'?Q?'+s1+'?='; -end; -{==============================================================================} -{NeedInline} -Function NeedInline(value:string):boolean; +function InlineCode(const Value: string): string; var - n:integer; + c: TMimeChar; begin - result:=false; - for n:=1 to length(value) do - if value[n] in (SpecialChar+[char(1)..char(31),char(128)..char(255)]) then - begin - result:=true; - break; - end; -end; - -{==============================================================================} -{InlineCode} -function InlineCode(value:string):string; -var - c:TMimeChar; -begin - if NeedInline(value) - then - begin - c:=IdealCoding(value,GetCurCP, - [ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5, - ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10]); - result:=InlineEncode(value,GetCurCP,c); - end - else result:=value; -end; - -{==============================================================================} -{InlineEmail} -function InlineEmail(value:string):string; -var - sd,se:string; -begin - sd:=getEmaildesc(value); - se:=getEmailAddr(value); - if sd='' - then result:=se - else result:='"'+InlineCode(sd)+'"<'+se+'>'; + if NeedInline(Value) then + begin + c := IdealCharsetCoding(Value, GetCurCP, + [ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5, + ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10]); + Result := InlineEncode(Value, GetCurCP, c); + end + else + Result := Value; end; {==============================================================================} +function InlineEmail(const Value: string): string; +var + sd, se: string; begin - exit; - asm - db 'Synapse Inline MIME encoding and decoding library by Lukas Gebauer',0 - end; + sd := GetEmailDesc(Value); + se := GetEmailAddr(Value); + if sd = '' then + Result := se + else + Result := '"' + InlineCode(sd) + '"<' + se + '>'; +end; + end. diff --git a/mimemess.pas b/mimemess.pas index 804e8b9..834acd7 100644 --- a/mimemess.pas +++ b/mimemess.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.003.000 | +| Project : Delphree - Synapse | 001.004.000 | |==============================================================================| | Content: MIME message object | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are Subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -19,314 +19,334 @@ |==============================================================================| | Contributor(s): | |==============================================================================| -| History: see HISTORY.HTM from distribution package | +| History: see HISTORY.HTM From distribution package | | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} +{$WEAKPACKAGEUNIT ON} unit MIMEmess; interface uses - classes, Sysutils, MIMEpart, MimeChar, SynaUtil, MIMEInLn; + Classes, SysUtils, + MIMEpart, SynaChar, SynaUtil, MIMEinLn; type - -TMessHeader=record - from:string; - ToList:tstringlist; - subject:string; - organization:string; -end; - -TMimeMess=class(TObject) + TMessHeader = class(TObject) private + FFrom: string; + FToList: TStringList; + FSubject: string; + FOrganization: string; public - PartList:TList; - Lines:TStringList; - header:TMessHeader; constructor Create; destructor Destroy; override; procedure Clear; - function AddPart:integer; - procedure AddPartText(value:tstringList); - procedure AddPartHTML(value:tstringList); - procedure AddPartHTMLBinary(Value,Cid:string); - procedure AddPartBinary(value:string); + published + property From: string read FFrom Write FFrom; + property ToList: TStringList read FToList Write FToList; + property Subject: string read FSubject Write FSubject; + property Organization: string read FOrganization Write FOrganization; + end; + + TMimeMess = class(TObject) + private + FPartList: TList; + FLines: TStringList; + FHeader: TMessHeader; + public + constructor Create; + destructor Destroy; override; + procedure Clear; + function AddPart: Integer; + procedure AddPartText(Value: TStringList); + procedure AddPartHTML(Value: TStringList); + procedure AddPartHTMLBinary(Value, Cid: string); + procedure AddPartBinary(Value: string); procedure EncodeMessage; procedure FinalizeHeaders; procedure ParseHeaders; procedure DecodeMessage; -end; + published + property PartList: TList read FPartList Write FPartList; + property Lines: TStringList read FLines Write FLines; + property Header: TMessHeader read FHeader Write FHeader; + end; implementation {==============================================================================} -{TMimeMess.Create} -Constructor TMimeMess.Create; + +constructor TMessHeader.Create; begin inherited Create; - PartList:=TList.create; - Lines:=TStringList.create; - Header.ToList:=TStringList.create; + FToList := TStringList.Create; end; -{TMimeMess.Destroy} -Destructor TMimeMess.Destroy; +destructor TMessHeader.Destroy; begin - Header.ToList.free; - Lines.free; - PartList.free; - inherited destroy; + FToList.Free; + inherited Destroy; end; {==============================================================================} -{TMimeMess.Clear} + +procedure TMessHeader.Clear; +begin + FFrom := ''; + FToList.Clear; + FSubject := ''; + FOrganization := ''; +end; + +{==============================================================================} + +constructor TMimeMess.Create; +begin + inherited Create; + FPartList := TList.Create; + FLines := TStringList.Create; + FHeader := TMessHeader.Create; +end; + +destructor TMimeMess.Destroy; +begin + FHeader.Free; + Lines.Free; + PartList.Free; + inherited Destroy; +end; + +{==============================================================================} + procedure TMimeMess.Clear; var - n:integer; + n: Integer; begin - Lines.clear; - for n:=0 to PartList.count-1 do + Lines.Clear; + for n := 0 to PartList.Count - 1 do TMimePart(PartList[n]).Free; PartList.Clear; - with header do - begin - from:=''; - ToList.clear; - subject:=''; - organization:=''; - end; + FHeader.Clear; end; {==============================================================================} -{TMimeMess.AddPart} -function TMimeMess.AddPart:integer; + +function TMimeMess.AddPart: Integer; var - mp:TMimePart; + mp: TMimePart; begin - mp:=TMimePart.create; - result:=PartList.Add(mp); + mp := TMimePart.Create; + Result := PartList.Add(mp); end; {==============================================================================} -{TMimeMess.AddPartText} -procedure TMimeMess.AddPartText(value:tstringList); + +procedure TMimeMess.AddPartText(Value: TStringList); var - x:integer; + x: Integer; begin - x:=Addpart; + x := AddPart; with TMimePart(PartList[x]) do - begin - value.SaveToStream(decodedlines); - primary:='text'; - secondary:='plain'; - description:='Message text'; - disposition:='inline'; - CharsetCode:=IdealCoding(value.text,targetCharset, - [ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5, - ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10]); - EncodingCode:=ME_QUOTED_PRINTABLE; - EncodePart; - end; -end; - -{==============================================================================} -{TMimeMess.AddPartHTML} -procedure TMimeMess.AddPartHTML(value:tstringList); -var - x:integer; -begin - x:=Addpart; - with TMimePart(PartList[x]) do - begin - value.SaveToStream(decodedlines); - primary:='text'; - secondary:='html'; - description:='HTML text'; - disposition:='inline'; - CharsetCode:=UTF_8; - EncodingCode:=ME_QUOTED_PRINTABLE; - EncodePart; - end; -end; - -{==============================================================================} -{TMimeMess.AddPartBinary} -procedure TMimeMess.AddPartBinary(value:string); -var - x:integer; - s:string; -begin - x:=Addpart; - with TMimePart(PartList[x]) do - begin - DecodedLines.LoadFromFile(Value); - s:=ExtractFileName(value); - MimeTypeFromExt(s); - description:='Attached file: '+s; - disposition:='attachment'; - filename:=s; - EncodingCode:=ME_BASE64; - EncodePart; - end; -end; - -{TMimeMess.AddPartHTMLBinary} -procedure TMimeMess.AddPartHTMLBinary(Value,Cid:string); -var - x:integer; - s:string; -begin - x:=Addpart; - with TMimePart(PartList[x]) do - begin - DecodedLines.LoadFromFile(Value); - s:=ExtractFileName(value); - MimeTypeFromExt(s); - description:='Included file: '+s; - disposition:='inline'; - contentID:=cid; - filename:=s; - EncodingCode:=ME_BASE64; - EncodePart; - end; -end; - -{==============================================================================} -{TMimeMess.Encodemessage} -procedure TMimeMess.Encodemessage; -var - bound:string; - n:integer; - m:TMimepart; -begin - lines.clear; - If PartList.Count=1 - then - Lines.assign(TMimePart(PartList[0]).lines) - else - begin - bound:=generateboundary; - for n:=0 to PartList.count-1 do - begin - Lines.add('--'+bound); - lines.AddStrings(TMimePart(PartList[n]).lines); - end; - Lines.add('--'+bound); - m:=TMimePart.Create; - try - Lines.SaveToStream(m.DecodedLines); - m.Primary:='Multipart'; - m.secondary:='mixed'; - m.description:='Multipart message'; - m.boundary:=bound; - m.EncodePart; - Lines.assign(m.lines); - finally - m.free; - end; - end; -end; - -{==============================================================================} -{TMimeMess.FinalizeHeaders} -procedure TMimeMess.FinalizeHeaders; -var - n:integer; -begin - Lines.Insert(0,'x-mailer: Synapse - Delphi TCP/IP library by Lukas Gebauer'); - Lines.Insert(0,'MIME-Version: 1.0 (produced by Synapse)'); - Lines.Insert(0,'date: '+Rfc822DateTime(now)); - if header.organization<>'' - then Lines.Insert(0,'Organization: '+InlineCode(header.organization)); - if header.subject<>'' - then Lines.Insert(0,'Subject: '+InlineCode(header.subject)); - for n:=0 to Header.ToList.count-1 do - Lines.Insert(0,'To: '+InlineEmail(header.ToList[n])); - Lines.Insert(0,'From: '+InlineEmail(header.from)); -end; - -{==============================================================================} -{TMimeMess.ParseHeaders} -procedure TMimeMess.ParseHeaders; -var - s:string; - x:integer; - cp:TMimeChar; -begin - cp:=getCurCP; - header.ToList.clear; - x:=0; - while lines.count>x do - begin - s:=normalizeheader(lines,x); - if s='' - then break; - If pos('FROM:',uppercase(s))=1 - then header.from:=InlineDecode(separateright(s,':'),cp); - If pos('SUBJECT:',uppercase(s))=1 - then header.subject:=InlineDecode(separateright(s,':'),cp); - If pos('ORGANIZATION:',uppercase(s))=1 - then header.organization:=InlineDecode(separateright(s,':'),cp); - If pos('TO:',uppercase(s))=1 - then header.ToList.add(InlineDecode(separateright(s,':'),cp)); - end; -end; - -{==============================================================================} -{TMimeMess.DecodeMessage} -procedure TMimeMess.DecodeMessage; -var - l:tstringlist; - m:tmimepart; - x,i:integer; - bound:string; -begin - l:=tstringlist.create; - m:=tmimepart.create; - try - l.assign(lines); - with header do - begin - from:=''; - ToList.clear; - subject:=''; - organization:=''; - end; - ParseHeaders; - m.ExtractPart(l,0); - if m.primarycode=MP_MULTIPART - then - begin - bound:=m.boundary; - i:=0; - repeat - x:=AddPart; - with TMimePart(PartList[x]) do - begin - boundary:=bound; - i:=ExtractPart(l,i); - DecodePart; - end; - until i>=l.count-2; - end - else - begin - x:=AddPart; - with TMimePart(PartList[x]) do - begin - ExtractPart(l,0); - DecodePart; - end; - end; - finally - m.free; - l.free; + begin + Value.SaveToStream(DecodedLines); + Primary := 'text'; + Secondary := 'plain'; + Description := 'Message text'; + Disposition := 'inline'; + CharsetCode := IdealCharsetCoding(Value.Text, TargetCharset, + [ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5, + ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10]); + EncodingCode := ME_QUOTED_PRINTABLE; + EncodePart; end; end; {==============================================================================} +procedure TMimeMess.AddPartHTML(Value: TStringList); +var + x: Integer; +begin + x := AddPart; + with TMimePart(PartList[x]) do + begin + Value.SaveToStream(DecodedLines); + Primary := 'text'; + Secondary := 'html'; + Description := 'HTML text'; + Disposition := 'inline'; + CharsetCode := UTF_8; + EncodingCode := ME_QUOTED_PRINTABLE; + EncodePart; + end; +end; + +{==============================================================================} + +procedure TMimeMess.AddPartBinary(Value: string); +var + x: Integer; + s: string; +begin + x := AddPart; + with TMimePart(PartList[x]) do + begin + DecodedLines.LoadFromFile(Value); + s := ExtractFileName(Value); + MimeTypeFromExt(s); + Description := 'Attached file: ' + s; + Disposition := 'attachment'; + FileName := s; + EncodingCode := ME_BASE64; + EncodePart; + end; +end; + +procedure TMimeMess.AddPartHTMLBinary(Value, Cid: string); +var + x: Integer; + s: string; +begin + x := AddPart; + with TMimePart(PartList[x]) do + begin + DecodedLines.LoadFromFile(Value); + s := ExtractFileName(Value); + MimeTypeFromExt(s); + Description := 'Included file: ' + s; + Disposition := 'inline'; + ContentID := cid; + FileName := s; + EncodingCode := ME_BASE64; + EncodePart; + end; +end; + +{==============================================================================} + +procedure TMimeMess.EncodeMessage; +var + bound: string; + n: Integer; +begin + Lines.Clear; + if PartList.Count = 1 then + Lines.Assign(TMimePart(PartList[0]).Lines) + else + begin + bound := GenerateBoundary; + for n := 0 to PartList.Count - 1 do + begin + Lines.Add('--' + bound); + Lines.AddStrings(TMimePart(PartList[n]).Lines); + end; + Lines.Add('--' + bound); + with TMimePart.Create do + try + Self.Lines.SaveToStream(DecodedLines); + Primary := 'Multipart'; + Secondary := 'mixed'; + Description := 'Multipart message'; + Boundary := bound; + EncodePart; + Self.Lines.Assign(Lines); + finally + Free; + end; + end; +end; + +{==============================================================================} + +procedure TMimeMess.FinalizeHeaders; +var + n: Integer; +begin + Lines.Insert(0, 'x-mailer: Synapse - Delphi TCP/IP library by Lukas Gebauer'); + Lines.Insert(0, 'MIME-Version: 1.0 (produced by Synapse)'); + Lines.Insert(0, 'date: ' + Rfc822DateTime(Now)); + if FHeader.Organization <> '' then + Lines.Insert(0, 'Organization: ' + InlineCode(Header.Organization)); + if Header.Subject <> '' then + FLines.Insert(0, 'Subject: ' + InlineCode(Header.Subject)); + for n := 0 to FHeader.ToList.Count - 1 do + Lines.Insert(0, 'To: ' + InlineEmail(FHeader.ToList[n])); + Lines.Insert(0, 'From: ' + InlineEmail(FHeader.From)); +end; + +{==============================================================================} + +procedure TMimeMess.ParseHeaders; +var + s: string; + x: Integer; + cp: TMimeChar; +begin + cp := GetCurCP; + FHeader.Clear; + x := 0; + while Lines.Count > x do + begin + s := NormalizeHeader(Lines, x); + if s = '' then + Break; + if Pos('FROM:', UpperCase(s)) = 1 then + FHeader.From := InlineDecode(SeparateRight(s, ':'), cp); + if Pos('SUBJECT:', UpperCase(s)) = 1 then + FHeader.Subject := InlineDecode(SeparateRight(s, ':'), cp); + if Pos('ORGANIZATION:', UpperCase(s)) = 1 then + FHeader.Organization := InlineDecode(SeparateRight(s, ':'), cp); + if Pos('TO:', UpperCase(s)) = 1 then + FHeader.ToList.Add(InlineDecode(SeparateRight(s, ':'), cp)); + end; +end; + +{==============================================================================} + +procedure TMimeMess.DecodeMessage; +var + l: TStringList; + m: TMimePart; + x, i: Integer; + bound: string; +begin + l := TStringList.Create; + m := TMimePart.Create; + try + l.Assign(Lines); + FHeader.Clear; + ParseHeaders; + m.ExtractPart(l, 0); + if m.PrimaryCode = MP_MULTIPART then + begin + bound := m.Boundary; + i := 0; + repeat + x := AddPart; + with TMimePart(PartList[x]) do + begin + Boundary := bound; + i := ExtractPart(l, i); + DecodePart; + end; + until i >= l.Count - 2; + end + else + begin + x := AddPart; + with TMimePart(PartList[x]) do + begin + ExtractPart(l, 0); + DecodePart; + end; + end; + finally + m.Free; + l.Free; + end; +end; + end. diff --git a/mimepart.pas b/mimepart.pas index 78564ff..4b22501 100644 --- a/mimepart.pas +++ b/mimepart.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.004.000 | +| Project : Delphree - Synapse | 001.004.001 | |==============================================================================| | Content: MIME support procedures and functions | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -28,553 +28,532 @@ unit MIMEpart; interface uses - sysutils, classes, MIMEchar, SynaCode, SynaUtil, MIMEinLn; + SysUtils, Classes, + SynaChar, SynaCode, SynaUtil, MIMEinLn; type -TMimePrimary=(MP_TEXT, - MP_MULTIPART, - MP_MESSAGE, - MP_BINARY); + TMimePrimary = (MP_TEXT, MP_MULTIPART, + MP_MESSAGE, MP_BINARY); -TMimeEncoding=(ME_7BIT, - ME_8BIT, - ME_QUOTED_PRINTABLE, - ME_BASE64, - ME_UU, - ME_XX); + TMimeEncoding = (ME_7BIT, ME_8BIT, ME_QUOTED_PRINTABLE, + ME_BASE64, ME_UU, ME_XX); -TMimePart=class + TMimePart = class(TObject) private - FPrimary:string; - FEncoding:string; - FCharset:string; - procedure Setprimary(Value:string); - procedure SetEncoding(Value:string); - procedure SetCharset(Value:string); - protected + FPrimary: string; + FEncoding: string; + FCharset: string; + FPrimaryCode: TMimePrimary; + FEncodingCode: TMimeEncoding; + FCharsetCode: TMimeChar; + FTargetCharset: TMimeChar; + FSecondary: string; + FDescription: string; + FDisposition: string; + FContentID: string; + FBoundary: string; + FFileName: string; + FLines: TStringList; + FDecodedLines: TMemoryStream; + procedure SetPrimary(Value: string); + procedure SetEncoding(Value: string); + procedure SetCharset(Value: string); public - PrimaryCode:TMimePrimary; - EncodingCode:TMimeEncoding; - CharsetCode:TMimeChar; - TargetCharset:TMimeChar; - secondary:string; - description:string; - disposition:string; - contentID:string; - boundary:string; - FileName:string; - Lines:TStringList; - DecodedLines:TmemoryStream; constructor Create; destructor Destroy; override; - procedure clear; - function ExtractPart(value:TStringList; BeginLine:integer):integer; + procedure Clear; + function ExtractPart(Value: TStringList; BeginLine: Integer): Integer; procedure DecodePart; procedure EncodePart; - procedure MimeTypeFromExt(value:string); - property - Primary:string read FPrimary Write SetPrimary; - property - encoding:string read FEncoding write SetEncoding; - property - Charset:string read FCharset write SetCharset; -end; + procedure MimeTypeFromExt(Value: string); + published + property Primary: string read FPrimary write SetPrimary; + property Encoding: string read FEncoding write SetEncoding; + property Charset: string read FCharset write SetCharset; + property PrimaryCode: TMimePrimary read FPrimaryCode Write FPrimaryCode; + property EncodingCode: TMimeEncoding read FEncodingCode Write FEncodingCode; + property CharsetCode: TMimeChar read FCharsetCode Write FCharsetCode; + property TargetCharset: TMimeChar read FTargetCharset Write FTargetCharset; + property Secondary: string read FSecondary Write FSecondary; + property Description: string read FDescription Write FDescription; + property Disposition: string read FDisposition Write FDisposition; + property ContentID: string read FContentID Write FContentID; + property Boundary: string read FBoundary Write FBoundary; + property FileName: string read FFileName Write FFileName; + property Lines: TStringList read FLines Write FLines; + property DecodedLines: TMemoryStream read FDecodedLines Write FDecodedLines; + end; const - MaxMimeType=25; - MimeType:array [0..MaxMimeType,0..2] of string= - ( - ('AU','audio','basic'), - ('AVI','video','x-msvideo'), - ('BMP','image','BMP'), - ('DOC','application','MSWord'), - ('EPS','application','Postscript'), - ('GIF','image','GIF'), - ('JPEG','image','JPEG'), - ('JPG','image','JPEG'), - ('MID','audio','midi'), - ('MOV','video','quicktime'), - ('MPEG','video','MPEG'), - ('MPG','video','MPEG'), - ('MP2','audio','mpeg'), - ('MP3','audio','mpeg'), - ('PDF','application','PDF'), - ('PNG','image','PNG'), - ('PS','application','Postscript'), - ('QT','video','quicktime'), - ('RA','audio','x-realaudio'), - ('RTF','application','RTF'), - ('SND','audio','basic'), - ('TIF','image','TIFF'), - ('TIFF','image','TIFF'), - ('WAV','audio','x-wav'), - ('WPD','application','Wordperfect5.1'), - ('ZIP','application','ZIP') + MaxMimeType = 25; + MimeType: array[0..MaxMimeType, 0..2] of string = + ( + ('AU', 'audio', 'basic'), + ('AVI', 'video', 'x-msvideo'), + ('BMP', 'image', 'BMP'), + ('DOC', 'application', 'MSWord'), + ('EPS', 'application', 'Postscript'), + ('GIF', 'image', 'GIF'), + ('JPEG', 'image', 'JPEG'), + ('JPG', 'image', 'JPEG'), + ('MID', 'audio', 'midi'), + ('MOV', 'video', 'quicktime'), + ('MPEG', 'video', 'MPEG'), + ('MPG', 'video', 'MPEG'), + ('MP2', 'audio', 'mpeg'), + ('MP3', 'audio', 'mpeg'), + ('PDF', 'application', 'PDF'), + ('PNG', 'image', 'PNG'), + ('PS', 'application', 'Postscript'), + ('QT', 'video', 'quicktime'), + ('RA', 'audio', 'x-realaudio'), + ('RTF', 'application', 'RTF'), + ('SND', 'audio', 'basic'), + ('TIF', 'image', 'TIFF'), + ('TIFF', 'image', 'TIFF'), + ('WAV', 'audio', 'x-wav'), + ('WPD', 'application', 'Wordperfect5.1'), + ('ZIP', 'application', 'ZIP') ); -function NormalizeHeader(value:TStringList;var index:integer):string; -function GenerateBoundary:string; +function NormalizeHeader(Value: TStringList; var Index: Integer): string; +function GenerateBoundary: string; implementation -function NormalizeHeader(value:TStringList;var index:integer):string; +function NormalizeHeader(Value: TStringList; var Index: Integer): string; var - s,t:string; - n:integer; + s, t: string; + n: Integer; begin - s:=value[index]; - inc(index); - if s<>'' - then - while (value.Count-1) > index do - begin - t:=value[index]; - if t='' - then break; - for n:=1 to length(t) do - if t[n]=#9 - then t[n]:=' '; - if t[1]<>' ' - then break - else - begin - s:=s+' '+trim(t); - inc(index); - end; - end; - result:=s; + s := Value[Index]; + Inc(Index); + if s <> '' then + while (Value.Count - 1) > Index do + begin + t := Value[Index]; + if t = '' then + Break; + for n := 1 to Length(t) do + if t[n] = #9 then + t[n] := ' '; + if t[1] <> ' ' then + Break + else + begin + s := s + ' ' + Trim(t); + Inc(Index); + end; + end; + Result := s; end; {==============================================================================} -{TMIMEPart.Create} -Constructor TMIMEPart.Create; + +constructor TMIMEPart.Create; begin inherited Create; - Lines:=TStringList.Create; - DecodedLines:=TmemoryStream.create; - TargetCharset:=GetCurCP; + FLines := TStringList.Create; + FDecodedLines := TMemoryStream.Create; + FTargetCharset := GetCurCP; end; -{TMIMEPart.Destroy} -Destructor TMIMEPart.Destroy; +destructor TMIMEPart.Destroy; begin - DecodedLines.free; - Lines.free; - inherited destroy; + FDecodedLines.Free; + FLines.Free; + inherited Destroy; end; {==============================================================================} -{TMIMEPart.Clear} + procedure TMIMEPart.Clear; begin - FPrimary:=''; - FEncoding:=''; - FCharset:=''; - PrimaryCode:=MP_TEXT; - EncodingCode:=ME_7BIT; - CharsetCode:=ISO_8859_1; - TargetCharset:=GetCurCP; - secondary:=''; - disposition:=''; - contentID:=''; - description:=''; - boundary:=''; - FileName:=''; - Lines.clear; - DecodedLines.clear; + FPrimary := ''; + FEncoding := ''; + FCharset := ''; + FPrimaryCode := MP_TEXT; + FEncodingCode := ME_7BIT; + FCharsetCode := ISO_8859_1; + FTargetCharset := GetCurCP; + FSecondary := ''; + FDisposition := ''; + FContentID := ''; + FDescription := ''; + FBoundary := ''; + FFileName := ''; + FLines.Clear; + FDecodedLines.Clear; end; {==============================================================================} -{TMIMEPart.ExtractPart} -function TMIMEPart.ExtractPart(value:TStringList; BeginLine:integer):integer; + +function TMIMEPart.ExtractPart(Value: TStringList; BeginLine: Integer): Integer; var - n,x,x1,x2:integer; - t:tstringlist; - s,su,b:string; - st,st2:string; - e:boolean; - fn:string; + n, x, x1, x2: Integer; + t: TStringList; + s, su, b: string; + st, st2: string; + e: Boolean; + fn: string; begin - t:=tstringlist.create; + t := TStringlist.Create; try - {defaults} - lines.clear; - primary:='text'; - secondary:='plain'; - description:=''; - charset:='US-ASCII'; - FileName:=''; - encoding:='7BIT'; + { defaults } + FLines.Clear; + Primary := 'text'; + FSecondary := 'plain'; + FDescription := ''; + Charset := 'US-ASCII'; + FFileName := ''; + Encoding := '7BIT'; - fn:=''; - x:=beginline; - b:=boundary; - if b<>'' then - while value.count>x do - begin - s:=value[x]; - inc(x); - if pos('--'+b,s)>0 - then break; - end; - - {parse header} - while value.count>x do + fn := ''; + x := BeginLine; + b := FBoundary; + if b <> '' then + while Value.Count > x do begin - s:=normalizeheader(value,x); - if s='' - then break; - su:=uppercase(s); - if pos('CONTENT-TYPE:',su)=1 then - begin - st:=separateright(su,':'); - st2:=separateleft(st,';'); - primary:=separateleft(st2,'/'); - secondary:=separateright(st2,'/'); - if (secondary=primary) and (pos('/',st2)<1) - then secondary:=''; - case primarycode of - MP_TEXT: - begin - charset:=uppercase(getparameter(s,'charset=')); - end; - MP_MULTIPART: - begin - boundary:=getparameter(s,'boundary='); - end; - MP_MESSAGE: - begin - end; - MP_BINARY: - begin - filename:=getparameter(s,'name='); - end; - end; - end; - if pos('CONTENT-TRANSFER-ENCODING:',su)=1 then - begin - encoding:=separateright(su,':'); - end; - if pos('CONTENT-DESCRIPTION:',su)=1 then - begin - description:=separateright(s,':'); - end; - if pos('CONTENT-DISPOSITION:',su)=1 then - begin - disposition:=separateright(su,':'); - disposition:=trim(separateleft(disposition,';')); - fn:=getparameter(s,'filename='); - end; - if pos('CONTENT-ID:',su)=1 then - begin - contentID:=separateright(s,':'); - end; + s := Value[x]; + Inc(x); + if Pos('--' + b, s) > 0 then + Break; end; - if (primarycode=MP_BINARY) and (filename='') - then filename:=fn; - filename:=InlineDecode(filename,getCurCP); - filename:=extractfilename(filename); - - x1:=x; - x2:=value.count-1; - if b<>'' then + { parse header } + while Value.Count > x do + begin + s := NormalizeHeader(Value, x); + if s = '' then + Break; + su := UpperCase(s); + if Pos('CONTENT-TYPE:', su) = 1 then begin - for n:=x to value.count-1 do - begin - x2:=n; - s:=value[n]; - if pos('--'+b,s)>0 - then begin - dec(x2); - break; - end; - end; - end; - if primarycode=MP_MULTIPART then - begin - for n:=x to value.count-1 do - begin - s:=value[n]; - if pos('--'+boundary,s)>0 then - begin - x1:=n; - break; - end; - end; - for n:=value.count-1 downto x do - begin - s:=value[n]; - if pos('--'+boundary,s)>0 then - begin - x2:=n; - break; - end; - end; - end; - for n:=x1 to x2 do - lines.add(value[n]); - result:=x2; - if primarycode=MP_MULTIPART then - begin - e:=false; - for n:=x2+1 to value.count-1 do - if pos('--'+boundary,value[n])>0 then + st := SeparateRight(su, ':'); + st2 := SeparateLeft(st, ';'); + Primary := SeparateLeft(st2, '/'); + FSecondary := SeparateRight(st2, '/'); + if (FSecondary = Primary) and (Pos('/', st2) < 1) then FSecondary := ''; + case FPrimaryCode of + MP_TEXT: + Charset := UpperCase(GetParameter(s, 'charset=')); + MP_MULTIPART: + FBoundary := GetParameter(s, 'Boundary='); + MP_MESSAGE: begin - e:=true; - break; end; - if not e - then result:=value.count-1; + MP_BINARY: + FFileName := GetParameter(s, 'name='); + end; end; + if Pos('CONTENT-TRANSFER-ENCODING:', su) = 1 then + Encoding := SeparateRight(su, ':'); + if Pos('CONTENT-DESCRIPTION:', su) = 1 then + FDescription := SeparateRight(s, ':'); + if Pos('CONTENT-DISPOSITION:', su) = 1 then + begin + FDisposition := SeparateRight(su, ':'); + FDisposition := Trim(SeparateLeft(FDisposition, ';')); + fn := GetParameter(s, 'FileName='); + end; + if Pos('CONTENT-ID:', su) = 1 then + FContentID := SeparateRight(s, ':'); + end; + + if (PrimaryCode = MP_BINARY) and (FFileName = '') then + FFileName := fn; + FFileName := InlineDecode(FFileName, getCurCP); + FFileName := ExtractFileName(FFileName); + + x1 := x; + x2 := Value.Count - 1; + if b <> '' then + begin + for n := x to Value.Count - 1 do + begin + x2 := n; + s := Value[n]; + if Pos('--' + b, s) > 0 then + begin + Dec(x2); + Break; + end; + end; + end; + if FPrimaryCode = MP_MULTIPART then + begin + for n := x to Value.Count - 1 do + begin + s := Value[n]; + if Pos('--' + Boundary, s) > 0 then + begin + x1 := n; + Break; + end; + end; + for n := Value.Count - 1 downto x do + begin + s := Value[n]; + if Pos('--' + Boundary, s) > 0 then + begin + x2 := n; + Break; + end; + end; + end; + for n := x1 to x2 do + FLines.Add(Value[n]); + Result := x2; + if FPrimaryCode = MP_MULTIPART then + begin + e := False; + for n := x2 + 1 to Value.Count - 1 do + if Pos('--' + Boundary, Value[n]) > 0 then + begin + e := True; + Break; + end; + if not e then + Result := Value.Count - 1; + end; finally - t.free; + t.Free; end; end; {==============================================================================} -{TMIMEPart.DecodePart} + procedure TMIMEPart.DecodePart; const - CRLF=#$0D+#$0A; + CRLF = #13#10; var - n:integer; - s:string; + n: Integer; + s: string; begin - decodedLines.Clear; - for n:=0 to lines.count-1 do - begin - s:=lines[n]; - case EncodingCode of - ME_7BIT: - begin - s:=s+CRLF; - end; - ME_8BIT: - begin - s:=decodeChar(s,CharsetCode,TargetCharset); - s:=s+CRLF; - end; - ME_QUOTED_PRINTABLE: - begin - if s='' - then s:=CRLF - else - if s[length(s)]<>'=' - then s:=s+CRLF; - s:=DecodeQuotedPrintable(s); - if PrimaryCode=MP_TEXT - then s:=decodeChar(s,CharsetCode,TargetCharset); - end; - ME_BASE64: - begin - if s<>'' - then s:=DecodeBase64(s); - if PrimaryCode=MP_TEXT - then s:=decodeChar(s,CharsetCode,TargetCharset); - end; - ME_UU: - begin - if s<>'' - then s:=DecodeUU(s); - end; - ME_XX: - begin - if s<>'' - then s:=DecodeXX(s); - end; - end; - Decodedlines.Write(pointer(s)^,length(s)); + FDecodedLines.Clear; + for n := 0 to FLines.Count - 1 do + begin + s := FLines[n]; + case FEncodingCode of + ME_7BIT: + s := s + CRLF; + ME_8BIT: + begin + s := CharsetConversion(s, FCharsetCode, FTargetCharset); + s := s + CRLF; + end; + ME_QUOTED_PRINTABLE: + begin + if s = '' then + s := CRLF + else + if s[Length(s)] <> '=' then + s := s + CRLF; + s := DecodeQuotedPrintable(s); + if FPrimaryCode = MP_TEXT then + s := CharsetConversion(s, FCharsetCode, FTargetCharset); + end; + ME_BASE64: + begin + if s <> '' then + s := DecodeBase64(s); + if FPrimaryCode = MP_TEXT then + s := CharsetConversion(s, FCharsetCode, FTargetCharset); + end; + ME_UU: + if s <> '' then + s := DecodeUU(s); + ME_XX: + if s <> '' then + s := DecodeXX(s); end; - decodedlines.Seek(0,soFromBeginning); + FDecodedLines.Write(Pointer(s)^, Length(s)); + end; + FDecodedLines.Seek(0, soFromBeginning); end; {==============================================================================} -{TMIMEPart.EncodePart} + procedure TMIMEPart.EncodePart; var - l:TStringList; - s,buff:string; - n,x:integer; + l: TStringList; + s, buff: string; + n, x: Integer; begin - if EncodingCode=ME_UU - then encoding:='base64'; - if EncodingCode=ME_XX - then encoding:='base64'; - l:=tstringlist.create; - Lines.clear; - decodedlines.Seek(0,soFromBeginning); + if (FEncodingCode = ME_UU) or (FEncodingCode = ME_XX) then + Encoding := 'base64'; + l := TStringList.Create; + FLines.Clear; + FDecodedLines.Seek(0, soFromBeginning); try - case primarycode of - MP_MULTIPART, - MP_MESSAGE: + case FPrimaryCode of + MP_MULTIPART, MP_MESSAGE: + FLines.LoadFromStream(FDecodedLines); + MP_TEXT, MP_BINARY: + if FEncodingCode = ME_BASE64 then begin - lines.LoadFromStream(DecodedLines); + while FDecodedLines.Position < FDecodedLines.Size do + begin + Setlength(Buff, 54); + s := ''; + x := FDecodedLines.Read(pointer(Buff)^, 54); + for n := 1 to x do + s := s + Buff[n]; + if FPrimaryCode = MP_TEXT then + s := CharsetConversion(s, FTargetCharset, FCharsetCode); + s := EncodeBase64(s); + if x <> 54 then + s := s + '='; + FLines.Add(s); + end; + end + else + begin + l.LoadFromStream(FDecodedLines); + for n := 0 to l.Count - 1 do + begin + s := l[n]; + if FPrimaryCode = MP_TEXT then + s := CharsetConversion(s, FTargetCharset, FCharsetCode); + s := EncodeQuotedPrintable(s); + FLines.Add(s); + end; end; + + end; + FLines.Add(''); + FLines.Insert(0, ''); + if FSecondary = '' then + case FPrimaryCode of + MP_TEXT: + FSecondary := 'plain'; + MP_MULTIPART: + FSecondary := 'mixed'; + MP_MESSAGE: + FSecondary := 'rfc822'; + MP_BINARY: + FSecondary := 'octet-stream'; + end; + if FDescription <> '' then + FLines.Insert(0, 'Content-Description: ' + FDescription); + if FDisposition <> '' then + begin + s := ''; + if FFileName <> '' then + s := '; FileName="' + FFileName + '"'; + FLines.Insert(0, 'Content-Disposition: ' + LowerCase(FDisposition) + s); + end; + if FContentID <> '' then + FLines.Insert(0, 'Content-ID: ' + FContentID); + + case FEncodingCode of + ME_7BIT: + s := '7bit'; + ME_8BIT: + s := '8bit'; + ME_QUOTED_PRINTABLE: + s := 'Quoted-printable'; + ME_BASE64: + s := 'Base64'; + end; + case FPrimaryCode of MP_TEXT, + MP_BINARY: FLines.Insert(0, 'Content-Transfer-Encoding: ' + s); + end; + case FPrimaryCode of + MP_TEXT: + s := FPrimary + '/' + FSecondary + '; charset=' + GetIDfromCP(FCharsetCode); + MP_MULTIPART: + s := FPrimary + '/' + FSecondary + '; boundary="' + Boundary + '"'; + MP_MESSAGE: + s := FPrimary + '/' + FSecondary + ''; MP_BINARY: - if EncodingCode=ME_BASE64 - then - begin - while decodedlines.Position54 - then s:=s+'='; - Lines.add(s); - end; - end - else - begin - l.LoadFromStream(DecodedLines); - for n:=0 to l.count-1 do - begin - s:=l[n]; - if PrimaryCode=MP_TEXT - then s:=decodeChar(s,TargetCharset,CharsetCode); - s:=EncodeQuotedPrintable(s); - Lines.add(s); - end; - end; - + s := FPrimary + '/' + FSecondary + '; name="' + FFileName + '"'; end; - Lines.add(''); - lines.insert(0,''); - if secondary='' then - case PrimaryCode of - MP_TEXT: secondary:='plain'; - MP_MULTIPART: secondary:='mixed'; - MP_MESSAGE: secondary:='rfc822'; - MP_BINARY: secondary:='octet-stream'; - end; - if description<>'' - then lines.insert(0,'Content-Description: '+Description); - if disposition<>'' then - begin - s:=''; - if filename<>'' - then s:='; filename="'+filename+'"'; - lines.insert(0,'Content-Disposition: '+lowercase(disposition)+s); - end; - if contentID<>'' - then lines.insert(0,'Content-ID: '+contentID); - - case EncodingCode of - ME_7BIT: s:='7bit'; - ME_8BIT: s:='8bit'; - ME_QUOTED_PRINTABLE: s:='Quoted-printable'; - ME_BASE64: s:='Base64'; - end; - case PrimaryCode of - MP_TEXT, - MP_BINARY: lines.insert(0,'Content-Transfer-Encoding: '+s); - end; - case PrimaryCode of - MP_TEXT: s:=primary+'/'+secondary+'; charset='+GetIDfromCP(charsetcode); - MP_MULTIPART: s:=primary+'/'+secondary+'; boundary="'+boundary+'"'; - MP_MESSAGE: s:=primary+'/'+secondary+''; - MP_BINARY: s:=primary+'/'+secondary+'; name="'+FileName+'"'; - end; - lines.insert(0,'Content-type: '+s); + FLines.Insert(0, 'Content-type: ' + s); finally - l.free; + l.Free; end; end; {==============================================================================} -{TMIMEPart.MimeTypeFromExt} -procedure TMIMEPart.MimeTypeFromExt(value:string); -var - s:string; - n:integer; -begin - primary:=''; - secondary:=''; - s:=uppercase(extractfileext(value)); - if s='' - then s:=uppercase(value); - s:=separateright(s,'.'); - for n:=0 to MaxMimeType do - if MimeType[n,0]=s then - begin - primary:=MimeType[n,1]; - secondary:=MimeType[n,2]; - break; - end; - if primary='' - then primary:='application'; - if secondary='' - then secondary:='mixed'; -end; -{==============================================================================} -{TMIMEPart.Setprimary} -procedure TMIMEPart.Setprimary(Value:string); +procedure TMIMEPart.MimeTypeFromExt(Value: string); var - s:string; + s: string; + n: Integer; begin - Fprimary:=Value; - s:=uppercase(Value); - PrimaryCode:=MP_BINARY; - if Pos('TEXT',s)=1 - then PrimaryCode:=MP_TEXT; - if Pos('MULTIPART',s)=1 - then PrimaryCode:=MP_MULTIPART; - if Pos('MESSAGE',s)=1 - then PrimaryCode:=MP_MESSAGE; -end; - -{TMIMEPart.SetEncoding} -procedure TMIMEPart.SetEncoding(Value:string); -var - s:string; -begin - FEncoding:=Value; - s:=uppercase(Value); - EncodingCode:=ME_7BIT; - if Pos('8BIT',s)=1 - then EncodingCode:=ME_8BIT; - if Pos('QUOTED-PRINTABLE',s)=1 - then EncodingCode:=ME_QUOTED_PRINTABLE; - if Pos('BASE64',s)=1 - then EncodingCode:=ME_BASE64; - if Pos('X-UU',s)=1 - then EncodingCode:=ME_UU; - if Pos('X-XX',s)=1 - then EncodingCode:=ME_XX; -end; - -{TMIMEPart.SetCharset} -procedure TMIMEPart.SetCharset(Value:string); -begin - FCharset:=Value; - CharsetCode:=GetCPfromID(value); -end; - -{==============================================================================} -{GenerateBoundary} -function GenerateBoundary:string; -var - x:integer; -begin - randomize; - x:=random(maxint); - result:='----'+Inttohex(x,8)+'_Synapse_message_boundary'; + Primary := ''; + FSecondary := ''; + s := UpperCase(ExtractFileExt(Value)); + if s = '' then + s := UpperCase(Value); + s := SeparateRight(s, '.'); + for n := 0 to MaxMimeType do + if MimeType[n, 0] = s then + begin + Primary := MimeType[n, 1]; + FSecondary := MimeType[n, 2]; + Break; + end; + if Primary = '' then + Primary := 'application'; + if FSecondary = '' then + FSecondary := 'mixed'; end; {==============================================================================} +procedure TMIMEPart.SetPrimary(Value: string); +var + s: string; begin - exit; - asm - db 'Synapse MIME messages encoding and decoding library by Lukas Gebauer',0 - end; + FPrimary := Value; + s := UpperCase(Value); + FPrimaryCode := MP_BINARY; + if Pos('TEXT', s) = 1 then + FPrimaryCode := MP_TEXT; + if Pos('MULTIPART', s) = 1 then + FPrimaryCode := MP_MULTIPART; + if Pos('MESSAGE', s) = 1 then + FPrimaryCode := MP_MESSAGE; +end; + +procedure TMIMEPart.SetEncoding(Value: string); +var + s: string; +begin + FEncoding := Value; + s := UpperCase(Value); + FEncodingCode := ME_7BIT; + if Pos('8BIT', s) = 1 then + FEncodingCode := ME_8BIT; + if Pos('QUOTED-PRINTABLE', s) = 1 then + FEncodingCode := ME_QUOTED_PRINTABLE; + if Pos('BASE64', s) = 1 then + FEncodingCode := ME_BASE64; + if Pos('X-UU', s) = 1 then + FEncodingCode := ME_UU; + if Pos('X-XX', s) = 1 then + FEncodingCode := ME_XX; +end; + +procedure TMIMEPart.SetCharset(Value: string); +begin + FCharset := Value; + FCharsetCode := GetCPFromID(Value); +end; + +{==============================================================================} + +function GenerateBoundary: string; +var + x: Integer; +begin + Randomize; + x := Random(MaxInt); + Result := '----' + IntToHex(x, 8) + '_Synapse_message_boundary'; +end; + end. diff --git a/pingsend.pas b/pingsend.pas index c6c5e78..20197f0 100644 --- a/pingsend.pas +++ b/pingsend.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.000.000 | +| Project : Delphree - Synapse | 002.001.000 | |==============================================================================| | Content: PING sender | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -14,7 +14,7 @@ | The Original Code is Synapse Delphi Library. | |==============================================================================| | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| -| Portions created by Lukas Gebauer are Copyright (c)2000. | +| Portions created by Lukas Gebauer are Copyright (c)2000,2001. | | All Rights Reserved. | |==============================================================================| | Contributor(s): | @@ -25,27 +25,12 @@ { !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -Remember, this unit work only on Linux or Windows with Winsock2! - (on Win98 and WinNT 4.0 or higher) -If you must use this unit on Win95, download Wínsock2 from Microsoft -and distribute it with your application! - -In spite of I use Winsock level version 1.1, RAW sockets work in this level only -if Winsock2 is installed on your computer!!! - -On WinNT standardly RAW sockets work if program is running under user with -administrators provilegies. To use RAW sockets under another users, you must -create the following registry variable and set its value to DWORD 1: - -HKLM\System\CurrentControlSet\Services\Afd\Parameters\DisableRawSecurity - -After you change the registry, you need to restart your computer! - +See 'winsock2.txt' file in distribute package! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } {$Q-} +{$WEAKPACKAGEUNIT ON} unit PINGsend; @@ -53,159 +38,183 @@ interface uses {$IFDEF LINUX} - libc, + Libc, {$ELSE} - windows, + Windows, {$ENDIF} - synsock, SysUtils, blcksck2, Synautil; + SysUtils, + synsock, blcksock, SynaUtil; const - ICMP_ECHO=8; - ICMP_ECHOREPLY=0; + ICMP_ECHO = 8; + ICMP_ECHOREPLY = 0; type + TIcmpEchoHeader = record + i_type: Byte; + i_code: Byte; + i_checkSum: Word; + i_Id: Word; + i_seq: Word; + TimeStamp: ULONG; + end; -TIcmpEchoHeader = Record - i_type : Byte; - i_code : Byte; - i_checkSum : Word; - i_Id : Word; - i_seq : Word; - TimeStamp : ULong; -End; - -TPINGSend=class(TObject) + TPINGSend = class(TObject) private - Sock:TICMPBlockSocket; - Buffer:string; - seq:integer; - id:integer; - function checksum:integer; - function GetTick:cardinal; + FSock: TICMPBlockSocket; + FBuffer: string; + FSeq: Integer; + FId: Integer; + FTimeout: Integer; + FPacketSize: Integer; + FPingTime: Integer; + function Checksum: Integer; + function GetTick: Cardinal; + function ReadPacket: Boolean; public - timeout:integer; - PacketSize:integer; - PingTime:integer; - function ping(host:string):Boolean; + function Ping(const Host: string): Boolean; constructor Create; destructor Destroy; override; -end; + published + property Timeout: Integer read FTimeout Write FTimeout; + property PacketSize: Integer read FPacketSize Write FPacketSize; + property PingTime: Integer read FPingTime; + end; -function PingHost(host:string):integer; +function PingHost(const Host: string): Integer; implementation {==============================================================================} -{TPINGSend.Create} -Constructor TPINGSend.Create; +constructor TPINGSend.Create; begin inherited Create; - sock:=TICMPBlockSocket.create; - sock.CreateSocket; - timeout:=5000; - packetsize:=32; - seq:=0; + FSock := TICMPBlockSocket.Create; + FSock.CreateSocket; + FTimeout := 5000; + FPacketSize := 32; + FSeq := 0; + Randomize; end; -{TPINGSend.Destroy} -Destructor TPINGSend.Destroy; +destructor TPINGSend.Destroy; begin - Sock.free; - inherited destroy; + FSock.Free; + inherited Destroy; end; -{TPINGSend.ping} -function TPINGSend.ping(host:string):Boolean; +function TPINGSend.ReadPacket: Boolean; var - PIPHeader:^TIPHeader; - IpHdrLen:Integer; - PIcmpEchoHeader:^TICMPEchoHeader; - n,x:integer; + x: Integer; begin - Result:=False; - sock.connect(host,'0'); - Buffer:=StringOfChar(#0,SizeOf(TICMPEchoHeader)+packetSize); - PIcmpEchoHeader := Pointer(Buffer); - With PIcmpEchoHeader^ Do Begin - i_type:=ICMP_ECHO; - i_code:=0; - i_CheckSum:=0; - id:=Random(32767); - i_Id:=id; - TimeStamp:=GetTick; - Inc(Seq); - i_Seq:=Seq; - for n:=Succ(SizeOf(TicmpEchoHeader)) to Length(Buffer) do - Buffer[n]:=#$55; - i_CheckSum:=CheckSum; + Result := FSock.CanRead(FTimeout); + if Result then + begin + x := FSock.WaitingData; + SetLength(FBuffer, x); + FSock.RecvBuffer(Pointer(FBuffer), x); end; - sock.sendString(Buffer); - if sock.canread(timeout) - then begin - x:=sock.waitingdata; - setlength(Buffer,x); - sock.recvbuffer(Pointer(Buffer),x); - PIpHeader:=Pointer(Buffer); - IpHdrLen:=(PIpHeader^.VerLen and $0F)*4; - PIcmpEchoHeader:=@Buffer[IpHdrLen+1]; - if (PIcmpEchoHeader^.i_type=ICMP_ECHOREPLY) -// Linux return from localhost ECHO instead ECHOREPLY??? - or (PIcmpEchoHeader^.i_type=ICMP_ECHO) then - if (PIcmpEchoHeader^.i_id=id) then - begin - PingTime:=GetTick-PIcmpEchoHeader^.TimeStamp; - Result:=True; - end; - end; end; -{TPINGSend.checksum} -function TPINGSend.checksum:integer; -type - tWordArray=Array[0..0] Of Word; +function TPINGSend.Ping(const Host: string): Boolean; var - PWordArray:^TWordArray; - CkSum:Dword; - Num,Remain:Integer; - n:Integer; + IPHeadPtr: ^TIPHeader; + IpHdrLen: Integer; + IcmpEchoHeaderPtr: ^TICMPEchoHeader; + n: Integer; + t: Boolean; begin - Num:=length(Buffer) div 2; - Remain:=length(Buffer) mod 2; - PWordArray:=Pointer(Buffer); - CkSum := 0; - for n:=0 to Num-1 do - CkSum:=CkSum+PWordArray^[n]; - if Remain<>0 then - CkSum:=CkSum+ord(Buffer[Length(Buffer)]); - CkSum:=(CkSum shr 16)+(CkSum and $FFFF); - CkSum:=CkSum+(CkSum shr 16); - Result:=Word(not CkSum); + Result := False; + FSock.Connect(Host, '0'); + FBuffer := StringOfChar(#0, SizeOf(TICMPEchoHeader) + FPacketSize); + IcmpEchoHeaderPtr := Pointer(FBuffer); + with IcmpEchoHeaderPtr^ do + begin + i_type := ICMP_ECHO; + i_code := 0; + i_CheckSum := 0; + FId := Random(32767); + i_Id := FId; + TimeStamp := GetTick; + Inc(FSeq); + i_Seq := FSeq; + for n := Succ(SizeOf(TIcmpEchoHeader)) to Length(FBuffer) do + FBuffer[n] := #$55; + i_CheckSum := CheckSum; + end; + FSock.SendString(FBuffer); + repeat + t := ReadPacket; + if not t then + break; + IPHeadPtr := Pointer(FBuffer); + IpHdrLen := (IPHeadPtr^.VerLen and $0F) * 4; + IcmpEchoHeaderPtr := @FBuffer[IpHdrLen + 1]; + until IcmpEchoHeaderPtr^.i_type <> ICMP_ECHO; + //it discard sometimes possible 'echoes' of previosly sended packet... + if t then + if (IcmpEchoHeaderPtr^.i_type = ICMP_ECHOREPLY) then + if (IcmpEchoHeaderPtr^.i_id = FId) then + begin + FPingTime := GetTick - IcmpEchoHeaderPtr^.TimeStamp; + Result := True; + end; end; -{TPINGSend.GetTick} -function TPINGSend.GetTick:cardinal; +function TPINGSend.Checksum: Integer; +type + TWordArray = array[0..0] of Word; +var + WordArr: ^TWordArray; + CkSum: DWORD; + Num, Remain: Integer; + n: Integer; begin -{$IFDEF LINUX} - result:=clock div (CLOCKS_PER_SEC div 1000); -{$ELSE} - result:=windows.GetTickCount; -{$ENDIF} + Num := Length(FBuffer) div 2; + Remain := Length(FBuffer) mod 2; + WordArr := Pointer(FBuffer); + CkSum := 0; + for n := 0 to Num - 1 do + CkSum := CkSum + WordArr^[n]; + if Remain <> 0 then + CkSum := CkSum + Ord(FBuffer[Length(FBuffer)]); + CkSum := (CkSum shr 16) + (CkSum and $FFFF); + CkSum := CkSum + (CkSum shr 16); + Result := Word(not CkSum); end; +{$IFDEF LINUX} + +function TPINGSend.GetTick: Cardinal; +var + Stamp: TTimeStamp; +begin + Stamp := DateTimeToTimeStamp(Now); + Result := Stamp.Time; +end; + +{$ELSE} + +function TPINGSend.GetTick: Cardinal; +begin + Result := Windows.GetTickCount; +end; + +{$ENDIF} + {==============================================================================} -function PingHost(host:string):integer; -var - ping:TPINGSend; +function PingHost(const Host: string): Integer; begin - ping:=TPINGSend.Create; + with TPINGSend.Create do try - if ping.ping(host) - then Result:=ping.pingtime - else Result:=-1; + if Ping(Host) then + Result := PingTime + else + Result := -1; finally - ping.Free; + Free; end; end; diff --git a/pop3send.pas b/pop3send.pas index 152948e..ea288c6 100644 --- a/pop3send.pas +++ b/pop3send.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.001.000 | +| Project : Delphree - Synapse | 001.001.001 | |==============================================================================| | Content: POP3 client | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -23,252 +23,239 @@ | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} +{$WEAKPACKAGEUNIT ON} + unit POP3send; interface + uses - Blcksock, sysutils, classes, SynaUtil, SynaCode; + SysUtils, Classes, + blcksock, SynaUtil, SynaCode; const - CRLF=#13+#10; + cPop3Protocol = 'pop3'; type - TPOP3AuthType = (POP3AuthAll,POP3AuthLogin,POP3AuthAPOP); + TPOP3AuthType = (POP3AuthAll, POP3AuthLogin, POP3AuthAPOP); - TPOP3Send = class + TPOP3Send = class(TObject) private - Sock:TTCPBlockSocket; - function ReadResult(full:boolean):integer; - function Connect:Boolean; + FSock: TTCPBlockSocket; + FTimeout: Integer; + FPOP3Host: string; + FPOP3Port: string; + FResultCode: Integer; + FResultString: string; + FFullResult: TStringList; + FUsername: string; + FPassword: string; + FStatCount: Integer; + FStatSize: Integer; + FTimeStamp: string; + FAuthType: TPOP3AuthType; + function ReadResult(Full: Boolean): Integer; + function Connect: Boolean; + function AuthLogin: Boolean; + function AuthApop: Boolean; public - timeout:integer; - POP3Host:string; - POP3Port:string; - ResultCode:integer; - ResultString:string; - FullResult:TStringList; - Username:string; - Password:string; - StatCount:integer; - StatSize:integer; - TimeStamp:string; - AuthType:TPOP3AuthType; - Constructor Create; - Destructor Destroy; override; - function AuthLogin:Boolean; - function AuthApop:Boolean; - function login:Boolean; - procedure logout; - function reset:Boolean; - function noop:Boolean; - function stat:Boolean; - function list(value:integer):Boolean; - function retr(value:integer):Boolean; - function dele(value:integer):Boolean; - function top(value,maxlines:integer):Boolean; - function uidl(value:integer):Boolean; + constructor Create; + destructor Destroy; override; + function Login: Boolean; + procedure Logout; + function Reset: Boolean; + function NoOp: Boolean; + function Stat: Boolean; + function List(Value: Integer): Boolean; + function Retr(Value: Integer): Boolean; + function Dele(Value: Integer): Boolean; + function Top(Value, Maxlines: Integer): Boolean; + function Uidl(Value: Integer): Boolean; + published + property Timeout: Integer read FTimeout Write FTimeout; + property POP3Host: string read FPOP3Host Write FPOP3Host; + property POP3Port: string read FPOP3Port Write FPOP3Port; + property ResultCode: Integer read FResultCode; + property ResultString: string read FResultString; + property FullResult: TStringList read FFullResult; + property Username: string read FUsername Write FUsername; + property Password: string read FPassword Write FPassword; + property StatCount: Integer read FStatCount; + property StatSize: Integer read FStatSize; + property TimeStamp: string read FTimeStamp; + property AuthType: TPOP3AuthType read FAuthType Write FAuthType; end; implementation -{TPOP3Send.Create} -Constructor TPOP3Send.Create; +const + CRLF = #13#10; + +constructor TPOP3Send.Create; begin inherited Create; - FullResult:=TStringList.create; - sock:=TTCPBlockSocket.create; - sock.CreateSocket; - timeout:=300000; - POP3host:='localhost'; - POP3Port:='pop3'; - Username:=''; - Password:=''; - StatCount:=0; - StatSize:=0; - AuthType:=POP3AuthAll; + FFullResult := TStringList.Create; + FSock := TTCPBlockSocket.Create; + FSock.CreateSocket; + FTimeout := 300000; + FPOP3host := cLocalhost; + FPOP3Port := cPop3Protocol; + FUsername := ''; + FPassword := ''; + FStatCount := 0; + FStatSize := 0; + FAuthType := POP3AuthAll; end; -{TPOP3Send.Destroy} -Destructor TPOP3Send.Destroy; +destructor TPOP3Send.Destroy; begin - Sock.free; - FullResult.free; - inherited destroy; + FSock.Free; + FullResult.Free; + inherited Destroy; end; -{TPOP3Send.ReadResult} -function TPOP3Send.ReadResult(full:boolean):integer; +function TPOP3Send.ReadResult(Full: Boolean): Integer; var - s:string; + s: string; begin - Result:=0; - FullResult.Clear; - s:=sock.recvstring(timeout); - if pos('+OK',s)=1 - then result:=1; - ResultString:=s; - if full and (result=1)then + Result := 0; + FFullResult.Clear; + s := FSock.RecvString(FTimeout); + if Pos('+OK', s) = 1 then + Result := 1; + FResultString := s; + if Full and (Result = 1) then repeat - s:=sock.recvstring(timeout); - if s='.' - then break; - FullResult.add(s); - until sock.LastError<>0; - ResultCode:=Result; + s := FSock.RecvString(FTimeout); + if s = '.' then + Break; + FFullResult.Add(s); + until FSock.LastError <> 0; + FResultCode := Result; end; -{TPOP3Send.AuthLogin} -function TPOP3Send.AuthLogin:Boolean; +function TPOP3Send.AuthLogin: Boolean; begin - Result:=false; - Sock.SendString('USER '+username+CRLF); - if readresult(false)<>1 then Exit; - Sock.SendString('PASS '+password+CRLF); - if readresult(false)<>1 then Exit; - Result:=True; + Result := False; + FSock.SendString('USER ' + FUserName + CRLF); + if ReadResult(False) <> 1 then + Exit; + FSock.SendString('PASS ' + FPassword + CRLF); + Result := ReadResult(False) = 1; end; -{TPOP3Send.AuthAPop} -function TPOP3Send.AuthAPOP:Boolean; +function TPOP3Send.AuthAPOP: Boolean; var - s:string; + s: string; begin - Result:=false; - s:=StrToHex(MD5(TimeStamp+PassWord)); - Sock.SendString('APOP '+username+' '+s+CRLF); - if readresult(false)<>1 then Exit; - Result:=True; + s := StrToHex(MD5(FTimeStamp + FPassWord)); + FSock.SendString('APOP ' + FUserName + ' ' + s + CRLF); + Result := ReadResult(False) = 1; end; - -{TPOP3Send.Connect} -function TPOP3Send.Connect:Boolean; +function TPOP3Send.Connect: Boolean; begin -//Do not call this function! It is calling by LOGIN method! - Result:=false; - StatCount:=0; - StatSize:=0; - sock.CloseSocket; - sock.LineBuffer:=''; - sock.CreateSocket; - sock.Connect(POP3Host,POP3Port); - if sock.lasterror<>0 then Exit; - Result:=True; + // Do not call this function! It is calling by LOGIN method! + FStatCount := 0; + FStatSize := 0; + FSock.CloseSocket; + FSock.LineBuffer := ''; + FSock.CreateSocket; + FSock.Connect(POP3Host, POP3Port); + Result := FSock.LastError = 0; end; -{TPOP3Send.login} -function TPOP3Send.login:Boolean; +function TPOP3Send.Login: Boolean; var - s,s1:string; + s, s1: string; begin - Result:=False; - TimeStamp:=''; - if not Connect then Exit; - if readresult(false)<>1 then Exit; - s:=separateright(Resultstring,'<'); - if s<>Resultstring then - begin - s1:=separateleft(s,'>'); - if s1<>s - then TimeStamp:='<'+s1+'>'; - end; - result:=false; - if (TimeStamp<>'') and not(AuthType=POP3AuthLogin) - then result:=AuthApop; - if not(Result) and not(AuthType=POP3AuthAPOP) - then result:=AuthLogin; + Result := False; + FTimeStamp := ''; + if not Connect then + Exit; + if ReadResult(False) <> 1 then + Exit; + s := SeparateRight(FResultString, '<'); + if s <> FResultString then + begin + s1 := SeparateLeft(s, '>'); + if s1 <> s then + FTimeStamp := '<' + s1 + '>'; + end; + Result := False; + if (FTimeStamp <> '') and not (FAuthType = POP3AuthLogin) then + Result := AuthApop; + if not Result and not (FAuthType = POP3AuthAPOP) then + Result := AuthLogin; end; -{TPOP3Send.logout} -procedure TPOP3Send.logout; +procedure TPOP3Send.Logout; begin - Sock.SendString('QUIT'+CRLF); - readresult(false); - Sock.CloseSocket; + FSock.SendString('QUIT' + CRLF); + ReadResult(False); + FSock.CloseSocket; end; -{TPOP3Send.reset} -function TPOP3Send.reset:Boolean; +function TPOP3Send.Reset: Boolean; begin - Result:=false; - Sock.SendString('RSET'+CRLF); - if readresult(false)<>1 then Exit; - Result:=True; + FSock.SendString('RSET' + CRLF); + Result := ReadResult(False) = 1; end; -{TPOP3Send.noop} -function TPOP3Send.noop:Boolean; +function TPOP3Send.NoOp: Boolean; begin - Result:=false; - Sock.SendString('NOOP'+CRLF); - if readresult(false)<>1 then Exit; - Result:=True; + FSock.SendString('NOOP' + CRLF); + Result := ReadResult(False) = 1; end; -{TPOP3Send.stat} -function TPOP3Send.stat:Boolean; +function TPOP3Send.Stat: Boolean; var - s:string; + s: string; begin - Result:=false; - Sock.SendString('STAT'+CRLF); - if readresult(false)<>1 then Exit; - s:=separateright(ResultString,'+OK '); - StatCount:=StrToIntDef(separateleft(s,' '),0); - StatSize:=StrToIntDef(separateright(s,' '),0); - Result:=True; + Result := False; + FSock.SendString('STAT' + CRLF); + if ReadResult(False) <> 1 then + Exit; + s := SeparateRight(ResultString, '+OK '); + FStatCount := StrToIntDef(SeparateLeft(s, ' '), 0); + FStatSize := StrToIntDef(SeparateRight(s, ' '), 0); + Result := True; end; -{TPOP3Send.list} -function TPOP3Send.list(value:integer):Boolean; +function TPOP3Send.List(Value: Integer): Boolean; begin - Result:=false; - if value=0 - then Sock.SendString('LIST'+CRLF) - else Sock.SendString('LIST '+IntToStr(value)+CRLF); - if readresult(value=0)<>1 then Exit; - Result:=True; + if Value = 0 then + FSock.SendString('LIST' + CRLF) + else + FSock.SendString('LIST ' + IntToStr(Value) + CRLF); + Result := ReadResult(Value = 0) = 1; end; -{TPOP3Send.retr} -function TPOP3Send.retr(value:integer):Boolean; +function TPOP3Send.Retr(Value: Integer): Boolean; begin - Result:=false; - Sock.SendString('RETR '+IntToStr(value)+CRLF); - if readresult(true)<>1 then Exit; - Result:=True; + FSock.SendString('RETR ' + IntToStr(Value) + CRLF); + Result := ReadResult(True) = 1; end; -{TPOP3Send.dele} -function TPOP3Send.dele(value:integer):Boolean; +function TPOP3Send.Dele(Value: Integer): Boolean; begin - Result:=false; - Sock.SendString('DELE '+IntToStr(value)+CRLF); - if readresult(false)<>1 then Exit; - Result:=True; + FSock.SendString('DELE ' + IntToStr(Value) + CRLF); + Result := ReadResult(False) = 1; end; -{TPOP3Send.top} -function TPOP3Send.top(value,maxlines:integer):Boolean; +function TPOP3Send.Top(Value, Maxlines: Integer): Boolean; begin - Result:=false; - Sock.SendString('TOP '+IntToStr(value)+' '+IntToStr(maxlines)+CRLF); - if readresult(true)<>1 then Exit; - Result:=True; + FSock.SendString('TOP ' + IntToStr(Value) + ' ' + IntToStr(Maxlines) + CRLF); + Result := ReadResult(True) = 1; end; -{TPOP3Send.uidl} -function TPOP3Send.uidl(value:integer):Boolean; +function TPOP3Send.Uidl(Value: Integer): Boolean; begin - Result:=false; - if value=0 - then Sock.SendString('UIDL'+CRLF) - else Sock.SendString('UIDL '+IntToStr(value)+CRLF); - if readresult(value=0)<>1 then Exit; - Result:=True; + if Value = 0 then + FSock.SendString('UIDL' + CRLF) + else + FSock.SendString('UIDL ' + IntToStr(Value) + CRLF); + Result := ReadResult(Value = 0) = 1; end; - -{==============================================================================} - end. diff --git a/smtpsend.pas b/smtpsend.pas index f5575fc..ee257b0 100644 --- a/smtpsend.pas +++ b/smtpsend.pas @@ -1,11 +1,11 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.001.002 | +| Project : Delphree - Synapse | 002.001.003 | |==============================================================================| | Content: SMTP client | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are Subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | -| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | +| License. You may obtain a Copy of the License at http://www.mozilla.org/MPL/ | | | | Software distributed under the License is distributed on an "AS IS" basis, | | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | @@ -23,485 +23,481 @@ | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} +{$WEAKPACKAGEUNIT ON} + unit SMTPsend; interface + uses - Blcksock, sysutils, classes, SynaUtil, SynaCode; + SysUtils, Classes, + blcksock, SynaUtil, SynaCode; const - CRLF=#13+#10; + cSmtpProtocol = 'smtp'; type - TSMTPSend = class + TSMTPSend = class(TObject) private - Sock:TTCPBlockSocket; - procedure EnhancedCode(value:string); - function ReadResult:integer; + FSock: TTCPBlockSocket; + FTimeout: Integer; + FSMTPHost: string; + FSMTPPort: string; + FResultCode: Integer; + FResultString: string; + FFullResult: TStringList; + FESMTPcap: TStringList; + FESMTP: Boolean; + FUsername: string; + FPassword: string; + FAuthDone: Boolean; + FESMTPSize: Boolean; + FMaxSize: Integer; + FEnhCode1: Integer; + FEnhCode2: Integer; + FEnhCode3: Integer; + FSystemName: string; + procedure EnhancedCode(const Value: string); + function ReadResult: Integer; + function AuthLogin: Boolean; + function AuthCram: Boolean; + function Helo: Boolean; + function Ehlo: Boolean; + function Connect: Boolean; public - timeout:integer; - SMTPHost:string; - SMTPPort:string; - ResultCode:integer; - ResultString:string; - FullResult:TStringList; - ESMTPcap:TStringList; - ESMTP:boolean; - Username:string; - Password:string; - AuthDone:boolean; - ESMTPSize:boolean; - MaxSize:integer; - EnhCode1:integer; - EnhCode2:integer; - EnhCode3:integer; - SystemName:string; - Constructor Create; - Destructor Destroy; override; - function AuthLogin:Boolean; - function AuthCram:Boolean; - function Connect:Boolean; - function Helo:Boolean; - function Ehlo:Boolean; - function login:Boolean; - procedure logout; - function reset:Boolean; - function noop:Boolean; - function mailfrom(Value:string; size:integer):Boolean; - function mailto(Value:string):Boolean; - function maildata(Value:Tstrings):Boolean; - function etrn(Value:string):Boolean; - function verify(Value:string):Boolean; - function EnhCodeString:string; - function FindCap(value:string):string; + constructor Create; + destructor Destroy; override; + function Login: Boolean; + procedure Logout; + function Reset: Boolean; + function NoOp: Boolean; + function MailFrom(const Value: string; Size: Integer): Boolean; + function MailTo(const Value: string): Boolean; + function MailData(const Value: Tstrings): Boolean; + function Etrn(const Value: string): Boolean; + function Verify(const Value: string): Boolean; + function EnhCodeString: string; + function FindCap(const Value: string): string; + published + property Timeout: Integer read FTimeout Write FTimeout; + property SMTPHost: string read FSMTPHost Write FSMTPHost; + property SMTPPort: string read FSMTPPort Write FSMTPPort; + property ResultCode: Integer read FResultCode; + property ResultString: string read FResultString; + property FullResult: TStringList read FFullResult; + property ESMTPcap: TStringList read FESMTPcap; + property ESMTP: Boolean read FESMTP; + property Username: string read FUsername Write FUsername; + property Password: string read FPassword Write FPassword; + property AuthDone: Boolean read FAuthDone; + property ESMTPSize: Boolean read FESMTPSize; + property MaxSize: Integer read FMaxSize; + property EnhCode1: Integer read FEnhCode1; + property EnhCode2: Integer read FEnhCode2; + property EnhCode3: Integer read FEnhCode3; + property SystemName: string read FSystemName Write FSystemName; end; -function SendtoRaw -(mailfrom,mailto,SMTPHost:string;maildata:TStrings;Username,Password:string):Boolean; -function Sendto -(mailfrom,mailto,subject,SMTPHost:string;maildata:TStrings):Boolean; -function SendtoEx -(mailfrom,mailto,subject,SMTPHost:string;maildata:TStrings;Username,Password:string):Boolean; +function SendToRaw(const MailFrom, MailTo, SMTPHost: string; + const MailData: TStrings; const Username, Password: string): Boolean; +function SendTo(const MailFrom, MailTo, Subject, SMTPHost: string; + const MailData: TStrings): Boolean; +function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string; + const MailData: TStrings; const Username, Password: string): Boolean; implementation -{TSMTPSend.Create} -Constructor TSMTPSend.Create; +const + CRLF = #13#10; + +constructor TSMTPSend.Create; begin inherited Create; - FullResult:=TStringList.create; - ESMTPcap:=TStringList.create; - sock:=TTCPBlockSocket.create; - sock.CreateSocket; - timeout:=300000; - SMTPhost:='localhost'; - SMTPPort:='smtp'; - Username:=''; - Password:=''; - SystemName:=sock.localname; + FFullResult := TStringList.Create; + FESMTPcap := TStringList.Create; + FSock := TTCPBlockSocket.Create; + FSock.CreateSocket; + FTimeout := 300000; + FSMTPhost := cLocalhost; + FSMTPPort := cSmtpProtocol; + FUsername := ''; + FPassword := ''; + FSystemName := FSock.LocalName; end; -{TSMTPSend.Destroy} -Destructor TSMTPSend.Destroy; +destructor TSMTPSend.Destroy; begin - Sock.free; - ESMTPcap.free; - FullResult.free; - inherited destroy; + FSock.Free; + FESMTPcap.Free; + FFullResult.Free; + inherited Destroy; end; -{TSMTPSend.EnhancedCode} -procedure TSMTPSend.EnhancedCode (value:string); +procedure TSMTPSend.EnhancedCode(const Value: string); var - s,t:string; - e1,e2,e3:integer; + s, t: string; + e1, e2, e3: Integer; begin - EnhCode1:=0; - EnhCode2:=0; - EnhCode3:=0; - s:=copy(value,5,length(value)-4); - t:=separateleft(s,'.'); - s:=separateright(s,'.'); - if t='' then exit; - if length(t)>1 then exit; - e1:=strtointdef(t,0); - if e1=0 then exit; - t:=separateleft(s,'.'); - s:=separateright(s,'.'); - if t='' then exit; - if length(t)>3 then exit; - e2:=strtointdef(t,0); - t:=separateleft(s,' '); - if t='' then exit; - if length(t)>3 then exit; - e3:=strtointdef(t,0); - EnhCode1:=e1; - EnhCode2:=e2; - EnhCode3:=e3; + FEnhCode1 := 0; + FEnhCode2 := 0; + FEnhCode3 := 0; + s := Copy(Value, 5, Length(Value) - 4); + t := SeparateLeft(s, '.'); + s := SeparateRight(s, '.'); + if t = '' then + Exit; + if Length(t) > 1 then + Exit; + e1 := StrToIntDef(t, 0); + if e1 = 0 then + Exit; + t := SeparateLeft(s, '.'); + s := SeparateRight(s, '.'); + if t = '' then + Exit; + if Length(t) > 3 then + Exit; + e2 := StrToIntDef(t, 0); + t := SeparateLeft(s, ' '); + if t = '' then + Exit; + if Length(t) > 3 then + Exit; + e3 := StrToIntDef(t, 0); + FEnhCode1 := e1; + FEnhCode2 := e2; + FEnhCode3 := e3; end; -{TSMTPSend.ReadResult} -function TSMTPSend.ReadResult:integer; +function TSMTPSend.ReadResult: Integer; var - s:string; + s: string; begin - Result:=0; - FullResult.Clear; + Result := 0; + FFullResult.Clear; repeat - s:=sock.recvstring(timeout); - ResultString:=s; - FullResult.add(s); - if sock.LastError<>0 then - break; - until pos('-',s)<>4; - s:=FullResult[0]; - if Length(s)>=3 then Result:=Strtointdef(Copy(s,1,3),0); - ResultCode:=Result; + s := FSock.RecvString(FTimeout); + FResultString := s; + FFullResult.Add(s); + if FSock.LastError <> 0 then + Break; + until Pos('-', s) <> 4; + s := FFullResult[0]; + if Length(s) >= 3 then + Result := StrToIntDef(Copy(s, 1, 3), 0); + FResultCode := Result; EnhancedCode(s); end; -{TSMTPSend.AuthLogin} -function TSMTPSend.AuthLogin:Boolean; +function TSMTPSend.AuthLogin: Boolean; begin - Result:=false; - Sock.SendString('AUTH LOGIN'+CRLF); - if readresult<>334 then Exit; - Sock.SendString(Encodebase64(username)+CRLF); - if readresult<>334 then Exit; - Sock.SendString(Encodebase64(password)+CRLF); - if readresult<>235 then Exit; - Result:=True; + Result := False; + FSock.SendString('AUTH LOGIN' + CRLF); + if ReadResult <> 334 then + Exit; + FSock.SendString(EncodeBase64(FUsername) + CRLF); + if ReadResult <> 334 then + Exit; + FSock.SendString(EncodeBase64(FPassword) + CRLF); + Result := ReadResult = 235; end; -{TSMTPSend.AuthCram} -function TSMTPSend.AuthCram:Boolean; +function TSMTPSend.AuthCram: Boolean; var - s:string; + s: string; begin - Result:=false; - Sock.SendString('AUTH CRAM-MD5'+CRLF); - if readresult<>334 then Exit; - s:=copy(ResultString,5,length(ResultString)-4); - s:=DecodeBase64(s); - s:=HMAC_MD5(s,password); - s:=Username+' '+strtohex(s); - Sock.SendString(Encodebase64(s)+CRLF); - if readresult<>235 then Exit; - Result:=True; + Result := False; + FSock.SendString('AUTH CRAM-MD5' + CRLF); + if ReadResult <> 334 then + Exit; + s := Copy(FResultString, 5, Length(FResultString) - 4); + s := DecodeBase64(s); + s := HMAC_MD5(s, FPassword); + s := FUsername + ' ' + StrToHex(s); + FSock.SendString(EncodeBase64(s) + CRLF); + Result := ReadResult = 235; end; -{TSMTPSend.Connect} -function TSMTPSend.Connect:Boolean; +function TSMTPSend.Connect: Boolean; begin - Result:=false; - sock.CloseSocket; - sock.CreateSocket; - sock.Connect(SMTPHost,SMTPPort); - if sock.lasterror<>0 then Exit; - Result:=True; + FSock.CloseSocket; + FSock.CreateSocket; + FSock.Connect(FSMTPHost, FSMTPPort); + Result := FSock.LastError = 0; end; -{TSMTPSend.Helo} -function TSMTPSend.Helo:Boolean; +function TSMTPSend.Helo: Boolean; var - x:integer; + x: Integer; begin - Result:=false; - Sock.SendString('HELO '+SystemName+CRLF); - x:=ReadResult; - if (x<250) or (x>259) then Exit; - Result:=True; + FSock.SendString('HELO ' + FSystemName + CRLF); + x := ReadResult; + Result := (x >= 250) and (x <= 259); end; -{TSMTPSend.Ehlo} -function TSMTPSend.Ehlo:Boolean; +function TSMTPSend.Ehlo: Boolean; var - x:integer; + x: Integer; begin - Result:=false; - Sock.SendString('EHLO '+SystemName+CRLF); - x:=ReadResult; - if (x<250) or (x>259) then Exit; - Result:=True; + FSock.SendString('EHLO ' + FSystemName + CRLF); + x := ReadResult; + Result := (x >= 250) and (x <= 259); end; -{TSMTPSend.login} -function TSMTPSend.login:Boolean; +function TSMTPSend.Login: Boolean; var - n:integer; - auths:string; - s:string; + n: Integer; + auths: string; + s: string; begin - Result:=False; - ESMTP:=true; - AuthDone:=false; - ESMTPcap.clear; - ESMTPSize:=false; - MaxSize:=0; - if not Connect then Exit; - if readresult<>220 then Exit; + Result := False; + FESMTP := True; + FAuthDone := False; + FESMTPcap.clear; + FESMTPSize := False; + FMaxSize := 0; + if not Connect then + Exit; + if ReadResult <> 220 then + Exit; if not Ehlo then + begin + FESMTP := False; + if not Helo then + Exit; + end; + Result := True; + if FESMTP then + begin + for n := 1 to FFullResult.Count - 1 do + FESMTPcap.Add(Copy(FFullResult[n], 5, Length(FFullResult[n]) - 4)); + if not ((FUsername = '') and (FPassword = '')) then begin - ESMTP:=false; - if not Helo then exit; - end; - Result:=True; - if ESMTP then - begin - for n:=1 to FullResult.count-1 do - ESMTPcap.add(Copy(FullResult[n],5,length(Fullresult[n])-4)); - if not ((Username='') and (Password='')) then - begin - s:=FindCap('AUTH '); - if s='' - then s:=FindCap('AUTH='); - auths:=uppercase(s); - if s<>'' then - begin - if pos('CRAM-MD5',auths)>0 - then AuthDone:=AuthCram; - if (pos('LOGIN',auths)>0) and (not authDone) - then AuthDone:=AuthLogin; - end; - if AuthDone - then Ehlo; - end; - s:=FindCap('SIZE'); - if s<>'' then - begin - ESMTPsize:=true; - MaxSize:=StrToIntDef(copy(s,6,length(s)-5),0); - end; - end; -end; - -{TSMTPSend.logout} -procedure TSMTPSend.logout; -begin - Sock.SendString('QUIT'+CRLF); - readresult; - Sock.CloseSocket; -end; - -{TSMTPSend.reset} -function TSMTPSend.reset:Boolean; -begin - Result:=false; - Sock.SendString('RSET'+CRLF); - if readresult<>250 then Exit; - Result:=True; -end; - -{TSMTPSend.noop} -function TSMTPSend.noop:Boolean; -begin - Result:=false; - Sock.SendString('NOOP'+CRLF); - if readresult<>250 then Exit; - Result:=True; -end; - - -{TSMTPSend.mailfrom} -function TSMTPSend.mailfrom(Value:string; size:integer):Boolean; -var - s:string; -begin - Result:=false; - s:='MAIL FROM:<'+Value+'>'; - if ESMTPsize and (size>0) - then s:=s+' SIZE='+IntToStr(size); - Sock.SendString(s+CRLF); - if readresult<>250 then Exit; - Result:=True; -end; - -{TSMTPSend.mailto} -function TSMTPSend.mailto(Value:string):Boolean; -begin - Result:=false; - Sock.SendString('RCPT TO:<'+Value+'>'+CRLF); - if readresult<>250 then Exit; - Result:=True; -end; - -{TSMTPSend.maildata} -function TSMTPSend.maildata(Value:Tstrings):Boolean; -var - n:integer; - s:string; -begin - Result:=false; - Sock.SendString('DATA'+CRLF); - if readresult<>354 then Exit; - for n:=0 to Value.Count-1 do - begin - s:=value[n]; - if Length(s)>=1 then - if s[1]='.' then s:='.'+s; - Sock.SendString(s+CRLF); - end; - Sock.SendString('.'+CRLF); - if readresult<>250 then Exit; - Result:=True; -end; - -{TSMTPSend.etrn} -function TSMTPSend.etrn(Value:string):Boolean; -var - x:integer; -begin - Result:=false; - Sock.SendString('ETRN '+Value+CRLF); - x:=ReadResult; - if (x<250) or (x>259) then Exit; - Result:=True; -end; - -{TSMTPSend.verify} -function TSMTPSend.verify(Value:string):Boolean; -var - x:integer; -begin - Result:=false; - Sock.SendString('VRFY '+Value+CRLF); - x:=ReadResult; - if (x<250) or (x>259) then Exit; - Result:=True; -end; - -{TSMTPSend.EnhCodeString} -function TSMTPSend.EnhCodeString:string; -var - s,t:string; -begin - s:=inttostr(EnhCode2)+'.'+inttostr(EnhCode3); - t:=''; - if s='0.0' then t:='Other undefined Status'; - if s='1.0' then t:='Other address status'; - if s='1.1' then t:='Bad destination mailbox address'; - if s='1.2' then t:='Bad destination system address'; - if s='1.3' then t:='Bad destination mailbox address syntax'; - if s='1.4' then t:='Destination mailbox address ambiguous'; - if s='1.5' then t:='Destination mailbox address valid'; - if s='1.6' then t:='Mailbox has moved'; - if s='1.7' then t:='Bad sender''s mailbox address syntax'; - if s='1.8' then t:='Bad sender''s system address'; - if s='2.0' then t:='Other or undefined mailbox status'; - if s='2.1' then t:='Mailbox disabled, not accepting messages'; - if s='2.2' then t:='Mailbox full'; - if s='2.3' then t:='Message length exceeds administrative limit'; - if s='2.4' then t:='Mailing list expansion problem'; - if s='3.0' then t:='Other or undefined mail system status'; - if s='3.1' then t:='Mail system full'; - if s='3.2' then t:='System not accepting network messages'; - if s='3.3' then t:='System not capable of selected features'; - if s='3.4' then t:='Message too big for system'; - if s='3.5' then t:='System incorrectly configured'; - if s='4.0' then t:='Other or undefined network or routing status'; - if s='4.1' then t:='No answer from host'; - if s='4.2' then t:='Bad connection'; - if s='4.3' then t:='Routing server failure'; - if s='4.4' then t:='Unable to route'; - if s='4.5' then t:='Network congestion'; - if s='4.6' then t:='Routing loop detected'; - if s='4.7' then t:='Delivery time expired'; - if s='5.0' then t:='Other or undefined protocol status'; - if s='5.1' then t:='Invalid command'; - if s='5.2' then t:='Syntax error'; - if s='5.3' then t:='Too many recipients'; - if s='5.4' then t:='Invalid command arguments'; - if s='5.5' then t:='Wrong protocol version'; - if s='6.0' then t:='Other or undefined media error'; - if s='6.1' then t:='Media not supported'; - if s='6.2' then t:='Conversion required and prohibited'; - if s='6.3' then t:='Conversion required but not supported'; - if s='6.4' then t:='Conversion with loss performed'; - if s='6.5' then t:='Conversion failed'; - if s='7.0' then t:='Other or undefined security status'; - if s='7.1' then t:='Delivery not authorized, message refused'; - if s='7.2' then t:='Mailing list expansion prohibited'; - if s='7.3' then t:='Security conversion required but not possible'; - if s='7.4' then t:='Security features not supported'; - if s='7.5' then t:='Cryptographic failure'; - if s='7.6' then t:='Cryptographic algorithm not supported'; - if s='7.7' then t:='Message integrity failure'; - s:='???-'; - if EnhCode1=2 then s:='Success-'; - if EnhCode1=4 then s:='Persistent Transient Failure-'; - if EnhCode1=5 then s:='Permanent Failure-'; - result:=s+t; -end; - -{TSMTPSend.FindCap} -function TSMTPSend.FindCap(value:string):string; -var - n:integer; - s:string; -begin - s:=uppercase(value); - result:=''; - for n:=0 to ESMTPcap.count-1 do - if pos(s,uppercase(ESMTPcap[n]))=1 then + s := FindCap('AUTH '); + if s = '' then + s := FindCap('AUTH='); + auths := UpperCase(s); + if s <> '' then begin - result:=ESMTPcap[n]; - break; + if Pos('CRAM-MD5', auths) > 0 then + FAuthDone := AuthCram; + if (Pos('LOGIN', auths) > 0) and (not FauthDone) then + FAuthDone := AuthLogin; end; + if FAuthDone then + Ehlo; + end; + s := FindCap('SIZE'); + if s <> '' then + begin + FESMTPsize := True; + FMaxSize := StrToIntDef(Copy(s, 6, Length(s) - 5), 0); + end; + end; +end; + +procedure TSMTPSend.Logout; +begin + FSock.SendString('QUIT' + CRLF); + ReadResult; + FSock.CloseSocket; +end; + +function TSMTPSend.Reset: Boolean; +begin + FSock.SendString('RSET' + CRLF); + Result := ReadResult = 250; +end; + +function TSMTPSend.NoOp: Boolean; +begin + FSock.SendString('NOOP' + CRLF); + Result := ReadResult = 250; +end; + +function TSMTPSend.MailFrom(const Value: string; Size: Integer): Boolean; +var + s: string; +begin + s := 'MAIL FROM:<' + Value + '>'; + if FESMTPsize and (Size > 0) then + s := s + ' SIZE=' + IntToStr(Size); + FSock.SendString(s + CRLF); + Result := ReadResult = 250; +end; + +function TSMTPSend.MailTo(const Value: string): Boolean; +begin + FSock.SendString('RCPT TO:<' + Value + '>' + CRLF); + Result := ReadResult = 250; +end; + +function TSMTPSend.MailData(const Value: TStrings): Boolean; +var + n: Integer; + s: string; +begin + Result := False; + FSock.SendString('DATA' + CRLF); + if ReadResult <> 354 then + Exit; + for n := 0 to Value.Count - 1 do + begin + s := Value[n]; + if Length(s) >= 1 then + if s[1] = '.' then + s := '.' + s; + FSock.SendString(s + CRLF); + end; + FSock.SendString('.' + CRLF); + Result := ReadResult = 250; +end; + +function TSMTPSend.Etrn(const Value: string): Boolean; +var + x: Integer; +begin + FSock.SendString('ETRN ' + Value + CRLF); + x := ReadResult; + Result := (x >= 250) and (x <= 259); +end; + +function TSMTPSend.Verify(const Value: string): Boolean; +var + x: Integer; +begin + FSock.SendString('VRFY ' + Value + CRLF); + x := ReadResult; + Result := (x >= 250) and (x <= 259); +end; + +function TSMTPSend.EnhCodeString: string; +var + s, t: string; +begin + s := IntToStr(FEnhCode2) + '.' + IntToStr(FEnhCode3); + t := ''; + if s = '0.0' then t := 'Other undefined Status'; + if s = '1.0' then t := 'Other address status'; + if s = '1.1' then t := 'Bad destination mailbox address'; + if s = '1.2' then t := 'Bad destination system address'; + if s = '1.3' then t := 'Bad destination mailbox address syntax'; + if s = '1.4' then t := 'Destination mailbox address ambiguous'; + if s = '1.5' then t := 'Destination mailbox address valid'; + if s = '1.6' then t := 'Mailbox has moved'; + if s = '1.7' then t := 'Bad sender''s mailbox address syntax'; + if s = '1.8' then t := 'Bad sender''s system address'; + if s = '2.0' then t := 'Other or undefined mailbox status'; + if s = '2.1' then t := 'Mailbox disabled, not accepting messages'; + if s = '2.2' then t := 'Mailbox full'; + if s = '2.3' then t := 'Message Length exceeds administrative limit'; + if s = '2.4' then t := 'Mailing list expansion problem'; + if s = '3.0' then t := 'Other or undefined mail system status'; + if s = '3.1' then t := 'Mail system full'; + if s = '3.2' then t := 'System not accepting network messages'; + if s = '3.3' then t := 'System not capable of selected features'; + if s = '3.4' then t := 'Message too big for system'; + if s = '3.5' then t := 'System incorrectly configured'; + if s = '4.0' then t := 'Other or undefined network or routing status'; + if s = '4.1' then t := 'No answer from host'; + if s = '4.2' then t := 'Bad connection'; + if s = '4.3' then t := 'Routing server failure'; + if s = '4.4' then t := 'Unable to route'; + if s = '4.5' then t := 'Network congestion'; + if s = '4.6' then t := 'Routing loop detected'; + if s = '4.7' then t := 'Delivery time expired'; + if s = '5.0' then t := 'Other or undefined protocol status'; + if s = '5.1' then t := 'Invalid command'; + if s = '5.2' then t := 'Syntax error'; + if s = '5.3' then t := 'Too many recipients'; + if s = '5.4' then t := 'Invalid command arguments'; + if s = '5.5' then t := 'Wrong protocol version'; + if s = '6.0' then t := 'Other or undefined media error'; + if s = '6.1' then t := 'Media not supported'; + if s = '6.2' then t := 'Conversion required and prohibited'; + if s = '6.3' then t := 'Conversion required but not supported'; + if s = '6.4' then t := 'Conversion with loss performed'; + if s = '6.5' then t := 'Conversion failed'; + if s = '7.0' then t := 'Other or undefined security status'; + if s = '7.1' then t := 'Delivery not authorized, message refused'; + if s = '7.2' then t := 'Mailing list expansion prohibited'; + if s = '7.3' then t := 'Security conversion required but not possible'; + if s = '7.4' then t := 'Security features not supported'; + if s = '7.5' then t := 'Cryptographic failure'; + if s = '7.6' then t := 'Cryptographic algorithm not supported'; + if s = '7.7' then t := 'Message integrity failure'; + s := '???-'; + if FEnhCode1 = 2 then s := 'Success-'; + if FEnhCode1 = 4 then s := 'Persistent Transient Failure-'; + if FEnhCode1 = 5 then s := 'Permanent Failure-'; + Result := s + t; +end; + +function TSMTPSend.FindCap(const Value: string): string; +var + n: Integer; + s: string; +begin + s := UpperCase(Value); + Result := ''; + for n := 0 to FESMTPcap.Count - 1 do + if Pos(s, UpperCase(FESMTPcap[n])) = 1 then + begin + Result := FESMTPcap[n]; + Break; + end; end; {==============================================================================} -function SendtoRaw (mailfrom,mailto,SMTPHost:string;maildata:TStrings; - Username,Password:string):Boolean; +function SendToRaw(const MailFrom, MailTo, SMTPHost: string; + const MailData: TStrings; const Username, Password: string): Boolean; var - SMTP:TSMTPSend; - size:integer; + SMTP: TSMTPSend; begin - Result:=False; - SMTP:=TSMTPSend.Create; + Result := False; + SMTP := TSMTPSend.Create; try - SMTP.SMTPHost:=SMTPHost; - SMTP.Username:=Username; - SMTP.Password:=Password; - if not SMTP.login then Exit; - size:=length(maildata.text); - if not SMTP.mailfrom(mailfrom,size) then Exit; - if not SMTP.mailto(mailto) then Exit; - if not SMTP.maildata(Maildata) then Exit; - SMTP.logout; - Result:=True; + SMTP.SMTPHost := SMTPHost; + SMTP.Username := Username; + SMTP.Password := Password; + if SMTP.Login then + begin + if SMTP.MailFrom(MailFrom, Length(MailData.Text)) then + if SMTP.MailTo(MailTo) then + if SMTP.MailData(MailData) then + Result := True; + SMTP.Logout; + end; finally SMTP.Free; end; end; -function SendtoEx (mailfrom,mailto,subject,SMTPHost:string;maildata:TStrings; - Username,Password:string):Boolean; +function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string; + const MailData: TStrings; const Username, Password: string): Boolean; var - t:TStrings; + t: TStrings; begin -// Result:=False; - t:=TStringList.Create; + t := TStringList.Create; try - t.assign(Maildata); - t.Insert(0,''); - t.Insert(0,'x-mailer: Synapse - Delphi TCP/IP library by Lukas Gebauer'); - t.Insert(0,'subject: '+subject); - t.Insert(0,'date: '+Rfc822DateTime(now)); - t.Insert(0,'to: '+mailto); - t.Insert(0,'from: '+mailfrom); - Result:=SendToRaw(mailfrom,mailto,SMTPHost,t,Username,Password); + t.Assign(MailData); + t.Insert(0, ''); + t.Insert(0, 'x-mailer: Synapse - Delphi TCP/IP library by Lukas Gebauer'); + t.Insert(0, 'subject: ' + Subject); + t.Insert(0, 'date: ' + Rfc822DateTime(now)); + t.Insert(0, 'to: ' + MailTo); + t.Insert(0, 'from: ' + MailFrom); + Result := SendToRaw(MailFrom, MailTo, SMTPHost, t, Username, Password); finally t.Free; end; end; -function Sendto -(mailfrom,mailto,subject,SMTPHost:string;maildata:TStrings):Boolean; +function SendTo(const MailFrom, MailTo, Subject, SMTPHost: string; + const MailData: TStrings): Boolean; begin - result:=SendToEx(mailfrom,mailto,subject,SMTPHost,maildata,'',''); + Result := SendToEx(MailFrom, MailTo, Subject, SMTPHost, MailData, '', ''); end; end. - - diff --git a/snmpsend.pas b/snmpsend.pas index a32d2d9..7ff7b84 100644 --- a/snmpsend.pas +++ b/snmpsend.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.003.001 | +| Project : Delphree - Synapse | 002.003.002 | |==============================================================================| | Content: SNMP client | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -25,201 +25,213 @@ |==============================================================================} {$Q-} +{$WEAKPACKAGEUNIT ON} unit SNMPSend; interface uses - BlckSock, synautil, classes, sysutils, ASN1Util; + Classes, SysUtils, + blckSock, SynaUtil, ASN1Util; const + cSnmpProtocol = '161'; //PDU type -PDUGetRequest=$a0; -PDUGetNextRequest=$a1; -PDUGetResponse=$a2; -PDUSetRequest=$a3; -PDUTrap=$a4; + PDUGetRequest = $A0; + PDUGetNextRequest = $A1; + PDUGetResponse = $A2; + PDUSetRequest = $A3; + PDUTrap = $A4; //errors -ENoError=0; -ETooBig=1; -ENoSuchName=2; -EBadValue=3; -EReadOnly=4; -EGenErr=5; + ENoError = 0; + ETooBig = 1; + ENoSuchName = 2; + EBadValue = 3; + EReadOnly = 4; + EGenErr = 5; type - -TSNMPMib = class - OID: string; - Value: string; - ValueType: integer; -end; - -TSNMPRec=class(TObject) - public - version:integer; - community:string; - PDUType:integer; - ID:integer; - ErrorStatus:integer; - ErrorIndex:integer; - SNMPMibList: TList; - constructor Create; - destructor Destroy; override; - function DecodeBuf(Buffer:string):boolean; - function EncodeBuf:string; - procedure Clear; - procedure MIBAdd(MIB,Value:string; ValueType:integer); - procedure MIBdelete(Index:integer); - function MIBGet(MIB:string):string; -end; - -TSNMPSend=class(TObject) + TSNMPMib = class(TObject) private - Sock:TUDPBlockSocket; - Buffer:string; + FOID: string; + FValue: string; + FValueType: Integer; + published + property OID: string read FOID Write FOID; + property Value: string read FValue Write FValue; + property ValueType: Integer read FValueType Write FValueType; + end; + + TSNMPRec = class(TObject) + private + FVersion: Integer; + FCommunity: string; + FPDUType: Integer; + FID: Integer; + FErrorStatus: Integer; + FErrorIndex: Integer; + FSNMPMibList: TList; public - Timeout:integer; - Host:string; - HostIP:string; - Query:TSNMPrec; - Reply:TSNMPrec; constructor Create; destructor Destroy; override; - function DoIt:boolean; -end; + function DecodeBuf(const Buffer: string): Boolean; + function EncodeBuf: string; + procedure Clear; + procedure MIBAdd(const MIB, Value: string; ValueType: Integer); + procedure MIBDelete(Index: Integer); + function MIBGet(const MIB: string): string; + published + property Version: Integer read FVersion Write FVersion; + property Community: string read FCommunity Write FCommunity; + property PDUType: Integer read FPDUType Write FPDUType; + property ID: Integer read FID Write FID; + property ErrorStatus: Integer read FErrorStatus Write FErrorStatus; + property ErrorIndex: Integer read FErrorIndex Write FErrorIndex; + property SNMPMibList: TList read FSNMPMibList; + end; -function SNMPget (Oid, Community, SNMPHost:string; var Value:string):Boolean; -function SNMPSet (Oid, Community, SNMPHost, Value: string; ValueType: integer): boolean; + TSNMPSend = class(TObject) + private + FSock: TUDPBlockSocket; + FBuffer: string; + FTimeout: Integer; + FHost: string; + FHostIP: string; + FQuery: TSNMPRec; + FReply: TSNMPRec; + public + constructor Create; + destructor Destroy; override; + function DoIt: Boolean; + published + property Timeout: Integer read FTimeout Write FTimeout; + property Host: string read FHost Write FHost; + property HostIP: string read FHostIP; + property Query: TSNMPRec read FQuery; + property Reply: TSNMPRec read FReply; + end; + +function SNMPGet(const Oid, Community, SNMPHost: string; + var Value: string): Boolean; +function SNMPSet(const Oid, Community, SNMPHost, Value: string; + ValueType: Integer): Boolean; implementation {==============================================================================} -{TSNMPRec.Create} constructor TSNMPRec.Create; begin - inherited create; - SNMPMibList := TList.create; - id:=1; + inherited Create; + FSNMPMibList := TList.Create; + id := 1; end; -{TSNMPRec.Destroy} destructor TSNMPRec.Destroy; var - i:integer; + i: Integer; begin - for i := 0 to SNMPMibList.count - 1 do - TSNMPMib(SNMPMibList[i]).Free; - SNMPMibList.free; - inherited destroy; + for i := 0 to FSNMPMibList.Count - 1 do + TSNMPMib(FSNMPMibList[i]).Free; + FSNMPMibList.Free; + inherited Destroy; end; -{TSNMPRec.DecodeBuf} -function TSNMPRec.DecodeBuf(Buffer:string):boolean; +function TSNMPRec.DecodeBuf(const Buffer: string): Boolean; var - Pos:integer; - endpos:integer; - sm,sv:string; - svt: integer; + Pos: Integer; + EndPos: Integer; + sm, sv: string; + Svt: Integer; begin - result:=false; - if length(buffer)<2 - then exit; - if (ord(buffer[1]) and $20)=0 - then exit; - Pos:=2; - Endpos:=ASNDecLen(Pos,buffer); - if length(buffer)<(Endpos+2) - then exit; - Self.version:=StrToIntDef(ASNItem(Pos,buffer,svt),0); - Self.community:=ASNItem(Pos,buffer,svt); - Self.PDUType:=StrToIntDef(ASNItem(Pos,buffer,svt),0); - Self.ID:=StrToIntDef(ASNItem(Pos,buffer,svt),0); - Self.ErrorStatus:=StrToIntDef(ASNItem(Pos,buffer,svt),0); - Self.ErrorIndex:=StrToIntDef(ASNItem(Pos,buffer,svt),0); - ASNItem(Pos,buffer,svt); - while Pos= 0) and (Index < SNMPMibList.count) then - begin - TSNMPMib(SNMPMibList[Index]).Free; - SNMPMibList.Delete(Index); - end; + if (Index >= 0) and (Index < FSNMPMibList.Count) then + begin + TSNMPMib(FSNMPMibList[Index]).Free; + FSNMPMibList.Delete(Index); + end; end; -{TSNMPRec.MIBGet} -function TSNMPRec.MIBGet(MIB:string):string; +function TSNMPRec.MIBGet(const MIB: string): string; var - i: integer; + i: Integer; begin Result := ''; - for i := 0 to SNMPMibList.count - 1 do + for i := 0 to FSNMPMibList.Count - 1 do + begin + if ((TSNMPMib(FSNMPMibList[i])).OID = MIB) then begin - if ((TSNMPMib(SNMPMibList[i])).OID = MIB) then - begin - Result := (TSNMPMib(SNMPMibList[i])).Value; - break; - end; + Result := (TSNMPMib(FSNMPMibList[i])).Value; + Break; end; + end; end; - {==============================================================================} -{TSNMPSend.Create} constructor TSNMPSend.Create; begin - inherited create; - Query:=TSNMPRec.Create; - Reply:=TSNMPRec.Create; - Query.Clear; - Reply.Clear; - sock:=TUDPBlockSocket.create; - sock.createsocket; - timeout:=5000; - host:='localhost'; - HostIP:=''; + inherited Create; + FQuery := TSNMPRec.Create; + FReply := TSNMPRec.Create; + FQuery.Clear; + FReply.Clear; + FSock := TUDPBlockSocket.Create; + FSock.CreateSocket; + FTimeout := 5000; + FHost := cLocalhost; + FHostIP := ''; end; -{TSNMPSend.Destroy} destructor TSNMPSend.Destroy; begin - Sock.Free; - Reply.Free; - Query.Free; - inherited destroy; + FSock.Free; + FReply.Free; + FQuery.Free; + inherited Destroy; end; -{TSNMPSend.DoIt} -function TSNMPSend.DoIt:boolean; +function TSNMPSend.DoIt: Boolean; var - x:integer; + x: Integer; begin - Result:=false; - reply.clear; - Buffer:=Query.Encodebuf; - sock.connect(host,'161'); - HostIP:=sock.GetRemoteSinIP; - sock.SendBuffer(PChar(Buffer),Length(Buffer)); - if sock.canread(timeout) - then begin - x:=sock.WaitingData; - if x>0 then - begin - setlength(Buffer,x); - sock.RecvBuffer(PChar(Buffer),x); - result:=true; - end; + Result := False; + FReply.Clear; + FBuffer := Query.EncodeBuf; + FSock.Connect(FHost, cSnmpProtocol); + FHostIP := FSock.GetRemoteSinIP; + FSock.SendBuffer(PChar(FBuffer), Length(FBuffer)); + if FSock.CanRead(FTimeout) then + begin + x := FSock.WaitingData; + if x > 0 then + begin + SetLength(FBuffer, x); + FSock.RecvBuffer(PChar(FBuffer), x); + Result := True; end; - if Result - then result:=reply.DecodeBuf(Buffer); + end; + if Result then + Result := FReply.DecodeBuf(FBuffer); end; {==============================================================================} -function SNMPget (Oid, Community, SNMPHost:string; var Value:string):Boolean; +function SNMPGet(const Oid, Community, SNMPHost: string; + var Value: string): Boolean; var - SNMP:TSNMPSend; + SNMP: TSNMPSend; begin - SNMP:=TSNMPSend.Create; + SNMP := TSNMPSend.Create; try - Snmp.Query.community:=Community; - Snmp.Query.PDUType:=PDUGetRequest; - Snmp.Query.MIBAdd(Oid,'',ASN1_NULL); - Snmp.host:=SNMPHost; - Result:=Snmp.DoIt; + SNMP.Query.Community := Community; + SNMP.Query.PDUType := PDUGetRequest; + SNMP.Query.MIBAdd(Oid, '', ASN1_NULL); + SNMP.Host := SNMPHost; + Result := SNMP.DoIt; if Result then - Value:=Snmp.Reply.MIBGet(Oid); + Value := SNMP.Reply.MIBGet(Oid); finally SNMP.Free; end; end; -function SNMPSet(Oid, Community, SNMPHost, Value: string; ValueType: integer): boolean; +function SNMPSet(const Oid, Community, SNMPHost, Value: string; + ValueType: Integer): Boolean; var SNMPSend: TSNMPSend; begin SNMPSend := TSNMPSend.Create; try - SNMPSend.Query.community := Community; + SNMPSend.Query.Community := Community; SNMPSend.Query.PDUType := PDUSetRequest; SNMPSend.Query.MIBAdd(Oid, Value, ValueType); SNMPSend.Host := SNMPHost; - result:= SNMPSend.DoIt=true; + Result := SNMPSend.DoIt = True; finally SNMPSend.Free; end; end; - end. diff --git a/snmptrap.pas b/snmptrap.pas index 57a97c4..3f63f59 100644 --- a/snmptrap.pas +++ b/snmptrap.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.002.001 | +| Project : Delphree - Synapse | 002.002.002 | |==============================================================================| | Content: SNMP traps | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -25,105 +25,123 @@ |==============================================================================} {$Q-} +{$WEAKPACKAGEUNIT ON} unit SNMPTrap; interface uses - Classes, SysUtils, BlckSock, SynaUtil, ASN1Util, SNMPsend; + Classes, SysUtils, + blckSock, SynaUtil, ASN1Util, SNMPSend; const - TRAP_PORT = 162; + cSnmpTrapProtocol = '162'; - SNMP_VERSION = 0; + SNMP_VERSION = 0; - PDU_GET = $A0; - PDU_GETN = $A1; - PDU_RESP = $A2; - PDU_SET = $A3; - PDU_TRAP = $A4; + PDU_GET = $A0; + PDU_GETN = $A1; + PDU_RESP = $A2; + PDU_SET = $A3; + PDU_TRAP = $A4; type TTrapPDU = class(TObject) - private - protected - Buffer: string; - public - TrapPort: integer; - Version: integer; - PDUType: integer; - Community: string; - Enterprise: string; - TrapHost: string; - GenTrap: integer; - SpecTrap: integer; - TimeTicks: integer; - SNMPMibList: TList; - constructor Create; - destructor Destroy; override; - procedure Clear; - procedure MIBAdd(MIB, Value: string; ValueType:integer); - procedure MIBDelete(Index: integer); - function MIBGet(MIB: string): string; - function EncodeTrap: integer; - function DecodeTrap: boolean; + private + FBuffer: string; + FTrapPort: string; + FVersion: Integer; + FPDUType: Integer; + FCommunity: string; + FEnterprise: string; + FTrapHost: string; + FGenTrap: Integer; + FSpecTrap: Integer; + FTimeTicks: Integer; + FSNMPMibList: TList; + public + constructor Create; + destructor Destroy; override; + procedure Clear; + procedure MIBAdd(const MIB, Value: string; ValueType: Integer); + procedure MIBDelete(Index: Integer); + function MIBGet(const MIB: string): string; + function EncodeTrap: Integer; + function DecodeTrap: Boolean; + published + property Version: Integer read FVersion Write FVersion; + property Community: string read FCommunity Write FCommunity; + property PDUType: Integer read FPDUType Write FPDUType; + property TrapPort: string read FTrapPort Write FTrapPort; + property Enterprise: string read FEnterprise Write FEnterprise; + property TrapHost: string read FTrapHost Write FTrapHost; + property GenTrap: Integer read FGenTrap Write FGenTrap; + property SpecTrap: Integer read FSpecTrap Write FSpecTrap; + property TimeTicks: Integer read FTimeTicks Write FTimeTicks; + property SNMPMibList: TList read FSNMPMibList; end; TTrapSNMP = class(TObject) private - sock: TUDPBlockSocket; + FSock: TUDPBlockSocket; + FTrap: TTrapPDU; + FSNMPHost: string; + FTimeout: Integer; public - Trap: TTrapPDU; - SNMPHost: string; - Timeout: integer; constructor Create; destructor Destroy; override; - function Send: integer; - function Recv: integer; + function Send: Integer; + function Recv: Integer; + published + property Trap: TTrapPDU read FTrap; + property SNMPHost: string read FSNMPHost Write FSNMPHost; + property Timeout: Integer read FTimeout Write FTimeout; end; -function SendTrap(Dest, Source, Enterprise, Community: string; - Generic, Specific, Seconds: integer; MIBName, MIBValue: string; MIBtype:integer): integer; +function SendTrap(const Dest, Source, Enterprise, Community: string; + Generic, Specific, Seconds: Integer; const MIBName, MIBValue: string; + MIBtype: Integer): Integer; function RecvTrap(var Dest, Source, Enterprise, Community: string; - var Generic, Specific, Seconds: integer; var MIBName, MIBValue: TStringList): integer; + var Generic, Specific, Seconds: Integer; const MIBName, + MIBValue: TStringList): Integer; implementation constructor TTrapPDU.Create; begin inherited Create; - SNMPMibList := TList.create; - TrapPort := TRAP_PORT; - Version := SNMP_VERSION; - PDUType := PDU_TRAP; - Community := 'public'; + FSNMPMibList := TList.Create; + FTrapPort := cSnmpTrapProtocol; + FVersion := SNMP_VERSION; + FPDUType := PDU_TRAP; + FCommunity := 'public'; end; destructor TTrapPDU.Destroy; var - i:integer; + i: Integer; begin - for i := 0 to SNMPMibList.count - 1 do - TSNMPMib(SNMPMibList[i]).Free; - SNMPMibList.free; + for i := 0 to FSNMPMibList.Count - 1 do + TSNMPMib(FSNMPMibList[i]).Free; + FSNMPMibList.Free; inherited Destroy; end; procedure TTrapPDU.Clear; var - i:integer; + i: Integer; begin - for i := 0 to SNMPMibList.count - 1 do - TSNMPMib(SNMPMibList[i]).Free; - SNMPMibList.Clear; - TrapPort := TRAP_PORT; - Version := SNMP_VERSION; - PDUType := PDU_TRAP; - Community := 'public'; + for i := 0 to FSNMPMibList.Count - 1 do + TSNMPMib(FSNMPMibList[i]).Free; + FSNMPMibList.Clear; + FTrapPort := cSnmpTrapProtocol; + FVersion := SNMP_VERSION; + FPDUType := PDU_TRAP; + FCommunity := 'public'; end; -procedure TTrapPDU.MIBAdd(MIB, Value: string; ValueType:integer); +procedure TTrapPDU.MIBAdd(const MIB, Value: string; ValueType: Integer); var SNMPMib: TSNMPMib; begin @@ -131,216 +149,207 @@ begin SNMPMib.OID := MIB; SNMPMib.Value := Value; SNMPMib.ValueType := ValueType; - SNMPMibList.Add(SNMPMib); + FSNMPMibList.Add(SNMPMib); end; -procedure TTrapPDU.MIBDelete(Index: integer); +procedure TTrapPDU.MIBDelete(Index: Integer); begin - if (Index >= 0) and (Index < SNMPMibList.count) then - begin - TSNMPMib(SNMPMibList[Index]).Free; - SNMPMibList.Delete(Index); - end; + if (Index >= 0) and (Index < FSNMPMibList.Count) then + begin + TSNMPMib(FSNMPMibList[Index]).Free; + FSNMPMibList.Delete(Index); + end; end; -function TTrapPDU.MIBGet(MIB: string): string; +function TTrapPDU.MIBGet(const MIB: string): string; var - i: integer; + i: Integer; begin Result := ''; - for i := 0 to SNMPMibList.count - 1 do + for i := 0 to FSNMPMibList.Count - 1 do + begin + if TSNMPMib(FSNMPMibList[i]).OID = MIB then begin - if ((TSNMPMib(SNMPMibList[i])).OID = MIB) then - begin - Result := (TSNMPMib(SNMPMibList[i])).Value; - break; - end; + Result := TSNMPMib(FSNMPMibList[i]).Value; + Break; end; + end; end; -function TTrapPDU.EncodeTrap: integer; +function TTrapPDU.EncodeTrap: Integer; var s: string; - n: integer; + n: Integer; SNMPMib: TSNMPMib; begin - Buffer := ''; - for n:=0 to SNMPMibList.Count-1 do - begin - SNMPMib := SNMPMibList[n]; - case (SNMPMib.ValueType) of - ASN1_INT: - begin - s := ASNObject(MibToID(SNMPMib.OID),ASN1_OBJID) - +ASNObject(ASNEncInt(strToIntDef(SNMPMib.Value,0)),SNMPMib.ValueType); - end; - ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS: - begin - s := ASNObject(MibToID(SNMPMib.OID),ASN1_OBJID) - +ASNObject(ASNEncUInt(strToIntDef(SNMPMib.Value,0)),SNMPMib.ValueType); - end; - ASN1_OBJID: - begin - s := ASNObject(MibToID(SNMPMib.OID),ASN1_OBJID) + ASNObject(MibToID(SNMPMib.Value),SNMPMib.ValueType); - end; - ASN1_IPADDR: - begin - s := ASNObject(MibToID(SNMPMib.OID),ASN1_OBJID) + ASNObject(IPToID(SNMPMib.Value),SNMPMib.ValueType); - end; - ASN1_NULL: - begin - s := ASNObject(MibToID(SNMPMib.OID),ASN1_OBJID) + ASNObject('',ASN1_NULL); - end; - else - s := ASNObject(MibToID(SNMPMib.OID),ASN1_OBJID) + ASNObject(SNMPMib.Value,SNMPMib.ValueType); - end; - Buffer := Buffer + ASNObject(s, ASN1_SEQ); + FBuffer := ''; + for n := 0 to FSNMPMibList.Count - 1 do + begin + SNMPMib := FSNMPMibList[n]; + case SNMPMib.ValueType of + ASN1_INT: + s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) + + ASNObject(ASNEncInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType); + ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS: + s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) + + ASNObject(ASNEncUInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType); + ASN1_OBJID: + s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) + + ASNObject(MibToID(SNMPMib.Value), SNMPMib.ValueType); + ASN1_IPADDR: + s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) + + ASNObject(IPToID(SNMPMib.Value), SNMPMib.ValueType); + ASN1_NULL: + s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) + + ASNObject('', ASN1_NULL); + else + s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) + + ASNObject(SNMPMib.Value, SNMPMib.ValueType); end; - Buffer := ASNObject(Buffer, ASN1_SEQ); - Buffer := ASNObject(ASNEncInt(GenTrap), ASN1_INT) - + ASNObject(ASNEncInt(SpecTrap), ASN1_INT) - + ASNObject(ASNEncUInt(TimeTicks), ASN1_TIMETICKS) - + Buffer; - Buffer := ASNObject(MibToID(Enterprise), ASN1_OBJID) - + ASNObject(IPToID(TrapHost), ASN1_IPADDR) - + Buffer; - Buffer := ASNObject(ASNEncInt(Version), ASN1_INT) - + ASNObject(Community, ASN1_OCTSTR) - + ASNObject(Buffer, Self.PDUType); - Buffer := ASNObject(Buffer, ASN1_SEQ); + FBuffer := FBuffer + ASNObject(s, ASN1_SEQ); + end; + FBuffer := ASNObject(FBuffer, ASN1_SEQ); + FBuffer := ASNObject(ASNEncInt(FGenTrap), ASN1_INT) + + ASNObject(ASNEncInt(FSpecTrap), ASN1_INT) + + ASNObject(ASNEncUInt(FTimeTicks), ASN1_TIMETICKS) + + FBuffer; + FBuffer := ASNObject(MibToID(FEnterprise), ASN1_OBJID) + + ASNObject(IPToID(FTrapHost), ASN1_IPADDR) + + FBuffer; + FBuffer := ASNObject(ASNEncInt(FVersion), ASN1_INT) + + ASNObject(FCommunity, ASN1_OCTSTR) + + ASNObject(FBuffer, Self.FPDUType); + FBuffer := ASNObject(FBuffer, ASN1_SEQ); Result := 1; end; -function TTrapPDU.DecodeTrap: boolean; +function TTrapPDU.DecodeTrap: Boolean; var - Pos, EndPos: integer; + Pos, EndPos: Integer; Sm, Sv: string; - Svt:integer; + Svt: Integer; begin - clear; - result:=false; - if length(buffer)<2 - then exit; - if (ord(buffer[1]) and $20)=0 - then exit; + Clear; + Result := False; + if Length(FBuffer) < 2 then + Exit; + if (Ord(FBuffer[1]) and $20) = 0 then + Exit; Pos := 2; - EndPos := ASNDecLen(Pos, Buffer); - Version := StrToIntDef(ASNItem(Pos, Buffer,svt), 0); - Community := ASNItem(Pos, Buffer,svt); - PDUType := StrToIntDef(ASNItem(Pos, Buffer,svt), PDU_TRAP); - Enterprise := ASNItem(Pos, Buffer,svt); - TrapHost := ASNItem(Pos, Buffer,svt); - GenTrap := StrToIntDef(ASNItem(Pos, Buffer,svt), 0); - Spectrap := StrToIntDef(ASNItem(Pos, Buffer,svt), 0); - TimeTicks := StrToIntDef(ASNItem(Pos, Buffer,svt), 0); - ASNItem(Pos, Buffer,svt); - while (Pos < EndPos) do - begin - ASNItem(Pos, Buffer,svt); - Sm := ASNItem(Pos, Buffer,svt); - Sv := ASNItem(Pos, Buffer,svt); - MIBAdd(Sm, Sv, svt); - end; - Result := true; + EndPos := ASNDecLen(Pos, FBuffer); + FVersion := StrToIntDef(ASNItem(Pos, FBuffer, Svt), 0); + FCommunity := ASNItem(Pos, FBuffer, Svt); + FPDUType := StrToIntDef(ASNItem(Pos, FBuffer, Svt), PDU_TRAP); + FEnterprise := ASNItem(Pos, FBuffer, Svt); + FTrapHost := ASNItem(Pos, FBuffer, Svt); + FGenTrap := StrToIntDef(ASNItem(Pos, FBuffer, Svt), 0); + FSpecTrap := StrToIntDef(ASNItem(Pos, FBuffer, Svt), 0); + FTimeTicks := StrToIntDef(ASNItem(Pos, FBuffer, Svt), 0); + ASNItem(Pos, FBuffer, Svt); + while Pos < EndPos do + begin + ASNItem(Pos, FBuffer, Svt); + Sm := ASNItem(Pos, FBuffer, Svt); + Sv := ASNItem(Pos, FBuffer, Svt); + MIBAdd(Sm, Sv, Svt); + end; + Result := True; end; constructor TTrapSNMP.Create; begin inherited Create; - Sock := TUDPBlockSocket.Create; - Trap := TTrapPDU.Create; - Timeout := 5000; - SNMPHost := '127.0.0.1'; - Sock.CreateSocket; + FSock := TUDPBlockSocket.Create; + FTrap := TTrapPDU.Create; + FTimeout := 5000; + FSNMPHost := cLocalhost; + FSock.CreateSocket; end; destructor TTrapSNMP.Destroy; begin - Trap.Free; - Sock.Free; + FTrap.Free; + FSock.Free; inherited Destroy; end; -function TTrapSNMP.Send: integer; +function TTrapSNMP.Send: Integer; begin - Trap.EncodeTrap; - Sock.Connect(SNMPHost, IntToStr(Trap.TrapPort)); - Sock.SendBuffer(PChar(Trap.Buffer), Length(Trap.Buffer)); + FTrap.EncodeTrap; + FSock.Connect(SNMPHost, FTrap.TrapPort); + FSock.SendBuffer(PChar(FTrap.FBuffer), Length(FTrap.FBuffer)); Result := 1; end; -function TTrapSNMP.Recv: integer; +function TTrapSNMP.Recv: Integer; var - x: integer; + x: Integer; begin Result := 0; - Sock.Bind('0.0.0.0', IntToStr(Trap.TrapPort)); - if Sock.CanRead(Timeout) then + FSock.Bind('0.0.0.0', FTrap.TrapPort); + if FSock.CanRead(FTimeout) then + begin + x := FSock.WaitingData; + if x > 0 then begin - x := Sock.WaitingData; - if (x > 0) then - begin - SetLength(Trap.Buffer, x); - Sock.RecvBuffer(PChar(Trap.Buffer), x); - if Trap.DecodeTrap - then Result:=1; - end; + SetLength(FTrap.FBuffer, x); + FSock.RecvBuffer(PChar(FTrap.FBuffer), x); + if FTrap.DecodeTrap then + Result := 1; end; + end; end; -function SendTrap(Dest, Source, Enterprise, Community: string; - Generic, Specific, Seconds: integer; MIBName, MIBValue: string; MIBtype:integer): integer; -var - SNMP: TTrapSNMP; +function SendTrap(const Dest, Source, Enterprise, Community: string; + Generic, Specific, Seconds: Integer; const MIBName, MIBValue: string; + MIBtype: Integer): Integer; begin - SNMP := TTrapSNMP.Create; + with TTrapSNMP.Create do try - SNMP.SNMPHost := Dest; - SNMP.Trap.TrapHost := Source; - SNMP.Trap.Enterprise := Enterprise; - SNMP.Trap.Community := Community; - SNMP.Trap.GenTrap := Generic; - SNMP.Trap.SpecTrap := Specific; - SNMP.Trap.TimeTicks := Seconds; - SNMP.Trap.MIBAdd(MIBName,MIBValue,MIBType); - Result := SNMP.Send; + SNMPHost := Dest; + Trap.TrapHost := Source; + Trap.Enterprise := Enterprise; + Trap.Community := Community; + Trap.GenTrap := Generic; + Trap.SpecTrap := Specific; + Trap.TimeTicks := Seconds; + Trap.MIBAdd(MIBName, MIBValue, MIBType); + Result := Send; finally - SNMP.Free; + Free; end; end; function RecvTrap(var Dest, Source, Enterprise, Community: string; - var Generic, Specific, Seconds: integer; var MIBName, MIBValue: TStringList): -integer; + var Generic, Specific, Seconds: Integer; + const MIBName, MIBValue: TStringList): Integer; var - SNMP: TTrapSNMP; - i: integer; + i: Integer; begin - SNMP := TTrapSNMP.Create; + with TTrapSNMP.Create do try - SNMP.SNMPHost := Dest; - Result := SNMP.Recv; - if (Result <> 0) then + SNMPHost := Dest; + Result := Recv; + if Result <> 0 then begin - Dest := SNMP.SNMPHost; - Source := SNMP.Trap.TrapHost; - Enterprise := SNMP.Trap.Enterprise; - Community := SNMP.Trap.Community; - Generic := SNMP.Trap.GenTrap; - Specific := SNMP.Trap.SpecTrap; - Seconds := SNMP.Trap.TimeTicks; + Dest := SNMPHost; + Source := Trap.TrapHost; + Enterprise := Trap.Enterprise; + Community := Trap.Community; + Generic := Trap.GenTrap; + Specific := Trap.SpecTrap; + Seconds := Trap.TimeTicks; MIBName.Clear; MIBValue.Clear; - for i:=0 to (SNMP.Trap.SNMPMibList.count - 1) do - begin - MIBName.Add(TSNMPMib(SNMP.Trap.SNMPMibList[i]).OID); - MIBValue.Add(TSNMPMib(SNMP.Trap.SNMPMibList[i]).Value); - end; + for i := 0 to Trap.SNMPMibList.Count - 1 do + begin + MIBName.Add(TSNMPMib(Trap.SNMPMibList[i]).OID); + MIBValue.Add(TSNMPMib(Trap.SNMPMibList[i]).Value); + end; end; finally - SNMP.Free; + Free; end; end; end. - diff --git a/sntpsend.pas b/sntpsend.pas index 744d230..f5a54d8 100644 --- a/sntpsend.pas +++ b/sntpsend.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.000.000 | +| Project : Delphree - Synapse | 002.000.001 | |==============================================================================| | Content: SNTP client | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -14,7 +14,7 @@ | The Original Code is Synapse Delphi Library. | |==============================================================================| | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| -| Portions created by Lukas Gebauer are Copyright (c)2000. | +| Portions created by Lukas Gebauer are Copyright (c)2000,2001. | | All Rights Reserved. | |==============================================================================| | Contributor(s): | @@ -24,142 +24,144 @@ |==============================================================================} {$Q-} +{$WEAKPACKAGEUNIT ON} unit SNTPsend; interface uses - synsock, SysUtils, blcksock; + SysUtils, + synsock, blcksock; + +const + cNtpProtocol = 'ntp'; type - + PNtp = ^TNtp; TNtp = packed record - mode:Byte; - stratum:Byte; - poll:Byte; - Precision:Byte; - RootDelay : longint; - RootDisperson : longint; - RefID : longint; - Ref1, Ref2, - Org1, Org2, - Rcv1, Rcv2, - Xmit1, Xmit2 : longint; + mode: Byte; + stratum: Byte; + poll: Byte; + Precision: Byte; + RootDelay: Longint; + RootDisperson: Longint; + RefID: Longint; + Ref1: Longint; + Ref2: Longint; + Org1: Longint; + Org2: Longint; + Rcv1: Longint; + Rcv2: Longint; + Xmit1: Longint; + Xmit2: Longint; end; -TSNTPSend=class(TObject) + TSNTPSend = class(TObject) private - Sock:TUDPBlockSocket; - Buffer:string; + FNTPReply: TNtp; + FNTPTime: TDateTime; + FSntpHost: string; + FTimeout: Integer; + FSock: TUDPBlockSocket; + FBuffer: string; public - timeout:integer; - SntpHost:string; - NTPReply:TNtp; - NTPTime:TDateTime; constructor Create; destructor Destroy; override; - function DecodeTs(nsec,nfrac:Longint):tdatetime; - function GetNTP:Boolean; - function GetBroadcastNTP:Boolean; -end; + function DecodeTs(Nsec, Nfrac: Longint): TDateTime; + function GetNTP: Boolean; + function GetBroadcastNTP: Boolean; + published + property NTPReply: TNtp read FNTPReply; + property NTPTime: TDateTime read FNTPTime; + property SntpHost: string read FSntpHost write FSntpHost; + property Timeout: Integer read FTimeout write FTimeout; + end; implementation -{==============================================================================} - -{TSNTPSend.Create} -Constructor TSNTPSend.Create; +constructor TSNTPSend.Create; begin inherited Create; - sock:=TUDPBlockSocket.create; - sock.CreateSocket; - timeout:=5000; - sntphost:='localhost'; + FSock := TUDPBlockSocket.Create; + FSock.CreateSocket; + FTimeout := 5000; + FSntpHost := cLocalhost; end; -{TSNTPSend.Destroy} -Destructor TSNTPSend.Destroy; +destructor TSNTPSend.Destroy; begin - Sock.free; - inherited destroy; + FSock.Free; + inherited Destroy; end; -{TSNTPSend.DecodeTs} -function TSNTPSend.DecodeTs(nsec,nfrac:Longint):tdatetime; +function TSNTPSend.DecodeTs(Nsec, Nfrac: Longint): TDateTime; const maxi = 4294967296.0; var - d, d1: double; + d, d1: Double; begin - nsec:=synsock.htonl(nsec); - nfrac:=synsock.htonl(nfrac); - d:=nsec; - if d<0 - then d:=maxi+d-1; - d1 := nfrac; - if d1<0 - then d1:=maxi+d1-1; - d1:=d1/maxi; - d1:=trunc(d1*1000)/1000; - result:=(d+d1)/86400; - result := Result + 2; + Nsec := synsock.htonl(Nsec); + Nfrac := synsock.htonl(Nfrac); + d := Nsec; + if d < 0 then + d := maxi + d - 1; + d1 := Nfrac; + if d1 < 0 then + d1 := maxi + d1 - 1; + d1 := d1 / maxi; + d1 := Trunc(d1 * 1000) / 1000; + Result := (d + d1) / 86400; + Result := Result + 2; end; - -{TSNTPSend.GetBroadcastNTP} -function TSNTPSend.GetBroadcastNTP:Boolean; +function TSNTPSend.GetBroadcastNTP: Boolean; var - PNtp:^TNtp; - x:integer; + NtpPtr: PNtp; + x: Integer; begin - Result:=False; - sock.bind('0.0.0.0','ntp'); - if sock.canread(timeout) - then begin - x:=sock.waitingdata; - setlength(Buffer,x); - sock.recvbufferFrom(Pointer(Buffer),x); - if (sntphost='0.0.0.0') or (sock.GetRemoteSinIP=sntphost) then - if x>=SizeOf(NTPReply) then - begin - PNtp:=Pointer(Buffer); - NtpReply:=PNtp^; - NTPtime:=DeCodeTs(ntpreply.Xmit1,ntpreply.Xmit2); - Result:=True; - end; - end; + Result := False; + FSock.Bind('0.0.0.0', cNtpProtocol); + if FSock.CanRead(Timeout) then + begin + x := FSock.WaitingData; + SetLength(FBuffer, x); + FSock.RecvBufferFrom(Pointer(FBuffer), x); + if (SntpHost = '0.0.0.0') or (FSock.GetRemoteSinIP = SntpHost) then + if x >= SizeOf(NTPReply) then + begin + NtpPtr := Pointer(FBuffer); + FNTPReply := NtpPtr^; + FNTPTime := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2); + Result := True; + end; + end; end; -{TSNTPSend.GetNTP} -function TSNTPSend.GetNTP:Boolean; +function TSNTPSend.GetNTP: Boolean; var - q:Tntp; - PNtp:^TNtp; - x:integer; + q: TNtp; + NtpPtr: PNtp; + x: Integer; begin - Result:=False; - sock.Connect(sntphost,'ntp'); - fillchar(q,SizeOf(q),0); - q.mode:=$1b; - sock.SendBuffer(@q,SizeOf(q)); - if sock.canread(timeout) - then begin - x:=sock.waitingdata; - setlength(Buffer,x); - sock.recvbuffer(Pointer(Buffer),x); - if x>=SizeOf(NTPReply) then - begin - PNtp:=Pointer(Buffer); - NtpReply:=PNtp^; - NTPtime:=DeCodeTs(ntpreply.Xmit1,ntpreply.Xmit2); - Result:=True; - end; + Result := False; + FSock.Connect(sntphost, cNtpProtocol); + FillChar(q, SizeOf(q), 0); + q.mode := $1B; + FSock.SendBuffer(@q, SizeOf(q)); + if FSock.CanRead(Timeout) then + begin + x := FSock.WaitingData; + SetLength(FBuffer, x); + FSock.RecvBuffer(Pointer(FBuffer), x); + if x >= SizeOf(NTPReply) then + begin + NtpPtr := Pointer(FBuffer); + FNTPReply := NtpPtr^; + FNTPTime := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2); + Result := True; end; + end; end; - -{==============================================================================} - - end. diff --git a/synachar.pas b/synachar.pas new file mode 100644 index 0000000..c0d21e6 --- /dev/null +++ b/synachar.pas @@ -0,0 +1,1191 @@ +{==============================================================================| +| Project : Delphree - Synapse | 003.001.000 | +|==============================================================================| +| Content: Charset conversion support | +|==============================================================================| +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | +| (the "License"); you may not use this file except in compliance with the | +| License. You may obtain a Copy of the License at http://www.mozilla.org/MPL/ | +| | +| Software distributed under the License is distributed on an "AS IS" basis, | +| WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | +| the specific language governing rights and limitations under the License. | +|==============================================================================| +| The Original Code is Synapse Delphi Library. | +|==============================================================================| +| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| +| Portions created by Lukas Gebauer are Copyright (c)2000,2001. | +| All Rights Reserved. | +|==============================================================================| +| Contributor(s): | +|==============================================================================| +| History: see HISTORY.HTM from distribution package | +| (Found at URL: http://www.ararat.cz/synapse/) | +|==============================================================================} + +{$Q-} +{$WEAKPACKAGEUNIT ON} + +unit SynaChar; + +interface + +type + TMimeChar = (ISO_8859_1, ISO_8859_2, ISO_8859_3, + ISO_8859_4, ISO_8859_5, ISO_8859_6, ISO_8859_7, + ISO_8859_8, ISO_8859_9, ISO_8859_10, CP1250, + CP1251, CP1252, CP1253, CP1254, CP1255, CP1256, + CP1257, CP1258, KOI8_R, CP895, CP852, + UCS_2, UCS_4, UTF_8, UTF_7); + + TMimeSetChar = set of TMimeChar; + +//character transcoding tables X to UCS-2 +{ +//dummy table +$0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, +$0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, +$0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, +$0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, +$00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, +$00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, +$00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, +$00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, +$00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, +$00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, +$00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, +$00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, +$00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, +$00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, +$00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, +$00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF +} + +const + +{Latin-1 + Danish, Dutch, English, Faeroese, Finnish, French, German, Icelandic, + Irish, Italian, Norwegian, Portuguese, Spanish and Swedish. +} + CharISO_8859_1: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, + $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, + $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, + $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, + $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, + $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, + $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, + $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, + $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF + ); + +{Latin-2 + Albanian, Czech, English, German, Hungarian, Polish, Rumanian, + Serbo-Croatian, Slovak, Slovene and Swedish. +} + CharISO_8859_2: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $0104, $02D8, $0141, $00A4, $013D, $015A, $00A7, + $00A8, $0160, $015E, $0164, $0179, $00AD, $017D, $017B, + $00B0, $0105, $02DB, $0142, $00B4, $013E, $015B, $02C7, + $00B8, $0161, $015F, $0165, $017A, $02DD, $017E, $017C, + $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7, + $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E, + $0110, $0143, $0147, $00D3, $00D4, $0150, $00D6, $00D7, + $0158, $016E, $00DA, $0170, $00DC, $00DD, $0162, $00DF, + $0155, $00E1, $00E2, $0103, $00E4, $013A, $0107, $00E7, + $010D, $00E9, $0119, $00EB, $011B, $00ED, $00EE, $010F, + $0111, $0144, $0148, $00F3, $00F4, $0151, $00F6, $00F7, + $0159, $016F, $00FA, $0171, $00FC, $00FD, $0163, $02D9 + ); + +{Latin-3 + Afrikaans, Catalan, English, Esperanto, French, Galician, + German, Italian, Maltese and Turkish. +} + CharISO_8859_3: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $0126, $02D8, $00A3, $00A4, $FFFD, $0124, $00A7, + $00A8, $0130, $015E, $011E, $0134, $00AD, $FFFD, $017B, + $00B0, $0127, $00B2, $00B3, $00B4, $00B5, $0125, $00B7, + $00B8, $0131, $015F, $011F, $0135, $00BD, $FFFD, $017C, + $00C0, $00C1, $00C2, $FFFD, $00C4, $010A, $0108, $00C7, + $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, + $FFFD, $00D1, $00D2, $00D3, $00D4, $0120, $00D6, $00D7, + $011C, $00D9, $00DA, $00DB, $00DC, $016C, $015C, $00DF, + $00E0, $00E1, $00E2, $FFFD, $00E4, $010B, $0109, $00E7, + $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, + $FFFD, $00F1, $00F2, $00F3, $00F4, $0121, $00F6, $00F7, + $011D, $00F9, $00FA, $00FB, $00FC, $016D, $015D, $02D9 + ); + +{Latin-4 + Danish, English, Estonian, Finnish, German, Greenlandic, + Lappish, Latvian, Lithuanian, Norwegian and Swedish. +} + CharISO_8859_4: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $0104, $0138, $0156, $00A4, $0128, $013B, $00A7, + $00A8, $0160, $0112, $0122, $0166, $00AD, $017D, $00AF, + $00B0, $0105, $02DB, $0157, $00B4, $0129, $013C, $02C7, + $00B8, $0161, $0113, $0123, $0167, $014A, $017E, $014B, + $0100, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $012E, + $010C, $00C9, $0118, $00CB, $0116, $00CD, $00CE, $012A, + $0110, $0145, $014C, $0136, $00D4, $00D5, $00D6, $00D7, + $00D8, $0172, $00DA, $00DB, $00DC, $0168, $016A, $00DF, + $0101, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $012F, + $010D, $00E9, $0119, $00EB, $0117, $00ED, $00EE, $012B, + $0111, $0146, $014D, $0137, $00F4, $00F5, $00F6, $00F7, + $00F8, $0173, $00FA, $00FB, $00FC, $0169, $016B, $02D9 + ); + +{CYRILLIC + Bulgarian, Bielorussian, English, Macedonian, Russian, + Serbo-Croatian and Ukrainian. +} + CharISO_8859_5: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $0401, $0402, $0403, $0404, $0405, $0406, $0407, + $0408, $0409, $040A, $040B, $040C, $00AD, $040E, $040F, + $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417, + $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F, + $0420, $0421, $0422, $0423, $0424, $0425, $0426, $0427, + $0428, $0429, $042A, $042B, $042C, $042D, $042E, $042F, + $0430, $0431, $0432, $0433, $0434, $0435, $0436, $0437, + $0438, $0439, $043A, $043B, $043C, $043D, $043E, $043F, + $0440, $0441, $0442, $0443, $0444, $0445, $0446, $0447, + $0448, $0449, $044A, $044B, $044C, $044D, $044E, $044F, + $2116, $0451, $0452, $0453, $0454, $0455, $0456, $0457, + $0458, $0459, $045A, $045B, $045C, $00A7, $045E, $045F + ); + +{ARABIC +} + CharISO_8859_6: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $FFFD, $FFFD, $FFFD, $00A4, $FFFD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $060C, $00AD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $061B, $FFFD, $FFFD, $FFFD, $061F, + $FFFD, $0621, $0622, $0623, $0624, $0625, $0626, $0627, + $0628, $0629, $062A, $062B, $062C, $062D, $062E, $062F, + $0630, $0631, $0632, $0633, $0634, $0635, $0636, $0637, + $0638, $0639, $063A, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $0640, $0641, $0642, $0643, $0644, $0645, $0646, $0647, + $0648, $0649, $064A, $064B, $064C, $064D, $064E, $064F, + $0650, $0651, $0652, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD + ); + +{GREEK +} + CharISO_8859_7: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $2018, $2019, $00A3, $FFFD, $FFFD, $00A6, $00A7, + $00A8, $00A9, $FFFD, $00AB, $00AC, $00AD, $FFFD, $2015, + $00B0, $00B1, $00B2, $00B3, $0384, $0385, $0386, $00B7, + $0388, $0389, $038A, $00BB, $038C, $00BD, $038E, $038F, + $0390, $0391, $0392, $0393, $0394, $0395, $0396, $0397, + $0398, $0399, $039A, $039B, $039C, $039D, $039E, $039F, + $03A0, $03A1, $FFFD, $03A3, $03A4, $03A5, $03A6, $03A7, + $03A8, $03A9, $03AA, $03AB, $03AC, $03AD, $03AE, $03AF, + $03B0, $03B1, $03B2, $03B3, $03B4, $03B5, $03B6, $03B7, + $03B8, $03B9, $03BA, $03BB, $03BC, $03BD, $03BE, $03BF, + $03C0, $03C1, $03C2, $03C3, $03C4, $03C5, $03C6, $03C7, + $03C8, $03C9, $03CA, $03CB, $03CC, $03CD, $03CE, $FFFD + ); + +{HEBREW +} + CharISO_8859_8: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $FFFD, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $00D7, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $00F7, $00BB, $00BC, $00BD, $00BE, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $2017, + $05D0, $05D1, $05D2, $05D3, $05D4, $05D5, $05D6, $05D7, + $05D8, $05D9, $05DA, $05DB, $05DC, $05DD, $05DE, $05DF, + $05E0, $05E1, $05E2, $05E3, $05E4, $05E5, $05E6, $05E7, + $05E8, $05E9, $05EA, $FFFD, $FFFD, $200E, $200F, $FFFD + ); + +{Latin-5 + English, Finnish, French, German, Irish, Italian, Norwegian, + Portuguese, Spanish, Swedish and Turkish. +} + CharISO_8859_9: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $0104, $02D8, $0141, $00A4, $013D, $015A, $00A7, + $00A8, $0160, $015E, $0164, $0179, $00AD, $017D, $017B, + $00B0, $0105, $02DB, $0142, $00B4, $013E, $015B, $02C7, + $00B8, $0161, $015F, $0165, $017A, $02DD, $017E, $017C, + $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7, + $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E, + $011E, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, + $00D8, $00D9, $00DA, $00DB, $00DC, $0130, $015E, $00DF, + $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, + $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, + $011F, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, + $00F8, $00F9, $00FA, $00FB, $00FC, $0131, $015F, $00FF + ); + +{Latin-6 + Danish, English, Estonian, Faeroese, Finnish, German, Greenlandic, + Icelandic, Lappish, Latvian, Lithuanian, Norwegian and Swedish. +} + CharISO_8859_10: array[128..255] of Word = + ( + $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087, + $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F, + $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097, + $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F, + $00A0, $0104, $0112, $0122, $012A, $0128, $0136, $00A7, + $013B, $0110, $0160, $0166, $017D, $00AD, $016A, $014A, + $00B0, $0105, $0113, $0123, $012B, $0129, $0137, $00B7, + $013C, $0111, $0161, $0167, $017E, $2015, $016B, $014B, + $0100, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $012E, + $010C, $00C9, $0118, $00CB, $0116, $00CD, $00CE, $00CF, + $00D0, $0145, $014C, $00D3, $00D4, $00D5, $00D6, $0168, + $00D8, $0172, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, + $0101, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $012F, + $010D, $00E9, $0119, $00EB, $0117, $00ED, $00EE, $00EF, + $00F0, $0146, $014D, $00F3, $00F4, $00F5, $00F6, $0169, + $00F8, $0173, $00FA, $00FB, $00FC, $00FD, $00FE, $0138 + ); + +{Eastern European +} + CharCP_1250: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $FFFD, $201E, $2026, $2020, $2021, + $FFFD, $2030, $0160, $2039, $015A, $0164, $017D, $0179, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $FFFD, $2122, $0161, $203A, $015B, $0165, $017E, $017A, + $00A0, $02C7, $02D8, $0141, $00A4, $0104, $00A6, $00A7, + $00A8, $00A9, $015E, $00AB, $00AC, $00AD, $00AE, $017B, + $00B0, $00B1, $02DB, $0142, $00B4, $00B5, $00B6, $00B7, + $00B8, $0105, $015F, $00BB, $013D, $02DD, $013E, $017C, + $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7, + $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E, + $0110, $0143, $0147, $00D3, $00D4, $0150, $00D6, $00D7, + $0158, $016E, $00DA, $0170, $00DC, $00DD, $0162, $00DF, + $0155, $00E1, $00E2, $0103, $00E4, $013A, $0107, $00E7, + $010D, $00E9, $0119, $00EB, $011B, $00ED, $00EE, $010F, + $0111, $0144, $0148, $00F3, $00F4, $0151, $00F6, $00F7, + $0159, $016F, $00FA, $0171, $00FC, $00FD, $0163, $02D9 + ); + +{Cyrillic +} + CharCP_1251: array[128..255] of Word = + ( + $0402, $0403, $201A, $0453, $201E, $2026, $2020, $2021, + $20AC, $2030, $0409, $2039, $040A, $040C, $040B, $040F, + $0452, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $FFFD, $2122, $0459, $203A, $045A, $045C, $045B, $045F, + $00A0, $040E, $045E, $0408, $00A4, $0490, $00A6, $00A7, + $0401, $00A9, $0404, $00AB, $00AC, $00AD, $00AE, $0407, + $00B0, $00B1, $0406, $0456, $0491, $00B5, $00B6, $00B7, + $0451, $2116, $0454, $00BB, $0458, $0405, $0455, $0457, + $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417, + $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F, + $0420, $0421, $0422, $0423, $0424, $0425, $0426, $0427, + $0428, $0429, $042A, $042B, $042C, $042D, $042E, $042F, + $0430, $0431, $0432, $0433, $0434, $0435, $0436, $0437, + $0438, $0439, $043A, $043B, $043C, $043D, $043E, $043F, + $0440, $0441, $0442, $0443, $0444, $0445, $0446, $0447, + $0448, $0449, $044A, $044B, $044C, $044D, $044E, $044F + ); + +{Latin-1 (US, Western Europe) +} + CharCP_1252: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021, + $02C6, $2030, $0160, $2039, $0152, $FFFD, $017D, $FFFD, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $02DC, $2122, $0161, $203A, $0153, $FFFD, $017E, $0178, + $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, + $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, + $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, + $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, + $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, + $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, + $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, + $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, + $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF + ); + +{Greek +} + CharCP_1253: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021, + $FFFD, $2030, $FFFD, $2039, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $FFFD, $2122, $FFFD, $203A, $FFFD, $FFFD, $FFFD, $FFFD, + $00A0, $0385, $0386, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $FFFD, $00AB, $00AC, $00AD, $00AE, $2015, + $00B0, $00B1, $00B2, $00B3, $0384, $00B5, $00B6, $00B7, + $0388, $0389, $038A, $00BB, $038C, $00BD, $038E, $038F, + $0390, $0391, $0392, $0393, $0394, $0395, $0396, $0397, + $0398, $0399, $039A, $039B, $039C, $039D, $039E, $039F, + $03A0, $03A1, $FFFD, $03A3, $03A4, $03A5, $03A6, $03A7, + $03A8, $03A9, $03AA, $03AB, $03AC, $03AD, $03AE, $03AF, + $03B0, $03B1, $03B2, $03B3, $03B4, $03B5, $03B6, $03B7, + $03B8, $03B9, $03BA, $03BB, $03BC, $03BD, $03BE, $03BF, + $03C0, $03C1, $03C2, $03C3, $03C4, $03C5, $03C6, $03C7, + $03C8, $03C9, $03CA, $03CB, $03CC, $03CD, $03CE, $FFFD + ); + +{Turkish +} + CharCP_1254: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021, + $02C6, $2030, $0160, $2039, $0152, $FFFD, $FFFD, $FFFD, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $02DC, $2122, $0161, $203A, $0153, $FFFD, $FFFD, $0178, + $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, + $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7, + $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF, + $011E, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, + $00D8, $00D9, $00DA, $00DB, $00DC, $0130, $015E, $00DF, + $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7, + $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF, + $011F, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7, + $00F8, $00F9, $00FA, $00FB, $00FC, $0131, $015F, $00FF + ); + +{Hebrew +} + CharCP_1255: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021, + $02C6, $2030, $FFFD, $2039, $FFFD, $FFFD, $FFFD, $FFFD, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $02DC, $2122, $FFFD, $203A, $FFFD, $FFFD, $FFFD, $FFFD, + $00A0, $00A1, $00A2, $00A3, $20AA, $00A5, $00A6, $00A7, + $00A8, $00A9, $00D7, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $00F7, $00BB, $00BC, $00BD, $00BE, $00BF, + $05B0, $05B1, $05B2, $05B3, $05B4, $05B5, $05B6, $05B7, + $05B8, $05B9, $FFFD, $05BB, $05BC, $05BD, $05BE, $05BF, + $05C0, $05C1, $05C2, $05C3, $05F0, $05F1, $05F2, $05F3, + $05F4, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, + $05D0, $05D1, $05D2, $05D3, $05D4, $05D5, $05D6, $05D7, + $05D8, $05D9, $05DA, $05DB, $05DC, $05DD, $05DE, $05DF, + $05E0, $05E1, $05E2, $05E3, $05E4, $05E5, $05E6, $05E7, + $05E8, $05E9, $05EA, $FFFD, $FFFD, $200E, $200F, $FFFD + ); + +{Arabic +} + CharCP_1256: array[128..255] of Word = + ( + $20AC, $067E, $201A, $0192, $201E, $2026, $2020, $2021, + $02C6, $2030, $0679, $2039, $0152, $0686, $0698, $0688, + $06AF, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $06A9, $2122, $0691, $203A, $0153, $200C, $200D, $06BA, + $00A0, $060C, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $06BE, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $061B, $00BB, $00BC, $00BD, $00BE, $061F, + $06C1, $0621, $0622, $0623, $0624, $0625, $0626, $0627, + $0628, $0629, $062A, $062B, $062C, $062D, $062E, $062F, + $0630, $0631, $0632, $0633, $0634, $0635, $0636, $00D7, + $0637, $0638, $0639, $063A, $0640, $0641, $0642, $0643, + $00E0, $0644, $00E2, $0645, $0646, $0647, $0648, $00E7, + $00E8, $00E9, $00EA, $00EB, $0649, $064A, $00EE, $00EF, + $064B, $064C, $064D, $064E, $00F4, $064F, $0650, $00F7, + $0651, $00F9, $0652, $00FB, $00FC, $200E, $200F, $06D2 + ); + +{Baltic +} + CharCP_1257: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $FFFD, $201E, $2026, $2020, $2021, + $FFFD, $2030, $FFFD, $2039, $FFFD, $00A8, $02C7, $00B8, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $FFFD, $2122, $FFFD, $203A, $FFFD, $00AF, $02DB, $FFFD, + $00A0, $FFFD, $00A2, $00A3, $00A4, $FFFD, $00A6, $00A7, + $00D8, $00A9, $0156, $00AB, $00AC, $00AD, $00AE, $00C6, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00F8, $00B9, $0157, $00BB, $00BC, $00BD, $00BE, $00E6, + $0104, $012E, $0100, $0106, $00C4, $00C5, $0118, $0112, + $010C, $00C9, $0179, $0116, $0122, $0136, $012A, $013B, + $0160, $0143, $0145, $00D3, $014C, $00D5, $00D6, $00D7, + $0172, $0141, $015A, $016A, $00DC, $017B, $017D, $00DF, + $0105, $012F, $0101, $0107, $00E4, $00E5, $0119, $0113, + $010D, $00E9, $017A, $0117, $0123, $0137, $012B, $013C, + $0161, $0144, $0146, $00F3, $014D, $00F5, $00F6, $00F7, + $0173, $0142, $015B, $016B, $00FC, $017C, $017E, $02D9 + ); + +{?? +} + CharCP_1258: array[128..255] of Word = + ( + $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021, + $02C6, $2030, $FFFD, $2039, $0152, $FFFD, $FFFD, $FFFD, + $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014, + $02DC, $2122, $FFFD, $203A, $0153, $FFFD, $FFFD, $0178, + $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7, + $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, + $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, + $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF, + $00C0, $00C1, $00C2, $0102, $00C4, $00C5, $00C6, $00C7, + $00C8, $00C9, $00CA, $00CB, $0300, $00CD, $00CE, $00CF, + $0110, $00D1, $0309, $00D3, $00D4, $01A0, $00D6, $00D7, + $00D8, $00D9, $00DA, $00DB, $00DC, $01AF, $0303, $00DF, + $00E0, $00E1, $00E2, $0103, $00E4, $00E5, $00E6, $00E7, + $00E8, $00E9, $00EA, $00EB, $0301, $00ED, $00EE, $00EF, + $0111, $00F1, $0323, $00F3, $00F4, $01A1, $00F6, $00F7, + $00F8, $00F9, $00FA, $00FB, $00FC, $01B0, $20AB, $00FF + ); + +{Cyrillic +} + CharKOI8_R: array[128..255] of Word = + ( + $2500, $2502, $250C, $2510, $2514, $2518, $251C, $2524, + $252C, $2534, $253C, $2580, $2584, $2588, $258C, $2590, + $2591, $2592, $2593, $2320, $25A0, $2219, $221A, $2248, + $2264, $2265, $00A0, $2321, $00B0, $00B2, $00B7, $00F7, + $2550, $2551, $2552, $0451, $2553, $2554, $2555, $2556, + $2557, $2558, $2559, $255A, $255B, $255C, $255D, $255E, + $255F, $2560, $2561, $0401, $2562, $2563, $2564, $2565, + $2566, $2567, $2568, $2569, $256A, $256B, $256C, $00A9, + $044E, $0430, $0431, $0446, $0434, $0435, $0444, $0433, + $0445, $0438, $0439, $043A, $043B, $043C, $043D, $043E, + $043F, $044F, $0440, $0441, $0442, $0443, $0436, $0432, + $044C, $044B, $0437, $0448, $044D, $0449, $0447, $044A, + $042E, $0410, $0411, $0426, $0414, $0415, $0424, $0413, + $0425, $0418, $0419, $041A, $041B, $041C, $041D, $041E, + $041F, $042F, $0420, $0421, $0422, $0423, $0416, $0412, + $042C, $042B, $0417, $0428, $042D, $0429, $0427, $042A + ); + +{Czech (Kamenicky) +} + CharCP_895: array[128..255] of Word = + ( + $010C, $00FC, $00E9, $010F, $00E4, $010E, $0164, $010D, + $011B, $011A, $0139, $00CD, $013E, $013A, $00C4, $00C1, + $00C9, $017E, $017D, $00F4, $00F6, $00D3, $016F, $00DA, + $00FD, $00D6, $00DC, $0160, $013D, $00DD, $0158, $0165, + $00E1, $00ED, $00F3, $00FA, $0148, $0147, $016E, $00D4, + $0161, $0159, $0155, $0154, $00BC, $00A7, $00AB, $00BB, + $2591, $2592, $2593, $2502, $2524, $2561, $2562, $2556, + $2555, $2563, $2551, $2557, $255D, $255C, $255B, $2510, + $2514, $2534, $252C, $251C, $2500, $253C, $255E, $255F, + $255A, $2554, $2569, $2566, $2560, $2550, $256C, $2567, + $2568, $2564, $2565, $2559, $2558, $2552, $2553, $256B, + $256A, $2518, $250C, $2588, $2584, $258C, $2590, $2580, + $03B1, $03B2, $0393, $03C0, $03A3, $03C3, $03BC, $03C4, + $03A6, $0398, $03A9, $03B4, $221E, $2205, $03B5, $2229, + $2261, $00B1, $2265, $2264, $2320, $2321, $00F7, $2248, + $2218, $00B7, $2219, $221A, $207F, $00B2, $25A0, $00A0 + ); + +{Eastern European +} + CharCP_852: array[128..255] of Word = + ( + $00C7, $00FC, $00E9, $00E2, $00E4, $016F, $0107, $00E7, + $0142, $00EB, $0150, $0151, $00EE, $0179, $00C4, $0106, + $00C9, $0139, $013A, $00F4, $00F6, $013D, $013E, $015A, + $015B, $00D6, $00DC, $0164, $0165, $0141, $00D7, $010D, + $00E1, $00ED, $00F3, $00FA, $0104, $0105, $017D, $017E, + $0118, $0119, $00AC, $017A, $010C, $015F, $00AB, $00BB, + $2591, $2592, $2593, $2502, $2524, $00C1, $00C2, $011A, + $015E, $2563, $2551, $2557, $255D, $017B, $017C, $2510, + $2514, $2534, $252C, $251C, $2500, $253C, $0102, $0103, + $255A, $2554, $2569, $2566, $2560, $2550, $256C, $00A4, + $0111, $0110, $010E, $00CB, $010F, $0147, $00CD, $00CE, + $011B, $2518, $250C, $2588, $2584, $0162, $016E, $2580, + $00D3, $00DF, $00D4, $0143, $0144, $0148, $0160, $0161, + $0154, $00DA, $0155, $0170, $00FD, $00DD, $0163, $00B4, + $00AD, $02DD, $02DB, $02C7, $02D8, $00A7, $00F7, $00B8, + $00B0, $00A8, $02D9, $0171, $0158, $0159, $25A0, $00A0 + ); + +{==============================================================================} +function UTF8toUCS4(const Value: string): string; +function UCS4toUTF8(const Value: string): string; +function UTF7toUCS2(const Value: string): string; +function UCS2toUTF7(const Value: string): string; +function CharsetConversion(Value: string; CharFrom: TMimeChar; + CharTo: TMimeChar): string; +function GetCurCP: TMimeChar; +function GetCPFromID(Value: string): TMimeChar; +function GetIDFromCP(Value: TMimeChar): string; +function NeedCharsetConversion(const Value: string): Boolean; +function IdealCharsetCoding(const Value: string; CharFrom: TMimeChar; + CharTo: TMimeSetChar): TMimeChar; + +implementation + +uses +{$IFDEF LINUX} + Libc, +{$ELSE} + Windows, +{$ENDIF} + SysUtils, + SynaUtil, SynaCode; + +const + NotFoundChar = '_'; + +var + SetTwo: set of TMimeChar = [UCS_2, UTF_7]; + SetFour: set of TMimeChar = [UCS_4, UTF_8]; + +{==============================================================================} + +procedure CopyArray(const SourceTable: array of Word; + var TargetTable: array of Word); +var + n: Integer; +begin + for n := 0 to 127 do + TargetTable[n] := SourceTable[n]; +end; + +{==============================================================================} + +procedure GetArray(CharSet: TMimeChar; var Result: array of Word); +begin + case CharSet of + ISO_8859_1: + CopyArray(CharISO_8859_1, Result); + ISO_8859_2: + CopyArray(CharISO_8859_2, Result); + ISO_8859_3: + CopyArray(CharISO_8859_3, Result); + ISO_8859_4: + CopyArray(CharISO_8859_4, Result); + ISO_8859_5: + CopyArray(CharISO_8859_5, Result); + ISO_8859_6: + CopyArray(CharISO_8859_6, Result); + ISO_8859_7: + CopyArray(CharISO_8859_7, Result); + ISO_8859_8: + CopyArray(CharISO_8859_8, Result); + ISO_8859_9: + CopyArray(CharISO_8859_9, Result); + ISO_8859_10: + CopyArray(CharISO_8859_10, Result); + CP1250: + CopyArray(CharCP_1250, Result); + CP1251: + CopyArray(CharCP_1251, Result); + CP1252: + CopyArray(CharCP_1252, Result); + CP1253: + CopyArray(CharCP_1253, Result); + CP1254: + CopyArray(CharCP_1254, Result); + CP1255: + CopyArray(CharCP_1255, Result); + CP1256: + CopyArray(CharCP_1256, Result); + CP1257: + CopyArray(CharCP_1257, Result); + CP1258: + CopyArray(CharCP_1258, Result); + KOI8_R: + CopyArray(CharKOI8_R, Result); + CP895: + CopyArray(CharCP_895, Result); + CP852: + CopyArray(CharCP_852, Result); + end; +end; + +{==============================================================================} + +procedure ReadMulti(const Value: string; var Index: Integer; mb: Byte; + var b1, b2, b3, b4: Byte); +var + b: array[0..3] of Byte; + n: Integer; + s: string; +begin + b[0] := 0; + b[1] := 0; + b[2] := 0; + b[3] := 0; + if (Length(Value) + 1) < Index + mb then + Exit; + s := ''; + for n := 1 to mb do + begin + s := Value[Index] + s; + Inc(Index); + end; + for n := 1 to mb do + b[n - 1] := Ord(s[n]); + b1 := b[0]; + b2 := b[1]; + b3 := b[2]; + b4 := b[3]; +end; + +{==============================================================================} + +function WriteMulti(b1, b2, b3, b4: Byte; mb: Byte): string; +var + b: array[0..3] of Byte; + n: Integer; +begin + Result := ''; + b[0] := b1; + b[1] := b2; + b[2] := b3; + b[3] := b4; + for n := 1 to mb do + Result := Char(b[n - 1]) + Result; +end; + +{==============================================================================} + +function UTF8toUCS4(const Value: string): string; +var + n, x, ul, m: Integer; + s: string; + w1, w2: Word; +begin + Result := ''; + n := 1; + while Length(Value) >= n do + begin + x := Ord(Value[n]); + Inc(n); + if x < 128 then + Result := Result + WriteMulti(x, 0, 0, 0, 4) + else + begin + m := 0; + if (x and $E0) = $C0 then + m := $1F; + if (x and $F0) = $E0 then + m := $0F; + if (x and $F8) = $F0 then + m := $07; + if (x and $FC) = $F8 then + m := $03; + if (x and $FE) = $FC then + m := $01; + ul := x and m; + s := IntToBin(ul, 0); + while Length(Value) >= n do + begin + x := Ord(Value[n]); + Inc(n); + if (x and $C0) = $80 then + s := s + IntToBin(x and $3F, 6) + else + begin + Dec(n); + Break; + end; + end; + ul := BinToInt(s); + w1 := ul div 65536; + w2 := ul mod 65536; + Result := Result + WriteMulti(Lo(w2), Hi(w2), Lo(w1), Hi(w1), 4); + end; + end; +end; + +{==============================================================================} + +function UCS4toUTF8(const Value: string): string; +var + s, l, k: string; + b1, b2, b3, b4: Byte; + n, m, x, y: Integer; + b: Byte; +begin + Result := ''; + n := 1; + while Length(Value) >= n do + begin + ReadMulti(Value, n, 4, b1, b2, b3, b4); + if (b2 = 0) and (b3 = 0) and (b4 = 0) and (b1 < 128) then + Result := Result + Char(b1) + else + begin + x := (b1 + 256 * b2) + (b3 + 256 * b4) * 65536; + l := IntToBin(x, 0); + y := Length(l) div 6; + s := ''; + for m := 1 to y do + begin + k := Copy(l, Length(l) - 5, 6); + l := Copy(l, 1, Length(l) - 6); + b := BinToInt(k) or $80; + s := Char(b) + s; + end; + b := BinToInt(l); + case y of + 5: + b := b or $FC; + 4: + b := b or $F8; + 3: + b := b or $F0; + 2: + b := b or $E0; + 1: + b := b or $C0; + end; + s := Char(b) + s; + Result := Result + s; + end; + end; +end; + +{==============================================================================} + +function UTF7toUCS2(const Value: string): string; +var + n: Integer; + c: Char; + s: string; +begin + Result := ''; + n := 1; + while Length(Value) >= n do + begin + c := Value[n]; + Inc(n); + if c <> '+' then + Result := Result + WriteMulti(Ord(c), 0, 0, 0, 2) + else + begin + s := ''; + while Length(Value) >= n do + begin + c := Value[n]; + Inc(n); + if c = '-' then + Break; + if (c = '=') or (Pos(c, TableBase64) < 1) then + begin + Dec(n); + Break; + end; + s := s + c; + end; + if s = '' then + s := '+' + else + s := DecodeBase64(s); + Result := Result + s; + end; + end; +end; + +{==============================================================================} + +function UCS2toUTF7(const Value: string): string; +var + s: string; + b1, b2, b3, b4: Byte; + n, m: Integer; +begin + Result := ''; + n := 1; + while Length(Value) >= n do + begin + ReadMulti(Value, n, 2, b1, b2, b3, b4); + if (b2 = 0) and (b1 < 128) then + if Char(b1) = '+' then + Result := Result + '+-' + else + Result := Result + Char(b1) + else + begin + s := Char(b2) + Char(b1); + while Length(Value) >= n do + begin + ReadMulti(Value, n, 2, b1, b2, b3, b4); + if (b2 = 0) and (b1 < 128) then + begin + Dec(n, 2); + Break; + end; + s := s + Char(b2) + Char(b1); + end; + s := EncodeBase64(s); + m := Pos('=', s); + if m > 0 then + s := Copy(s, 1, m - 1); + Result := Result + '+' + s + '-'; + end; + end; +end; + +{==============================================================================} + +function CharsetConversion(Value: string; CharFrom: TMimeChar; + CharTo: TMimeChar): string; +var + uni: Word; + n, m: Integer; + b: Byte; + b1, b2, b3, b4: Byte; + SourceTable, TargetTable: array[128..255] of Word; + mbf, mbt: Byte; +begin + GetArray(CharFrom, SourceTable); + GetArray(CharTo, TargetTable); + mbf := 1; + if CharFrom in SetTwo then + mbf := 2; + if CharFrom in SetFour then + mbf := 4; + mbt := 1; + if CharTo in SetTwo then + mbt := 2; + if CharTo in SetFour then + mbt := 4; + + if CharFrom = UTF_8 then + Value := UTF8toUCS4(Value); + if CharFrom = UTF_7 then + Value := UTF7toUCS2(Value); + Result := ''; + + n := 1; + while Length(Value) >= n do + begin + ReadMulti(Value, n, mbf, b1, b2, b3, b4); + if mbf = 1 then + if b1 > 127 then + begin + uni := SourceTable[b1]; + b1 := Lo(uni); + b2 := Hi(uni); + end; + // b1..b4 - Unicode Char + uni := b2 * 256 + b1; + if (b3 <> 0) or (b4 <> 0) then + begin + b1 := Ord(NotFoundChar); + b2 := 0; + b3 := 0; + b4 := 0; + end + else + if mbt = 1 then + if uni > 127 then + begin + b := Ord(NotFoundChar); + for m := 128 to 255 do + if TargetTable[m] = uni then + begin + b := m; + Break; + end; + b1 := b; + b2 := 0; + end + else + b1 := Lo(uni); + Result := Result + WriteMulti(b1, b2, b3, b4, mbt) + end; + + if CharTo = UTF_7 then + Result := UCS2toUTF7(Result); + if CharTo = UTF_8 then + Result := UCS4toUTF8(Result); + +end; + +{==============================================================================} + +{$IFDEF LINUX} + +function GetCurCP: TMimeChar; +begin + Result := GetCPFromID(nl_langinfo(_NL_CTYPE_CODESET_NAME)); +end; + +{$ELSE} + +function GetCurCP: TMimeChar; +begin + case GetACP of + 1250: + Result := CP1250; + 1251: + Result := CP1251; + 1253: + Result := CP1253; + 1254: + Result := CP1254; + 1255: + Result := CP1255; + 1256: + Result := CP1256; + 1257: + Result := CP1257; + 1258: + Result := CP1258; + else + Result := CP1252; + end; +end; + +{$ENDIF} + +{==============================================================================} + +function GetCPFromID(Value: string): TMimeChar; +begin + Value := UpperCase(Value); + Result := ISO_8859_1; + if Pos('ISO-8859-10', Value) = 1 then + Result := ISO_8859_10 + else + if Pos('ISO-8859-2', Value) = 1 then + Result := ISO_8859_2 + else + if Pos('ISO-8859-3', Value) = 1 then + Result := ISO_8859_3 + else + if Pos('ISO-8859-4', Value) = 1 then + Result := ISO_8859_4 + else + if Pos('ISO-8859-5', Value) = 1 then + Result := ISO_8859_5 + else + if Pos('ISO-8859-6', Value) = 1 then + Result := ISO_8859_6 + else + if Pos('ISO-8859-7', Value) = 1 then + Result := ISO_8859_7 + else + if Pos('ISO-8859-8', Value) = 1 then + Result := ISO_8859_8 + else + if Pos('ISO-8859-9', Value) = 1 then + Result := ISO_8859_9 + else + if (Pos('WINDOWS-1250', Value) = 1) or (Pos('X-CP1250', Value) = 1) then + Result := CP1250 + else + if (Pos('WINDOWS-1251', Value) = 1) or (Pos('X-CP1251', Value) = 1) then + Result := CP1251 + else + if (Pos('WINDOWS-1252', Value) = 1) or (Pos('X-CP1252', Value) = 1) then + Result := CP1252 + else + if (Pos('WINDOWS-1253', Value) = 1) or (Pos('X-CP1253', Value) = 1) then + Result := CP1253 + else + if (Pos('WINDOWS-1254', Value) = 1) or (Pos('X-CP1254', Value) = 1) then + Result := CP1254 + else + if (Pos('WINDOWS-1255', Value) = 1) or (Pos('X-CP1255', Value) = 1) then + Result := CP1255 + else + if (Pos('WINDOWS-1256', Value) = 1) or (Pos('X-CP1256', Value) = 1) then + Result := CP1256 + else + if (Pos('WINDOWS-1257', Value) = 1) or (Pos('X-CP1257', Value) = 1) then + Result := CP1257 + else + if (Pos('WINDOWS-1258', Value) = 1) or (Pos('X-CP1258', Value) = 1) then + Result := CP1258 + else + if Pos('KOI8-R', Value) = 1 then + Result := KOI8_R + else + if (Pos('KAMENICKY', Value) > 0) or (Pos('895', Value) > 0) then + Result := CP895 + else + if (Pos('LATIN-2', Value) > 0) or (Pos('852', Value) > 0) then + Result := CP852 + else + if Pos('UTF-7', Value) = 1 then + Result := UTF_7 + else + if Pos('UTF-8', Value) > 0 then + Result := UTF_8 + else + if Pos('UCS-4', Value) > 0 then + Result := UCS_4 + else + if Pos('UCS-2', Value) > 0 then + Result := UCS_2 + else + if Pos('UNICODE', Value) = 1 then + Result := UCS_2 +end; + +{==============================================================================} + +function GetIDFromCP(Value: TMimeChar): string; +begin + case Value of + ISO_8859_2: + Result := 'ISO-8859-2'; + ISO_8859_3: + Result := 'ISO-8859-3'; + ISO_8859_4: + Result := 'ISO-8859-4'; + ISO_8859_5: + Result := 'ISO-8859-5'; + ISO_8859_6: + Result := 'ISO-8859-6'; + ISO_8859_7: + Result := 'ISO-8859-7'; + ISO_8859_8: + Result := 'ISO-8859-8'; + ISO_8859_9: + Result := 'ISO-8859-9'; + ISO_8859_10: + Result := 'ISO-8859-10'; + CP1250: + Result := 'WINDOWS-1250'; + CP1251: + Result := 'WINDOWS-1251'; + CP1252: + Result := 'WINDOWS-1252'; + CP1253: + Result := 'WINDOWS-1253'; + CP1254: + Result := 'WINDOWS-1254'; + CP1255: + Result := 'WINDOWS-1255'; + CP1256: + Result := 'WINDOWS-1256'; + CP1257: + Result := 'WINDOWS-1257'; + CP1258: + Result := 'WINDOWS-1258'; + KOI8_R: + Result := 'KOI8-R'; + CP895: + Result := 'CP-895'; + CP852: + Result := 'CP-852'; + UCS_2: + Result := 'Unicode-1-1-UCS-2'; + UCS_4: + Result := 'Unicode-1-1-UCS-4'; + UTF_8: + Result := 'UTF-8'; + UTF_7: + Result := 'UTF-7'; + else + Result := 'ISO-8859-1'; + end; +end; + +{==============================================================================} + +function NeedCharsetConversion(const Value: string): Boolean; +var + n: Integer; +begin + Result := False; + for n := 1 to Length(Value) do + if Ord(Value[n]) > 127 then + begin + Result := True; + Break; + end; +end; + +{==============================================================================} + +function IdealCharsetCoding(const Value: string; CharFrom: TMimeChar; + CharTo: TMimeSetChar): TMimeChar; +var + n, m: Integer; + min, x: Integer; + s, t: string; +begin + Result := ISO_8859_1; + s := ''; + for n := 1 to Length(Value) do + if Ord(Value[n]) > 127 then + s := s + Value[n]; + min := 128; + for n := Ord(Low(TMimeChar)) to Ord(High(TMimeChar)) do + if TMimeChar(n) in CharTo then + begin + t := CharsetConversion(s, CharFrom, TMimeChar(n)); + x := 0; + for m := 1 to Length(t) do + if t[m] = NotFoundChar then + Inc(x); + if x < min then + begin + min := x; + Result := TMimeChar(n); + if x = 0 then + Break; + end; + end; +end; + +end. diff --git a/synacode.pas b/synacode.pas index 19b28d1..32e7e86 100644 --- a/synacode.pas +++ b/synacode.pas @@ -1,11 +1,11 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.004.000 | +| Project : Delphree - Synapse | 001.004.001 | |==============================================================================| | Content: Coding and decoding support | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | -| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | +| License. You may obtain a Copy of the License at http://www.mozilla.org/MPL/ | | | | Software distributed under the License is distributed on an "AS IS" basis, | | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | @@ -24,660 +24,669 @@ |==============================================================================} {$Q-} +{$WEAKPACKAGEUNIT ON} unit SynaCode; interface uses - sysutils; + SysUtils; type - TSpecials=set of char; + TSpecials = set of Char; const - SpecialChar:TSpecials - =['=','(',')','[',']','<','>',':',';','.',',','@','/','?','\','"','_']; - URLFullSpecialChar:TSpecials - =[';','/','?',':','@','=','&','#']; - URLSpecialChar:TSpecials - =[#$00..#$1f,'_','<','>','"','%','{','}','|','\','^','~','[',']','`',#$7f..#$ff]; - - TableBase64= + SpecialChar: TSpecials = + ['=', '(', ')', '[', ']', '<', '>', ':', ';', '.', ',', '@', '/', '?', '\', + '"', '_']; + URLFullSpecialChar: TSpecials = + [';', '/', '?', ':', '@', '=', '&', '#']; + URLSpecialChar: TSpecials = + [#$00..#$20, '_', '<', '>', '"', '%', '{', '}', '|', '\', '^', '~', '[', ']', + '`', #$7F..#$FF]; + TableBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - TableUU= + TableUU = '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'; - TableXX= + TableXX = '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_'; - Crc32Tab: array[0..255] of integer = ( - Integer($00000000),Integer($77073096),Integer($ee0e612c),Integer($990951ba), - Integer($076dc419),Integer($706af48f),Integer($e963a535),Integer($9e6495a3), - Integer($0edb8832),Integer($79dcb8a4),Integer($e0d5e91e),Integer($97d2d988), - Integer($09b64c2b),Integer($7eb17cbd),Integer($e7b82d07),Integer($90bf1d91), - Integer($1db71064),Integer($6ab020f2),Integer($f3b97148),Integer($84be41de), - Integer($1adad47d),Integer($6ddde4eb),Integer($f4d4b551),Integer($83d385c7), - Integer($136c9856),Integer($646ba8c0),Integer($fd62f97a),Integer($8a65c9ec), - Integer($14015c4f),Integer($63066cd9),Integer($fa0f3d63),Integer($8d080df5), - Integer($3b6e20c8),Integer($4c69105e),Integer($d56041e4),Integer($a2677172), - Integer($3c03e4d1),Integer($4b04d447),Integer($d20d85fd),Integer($a50ab56b), - Integer($35b5a8fa),Integer($42b2986c),Integer($dbbbc9d6),Integer($acbcf940), - Integer($32d86ce3),Integer($45df5c75),Integer($dcd60dcf),Integer($abd13d59), - Integer($26d930ac),Integer($51de003a),Integer($c8d75180),Integer($bfd06116), - Integer($21b4f4b5),Integer($56b3c423),Integer($cfba9599),Integer($b8bda50f), - Integer($2802b89e),Integer($5f058808),Integer($c60cd9b2),Integer($b10be924), - Integer($2f6f7c87),Integer($58684c11),Integer($c1611dab),Integer($b6662d3d), - Integer($76dc4190),Integer($01db7106),Integer($98d220bc),Integer($efd5102a), - Integer($71b18589),Integer($06b6b51f),Integer($9fbfe4a5),Integer($e8b8d433), - Integer($7807c9a2),Integer($0f00f934),Integer($9609a88e),Integer($e10e9818), - Integer($7f6a0dbb),Integer($086d3d2d),Integer($91646c97),Integer($e6635c01), - Integer($6b6b51f4),Integer($1c6c6162),Integer($856530d8),Integer($f262004e), - Integer($6c0695ed),Integer($1b01a57b),Integer($8208f4c1),Integer($f50fc457), - Integer($65b0d9c6),Integer($12b7e950),Integer($8bbeb8ea),Integer($fcb9887c), - Integer($62dd1ddf),Integer($15da2d49),Integer($8cd37cf3),Integer($fbd44c65), - Integer($4db26158),Integer($3ab551ce),Integer($a3bc0074),Integer($d4bb30e2), - Integer($4adfa541),Integer($3dd895d7),Integer($a4d1c46d),Integer($d3d6f4fb), - Integer($4369e96a),Integer($346ed9fc),Integer($ad678846),Integer($da60b8d0), - Integer($44042d73),Integer($33031de5),Integer($aa0a4c5f),Integer($dd0d7cc9), - Integer($5005713c),Integer($270241aa),Integer($be0b1010),Integer($c90c2086), - Integer($5768b525),Integer($206f85b3),Integer($b966d409),Integer($ce61e49f), - Integer($5edef90e),Integer($29d9c998),Integer($b0d09822),Integer($c7d7a8b4), - Integer($59b33d17),Integer($2eb40d81),Integer($b7bd5c3b),Integer($c0ba6cad), - Integer($edb88320),Integer($9abfb3b6),Integer($03b6e20c),Integer($74b1d29a), - Integer($ead54739),Integer($9dd277af),Integer($04db2615),Integer($73dc1683), - Integer($e3630b12),Integer($94643b84),Integer($0d6d6a3e),Integer($7a6a5aa8), - Integer($e40ecf0b),Integer($9309ff9d),Integer($0a00ae27),Integer($7d079eb1), - Integer($f00f9344),Integer($8708a3d2),Integer($1e01f268),Integer($6906c2fe), - Integer($f762575d),Integer($806567cb),Integer($196c3671),Integer($6e6b06e7), - Integer($fed41b76),Integer($89d32be0),Integer($10da7a5a),Integer($67dd4acc), - Integer($f9b9df6f),Integer($8ebeeff9),Integer($17b7be43),Integer($60b08ed5), - Integer($d6d6a3e8),Integer($a1d1937e),Integer($38d8c2c4),Integer($4fdff252), - Integer($d1bb67f1),Integer($a6bc5767),Integer($3fb506dd),Integer($48b2364b), - Integer($d80d2bda),Integer($af0a1b4c),Integer($36034af6),Integer($41047a60), - Integer($df60efc3),Integer($a867df55),Integer($316e8eef),Integer($4669be79), - Integer($cb61b38c),Integer($bc66831a),Integer($256fd2a0),Integer($5268e236), - Integer($cc0c7795),Integer($bb0b4703),Integer($220216b9),Integer($5505262f), - Integer($c5ba3bbe),Integer($b2bd0b28),Integer($2bb45a92),Integer($5cb36a04), - Integer($c2d7ffa7),Integer($b5d0cf31),Integer($2cd99e8b),Integer($5bdeae1d), - Integer($9b64c2b0),Integer($ec63f226),Integer($756aa39c),Integer($026d930a), - Integer($9c0906a9),Integer($eb0e363f),Integer($72076785),Integer($05005713), - Integer($95bf4a82),Integer($e2b87a14),Integer($7bb12bae),Integer($0cb61b38), - Integer($92d28e9b),Integer($e5d5be0d),Integer($7cdcefb7),Integer($0bdbdf21), - Integer($86d3d2d4),Integer($f1d4e242),Integer($68ddb3f8),Integer($1fda836e), - Integer($81be16cd),Integer($f6b9265b),Integer($6fb077e1),Integer($18b74777), - Integer($88085ae6),Integer($ff0f6a70),Integer($66063bca),Integer($11010b5c), - Integer($8f659eff),Integer($f862ae69),Integer($616bffd3),Integer($166ccf45), - Integer($a00ae278),Integer($d70dd2ee),Integer($4e048354),Integer($3903b3c2), - Integer($a7672661),Integer($d06016f7),Integer($4969474d),Integer($3e6e77db), - Integer($aed16a4a),Integer($d9d65adc),Integer($40df0b66),Integer($37d83bf0), - Integer($a9bcae53),Integer($debb9ec5),Integer($47b2cf7f),Integer($30b5ffe9), - Integer($bdbdf21c),Integer($cabac28a),Integer($53b39330),Integer($24b4a3a6), - Integer($bad03605),Integer($cdd70693),Integer($54de5729),Integer($23d967bf), - Integer($b3667a2e),Integer($c4614ab8),Integer($5d681b02),Integer($2a6f2b94), - Integer($b40bbe37),Integer($c30c8ea1),Integer($5a05df1b),Integer($2d02ef8d) - ); - - Crc16Tab: array[0..255] of word = ( - $0000, $1189, $2312, $329b, $4624, $57ad, $6536, $74bf, - $8c48, $9dc1, $af5a, $bed3, $ca6c, $dbe5, $e97e, $f8f7, - $1081, $0108, $3393, $221a, $56a5, $472c, $75b7, $643e, - $9cc9, $8d40, $bfdb, $ae52, $daed, $cb64, $f9ff, $e876, - $2102, $308b, $0210, $1399, $6726, $76af, $4434, $55bd, - $ad4a, $bcc3, $8e58, $9fd1, $eb6e, $fae7, $c87c, $d9f5, - $3183, $200a, $1291, $0318, $77a7, $662e, $54b5, $453c, - $bdcb, $ac42, $9ed9, $8f50, $fbef, $ea66, $d8fd, $c974, - $4204, $538d, $6116, $709f, $0420, $15a9, $2732, $36bb, - $ce4c, $dfc5, $ed5e, $fcd7, $8868, $99e1, $ab7a, $baf3, - $5285, $430c, $7197, $601e, $14a1, $0528, $37b3, $263a, - $decd, $cf44, $fddf, $ec56, $98e9, $8960, $bbfb, $aa72, - $6306, $728f, $4014, $519d, $2522, $34ab, $0630, $17b9, - $ef4e, $fec7, $cc5c, $ddd5, $a96a, $b8e3, $8a78, $9bf1, - $7387, $620e, $5095, $411c, $35a3, $242a, $16b1, $0738, - $ffcf, $ee46, $dcdd, $cd54, $b9eb, $a862, $9af9, $8b70, - $8408, $9581, $a71a, $b693, $c22c, $d3a5, $e13e, $f0b7, - $0840, $19c9, $2b52, $3adb, $4e64, $5fed, $6d76, $7cff, - $9489, $8500, $b79b, $a612, $d2ad, $c324, $f1bf, $e036, - $18c1, $0948, $3bd3, $2a5a, $5ee5, $4f6c, $7df7, $6c7e, - $a50a, $b483, $8618, $9791, $e32e, $f2a7, $c03c, $d1b5, - $2942, $38cb, $0a50, $1bd9, $6f66, $7eef, $4c74, $5dfd, - $b58b, $a402, $9699, $8710, $f3af, $e226, $d0bd, $c134, - $39c3, $284a, $1ad1, $0b58, $7fe7, $6e6e, $5cf5, $4d7c, - $c60c, $d785, $e51e, $f497, $8028, $91a1, $a33a, $b2b3, - $4a44, $5bcd, $6956, $78df, $0c60, $1de9, $2f72, $3efb, - $d68d, $c704, $f59f, $e416, $90a9, $8120, $b3bb, $a232, - $5ac5, $4b4c, $79d7, $685e, $1ce1, $0d68, $3ff3, $2e7a, - $e70e, $f687, $c41c, $d595, $a12a, $b0a3, $8238, $93b1, - $6b46, $7acf, $4854, $59dd, $2d62, $3ceb, $0e70, $1ff9, - $f78f, $e606, $d49d, $c514, $b1ab, $a022, $92b9, $8330, - $7bc7, $6a4e, $58d5, $495c, $3de3, $2c6a, $1ef1, $0f78 - ); - -type - TMD5Ctx = record - State: array[0..3] of integer; - Count: array[0..1] of integer; - case Integer of - 0: (BufChar: array[0..63] of Byte); - 1: (BufLong: array[0..15] of integer); - end; - -function DecodeTriplet(Value:string;limiter:char):string; -function DecodeQuotedPrintable(value:string):string; -function DecodeURL(value:string):string; -function EncodeTriplet(value:string;limiter:char;specials:TSpecials):string; -function EncodeQuotedPrintable(value:string):string; -function EncodeURLElement(value:string):string; -function EncodeURL(value:string):string; -function Decode4to3(value,table:string):string; -function DecodeBase64(value:string):string; -function EncodeBase64(value:string):string; -function DecodeUU(value:string):string; -function DecodeXX(value:string):string; -function UpdateCrc32(value:byte;crc32:integer):integer; -function Crc32(value:string):integer; -function UpdateCrc16(value:byte;crc16:word):word; -function Crc16(value:string):word; -function MD5(value:string):string; -function HMAC_MD5(text,key:string):string; +function DecodeTriplet(const Value: string; Delimiter: Char): string; +function DecodeQuotedPrintable(const Value: string): string; +function DecodeURL(const Value: string): string; +function EncodeTriplet(const Value: string; Delimiter: Char; + Specials: TSpecials): string; +function EncodeQuotedPrintable(const Value: string): string; +function EncodeURLElement(const Value: string): string; +function EncodeURL(const Value: string): string; +function Decode4to3(const Value, Table: string): string; +function DecodeBase64(const Value: string): string; +function EncodeBase64(const Value: string): string; +function DecodeUU(const Value: string): string; +function DecodeXX(const Value: string): string; +function UpdateCrc32(Value: Byte; Crc32: Integer): Integer; +function Crc32(const Value: string): Integer; +function UpdateCrc16(Value: Byte; Crc16: Word): Word; +function Crc16(const Value: string): Word; +function MD5(const Value: string): string; +function HMAC_MD5(Text, Key: string): string; implementation +const + + Crc32Tab: array[0..255] of Integer = ( + Integer($00000000), Integer($77073096), Integer($EE0E612C), Integer($990951BA), + Integer($076DC419), Integer($706AF48F), Integer($E963A535), Integer($9E6495A3), + Integer($0EDB8832), Integer($79DCB8A4), Integer($E0D5E91E), Integer($97D2D988), + Integer($09B64C2B), Integer($7EB17CBD), Integer($E7B82D07), Integer($90BF1D91), + Integer($1DB71064), Integer($6AB020F2), Integer($F3B97148), Integer($84BE41DE), + Integer($1ADAD47D), Integer($6DDDE4EB), Integer($F4D4B551), Integer($83D385C7), + Integer($136C9856), Integer($646BA8C0), Integer($FD62F97A), Integer($8A65C9EC), + Integer($14015C4F), Integer($63066CD9), Integer($FA0F3D63), Integer($8D080DF5), + Integer($3B6E20C8), Integer($4C69105E), Integer($D56041E4), Integer($A2677172), + Integer($3C03E4D1), Integer($4B04D447), Integer($D20D85FD), Integer($A50AB56B), + Integer($35B5A8FA), Integer($42B2986C), Integer($DBBBC9D6), Integer($ACBCF940), + Integer($32D86CE3), Integer($45DF5C75), Integer($DCD60DCF), Integer($ABD13D59), + Integer($26D930AC), Integer($51DE003A), Integer($C8D75180), Integer($BFD06116), + Integer($21B4F4B5), Integer($56B3C423), Integer($CFBA9599), Integer($B8BDA50F), + Integer($2802B89E), Integer($5F058808), Integer($C60CD9B2), Integer($B10BE924), + Integer($2F6F7C87), Integer($58684C11), Integer($C1611DAB), Integer($B6662D3D), + Integer($76DC4190), Integer($01DB7106), Integer($98D220BC), Integer($EFD5102A), + Integer($71B18589), Integer($06B6B51F), Integer($9FBFE4A5), Integer($E8B8D433), + Integer($7807C9A2), Integer($0F00F934), Integer($9609A88E), Integer($E10E9818), + Integer($7F6A0DBB), Integer($086D3D2D), Integer($91646C97), Integer($E6635C01), + Integer($6B6B51F4), Integer($1C6C6162), Integer($856530D8), Integer($F262004E), + Integer($6C0695ED), Integer($1B01A57B), Integer($8208F4C1), Integer($F50FC457), + Integer($65B0D9C6), Integer($12B7E950), Integer($8BBEB8EA), Integer($FCB9887C), + Integer($62DD1DDF), Integer($15DA2D49), Integer($8CD37CF3), Integer($FBD44C65), + Integer($4DB26158), Integer($3AB551CE), Integer($A3BC0074), Integer($D4BB30E2), + Integer($4ADFA541), Integer($3DD895D7), Integer($A4D1C46D), Integer($D3D6F4FB), + Integer($4369E96A), Integer($346ED9FC), Integer($AD678846), Integer($DA60B8D0), + Integer($44042D73), Integer($33031DE5), Integer($AA0A4C5F), Integer($DD0D7CC9), + Integer($5005713C), Integer($270241AA), Integer($BE0B1010), Integer($C90C2086), + Integer($5768B525), Integer($206F85B3), Integer($B966D409), Integer($CE61E49F), + Integer($5EDEF90E), Integer($29D9C998), Integer($B0D09822), Integer($C7D7A8B4), + Integer($59B33D17), Integer($2EB40D81), Integer($B7BD5C3B), Integer($C0BA6CAD), + Integer($EDB88320), Integer($9ABFB3B6), Integer($03B6E20C), Integer($74B1D29A), + Integer($EAD54739), Integer($9DD277AF), Integer($04DB2615), Integer($73DC1683), + Integer($E3630B12), Integer($94643B84), Integer($0D6D6A3E), Integer($7A6A5AA8), + Integer($E40ECF0B), Integer($9309FF9D), Integer($0A00AE27), Integer($7D079EB1), + Integer($F00F9344), Integer($8708A3D2), Integer($1E01F268), Integer($6906C2FE), + Integer($F762575D), Integer($806567CB), Integer($196C3671), Integer($6E6B06E7), + Integer($FED41B76), Integer($89D32BE0), Integer($10DA7A5A), Integer($67DD4ACC), + Integer($F9B9DF6F), Integer($8EBEEFF9), Integer($17B7BE43), Integer($60B08ED5), + Integer($D6D6A3E8), Integer($A1D1937E), Integer($38D8C2C4), Integer($4FDFF252), + Integer($D1BB67F1), Integer($A6BC5767), Integer($3FB506DD), Integer($48B2364B), + Integer($D80D2BDA), Integer($AF0A1B4C), Integer($36034AF6), Integer($41047A60), + Integer($DF60EFC3), Integer($A867DF55), Integer($316E8EEF), Integer($4669BE79), + Integer($CB61B38C), Integer($BC66831A), Integer($256FD2A0), Integer($5268E236), + Integer($CC0C7795), Integer($BB0B4703), Integer($220216B9), Integer($5505262F), + Integer($C5BA3BBE), Integer($B2BD0B28), Integer($2BB45A92), Integer($5CB36A04), + Integer($C2D7FFA7), Integer($B5D0CF31), Integer($2CD99E8B), Integer($5BDEAE1D), + Integer($9B64C2B0), Integer($EC63F226), Integer($756AA39C), Integer($026D930A), + Integer($9C0906A9), Integer($EB0E363F), Integer($72076785), Integer($05005713), + Integer($95BF4A82), Integer($E2B87A14), Integer($7BB12BAE), Integer($0CB61B38), + Integer($92D28E9B), Integer($E5D5BE0D), Integer($7CDCEFB7), Integer($0BDBDF21), + Integer($86D3D2D4), Integer($F1D4E242), Integer($68DDB3F8), Integer($1FDA836E), + Integer($81BE16CD), Integer($F6B9265B), Integer($6FB077E1), Integer($18B74777), + Integer($88085AE6), Integer($FF0F6A70), Integer($66063BCA), Integer($11010B5C), + Integer($8F659EFF), Integer($F862AE69), Integer($616BFFD3), Integer($166CCF45), + Integer($A00AE278), Integer($D70DD2EE), Integer($4E048354), Integer($3903B3C2), + Integer($A7672661), Integer($D06016F7), Integer($4969474D), Integer($3E6E77DB), + Integer($AED16A4A), Integer($D9D65ADC), Integer($40DF0B66), Integer($37D83BF0), + Integer($A9BCAE53), Integer($DEBB9EC5), Integer($47B2CF7F), Integer($30B5FFE9), + Integer($BDBDF21C), Integer($CABAC28A), Integer($53B39330), Integer($24B4A3A6), + Integer($BAD03605), Integer($CDD70693), Integer($54DE5729), Integer($23D967BF), + Integer($B3667A2E), Integer($C4614AB8), Integer($5D681B02), Integer($2A6F2B94), + Integer($B40BBE37), Integer($C30C8EA1), Integer($5A05DF1B), Integer($2D02EF8D) + ); + + Crc16Tab: array[0..255] of Word = ( + $0000, $1189, $2312, $329B, $4624, $57AD, $6536, $74BF, + $8C48, $9DC1, $AF5A, $BED3, $CA6C, $DBE5, $E97E, $F8F7, + $1081, $0108, $3393, $221A, $56A5, $472C, $75B7, $643E, + $9CC9, $8D40, $BFDB, $AE52, $DAED, $CB64, $F9FF, $E876, + $2102, $308B, $0210, $1399, $6726, $76AF, $4434, $55BD, + $AD4A, $BCC3, $8E58, $9FD1, $EB6E, $FAE7, $C87C, $D9F5, + $3183, $200A, $1291, $0318, $77A7, $662E, $54B5, $453C, + $BDCB, $AC42, $9ED9, $8F50, $FBEF, $EA66, $D8FD, $C974, + $4204, $538D, $6116, $709F, $0420, $15A9, $2732, $36BB, + $CE4C, $DFC5, $ED5E, $FCD7, $8868, $99E1, $AB7A, $BAF3, + $5285, $430C, $7197, $601E, $14A1, $0528, $37B3, $263A, + $DECD, $CF44, $FDDF, $EC56, $98E9, $8960, $BBFB, $AA72, + $6306, $728F, $4014, $519D, $2522, $34AB, $0630, $17B9, + $EF4E, $FEC7, $CC5C, $DDD5, $A96A, $B8E3, $8A78, $9BF1, + $7387, $620E, $5095, $411C, $35A3, $242A, $16B1, $0738, + $FFCF, $EE46, $DCDD, $CD54, $B9EB, $A862, $9AF9, $8B70, + $8408, $9581, $A71A, $B693, $C22C, $D3A5, $E13E, $F0B7, + $0840, $19C9, $2B52, $3ADB, $4E64, $5FED, $6D76, $7CFF, + $9489, $8500, $B79B, $A612, $D2AD, $C324, $F1BF, $E036, + $18C1, $0948, $3BD3, $2A5A, $5EE5, $4F6C, $7DF7, $6C7E, + $A50A, $B483, $8618, $9791, $E32E, $F2A7, $C03C, $D1B5, + $2942, $38CB, $0A50, $1BD9, $6F66, $7EEF, $4C74, $5DFD, + $B58B, $A402, $9699, $8710, $F3AF, $E226, $D0BD, $C134, + $39C3, $284A, $1AD1, $0B58, $7FE7, $6E6E, $5CF5, $4D7C, + $C60C, $D785, $E51E, $F497, $8028, $91A1, $A33A, $B2B3, + $4A44, $5BCD, $6956, $78DF, $0C60, $1DE9, $2F72, $3EFB, + $D68D, $C704, $F59F, $E416, $90A9, $8120, $B3BB, $A232, + $5AC5, $4B4C, $79D7, $685E, $1CE1, $0D68, $3FF3, $2E7A, + $E70E, $F687, $C41C, $D595, $A12A, $B0A3, $8238, $93B1, + $6B46, $7ACF, $4854, $59DD, $2D62, $3CEB, $0E70, $1FF9, + $F78F, $E606, $D49D, $C514, $B1AB, $A022, $92B9, $8330, + $7BC7, $6A4E, $58D5, $495C, $3DE3, $2C6A, $1EF1, $0F78 + ); + +type + TMD5Ctx = record + State: array[0..3] of Integer; + Count: array[0..1] of Integer; + case Integer of + 0: (BufChar: array[0..63] of Byte); + 1: (BufLong: array[0..15] of Integer); + end; + {==============================================================================} -{DecodeTriplet} -function DecodeTriplet(Value:string;limiter:char):string; + +function DecodeTriplet(const Value: string; Delimiter: Char): string; var - x:integer; - c:char; - s:string; + x: Integer; + c: Char; + s: string; begin - result:=''; - x:=1; - while x<=length(value) do - begin - c:=value[x]; - inc(x); - if c<>limiter - then result:=result+c - else - if x Delimiter then + Result := Result + c + else + if x < Length(Value) then + begin + s := Copy(Value, x, 2); + Inc(x, 2); + if pos(#13, s) + pos(#10, s) = 0 then + Result := Result + Char(StrToIntDef('$' + s, 32)); + end; + end; end; {==============================================================================} {DecodeQuotedPrintable} -function DecodeQuotedPrintable(value:string):string; + +function DecodeQuotedPrintable(const Value: string): string; begin - Result:=DecodeTriplet(Value,'='); + Result := DecodeTriplet(Value, '='); end; {==============================================================================} -{DecodeURL} -function DecodeURL(value:string):string; + +function DecodeURL(const Value: string): string; begin - Result:=DecodeTriplet(Value,'%'); + Result := DecodeTriplet(Value, '%'); end; {==============================================================================} -{EncodeTriplet} -function EncodeTriplet(value:string;limiter:char;specials:TSpecials):string; + +function EncodeTriplet(const Value: string; Delimiter: Char; + Specials: TSpecials): string; var - n:integer; - s:string; + n: Integer; + s: string; begin - result:=''; - for n:=1 to length(value) do + Result := ''; + for n := 1 to Length(Value) do + begin + s := Value[n]; + if s[1] in Specials then + s := Delimiter + IntToHex(Ord(s[1]), 2); + Result := Result + s; + end; +end; + +{==============================================================================} + +function EncodeQuotedPrintable(const Value: string): string; +begin + Result := EncodeTriplet(Value, '=', SpecialChar + + [Char(1)..Char(31), Char(128)..Char(255)]); +end; + +{==============================================================================} + +function EncodeURLElement(const Value: string): string; +begin + Result := EncodeTriplet(Value, '%', URLSpecialChar + URLFullSpecialChar); +end; + +{==============================================================================} + +function EncodeURL(const Value: string): string; +begin + Result := EncodeTriplet(Value, '%', URLSpecialChar); +end; + +{==============================================================================} + +function Decode4to3(const Value, Table: string): string; +var + x, y, n: Integer; + d: array[0..3] of Byte; +begin + Result := ''; + x := 1; + while x < Length(Value) do + begin + for n := 0 to 3 do begin - s:=value[n]; - if s[1] in Specials - then s:=limiter+inttohex(ord(s[1]),2); - result:=result+s; + if x > Length(Value) then + d[n] := 64 + else + begin + y := Pos(Value[x], Table); + if y < 1 then + y := 65; + d[n] := y - 1; + end; + Inc(x); end; -end; - -{==============================================================================} -{EncodeQuotedPrintable} -function EncodeQuotedPrintable(value:string):string; -begin - Result:=EncodeTriplet(Value,'=',SpecialChar+[char(1)..char(31),char(128)..char(255)]); -end; - -{==============================================================================} -{EncodeURLElement} -function EncodeURLElement(value:string):string; -begin - Result:=EncodeTriplet(Value,'%',URLSpecialChar+URLFullSpecialChar); -end; - -{==============================================================================} -{EncodeURL} -function EncodeURL(value:string):string; -begin - Result:=EncodeTriplet(Value,'%',URLSpecialChar); -end; - -{==============================================================================} -{Decode4to3} -function Decode4to3(value,table:string):string; -var - x,y,n:integer; - d: array[0..3] of byte; -begin - result:=''; - x:=1; - while x 64 then begin - for n:=0 to 3 do - begin - if x>length(value) - then d[n]:=64 - else - begin - y:=pos(value[x],table); - if y<1 then y:=65; - d[n]:=y-1; - end; - inc(x); - end; - result:=result+char((D[0] and $3F) shl 2 + (D[1] and $30) shr 4); - if d[2]<>64 then - begin - result:=result+char((D[1] and $0F) shl 4 + (D[2] and $3C) shr 2); - if d[3]<>64 then - result:=result+char((D[2] and $03) shl 6 + (D[3] and $3F)); - end; + Result := Result + Char((D[1] and $0F) shl 4 + (D[2] and $3C) shr 2); + if d[3] <> 64 then + Result := Result + Char((D[2] and $03) shl 6 + (D[3] and $3F)); end; + end; end; {==============================================================================} -{DecodeBase64} -function DecodeBase64(value:string):string; + +function DecodeBase64(const Value: string): string; begin - result:=Decode4to3(value,TableBase64); + Result := Decode4to3(Value, TableBase64); end; {==============================================================================} -{EncodeBase64} -function EncodeBase64(value:string):string; + +function EncodeBase64(const Value: string): string; var - c:byte; - n:integer; - Count:integer; - DOut:array [0..3] of byte; + c: Byte; + n: Integer; + Count: Integer; + DOut: array[0..3] of Byte; begin - result:=''; + Result := ''; Count := 1; - while count<=length(value) do + while Count <= Length(Value) do + begin + c := Ord(Value[Count]); + Inc(Count); + DOut[0] := (c and $FC) shr 2; + DOut[1] := (c and $03) shl 4; + if Count <= Length(Value) then begin - c:=ord(value[count]); - inc(count); - DOut[0]:=(c and $FC) shr 2; - DOut[1]:=(c and $03) shl 4; - if count<=length(value) - then - begin - c:=ord(value[count]); - inc(count); - DOut[1]:=DOut[1]+(c and $F0) shr 4; - DOut[2]:=(c and $0F) shl 2; - if count<=length(value) - then - begin - c:=ord(value[count]); - inc(count); - DOut[2]:=DOut[2]+(c and $C0) shr 6; - DOut[3]:=(c and $3F); - end - else - begin - DOut[3] := $40; - end; - end - else - begin - DOut[2] := $40; - DOut[3] := $40; - end; - for n:=0 to 3 do - result:=result+TableBase64[DOut[n]+1]; + c := Ord(Value[Count]); + Inc(Count); + DOut[1] := DOut[1] + (c and $F0) shr 4; + DOut[2] := (c and $0F) shl 2; + if Count <= Length(Value) then + begin + c := Ord(Value[Count]); + Inc(Count); + DOut[2] := DOut[2] + (c and $C0) shr 6; + DOut[3] := (c and $3F); + end + else + begin + DOut[3] := $40; + end; + end + else + begin + DOut[2] := $40; + DOut[3] := $40; end; + for n := 0 to 3 do + Result := Result + TableBase64[DOut[n] + 1]; + end; end; {==============================================================================} -{DecodeUU} -function DecodeUU(value:string):string; + +function DecodeUU(const Value: string): string; var - s:string; - uut:string; - x:integer; + s: string; + uut: string; + x: Integer; begin - result:=''; - uut:=TableUU; - s:=trim(uppercase(value)); - if s='' then exit; - if pos('BEGIN',s)=1 then exit; - if pos('END',s)=1 then exit; - if pos('TABLE',s)=1 then exit; //ignore table yet (set custom UUT) + Result := ''; + uut := TableUU; + s := trim(UpperCase(Value)); + if s = '' then Exit; + if Pos('BEGIN', s) = 1 then + Exit; + if Pos('END', s) = 1 then + Exit; + if Pos('TABLE', s) = 1 then + Exit; //ignore Table yet (set custom UUT) //begin decoding - x:=pos(value[1],uut)-1; - x:=round((x/3)*4); + x := Pos(Value[1], uut) - 1; + x := Round((x / 3) * 4); //x - lenght UU line - s:=copy(value,2,x); - if s='' then exit; - result:=Decode4to3(s,uut); + s := Copy(Value, 2, x); + if s = '' then + Exit; + Result := Decode4to3(s, uut); end; {==============================================================================} -{DecodeXX} -function DecodeXX(value:string):string; + +function DecodeXX(const Value: string): string; var - s:string; - x:integer; + s: string; + x: Integer; begin - result:=''; - s:=trim(uppercase(value)); - if s='' then exit; - if pos('BEGIN',s)=1 then exit; - if pos('END',s)=1 then exit; + Result := ''; + s := trim(UpperCase(Value)); + if s = '' then + Exit; + if Pos('BEGIN', s) = 1 then + Exit; + if Pos('END', s) = 1 then + Exit; //begin decoding - x:=pos(value[1],TableXX)-1; - x:=round((x/3)*4); + x := Pos(Value[1], TableXX) - 1; + x := Round((x / 3) * 4); //x - lenght XX line - s:=copy(value,2,x); - if s='' then exit; - result:=Decode4to3(s,TableXX); + s := Copy(Value, 2, x); + if s = '' then + Exit; + Result := Decode4to3(s, TableXX); end; {==============================================================================} -{UpdateCrc32} -function UpdateCrc32(value:byte;crc32:integer):integer; + +function UpdateCrc32(Value: Byte; Crc32: Integer): Integer; begin - result:=((crc32 shr 8) and Integer($00FFFFFF)) - xor crc32tab[byte(crc32 XOR integer(value)) and Integer($000000FF)]; + Result := ((Crc32 shr 8) and Integer($00FFFFFF)) xor + crc32tab[Byte(Crc32 xor Integer(Value)) and Integer($000000FF)]; end; {==============================================================================} -{Crc32} -function Crc32(value:string):integer; + +function Crc32(const Value: string): Integer; var - n:integer; + n: Integer; begin - result:=Integer($FFFFFFFF); - for n:=1 to length(value) do - result:=UpdateCrc32(ord(value[n]), result); + Result := Integer($FFFFFFFF); + for n := 1 to Length(Value) do + Result := UpdateCrc32(Ord(Value[n]), Result); end; {==============================================================================} -{UpdateCrc16} -function UpdateCrc16(value:byte;crc16:word):word; + +function UpdateCrc16(Value: Byte; Crc16: Word): Word; begin - result:=((crc16 shr 8) and $00FF) - xor crc16tab[byte(crc16 XOR (word(value)) and $00FF)]; + Result := ((Crc16 shr 8) and $00FF) xor + crc16tab[Byte(Crc16 xor (Word(Value)) and $00FF)]; end; {==============================================================================} -{Crc16} -function Crc16(value:string):word; + +function Crc16(const Value: string): Word; var - n:integer; + n: Integer; begin - result:=$FFFF; - for n:=1 to length(value) do - result:=UpdateCrc16(ord(value[n]), result); + Result := $FFFF; + for n := 1 to Length(Value) do + Result := UpdateCrc16(Ord(Value[n]), Result); end; {==============================================================================} + procedure MD5Init(var MD5Context: TMD5Ctx); begin FillChar(MD5Context, SizeOf(TMD5Ctx), #0); - with MD5Context do begin + with MD5Context do + begin State[0] := Integer($67452301); State[1] := Integer($EFCDAB89); State[2] := Integer($98BADCFE); State[3] := Integer($10325476); - end + end; end; -procedure MD5Transform(var Buf:array of LongInt; const Data:array of LongInt); +procedure MD5Transform(var Buf: array of LongInt; const Data: array of LongInt); var - A,B,C,D: LongInt; + A, B, C, D: LongInt; procedure Round1(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); begin Inc(W, (Z xor (X and (Y xor Z))) + Data); W := (W shl S) or (W shr (32 - S)); - Inc(W, X) + Inc(W, X); end; procedure Round2(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); begin Inc(W, (Y xor (Z and (X xor Y))) + Data); W := (W shl S) or (W shr (32 - S)); - Inc(W, X) + Inc(W, X); end; procedure Round3(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); begin Inc(W, (X xor Y xor Z) + Data); W := (W shl S) or (W shr (32 - S)); - Inc(W, X) + Inc(W, X); end; procedure Round4(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); begin Inc(W, (Y xor (X or not Z)) + Data); W := (W shl S) or (W shr (32 - S)); - Inc(W, X) + Inc(W, X); end; begin - A:=Buf[0]; - B:=Buf[1]; - C:=Buf[2]; - D:=Buf[3]; + A := Buf[0]; + B := Buf[1]; + C := Buf[2]; + D := Buf[3]; - Round1(A,B,C,D, Data[ 0] + longint($d76aa478), 7); - Round1(D,A,B,C, Data[ 1] + longint($e8c7b756), 12); - Round1(C,D,A,B, Data[ 2] + longint($242070db), 17); - Round1(B,C,D,A, Data[ 3] + longint($c1bdceee), 22); - Round1(A,B,C,D, Data[ 4] + longint($f57c0faf), 7); - Round1(D,A,B,C, Data[ 5] + longint($4787c62a), 12); - Round1(C,D,A,B, Data[ 6] + longint($a8304613), 17); - Round1(B,C,D,A, Data[ 7] + longint($fd469501), 22); - Round1(A,B,C,D, Data[ 8] + longint($698098d8), 7); - Round1(D,A,B,C, Data[ 9] + longint($8b44f7af), 12); - Round1(C,D,A,B, Data[10] + longint($ffff5bb1), 17); - Round1(B,C,D,A, Data[11] + longint($895cd7be), 22); - Round1(A,B,C,D, Data[12] + longint($6b901122), 7); - Round1(D,A,B,C, Data[13] + longint($fd987193), 12); - Round1(C,D,A,B, Data[14] + longint($a679438e), 17); - Round1(B,C,D,A, Data[15] + longint($49b40821), 22); + Round1(A, B, C, D, Data[0] + Longint($D76AA478), 7); + Round1(D, A, B, C, Data[1] + Longint($E8C7B756), 12); + Round1(C, D, A, B, Data[2] + Longint($242070DB), 17); + Round1(B, C, D, A, Data[3] + Longint($C1BDCEEE), 22); + Round1(A, B, C, D, Data[4] + Longint($F57C0FAF), 7); + Round1(D, A, B, C, Data[5] + Longint($4787C62A), 12); + Round1(C, D, A, B, Data[6] + Longint($A8304613), 17); + Round1(B, C, D, A, Data[7] + Longint($FD469501), 22); + Round1(A, B, C, D, Data[8] + Longint($698098D8), 7); + Round1(D, A, B, C, Data[9] + Longint($8B44F7AF), 12); + Round1(C, D, A, B, Data[10] + Longint($FFFF5BB1), 17); + Round1(B, C, D, A, Data[11] + Longint($895CD7BE), 22); + Round1(A, B, C, D, Data[12] + Longint($6B901122), 7); + Round1(D, A, B, C, Data[13] + Longint($FD987193), 12); + Round1(C, D, A, B, Data[14] + Longint($A679438E), 17); + Round1(B, C, D, A, Data[15] + Longint($49B40821), 22); - Round2(A,B,C,D, Data[ 1] + longint($f61e2562), 5); - Round2(D,A,B,C, Data[ 6] + longint($c040b340), 9); - Round2(C,D,A,B, Data[11] + longint($265e5a51), 14); - Round2(B,C,D,A, Data[ 0] + longint($e9b6c7aa), 20); - Round2(A,B,C,D, Data[ 5] + longint($d62f105d), 5); - Round2(D,A,B,C, Data[10] + longint($02441453), 9); - Round2(C,D,A,B, Data[15] + longint($d8a1e681), 14); - Round2(B,C,D,A, Data[ 4] + longint($e7d3fbc8), 20); - Round2(A,B,C,D, Data[ 9] + longint($21e1cde6), 5); - Round2(D,A,B,C, Data[14] + longint($c33707d6), 9); - Round2(C,D,A,B, Data[ 3] + longint($f4d50d87), 14); - Round2(B,C,D,A, Data[ 8] + longint($455a14ed), 20); - Round2(A,B,C,D, Data[13] + longint($a9e3e905), 5); - Round2(D,A,B,C, Data[ 2] + longint($fcefa3f8), 9); - Round2(C,D,A,B, Data[ 7] + longint($676f02d9), 14); - Round2(B,C,D,A, Data[12] + longint($8d2a4c8a), 20); + Round2(A, B, C, D, Data[1] + Longint($F61E2562), 5); + Round2(D, A, B, C, Data[6] + Longint($C040B340), 9); + Round2(C, D, A, B, Data[11] + Longint($265E5A51), 14); + Round2(B, C, D, A, Data[0] + Longint($E9B6C7AA), 20); + Round2(A, B, C, D, Data[5] + Longint($D62F105D), 5); + Round2(D, A, B, C, Data[10] + Longint($02441453), 9); + Round2(C, D, A, B, Data[15] + Longint($D8A1E681), 14); + Round2(B, C, D, A, Data[4] + Longint($E7D3FBC8), 20); + Round2(A, B, C, D, Data[9] + Longint($21E1CDE6), 5); + Round2(D, A, B, C, Data[14] + Longint($C33707D6), 9); + Round2(C, D, A, B, Data[3] + Longint($F4D50D87), 14); + Round2(B, C, D, A, Data[8] + Longint($455A14ED), 20); + Round2(A, B, C, D, Data[13] + Longint($A9E3E905), 5); + Round2(D, A, B, C, Data[2] + Longint($FCEFA3F8), 9); + Round2(C, D, A, B, Data[7] + Longint($676F02D9), 14); + Round2(B, C, D, A, Data[12] + Longint($8D2A4C8A), 20); - Round3(A,B,C,D, Data[ 5] + longint($fffa3942), 4); - Round3(D,A,B,C, Data[ 8] + longint($8771f681), 11); - Round3(C,D,A,B, Data[11] + longint($6d9d6122), 16); - Round3(B,C,D,A, Data[14] + longint($fde5380c), 23); - Round3(A,B,C,D, Data[ 1] + longint($a4beea44), 4); - Round3(D,A,B,C, Data[ 4] + longint($4bdecfa9), 11); - Round3(C,D,A,B, Data[ 7] + longint($f6bb4b60), 16); - Round3(B,C,D,A, Data[10] + longint($bebfbc70), 23); - Round3(A,B,C,D, Data[13] + longint($289b7ec6), 4); - Round3(D,A,B,C, Data[ 0] + longint($eaa127fa), 11); - Round3(C,D,A,B, Data[ 3] + longint($d4ef3085), 16); - Round3(B,C,D,A, Data[ 6] + longint($04881d05), 23); - Round3(A,B,C,D, Data[ 9] + longint($d9d4d039), 4); - Round3(D,A,B,C, Data[12] + longint($e6db99e5), 11); - Round3(C,D,A,B, Data[15] + longint($1fa27cf8), 16); - Round3(B,C,D,A, Data[ 2] + longint($c4ac5665), 23); + Round3(A, B, C, D, Data[5] + Longint($FFFA3942), 4); + Round3(D, A, B, C, Data[8] + Longint($8771F681), 11); + Round3(C, D, A, B, Data[11] + Longint($6D9D6122), 16); + Round3(B, C, D, A, Data[14] + Longint($FDE5380C), 23); + Round3(A, B, C, D, Data[1] + Longint($A4BEEA44), 4); + Round3(D, A, B, C, Data[4] + Longint($4BDECFA9), 11); + Round3(C, D, A, B, Data[7] + Longint($F6BB4B60), 16); + Round3(B, C, D, A, Data[10] + Longint($BEBFBC70), 23); + Round3(A, B, C, D, Data[13] + Longint($289B7EC6), 4); + Round3(D, A, B, C, Data[0] + Longint($EAA127FA), 11); + Round3(C, D, A, B, Data[3] + Longint($D4EF3085), 16); + Round3(B, C, D, A, Data[6] + Longint($04881D05), 23); + Round3(A, B, C, D, Data[9] + Longint($D9D4D039), 4); + Round3(D, A, B, C, Data[12] + Longint($E6DB99E5), 11); + Round3(C, D, A, B, Data[15] + Longint($1FA27CF8), 16); + Round3(B, C, D, A, Data[2] + Longint($C4AC5665), 23); - Round4(A,B,C,D, Data[ 0] + longint($f4292244), 6); - Round4(D,A,B,C, Data[ 7] + longint($432aff97), 10); - Round4(C,D,A,B, Data[14] + longint($ab9423a7), 15); - Round4(B,C,D,A, Data[ 5] + longint($fc93a039), 21); - Round4(A,B,C,D, Data[12] + longint($655b59c3), 6); - Round4(D,A,B,C, Data[ 3] + longint($8f0ccc92), 10); - Round4(C,D,A,B, Data[10] + longint($ffeff47d), 15); - Round4(B,C,D,A, Data[ 1] + longint($85845dd1), 21); - Round4(A,B,C,D, Data[ 8] + longint($6fa87e4f), 6); - Round4(D,A,B,C, Data[15] + longint($fe2ce6e0), 10); - Round4(C,D,A,B, Data[ 6] + longint($a3014314), 15); - Round4(B,C,D,A, Data[13] + longint($4e0811a1), 21); - Round4(A,B,C,D, Data[ 4] + longint($f7537e82), 6); - Round4(D,A,B,C, Data[11] + longint($bd3af235), 10); - Round4(C,D,A,B, Data[ 2] + longint($2ad7d2bb), 15); - Round4(B,C,D,A, Data[ 9] + longint($eb86d391), 21); + Round4(A, B, C, D, Data[0] + Longint($F4292244), 6); + Round4(D, A, B, C, Data[7] + Longint($432AFF97), 10); + Round4(C, D, A, B, Data[14] + Longint($AB9423A7), 15); + Round4(B, C, D, A, Data[5] + Longint($FC93A039), 21); + Round4(A, B, C, D, Data[12] + Longint($655B59C3), 6); + Round4(D, A, B, C, Data[3] + Longint($8F0CCC92), 10); + Round4(C, D, A, B, Data[10] + Longint($FFEFF47D), 15); + Round4(B, C, D, A, Data[1] + Longint($85845DD1), 21); + Round4(A, B, C, D, Data[8] + Longint($6FA87E4F), 6); + Round4(D, A, B, C, Data[15] + Longint($FE2CE6E0), 10); + Round4(C, D, A, B, Data[6] + Longint($A3014314), 15); + Round4(B, C, D, A, Data[13] + Longint($4E0811A1), 21); + Round4(A, B, C, D, Data[4] + Longint($F7537E82), 6); + Round4(D, A, B, C, Data[11] + Longint($BD3AF235), 10); + Round4(C, D, A, B, Data[2] + Longint($2AD7D2BB), 15); + Round4(B, C, D, A, Data[9] + Longint($EB86D391), 21); - Inc(Buf[0],A); - Inc(Buf[1],B); - Inc(Buf[2],C); - Inc(Buf[3],D); + Inc(Buf[0], A); + Inc(Buf[1], B); + Inc(Buf[2], C); + Inc(Buf[3], D); end; -procedure MD5Update(var MD5Context:TMD5Ctx; const Data:string); +procedure MD5Update(var MD5Context: TMD5Ctx; const Data: string); var - Index,t,len:integer; + Index, t, len: Integer; begin - len:=length(data); + len := Length(Data); with MD5Context do + begin + T := Count[0]; + Inc(Count[0], Len shl 3); + if Count[0] < T then + Inc(Count[1]); + Inc(Count[1], Len shr 29); + T := (T shr 3) and $3F; + Index := 0; + if T <> 0 then begin - T:=Count[0]; - Inc(Count[0], Len shl 3); - if Count[0]0 then - begin - Index:=T; - T:=64-T; - if Len=64 do - begin - Move(Data[Index+1], Bufchar, 64); - MD5Transform(State, Buflong); - Inc(Index, 64); - Dec(Len, 64); - end; - Move(Data[Index+1], Bufchar, Len); - end -end; - -function MD5Final(var MD5Context: TMD5Ctx):string; -var - Cnt : Word; - P : Byte; - digest:array[0..15] of Char; - i:integer; -begin - for I:=0 to 15 do - Byte(Digest[I]):=I+1; - with MD5Context do - begin - Cnt:=(Count[0] shr 3) and $3F; - P:=Cnt; - BufChar[P]:=$80; - Inc(P); - Cnt:=64-1-Cnt; - if Cnt<8 then - begin - FillChar(BufChar[P], Cnt, #0); - MD5Transform(State, BufLong); - FillChar(BufChar, 56, #0); - end - else fillChar(BufChar[P], Cnt-8, #0); - BufLong[14] := Count[0]; - BufLong[15] := Count[1]; - MD5Transform(State, BufLong); - Move(State, Digest, 16); - result:=''; - for i:=0 to 15 do - result:=result+char(digest[i]); + Index := T; + T := 64 - T; + if Len < T then + begin + Move(Data, Bufchar[Index], Len); + Exit; + end; + Move(Data, Bufchar[Index], T); + MD5Transform(State, Buflong); + Dec(Len, T); + Index := T; end; + while Len >= 64 do + begin + Move(Data[Index + 1], Bufchar, 64); + MD5Transform(State, Buflong); + Inc(Index, 64); + Dec(Len, 64); + end; + Move(Data[Index + 1], Bufchar, Len); + end +end; + +function MD5Final(var MD5Context: TMD5Ctx): string; +var + Cnt: Word; + P: Byte; + digest: array[0..15] of Char; + i: Integer; +begin + for I := 0 to 15 do + Byte(Digest[I]) := I + 1; + with MD5Context do + begin + Cnt := (Count[0] shr 3) and $3F; + P := Cnt; + BufChar[P] := $80; + Inc(P); + Cnt := 64 - 1 - Cnt; + if Cnt < 8 then + begin + FillChar(BufChar[P], Cnt, #0); + MD5Transform(State, BufLong); + FillChar(BufChar, 56, #0); + end + else + FillChar(BufChar[P], Cnt - 8, #0); + BufLong[14] := Count[0]; + BufLong[15] := Count[1]; + MD5Transform(State, BufLong); + Move(State, Digest, 16); + Result := ''; + for i := 0 to 15 do + Result := Result + Char(digest[i]); + end; FillChar(MD5Context, SizeOf(TMD5Ctx), #0) end; {==============================================================================} -{MD5} -function MD5(value:string): string; -var - MD5Context : TMD5Ctx; -begin - MD5Init(MD5Context); - MD5Update(MD5Context,value); - result:=MD5Final(MD5Context); -end; -{==============================================================================} -{HMAC_MD5} -function HMAC_MD5(text,key:string):string; +function MD5(const Value: string): string; var - ipad,opad,s:string; - n:integer; - MD5Context : TMD5Ctx; + MD5Context: TMD5Ctx; begin - if length(key)>64 then - key:=md5(key); - ipad:=''; - for n:=1 to 64 do - ipad:=ipad+#$36; - opad:=''; - for n:=1 to 64 do - opad:=opad+#$5c; - for n:=1 to length(key) do - begin - ipad[n]:=char(byte(ipad[n]) xor byte(key[n])); - opad[n]:=char(byte(opad[n]) xor byte(key[n])); - end; MD5Init(MD5Context); - MD5Update(MD5Context,ipad); - MD5Update(MD5Context,text); - s:=MD5Final(MD5Context); - MD5Init(MD5Context); - MD5Update(MD5Context,opad); - MD5Update(MD5Context,s); - result:=MD5Final(MD5Context); + MD5Update(MD5Context, Value); + Result := MD5Final(MD5Context); end; {==============================================================================} +function HMAC_MD5(Text, Key: string): string; +var + ipad, opad, s: string; + n: Integer; + MD5Context: TMD5Ctx; begin - exit; - asm - db 'Synapse coding and decoding support library by Lukas Gebauer',0 + if Length(Key) > 64 then + Key := md5(Key); + ipad := ''; + for n := 1 to 64 do + ipad := ipad + #$36; + opad := ''; + for n := 1 to 64 do + opad := opad + #$5C; + for n := 1 to Length(Key) do + begin + ipad[n] := Char(Byte(ipad[n]) xor Byte(Key[n])); + opad[n] := Char(Byte(opad[n]) xor Byte(Key[n])); end; + MD5Init(MD5Context); + MD5Update(MD5Context, ipad); + MD5Update(MD5Context, Text); + s := MD5Final(MD5Context); + MD5Init(MD5Context); + MD5Update(MD5Context, opad); + MD5Update(MD5Context, s); + Result := MD5Final(MD5Context); +end; + end. - - diff --git a/synahook.pas b/synahook.pas new file mode 100644 index 0000000..38abbd3 --- /dev/null +++ b/synahook.pas @@ -0,0 +1,21 @@ +unit SynaHook; + +interface + +type + THookReason = ( + HR_connect, + HR_login, + HR_logout, + HR_command, + HR_result, + HR_beginTransfer, + HR_endTransfer, + HR_TransferCounter + ); + + THookEvent = procedure(Sender: TObject; Reason: THookReason; Value: string) of object; + +implementation + +end. diff --git a/synautil.pas b/synautil.pas index dcfc973..7842a49 100644 --- a/synautil.pas +++ b/synautil.pas @@ -1,11 +1,11 @@ {==============================================================================| -| Project : Delphree - Synapse | 002.000.000 | +| Project : Delphree - Synapse | 002.000.001 | |==============================================================================| | Content: support procedures and functions | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | -| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | +| License. You may obtain a Copy of the License at http://www.mozilla.org/MPL/ | | | | Software distributed under the License is distributed on an "AS IS" basis, | | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | @@ -32,428 +32,447 @@ unit SynaUtil; interface uses - sysutils, classes, + SysUtils, Classes, {$IFDEF LINUX} - libc; + Libc; {$ELSE} - windows; + Windows; {$ENDIF} -function timezone:string; -function Rfc822DateTime(t:TDateTime):String; -function CodeInt(Value:word):string; -function DeCodeInt(Value:string;Index:integer):word; -function IsIP(Value:string):Boolean; -function ReverseIP(Value:string):string; -procedure Dump (Buffer:string;DumpFile:string); -function SeparateLeft(value,delimiter:string):string; -function SeparateRight(value,delimiter:string):string; -function getparameter(value,parameter:string):string; -function GetEmailAddr(value:string):string; -function GetEmailDesc(value:string):string; -function StrToHex(value:string):string; -function IntToBin(value:integer;digits:byte):string; -function BinToInt(value:string):integer; -function ParseURL(URL:string; var Prot,User,Pass,Host,Port,Path,Para:string):string; -function StringReplace(value,search,replace:string):string; +function Timezone: string; +function Rfc822DateTime(t: TDateTime): string; +function CodeInt(Value: Word): string; +function DecodeInt(const Value: string; Index: Integer): Word; +function IsIP(const Value: string): Boolean; +function ReverseIP(Value: string): string; +procedure Dump(const Buffer, DumpFile: string); +function SeparateLeft(const Value, Delimiter: string): string; +function SeparateRight(const Value, Delimiter: string): string; +function GetParameter(const Value, Parameter: string): string; +function GetEmailAddr(const Value: string): string; +function GetEmailDesc(Value: string): string; +function StrToHex(const Value: string): string; +function IntToBin(Value: Integer; Digits: Byte): string; +function BinToInt(const Value: string): Integer; +function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path, + Para: string): string; +function StringReplace(Value, Search, Replace: string): string; implementation {==============================================================================} -{timezone} -function timezone:string; + +function Timezone: string; {$IFDEF LINUX} var t: TTime_T; - UT: TUnixTime; - bias:integer; - h,m:integer; + UT: TUnixTime; + bias: Integer; + h, m: Integer; begin __time(@T); - localtime_r(@T,UT); - bias:=ut.__tm_gmtoff div 60; - if bias>=0 then result:='+' - else result:='-'; -{$ELSE} + localtime_r(@T, UT); + bias := ut.__tm_gmtoff div 60; + if bias >= 0 then + Result := '+' + else + Result := '-'; +{$ELSE} var - zoneinfo:TTimeZoneInformation; - bias:integer; - h,m:integer; + zoneinfo: TTimeZoneInformation; + bias: Integer; + h, m: Integer; begin case GetTimeZoneInformation(Zoneinfo) of - 2: bias:=zoneinfo.bias+zoneinfo.DaylightBias; - 1: bias:=zoneinfo.bias+zoneinfo.StandardBias; - else - bias:=zoneinfo.bias; + 2: + bias := zoneinfo.Bias + zoneinfo.DaylightBias; + 1: + bias := zoneinfo.Bias + zoneinfo.StandardBias; + else + bias := zoneinfo.Bias; end; - if bias<=0 then result:='+' - else result:='-'; + if bias <= 0 then + Result := '+' + else + Result := '-'; {$ENDIF} - bias:=abs(bias); - h:=bias div 60; - m:=bias mod 60; - result:=result+format('%.2d%.2d',[h,m]); + bias := Abs(bias); + h := bias div 60; + m := bias mod 60; + Result := Result + Format('%.2d%.2d', [h, m]); end; {==============================================================================} -{Rfc822DateTime} -function Rfc822DateTime(t:TDateTime):String; +function Rfc822DateTime(t: TDateTime): string; var I: Integer; SaveDayNames: array[1..7] of string; SaveMonthNames: array[1..12] of string; const MyDayNames: array[1..7] of string = - ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); + ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); MyMonthNames: array[1..12] of string = - ('Jan', 'Feb', 'Mar', 'Apr', - 'May', 'Jun', 'Jul', 'Aug', - 'Sep', 'Oct', 'Nov', 'Dec'); + ('Jan', 'Feb', 'Mar', 'Apr', + 'May', 'Jun', 'Jul', 'Aug', + 'Sep', 'Oct', 'Nov', 'Dec'); begin - if ShortDayNames[1] = MyDayNames[1] - then Result := FormatDateTime('ddd, d mmm yyyy hh:mm:ss', t) + if ShortDayNames[1] = MyDayNames[1] then + Result := FormatDateTime('ddd, d mmm yyyy hh:mm:ss', t) + else + begin + for I := Low(ShortDayNames) to High(ShortDayNames) do + begin + SaveDayNames[I] := ShortDayNames[I]; + ShortDayNames[I] := MyDayNames[I]; + end; + for I := Low(ShortMonthNames) to High(ShortMonthNames) do + begin + SaveMonthNames[I] := ShortMonthNames[I]; + ShortMonthNames[I] := MyMonthNames[I]; + end; + Result := FormatDateTime('ddd, d mmm yyyy hh:mm:ss', t); + for I := Low(ShortDayNames) to High(ShortDayNames) do + ShortDayNames[I] := SaveDayNames[I]; + for I := Low(ShortMonthNames) to High(ShortMonthNames) do + ShortMonthNames[I] := SaveMonthNames[I]; + end; + Result := Result + ' ' + Timezone; +end; + +{==============================================================================} + +function CodeInt(Value: Word): string; +begin + Result := Chr(Hi(Value)) + Chr(Lo(Value)) +end; + +{==============================================================================} + +function DecodeInt(const Value: string; Index: Integer): Word; +var + x, y: Byte; +begin + if Length(Value) > Index then + x := Ord(Value[Index]) + else + x := 0; + if Length(Value) > (Index + 1) then + y := Ord(Value[Index + 1]) + else + y := 0; + Result := x * 256 + y; +end; + +{==============================================================================} + +function IsIP(const Value: string): Boolean; +var + n, x: Integer; +begin + Result := true; + x := 0; + for n := 1 to Length(Value) do + if not (Value[n] in ['0'..'9', '.']) then + begin + Result := False; + Break; + end else - begin - for I := Low(ShortDayNames) to High(ShortDayNames) do - begin - SaveDayNames[I] := ShortDayNames[I]; - ShortDayNames[I] := MyDayNames[I]; - end; - for I := Low(ShortMonthNames) to High(ShortMonthNames) do - begin - SaveMonthNames[I] := ShortMonthNames[I]; - ShortMonthNames[I] := MyMonthNames[I]; - end; - Result := FormatDateTime('ddd, d mmm yyyy hh:mm:ss', t); - for I := Low(ShortDayNames) to High(ShortDayNames) do - ShortDayNames[I] := SaveDayNames[I]; - for I := Low(ShortMonthNames) to High(ShortMonthNames) do - ShortMonthNames[I] := SaveMonthNames[I]; - end; - Result:=Result+' '+Timezone; + begin + if Value[n] = '.' then + Inc(x); + end; + if x <> 3 then + Result := False; end; {==============================================================================} -{CodeInt} -function CodeInt(Value:word):string; -begin - Result := Chr(Hi(Value))+ Chr(Lo(Value)) -end; - -{==============================================================================} - -{DeCodeInt} -function DeCodeInt(Value:string;Index:integer):word; +function ReverseIP(Value: string): string; var - x,y:Byte; + x: Integer; begin - if Length(Value)>index then x:=Ord(Value[index]) - else x:=0; - if Length(Value)>(Index+1) then y:=Ord(Value[Index+1]) - else y:=0; - Result:=x*256+y; -end; - -{==============================================================================} - -{IsIP} -function IsIP(Value:string):Boolean; -var - n,x:integer; -begin - Result:=true; - x:=0; - for n:=1 to Length(Value) do - if not (Value[n] in ['0'..'9','.']) - then begin - Result:=False; - break; - end - else begin - if Value[n]='.' then Inc(x); - end; - if x<>3 then Result:=False; -end; - -{==============================================================================} - -{ReverseIP} -function ReverseIP(Value:string):string; -var - x:integer; -begin - Result:=''; + Result := ''; repeat - x:=LastDelimiter('.',Value); - Result:=Result+'.'+Copy(Value,x+1,Length(Value)-x); - Delete(Value,x,Length(Value)-x+1); - until x<1; - if Length(Result)>0 then - if Result[1]='.' then + x := LastDelimiter('.', Value); + Result := Result + '.' + Copy(Value, x + 1, Length(Value) - x); + Delete(Value, x, Length(Value) - x + 1); + until x < 1; + if Length(Result) > 0 then + if Result[1] = '.' then Delete(Result, 1, 1); end; {==============================================================================} -{dump} -procedure dump (Buffer:string;DumpFile:string); +procedure Dump(const Buffer, DumpFile: string); var - n:integer; - s:string; - f:Text; + n: Integer; + s: string; + f: Text; begin - s:=''; - for n:=1 to Length(Buffer) do - s:=s+' +#$'+IntToHex(Ord(Buffer[n]),2); - Assignfile(f,DumpFile); - if fileexists(DumpFile) then deletefile(PChar(DumpFile)); - rewrite(f); + s := ''; + for n := 1 to Length(Buffer) do + s := s + ' +#$' + IntToHex(Ord(Buffer[n]), 2); + AssignFile(f, DumpFile); + if FileExists(DumpFile) then + DeleteFile(PChar(DumpFile)); + Rewrite(f); try - writeln(f,s); + Writeln(f, s); finally - closefile(f); + CloseFile(f); end; end; {==============================================================================} -{SeparateLeft} -function SeparateLeft(value,delimiter:string):string; + +function SeparateLeft(const Value, Delimiter: string): string; var - x:integer; + x: Integer; begin - x:=pos(delimiter,value); - if x<1 - then result:=trim(value) - else result:=trim(copy(value,1,x-1)); + x := Pos(Delimiter, Value); + if x < 1 then + Result := Trim(Value) + else + Result := Trim(Copy(Value, 1, x - 1)); end; {==============================================================================} -{SeparateRight} -function SeparateRight(value,delimiter:string):string; + +function SeparateRight(const Value, Delimiter: string): string; var - x:integer; + x: Integer; begin - x:=pos(delimiter,value); - if x>0 - then x:=x+length(delimiter)-1; - result:=trim(copy(value,x+1,length(value)-x)); + x := Pos(Delimiter, Value); + if x > 0 then + x := x + Length(Delimiter) - 1; + Result := Trim(Copy(Value, x + 1, Length(Value) - x)); end; {==============================================================================} -{GetParameter} -function getparameter(value,parameter:string):string; + +function GetParameter(const Value, Parameter: string): string; var - x,x1:integer; - s:string; + x, x1: Integer; + s: string; begin - x:=pos(uppercase(parameter),uppercase(value)); - result:=''; - if x>0 then + x := Pos(UpperCase(Parameter), UpperCase(Value)); + Result := ''; + if x > 0 then + begin + s := Copy(Value, x + Length(Parameter), Length(Value) + - (x + Length(Parameter)) + 1); + s := Trim(s); + x1 := Length(s); + if Length(s) > 1 then begin - s:=copy(value,x+length(parameter),length(value)-(x+length(parameter))+1); - s:=trim(s); - x1:=length(s); - if length(s)>1 then - begin - if s[1]='"' - then - begin - s:=copy(s,2,length(s)-1); - x:=pos('"',s); - if x>0 then x1:=x-1; - end - else - begin - x:=pos(' ',s); - if x>0 then x1:=x-1; - end; - end; - result:=copy(s,1,x1); - end; -end; - -{==============================================================================} -{GetEmailAddr} -function GetEmailAddr(value:string):string; -var - s:string; -begin - s:=separateright(value,'<'); - s:=separateleft(s,'>'); - result:=trim(s); -end; - -{==============================================================================} -{GetEmailDesc} -function GetEmailDesc(value:string):string; -var - s:string; -begin - value:=trim(value); - s:=separateright(value,'"'); - if s<>value - then s:=separateleft(s,'"') - else + if s[1] = '"' then begin - s:=separateright(value,'('); - if s<>value - then s:=separateleft(s,')') - else - begin - s:=separateleft(value,'<'); - if s=value - then s:=''; - end; + s := Copy(s, 2, Length(s) - 1); + x := Pos('"', s); + if x > 0 then + x1 := x - 1; + end + else + begin + x := Pos(' ', s); + if x > 0 then + x1 := x - 1; end; - result:=trim(s); -end; - -{==============================================================================} -{StrToHex} -function StrToHex(value:string):string; -var - n:integer; -begin - result:=''; - for n:=1 to length(value) do - Result:=Result+IntToHex(Byte(value[n]),2); - result:=lowercase(result); -end; - -{==============================================================================} -{IntToBin} -function IntToBin(value:integer;digits:byte):string; -var - x,y,n:integer; -begin - result:=''; - x:=value; - repeat - y:=x mod 2; - x:=x div 2; - if y>0 - then result:='1'+result - else result:='0'+result; - until x=0; - x:=length(result); - for n:=x to digits-1 do - result:='0'+result; -end; - -{==============================================================================} -{BinToInt} -function BinToInt(value:string):integer; -var - x,n:integer; -begin - result:=0; - for n:=1 to length(value) do - begin - if value[n]='0' - then x:=0 - else x:=1; - result:=result*2+x; end; + Result := Copy(s, 1, x1); + end; end; {==============================================================================} -{ParseURL} -function ParseURL(URL:string; var Prot,User,Pass,Host,Port,Path,Para:string):string; -var - x:integer; - sURL:string; - s:string; - s1,s2:string; -begin - prot:='http'; - user:=''; - pass:=''; - port:='80'; - para:=''; - x:=pos('://',URL); - if x>0 then - begin - prot:=separateleft(URL,'://'); - sURL:=separateright(URL,'://'); - end - else sURL:=URL; - x:=pos('@',sURL); - if x>0 then - begin - s:=separateleft(sURL,'@'); - sURL:=separateright(sURL,'@'); - x:=pos(':',s); - if x>0 then - begin - user:=separateleft(s,':'); - pass:=separateright(s,':'); - end - else user:=s; - end; - x:=pos('/',sURL); - if x>0 then - begin - s1:=separateleft(sURL,'/'); - s2:=separateright(sURL,'/'); - end +function GetEmailAddr(const Value: string): string; +var + s: string; +begin + s := SeparateRight(Value, '<'); + s := SeparateLeft(s, '>'); + Result := Trim(s); +end; + +{==============================================================================} + +function GetEmailDesc(Value: string): string; +var + s: string; +begin + Value := Trim(Value); + s := SeparateRight(Value, '"'); + if s <> Value then + s := SeparateLeft(s, '"') + else + begin + s := SeparateRight(Value, '('); + if s <> Value then + s := SeparateLeft(s, ')') else begin - s1:=sURL; - s2:=''; + s := SeparateLeft(Value, '<'); + if s = Value then + s := ''; end; - x:=pos(':',s1); - if x>0 then - begin - host:=separateleft(s1,':'); - port:=separateright(s1,':'); - end - else host:=s1; - result:='/'+s2; - x:=pos('?',s2); - if x>0 then - begin - path:='/'+separateleft(s2,'?'); - para:=separateright(s2,'?'); - end - else path:='/'+s2; - if host='' - then host:='localhost'; + end; + Result := Trim(s); end; {==============================================================================} -{StringReplace} -function StringReplace(value,search,replace:string):string; + +function StrToHex(const Value: string): string; var - x,l,ls,lr:integer; + n: Integer; begin - if (value='') or (Search='') then - begin - result:=value; - Exit; - end; - ls:=length(search); - lr:=length(replace); - result:=''; - x:=pos(search,value); - while x>0 do - begin - l:=length(result); - setlength(result,l+x-1); - Move(pointer(value)^,Pointer(@result[l+1])^, x-1); -// result:=result+copy(value,1,x-1); - l:=length(result); - setlength(result,l+lr); - Move(pointer(replace)^,Pointer(@result[l+1])^, lr); -// result:=result+replace; - delete(value,1,x-1+ls); - x:=pos(search,value); - end; - result:=result+value; + Result := ''; + for n := 1 to Length(Value) do + Result := Result + IntToHex(Byte(Value[n]), 2); + Result := LowerCase(Result); end; {==============================================================================} +function IntToBin(Value: Integer; Digits: Byte): string; +var + x, y, n: Integer; +begin + Result := ''; + x := Value; + repeat + y := x mod 2; + x := x div 2; + if y > 0 then + Result := '1' + Result + else + Result := '0' + Result; + until x = 0; + x := Length(Result); + for n := x to Digits - 1 do + Result := '0' + Result; +end; + +{==============================================================================} + +function BinToInt(const Value: string): Integer; +var + n: Integer; +begin + Result := 0; + for n := 1 to Length(Value) do + begin + if Value[n] = '0' then + Result := Result * 2 + else + if Value[n] = '1' then + Result := Result * 2 + 1 + else + Break; + end; +end; + +{==============================================================================} + +function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path, + Para: string): string; +var + x: Integer; + sURL: string; + s: string; + s1, s2: string; +begin + Prot := 'http'; + User := ''; + Pass := ''; + Port := '80'; + Para := ''; + + x := Pos('://', URL); + if x > 0 then + begin + Prot := SeparateLeft(URL, '://'); + sURL := SeparateRight(URL, '://'); + end + else + sURL := URL; + x := Pos('@', sURL); + if x > 0 then + begin + s := SeparateLeft(sURL, '@'); + sURL := SeparateRight(sURL, '@'); + x := Pos(':', s); + if x > 0 then + begin + User := SeparateLeft(s, ':'); + Pass := SeparateRight(s, ':'); + end + else + User := s; + end; + x := Pos('/', sURL); + if x > 0 then + begin + s1 := SeparateLeft(sURL, '/'); + s2 := SeparateRight(sURL, '/'); + end + else + begin + s1 := sURL; + s2 := ''; + end; + x := Pos(':', s1); + if x > 0 then + begin + Host := SeparateLeft(s1, ':'); + Port := SeparateRight(s1, ':'); + end + else + Host := s1; + Result := '/' + s2; + x := Pos('?', s2); + if x > 0 then + begin + Path := '/' + SeparateLeft(s2, '?'); + Para := SeparateRight(s2, '?'); + end + else + Path := '/' + s2; + if Host = '' then + Host := 'localhost'; +end; + +{==============================================================================} + +function StringReplace(Value, Search, Replace: string): string; +var + x, l, ls, lr: Integer; +begin + if (Value = '') or (Search = '') then + begin + Result := Value; + Exit; + end; + ls := Length(Search); + lr := Length(Replace); + Result := ''; + x := Pos(Search, Value); + while x > 0 do + begin + l := Length(Result); + SetLength(Result, l + x - 1); + Move(Pointer(Value)^, Pointer(@Result[l + 1])^, x - 1); +// Result:=Result+Copy(Value,1,x-1); + l := Length(Result); + SetLength(Result, l + lr); + Move(Pointer(Replace)^, Pointer(@Result[l + 1])^, lr); +// Result:=Result+Replace; + Delete(Value, 1, x - 1 + ls); + x := Pos(Search, Value); + end; + Result := Result + Value; +end; + end. diff --git a/synsock.pas b/synsock.pas index 86413d9..acc8a2d 100644 --- a/synsock.pas +++ b/synsock.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Delphree - Synapse | 001.000.001 | +| Project : Delphree - Synapse | 001.000.002 | |==============================================================================| | Content: Socket Independent Platform | |==============================================================================| -| The contents of this file are subject to the Mozilla Public License Ver. 1.0 | +| The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | @@ -23,83 +23,86 @@ | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================} +{$WEAKPACKAGEUNIT ON} + unit synsock; interface uses {$IFDEF LINUX} - libc, kernelioctl; + Libc, KernelIoctl; {$ELSE} - winsock, windows; + Windows, WinSock; {$ENDIF} {$IFDEF LINUX} const - WSAEINTR = EINTR; - WSAEBADF = EBADF; - WSAEACCES = EACCES; - WSAEFAULT = EFAULT; - WSAEINVAL = EINVAL; - WSAEMFILE = EMFILE; - WSAEWOULDBLOCK = EWOULDBLOCK; - WSAEINPROGRESS = EINPROGRESS; - WSAEALREADY = EALREADY; - WSAENOTSOCK = ENOTSOCK; - WSAEDESTADDRREQ = EDESTADDRREQ; - WSAEMSGSIZE = EMSGSIZE; - WSAEPROTOTYPE = EPROTOTYPE; - WSAENOPROTOOPT = ENOPROTOOPT; + WSAEINTR = EINTR; + WSAEBADF = EBADF; + WSAEACCES = EACCES; + WSAEFAULT = EFAULT; + WSAEINVAL = EINVAL; + WSAEMFILE = EMFILE; + WSAEWOULDBLOCK = EWOULDBLOCK; + WSAEINPROGRESS = EINPROGRESS; + WSAEALREADY = EALREADY; + WSAENOTSOCK = ENOTSOCK; + WSAEDESTADDRREQ = EDESTADDRREQ; + WSAEMSGSIZE = EMSGSIZE; + WSAEPROTOTYPE = EPROTOTYPE; + WSAENOPROTOOPT = ENOPROTOOPT; WSAEPROTONOSUPPORT = EPROTONOSUPPORT; WSAESOCKTNOSUPPORT = ESOCKTNOSUPPORT; - WSAEOPNOTSUPP = EOPNOTSUPP; - WSAEPFNOSUPPORT = EPFNOSUPPORT; - WSAEAFNOSUPPORT = EAFNOSUPPORT; - WSAEADDRINUSE = EADDRINUSE; - WSAEADDRNOTAVAIL = EADDRNOTAVAIL; - WSAENETDOWN = ENETDOWN; - WSAENETUNREACH = ENETUNREACH; - WSAENETRESET = ENETRESET; - WSAECONNABORTED = ECONNABORTED; - WSAECONNRESET = ECONNRESET; - WSAENOBUFS = ENOBUFS; - WSAEISCONN = EISCONN; - WSAENOTCONN = ENOTCONN; - WSAESHUTDOWN = ESHUTDOWN; - WSAETOOMANYREFS = ETOOMANYREFS; - WSAETIMEDOUT = ETIMEDOUT; - WSAECONNREFUSED = ECONNREFUSED; - WSAELOOP = ELOOP; - WSAENAMETOOLONG = ENAMETOOLONG; - WSAEHOSTDOWN = EHOSTDOWN; - WSAEHOSTUNREACH = EHOSTUNREACH; - WSAENOTEMPTY = ENOTEMPTY; - WSAEPROCLIM = -1; - WSAEUSERS = EUSERS; - WSAEDQUOT = EDQUOT; - WSAESTALE = ESTALE; - WSAEREMOTE = EREMOTE; - WSASYSNOTREADY = -2; + WSAEOPNOTSUPP = EOPNOTSUPP; + WSAEPFNOSUPPORT = EPFNOSUPPORT; + WSAEAFNOSUPPORT = EAFNOSUPPORT; + WSAEADDRINUSE = EADDRINUSE; + WSAEADDRNOTAVAIL = EADDRNOTAVAIL; + WSAENETDOWN = ENETDOWN; + WSAENETUNREACH = ENETUNREACH; + WSAENETRESET = ENETRESET; + WSAECONNABORTED = ECONNABORTED; + WSAECONNRESET = ECONNRESET; + WSAENOBUFS = ENOBUFS; + WSAEISCONN = EISCONN; + WSAENOTCONN = ENOTCONN; + WSAESHUTDOWN = ESHUTDOWN; + WSAETOOMANYREFS = ETOOMANYREFS; + WSAETIMEDOUT = ETIMEDOUT; + WSAECONNREFUSED = ECONNREFUSED; + WSAELOOP = ELOOP; + WSAENAMETOOLONG = ENAMETOOLONG; + WSAEHOSTDOWN = EHOSTDOWN; + WSAEHOSTUNREACH = EHOSTUNREACH; + WSAENOTEMPTY = ENOTEMPTY; + WSAEPROCLIM = -1; + WSAEUSERS = EUSERS; + WSAEDQUOT = EDQUOT; + WSAESTALE = ESTALE; + WSAEREMOTE = EREMOTE; + WSASYSNOTREADY = -2; WSAVERNOTSUPPORTED = -3; - WSANOTINITIALISED = -4; - WSAEDISCON = -5; - WSAHOST_NOT_FOUND = HOST_NOT_FOUND; - WSATRY_AGAIN = TRY_AGAIN; - WSANO_RECOVERY = NO_RECOVERY; + WSANOTINITIALISED = -4; + WSAEDISCON = -5; + WSAHOST_NOT_FOUND = HOST_NOT_FOUND; + WSATRY_AGAIN = TRY_AGAIN; + WSANO_RECOVERY = NO_RECOVERY; // WSANO_DATA = NO_DATA; - WSANO_DATA = -6; + WSANO_DATA = -6; {$ELSE} + const DLLStackName = 'wsock32.dll'; var - LibHandle : THandle = 0; + LibHandle: THandle = 0; {$ENDIF} {$IFDEF LINUX} const - WSADESCRIPTION_LEN = 256; - WSASYS_STATUS_LEN = 128; + WSADESCRIPTION_LEN = 256; + WSASYS_STATUS_LEN = 128; type PWSAData = ^TWSAData; TWSAData = packed record @@ -111,321 +114,328 @@ type iMaxUdpDg: Word; lpVendorInfo: PChar; end; - DWORD=integer; - TLinger=Linger; + DWORD = Integer; + TLinger = Linger; {$ENDIF} - type - TWSAStartup = function (wVersionRequired: word; - var WSData: TWSAData): Integer; stdcall; - TWSACleanup = function : Integer; stdcall; - TWSAGetLastError = function : Integer; stdcall; - TGetServByName = function (name, proto: PChar): PServEnt; stdcall; - TGetServByPort = function (port: Integer; proto: PChar): PServEnt; stdcall; - TGetProtoByName = function (name: PChar): PProtoEnt; stdcall; - TGetProtoByNumber = function (proto: Integer): PProtoEnt; stdcall; - TGetHostByName = function (name: PChar): PHostEnt; stdcall; - TGetHostByAddr = function (addr: Pointer; len, Struct: Integer): PHostEnt; stdcall; - TGetHostName = function (name: PChar; len: Integer): Integer; stdcall; - TShutdown = function (s: TSocket; how: Integer): Integer; stdcall; - TSetSockOpt = function (s: TSocket; level, optname: Integer; - optval: PChar; - optlen: Integer): Integer; stdcall; - TGetSockOpt = function (s: TSocket; level, optname: Integer; - optval: PChar; - var optlen: Integer): Integer; stdcall; - TSendTo = function (s: TSocket; var Buf; - len, flags: Integer; - var addrto: TSockAddr; - tolen: Integer): Integer; stdcall; - TSend = function (s: TSocket; var Buf; - len, flags: Integer): Integer; stdcall; - TRecv = function (s: TSocket; - var Buf; - len, flags: Integer): Integer; stdcall; - TRecvFrom = function (s: TSocket; - var Buf; len, flags: Integer; - var from: TSockAddr; - var fromlen: Integer): Integer; stdcall; - Tntohs = function (netshort: u_short): u_short; stdcall; - Tntohl = function (netlong: u_long): u_long; stdcall; - TListen = function (s: TSocket; - backlog: Integer): Integer; stdcall; - TIoctlSocket = function (s: TSocket; cmd: DWORD; - var arg: u_long): Integer; stdcall; - TInet_ntoa = function (inaddr: TInAddr): PChar; stdcall; - TInet_addr = function (cp: PChar): u_long; stdcall; - Thtons = function (hostshort: u_short): u_short; stdcall; - Thtonl = function (hostlong: u_long): u_long; stdcall; - TGetSockName = function (s: TSocket; var name: TSockAddr; - var namelen: Integer): Integer; stdcall; - TGetPeerName = function (s: TSocket; var name: TSockAddr; - var namelen: Integer): Integer; stdcall; - TConnect = function (s: TSocket; var name: TSockAddr; - namelen: Integer): Integer; stdcall; - TCloseSocket = function (s: TSocket): Integer; stdcall; - TBind = function (s: TSocket; var addr: TSockAddr; - namelen: Integer): Integer; stdcall; - TAccept = function (s: TSocket; addr: PSockAddr; - addrlen: PInteger): TSocket; stdcall; - TSocketProc = function (af, Struct, protocol: Integer): TSocket; stdcall; - TSelect = function (nfds: Integer; readfds, writefds, exceptfds: PFDSet; - timeout: PTimeVal): Longint; stdcall; + TWSAStartup = function(wVersionRequired: Word; + var WSData: TWSAData): Integer; stdcall; + TWSACleanup = function: Integer; stdcall; + TWSAGetLastError = function: Integer; stdcall; + TGetServByName = function(name, proto: PChar): PServEnt; stdcall; + TGetServByPort = function(port: Integer; proto: PChar): PServEnt; stdcall; + TGetProtoByName = function(name: PChar): PProtoEnt; stdcall; + TGetProtoByNumber = function(proto: Integer): PProtoEnt; stdcall; + TGetHostByName = function(name: PChar): PHostEnt; stdcall; + TGetHostByAddr = function(addr: Pointer; len, Struc: Integer): PHostEnt; stdcall; + TGetHostName = function(name: PChar; len: Integer): Integer; stdcall; + TShutdown = function(s: TSocket; how: Integer): Integer; stdcall; + TSetSockOpt = function(s: TSocket; level, optname: Integer; + optval: PChar; optlen: Integer): Integer; stdcall; + TGetSockOpt = function(s: TSocket; level, optname: Integer; + optval: PChar; var optlen: Integer): Integer; stdcall; + TSendTo = function(s: TSocket; var Buf; + len, flags: Integer; var addrto: TSockAddr; + tolen: Integer): Integer; stdcall; + TSend = function(s: TSocket; var Buf; + len, flags: Integer): Integer; stdcall; + TRecv = function(s: TSocket; + var Buf; len, flags: Integer): Integer; stdcall; + TRecvFrom = function(s: TSocket; + var Buf; len, flags: Integer; var from: TSockAddr; + var fromlen: Integer): Integer; stdcall; + Tntohs = function(netshort: u_short): u_short; stdcall; + Tntohl = function(netlong: u_long): u_long; stdcall; + TListen = function(s: TSocket; backlog: Integer): Integer; stdcall; + TIoctlSocket = function(s: TSocket; cmd: DWORD; + var arg: u_long): Integer; stdcall; + TInet_ntoa = function(inaddr: TInAddr): PChar; stdcall; + TInet_addr = function(cp: PChar): u_long; stdcall; + Thtons = function(hostshort: u_short): u_short; stdcall; + Thtonl = function(hostlong: u_long): u_long; stdcall; + TGetSockName = function(s: TSocket; var name: TSockAddr; + var namelen: Integer): Integer; stdcall; + TGetPeerName = function(s: TSocket; var name: TSockAddr; + var namelen: Integer): Integer; stdcall; + TConnect = function(s: TSocket; var name: TSockAddr; + namelen: Integer): Integer; stdcall; + TCloseSocket = function(s: TSocket): Integer; stdcall; + TBind = function(s: TSocket; var addr: TSockAddr; + namelen: Integer): Integer; stdcall; + TAccept = function(s: TSocket; addr: PSockAddr; + addrlen: PInteger): TSocket; stdcall; + TSocketProc = function(af, Struc, Protocol: Integer): TSocket; stdcall; + TSelect = function(nfds: Integer; readfds, writefds, exceptfds: PFDSet; + timeout: PTimeVal): Longint; stdcall; var - WSAStartup : TWSAStartup =nil; - WSACleanup : TWSACleanup =nil; - WSAGetLastError : TWSAGetLastError =nil; - GetServByName : TGetServByName =nil; - GetServByPort : TGetServByPort =nil; - GetProtoByName : TGetProtoByName =nil; - GetProtoByNumber : TGetProtoByNumber =nil; - GetHostByName : TGetHostByName =nil; - GetHostByAddr : TGetHostByAddr =nil; - GetHostName : TGetHostName =nil; - Shutdown : TShutdown =nil; - SetSockOpt : TSetSockOpt =nil; - GetSockOpt : TGetSockOpt =nil; - SendTo : TSendTo =nil; - Send : TSend =nil; - Recv : TRecv =nil; - RecvFrom : TRecvFrom =nil; - ntohs : Tntohs =nil; - ntohl : Tntohl =nil; - Listen : TListen =nil; - IoctlSocket : TIoctlSocket =nil; - Inet_ntoa : TInet_ntoa =nil; - Inet_addr : TInet_addr =nil; - htons : Thtons =nil; - htonl : Thtonl =nil; - GetSockName : TGetSockName =nil; - GetPeerName : TGetPeerName =nil; - Connect : TConnect =nil; - CloseSocket : TCloseSocket =nil; - Bind : TBind =nil; - Accept : TAccept =nil; - Socket : TSocketProc =nil; - Select : TSelect =nil; + WSAStartup: TWSAStartup = nil; + WSACleanup: TWSACleanup = nil; + WSAGetLastError: TWSAGetLastError = nil; + GetServByName: TGetServByName = nil; + GetServByPort: TGetServByPort = nil; + GetProtoByName: TGetProtoByName = nil; + GetProtoByNumber: TGetProtoByNumber = nil; + GetHostByName: TGetHostByName = nil; + GetHostByAddr: TGetHostByAddr = nil; + GetHostName: TGetHostName = nil; + Shutdown: TShutdown = nil; + SetSockOpt: TSetSockOpt = nil; + GetSockOpt: TGetSockOpt = nil; + SendTo: TSendTo = nil; + Send: TSend = nil; + Recv: TRecv = nil; + RecvFrom: TRecvFrom = nil; + ntohs: Tntohs = nil; + ntohl: Tntohl = nil; + Listen: TListen = nil; + IoctlSocket: TIoctlSocket = nil; + Inet_ntoa: TInet_ntoa = nil; + Inet_addr: TInet_addr = nil; + htons: Thtons = nil; + htonl: Thtonl = nil; + GetSockName: TGetSockName = nil; + GetPeerName: TGetPeerName = nil; + Connect: TConnect = nil; + CloseSocket: TCloseSocket = nil; + Bind: TBind = nil; + Accept: TAccept = nil; + Socket: TSocketProc = nil; + Select: TSelect = nil; -function InitSocketInterface(stack:string):Boolean; -function DestroySocketInterface:Boolean; +function InitSocketInterface(stack: string): Boolean; +function DestroySocketInterface: Boolean; {$IFDEF LINUX} -function LSWSAStartup (wVersionRequired: Word; var WSData: TWSAData): Integer; stdcall; -function LSWSACleanup : Integer; stdcall; -function LSWSAGetLastError : Integer; stdcall; -function LSGetServByName (name, proto: PChar): PServEnt; stdcall; -function LSGetServByPort (port: Integer; proto: PChar): PServEnt; stdcall; -function LSGetProtoByName (name: PChar): PProtoEnt; stdcall; -function LSGetProtoByNumber (proto: Integer): PProtoEnt; stdcall; -function LSGetHostByName (name: PChar): PHostEnt; stdcall; -function LSGetHostByAddr (addr: Pointer; len, Struct: Integer): PHostEnt; stdcall; -function LSGetHostName (name: PChar; len: Integer): Integer; stdcall; -function LSShutdown (s: TSocket; how: Integer): Integer; stdcall; -function LSSetSockOpt (s: TSocket; level, optname: Integer; optval: PChar; optlen: Integer): Integer; stdcall; -function LSGetSockOpt (s: TSocket; level, optname: Integer; optval: PChar; var optlen: Integer): Integer; stdcall; -function LSSendTo (s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr; tolen: Integer): Integer; stdcall; -function LSSend (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; -function LSRecv (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; -function LSRecvFrom (s: TSocket; var Buf; len, flags: Integer; var from: TSockAddr; var fromlen: Integer): Integer; stdcall; -function LSntohs (netshort: u_short): u_short; stdcall; -function LSntohl (netlong: u_long): u_long; stdcall; -function LSListen (s: TSocket; backlog: Integer): Integer; stdcall; -function LSIoctlSocket (s: TSocket; cmd: DWORD; var arg: u_long): Integer; stdcall; -function LSInet_ntoa (inaddr: TInAddr): PChar; stdcall; -function LSInet_addr (cp: PChar): u_long; stdcall; -function LShtons (hostshort: u_short): u_short; stdcall; -function LShtonl (hostlong: u_long): u_long; stdcall; -function LSGetSockName (s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; stdcall; -function LSGetPeerName (s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; stdcall; -function LSConnect (s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall; -function LSCloseSocket (s: TSocket): Integer; stdcall; -function LSBind (s: TSocket; var addr: TSockAddr; namelen: Integer): Integer; stdcall; -function LSAccept (s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; stdcall; -function LSSocketProc (af, Struct, protocol: Integer): TSocket; stdcall; -function LSSelect (nfds: Integer; readfds, writefds, exceptfds: PFDSet; timeout: PTimeVal): Longint; stdcall; +function LSWSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer; stdcall; +function LSWSACleanup: Integer; stdcall; +function LSWSAGetLastError: Integer; stdcall; +function LSGetServByName(name, proto: PChar): PServEnt; stdcall; +function LSGetServByPort(port: Integer; proto: PChar): PServEnt; stdcall; +function LSGetProtoByName(name: PChar): PProtoEnt; stdcall; +function LSGetProtoByNumber(proto: Integer): PProtoEnt; stdcall; +function LSGetHostByName(name: PChar): PHostEnt; stdcall; +function LSGetHostByAddr(addr: Pointer; len, Struc: Integer): PHostEnt; stdcall; +function LSGetHostName(name: PChar; len: Integer): Integer; stdcall; +function LSShutdown(s: TSocket; how: Integer): Integer; stdcall; +function LSSetSockOpt(s: TSocket; level, optname: Integer; optval: PChar; + optlen: Integer): Integer; stdcall; +function LSGetSockOpt(s: TSocket; level, optname: Integer; optval: PChar; + var optlen: Integer): Integer; stdcall; +function LSSendTo(s: TSocket; var Buf; len, flags: Integer; + var addrto: TSockAddr; tolen: Integer): Integer; stdcall; +function LSSend(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; +function LSRecv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; +function LSRecvFrom(s: TSocket; var Buf; len, flags: Integer; + var from: TSockAddr; var fromlen: Integer): Integer; stdcall; +function LSntohs(netshort: u_short): u_short; stdcall; +function LSntohl(netlong: u_long): u_long; stdcall; +function LSListen(s: TSocket; backlog: Integer): Integer; stdcall; +function LSIoctlSocket(s: TSocket; cmd: DWORD; var arg: u_long): Integer; stdcall; +function LSInet_ntoa(inaddr: TInAddr): PChar; stdcall; +function LSInet_addr(cp: PChar): u_long; stdcall; +function LShtons(hostshort: u_short): u_short; stdcall; +function LShtonl(hostlong: u_long): u_long; stdcall; +function LSGetSockName(s: TSocket; var name: TSockAddr; + var namelen: Integer): Integer; stdcall; +function LSGetPeerName(s: TSocket; var name: TSockAddr; + var namelen: Integer): Integer; stdcall; +function LSConnect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall; +function LSCloseSocket(s: TSocket): Integer; stdcall; +function LSBind(s: TSocket; var addr: TSockAddr; namelen: Integer): Integer; stdcall; +function LSAccept(s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; stdcall; +function LSSocketProc(af, Struc, Protocol: Integer): TSocket; stdcall; +function LSSelect(nfds: Integer; readfds, writefds, exceptfds: PFDSet; + timeout: PTimeVal): Longint; stdcall; {$ENDIF} - implementation {$IFDEF LINUX} -function LSWSAStartup (wVersionRequired: Word; var WSData: TWSAData): Integer; + +function LSWSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer; begin - WSData.wVersion:=wVersionRequired; - WSData.wHighVersion:=$101; - WSData.szDescription:='Synapse Platform Independent Socket Layer'; - WSData.szSystemStatus:='On Linux'; - WSData.iMaxSockets:=32768; - WSData.iMaxUdpDg:=8192; - result:=0; + with WSData do + begin + wVersion := wVersionRequired; + wHighVersion := $101; + szDescription := 'Synapse Platform Independent Socket Layer'; + szSystemStatus := 'On Linux'; + iMaxSockets := 32768; + iMaxUdpDg := 8192; + end; + Result := 0; end; -function LSWSACleanup : Integer; +function LSWSACleanup: Integer; begin - Result:=0; + Result := 0; end; -function LSWSAGetLastError : Integer; +function LSWSAGetLastError: Integer; begin - result:=System.GetLastError; + Result := System.GetLastError; end; -function LSGetServByName (name, proto: PChar): PServEnt; +function LSGetServByName(name, proto: PChar): PServEnt; begin - result:=libc.GetServByName(name,proto); + Result := libc.GetServByName(name, proto); end; -function LSGetServByPort (port: Integer; proto: PChar): PServEnt; +function LSGetServByPort(port: Integer; proto: PChar): PServEnt; begin - result:=libc.GetServByPort(port,proto); + Result := libc.GetServByPort(port, proto); end; -function LSGetProtoByName (name: PChar): PProtoEnt; +function LSGetProtoByName(name: PChar): PProtoEnt; begin - result:=libc.getprotobyname(Name); + Result := libc.GetProtoByName(Name); end; -function LSGetProtoByNumber (proto: Integer): PProtoEnt; +function LSGetProtoByNumber(proto: Integer): PProtoEnt; begin - result:=libc.getprotobynumber(proto); + Result := libc.GetProtoByNumber(proto); end; -function LSGetHostByName (name: PChar): PHostEnt; +function LSGetHostByName(name: PChar): PHostEnt; begin - result:=libc.GetHostByName(Name); + Result := libc.GetHostByName(Name); end; -function LSGetHostByAddr (addr: Pointer; len, Struct: Integer): PHostEnt; +function LSGetHostByAddr(addr: Pointer; len, Struc: Integer): PHostEnt; begin - Result:=libc.GetHostByAddr(Addr,len,struct); + Result := libc.GetHostByAddr(Addr, len, struc); end; -function LSGetHostName (name: PChar; len: Integer): Integer; +function LSGetHostName(name: PChar; len: Integer): Integer; begin - Result:=libc.GetHostName(Name,Len); + Result := libc.GetHostName(Name, Len); end; -function LSShutdown (s: TSocket; how: Integer): Integer; +function LSShutdown(s: TSocket; how: Integer): Integer; begin - result:=libc.Shutdown(S,How); + Result := libc.Shutdown(S, How); end; -function LSSetSockOpt (s: TSocket; level, optname: Integer; optval: PChar; optlen: Integer): Integer; +function LSSetSockOpt(s: TSocket; level, optname: Integer; optval: PChar; + optlen: Integer): Integer; begin - result:=libc.SetSockOpt(S,Level,OptName,OptVal,OptLen); + Result := libc.SetSockOpt(S, Level, OptName, OptVal, OptLen); end; -function LSGetSockOpt (s: TSocket; level, optname: Integer; optval: PChar; var optlen: Integer): Integer; +function LSGetSockOpt(s: TSocket; level, optname: Integer; optval: PChar; + var optlen: Integer): Integer; begin - result:=libc.getsockopt(s,level,optname,optval,cardinal(optlen)); + Result := libc.getsockopt(s, level, optname, optval, cardinal(optlen)); end; -function LSSendTo (s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr; tolen: Integer): Integer; +function LSSendTo(s: TSocket; var Buf; len, flags: Integer; + var addrto: TSockAddr; tolen: Integer): Integer; begin - result:=libc.SendTo(S,Buf,Len,Flags,Addrto,Tolen); + Result := libc.SendTo(S, Buf, Len, Flags, Addrto, Tolen); end; -function LSSend (s: TSocket; var Buf; len, flags: Integer): Integer; +function LSSend(s: TSocket; var Buf; len, flags: Integer): Integer; begin - result:=libc.Send(S,Buf,Len,Flags); + Result := libc.Send(S, Buf, Len, Flags); end; -function LSRecv (s: TSocket; var Buf; len, flags: Integer): Integer; +function LSRecv(s: TSocket; var Buf; len, flags: Integer): Integer; begin - result:=libc.Recv(S,Buf,Len,Flags); + Result := libc.Recv(S, Buf, Len, Flags); end; -function LSRecvFrom (s: TSocket; var Buf; len, flags: Integer; var from: TSockAddr; var fromlen: Integer): Integer; +function LSRecvFrom(s: TSocket; var Buf; len, flags: Integer; + var from: TSockAddr; var fromlen: Integer): Integer; begin - result:=libc.RecvFrom(S,Buf,Len,Flags,@from,@fromlen); + Result := libc.RecvFrom(S, Buf, Len, Flags, @from, @fromlen); end; -function LSntohs (netshort: u_short): u_short; +function LSntohs(netshort: u_short): u_short; begin - Result:=libc.NToHS(netshort); + Result := libc.NToHS(netshort); end; -function LSntohl (netlong: u_long): u_long; +function LSntohl(netlong: u_long): u_long; begin - Result:=libc.NToHL(netlong); + Result := libc.NToHL(netlong); end; -function LSListen (s: TSocket; backlog: Integer): Integer; +function LSListen(s: TSocket; backlog: Integer): Integer; begin - result:=libc.Listen(S,Backlog); + Result := libc.Listen(S, Backlog); end; -function LSIoctlSocket (s: TSocket; cmd: DWORD; var arg: u_long): Integer; +function LSIoctlSocket(s: TSocket; cmd: DWORD; var arg: u_long): Integer; begin - result:=libc.ioctl(s,cmd,@arg); + Result := libc.ioctl(s, cmd, @arg); end; -function LSInet_ntoa (inaddr: TInAddr): PChar; +function LSInet_ntoa(inaddr: TInAddr): PChar; begin - result:=libc.inet_ntoa(inaddr); + Result := libc.inet_ntoa(inaddr); end; -function LSInet_addr (cp: PChar): u_long; +function LSInet_addr(cp: PChar): u_long; begin - result:=libc.inet_addr(cp); + Result := libc.inet_addr(cp); end; -function LShtons (hostshort: u_short): u_short; +function LShtons(hostshort: u_short): u_short; begin - result:=libc.HToNs(HostShort); + Result := libc.HToNs(HostShort); end; -function LShtonl (hostlong: u_long): u_long; +function LShtonl(hostlong: u_long): u_long; begin - Result:=libc.HToNL(HostLong); + Result := libc.HToNL(HostLong); end; -function LSGetSockName (s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; +function LSGetSockName(s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; begin - Result:=libc.GetSockName(S,Name,cardinal(namelen)); + Result := libc.GetSockName(S, Name, cardinal(namelen)); end; -function LSGetPeerName (s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; +function LSGetPeerName(s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; begin - Result:=libc.GetPeerName(S,Name,cardinal(namelen)); + Result := libc.GetPeerName(S, Name, cardinal(namelen)); end; -function LSConnect (s: TSocket; var name: TSockAddr; namelen: Integer): Integer; +function LSConnect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; begin - result:=libc.Connect(S,name,namelen); + Result := libc.Connect(S, name, namelen); end; -function LSCloseSocket (s: TSocket): Integer; +function LSCloseSocket(s: TSocket): Integer; begin - result:=libc.__close(s); + Result := libc.__close(s); end; -function LSBind (s: TSocket; var addr: TSockAddr; namelen: Integer): Integer; +function LSBind(s: TSocket; var addr: TSockAddr; namelen: Integer): Integer; begin - result:=libc.Bind(S,addr,namelen); + Result := libc.Bind(S, addr, namelen); end; -function LSAccept (s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; +function LSAccept(s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; begin - result:=libc.Accept(S,addr,psocketlength(addrlen)); + Result := libc.Accept(S, addr, psocketlength(addrlen)); end; -function LSSocketProc (af, Struct, protocol: Integer): TSocket; +function LSSocketProc(af, Struc, Protocol: Integer): TSocket; begin - result:=libc.Socket(Af,Struct,Protocol); + Result := libc.Socket(Af, Struc, Protocol); end; -function LSSelect (nfds: Integer; readfds, writefds, exceptfds: PFDSet; timeout: PTimeVal): Longint; +function LSSelect(nfds: Integer; readfds, writefds, exceptfds: PFDSet; + timeout: PTimeVal): Longint; begin - Result:=libc.Select(nfds,readfds,writefds,exceptfds,timeout); + Result := libc.Select(nfds, readfds, writefds, exceptfds, timeout); end; {$ENDIF} - -function InitSocketInterface(stack:string):Boolean; +function InitSocketInterface(stack: string): Boolean; begin {$IFDEF LINUX} Accept := LSAccept; @@ -451,72 +461,71 @@ begin SetSockOpt := LSsetsockopt; ShutDown := LSshutdown; Socket := LSsocketProc; - GetHostByAddr := LSgethostbyaddr; - GetHostByName := LSgethostbyname; - GetProtoByName := LSgetprotobyname; - GetProtoByNumber := LSgetprotobynumber; - GetServByName := LSgetservbyname; - GetServByPort := LSgetservbyport; - GetHostName := LSgethostname; + GetHostByAddr := LSGetHostByAddr; + GetHostByName := LSGetHostByName; + GetProtoByName := LSGetProtoByName; + GetProtoByNumber := LSGetProtoByNumber; + GetServByName := LSGetServByName; + GetServByPort := LSGetServByPort; + GetHostName := LSGetHostName; WSAGetLastError := LSWSAGetLastError; WSAStartup := LSWSAStartup; WSACleanup := LSWSACleanup; - Result:=True; + Result := True; {$ELSE} - Result:=False; - if stack='' - then stack:=DLLStackName; + Result := False; + if stack = '' then + stack := DLLStackName; LibHandle := Windows.LoadLibrary(PChar(Stack)); - if LibHandle <> 0 then begin - Accept := Windows.GetProcAddress (LibHandle, PChar('accept')); - Bind := Windows.GetProcAddress (LibHandle, PChar('bind')); - CloseSocket := Windows.GetProcAddress (LibHandle, PChar('closesocket')); - Connect := Windows.GetProcAddress (LibHandle, PChar('connect')); - GetPeerName := Windows.GetProcAddress (LibHandle, PChar('getpeername')); - GetSockName := Windows.GetProcAddress (LibHandle, PChar('getsockname')); - GetSockOpt := Windows.GetProcAddress (LibHandle, PChar('getsockopt')); - Htonl := Windows.GetProcAddress (LibHandle, PChar('htonl')); - Htons := Windows.GetProcAddress (LibHandle, PChar('htons')); - Inet_Addr := Windows.GetProcAddress (LibHandle, PChar('inet_addr')); - Inet_Ntoa := Windows.GetProcAddress (LibHandle, PChar('inet_ntoa')); - IoctlSocket := Windows.GetProcAddress (LibHandle, PChar('ioctlsocket')); - Listen := Windows.GetProcAddress (LibHandle, PChar('listen')); - Ntohl := Windows.GetProcAddress (LibHandle, PChar('ntohl')); - Ntohs := Windows.GetProcAddress (LibHandle, PChar('ntohs')); - Recv := Windows.GetProcAddress (LibHandle, PChar('recv')); - RecvFrom := Windows.GetProcAddress (LibHandle, PChar('recvfrom')); - Select := Windows.GetProcAddress (LibHandle, PChar('select')); - Send := Windows.GetProcAddress (LibHandle, PChar('send')); - SendTo := Windows.GetProcAddress (LibHandle, PChar('sendto')); - SetSockOpt := Windows.GetProcAddress (LibHandle, PChar('setsockopt')); - ShutDown := Windows.GetProcAddress (LibHandle, PChar('shutdown')); - Socket := Windows.GetProcAddress (LibHandle, PChar('socket')); - GetHostByAddr := Windows.GetProcAddress (LibHandle, PChar('gethostbyaddr')); - GetHostByName := Windows.GetProcAddress (LibHandle, PChar('gethostbyname')); - GetProtoByName := Windows.GetProcAddress (LibHandle, PChar('getprotobyname')); - GetProtoByNumber := Windows.GetProcAddress (LibHandle, PChar('getprotobynumber')); - GetServByName := Windows.GetProcAddress (LibHandle, PChar('getservbyname')); - GetServByPort := Windows.GetProcAddress (LibHandle, PChar('getservbyport')); - GetHostName := Windows.GetProcAddress (LibHandle, PChar('gethostname')); - WSAGetLastError := Windows.GetProcAddress (LibHandle, PChar('WSAGetLastError')); - WSAStartup := Windows.GetProcAddress (LibHandle, PChar('WSAStartup')); - WSACleanup := Windows.GetProcAddress (LibHandle, PChar('WSACleanup')); - Result:=True; + if LibHandle <> 0 then + begin + Accept := Windows.GetProcAddress(LibHandle, PChar('accept')); + Bind := Windows.GetProcAddress(LibHandle, PChar('bind')); + CloseSocket := Windows.GetProcAddress(LibHandle, PChar('closesocket')); + Connect := Windows.GetProcAddress(LibHandle, PChar('connect')); + GetPeerName := Windows.GetProcAddress(LibHandle, PChar('getpeername')); + GetSockName := Windows.GetProcAddress(LibHandle, PChar('getsockname')); + GetSockOpt := Windows.GetProcAddress(LibHandle, PChar('getsockopt')); + Htonl := Windows.GetProcAddress(LibHandle, PChar('htonl')); + Htons := Windows.GetProcAddress(LibHandle, PChar('htons')); + Inet_Addr := Windows.GetProcAddress(LibHandle, PChar('inet_addr')); + Inet_Ntoa := Windows.GetProcAddress(LibHandle, PChar('inet_ntoa')); + IoctlSocket := Windows.GetProcAddress(LibHandle, PChar('ioctlsocket')); + Listen := Windows.GetProcAddress(LibHandle, PChar('listen')); + Ntohl := Windows.GetProcAddress(LibHandle, PChar('ntohl')); + Ntohs := Windows.GetProcAddress(LibHandle, PChar('ntohs')); + Recv := Windows.GetProcAddress(LibHandle, PChar('recv')); + RecvFrom := Windows.GetProcAddress(LibHandle, PChar('recvfrom')); + Select := Windows.GetProcAddress(LibHandle, PChar('select')); + Send := Windows.GetProcAddress(LibHandle, PChar('send')); + SendTo := Windows.GetProcAddress(LibHandle, PChar('sendto')); + SetSockOpt := Windows.GetProcAddress(LibHandle, PChar('setsockopt')); + ShutDown := Windows.GetProcAddress(LibHandle, PChar('shutdown')); + Socket := Windows.GetProcAddress(LibHandle, PChar('socket')); + GetHostByAddr := Windows.GetProcAddress(LibHandle, PChar('gethostbyaddr')); + GetHostByName := Windows.GetProcAddress(LibHandle, PChar('gethostbyname')); + GetProtoByName := Windows.GetProcAddress(LibHandle, PChar('getprotobyname')); + GetProtoByNumber := Windows.GetProcAddress(LibHandle, PChar('getprotobynumber')); + GetServByName := Windows.GetProcAddress(LibHandle, PChar('getservbyname')); + GetServByPort := Windows.GetProcAddress(LibHandle, PChar('getservbyport')); + GetHostName := Windows.GetProcAddress(LibHandle, PChar('gethostname')); + WSAGetLastError := Windows.GetProcAddress(LibHandle, PChar('WSAGetLastError')); + WSAStartup := Windows.GetProcAddress(LibHandle, PChar('WSAStartup')); + WSACleanup := Windows.GetProcAddress(LibHandle, PChar('WSACleanup')); + Result := True; end; {$ENDIF} end; -function DestroySocketInterface:Boolean; +function DestroySocketInterface: Boolean; begin {$IFDEF LINUX} {$ELSE} - if LibHandle <> 0 then begin + if LibHandle <> 0 then Windows.FreeLibrary(libHandle); - end; LibHandle := 0; {$ENDIF} - Result:=True; + Result := True; end; - end.