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

 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: Console

 Handler for console user

*********************************************************}
unit Console;

interface

uses
  SysUtils, Classes, Classes2, Graphics, ZLibEx, WinSock, Windows, Constants,
  STypes, Lang, BlckSock, SynSock, Users, Registered, LocalUsers, Servers,
  Comctrls, SlavaStrings, Mmsystem, Class_Cmdlist, StringResources;

procedure ConsoleListRegistered;
procedure ConsoleListUsers;
procedure ConsoleListServers;
procedure ConsoleListChannels;
procedure ConsoleListBans;
procedure ConsoleListHotlist;
procedure ConsoleRefreshLists(Switch_Page: Boolean);
procedure ConsoleListLists(Switch_Page: Boolean);
procedure ConsoleReply(Id: Integer; Str: string);
procedure ConsoleAddServer(Str: string);
procedure ConsoleServerProps(Str: string);
procedure ConsoleUpdateServerProps(Str: string);
procedure SendPrivateMyMessage(Cmd: string);
procedure ConsoleSetCompress(Cmd: string);
procedure ConsoleSetStartup(Cmd: string);
procedure ConsoleSaveShared;

implementation

uses
  Vars, MainForm, Handler, Napigator, Dagsta, Thread, Channels, ChannelForm,
    Bans,
  ServerAttr, ChatForm, WhoisForm, InvitationForm, Share, Blocks, BrowseForm;

var
  HList: TMyStringList;
  Cmd: TNapCmd;
  Im_Log_File: TFileStream;

function CheckParams(N: Integer): Boolean;
begin
  SplitString(Cmd.Cmd, HList);
  Result := HList.Count >= N;
end;

procedure PlayChat(New_Window: Boolean);
var
  I: Integer;
begin
  Tmp_Pos := 1312;
  if not SlavaNapWindow.Cb_Log_Sound.Checked then Exit;
  if New_Window then
    I := 1
  else
    I := 2;
  PlaySound(PChar(ApplicationDir + 'newmsg' + IntToStr(I) + '.wav'), 0,
    SND_FILENAME or SND_ASYNC);
  Tmp_Pos := 1313;
end;

procedure ConsoleSaveShared; // for debug Only
var
  I, J: Integer;
  User: TLocalUser;
  // Sh: PShare;
  F: TFileStream;
  Str: string;
begin
  Tmp_Pos := 1314;
  try
    F := TFileStream.Create(ApplicationDir + 'shared.dat', fmCreate);
  except
    Exit;
  end;
  Str := RS_Console_SharedFileDescription;
  Tmp_Pos := 1315;
  for I := DB_Local.Count - 1 downto 0 do
  try
    User := DB_Local.Items[I];
    if User.Logged then
      if User.Shared <> nil then
        if User.Shared.Count > 0 then
          for J := 0 to User.Shared.Count - 1 do
          begin
            // Sh := User.Shared.Items[J];
            Str := User.Nick + ' ' + AddStr(User.Shared.GetFileName(J)) + #10;
            F.write(Str[1], Length(Str));
          end;
  except
  end;
  F.Free;
  Tmp_Pos := 1316;
end;

procedure ConsoleListServers;
var
  Item: TListItem;
  Srv: TServer;
  I: Integer;
  Str: string;
begin
  Tmp_Pos := 1317;
  if not Running then Exit;
  SlavaNapWindow.Btn_Servers_Refresh.Enabled := True;
  SlavaNapWindow.Mnu_Srv_Refresh.Enabled := True;
  with SlavaNapWindow.List_Servers do
  begin
    Items.BeginUpdate;
    Items.Clear;
    Tmp_Pos := 1318;
    if DB_Servers <> nil then
      for I := 0 to DB_Servers.Count - 1 do
      begin
        Srv := DB_Servers.Items[I];
        Tmp_Pos := 1319;
        Item := Items.Add;
        Item.Caption := Srv.Host;
        Item.SubItems.Add(IntToStr(Srv.Port));
        Str := '';
        Tmp_Pos := 1320;
        if Srv.Connected = conNotConnected then
          Str := GetLangI(LNG_SRV_DISCONNECTED)
        else if Srv.Connected = conConnected then
        begin
          if Srv.Logged = False then
            Str := GetLangI(LNG_SRV_LOGGING)
          else if Srv.Hub = nil then
            Str := GetLangI(LNG_SRV_LOGGED)
          else
            Str := GetLangI(LNG_SRV_HUB, GetServerName(Srv.Hub));
        end
        else if Srv.Connected = conConnecting then
          Str := GetLangI(LNG_SRV_CONNECTING)
        else
          Str := GetLangI(LNG_SRV_DISCONNECTED);
        Tmp_Pos := 1321;
        Item.SubItems.Add(Str);
        Tmp_Pos := 1322;
        if (Srv.Connected = conConnected) and (Srv.Hub = nil) then
          Item.SubItems.Add(GetLangI(LNG_SLIST_LAGSEC, Srv.CountLag))
        else
          Item.SubItems.Add('');
        if Srv.Logged then
          Item.SubItems.Add(IntToStr(Srv.Num_Users) + '/' +
            IntToStr(Srv.Max_Users))
        else
          Item.SubItems.Add('');
        Tmp_Pos := 1323;
        if Srv.Authentication = authResolve then
          Item.SubItems.Add(GetLangI(LNG_SRV_RESOLVE))
        else
          Item.SubItems.Add(GetLangI(LNG_SRV_PASSWORD));
        if Srv.Relink = 0 then
          Item.SubItems.Add('')
        else
          Item.SubItems.Add(GetLangI(LNG_SRV_RELINKTIME, Srv.Relink div 60000));
        Tmp_Pos := 1324;
        Item.SubItems.Add(Srv.Comments);
        Item.SubItems.Add(Srv.Alias);
        Item.SubItems.Add(IntToStr(Srv.Redirects));
        Tmp_Pos := 1325;
      end;
    AlphaSort;
    Tmp_Pos := 1326;
    Items.EndUpdate;
  end;
  Tmp_Pos := 1327;
  SlavaNapWindow.ToolBarResize(nil);
  Tmp_Pos := 1328;
end;

procedure ConsoleListChannels;
var
  Item: TListItem;
  Ch: TChannel;
  I: Integer;
  Str: string;
