📄 banlistupdate.cpp
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.com>
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
//---------------------------------------------------------------------------
#include <vcl.h>
#include <KCeasy.h>
#pragma hdrstop
#include <stdio.h>
#include "AboutDialog.h" // version
#include "BanlistUpdate.h"
#include "zlib.h"
#include "Sha1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//TBanlistUpdateForm *BanlistUpdateForm;
//---------------------------------------------------------------------------
typedef struct
{
char* DisplayName;
char* Network;
char* Url;
char* LocalPath; // relative to gift dir
bool Checked; // if item is selected for download by default
} TUpdateFiles;
// relative to KCeasy dir
static const char TEMP_FILE_PATH[] = "\\banlist.tmp";
//---------------------------------------------------------------------------
TUpdateFile::TUpdateFile(const string& NNetwork)
: Network(NNetwork),
LastUpdate(0),
UpdateOnInstall(false)
{
}
TUpdateFile::~TUpdateFile()
{
}
bool TUpdateFile::Parse(const string& ConfStr)
{
// <display name>|<type>|<last update>|<filename>|<url>|<update on install>
// <compression>|<challenge range>
list<string> Fields = string_split(ConfStr,"|");
list<string>::iterator CurrField = Fields.begin();
if(Fields.size() < 8)
return false;
DisplayName = string_trim(*CurrField); ++CurrField;
Type = string_trim(*CurrField); ++CurrField;
LastUpdate = string_to_int(*CurrField); ++CurrField;
FileName = string_trim(*CurrField); ++CurrField;
Url = string_trim(*CurrField); ++CurrField;
UpdateOnInstall = string_to_int(*CurrField); ++CurrField;
unsigned int Compress = string_to_int(*CurrField); ++CurrField;
string Challenge = string_trim(*CurrField); ++CurrField;
// parse compression type
switch (Compress)
{
case 0: Compression = CompressNone; break;
case 1: Compression = CompressGzip; break;
default: return false;
}
// parse challenge range
ChallengeStart = 0;
ChallengeStop = 0;
list<string> Range = string_split(Challenge,"-");
if (Range.size() == 2) {
ChallengeStart = string_to_int(Range.front());
ChallengeStop = string_to_int(Range.back());
}
return true;
}
//---------------------------------------------------------------------------
__fastcall TBanlistUpdateForm::TBanlistUpdateForm(TComponent* Owner,
bool FirstInstall)
: TForm(Owner),
Download(NULL),
UpdateFinished(false),
Automatic(FirstInstall)
{
TranslateComponent(this);
Caption = Brand->ReplaceAppName(Caption);
CurrentFileItr = UpdateFiles.end();
UpdateBtn->Enabled = false;
CancelBtn->Enabled = true;
ImportantLbl->Visible = !Automatic;
FilesLbl->Visible = !Automatic;
TempFilePath = Application->ExeName.c_str();
TempFilePath.erase(TempFilePath.rfind('\\'));
TempFilePath += TEMP_FILE_PATH;
FilesListView->Items->Clear();
FilesListView->Checkboxes = false;
TListItem* Item = FilesListView->Items->Add();
// TRANSLATOR: list view entry shown when getting list of files for banlist update
Item->Caption = _("Retrieving file list...");
Item->ImageIndex = -1;
// load local file list if not in automatic mode
if(!Automatic) {
string ConfPath = Application->ExeName.c_str();
ConfPath.erase(ConfPath.rfind('\\'));
AddFilesFromConfig(ConfPath + BANLISTS_CONF_PATH);
}
// start remote file list download
Download = new THttpDownload(this->Handle, WM_LISTRETRIEVE_CB);
string Url = Brand->GetBanlistUpdateUrl();
Url += (Url.find('?') == -1) ? "?" : "&";
Url += Brand->GetUrlSignature();
if(!Download->Start(Url,TempFilePath)) {
Download->Release();
Download = NULL;
// populate list view with local data and wait for user to select files
PopulateListView();
return;
}
// wait for download to complete / fail
}
__fastcall TBanlistUpdateForm::~TBanlistUpdateForm()
{
if(Download)
Download->Cancel();
while(!UpdateFiles.empty()) {
delete UpdateFiles.front();
UpdateFiles.pop_front();
}
}
//---------------------------------------------------------------------------
void __fastcall TBanlistUpdateForm::WMListRetrieveCb(TMessage& Msg)
{
THttpDownload* Dl = (THttpDownload*)Msg.WParam;
switch(Dl->GetState()) {
case HttpDownloadActive:
break;
case HttpDownloadCancelling:
break;
case HttpDownloadCancelled:
// release download
Dl->Release();
// do nothing else since the dialog was already closed by the cancel button
break;
case HttpDownloadCompleted:
// try to get files from downloaded config
AddFilesFromConfig(Dl->GetSavePath());
// fall through
case HttpDownloadFailed:
// remove temp file
::DeleteFile(Dl->GetSavePath().c_str());
// release download
Dl->Release();
Download = NULL;
// populate list view and wait for user to select files
PopulateListView();
break;
}
}
bool TBanlistUpdateForm::AddFilesFromConfig(const string& Path)
{
// add all files from config to file list
TFileConfig* Conf = new TFileConfig(Path);
if(!Conf->Load()) {
delete Conf;
return false;
}
// get a list of all sections
list<string> Sections = Conf->GetSections();
for(list<string>::iterator si = Sections.begin(); si != Sections.end(); ++si) {
// prepare plugin path
string PluginPath = string_trim(*si);
if(PluginPath == "")
continue;
// special case for "giFT"
if(PluginPath == "giFT")
PluginPath = Engine->GetLauncher()->GetConfPath();
else
PluginPath = Engine->GetLauncher()->GetConfPath() + "\\" + PluginPath;
// check if plugin for this network is installed
DWORD PathAttrib = ::GetFileAttributes(PluginPath.c_str());
if(PathAttrib == 0xFFFFFFFF || !(PathAttrib & FILE_ATTRIBUTE_DIRECTORY))
continue;
// get a list of all names in section
list<string> Names = Conf->GetNames(*si);
for(list<string>::iterator ni = Names.begin(); ni != Names.end(); ++ni) {
TUpdateFile* File = new TUpdateFile(*si);
if(File->Parse(Conf->GetValue((*si) + "/" + (*ni)))) {
// File.FileName must not contain directory elements
if(File->FileName.find_first_of("\\/") == -1) {
// make absolute path
File->SavePath = PluginPath + "\\" + File->FileName;
// add file to list
UpdateFiles.push_back(File);
continue;
}
}
delete File;
}
}
delete Conf;
return true;
}
void TBanlistUpdateForm::PopulateListView()
{
// populate list view
FilesListView->Items->Clear();
// if there are no files tell the user, otherwise proceed
if(UpdateFiles.empty()) {
TListItem* Item = FilesListView->Items->Add();
// TRANSLATOR: list view entry shown when there are no files for banlist update
Item->Caption = _("Error: No files available");
Item->ImageIndex = -1;
// if we are in automatic mode just quit if we cannot find any files
if(Automatic)
ModalResult = mrCancel;
return;
}
FilesListView->Items->Clear();
FilesListView->Checkboxes = true;
for(list<TUpdateFile*>::iterator itr = UpdateFiles.begin(); itr != UpdateFiles.end(); ++itr) {
TListItem* Item = FilesListView->Items->Add();
Item->Data = (void*)(*itr);
Item->Caption = (*itr)->DisplayName.c_str();
Item->ImageIndex = MainForm->IconManager->GetNetworkIconIndex((*itr)->Network);
Item->SubItems->Add(GetFileStatus(*itr));
Item->SubItems->Add((*itr)->Network.c_str());
Item->SubItems->Add((*itr)->FileName.c_str());
Item->Checked = Automatic && (*itr)->UpdateOnInstall;
}
// if we are in automatic mode immediately start download otherwise wait
// for user to select files
if(Automatic)
UpdateBtnClick(NULL);
else
UpdateBtn->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TBanlistUpdateForm::UpdateBtnClick(TObject *Sender)
{
// if we already updated this button is for closing
if(UpdateFinished) {
ModalResult = mrOk;
return;
}
// otherwise start update
FilesListView->Enabled = false;
UpdateBtn->Enabled = false;
UpdatedFiles = 0;
UpdateErrors = 0;
CurrentFileItr = UpdateFiles.end();
UpdateNextFile();
}
void __fastcall TBanlistUpdateForm::CancelBtnClick(TObject *Sender)
{
ModalResult = mrCancel;
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -