⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 banlistupdate.cpp

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
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 + -