Delphi 中的 IP 地址字符串例程?

问题描述 投票:0回答:3

我正在寻找一种在 Delphi 中验证和操作 IP 地址的方法。它应该能够做的一些事情是......

  • 验证字符串是否为有效的 IP 地址
  • 验证字符串是否是有效的子网掩码
  • 验证 IP 地址是否在给定子网内
  • 用于存储 IP 地址的某种类型(记录或字符串或其他)
  • IP 地址类型的基本转换,例如
    String
    Array[0..3] of Byte
  • 任何其他可以使 IP 操作更容易的 IP 地址例程

基本原因是,我想在继续重新发明它们之前看看这些东西是否已经存在。

string delphi delphi-7 ip-address
3个回答
11
投票

我还曾经编写过一个IPv4 和 IPv6 转换单元,其中包括针对这两种类型的 IP 地址的自定义变体类型。 这个答案展示了其功能的一些示例。最初,它的设计目的是在某些滑块控件1)上按比例可视化各种类型的值。当时的要求是默认的现有库是不够的,但我同意这里的评论,你可能会得到印地(10!)或类似的帮助。

用该单元的一些代码片段回答您的问题列表:

  • Q4:IP 类型的存储类型:

      const
        IPv4BitSize = SizeOf(Byte) * 4 * 8;
        IPv6BitSize = SizeOf(Word) * 8 * 8;
    
      type
        T4 = 0..3;
        T8 = 0..7;
        TIPv4ByteArray = array[T4] of Byte;
        TIPv6WordArray = array[T8] of Word;
    
        TIPv4 = packed record
          case Integer of
            0: (D, C, B, A: Byte);
            1: (Groups: TIPv4ByteArray);
            2: (Value: Cardinal);
        end;
    
        TIPv6 = packed record
          case Integer of
            0: (H, G, F, E, D, C, B, A: Word);
            1: (Groups: TIPv6WordArray);
        end;
    
  • Q5:将 IP 地址字符串转换为这些记录或数组类型:

      function StrToIPv4(const S: String): TIPv4;
      var
        SIP: String;
        Start: Integer;
        I: T4;
        Index: Integer;
        Count: Integer;
        SGroup: String;
        G: Integer;
      begin
        SIP := S + '.';
        Start := 1;
        for I := High(T4) downto Low(T4) do
        begin
          Index := PosEx('.', SIP, Start);
          if Index = 0 then
            IPv4ErrorFmt(SInvalidIPv4Value, S);
          Count := Index - Start + 1;
          SGroup := Copy(SIP, Start, Count - 1);
          if TryStrToInt(SGroup, G) and (G >= Low(Word)) and (G <= High(Word)) then
              Result.Groups[I] := G
            else
              Result.Groups[I] := 0;
          Inc(Start, Count);
        end;
      end;
    
      function StrToIPv6(const S: String): TIPv6;
      { Valid examples for S:
        2001:0db8:85a3:0000:0000:8a2e:0370:7334
        2001:db8:85a3:0:0:8a2e:370:7334
        2001:db8:85a3::8a2e:370:7334
        ::8a2e:370:7334
        2001:db8:85a3::
        ::1
        ::
        ::ffff:c000:280
        ::ffff:192.0.2.128 }
      var
        ZeroPos: Integer;
        DotPos: Integer;
        SIP: String;
        Start: Integer;
        Index: Integer;
        Count: Integer;
        SGroup: String;
        G: Integer;
    
        procedure NormalNotation;
        var
          I: T8;
        begin
          SIP := S + ':';
          Start := 1;
          for I := High(T8) downto Low(T8) do
          begin
            Index := PosEx(':', SIP, Start);
            if Index = 0 then
              IPv6ErrorFmt(SInvalidIPv6Value, S);
            Count := Index - Start + 1;
            SGroup := '$' + Copy(SIP, Start, Count - 1);
            if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
              IPv6ErrorFmt(SInvalidIPv6Value, S);
            Result.Groups[I] := G;
            Inc(Start, Count);
          end;
        end;
    
        procedure CompressedNotation;
        var
          I: T8;
          A: array of Word;
        begin
          SIP := S + ':';
          Start := 1;
          I := High(T8);
          while Start < ZeroPos do
          begin
            Index := PosEx(':', SIP, Start);
            if Index = 0 then
              IPv6ErrorFmt(SInvalidIPv6Value, S);
            Count := Index - Start + 1;
            SGroup := '$' + Copy(SIP, Start, Count - 1);
            if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
              IPv6ErrorFmt(SInvalidIPv6Value, S);
            Result.Groups[I] := G;
            Inc(Start, Count);
            Dec(I);
          end;
          FillChar(Result.H, (I + 1) * SizeOf(Word), 0);
          if ZeroPos < (Length(S) - 1) then
          begin
            SetLength(A, I + 1);
            Start := ZeroPos + 2;
            repeat
              Index := PosEx(':', SIP, Start);
              if Index > 0 then
              begin
                Count := Index - Start + 1;
                SGroup := '$' + Copy(SIP, Start, Count - 1);
                if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
                  IPv6ErrorFmt(SInvalidIPv6Value, S);
                A[I] := G;
                Inc(Start, Count);
                Dec(I);
              end;
            until Index = 0;
            Inc(I);
            Count := Length(A) - I;
            Move(A[I], Result.H, Count * SizeOf(Word));
          end;
        end;
    
        procedure DottedQuadNotation;
        var
          I: T4;
        begin
          if UpperCase(Copy(S, ZeroPos + 2, 4)) <> 'FFFF' then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          FillChar(Result.E, 5 * SizeOf(Word), 0);
          Result.F := $FFFF;
          SIP := S + '.';
          Start := ZeroPos + 7;
          for I := Low(T4) to High(T4) do
          begin
            Index := PosEx('.', SIP, Start);
            if Index = 0 then
              IPv6ErrorFmt(SInvalidIPv6Value, S);
            Count := Index - Start + 1;
            SGroup := Copy(SIP, Start, Count - 1);
            if not TryStrToInt(SGroup, G) or (G > High(Byte)) or (G < 0) then
              IPv6ErrorFmt(SInvalidIPv6Value, S);
            case I of
              0: Result.G := G shl 8;
              1: Inc(Result.G, G);
              2: Result.H := G shl 8;
              3: Inc(Result.H, G);
            end;
            Inc(Start, Count);
          end;
        end;
    
      begin
        ZeroPos := Pos('::', S);
        if ZeroPos = 0 then
          NormalNotation
        else
        begin
          DotPos := Pos('.', S);
          if DotPos = 0 then
            CompressedNotation
          else
            DottedQuadNotation;
        end;
      end;
    