begin
  if not Running then Exit;
  Tmp_Pos := 1329;
  SlavaNapWindow.Btn_Ch_Refresh.Enabled := True;
  SlavaNapWindow.Mnu_Ch_Refresh.Enabled := True;
  with SlavaNapWindow.List_Channels do
  begin
    Tmp_Pos := 1330;
    Items.BeginUpdate;
    Items.Clear;
    Tmp_Pos := 1331;
    if DB_Channels <> nil then
      for I := 0 to DB_Channels.Count - 1 do
      begin
        Ch := DB_Channels.Items[I];
        Tmp_Pos := 1332;
        Item := Items.Add;
        Item.Caption := Ch.Channel;
        Item.SubItems.Add(IntToStr(Ch.Users.Count));
        Item.SubItems.Add(IntToStr(Ch.Limit));
        Item.SubItems.Add(Level2Str(Ch.Level));
        Str := '';
        Tmp_Pos := 1333;
        if chRegistered in Ch.State then
          Str := GetLangI(LNG_CH_REGISTERED);
        if chModerated in Ch.State then
        begin
          if Str <> '' then
            Str := Str + ', ';
          Str := Str + GetLangI(LNG_CH_MODERATED);
        end;
        if chPrivate in Ch.State then
        begin
          if Str <> '' then
            Str := Str + ', ';
          Str := Str + GetLangI(LNG_CH_PRIVATE);
        end;
        if chTopic in Ch.State then
        begin
          if Str <> '' then
            Str := Str + ', ';
          Str := Str + GetLangI(LNG_CH_TOPIC);
        end;
        Tmp_Pos := 1334;
        Item.SubItems.Add(Str);
        Item.SubItems.Add(Ch.Topic);
        Item.SubItems.Add(JoinString(Ch.Bans));
        Item.SubItems.Add(JoinString(Ch.Ops));
        Item.SubItems.Add(JoinString(Ch.Voices));
      end;
    Tmp_Pos := 1335;
    AlphaSort;
    Items.EndUpdate;
  end;
  Tmp_Pos := 1336;
  SlavaNapWindow.ToolBarResize(nil);
  Tmp_Pos := 1337;
end;

procedure ConsoleListBans;
var
  Item: TListItem;
  I: Integer;
  B: PBan;
  Str: string;
begin
  Tmp_Pos := 1343;
  if not Running then Exit;
  if DB_Bans = nil then Exit;
  Str := GetLangI(LNG_BANS_NEVER_EXPIRE);
  Tmp_Pos := 1344;
  with SlavaNapWindow.List_Bans do
  begin
    Items.BeginUpdate;
    Items.Clear;
    Tmp_Pos := 1345;
    for I := 0 to DB_Bans.Count - 1 do
    begin
      B := DB_Bans.Items[I];
      Tmp_Pos := 1346;
      Item := Items.Add;
      Item.Caption := B^.User;
      Item.SubItems.Add(B^.Ip);
      Item.SubItems.Add(B^.Admin);
      Item.SubItems.Add(UnixTimeToStr(B^.Time));
      Tmp_Pos := 1347;
      if B^.Expires > 0 then
        Item.SubItems.Add(UnixTimeToStr(B^.Expires))
      else
        Item.SubItems.Add(Str);
      Item.SubItems.Add(UnixTimeToStr(B^.LastAttempt));
      Item.SubItems.Add(B^.Using);
      Item.SubItems.Add(IntToStr(B^.Tries));
      Item.SubItems.Add(B^.Reason);
    end;
    Tmp_Pos := 1348;
    AlphaSort;
    Items.EndUpdate;
  end;
  SlavaNapWindow.ToolBarResize(nil);
  Tmp_Pos := 1349;
end;

procedure ConsoleRefreshLists(Switch_Page: Boolean);
begin
  Tmp_Pos := 1350;
  if not Running then Exit;
  Blocks2List(Cons_Blocks);
  Tmp_Pos := 1352;
  StrHash_Copy(Cons.Ignored, Cons_Ignored);
  StrHash_Copy(DB_Friends, Cons_Friends);
  ConsoleListLists(Switch_Page);
  Tmp_Pos := 1353;
end;

procedure ConsoleListLists(Switch_Page: Boolean);
var
  Item: TListItem;
  I: Integer;
  List: TStringHash;
  T: PStringHashItem;
begin
  Tmp_Pos := 1354;
  if not Running then Exit;
  case Cons_List of
    consFriends: List := Cons_Friends;
    consIgnored: List := Cons_Ignored;
    consBlocks: List := Cons_Blocks;
  end;
  Tmp_Pos := 1355;
  if Switch_Page then
    SlavaNapWindow.Pages.ActivePage := SlavaNapWindow.Sh_List;
  with SlavaNapWindow.List_Lists do
  begin
    Items.BeginUpdate;
    Items.Clear;
    Tmp_Pos := 1356;
    T := List.First;
    while T <> nil do
    begin
      Item := Items.Add;
      Item.Caption := T^.Data;
      T := T^.Next;
    end;
    Tmp_Pos := 1357;
    AlphaSort;
    Items.EndUpdate;
  end;
  // Change Items
  Tmp_Pos := 1358;
  with SlavaNapWindow do
  begin
    case Cons_List of
      consFriends:
        begin
          Tmp_Pos := 1359;
          Lbl_List.Caption := GetLangI(LNG_LBL_FRIENDS);
          Btn_List_Refresh.Caption := GetLangI(LNG_FBTN_REFRESH);
          Btn_List_Delete.Caption := GetLangI(LNG_FBTN_REMOVE);
          Edit_List_Item.Hint := GetLangI(LNG_FEDIT_HINT);
          Btn_List_Add.Caption := GetLangI(LNG_FBTN_ADD);
          List_Lists.Columns.Items[0].Caption := GetLangI(LNG_FLIST_USER);
          List_Lists.PopupMenu := Popup_Friends;
        end;
      consIgnored:
        begin
          Tmp_Pos := 1360;
          Lbl_List.Caption := GetLangI(LNG_LBL_IGNORED);
          Btn_List_Refresh.Caption := GetLangI(LNG_IBTN_REFRESH);
          Btn_List_Delete.Caption := GetLangI(LNG_IBTN_REMOVE);
          Edit_List_Item.Hint := GetLangI(LNG_IEDIT_HINT);
          Btn_List_Add.Caption := GetLangI(LNG_IBTN_ADD);
          List_Lists.Columns.Items[0].Caption := GetLangI(LNG_ILIST_USER);
          List_Lists.PopupMenu := Popup_Ignored;
        end;
      consBlocks:
        begin
          Tmp_Pos := 1361;
          if Share_MatchedFile_Only then
          begin
            Lbl_List.Caption := RS_Console_LNG_LBL_BLOCKS;
            Btn_List_Refresh.Caption := GetLangI(LNG_BLBTN_REFRESH);
            Btn_List_Delete.Caption := GetLangI(LNG_BLBTN_REMOVE);
            Edit_List_Item.Hint := RS_Console_LNG_BLEDIT_HINT;
            Btn_List_Add.Caption := GetLangI(LNG_BLBTN_ADD);
            List_Lists.Columns.Items[0].Caption := RS_Console_LNG_BLLIST_ITEM;
            List_Lists.PopupMenu := Popup_Blocks;
            Mnu_Win_Blocked.Caption := RS_Console_LNG_MENU_BLOCK;
            Btn_Tb_Blocks.Caption := RS_Console_LNG_TB_BTN_BLOCKS;
            Btn_Tb_Blocks.Hint := RS_Console_LNG_TB_BTN_BLOCKS_HINT;
            Mnu_Bl_Delete.Caption := RS_Console_LNG_BMNU_DELETE;
          end
          else
          begin
            Lbl_List.Caption := GetLangI(LNG_LBL_BLOCKS);
            Btn_List_Refresh.Caption := GetLangI(LNG_BLBTN_REFRESH);
            Btn_List_Delete.Caption := GetLangI(LNG_BLBTN_REMOVE);
            Edit_List_Item.Hint := GetLangI(LNG_BLEDIT_HINT);
            Btn_List_Add.Caption := GetLangI(LNG_BLBTN_ADD);
            List_Lists.Columns.Items[0].Caption := GetLangI(LNG_BLLIST_ITEM);
            List_Lists.PopupMenu := Popup_Blocks;
          end;
        end;
    end;
    Tmp_Pos := 1362;
    I := Btn_List_Refresh.Left;
    Btn_List_Refresh.Width := Canvas.TextWidth(Btn_List_Refresh.Caption) + 20;
    Inc(I, Btn_List_Refresh.Width);
    Btn_List_Delete.Left := I;
    Btn_List_Delete.Width := Canvas.TextWidth(Btn_List_Delete.Caption) + 20;
    Inc(I, Btn_List_Delete.Width);
    Edit_List_Item.Left := I;
    Edit_List_Item.Text := '';
    Inc(I, Edit_List_Item.Width);
    Btn_List_Add.Left := I;
    Btn_List_Add.Width := Canvas.TextWidth(Btn_List_Add.Caption) + 20;
    Tmp_Pos := 1363;
    if Cons_List = consFriends then
    begin
      Cb_List_Sound.Visible := True;
      Inc(I, Btn_List_Add.Width + 10);
      Cb_List_Sound.Left := I;
      Cb_List_Sound.Caption := GetLangI(LNG_LIST_CB_SOUND);
      Cb_List_Sound.Width := Canvas.TextWidth(Cb_List_sOund.Caption) + 25;
    end
    else
      Cb_List_Sound.Visible := False;
    Tmp_Pos := 1364;
    if Cons_List = consBlocks then
    begin
      Inc(I, Btn_List_Add.Width);
      Btn_List_Reload.Visible := True;
      Btn_List_Reload.Left := I;
      Btn_List_Reload.Caption := GetLangI(LNG_BLBTN_RELOAD);
      Btn_List_Reload.Width := Canvas.TextWidth(Btn_List_Reload.Caption) + 25;
    end
    else
      Btn_List_Reload.Visible := False;
    toolbarResize(nil);
  end;
  Tmp_Pos := 1365;
