Search code examples
windowsip-addressinno-setuppascalscript

Basic IP validation within Inno Setup script


When I collect input from a user, how can I check to see if it's an IP address?


Solution

  • An IP Address (assuming you mean IPv4) is actually an integer, but it is usually written as four numbers separated by a .. Each of those numbers represent a byte value of the integer, so each of the numbers should be a number between 0 and 255 (incl).

    function CheckIP(Input: String): Cardinal;
    var
      IP: Cardinal;
      i : Integer;
      Part: Integer;
      PartValue: Cardinal;
      PartValid: Boolean;
    begin
      Part := 3;
      PartValue := 0;
      PartValid := False;
      IP := 0;
      { When a '.' is encountered, the previous part is processed. Force processing }
      { the last part by adding a '.' to the input. }
      Input := Input + '.';
    
      for i := 1 to Length(Input) do
      begin
    
        { Check next character }
        if Input[i] = '.' then
        begin
    
           if PartValue <= 255 then
           begin
             if PartValid then
             begin
               { A valid part is encountered. Put it in the result. }
               IP := IP or (PartValue shl (Part * 8));
               { Stop processing if this is the last '.' we put in ourselves. }
               if i = Length(Input) then
                 Break;
               { Else reset the temporary values. }
               PartValid := False;
               PartValue := 0;
               Dec(Part);
             end
             else
               RaiseException('Empty part');
           end
           else
             RaiseException('Part not within 0..255');
    
        end
        else if ((Input[i] >= '0') and (Input[i] <= '9')) then
        begin
    
          { A digit is found. Add it to the current part. }
          PartValue := PartValue * 10 + Cardinal((Ord(Input[i]) - Ord('0')));
          PartValid := True;
    
        end
        else
        begin
    
          { Any other character raises an exception }
          RaiseException('Invalid character');
    
        end;
    
        { If part < 0, we processed too many dots. }
        if Part < 0 then
          RaiseException('Too many dots');
    
      end;
    
      { Check if we found enough parts. }
      if Part > 0 then
        RaiseException('Address most consist of 4 numbers');
    
      { If Part is not valid after the loop, the input ended in a dot. }
      if not PartValid then
        RaiseException('IP cannot end in a dot');
    
      { Return the calculated IP address as a cardinal. }
      Result := IP;
    end;