对于 Q1 到 Q3,你必须自己导出一些例程,但这应该没有任何问题。

1) 对于那些感兴趣的人来说,这个滑块控件这个主题作为本单元的启动。


4
投票

我已经编写了您需要的所有功能,但恐怕我无法分享代码。

但是,Synapse库在synaip单元中包含相当多的函数。例如

function IsIP(const Value: string): Boolean;
function IsIP6(const Value: string): Boolean;
function IPToID(Host: string): Ansistring;
function StrToIp6(value: string): TIp6Bytes;
function Ip6ToStr(value: TIp6Bytes): string;
function StrToIp(value: string): integer;
function IpToStr(value: integer): string;
function ReverseIP(Value: AnsiString): AnsiString;
function ReverseIP6(Value: AnsiString): AnsiString;

几年前我尝试这些功能时,IPv6 功能有点错误,尤其是在处理压缩的 IPv6 地址时。

如果你想自己动手,这里有一些建议:

  • 操作 IPv4 地址相当简单,因为它们仅包含 可以以标准整数类型存储的 32 位。 IPv6 地址更难,因为它们需要 128 位,并且没有本机类型 那么多位。
  • 在尝试操作 IP 地址之前,首先将其转换为 整数(当然仅限 IPv4,IPv6 将需要不同的存储 方法)。为此,请使用“.”分隔 IP 地址。作为分隔符。 检查每个单独的值仅包含数字且介于 0 之间 和 255 然后使用这些值生成最终整数。
  • 将 IP 地址转换为整数后,您可以 随心所欲地操纵它。例如,给定一个 IP 地址和 子网掩码可以找到IP地址所属的子网 例如IPtoInt(IPAddress) AND NOT(IPToInt(SubnetMask)) = 的整数 子网。现在,您可以将整数 IP 地址转换为整数 子网以查看 IP 是否属于该子网。
  • 最后,将整数 IP 地址转换回字符串。