end;

procedure ConsoleListHotlist;
var
  Item: TListItem;
  User: POnlineUser;
  T: PStringHashItem;
begin
  Tmp_Pos := 1366;
  if not Running then Exit;
  with SlavaNapWindow.List_Hotlist do
  begin
    Tmp_Pos := 1367;
    Items.BeginUpdate;
    Items.Clear;
    T := Cons.Hotlist.First;
    while T <> nil do
    begin
      Tmp_Pos := 1368;
      Item := Items.Add;
      Item.Caption := T^.Data;
      Tmp_Pos := 1369;
      User := DB_Online.FindUser(T^.Data);
      if User = nil then
      begin
        Item.SubItems.Add(' ' + GetLangI(LNG_HLIST_OFFLINE));
        Item.SubItems.Add('');
      end
      else
      begin
        Item.SubItems.Add(GetServerName(User^.Server));
        Item.SubItems.Add(Speed2Str(User^.Speed));
      end;
      T := T^.Next;
    end;
    Tmp_Pos := 1370;
    AlphaSort;
    Items.EndUpdate;
  end;
  SlavaNapWindow.ToolBarResize(nil);
  Tmp_Pos := 1371;
end;

procedure ConsoleListUsers;
var
  I, J, K: Integer;
  User: POnlineUser;
  Localuser: TLocalUser;
  Item: TListItem;
  Str, F: string;
  B: Boolean;
  Th: TUserListReverseDNSThread;
