/* Synchronet Control Panel (GUI Borland C++ Builder Project for Win32) */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * * Copyright Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * See the GNU General Public License for more details: gpl.txt or * * http://www.fsf.org/copyleft/gpl.html * * * * For Synchronet coding style and modification guidelines, see * * http://www.synchro.net/source.html * * * * Note: If this box doesn't appear square, then you need to fix your tabs. * ****************************************************************************/ //--------------------------------------------------------------------------- #include <vcl.h> #include <vcl/Clipbrd.hpp> #pragma hdrstop #include "LoginAttemptsFormUnit.h" #include "MainFormUnit.h" #include "CodeInputFormUnit.h" #include "userdat.h" #include "datewrap.h" #include "trash.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TLoginAttemptsForm *LoginAttemptsForm; extern link_list_t login_attempt_list; extern bool clearLoginAttemptList; //--------------------------------------------------------------------------- __fastcall TLoginAttemptsForm::TLoginAttemptsForm(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::FillListView(TObject *Sender) { char str[128]; TListItem* Item; list_node_t* node; struct tm tm; login_attempt_t* attempt; Screen->Cursor=crAppStart; listLock(&login_attempt_list); ListView->AllocBy=listCountNodes(&login_attempt_list); ListView->Items->BeginUpdate(); for(node=login_attempt_list.first; node!=NULL; node=node->next) { if(node->data == NULL) continue; if((attempt = (login_attempt_t*)malloc(sizeof(*attempt))) == NULL) continue; *attempt = *(login_attempt_t*)node->data; Item=ListView->Items->Add(); Item->Caption=AnsiString(attempt->count-attempt->dupes); Item->Data=(void*)attempt; Item->SubItems->Add(attempt->dupes); if(inet_addrtop(&attempt->addr, str, sizeof(str))==NULL) strcpy(str, "<invalid address>"); Item->SubItems->Add(str); Item->SubItems->Add(attempt->prot); Item->SubItems->Add(attempt->user); Item->SubItems->Add(attempt->pass); localtime_r(&attempt->time,&tm); sprintf(str,"%u/%u/%u %02u:%02u:%02u" ,tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec); Item->SubItems->Add(str); } ListView->AlphaSort(); ListView->Items->EndUpdate(); listUnlock(&login_attempt_list); Screen->Cursor=crDefault; } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::FormShow(TObject *Sender) { ColumnToSort=0; SortBackwards=true; FillListView(Sender); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::FormClose(TObject *Sender, TCloseAction &Action) { ListView->Items->BeginUpdate(); ListView->Items->Clear(); ListView->Items->EndUpdate(); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::ListViewColumnClick(TObject *Sender, TListColumn *Column) { if(Column->Index == ColumnToSort) SortBackwards=!SortBackwards; else SortBackwards=false; ColumnToSort = Column->Index; ((TCustomListView *)Sender)->AlphaSort(); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::ListViewCompare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &Compare) { /* Decimal compare */ if (ColumnToSort < 2 || ColumnToSort == 6) { int num1, num2; if(ColumnToSort==6 && Item1->Data && Item2->Data) { /* Date */ num1 = ((login_attempt_t*)Item1->Data)->time; num2 = ((login_attempt_t*)Item2->Data)->time; } else if(ColumnToSort==0) { num1=Item1->Caption.ToIntDef(0); num2=Item2->Caption.ToIntDef(0); } else { int ix = ColumnToSort - 1; num1=Item1->SubItems->Strings[ix].ToIntDef(0); num2=Item2->SubItems->Strings[ix].ToIntDef(0); } if(SortBackwards) Compare=(num2-num1); else Compare=(num1-num2); } else { int ix = ColumnToSort - 1; if(SortBackwards) Compare = CompareText(Item2->SubItems->Strings[ix] ,Item1->SubItems->Strings[ix]); else Compare = CompareText(Item1->SubItems->Strings[ix] ,Item2->SubItems->Strings[ix]); } } //--------------------------------------------------------------------------- static AnsiString ListItemString(TListItem* item) { AnsiString str = item->Caption; int i; for(i=0;i<item->SubItems->Count;i++) str += "\t" + item->SubItems->Strings[i]; return str + "\r\n"; } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::CopyPopupClick(TObject *Sender) { AnsiString buf; TItemStates State; State << isSelected; TListItem* ListItem = ListView->Selected; while(ListItem != NULL) { buf += ListItemString(ListItem); ListItem = ListView->GetNextItem(ListItem, sdAll, State); } Clipboard()->SetTextBuf(buf.c_str()); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::SelectAllPopupClick(TObject *Sender) { ListView->SelectAll(); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::RefreshPopupClick(TObject *Sender) { ListView->Items->BeginUpdate(); ListView->Items->Clear(); ListView->Items->EndUpdate(); FillListView(Sender); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::FilterIpMenuItemClick(TObject *Sender) { char str[256]; char fname[MAX_PATH + 1]; int res; bool repeat = false; TListItem* ListItem; TItemStates State; static uint duration = MainForm->global.login_attempt.filter_duration; static bool silent; static bool apply_all; ListItem=ListView->Selected; State << isSelected; Screen->Cursor=crHourGlass; ListView->Items->BeginUpdate(); while(ListItem!=NULL) { TListItem* NextItem = ListView->GetNextItem(ListItem,sdAll,State); AnsiString ip_addr = ListItem->SubItems->Strings[1]; if(!repeat) { Application->CreateForm(__classid(TCodeInputForm), &CodeInputForm); wsprintf(str,"Disallow future connections from %s?", ip_addr); CodeInputForm->Caption = str; CodeInputForm->Label->Caption = "Address Filter Duration"; CodeInputForm->Edit->Visible = true; CodeInputForm->Edit->Text = duration ? duration_to_vstr(duration, str, sizeof str) : "Infinite"; CodeInputForm->Edit->Hint = "'Infinite' or number of Seconds/Minutes/Hours/Days/Weeks/Years"; CodeInputForm->Edit->ShowHint = true; CodeInputForm->RightCheckBox->Visible = true; CodeInputForm->RightCheckBox->Caption = "Silent Filter"; CodeInputForm->RightCheckBox->Checked = silent; CodeInputForm->RightCheckBox->Hint = "No messages logged when blocking this client"; CodeInputForm->RightCheckBox->ShowHint = true; if(ListView->SelCount > 1) { CodeInputForm->LeftCheckBox->Visible = true; CodeInputForm->LeftCheckBox->Caption = "All Selected"; CodeInputForm->LeftCheckBox->Checked = apply_all; CodeInputForm->LeftCheckBox->Hint = "Filter all selected addresses"; CodeInputForm->LeftCheckBox->ShowHint = true; } res = CodeInputForm->ShowModal(); duration = parse_duration(CodeInputForm->Edit->Text.c_str()); silent = CodeInputForm->RightCheckBox->Checked; repeat = CodeInputForm->LeftCheckBox->Checked; apply_all = repeat; delete CodeInputForm; if(res != mrOk) break; } login_attempt_t* attempt = (login_attempt_t*)ListItem->Data; if(attempt != NULL) { char* hostname = NULL; struct in_addr addr = {}; addr.s_addr = inet_addr(ip_addr.c_str()); HOSTENT* h = gethostbyaddr((char *)&addr,sizeof(addr),AF_INET); if(h!=NULL) hostname = h->h_name; char tmp[128]; AnsiString reason = ListItem->Caption + AnsiString(" " STR_FAILED_LOGIN_ATTEMPTS " in "); reason += duration_estimate_to_str(attempt->time - attempt->first, tmp, sizeof tmp, 1, 1); if(filter_ip(&MainForm->cfg, attempt->prot, reason.c_str(), hostname ,ip_addr.c_str(), attempt->user ,trashcan_fname(&MainForm->cfg, silent ? "ip-silent" : "ip", fname, sizeof fname) ,duration)) { loginSuccess(&login_attempt_list, &attempt->addr); ListItem->Delete(); } } ListItem = NextItem; } ListView->Items->EndUpdate(); Screen->Cursor=crDefault; } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::ResolveHostnameMenuItemClick( TObject *Sender) { char str[256]; int res; TListItem* ListItem; TItemStates State; ListItem=ListView->Selected; State << isSelected; while(ListItem!=NULL) { struct in_addr addr; HOSTENT* h; char* ip_addr=ListItem->SubItems->Strings[1].c_str(); char* hostname="<unknown>"; addr.s_addr=inet_addr(ip_addr); Screen->Cursor=crHourGlass; h=gethostbyaddr((char *)&addr,sizeof(addr),AF_INET); Screen->Cursor=crDefault; if(h!=NULL) hostname = h->h_name; wsprintf(str,"%s hostname is %s", ip_addr, hostname); Application->MessageBox(str, "Hostname Lookup", MB_OK|MB_ICONINFORMATION); if(ListView->Selected == NULL) break; ListItem=ListView->GetNextItem(ListItem,sdAll,State); } } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::ClearListMenuItemClick(TObject *Sender) { clearLoginAttemptList = true; ListView->Items->BeginUpdate(); ListView->Items->Clear(); ListView->Items->EndUpdate(); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::ListViewDeletion(TObject *Sender, TListItem *Item) { free(Item->Data); } //--------------------------------------------------------------------------- void __fastcall TLoginAttemptsForm::Remove1Click(TObject *Sender) { TItemStates State; TListItem* ListItem = ListView->Selected; State << isSelected; Screen->Cursor=crHourGlass; ListView->Items->BeginUpdate(); while (ListItem != NULL) { TListItem* NextItem = ListView->GetNextItem(ListItem, sdAll, State); login_attempt_t* attempt = (login_attempt_t*)ListItem->Data; if(attempt != NULL) { loginSuccess(&login_attempt_list, &attempt->addr); ListItem->Delete(); } ListItem = NextItem; } ListView->Items->EndUpdate(); Screen->Cursor=crDefault; } //---------------------------------------------------------------------------