Enable IPv6 listen address (ListenAddress6)
[mgsmtp.git] / Common.pas
index fadccc59f8b17f0ca294d84740c7af03e946d546..2280c2b5358f968ba6d8f0c5c070e445088be0d3 100644 (file)
@@ -26,7 +26,7 @@
 unit Common;
 
 interface
-uses Windows, SysUtils, DateUtils, Classes, INIFiles;
+uses Windows, SysUtils, DateUtils, Classes, INIFiles, RFCSMTP;
 
 type
 
@@ -73,10 +73,11 @@ type
       {FTimeCorrection: integer;}
       FTimeOffset: integer;
       FTimeOffsetStr: string;
-      FListenAddresses: TStrings;
+      FListenAddresses, FListenAddresses6: TStrings;
    public
       function GetVersionStr: string;
       property ListenAddresses: TStrings read FListenAddresses;
+      property ListenAddresses6: TStrings read FListenAddresses6;
       property Databytes: longint read FDatabytes;
       {property TimeCorrection: integer read FTimeCorrection;}
       property TimeOffset: integer read FTimeOffset;
@@ -165,6 +166,7 @@ type
    function IsPrintableString(S: string): boolean;
    function UnixTimeStamp(DateTime: TDateTime): TUnixTimeStamp;
    function CmdlineToStringArray: TStringArray;
+   procedure ParseIPv6Address(S: string; var Address: string; var Port: word);
    procedure SplitParameters(S: string; var FirstPrm, Remainder: string; Separator: char = #32);
 
    function ReadLineFromStream(Stream: TStream): string;
@@ -385,6 +387,54 @@ begin
    end;
 end;
 
+procedure ParseIPv6Address(S: string; var Address: string; var Port: word);
+{ IPv6 addresses can be supplied in the following formats:
+      [<IPv6 address>]:<port>    e.g.  [::1]:25
+  or
+      <hostname>:<port>          e.g.  mail.example.com:25 }
+var SPort: string; c: integer;
+begin
+   if S[1] = '[' then begin
+      { Guess format is "[<IPv6 address>]:<port>". }
+      c:= pos(']', S);
+      if c > 1 then begin
+         Address:= Copy(S, 2, c - 2);
+         if c = Length(S) then begin
+            { There is no port to extract. }
+            Port:= STANDARD_SMTP_PORT;
+         end
+         else begin
+            { The closing bracket should be followed by a colon. }
+            if S[c+1] = ':' then
+               { Extract port number. }
+               Port:= StrToIntDef(Copy(S, c+2, Length(S) - (c+1)), 0)
+            else
+               { Invalid format. }
+               Port:= 0;
+         end;
+      end
+      else begin
+         { Format is incorrect, return invalid data. }
+         Address:= '';
+         Port:= 0;
+      end;
+   end
+   else begin
+      { Guess format is "<hostname>:<port>". }
+      SplitParameters(S, Address, SPort, ':');
+      if (pos(':', Address) = 0) and (pos(':', SPort) = 0) then begin
+         { Format seems correct. }
+         if SPort = '' then Port:= STANDARD_SMTP_PORT
+         else Port:= StrToIntDef(SPort, 0);
+      end
+      else begin
+         { Format is incorrect, return invalid data. }
+         Address:= '';
+         Port:= 0;
+      end;
+   end;
+end;
+
 procedure SplitParameters(S: string; var FirstPrm, Remainder: string; Separator: char = #32);
 var i: integer;
 begin
@@ -483,6 +533,10 @@ begin
       portlist.Free;
    end;
 
+   FListenAddresses6:= TStringList.Create;
+   FListenAddresses6.Delimiter:= ',';
+   FListenAddresses6.DelimitedText:= Config.ReadString('Server', 'ListenAddress6', '');
+
    FDatabytes:=      Config.ReadInteger('Server', 'Databytes', 1024 * 1024 * 1024);
    FTimeOffset:=     Config.ReadInteger('Server', 'TimeOffset', Config.ReadInteger('Server', 'TimeCorrection', 0) * 100);
    FTimeOffsetStr:=  MakeTimeOffsetStr(FTimeOffset);