如果您有任何具体问题,我也可以尝试回答。


0
投票
    {*************************************************************************** }
    {
    { Outils pour les adresses IPv6 et IPv4 (2024)
    {
    { *************************************************************************** }
    unit MyIPUtils;


    interface

    uses
      Types;

    type

      TIPVersion = (_IPv4, _IPv6);

      TIPData = record
        case Integer of
          0 : (B : packed array[0..3] of Byte);  // Lo - > Hi
          1 : (W : packed array[0..7] of Word);
          2 : (Value: Cardinal); // IPv4
      end;


      TIP = record
      private
        FIPVersion: TIPVersion;
        Data : TIPData;
        FErr : Word;
        function Get(Index: Integer): Word;
        procedure Put(Index: Integer; Value: Word);
      public
        class operator Implicit(const a : UInt64) : TIP;
        class operator Implicit(const a : String) : TIP;
        class operator Implicit(const a : TIP) : String;
        class operator Explicit(const a : TIP) : String;
        class operator Equal(const a, b: TIP): Boolean;
        class operator NotEqual(const a, b: TIP): Boolean;
        class operator LogicalNot(const a: TIP): TIP;
        class operator GreaterThan(const a, b: TIP): Boolean;
        class operator GreaterThanOrEqual(const a, b: TIP): Boolean;
        class operator LessThan(const a, b: TIP): Boolean;
        class operator LessThanOrEqual(const a, b: TIP): Boolean;
        class operator LeftShift(a: TIP; b: LongWord): TIP;
        class operator RightShift(a: TIP; b: LongWord): TIP;
        class operator LogicalAnd(a, b: TIP): TIP;
        class operator LogicalOr(a, b: TIP): TIP;
        class operator LogicalXor(a, b: TIP): TIP;
        class operator BitwiseAnd(a, b: TIP): TIP;
        class operator BitwiseOr(a, b: TIP): TIP;
        class operator BitwiseXor(a, b: TIP): TIP;

        procedure Clear(aErr: Word = 0);
        procedure CheckMask(BitsCount: Word);
        procedure SetIPVersion(IPv: TIPVersion);
        property Err: Word read FErr;
        property Items[Index: Integer]: Word read Get write Put; default;
        property IPVersion: TIPVersion read FIPVersion write FIPVersion;
      end;

    function MakeMask(BitsCount: Word; IPVersion: TIPVersion): TIP; overload;
    function IsBetween(const Lo, Hi, Val: TIP): Boolean;
    function CmpVersion(const a, b: TIP): TValueRelationship;
    function IPCmp(a, b: TIP): TValueRelationship;
    function IsIPCIDR(AddrStr, MaskStr: WideString): Boolean;
    function IsValidIP(const IP: TIP): Boolean;
    function StrToIPv4(AIP: String): TIP;
    function StrToIPv6(AIP: String): TIP;
    function IpV4StrToInt(MyIP: PAnsiChar): LongWord;




    implementation

    uses
      SysUtils,
      MyWideStr;

    const
      LenIPs  : array[TIPVersion] of integer = (4, 8);  // 4 octets  ou 8 word
      SeparIP : array[TIPVersion] of Char = ('.', ':');

    resourcestring
      SInvalidIPv4Value = 'IPV4 conversion not possible.';
      SInvalidIPv6Value = 'IPV6 conversion not possible.';

    type
      EIPError = class(Exception);


    procedure IPErrorFmt(ResString: string; const Arg: String); local;
    begin
      raise EIPError.CreateFmt(ResString, [Arg]);
    end;

    function CmpWord(a, b: Word): TValueRelationship;
    begin
      if (a <= b) then
        if (a < b) then Result := LessThanValue
        else Result := EqualsValue
      else Result := GreaterThanValue;
    end;

    function CmpVersion(const a, b: TIP): TValueRelationship;
    begin
      if (a.IPVersion <= b.IPVersion) then
        if (a.IPVersion < b.IPVersion) then Result := LessThanValue
        else Result := EqualsValue
      else Result := GreaterThanValue;
    end;


    function IPCmp(a, b: TIP): TValueRelationship;
    var
      i : integer;
    begin
      if (a.IPVersion <> b.IPVersion) then begin
        a.IPVersion := _IPv6;
        b.IPVersion := _IPv6;
      end;
        for i := LenIPs[a.IPVersion] - 1 downto 0 do begin
          Result := CmpWord(a[i], b[i]);
          if (Result <> EqualsValue) then   // On ne compare pas tout
            Break;
        end;
    end;


    function IsBetween(const Lo, Hi, Val: TIP): Boolean;
    begin
      Result := (Lo <= Val) and (Val <= Hi);
    end;


    // https://www.it-connect.fr/adresses-ipv4-et-le-calcul-des-masques-de-sous-reseaux/
    // https://www.formip.com/pages/blog/type-dadresse-ipv6-et-eui-64
    function IsIPCIDR(AddrStr, MaskStr: WideString): Boolean;
    var
      LeftStr, S : String;
      BitsCount: Word;
      Err: Integer;
      Addr,
      Left,
      Mask : TIP;
    begin
      // L'adresse est de ce style 192.168.5.3/24
      S := MaskStr; BitsCount := 0; Err := 0;
      LeftStr := Fetch(S, '/');
      if (Length(S) > 0)then begin
        Val(S, BitsCount, Err);  // Si erreur de syntaxe dans le Masque
        // L'erreur de bitcount sera vérifié dans MakeMask
      end;
      Addr := AddrStr;
      Left := LeftStr;
      if (BitsCount = 0) then  // Pas de masque
        Result := (Addr = Left) and (Err = 0)
      else begin
        Mask := MakeMask(BitsCount, Left.IPVersion);  // IPv4 ou IPv6
        Result := IsBetween(Left and Mask, Left or not Mask, Addr) and (Mask.FErr = 0) and (Err = 0);
      end;
    end;


    procedure TIP.Clear(aErr: Word = 0);
    begin
      FErr := aErr;
      FillChar(Data.W, SizeOf(Data.W), 0);
    end;


    function IsValidIP(const IP: TIP): Boolean;
    begin
      Result := IP.FErr = 0;
    end;


    function TIP.Get(Index: Integer): Word;
    begin
      case IPVersion of
        _IPv4 : Result := Data.B[Index];
        _IPv6 : Result := Data.W[Index];
      end;
    end;

    procedure TIP.Put(Index: Integer; Value: Word);
    begin
      case IPVersion of
        _IPv4 : Data.B[Index] := Value;
        _IPv6 : Data.W[Index] := Value;
      end;
    end;

    { // Version poids faibles (pas la norme)
    function MakeMask(a: Word; IPVersion: TIPVersion): TIP;
    var
      b : TIP;
      i : integer;
    begin
      b.IPVersion := IPVersion;
      Clear(b); Result := b;
      for i := 0 to a  - 1 do
        Result := (Result shl 1) or 1;
    end;
    }

    {
    //  https://www.it-connect.fr/adresses-ipv4-et-le-calcul-des-masques-de-sous-reseaux/
        Le masque est sur les poids. Exemple IPV4

        Classe A : 255.0.0.0 soit /8
        Classe B : 255.255.0.0 soit /16
        Classe C : 255.255.255.0 soit /24
    }
    function MakeMask(BitsCount: Word; IPVersion: TIPVersion): TIP;
    var
      b : TIP;
      i, LenBits : integer;
    begin
      b.Clear;
      b.IPVersion := IPVersion;
      Result := b;  Result.CheckMask(BitsCount);
      i := LenIPs[IPVersion] -1;
      LenBits := LenIPs[IPVersion] * 2; // Nombre de bits par élément
      while (BitsCount >= LenBits) and (i >= 0) do
      begin
        Result[i] := Word(-1);  // Par paquet de 8 ou 16 bits
        Dec(i);
        Dec(BitsCount, LenBits);
      end;
      if (BitsCount > 0) and (i >= 0) then  // Le reste
      begin
        Result[i] := Word(-1) shl (LenBits-BitsCount);  // Nombre de 0 en poids faible
      end;
    end;


    function MaxVersion(const a, b: TIP): TIPVersion;
    begin
      if a.IPVersion > b.IPVersion then
        Result := a.IPVersion
      else
        Result := b.IPVersion;
    end;


    procedure TIP.CheckMask(BitsCount: Word);
    begin
      case IPVersion of
        _IPv4 : if (BitsCount > SizeOf(Data.B) * 8) then Inc(FErr);   // Dépasse le nombre de bits total
        _IPv6 : if (BitsCount > SizeOf(Data.W) * 8) then Inc(FErr);
      end;
    end;


    procedure TIP.SetIPVersion(IPv: TIPVersion);
    begin
      if (IPv <> IPVersion) then begin
        case IPv of
          _IPv4: FillChar(Data.W[2], 6 * SizeOf(Word), 0);
          _IPv6: begin Data.W[2] := $FFFF; FillChar(Data.W[3], 5 * SizeOf(Word), 0); end;
        end;
        FIPVersion := IPv;
      end;
    end;


    function StrToIPv4(AIP: String): TIP;
    var
      i: Integer;
      S : String;
      W : Integer;
      BitsCount: Word;
      Err: Integer;
    begin
      Result.Clear;
      Result.IPVersion := _IPv4;
      S := AIP;
      AIP := Fetch(S, '/');   // Découpe le masque
      if (Length(S) > 0)then begin
        Val(S, BitsCount, Err);
        if (Err > 0) or (BitsCount > (LenIPs[_IPv4] * 8)) then Inc(Result.FErr);  // Erreur dans le Masque Syntaxe ou trop grand
      end;
      for i := LenIPs[_IPv4] - 1 downto 0 do begin
        S := Fetch(AIP, '.');
        if (S = '') then Inc(Result.FErr)  // Pas de veleur
        else begin
          Val(S, W, Err);
          if (Err <> 0) or (W > 255) or (W < 0) then
            Inc(Result.FErr)  // Valeur erronnée
          else
            Result[i] := W;
        end;
      end;
      if (Length(AIP) > 0) or (i >= 0) then Inc(Result.FErr);  // Syntaxe incorrecte, Il reste des truc dans la chaine
    end;


    function StrToIPv6(AIP: String): TIP;
    var
      S : String;
      A : array of Word;
      i, Count, ZeroPos : integer;
      L : Integer;
      Err : Integer;
      BitsCount : Word;
      IPv4  : Boolean;
    begin
      Result.Clear;
      Result.IPVersion := _IPv6;
      S := AIP;  AIP := Fetch(S, '/');   // Découpe le masque
      if (Length(S) > 0)then begin
        Val(S, BitsCount, Err);
        if (Err > 0) or (BitsCount > (LenIPs[_IPv6] * 16)) then Inc(Result.FErr);  // Erreur dans le Masque Syntaxe ou trop grand
      end;
      i := LenIPs[_IPv6];  ZeroPos := -1;
      if (AIP[1] = ':') then Delete(AIP, 1, 1);     // '::'  Deux à la suite
      while (Length(AIP) > 0) do begin
        IPv4 := FindFirstWChar(PWideChar(AIP), ':.') = '.';
        if IPv4 then Break;

        S := Fetch(AIP, ':');
        if (S = '') then // '::'
          if (ZeroPos = -1) then
            ZeroPos := i
          else
            ZeroPos := -1  // '::' plusieurs fois signifie une Erreur
        else begin
          Dec(i);
          if (i >= 0) then begin
            Val('$'+S, L, Err);
            if (Err <> 0) or (L > $FFFF) or (L < 0) then
              Inc(Result.FErr)   // Le nombre Hexa exprimé n'est pas syntaxiquement correct
            else
              Result[i] := L;
          end
          else
            Inc(Result.FErr) // Trop de block dans le numéro IP V6
        end;
      end;
      // i est le dernier remplis
      if (ZeroPos >= 0) and (i >= 0) then begin  // '::'
        Count := ZeroPos - i;    // Nombre déjà dans la partie droite (Lo)
        if IPv4 then L := 2 else L := 0;
        Move(Result.Data.W[i], Result.Data.W[L], Count * SizeOf(Word));
        FillChar(Result.Data.W[Count+L], (i-L) * SizeOf(Word), 0);
      end
      else // Si on passe en IPv4, il doit rester 2 word, sinon 0
        if IPv4 then
          if (i <> 2) then Inc(Result.FErr) else   // Pas de place pour l'IPV4 finale
        else
          if (i <> 0) then Inc(Result.FErr);       // On a pas rempli les 8 word
      if IPv4 then begin
        Result := StrToIPv4(AIP) or Result;
      end;
    end;


    class operator TIP.Implicit(const a : UInt64) : TIP;
    begin
      Result.Clear;
      Move(a, Result.Data.W, SizeOf(a));
      Result.IPVersion := _IPv6;
    end;


    class operator TIP.Implicit(const a : String) : TIP;
    begin
      if (Pos(':', a) > 0) then
        Result := StrToIPv6(a)
      else
        Result := StrToIPv4(a);
    end;


    class operator TIP.Implicit(const a : TIP) : String;
    var
      i : Integer;
    begin
      Result := '';;
      for i := LenIPs[a.IPVersion] - 1 downto 0 do begin
        if (Length(Result) > 0) then
          Result := Result + SeparIP[a.IPVersion];
        case a.IPVersion of
          _IPv4: Result := Result + IntToStr(a[i]);
          _IPv6: Result := Result + IntToHex(a[i], 4);
        end;
      end;
    end;


    class operator TIP.Explicit(const a : TIP) : String;
    begin
      Result := a;  // -> Implicit
    end;


    class operator TIP.Equal(const a, b: TIP): Boolean;
    begin
      Result := IPCmp(a, b) = EqualsValue;
    end;


    class operator TIP.NotEqual(const a, b: TIP): Boolean;
    begin
      Result := IPCmp(a, b) <> EqualsValue;
    end;

    class operator TIP.GreaterThan(const a, b: TIP): Boolean;
    begin
      Result := IPCmp(a, b) = GreaterThanValue;
    end;

    class operator TIP.GreaterThanOrEqual(const a, b: TIP): Boolean;
    begin
      Result := IPCmp(a, b) >= EqualsValue;
    end;

    class operator TIP.LessThan(const a, b: TIP): Boolean;
    begin
      Result := IPCmp(a, b) = LessThanValue;
    end;

    class operator TIP.LessThanOrEqual(const a, b: TIP): Boolean;
    begin
      Result := IPCmp(a, b) <= EqualsValue;
    end;

    class operator TIP.LeftShift(a: TIP; b: LongWord): TIP;
    var
      i, d : integer;
      c : LongWord;
      e : Integer;
    begin
      Result.Clear(a.FErr);
      Result.IPVersion := a.IPVersion;
      if (b > 0) then begin
        e := LenIPs[a.IPVersion] * 2;
        repeat
          if (b >= e) then begin
            Result := a;
            d := b div e;
            for i:= LenIPs[a.IPVersion] - 1 - d downto 0 do
              Result[i + d] := Result[i];
            for i:= 0 to d-1 do
              Result[i] := 0;
            Dec(b, d * e);
            a := Result;
          end
          else begin
            c := 0;
            for i:= 0 to LenIPs[a.IPVersion] - 1 do begin
              c := (LongWord(a[i]) shl b) or c;
              Result[i] := c;
              c := c shr e;
            end;
            if (c > 0) then
              Result[i] := c;
            b := 0;
          end;
        until (b = 0);
      end
      else
        Result := a;
    end;

    class operator TIP.RightShift(a: TIP; b: LongWord): TIP;
    var
      i : integer;
      c : LongWord;
      d : LongWord;
      e : Integer;
    begin
      Result.Clear(a.FErr);
      Result.IPVersion := a.IPVersion;
      if (b > 0) then begin
        e := LenIPs[a.IPVersion] * 2;  // Un élément = 8 ou 16 bits
        repeat
          if (b >= e) then begin
            Result := a;
            d := b div e;   // Nombre d'éléments  0..N-1
            if (d < (LenIPs[a.IPVersion])) then begin
              for i:= d to LenIPs[a.IPVersion] - 1 do begin
                Result[i-d] := Result[i];
                Result[i] := 0;
              end;
            end
            else begin
              Result.Clear;
              exit;
            end;
            Dec(b, d * e);
            a := Result;
          end
          else begin
            c := 0;
            for i:= LenIPs[a.IPVersion] - 1 downto 0 do begin
              d := a[i];
              Result[i] := (d shr b) or c;
              c := d shl (e-b);  // Les bits à reporter
            end;
            b := 0;
          end;
        until (b = 0);
      end
      else
        Result := a;
    end;

    class operator TIP.LogicalNot(const a: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr;
      Result.IPVersion := a.IPVersion;
      for i := 0 to LenIPs[Result.IPVersion] - 1 do
        Result[i] := not a[i];
    end;

    class operator TIP.LogicalAnd(a, b: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr + b.FErr;
      Result.IPVersion := MaxVersion(a, b);
      for i := 0 to LenIPs[_IPv6] - 1 do
        Result.Data.W[i] := a.Data.W[i] and b.Data.W[i];
    end;

    class operator TIP.LogicalOr(a, b: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr + b.FErr;
      Result.IPVersion := MaxVersion(a, b);
      for i := 0 to LenIPs[_IPv6] - 1 do
        Result.Data.W[i] := a.Data.W[i] or b.Data.W[i];
    end;

    class operator TIP.LogicalXor(a, b: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr + b.FErr;
      Result.IPVersion := MaxVersion(a, b);
      for i := 0 to LenIPs[_IPv6] - 1 do
        Result.Data.W[i] := a.Data.W[i] xor b.Data.W[i];
    end;

    class operator TIP.BitwiseAnd(a, b: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr + b.FErr;
      Result.IPVersion := MaxVersion(a, b);
      for i := 0 to LenIPs[_IPv6] - 1 do
        Result.Data.W[i] := a.Data.W[i] and b.Data.W[i];
    end;

    class operator TIP.BitwiseOr(a, b: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr + b.FErr;
      Result.IPVersion := MaxVersion(a, b);
      for i := 0 to LenIPs[_IPv6] - 1 do
        Result.Data.W[i] := a.Data.W[i] or b.Data.W[i];
    end;

    class operator TIP.BitwiseXor(a, b: TIP): TIP;
    var
      i : integer;
    begin
      Result.FErr := a.FErr + b.FErr;
      Result.IPVersion := MaxVersion(a, b);
      for i := 0 to LenIPs[_IPv6] - 1 do
        Result.Data.W[i] := a.Data.W[i] xor b.Data.W[i];
    end;

    function IpV4StrToInt(MyIP: PAnsiChar): LongWord;
    var
      IP : TIP;
    begin
      IP := MyIP;
      Result := IP.Data.Value;
    end;




    function Tests: Boolean;
    var
      a, b, c : TIP;
      S : String;
      procedure TestA(St: String);  begin a := St; if a.Err = 0 then Beep; end;
      procedure TestB(St: String);  begin a := St; if a.Err > 0 then Beep; end;
    begin
      a := 1;
      b := a shl 127;
      a := b shr 10;
      if b > a then ;
      if b >= a then ;
      if a < b then ;
      if a <= b then ;
      if a <> b then ;
      c := not b;
      c := a and b;
      c := a or b;
      c := a xor b;
      a := '192.168.1.3';  b := MakeMask(24, _IPv4);  c := '192.168.1.5';
      Result := IsBetween(c and b, c or (not b), a);
      a := '192.168.1.3';  b := MakeMask(96+24, _IPv6);  c := '192.168.1.5';
      a.SetIPVersion(_IPv6);
      S := b;  // Implicit
      S := String(b) + ' ' + String(a);  // Explicit
      Result := IsBetween(c and b, c or (not b), a);
      { Erreurs }
      TestA('2001:0db8:85a3:1234:4567:0000:0000:8a2e:0370');
      TestA('2001:0db8:85a3::1234:4567:0000:0000:8a2e:0370');
      TestA('2001:0db8:85a3::1234:4567:0000:0000:8a2e:0370:192.168.1.8');
      TestA('2001:0db8:85k3:0000:0000:8a2e:0370:7334');
      TestA('2001:0db8:85a3:0000:0000:8a2e:0370');  // Pas assez de nombre
      TestA('2001:192.168.1.1:0000:0000:8a2e:0370');
      TestA('2001:0db8:192.0.2.128');
      TestA('2001:0db8:192.0.2.');
      TestA('2001:db8::85a3::ac1f:8001');
      Result := IsIPCIDR('192.168.50.5', '192.168.50.0/264');
      Result := IsIPCIDR('192.168.50.5', '192.168.50.0/64');
      Result := IsIPCIDR('192.168.50.5', '192.168.50.0/4a');
      TestA('2001:0db8');
      TestA('192.168b.1.5.24');
      TestA('192.168.1b.5.24');
      TestA('192.168.1.5.24');
      TestA('192.168.1.5/2b');
      TestA('192.168.1.5\24');
      TestA('192.168.1/24');
      TestA('192.168.1b.24');
      TestA('192.168.24');
      TestA('2001');

      { Correct}
      TestB('::192.168.1.4');
      TestB('2001::192.168.1.4');
      TestB('2001::0db8/94');
      TestB('::8888:192.168.1.4/95');
      TestB('2001:db8:85a3::8a2e:370:7334');
      TestB('::8a2e:370:7334');
      TestB('::1');
      TestB('::');
      TestB('::ffff:c000:280');
      TestB('::ffff:192.0.2.128');
      TestB('2001:db8:85a3::');
      TestB('2001:db8:85a3::/24');
      TestB('2001:0db8:85a3:0000:0000::0370:7334');
      TestB('2001:0db8:85a3:0000:0000:8a2e:0370:7334');
      TestB('0:0:0:0:0:ffff:192.168.1.3');
      TestB('2001:db8:85a3:0:0:8a2e:370:7334');
      TestB('ffff::');
      TestB('0:0:0:0:0:ffff:c0a8:103');
      TestB('192.168.1.4/24');
      Result := IsIPCIDR('192.168.50.5', '192.168.50.5');
      Result := IsIPCIDR('192.168.50.5', '192.168.50.0/24');
      Result := IsIPCIDR('2001:db8:85a3::8a2e:370:4324', '2001:db8:85a3::8a2e:370:7334/65');
      TestB('::ffff/95');
      S := String(a);   // Explicit
      if S = '' then;
      a.IPVersion := _IPv4;
      S := String(a);
      if S = '' then;
    end;

    initialization
    begin
      Tests;
    end;




    end.
© www.soinside.com 2019 - 2024. All rights reserved.