begin
  Tmp_Pos := 1372;
  if not Running then Exit;
  SlavaNapWindow.Btn_Users_Refresh.Enabled := True;
  SlavaNapWindow.Mnu_Users_Refresh.Enabled := True;
  if DB_Online = nil then Exit;
  F := AnsiLowerCase(SlavaNapWindow.Edit_Users_Filter.Text);
  if F = '*' then
    F := '';
  Tmp_Pos := 1373;
  with SlavaNapWindow.List_Users do
  begin
    Items.BeginUpdate;
    Items.Clear;
    Tmp_Pos := 1374;
    for I := 0 to USERS_NAME_ARRAY - 1 do
      for J := 0 to DB_Online.Names[I].Count - 1 do
      begin
        Tmp_Pos := 1375;
        User := DB_Online.Names[I].Items[J];
        B := True;
        if SlavaNapWindow.Cb_Users_Muzzled.Checked and (not (userMuzzled in
          User^.State)) then
          B := False;
        if User^.Level = napUserLeech then
          if not SlavaNapWindow.Cb_Users_Leeches.Checked then
            B := False;
        if User^.Level = napUserUser then
          if not SlavaNapWindow.Cb_Users_Users.Checked then
            B := False;
        if User^.Level > napUserUser then
          if not SlavaNapWindow.Cb_Users_Mods.Checked then
            B := False;
        if User^.Server = nil then
          if not SlavaNapWindow.Cb_Users_Local.Checked then
            B := False;
        if User^.Server <> nil then
          if not SlavaNapWindow.Cb_Users_Remote.Checked then
            B := False;
        Tmp_Pos := 1376;
        if B and (F <> '') then
          B := MatchesMaskEx(AnsiLowerCase(User^.UserName), F);
        if B then
        begin // if matches
          Tmp_Pos := 1377;
          Item := Items.Add;
          Item.Caption := User^.UserName;
          Item.SubItems.Add(Level2Str(User^.Level));
          Item.SubItems.Add(IntToStr(User^.Shared));
          if User^.Server = nil then
          begin // Local user
            for K := 0 to DB_Local.Count - 1 do
              if AnsiLowerCase(TLocalUser(DB_Local.Items[K]).Nick) =
                AnsiLowerCase(User^.UserName) then
              begin
                Localuser := DB_Local.Items[K];
                Item.SubItems.Add(IntToStr(Localuser.Shared_Size div (1024 *
                  1024)));
                if User^.Shared > 0 then
                  Item.SubItems.Add(IntToStr(Localuser.Shared_Size div
                    User^.Shared div (1024 * 1024)))
                else
                  Item.SubItems.Add('0');
                Break;
              end;
          end
          else // Remote user
          begin
            Item.SubItems.Add(RS_Console_Remote);
            Item.SubItems.Add(RS_Console_Remote);
          end;
          Item.SubItems.Add(User^.Software);
          Item.SubItems.Add(Speed2Str(User^.Speed));
          Item.SubItems.Add(Decode_Ip(User^.Ip));
          Item.SubItems.Add(RS_Console_Unresolved);
          if SlavaNapWindow.IsColumnVisible(SlavaNapWindow.List_Users,
            UL_REMOTEHOST + 1) then
          begin
            Th := TUserListReverseDNSThread.Create(False);
            Th.Ip := User^.Ip;
            Th.Item := Item;
          end;
          Item.SubItems.Add(IntToStr(User^.DataPort));
          Item.SubItems.Add(Time2Str(Current_Time_T - User^.Last_Seen_T));
          Item.SubItems.Add(IntToStr(User^.Uploads));
          Item.SubItems.Add(IntToStr(User^.Downloads));
          Str := IntToStr(User^.Uploads);
          if User^.Max_Up <> -1 then
            Str := Str + ' (' + IntToStr(User^.Max_Up) + ' Max)';
          Str := Str + ' / ' + IntToStr(User^.Downloads);
          Item.SubItems.Add(Str);
          Item.SubItems.Add(IntToStr(User^.Total_Up));
          Item.SubItems.Add(IntToStr(User^.Total_Down));
          Item.SubItems.Add(IntToStr(User^.Total_Up) + ' / ' +
            IntToStr(User^.Total_Down));
          Item.SubItems.Add(GetServerName(User^.Server));
          Item.SubItems.Add(IntToStr(User^.ULRequests));
          Item.SubItems.Add(IntToStr(User^.DLRequests));
          Item.SubItems.Add(IntToStr(User^.SearchReqs));
          Item.SubItems.Add(IntToStr(User^.BlockFiles));
          Str := '';
          Tmp_Pos := 1378;
          if userMuzzled in User^.State then
            Str := Str + GetLangI(LNG_LIST_MUZZLED);
          if userCloaked in User^.State then
          begin
            if Str <> '' then
              Str := Str + ', ';
            Str := Str + GetLangI(LNG_LIST_CLOAKED);
          end;
          if userChatting in User^.State then
          begin
            if Str <> '' then
              Str := Str + ', ';
            Str := Str + GetLangI(LNG_LIST_CHATTING);
          end;
          if User^.Local <> nil then
          begin // Adding items That present Only for Local users
            Tmp_Pos := 1379;
            if TLocalUser(User^.Local).SoftwareID = softWinMXHidden then
            begin
              if Str <> '' then
                Str := Str + ', ';
              Str := Str + GetLangI(LNG_LIST_WINMXH);
            end
            else
              {if (TLocalUser(User^.Local).SoftwareID <> softWinMXNormal) and
                (TLocalUser(User^.Local).SoftwareID <> softWinMXJap) and
                (not (locPingable in TLocalUser(User^.Local).Localstate)) and
                ((Current_Time-20000) > TLocalUser(User^.Local).Last_Seen) then
              begin
                if Str <> '' then Str := Str + ', ';
                Str := Str + GetLangI(LNG_LIST_NOPONG);
              end;}
              if Str <> '' then
                Str := Str + ', ';
            if locPingable in TLocalUser(User^.Local).Localstate then
            begin
              if Loc326 in TLocalUser(User^.Local).Detector then
                Str := Str + '2get'
              else if Loc10300 in TLocalUser(User^.Local).Detector then
                Str := Str + 'XNap';
              // else if not (loc208 in TLocalUser(User^.Local).Detector) then
              //   Str := Str + 'XNap??';
            end
            else if Loc326 in TLocalUser(User^.Local).Detector then
            begin
              if locMacDir in TLocalUser(User^.Local).Detector then
                Str := Str + '2get'
              else
                Str := Str + 'MX2.x';
            end
            else if Loc110 in TLocalUser(User^.Local).Detector then
              Str := Str + 'Napchan'
            else if Loc208 in TLocalUser(User^.Local).Detector then
              Str := Str + 'Utatane'
            else if locMD5Zeros in TLocalUser(User^.Local).Detector then
              Str := Str + 'Utatane'
            else if Loc10300 in TLocalUser(User^.Local).Detector then
              Str := Str + 'XNap'
            else if locMD5NonZero in TLocalUser(User^.Local).Detector then
              Str := Str + 'MX3.x'
            else
              Str := Str + 'MX3.x??'
          end;
          Item.SubItems.Add(Str);
          // Item.SubItems.Add(IntToStr(TLocalUser(User^.Local).Shared_Blocked));
          Str := '';
          if (User^.Server = nil) then
            if TLocalUser(User^.Local).Shared_Blocked > 0 then
              Str := IntToStr(TLocalUser(User^.Local).Shared_Blocked);
          Item.SubItems.Add(Str);
        end;
      end;
    Tmp_Pos := 1380;
    AlphaSort;
    Items.EndUpdate;
  end;
  SlavaNapWindow.ToolBarResize(nil);
  Tmp_Pos := 1381;
end;

procedure ConsoleListRegistered;
var
  I, J: Integer;
  Item: TListItem;
  Reg: PRegisteredUser;
  B: Boolean;
  F, Str: string;
begin
  Tmp_Pos := 1382;
  if not Running then Exit;
  SlavaNapWindow.Btn_Reg_Refresh.Enabled := True;
  SlavaNapWindow.Mnu_Reg_Refresh.Enabled := True;
  if DB_Registered = nil then Exit;
  F := AnsiLowerCase(SlavaNapWindow.Edit_Reg_Filter.Text);
  if F = '*' then
    F := '';
  Tmp_Pos := 1383;
  with SlavaNapWindow.List_Registered do
  begin
    Tmp_Pos := 1384;
    Items.BeginUpdate;
    Items.Clear;
    for I := 0 to USERS_NAME_ARRAY - 1 do
      for J := 0 to DB_Registered.List[I].Count - 1 do
      begin
        Tmp_Pos := 1385;
        Reg := DB_Registered.List[I].Items[J];
        if Reg^.Level = napUserLeech then
          B := SlavaNapWindow.Cb_Reg_Leeches.Checked
        else if Reg^.Level = napUserUser then
          B := SlavaNapWindow.Cb_Reg_Users.Checked
        else
          B := SlavaNapWindow.Cb_Reg_Mods.Checked;
        if SlavaNapWindow.Cb_Reg_Muzzled.Checked then
          B := userMuzzled in Reg^.State;
        Tmp_Pos := 1386;
        if B and (F <> '') then
          B := MatchesMaskEx(AnsiLowerCase(Reg^.Nick), F);
        if B then
        begin
          Tmp_Pos := 1387;
          Item := Items.Add;
          Item.Caption := Reg^.Nick;
          Item.SubItems.Add(Level2Str(Reg^.Level));
          Item.SubItems.Add(GetLangI(LNG_REG_TRANSFERS, Reg^.Downloads,
            Reg^.Uploads));
          Item.SubItems.Add(Decode_Ip(Reg^.Last_Ip));
          Item.SubItems.Add(UnixTimeToStr(Reg^.Last_Seen));
          Str := '';
          if userMuzzled in Reg^.State then
            Str := Str + GetLangI(LNG_REG_MUZZLED);
          if userCloaked in Reg^.State then
          begin
            if Str <> '' then
              Str := Str + ', ';
            Str := Str + GetLangI(LNG_REG_CLOAKED);
          end;
          Item.SubItems.Add(Str);
          Item.SubItems.Add(UnixTimeToStr(Reg^.Created));
          Item.SubItems.Add(Reg^.CreatedBy);
          Item.SubItems.Add(Reg^.LastSetBy);
          Item.ImageIndex := Ord(Reg^.Level);
        end;
      end;
    Tmp_Pos := 1388;
    AlphaSort;
    Items.EndUpdate;
  end;
  SlavaNapWindow.ToolBarResize(nil);
  Tmp_Pos := 1389;
