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

 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.
