294 lines
7.4 KiB
Plaintext
294 lines
7.4 KiB
Plaintext
|
{
|
||
|
$Project$
|
||
|
$Workfile$
|
||
|
$Revision$
|
||
|
$DateUTC$
|
||
|
$Id$
|
||
|
|
||
|
This file is part of the Indy (Internet Direct) project, and is offered
|
||
|
under the dual-licensing agreement described on the Indy website.
|
||
|
(http://www.indyproject.org/)
|
||
|
|
||
|
Copyright:
|
||
|
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
|
||
|
}
|
||
|
{
|
||
|
$Log$
|
||
|
}
|
||
|
{
|
||
|
Rev 1.10 2/8/05 5:29:16 PM RLebeau
|
||
|
Updated GetHToNBytes() to use CopyTIdWord() instead of AppendBytes() for IPv6
|
||
|
addresses.
|
||
|
|
||
|
Rev 1.9 28.09.2004 20:54:32 Andreas Hausladen
|
||
|
Removed unused functions that were moved to IdGlobal
|
||
|
|
||
|
Rev 1.8 6/11/2004 8:48:20 AM DSiders
|
||
|
Added "Do not Localize" comments.
|
||
|
|
||
|
Rev 1.7 5/19/2004 10:44:34 PM DSiders
|
||
|
Corrected spelling for TIdIPAddress.MakeAddressObject method.
|
||
|
|
||
|
Rev 1.6 14/04/2004 17:35:38 HHariri
|
||
|
Removed IP6 for BCB temporarily
|
||
|
|
||
|
Rev 1.5 2/11/2004 5:10:40 AM JPMugaas
|
||
|
Moved IPv6 address definition to System package.
|
||
|
|
||
|
Rev 1.4 2004.02.03 4:17:18 PM czhower
|
||
|
For unit name changes.
|
||
|
|
||
|
Rev 1.3 2/2/2004 12:22:24 PM JPMugaas
|
||
|
Now uses IdGlobal IPVersion Type. Added HToNBytes for things that need
|
||
|
to export into NetworkOrder for structures used in protocols.
|
||
|
|
||
|
Rev 1.2 1/3/2004 2:13:56 PM JPMugaas
|
||
|
Removed some empty function code that wasn't used.
|
||
|
Added some value comparison functions.
|
||
|
Added a function in the IPAddress object for comparing the value with another
|
||
|
IP address. Note that this comparison is useful as an IP address will take
|
||
|
several forms (especially common with IPv6).
|
||
|
Added a property for returning the IP address as a string which works for
|
||
|
both IPv4 and IPv6 addresses.
|
||
|
|
||
|
Rev 1.1 1/3/2004 1:03:14 PM JPMugaas
|
||
|
Removed Lo as it was not needed and is not safe in NET.
|
||
|
|
||
|
Rev 1.0 1/1/2004 4:00:18 PM JPMugaas
|
||
|
An object for handling both IPv4 and IPv6 addresses. This is a proposal with
|
||
|
some old code for conversions.
|
||
|
}
|
||
|
|
||
|
unit IdIPAddress;
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$I IdCompilerDefines.inc}
|
||
|
//we need to put this in Delphi mode to work
|
||
|
|
||
|
uses
|
||
|
Classes,
|
||
|
IdGlobal;
|
||
|
|
||
|
type
|
||
|
TIdIPAddress = class(TObject)
|
||
|
protected
|
||
|
FIPv4 : UInt32;
|
||
|
FAddrType : TIdIPVersion;
|
||
|
//general conversion stuff
|
||
|
//property as String Get methods
|
||
|
function GetIPv4AsString : String;
|
||
|
function GetIPv6AsString : String;
|
||
|
function GetIPAddress : String;
|
||
|
public
|
||
|
//We can't make this into a property for C++Builder
|
||
|
IPv6 : TIdIPv6Address;
|
||
|
|
||
|
constructor Create; virtual;
|
||
|
class function MakeAddressObject(const AIP : String) : TIdIPAddress; overload;
|
||
|
class function MakeAddressObject(const AIP : String; const AIPVersion: TIdIPVersion) : TIdIPAddress; overload;
|
||
|
function CompareAddress(const AIP : String; var VErr : Boolean) : Integer;
|
||
|
function HToNBytes: TIdBytes;
|
||
|
|
||
|
property IPv4 : UInt32 read FIPv4 write FIPv4;
|
||
|
property IPv4AsString : String read GetIPv4AsString;
|
||
|
property IPv6AsString : String read GetIPv6AsString;
|
||
|
property AddrType : TIdIPVersion read FAddrType write FAddrType;
|
||
|
property IPAsString : String read GetIPAddress;
|
||
|
end;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
IdStack, SysUtils;
|
||
|
|
||
|
//IPv4 address conversion
|
||
|
//Much of this is based on http://www.pc-help.org/obscure.htm
|
||
|
|
||
|
function CompareUInt16(const AWord1, AWord2 : UInt16) : Integer;
|
||
|
{$IFDEF USE_INLINE}inline;{$ENDIF}
|
||
|
{
|
||
|
AWord1 > AWord2 > 0
|
||
|
AWord1 < AWord2 < 0
|
||
|
AWord1 = AWord2 = 0
|
||
|
}
|
||
|
begin
|
||
|
if AWord1 > AWord2 then begin
|
||
|
Result := 1;
|
||
|
end else if AWord1 < AWord2 then begin
|
||
|
Result := -1;
|
||
|
end else begin
|
||
|
Result := 0;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function CompareUInt32(const ACard1, ACard2 : UInt32) : Integer;
|
||
|
{$IFDEF USE_INLINE}inline;{$ENDIF}
|
||
|
{
|
||
|
ACard1 > ACard2 > 0
|
||
|
ACard1 < ACard2 < 0
|
||
|
ACard1 = ACard2 = 0
|
||
|
}
|
||
|
begin
|
||
|
if ACard1 > ACard2 then begin
|
||
|
Result := 1;
|
||
|
end else if ACard1 < ACard2 then begin
|
||
|
Result := -1;
|
||
|
end else begin
|
||
|
Result := 0;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ TIdIPAddress }
|
||
|
|
||
|
function TIdIPAddress.CompareAddress(const AIP: String; var VErr: Boolean): Integer;
|
||
|
var
|
||
|
LIP2 : TIdIPAddress;
|
||
|
i : Integer;
|
||
|
{
|
||
|
Note that the IP address in the object is S1.
|
||
|
S1 > S2 > 0
|
||
|
S1 < S2 < 0
|
||
|
S1 = S2 = 0
|
||
|
}
|
||
|
begin
|
||
|
Result := 0;
|
||
|
//LIP2 may be nil if the IP address is invalid
|
||
|
LIP2 := MakeAddressObject(AIP);
|
||
|
VErr := not Assigned(LIP2);
|
||
|
if not VErr then begin
|
||
|
try
|
||
|
// we can't compare an IPv4 address with an IPv6 address
|
||
|
VErr := FAddrType <> LIP2.FAddrType;
|
||
|
if not VErr then begin
|
||
|
if FAddrType = Id_IPv4 then begin
|
||
|
Result := CompareUInt32(FIPv4, LIP2.FIPv4);
|
||
|
end else begin
|
||
|
for I := 0 to 7 do begin
|
||
|
Result := CompareUInt16(IPv6[i], LIP2.IPv6[i]);
|
||
|
if Result <> 0 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
FreeAndNil(LIP2);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
constructor TIdIPAddress.Create;
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FAddrType := Id_IPv4;
|
||
|
FIPv4 := 0; //'0.0.0.0'
|
||
|
end;
|
||
|
|
||
|
function TIdIPAddress.HToNBytes: TIdBytes;
|
||
|
var
|
||
|
I : Integer;
|
||
|
begin
|
||
|
if FAddrType = Id_IPv4 then begin
|
||
|
Result := ToBytes(GStack.HostToNetwork(FIPv4));
|
||
|
end else begin
|
||
|
SetLength(Result, 16);
|
||
|
for I := 0 to 7 do begin
|
||
|
CopyTIdUInt16(GStack.HostToNetwork(IPv6[i]), Result, 2*I);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdIPAddress.GetIPAddress: String;
|
||
|
begin
|
||
|
if FAddrType = Id_IPv4 then begin
|
||
|
Result := GetIPv4AsString;
|
||
|
end else begin
|
||
|
Result := GetIPv6AsString;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdIPAddress.GetIPv4AsString: String;
|
||
|
begin
|
||
|
if FAddrType = Id_IPv4 then begin
|
||
|
Result := IntToStr((FIPv4 shr 24) and $FF) + '.';
|
||
|
Result := Result + IntToStr((FIPv4 shr 16) and $FF) + '.';
|
||
|
Result := Result + IntToStr((FIPv4 shr 8) and $FF) + '.';
|
||
|
Result := Result + IntToStr(FIPv4 and $FF);
|
||
|
end else begin
|
||
|
Result := '';
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdIPAddress.GetIPv6AsString: String;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if FAddrType = Id_IPv6 then begin
|
||
|
Result := IntToHex(IPv6[0], 4);
|
||
|
for i := 1 to 7 do begin
|
||
|
Result := Result + ':' + IntToHex(IPv6[i], 4);
|
||
|
end;
|
||
|
end else begin
|
||
|
Result := '';
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
class function TIdIPAddress.MakeAddressObject(const AIP: String): TIdIPAddress;
|
||
|
var
|
||
|
LErr : Boolean;
|
||
|
begin
|
||
|
Result := TIdIPAddress.Create;
|
||
|
try
|
||
|
IPv6ToIdIPv6Address(AIP, Result.IPv6, LErr);
|
||
|
if not LErr then begin
|
||
|
Result.FAddrType := Id_IPv6;
|
||
|
Exit;
|
||
|
end;
|
||
|
Result.FIPv4 := IPv4ToUInt32(AIP, LErr);
|
||
|
if not LErr then begin
|
||
|
Result.FAddrType := Id_IPv4;
|
||
|
Exit;
|
||
|
end;
|
||
|
//this is not a valid IP address
|
||
|
FreeAndNil(Result);
|
||
|
except
|
||
|
FreeAndNil(Result);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
class function TIdIPAddress.MakeAddressObject(const AIP: String; const AIPVersion: TIdIPVersion): TIdIPAddress;
|
||
|
var
|
||
|
LErr : Boolean;
|
||
|
begin
|
||
|
Result := TIdIPAddress.Create;
|
||
|
try
|
||
|
case AIPVersion of
|
||
|
Id_IPV4:
|
||
|
begin
|
||
|
Result.FIPv4 := IPv4ToUInt32(AIP, LErr);
|
||
|
if not LErr then begin
|
||
|
Result.FAddrType := Id_IPv4;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Id_IPv6:
|
||
|
begin
|
||
|
IPv6ToIdIPv6Address(AIP, Result.IPv6, LErr);
|
||
|
if not LErr then begin
|
||
|
Result.FAddrType := Id_IPv6;
|
||
|
Exit;
|
||
|
end
|
||
|
end;
|
||
|
end;
|
||
|
//this is not a valid IP address
|
||
|
FreeAndNil(Result);
|
||
|
except
|
||
|
FreeAndNil(Result);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end.
|