end;

procedure Handler_JoinChannel;
var
  Form: TSlavaNapChannelWindow;
begin
  Tmp_Pos := 1390;
  if Cons_Channels = nil then Exit;
  if SlavaNapWindow.FindChannelWindow(Cmd.Cmd) <> nil then Exit;
  Form := SlavaNapWindow.CreateChannelWindow(Cmd.Cmd);
  if Form = nil then Exit;
  Tmp_Pos := 1391;
end;

procedure Handler_ChannelAddUser;
var
  Form: TSlavaNapChannelWindow;
  I: Integer;
  Item: TListItem;
  User: POnlineUser;
begin
  Tmp_Pos := 1392;
  if not CheckParams(4) then Exit;
  ;
  Form := SlavaNapWindow.FindChannelWindow(HList.Strings[0]);
  if Form = nil then Exit;
  Item := nil;
  Tmp_Pos := 1393;
  for I := 0 to Form.Users.Items.Count - 1 do
    if Form.Users.Items.Item[I].SubItems[0] = HList.Strings[1] then
      Item := Form.Users.Items.Item[I];
  Form.Users.Items.Beginupdate;
  if Item = nil then
  begin
    Item := Form.Users.Items.Add;
    Item.SubItems.Add('');
  end;
  Tmp_Pos := 1394;
  Item.Caption := GetLangI(LNG_CH_USERLIST, HList.Strings[1],
    Speed2Str(TNapSpeed(StrToIntDef(HList.Strings[3], 0))), HList.Strings[2]);
  Item.SubItems[0] := HList.Strings[1];
  Form.Users.Items.Endupdate;
  User := DB_Online.FindUser(HList.Strings[1]);
  if User = nil then Exit;
  if Cmd.Id = MSG_SERVER_JOIN then
    Form.AddMessage(slChannelJoin, GetLangI(LNG_CH_JOIN, HList.Strings[1],
      Speed2Str(TNapSpeed(StrToIntDef(HList.Strings[3], 0))), HList.Strings[2],
      Decode_Ip(User^.Ip)));
  Tmp_Pos := 1395;
end;

procedure Handler_ChannelRemoveUser;
var
  Form: TSlavaNapChannelWindow;
  I: Integer;
begin
  Tmp_Pos := 1396;
  if not CheckParams(2) then Exit;
  Form := SlavaNapWindow.FindchannelWindow(HList.Strings[0]);
  if Form = nil then Exit;
  Tmp_Pos := 1397;
  for I := Form.Users.Items.Count - 1 downto 0 do
    if Form.Users.Items.Item[I].SubItems[0] = HList.Strings[1] then
      Form.Users.Items.Delete(I);
  Form.AddMessage(slChannelPart, GetLangI(LNG_CH_PART, HList.Strings[1]));
  Tmp_Pos := 1398;
end;

procedure Handler_ChannelTopic;
var
  Form: TSlavaNapChannelWindow;
begin
  Tmp_Pos := 1399;
  if not CheckParams(1) then Exit;
  Form := SlavaNapWindow.FindChannelWindow(HList.Strings[0]);
  if Form = nil then Exit;
  Tmp_Pos := 1400;
  Form.Topic := NextParamEx(Cmd.Cmd);
  Form.Caption := Form.Channel + ': ' + Form.Topic;
  Form.AddMessage(slTopic, GetLangI(LNG_CH_CHTOPIC, Form.Topic));
  Tmp_Pos := 1401;
end;

procedure Handler_ChannelEmote;
var
  Form: TSlavaNapChannelWindow;
  Str, Str1: string;
begin
  Tmp_Pos := 1402;
  if not CheckParams(3) then Exit;
  Form := SlavaNapWindow.FindChannelWindow(HList.Strings[0]);
  if Form = nil then Exit;
  Tmp_Pos := 1403;
  Str := HList.Strings[1];
  if HList.Count = 3 then
    Str1 := HList.Strings[2]
  else
    Str1 := NextParamEx(Cmd.Cmd, 2);
  if Length(Str1) > 1 then
    if (Str1[1] = '"') and (Str1[Length(Str1)] = '"') then
      Str1 := Copy(Str1, 2, Length(Str1) - 2);
  Tmp_Pos := 1404;
  if Str = Cons.Nick then
    Form.AddMessage(slChannelMyEmote, ' ' + Str + ' ' + Str1)
  else
    Form.AddMessage(slChannelEmote, ' ' + Str + ' ' + Str1);
  Tmp_Pos := 1405;
end;

procedure Handler_ChannelMessage;
var
  Form: TSlavaNapChannelWindow;
  Str: string;
begin
  Tmp_Pos := 1406;
  if not CheckParams(3) then Exit;
  Form := SlavaNapWindow.FindChannelWindow(HList.Strings[0]);
  if Form = nil then Exit;
  Tmp_Pos := 1407;
  Str := HList.Strings[1];
  if Str = Cons.Nick then
    Form.AddMessage(slChannelMyMessage, '<' + Str + '> ' + NextParamEx(Cmd.Cmd,
      2))
  else
    Form.AddMessage(slChannelMessage, '<' + Str + '> ' + NextParamEx(Cmd.Cmd,
      2));
  Tmp_Pos := 1408;
end;

procedure Handler_PartChannel;
var
  Form: TSlavaNapChannelWindow;
begin
  Tmp_Pos := 1409;
  Form := SlavaNapWindow.FindChannelWindow(Cmd.Cmd);
  if Form = nil then Exit;
  Tmp_Pos := 1410;
  Form.Close;
  Tmp_Pos := 1411;
end;

procedure Handler_Wallop;
var
  Form: TSlavaNapChatWindow;
