/indy/IdIPAddress.pas
Pascal | 293 lines | 183 code | 22 blank | 88 comment | 28 complexity | c1f2d91dda71fdacd93ce5fd9509c8e4 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
- {
- $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 : Cardinal;
- 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 : Cardinal 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 CompareWord(const AWord1, AWord2 : Word) : 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 CompareCardinal(const ACard1, ACard2 : Cardinal) : 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 := CompareCardinal(FIPv4, LIP2.FIPv4);
- end else begin
- for I := 0 to 7 do begin
- Result := CompareWord(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
- CopyTIdWord(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 := IPv4ToDWord(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 := IPv4ToDWord(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.