{*********************************************************

 SlavaNap source code.

 Copyright 2001,2002 by SlavaNap development team
 Released under GNU General Public License

 Latest version is available at
 http://www.slavanap.org

**********************************************************

 Unit: Ips

 function to automatically replace some IPs

*********************************************************}
unit Ips;

interface

uses
  Windows, Classes2, SysUtils, Constants, STypes, BlckSock, SynSock, WinSock,
  Vars, Class_CmdExList, Class_Cmd2List;

function CheckIP(Socket: HSocket): Cardinal;
procedure LoadIPs;
procedure SaveIPs;

implementation

function CheckIP(Socket: HSocket): Cardinal;
var
  I, J, K: Integer;
  Ip, Localip: Cardinal;
  IpStr: string;
  List: TMyStringList;
  Item: PNapCmdEx;
begin
  Ip := TCPSocket_GetRemoteSin(Socket).Sin_Addr.S_Addr;
  Localip := TCPSocket_GetLocalSin(Socket).Sin_Addr.S_Addr;
  Result := Ip;
  if (LocalIp = Ip) and (DB_Ips_Local <> '') then
  begin // Local IP
    if DB_Ips_Local = '_server_' then
    begin
      List := TMyStringList.Create;
      ResolveNameToIp(ServerName_T, List);
      if List.Count > 0 then
        Result := Encode_Ip(List.Strings[0]);
      List.Free;
      Exit;
    end;
    J := 0;
    for I := 1 to Length(DB_Ips_Local) do
      if not (DB_Ips_Local[I] in ['0'..'9', '.']) then
        J := 1;
    if J = 0 then
    begin // Remote is IP
      Result := Encode_Ip(DB_Ips_Local);
      Exit;
    end;
    // Remote is host name
    List := TMyStringList.Create;
    ResolveNameToIp(DB_Ips_Local, List);
    if List.Count > 0 then
      Result := Encode_Ip(List.Strings[0]);
    List.Free;
    Exit;
  end;
  IpStr := Decode_Ip(Ip);
  for I := 0 to DB_Ips.Count - 1 do
  begin
    Item := DB_Ips.Items[I];
    case Item^.Id of
      IP_IP: if Item^.Cmd = IpStr then
        begin
          Result := Encode_Ip(Item^.Data);
          Exit;
        end;
      IP_RESOLVE: if Item^.Cmd = IpStr then
        begin
          List := TMyStringList.Create;
          ResolveNameToIp(Item^.Data, List);
          if List.Count > 0 then
            Result := Encode_Ip(List.Strings[0]);
          List.Free;
          Exit;
        end;
      IP_MASK: if MatchesMaskEx(IpStr, Item^.Cmd) then
        begin
          IpStr := Item^.Data;
          if IpStr = '_server_' then
            IpStr := ServerName_T;
          J := 0;
          for K := 1 to Length(IpStr) do
            if not (IpStr[K] in ['0'..'9', '.']) then
              J := 1;
          if J = 0 then
            Result := Encode_Ip(IpStr)
          else
          begin
            List := TMyStringList.Create;
            ResolveNameToIp(IpStr, List);
            if List.Count > 0 then
              Result := Encode_Ip(List.Strings[0]);
            List.Free;
          end;
        end;
    end;
  end;
end;

procedure CheckConsoleIP;
var
  List: TMyStringList;
  I, J: Integer;
begin
  if DB_Ips_Local = '' then Exit;
  if DB_Ips_Local = '_server_' then
  begin
    List := TMyStringList.Create;
    ResolveNameToIp(ServerName_T, List);
    if List.Count > 0 then
      Cons.Data.Ip := Encode_Ip(List.Strings[0]);
    List.Free;
    Exit;
  end;
  J := 0;
  for I := 1 to Length(DB_Ips_Local) do
    if not (DB_Ips_Local[I] in ['0'..'9', '.']) then
      J := 1;
  if J = 0 then
  begin // Remote is IP
    Cons.Data.Ip := Encode_Ip(DB_Ips_Local);
    Exit;
  end;
  // Remote is host name
  List := TMyStringList.Create;
  ResolveNameToIp(DB_Ips_Local, List);
  if List.Count > 0 then
    Cons.Data.Ip := Encode_Ip(List.Strings[0]);
  List.Free;
end;

procedure LoadIPs;
var
  Lst1, Lst2: TMyStringList;
  Str: string;
  I, J, K: Integer;
begin
  DB_Ips := TNapCmdExList.Create;
  DB_Ips_Local := '';
  if not FileExists(ApplicationDir + 'ips') then
  begin // Create new file
    DB_Ips_Local := '_server_';
    CheckConsoleIP;
    Exit;
  end;
  Lst1 := TMyStringList.Create;
  try
    Lst1.LoadFromFile(ApplicationDir + 'ips');
  except
    DB_Ips_Local := '_server_';
    Lst1.Free;
    CheckConsoleIP;
    Exit;
  end;
  Lst2 := TMyStringList.Create;
  for I := 0 to Lst1.Count - 1 do
  begin
    Str := Lst1.Strings[I];
    SplitString(Str, Lst2);
    if Lst2.Count = 2 then
      if Lst2.Strings[0] <> '#' then
      begin
        if Lst2.Strings[0] = '_local_' then
          DB_Ips_Local := Lst2.Strings[1]
        else if Pos('*', Lst2.Strings[0]) > 0 then
          DB_Ips.AddCmd(IP_MASK, Lst2.Strings[0], Lst2.Strings[1])
        else if Pos('?', Lst2.Strings[0]) > 0 then
          DB_Ips.AddCmd(IP_MASK, Lst2.Strings[0], Lst2.Strings[1])
        else
        begin
          K := IP_IP;
          for J := 1 to Length(Lst2.Strings[1]) do
            if not (Lst2.Strings[1][J] in ['0'..'9', '.']) then
              K := IP_RESOLVE;
          DB_Ips.AddCmd(K, Lst2.Strings[0], Lst2.Strings[1]);
        end;
      end;
  end;
  Lst2.Free;
  Lst1.Free;
  CheckConsoleIP;
end;

procedure SaveIPs;
var
  Lst: TMyStringList;
  I: Integer;
  Item: PNapCmdEx;
begin
  Lst := TMyStringList.Create;
  Lst.Add('# このファイルには、次の形式に変換されるIPの一覧が書いてあります');
  Lst.Add('# 形式:');
  Lst.Add('#  User_Ip Replace_Ip');
  Lst.Add('#  "_local_" はこのコンピュータに属するすべてのIpを意味します。 ' +
    '(ユーザーとサーバーが同じコンピューター上にいる)');
  Lst.Add('#  "_server_" はこのサーバーのホスト名のエイリアスです。 ' +
    '(ホスト名はサーバー設定で設定されていること)');
  Lst.Add('# 例:');
  Lst.Add('#  _local_ _server_');
  Lst.Add('#  62.63.64.65 myserver.no-ip.com');
  Lst.Add('#  62.63.64.66 62.63.64.67');
  Lst.Add('#  192.168.* _server_');
  if DB_Ips_Local <> '' then
    Lst.Add('_local_ ' + DB_Ips_Local);
  for I := 0 to DB_Ips.Count - 1 do
  begin
    Item := DB_Ips.Items[I];
    Lst.Add(Item^.Cmd + ' ' + Item^.Data);
  end;
  try
    Lst.SaveToFile(ApplicationDir + 'ips');
  except
  end;
  Lst.Free;
  DB_Ips.Free;
end;

end.