begin
  Tmp_Pos := 1412;
  if not CheckParams(1) then Exit;
  if Wallop_Sound then
    PlaySound(PChar(ApplicationDir + 'wallop.wav'), 0, SND_FILENAME or
      SND_ASYNC);
  if Wallop_Im then
    if (not SlavaNapWindow.Cb_Log_Away.Checked) or
      (SlavaNapWindow.Cb_Log_Awaypopup.Checked) then
    begin
      Tmp_Pos := 1413;
      Form := SlavaNapWindow.FindChatWindow(HList.Strings[0]);
      if Form = nil then
      begin
        if not Wallop_Sound then
          PlayChat(True);
        Form := SlavaNapWindow.CreateChatWindow(HList.Strings[0]);
      end
      else
        PlayChat(False);
      Tmp_Pos := 1414;
      Form.AddMessage(slChatMessage, '<wallop/' + HList.Strings[0] + '> ' +
        NextParamEx(Cmd.Cmd));
      Tmp_Pos := 1415;
      Exit;
    end;
  Tmp_Pos := 1416;
  SlavaNapWindow.LogConsole(slWallop, '<' + FirstParam(Cmd.Cmd) + '> ' +
    NextParamEx(Cmd.Cmd));
  Tmp_Pos := 1417;
end;

procedure Handler_PrivateMessage;
var
  Form: TSlavaNapChatWindow;
  Str: string;
begin
  Tmp_Pos := 1418;
  if not CheckParams(1) then Exit;
  if not FileExists(ApplicationDir + 'im.log') then
  try
    Im_Log_File := TFileStream.Create(ApplicationDir + 'im.log', fmCreate);
    Im_Log_File.Free;
  except
    Im_Log_File := nil;
    Exit;
  end;
  Im_Log_File := nil;
  try
    Im_Log_File := TFileStream.Create(ApplicationDir + 'im.log', fmOpenWrite or
      fmShareDenyWrite);
    Im_Log_File.Seek(0, soFromEnd);
  except
    Im_Log_File := nil;
    Exit;
  end;
  Str := '[' + DateTimeToStr(Now) + '] <' + Cons.Nick + '仼' + HList.Strings[0] +
    '> ' + NextParam(Cmd.Cmd) + #13#10;
  Im_Log_File.write(Str[1], Length(Str));
  Im_Log_File.Free;
  if SlavaNapWindow.Cb_Log_Away.Checked then
  begin
    Tmp_Pos := 1419;
    if SlavaNapWindow.Cb_Log_Awaypopup.Checked then
      Form := SlavaNapWindow.CreateChatWindow(HList.Strings[0])
    else
      Form := SlavaNapWindow.FindChatWindow(HList.Strings[0]);
    Tmp_Pos := 1420;
    if Form <> nil then
      Form.AddMessage(slChatMessage, '<' + HList.Strings[0] + '> ' +
        NextParamEx(Cmd.Cmd))
    else
      SlavaNapWindow.LogConsole(slChatMessage, '<' + HList.Strings[0] + '> ' +
        NextParamEx(Cmd.Cmd));
    Tmp_Pos := 1421;
    if Last_Away_User = HList.Strings[0] then
      if (GetTickCount - Last_Away_Time) < 15000 then Exit;
    Last_Away_User := HList.Strings[0];
    Last_Away_Time := GetTickCount;
    Tmp_Pos := 1422;
    Cmd_List.AddDoubleCmd(MSG_CLIENT_PRIVMSG, 0, HList.Strings[0] + ' ' +
      SlavaNapWindow.Edit_Log_Away.Text, '');
    Tmp_Pos := 1423;
    Exit;
  end;
  Tmp_Pos := 1424;
  Form := SlavaNapWindow.FindChatWindow(HList.Strings[0]);
  if Form = nil then
  begin
    Tmp_Pos := 1425;
    PlayChat(True);
    Form := SlavaNapWindow.CreateChatWindow(HList.Strings[0]);
  end
  else
    PlayChat(False);
  Tmp_Pos := 1426;
  if Form = nil then Exit;
  Form.AddMessage(slChatMessage, '<' + HList.Strings[0] + '> ' +
    NextParamEx(Cmd.Cmd));
  Tmp_Pos := 1427;
end;

procedure Handler_PrivateMyMessage(User, Text: string);
var
  Form: TSlavaNapChatWindow;
  Str: string;
begin
  Tmp_Pos := 1428;
  if not CheckParams(1) then Exit;
  ;
  if not FileExists(ApplicationDir + 'im.log') then
  try
    Im_Log_File := TFileStream.Create(ApplicationDir + 'im.log', fmCreate);
    Im_Log_File.Free;
  except
    Im_Log_File := nil;
    Exit;
  end;
  Im_Log_File := nil;
  try
    Im_Log_File := TFileStream.Create(ApplicationDir + 'im.log', fmOpenWrite or
      fmShareDenyWrite);
    Im_Log_File.Seek(0, soFromEnd);
  except
    Im_Log_File := nil;
    Exit;
  end;
  Str := '[' + DateTimeToStr(Now) + '] <' + Cons.Nick + '仺' + User + '> ' + Text
    + #13#10;
  Im_Log_File.write(Str[1], Length(Str));
  Im_Log_File.Free;

  if FirstParam(Text) = RS_Console_Announce then Exit;

  if SlavaNapWindow.Cb_Log_Away.Checked then
    if Text = SlavaNapWindow.Edit_Log_Away.Text then
    begin
      Tmp_Pos := 1429;
      Form := SlavaNapWindow.FindChatWindow(HList.Strings[0]);
      if Form = nil then Exit;
    end;
  Tmp_Pos := 1430;
  Form := SlavaNapWindow.CreateChatWindow(User);
  if Form = nil then Exit;
  Tmp_Pos := 1431;
  Form.AddMessage(slChatMyMessage, '<' + Cons.Nick + '> ' + Text);
  Tmp_Pos := 1432;
end;

procedure SendPrivateMyMessage(Cmd: string);
var
  Str, Str1: string;
begin
  Tmp_Pos := 1433;
  Str := FirstParam(Cmd);
  if Str = '' then Exit;
  Tmp_Pos := 1434;
  Str1 := NextParamEx(Cmd);
  Handler_PrivateMyMessage(Str, Str1);
  Tmp_Pos := 1435;
end;

procedure ConsoleAddServer(Str: string);
var
  Host, Port: string;
  Srv: TServer;
  I: Integer;
begin
  Tmp_Pos := 1436;
  I := Pos(':', Str);
  if I = 0 then
  begin
    Host := Str;
    Port := '8888';
  end
  else
  begin
    Host := Copy(Str, 1, I - 1);
    Port := Copy(Str, I + 1, 5);
  end;
  Host := LowerCase(Host);
  Tmp_Pos := 1437;
  Srv := FindServer(Host, False);
  if Srv <> nil then Exit;
  Tmp_Pos := 1438;
  Srv := TServer.Create;
  Srv.Host := Host;
  Srv.Port := StrToIntDef(Port, 8888);
  DB_Servers.Add(Srv);
  Tmp_Pos := 1439;
  ConsoleListServers;
  Tmp_Pos := 1440;
end;

procedure ConsoleServerProps(Str: string);
begin
  if not Running then Exit;
  Tmp_Pos := 1441;
  SlavaNapServerAttr.ShowServer(Str);
  Tmp_Pos := 1442;
end;

procedure ConsoleUpdateServerProps(Str: string);
var
  Srv: TServer;
begin
  if not Running then Exit;
  Tmp_Pos := 1443;
  if SlavaNapServerAttr.Server <> Str then Exit;
  Srv := FindServer(Str, False);
  if Srv = nil then Exit;
  Tmp_Pos := 1444;
  if Srv.Connected = conNotConnected then
  begin
    Str := LowerCase(SlavaNapServerAttr.Edit_Host.Text);
    if Str <> Srv.Host then
      if FindServer(Str, False) = nil then
        Srv.Host := Str;
    Srv.Port := SlavaNapServerAttr.Edit_Port.Value;
  end;
  Tmp_Pos := 1445;
  Srv.Forced_Ip := Trim(SlavaNapServerAttr.Edit_Ip.Text);
  if SlavaNapServerAttr.Cb_Auth_Resolve.Checked then
    Srv.Authentication := authResolve
  else
    Srv.Authentication := authPassword;
  Tmp_Pos := 1446;
  Srv.MyPassword := SlavaNapServerAttr.Edit_Mypass.Text;
  Srv.RemotePassword := SlavaNapServerAttr.Edit_Remotepass.Text;
  if SlavaNapServerAttr.Cb_Comp_0.Checked then
    Srv.Compress := zcNone
  else if SlavaNapServerAttr.Cb_Comp_1.Checked then
    Srv.Compress := zcFastest
  else if SlavaNapServerAttr.Cb_Comp_2.Checked then
    Srv.Compress := zcDefault
  else
    Srv.Compress := zcMax;
  Tmp_Pos := 1447;
  if SlavaNapServerAttr.Cb_Relink.Checked then
    Srv.Relink := SlavaNapServerAttr.Edit_Relink.Value * 60000
  else
    Srv.Relink := 0;
  Srv.Comments := SlavaNapServerAttr.Edit_Comments.Text;
  Tmp_Pos := 1448;
  ConsoleListServers;
  Tmp_Pos := 1449;
end;

procedure ConsoleHotListOnline(Str: string);
begin
  Tmp_Pos := 1450;
  if SlavaNapWindow.Cb_Hotlist_Sound.Checked then
    PlaySound(PChar(ApplicationDir + 'hotlistlogin.wav'), 0, SND_FILENAME or
      SND_ASYNC);
  ConsoleListHotlist;
  Tmp_Pos := 1451;
end;

procedure ConsoleSetCompress(Cmd: string);
var
  Srv: TServer;
  Comp: TZCompressionLevel;
begin
  Tmp_Pos := 1452;
  SplitString(Cmd, HList);
  if HList.Count < 2 then Exit;
  Tmp_Pos := 1453;
  Comp := TZCompressionLevel(StrToIntDef(HList.Strings[1], 3));
  Srv := FindServer(HList.Strings[0], False);
  if Srv <> nil then
    Srv.Compress := Comp;
  Tmp_Pos := 1454;
end;

procedure ConsoleSetStartup(Cmd: string);
var
  Srv: TServer;
  T: Cardinal;
begin
  Tmp_Pos := 1455;
  SplitString(Cmd, HList);
  if HList.Count < 2 then Exit;
  Tmp_Pos := 1456;
  T := StrToIntDef(HList.Strings[1], 0);
  Srv := FindServer(HList.Strings[0], False);
  if Srv <> nil then
    Srv.Relink := T;
  Tmp_Pos := 1457;
end;

procedure Handler_Whois;
var
  Form: TSlavaNapWhois;
  Str, Str1: string;
  I, J: Integer;
begin
  Tmp_Pos := 1458;
  SplitString(Cmd.Cmd, HList);
  if HList.Count < 17 then Exit;
  Tmp_Pos := 1459;
  Form := SlavaNapWindow.CreateWhoisWindow(HList.Strings[0]);
  Form.Caption := GetLangI(LNG_WHOIS_CAPTION, HList.Strings[0]);
  Form.Mnu_Close.Caption := GetLangI(LNG_WMENU_CLOSE);
  Form.Mnu_Hotlist.Caption := GetLangI(LNG_WMENU_HOTLIST);
  Form.Mnu_Friend.Caption := GetLangI(LNG_WMENU_FRIEND);
  Form.Mnu_Ignore.Caption := GetLangI(LNG_WMENU_IGNORE);
  Form.Mnu_Message.Caption := GetLangI(LNG_WMENU_MESSAGE);
  Tmp_Pos := 1460;
  Str := '';
  Str := GetLangI(LNG_WHOIS_USER, HList.Strings[0]); // User
  Str := Str + GetLangI(LNG_WHOIS_LEVEL, HList.Strings[1]); // Level
  I := StrToIntDef(HList.Strings[2], 0);
  J := I div 3600; // Hours
  I := I mod 3600;
  if J > 0 then
    Str1 := IntToStr(J) + ':'
  else
    Str1 := '';
  J := I div 60; // Mins
  I := I mod 60; // Sec
  if (Str1 <> '') and (J < 10) then
    Str1 := Str1 + '0' + IntToStr(J) + ':'
  else
    Str1 := Str1 + IntToStr(J) + ':';
  if I < 10 then
    Str1 := Str1 + '0' + IntToStr(I)
  else
    Str1 := Str1 + IntToStr(I);
  Tmp_Pos := 1461;
  Str := Str + GetLangI(LNG_WHOIS_TIME, Str1); // Time
  Str := Str + GetLangI(LNG_WHOIS_CHANNELS, HList.Strings[3]); // Channels
  Str := Str + GetLangI(LNG_WHOIS_STATUS, HList.Strings[4]); // Status
  Str := Str + GetLangI(LNG_WHOIS_SHARED, HList.Strings[5]); // Shared
  Str := Str + GetLangI(LNG_WHOIS_TRANSFERS, HList.Strings[6], HList.Strings[7]);
    // Down/up
  Str := Str + GetLangI(LNG_WHOIS_TOTAL, HList.Strings[10], HList.Strings[11]);
    // Total
  Str := Str + GetLangI(LNG_WHOIS_SPEED,
    Speed2Str(TNapSpeed(StrToIntDef(HList.Strings[8], 0)))); // Speed
  Str := Str + GetLangI(LNG_WHOIS_SOFTWARE, HList.Strings[9]); // Software
  Str := Str + GetLangI(LNG_WHOIS_IP, HList.Strings[12]); // IP
  if HList.Strings[13] <> '0' then
    Str := Str + GetLangI(LNG_WHOIS_PORT, HList.Strings[13]); // Port
  Str := Str + GetLangI(LNG_WHOIS_DATAPORT, HList.Strings[14]); // Dataport
  Str := Str + GetLangI(LNG_WHOIS_SERVER, HList.Strings[16]); // Server
  Form.Log.Text := Str;
  Tmp_Pos := 1462;
  Form.Show;
  Tmp_Pos := 1463;
end;

procedure Handler_Whowas;
var
  Str: string;
begin
  Tmp_Pos := 1464;
  SplitString(Cmd.Cmd, HList);
  if HList.Count < 3 then Exit;
  Tmp_Pos := 1465;
  Str := GetLangI(LNG_WHOIS_WHOWAS, HList.Strings[1], HList.Strings[0]);
  SlavaNapWindow.LogConsole(slWhowas, Str);
  Tmp_Pos := 1466;
end;

procedure Handler_Invite;
begin
  Tmp_Pos := 1467;
  SplitString(Cmd.Cmd, HList);
  if HList.Count < 3 then Exit;
  SlavaNapInvitation.User := HList.Strings[0];
  SlavaNapInvitation.Channel := HList.Strings[1];
  SlavaNapInvitation.Topic := HList.Strings[2];
  Tmp_Pos := 1468;
  SlavaNapInvitation.Show;
  SlavaNapInvitation.Btn_Accept.SetFocus;
  Tmp_Pos := 1469;
end;

procedure Handler_Browse;
var
  Form: TSlavaNapBrowseWindow;
  Item: TListItem;
  PFileName: PString;
  function FormatSize(SizeStr: string): string;
  begin
    Result := FormatFloat('0,', StrToInt64Def(SizeStr, -1));
  end;
  function FormatFreq(FreqStr: string): string;
  begin
    Result := IntToStr(StrToInt64Def(FreqStr, -1) div 1000);
  end;
  function FormatSec(SecStr: string): string;
  begin
    Result := Time2Str(StrToInt64Def(SecStr, -1));
  end;
begin
  Tmp_Pos := 122621;
  SplitString(Cmd.Cmd, HList);
  // 宍幃: <nick> "<fileName>" <md5> <size> <bitrate> <frequency> <time>
  if HList.Count <> 7 then Exit;
  Tmp_Pos := 122622;
  Form := SlavaNapWindow.CreateBrowseWindow(HList.Strings[0]);
  Tmp_Pos := 122623;
  Item := Form.List.Items.Add;
  New(PFileName);
  Item.Data := PFileName;
  PFileName^ := HList.Strings[1];
  if Form.Show_Fullpath then
    Item.Caption := HList.Strings[1]
  else
    Item.Caption := ExtractFileName(HList.Strings[1]);
  Item.SubItems.Add(FormatSize(HList.Strings[3])); // Bytes
  Item.SubItems.Add(HList.Strings[4]); // Kbps
  Item.SubItems.Add(FormatFreq(HList.Strings[5])); // kHz
  Item.SubItems.Add(FormatSec(HList.Strings[6])); // Time
  Inc(Form.Shared);
  Inc(Form.Size, StrToInt64Def(HList.Strings[3], 0));
  Tmp_Pos := 122624;
end;

procedure Handler_Browse_end;
var
  Form: TSlavaNapBrowseWindow;
  Str: string;
begin
  // 宍幃: <nick> [ip] (嶲徠幐攕偺偲偒偼Ip偑曉傜側偄)
  Tmp_Pos := 122626;
  SplitString(Cmd.Cmd, HList);
  if HList.Count < 2 then Exit;
  Tmp_Pos := 122627;
  Form := SlavaNapWindow.CreateBrowseWindow(HList.Strings[0]);
  Form.Ip := HList.Strings[1];
  Form.Caption := Format(RS_Console_Browse_end, [HList.Strings[0],
    Decode_Ip(HList.Strings[1])]);
  Str := Format(RS_Console_Browse_Total, [Form.Shared, Form.Size div MegaByte]);
  Form.Status.Panels[0].Text := Str;
  Form.Status.Panels[0].Width := Form.Canvas.TextWidth(Str) + 20;
  Form.Show;
  Tmp_Pos := 122628;
end;

procedure ConsoleReply(Id: Integer; Str: string);
begin
  if not Running then Exit;
  Tmp_Pos := 1470;
  Cmd.Cmd := Str;
  Cmd.Id := Id;
  try
    case Id of
      MSG_SERVER_JOIN_ACK: Handler_JoinChannel;
      MSG_SERVER_JOIN, MSG_SERVER_CHANNEL_USER_LIST: Handler_ChannelAddUser;
      MSG_SERVER_TOPIC: Handler_ChannelTopic;
      MSG_SERVER_EMOTE: Handler_ChannelEmote;
      MSG_SERVER_PUBLIC: Handler_ChannelMessage;
      MSG_CLIENT_PART: Handler_PartChannel;
      MSG_SERVER_PART: Handler_ChannelRemoveUser;
      MSG_SERVER_ERROR, MSG_SERVER_NOSUCH: slavaNapWindow.LogConsole(slError,
        Str);
      MSG_SERVER_WALLOP: Handler_Wallop;
      MSG_SERVER_ANNOUNCE: SlavaNapWindow.LogConsole(slAnnounce, '<' +
        FirstParam(Str) + '> ' + NextParamEx(Str));
      MSG_SERVER_USER_SIGNON: ConsoleHotListOnline(Str);
      MSG_SERVER_USER_SIGNOFF: ConsoleListHotlist;
      MSG_CLIENT_PRIVMSG: Handler_PrivateMessage;
      MSG_SERVER_WHOWAS: Handler_Whowas;
      MSG_SERVER_WHOIS_RESPONSE: Handler_Whois;
      MSG_CLIENT_PING: Cmd_List.AddDoubleCmd(MSG_CLIENT_PONG, 0, Str, '');
      MSG_CLIENT_PONG: SlavaNapWindow.LogConsole(slPong,
        GetLangI(LNG_CONSOLEPONG, FirstParam(Str)));
      MSG_CLIENT_CHANNEL_INVITE: Handler_Invite;
      MSG_SERVER_CHANNEL_USER_LIST_END,
        214, 207, 208, 301, 322, 323:
        begin
        end;
      MSG_SERVER_BROWSE_RESPONSE: Handler_Browse;
      MSG_SERVER_BROWSE_END: Handler_Browse_end;
    else
      SlavaNapWindow.LogConsole(clBlack, 'Reply [' + IntToStr(Id) + '] : ' +
        Str);
    end;
  except
    DebugLog('Exception in ConsoleReply()  Pos=' + IntToStr(Tmp_Pos));
  end;
  Tmp_Pos := 1471;
end;

initialization
  begin
    HList := TMyStringList.Create;
  end;

finalization
  begin
    HList.Free;
    HList := nil;
  end;
end.
