<commit_before>#include "upgrade.h"
#include "util.h"
#include "init.h"

#include <algorithm>
#include <univalue.h>
#include <vector>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/exception/exception.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <ostream>
#include <iostream>

#include <zip.h>
#include <fstream>
#include <openssl/sha.h>

struct_SnapshotExtractStatus ExtractStatus;

bool fCancelOperation = false;

Upgrade::Upgrade()
{
    // Clear the structs
    DownloadStatus.SnapshotDownloadSize = 0;
    DownloadStatus.SnapshotDownloadSpeed = 0;
    DownloadStatus.SnapshotDownloadAmount = 0;
    DownloadStatus.SnapshotDownloadFailed = false;
    DownloadStatus.SnapshotDownloadComplete = false;
    DownloadStatus.SnapshotDownloadProgress = 0;
    ExtractStatus.SnapshotExtractFailed = false;
    ExtractStatus.SnapshotExtractComplete = false;
    ExtractStatus.SnapshotExtractProgress = 0;
}

void Upgrade::CheckForLatestUpdate()
{
    // If testnet skip this || If the user changes this to disable while wallet running just drop out of here now. (need a way to remove items from scheduler)
    if (fTestNet || GetBoolArg("-disableupdatecheck", false))
        return;

    Http VersionPull;

    std::string GithubResponse = "";
    std::string VersionResponse = "";

    // We receive the response and it's in a json reply
    UniValue Response(UniValue::VOBJ);

    try
    {
        VersionResponse = VersionPull.GetLatestVersionResponse();
    }

    catch (const std::runtime_error& e)
    {
        LogPrintf("Update Checker: Exception occured while checking for latest update. (%s)", e.what());

        return;
    }

    if (VersionResponse.empty())
    {
        LogPrintf("Update Checker: No Response from github");

        return;
    }

    std::string GithubReleaseData = "";
    std::string GithubReleaseTypeData = "";
    std::string GithubReleaseBody = "";
    std::string GithubReleaseType = "";

    try
    {
        Response.read(VersionResponse);

        // Get the information we need:
        // 'body' for information about changes
        // 'tag_name' for version
        // 'name' for checking if its a mandatory or leisure
        GithubReleaseData = find_value(Response, "tag_name").get_str();
        GithubReleaseTypeData = find_value(Response, "name").get_str();
        GithubReleaseBody = find_value(Response, "body").get_str();
    }

    catch (std::exception& ex)
    {
        LogPrintf("Update Checker: Exception occured while parsing json response (%s)", ex.what());

        return;
    }

    if (GithubReleaseTypeData.find("leisure"))
        GithubReleaseType = _("leisure");

    else if (GithubReleaseTypeData.find("mandatory"))
        GithubReleaseType = _("mandatory");

    else
        GithubReleaseType = _("unknown");

    // Parse version data
    std::vector<std::string> GithubVersion;
    std::vector<int> LocalVersion;

    ParseString(GithubReleaseData, '.', GithubVersion);

    LocalVersion.push_back(CLIENT_VERSION_MAJOR);
    LocalVersion.push_back(CLIENT_VERSION_MINOR);
    LocalVersion.push_back(CLIENT_VERSION_REVISION);

    if (GithubVersion.size() != 4)
    {
        LogPrintf("Update Check: Got malformed version (%s)", GithubReleaseData);

        return;
    }

    bool NewVersion = false;

    try {
        // Left to right version numbers.
        // 3 numbers to check for production.
        for (unsigned int x = 0; x < 3; x++)
        {
            if (NewVersion)
                break;

            if (std::stoi(GithubVersion[x]) > LocalVersion[x])
                NewVersion = true;
        }
    }
    catch (std::exception& ex)
    {
        LogPrintf("Update Check: Exception occured checking client version against github version (%s)", ToString(ex.what()));

        return;
    }

    if (!NewVersion)
        return;

    // New version was found
    std::string ClientMessage = _("Local version: ") + strprintf("%d.%d.%d.%d", CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) + "\r\n";
    ClientMessage.append(_("Github version: ") + GithubReleaseData + "\r\n");
    ClientMessage.append(_("This update is ") + GithubReleaseType + "\r\n\r\n");

    std::string ChangeLog = GithubReleaseBody;

    uiInterface.UpdateMessageBox(ClientMessage, ChangeLog);

    return;
}

void Upgrade::SnapshotMain()
{
    std::cout << std::endl;
    std::cout << _("Snapshot Process Has Begun.") << std::endl;
    std::cout << _("Warning: Ending this process after Stage 2 will result in syncing from 0 or an incomplete/corrupted blockchain.") << std::endl << std::endl;

    // Create a thread for snapshot to be downloaded
    boost::thread SnapshotDownloadThread(std::bind(&Upgrade::DownloadSnapshot, this));

    Progress Prog;

    Prog.SetType(0);

    while (!DownloadStatus.SnapshotDownloadComplete)
    {
        if (DownloadStatus.SnapshotDownloadFailed)
            throw std::runtime_error("Failed to download snapshot.zip; See debug.log");

        if (Prog.Update(DownloadStatus.SnapshotDownloadProgress, DownloadStatus.SnapshotDownloadSpeed, DownloadStatus.SnapshotDownloadAmount, DownloadStatus.SnapshotDownloadSize))
            std::cout << Prog.Status() << std::flush;

        MilliSleep(1000);
    }

    // This is needed in some spots as the download can complete before the next progress update occurs so just 100% here as it was successful
    if (Prog.Update(100, -1, DownloadStatus.SnapshotDownloadSize, DownloadStatus.SnapshotDownloadSize))
        std::cout << Prog.Status() << std::flush;

    std::cout << std::endl;

    Prog.SetType(1);

    if (VerifySHA256SUM())
    {
        Prog.Update(100);

        std::cout << Prog.Status() << std::flush;
    }

    else
        throw std::runtime_error("Failed to verify SHA256SUM of snapshot.zip; See debug.log");

    std::cout << std::endl;

    Prog.SetType(2);

    if (CleanupBlockchainData())
    {
        Prog.Update(100);

        std::cout << Prog.Status() << std::flush;
    }

    else
        throw std::runtime_error("Failed to Cleanup previous blockchain data; See debug.log");

    std::cout << std::endl;

    Prog.SetType(3);

    // Create a thread for snapshot to be extracted
    boost::thread SnapshotExtractThread(std::bind(&Upgrade::ExtractSnapshot, this));

    while (!ExtractStatus.SnapshotExtractComplete)
    {
        if (ExtractStatus.SnapshotExtractFailed)
        {
            // Do this without checking on sucess, If it passed in stage 3 it will pass here.
            CleanupBlockchainData();

            throw std::runtime_error("Failed to extract snapshot.zip; See debug.log");
        }

        if (Prog.Update(ExtractStatus.SnapshotExtractProgress))
            std::cout << Prog.Status() << std::flush;

        MilliSleep(1000);
    }

    if (Prog.Update(100))
        std::cout << Prog.Status() << std::flush;

    std::cout << std::endl;
    std::cout << _("Snapshot Process Complete!") << std::endl;

    return;
}

void Upgrade::DownloadSnapshot()
{
     // Download the snapshot.zip
    Http HTTPHandler;

    try
    {
        HTTPHandler.DownloadSnapshot();
    }

    catch(std::runtime_error& e)
    {
        LogPrintf("Snapshot Downloader: Exception occured while attempting to download snapshot (%s)", e.what());

        DownloadStatus.SnapshotDownloadFailed = true;
    }

    return;
}

bool Upgrade::VerifySHA256SUM()
{
    Http HTTPHandler;

    std::string ServerSHA256SUM = "";

    try
    {
        ServerSHA256SUM = HTTPHandler.GetSnapshotSHA256();
    }

    catch (std::runtime_error& e)
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Exception occured while attempting to retrieve snapshot SHA256SUM (%s)", e.what());
    }

    if (ServerSHA256SUM.empty())
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Empty sha256sum returned from server");

        return false;
    }

    unsigned char digest[SHA256_DIGEST_LENGTH];

    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    boost::filesystem::path fileloc = GetDataDir() / "snapshot.zip";
    unsigned char *buffer[32768];
    int bytesread = 0;

    FILE *file = fsbridge::fopen(fileloc, "rb");

    if (!file)
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Failed to open snapshot.zip");

        return false;
    }

    while ((bytesread = fread(buffer, 1, sizeof(buffer), file)))
        SHA256_Update(&ctx, buffer, bytesread);

    SHA256_Final(digest, &ctx);

    char mdString[SHA256_DIGEST_LENGTH*2+1];

    for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
        sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);

    std::string FileSHA256SUM = {mdString};

    if (ServerSHA256SUM == FileSHA256SUM)
        return true;

    else
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Mismatch of sha256sum of snapshot.zip (Server = %s / File = %s)", ServerSHA256SUM, FileSHA256SUM);

        return false;
    }
}

bool Upgrade::CleanupBlockchainData()
{
    boost::filesystem::path CleanupPath = GetDataDir();

    // We must delete previous blockchain data
    // txleveldb
    // blk*.dat
    boost::filesystem::directory_iterator IterEnd;

    try
    {
        // Remove the files. We iterate as we know blk* will exist more and more in future as well
        for (boost::filesystem::directory_iterator Iter(CleanupPath); Iter != IterEnd; ++Iter)
        {
            if (boost::filesystem::is_directory(Iter->path()))
            {
                size_t DirLoc = Iter->path().string().find("txleveldb");

                if (DirLoc != std::string::npos)
                    if (!boost::filesystem::remove_all(*Iter))
                        return false;

                continue;

            }

            else if (boost::filesystem::is_regular_file(*Iter))
            {
                size_t FileLoc = Iter->path().filename().string().find("blk");

                if (FileLoc != std::string::npos)
                {
                    std::string filetocheck = Iter->path().filename().string();
                    // Check it ends with .dat and starts with blk
                    if (filetocheck.substr(0, 3) == "blk" && filetocheck.substr(filetocheck.length() - 4, 4) == ".dat")
                        if (!boost::filesystem::remove(*Iter))
                            return false;
                }
                continue;
            }
        }
    }

    catch (boost::filesystem::filesystem_error &ex)
    {
        LogPrintf("Snapshot (CleanupBlockchainData): Exception occured: %s", ex.what());

        return false;
    }

    return true;
}

bool Upgrade::ExtractSnapshot()
{
    std::string ArchiveFileString = GetDataDir().string() +  "/snapshot.zip";
    const char* ArchiveFile = ArchiveFileString.c_str();
    boost::filesystem::path ExtractPath = GetDataDir();
    struct zip* ZipArchive;
    struct zip_file* ZipFile;
    struct zip_stat ZipStat;
    char Buf[1024*1024];
    int err;
    uint64_t i, j;
    int64_t entries, len, sum;
    long long totaluncompressedsize = 0;
    long long currentuncompressedsize = 0;
    int64_t lastupdated = GetAdjustedTime();

    try
    {
        ZipArchive = zip_open(ArchiveFile, 0, &err);

        if (ZipArchive == nullptr)
        {
            zip_error_to_str(Buf, sizeof(Buf), err, errno);

            ExtractStatus.SnapshotExtractFailed = true;

            LogPrintf("Snapshot (ExtractSnapshot): Error opening snapshot.zip: %s", Buf);

            return false;
        }

        entries = zip_get_num_entries(ZipArchive, 0);

        // Lets scan for total size uncompressed so we can do a detailed progress for the watching user
        for (j = 0; j < (uint64_t)entries; j++)
        {
            if (zip_stat_index(ZipArchive, j, 0, &ZipStat) == 0)
            {
                if (ZipStat.name[strlen(ZipStat.name) - 1] != '/')
                    totaluncompressedsize += ZipStat.size;
            }
        }

        // Now extract
        for (i = 0; i < (uint64_t)entries; i++)
        {
            if (zip_stat_index(ZipArchive, i, 0, &ZipStat) == 0)
            {
                // Does this require a directory
                if (ZipStat.name[strlen(ZipStat.name) - 1] == '/')
                    boost::filesystem::create_directory(ExtractPath / ZipStat.name);

                else
                {
                    ZipFile = zip_fopen_index(ZipArchive, i, 0);

                    if (!ZipFile)
                    {
                        ExtractStatus.SnapshotExtractFailed = true;

                        LogPrintf("Snapshot (ExtractSnapshot): Error opening file %s within snapshot.zip", ZipStat.name);

                        return false;
                    }

                    boost::filesystem::path ExtractFileString = ExtractPath / ZipStat.name;

                    FILE* ExtractFile = fsbridge::fopen(ExtractFileString, "wb");

                    if (!ExtractFile)
                    {
                        ExtractStatus.SnapshotExtractFailed = true;

                        LogPrintf("Snapshot (ExtractSnapshot): Error opening file %s on filesystem", ZipStat.name);

                        return false;
                    }

                    sum = 0;

                    while ((uint64_t)sum != ZipStat.size)
                    {
                        boost::this_thread::interruption_point();

                        len = zip_fread(ZipFile, Buf, 1024*1024);

                        if (len < 0)
                        {
                            ExtractStatus.SnapshotExtractFailed = true;

                            LogPrintf("Snapshot (ExtractSnapshot): Failed to read zip buffer");

                            return false;
                        }

                        fwrite(Buf, 1, (uint64_t)len, ExtractFile);

                        sum += len;
                        currentuncompressedsize += len;

                        // Update Progress every 1 second
                        if (GetAdjustedTime() > lastupdated)
                        {
                            lastupdated = GetAdjustedTime();

                            ExtractStatus.SnapshotExtractProgress = ((currentuncompressedsize / (double)totaluncompressedsize) * 100);
                        }
                    }

                    fclose(ExtractFile);
                    zip_fclose(ZipFile);
                }
            }
        }

        if (zip_close(ZipArchive) == -1)
        {
            ExtractStatus.SnapshotExtractFailed = true;

            LogPrintf("Sanpshot (ExtractSnapshot): Failed to close snapshot.zip");

            return false;
        }

        ExtractStatus.SnapshotExtractComplete = true;
    }

    catch (boost::thread_interrupted&)
    {
        return false;
    }

    return true;
}

void Upgrade::DeleteSnapshot()
{
    // File is out of scope now check if it exists and if so delete it.
    // This covers partial downloaded files or a http response downloaded into file.
    std::string snapshotfile = GetArg("-snapshoturl", "https://download.gridcoin.us/download/downloadstake/signed/snapshot.zip");

    size_t pos = snapshotfile.find_last_of("/");

    snapshotfile = snapshotfile.substr(pos + 1, (snapshotfile.length() - pos - 1));

    try
    {
        boost::filesystem::path snapshotpath = GetDataDir() / snapshotfile;

        if (boost::filesystem::exists(snapshotpath))
            if (boost::filesystem::is_regular_file(snapshotpath))
                boost::filesystem::remove(snapshotpath);
    }

    catch (boost::filesystem::filesystem_error& e)
    {
        LogPrintf("Snapshot Downloader: Exception occured while attempting to delete snapshot (%s)", e.code().message());
    }
}
<commit_msg>Possible fix to windows issue; close file in sha256sum verification function<commit_after>#include "upgrade.h"
#include "util.h"
#include "init.h"

#include <algorithm>
#include <univalue.h>
#include <vector>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/exception/exception.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <ostream>
#include <iostream>

#include <zip.h>
#include <fstream>
#include <openssl/sha.h>

struct_SnapshotExtractStatus ExtractStatus;

bool fCancelOperation = false;

Upgrade::Upgrade()
{
    // Clear the structs
    DownloadStatus.SnapshotDownloadSize = 0;
    DownloadStatus.SnapshotDownloadSpeed = 0;
    DownloadStatus.SnapshotDownloadAmount = 0;
    DownloadStatus.SnapshotDownloadFailed = false;
    DownloadStatus.SnapshotDownloadComplete = false;
    DownloadStatus.SnapshotDownloadProgress = 0;
    ExtractStatus.SnapshotExtractFailed = false;
    ExtractStatus.SnapshotExtractComplete = false;
    ExtractStatus.SnapshotExtractProgress = 0;
}

void Upgrade::CheckForLatestUpdate()
{
    // If testnet skip this || If the user changes this to disable while wallet running just drop out of here now. (need a way to remove items from scheduler)
    if (fTestNet || GetBoolArg("-disableupdatecheck", false))
        return;

    Http VersionPull;

    std::string GithubResponse = "";
    std::string VersionResponse = "";

    // We receive the response and it's in a json reply
    UniValue Response(UniValue::VOBJ);

    try
    {
        VersionResponse = VersionPull.GetLatestVersionResponse();
    }

    catch (const std::runtime_error& e)
    {
        LogPrintf("Update Checker: Exception occured while checking for latest update. (%s)", e.what());

        return;
    }

    if (VersionResponse.empty())
    {
        LogPrintf("Update Checker: No Response from github");

        return;
    }

    std::string GithubReleaseData = "";
    std::string GithubReleaseTypeData = "";
    std::string GithubReleaseBody = "";
    std::string GithubReleaseType = "";

    try
    {
        Response.read(VersionResponse);

        // Get the information we need:
        // 'body' for information about changes
        // 'tag_name' for version
        // 'name' for checking if its a mandatory or leisure
        GithubReleaseData = find_value(Response, "tag_name").get_str();
        GithubReleaseTypeData = find_value(Response, "name").get_str();
        GithubReleaseBody = find_value(Response, "body").get_str();
    }

    catch (std::exception& ex)
    {
        LogPrintf("Update Checker: Exception occured while parsing json response (%s)", ex.what());

        return;
    }

    if (GithubReleaseTypeData.find("leisure"))
        GithubReleaseType = _("leisure");

    else if (GithubReleaseTypeData.find("mandatory"))
        GithubReleaseType = _("mandatory");

    else
        GithubReleaseType = _("unknown");

    // Parse version data
    std::vector<std::string> GithubVersion;
    std::vector<int> LocalVersion;

    ParseString(GithubReleaseData, '.', GithubVersion);

    LocalVersion.push_back(CLIENT_VERSION_MAJOR);
    LocalVersion.push_back(CLIENT_VERSION_MINOR);
    LocalVersion.push_back(CLIENT_VERSION_REVISION);

    if (GithubVersion.size() != 4)
    {
        LogPrintf("Update Check: Got malformed version (%s)", GithubReleaseData);

        return;
    }

    bool NewVersion = false;

    try {
        // Left to right version numbers.
        // 3 numbers to check for production.
        for (unsigned int x = 0; x < 3; x++)
        {
            if (NewVersion)
                break;

            if (std::stoi(GithubVersion[x]) > LocalVersion[x])
                NewVersion = true;
        }
    }
    catch (std::exception& ex)
    {
        LogPrintf("Update Check: Exception occured checking client version against github version (%s)", ToString(ex.what()));

        return;
    }

    if (!NewVersion)
        return;

    // New version was found
    std::string ClientMessage = _("Local version: ") + strprintf("%d.%d.%d.%d", CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) + "\r\n";
    ClientMessage.append(_("Github version: ") + GithubReleaseData + "\r\n");
    ClientMessage.append(_("This update is ") + GithubReleaseType + "\r\n\r\n");

    std::string ChangeLog = GithubReleaseBody;

    uiInterface.UpdateMessageBox(ClientMessage, ChangeLog);

    return;
}

void Upgrade::SnapshotMain()
{
    std::cout << std::endl;
    std::cout << _("Snapshot Process Has Begun.") << std::endl;
    std::cout << _("Warning: Ending this process after Stage 2 will result in syncing from 0 or an incomplete/corrupted blockchain.") << std::endl << std::endl;

    // Create a thread for snapshot to be downloaded
    boost::thread SnapshotDownloadThread(std::bind(&Upgrade::DownloadSnapshot, this));

    Progress Prog;

    Prog.SetType(0);

    while (!DownloadStatus.SnapshotDownloadComplete)
    {
        if (DownloadStatus.SnapshotDownloadFailed)
            throw std::runtime_error("Failed to download snapshot.zip; See debug.log");

        if (Prog.Update(DownloadStatus.SnapshotDownloadProgress, DownloadStatus.SnapshotDownloadSpeed, DownloadStatus.SnapshotDownloadAmount, DownloadStatus.SnapshotDownloadSize))
            std::cout << Prog.Status() << std::flush;

        MilliSleep(1000);
    }

    // This is needed in some spots as the download can complete before the next progress update occurs so just 100% here as it was successful
    if (Prog.Update(100, -1, DownloadStatus.SnapshotDownloadSize, DownloadStatus.SnapshotDownloadSize))
        std::cout << Prog.Status() << std::flush;

    std::cout << std::endl;

    Prog.SetType(1);

    if (VerifySHA256SUM())
    {
        Prog.Update(100);

        std::cout << Prog.Status() << std::flush;
    }

    else
        throw std::runtime_error("Failed to verify SHA256SUM of snapshot.zip; See debug.log");

    std::cout << std::endl;

    Prog.SetType(2);

    if (CleanupBlockchainData())
    {
        Prog.Update(100);

        std::cout << Prog.Status() << std::flush;
    }

    else
        throw std::runtime_error("Failed to Cleanup previous blockchain data; See debug.log");

    std::cout << std::endl;

    Prog.SetType(3);

    // Create a thread for snapshot to be extracted
    boost::thread SnapshotExtractThread(std::bind(&Upgrade::ExtractSnapshot, this));

    while (!ExtractStatus.SnapshotExtractComplete)
    {
        if (ExtractStatus.SnapshotExtractFailed)
        {
            // Do this without checking on sucess, If it passed in stage 3 it will pass here.
            CleanupBlockchainData();

            throw std::runtime_error("Failed to extract snapshot.zip; See debug.log");
        }

        if (Prog.Update(ExtractStatus.SnapshotExtractProgress))
            std::cout << Prog.Status() << std::flush;

        MilliSleep(1000);
    }

    if (Prog.Update(100))
        std::cout << Prog.Status() << std::flush;

    std::cout << std::endl;
    std::cout << _("Snapshot Process Complete!") << std::endl;

    return;
}

void Upgrade::DownloadSnapshot()
{
     // Download the snapshot.zip
    Http HTTPHandler;

    try
    {
        HTTPHandler.DownloadSnapshot();
    }

    catch(std::runtime_error& e)
    {
        LogPrintf("Snapshot Downloader: Exception occured while attempting to download snapshot (%s)", e.what());

        DownloadStatus.SnapshotDownloadFailed = true;
    }

    return;
}

bool Upgrade::VerifySHA256SUM()
{
    Http HTTPHandler;

    std::string ServerSHA256SUM = "";

    try
    {
        ServerSHA256SUM = HTTPHandler.GetSnapshotSHA256();
    }

    catch (std::runtime_error& e)
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Exception occured while attempting to retrieve snapshot SHA256SUM (%s)", e.what());
    }

    if (ServerSHA256SUM.empty())
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Empty sha256sum returned from server");

        return false;
    }

    unsigned char digest[SHA256_DIGEST_LENGTH];

    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    boost::filesystem::path fileloc = GetDataDir() / "snapshot.zip";
    unsigned char *buffer[32768];
    int bytesread = 0;

    FILE *file = fsbridge::fopen(fileloc, "rb");

    if (!file)
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Failed to open snapshot.zip");

        return false;
    }

    while ((bytesread = fread(buffer, 1, sizeof(buffer), file)))
        SHA256_Update(&ctx, buffer, bytesread);

    SHA256_Final(digest, &ctx);

    char mdString[SHA256_DIGEST_LENGTH*2+1];

    for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
        sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);

    std::string FileSHA256SUM = {mdString};

    fclose(file);

    if (ServerSHA256SUM == FileSHA256SUM)
        return true;

    else
    {
        LogPrintf("Snapshot (VerifySHA256SUM): Mismatch of sha256sum of snapshot.zip (Server = %s / File = %s)", ServerSHA256SUM, FileSHA256SUM);

        return false;
    }
}

bool Upgrade::CleanupBlockchainData()
{
    boost::filesystem::path CleanupPath = GetDataDir();

    // We must delete previous blockchain data
    // txleveldb
    // blk*.dat
    boost::filesystem::directory_iterator IterEnd;

    try
    {
        // Remove the files. We iterate as we know blk* will exist more and more in future as well
        for (boost::filesystem::directory_iterator Iter(CleanupPath); Iter != IterEnd; ++Iter)
        {
            if (boost::filesystem::is_directory(Iter->path()))
            {
                size_t DirLoc = Iter->path().string().find("txleveldb");

                if (DirLoc != std::string::npos)
                    if (!boost::filesystem::remove_all(*Iter))
                        return false;

                continue;

            }

            else if (boost::filesystem::is_regular_file(*Iter))
            {
                size_t FileLoc = Iter->path().filename().string().find("blk");

                if (FileLoc != std::string::npos)
                {
                    std::string filetocheck = Iter->path().filename().string();
                    // Check it ends with .dat and starts with blk
                    if (filetocheck.substr(0, 3) == "blk" && filetocheck.substr(filetocheck.length() - 4, 4) == ".dat")
                        if (!boost::filesystem::remove(*Iter))
                            return false;
                }
                continue;
            }
        }
    }

    catch (boost::filesystem::filesystem_error &ex)
    {
        LogPrintf("Snapshot (CleanupBlockchainData): Exception occured: %s", ex.what());

        return false;
    }

    return true;
}

bool Upgrade::ExtractSnapshot()
{
    std::string ArchiveFileString = GetDataDir().string() +  "/snapshot.zip";
    const char* ArchiveFile = ArchiveFileString.c_str();
    boost::filesystem::path ExtractPath = GetDataDir();
    struct zip* ZipArchive;
    struct zip_file* ZipFile;
    struct zip_stat ZipStat;
    char Buf[1024*1024];
    int err;
    uint64_t i, j;
    int64_t entries, len, sum;
    long long totaluncompressedsize = 0;
    long long currentuncompressedsize = 0;
    int64_t lastupdated = GetAdjustedTime();

    try
    {
        ZipArchive = zip_open(ArchiveFile, 0, &err);

        if (ZipArchive == nullptr)
        {
            zip_error_to_str(Buf, sizeof(Buf), err, errno);

            ExtractStatus.SnapshotExtractFailed = true;

            LogPrintf("Snapshot (ExtractSnapshot): Error opening snapshot.zip: %s", Buf);

            return false;
        }

        entries = zip_get_num_entries(ZipArchive, 0);

        // Lets scan for total size uncompressed so we can do a detailed progress for the watching user
        for (j = 0; j < (uint64_t)entries; j++)
        {
            if (zip_stat_index(ZipArchive, j, 0, &ZipStat) == 0)
            {
                if (ZipStat.name[strlen(ZipStat.name) - 1] != '/')
                    totaluncompressedsize += ZipStat.size;
            }
        }

        // Now extract
        for (i = 0; i < (uint64_t)entries; i++)
        {
            if (zip_stat_index(ZipArchive, i, 0, &ZipStat) == 0)
            {
                // Does this require a directory
                if (ZipStat.name[strlen(ZipStat.name) - 1] == '/')
                    boost::filesystem::create_directory(ExtractPath / ZipStat.name);

                else
                {
                    ZipFile = zip_fopen_index(ZipArchive, i, 0);

                    if (!ZipFile)
                    {
                        ExtractStatus.SnapshotExtractFailed = true;

                        LogPrintf("Snapshot (ExtractSnapshot): Error opening file %s within snapshot.zip", ZipStat.name);

                        return false;
                    }

                    boost::filesystem::path ExtractFileString = ExtractPath / ZipStat.name;

                    FILE* ExtractFile = fsbridge::fopen(ExtractFileString, "wb");

                    if (!ExtractFile)
                    {
                        ExtractStatus.SnapshotExtractFailed = true;

                        LogPrintf("Snapshot (ExtractSnapshot): Error opening file %s on filesystem", ZipStat.name);

                        return false;
                    }

                    sum = 0;

                    while ((uint64_t)sum != ZipStat.size)
                    {
                        boost::this_thread::interruption_point();

                        len = zip_fread(ZipFile, Buf, 1024*1024);

                        if (len < 0)
                        {
                            ExtractStatus.SnapshotExtractFailed = true;

                            LogPrintf("Snapshot (ExtractSnapshot): Failed to read zip buffer");

                            return false;
                        }

                        fwrite(Buf, 1, (uint64_t)len, ExtractFile);

                        sum += len;
                        currentuncompressedsize += len;

                        // Update Progress every 1 second
                        if (GetAdjustedTime() > lastupdated)
                        {
                            lastupdated = GetAdjustedTime();

                            ExtractStatus.SnapshotExtractProgress = ((currentuncompressedsize / (double)totaluncompressedsize) * 100);
                        }
                    }

                    fclose(ExtractFile);
                    zip_fclose(ZipFile);
                }
            }
        }

        if (zip_close(ZipArchive) == -1)
        {
            ExtractStatus.SnapshotExtractFailed = true;

            LogPrintf("Sanpshot (ExtractSnapshot): Failed to close snapshot.zip");

            return false;
        }

        ExtractStatus.SnapshotExtractComplete = true;
    }

    catch (boost::thread_interrupted&)
    {
        return false;
    }

    return true;
}

void Upgrade::DeleteSnapshot()
{
    // File is out of scope now check if it exists and if so delete it.
    // This covers partial downloaded files or a http response downloaded into file.
    std::string snapshotfile = GetArg("-snapshoturl", "https://download.gridcoin.us/download/downloadstake/signed/snapshot.zip");

    size_t pos = snapshotfile.find_last_of("/");

    snapshotfile = snapshotfile.substr(pos + 1, (snapshotfile.length() - pos - 1));

    try
    {
        boost::filesystem::path snapshotpath = GetDataDir() / snapshotfile;

        if (boost::filesystem::exists(snapshotpath))
            if (boost::filesystem::is_regular_file(snapshotpath))
                boost::filesystem::remove(snapshotpath);
    }

    catch (boost::filesystem::filesystem_error& e)
    {
        LogPrintf("Snapshot Downloader: Exception occured while attempting to delete snapshot (%s)", e.code().message());
    }
}
<|endoftext|>


<commit_before>#include "bspzipgui.h"

#include <iostream>

#include <QFile>
#include <qfiledialog>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QTextStream>

BspZipGui::BspZipGui(QWidget *parent, Qt::WindowFlags flags)
    : QDialog(parent, flags),
    bspzip_process_(NULL)
    //progress_dialog_(NULL)
{
    ui.setupUi(this);

    this->setWindowFlags(Qt::Window);

    bspzip_process_ = new QProcess(this);
    bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
    Q_ASSERT(b);

    //progress_dialog_ = new QProgressDialog(tr("Performing operation"),
    //                                       tr("Cancel"), 0, 100, this);
    //progress_dialog_->setMinimumDuration(0);

    QSettings settings("settings.ini", QSettings::IniFormat, this);
    QString bzip = tr("E:\\Games\\Steam\\SteamApps\\common\\nuclear dawn\\bin\\bspzip.exe");
    QString bsp = tr("E:\\Games\\Steam\\SteamApps\\common\\nuclear dawn\\nucleardawn\\maps\\sk_sandbrick.bsp");
    QString data_folder = tr("D:\\Programming\\AlienSwarmMaps\\nucleardawn\\sk_sandbrick");
    ui.bspzip_path->setText(settings.value("BSPZIP_PATH", bzip).toString());
    ui.bspfile_path->setText(settings.value("BSP_FILE_PATH", bsp).toString());
    ui.data_folder_path->setText(settings.value("DATA_FOLDER_PATH", data_folder).toString());
    this->resize(settings.value("SIZE", QSize(this->width(), this->height())).toSize());
}

BspZipGui::~BspZipGui()
{
    QSettings settings("settings.ini", QSettings::IniFormat, this);
    settings.setValue("BSPZIP_PATH", ui.bspzip_path->text());
    settings.setValue("BSP_FILE_PATH", ui.bspfile_path->text());
    settings.setValue("DATA_FOLDER_PATH", ui.data_folder_path->text());
    settings.setValue("SIZE", this->size());
}

void BspZipGui::on_browse_bspzip_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspzip_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select bspzip.exe file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspzip_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_bsp_file_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspfile_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select BSP file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspfile_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_data_folder_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.data_folder_path->text());
    if (fi.exists())
    {
        if (fi.isDir())
            default_dir_path = fi.absoluteFilePath();
        else
            default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getExistingDirectory(this, tr("Select folder where to extract BSP or which to embed in BSP"), default_dir_path);

    if (!path.isEmpty())
        ui.data_folder_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_embed_clicked()
{
    disableAllButtons();

    QStringList check_list;
    check_list << ui.bspzip_path->text() << ui.bspfile_path->text() << ui.data_folder_path->text();
    if (!filesExist(check_list))
    {
        enableAllButtons();
        return;
    }

    QFile bspzip_filelist_file(QDir::homePath() + "/bspzip_filelist.txt");
    log(tr("Opening file for writing: %1").arg( bspzip_filelist_file.fileName() ));
    if (!bspzip_filelist_file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        log(tr("Failed to open file for writing: %1").arg(bspzip_filelist_file.fileName()));
        enableAllButtons();
        return;
    }

    QDir data_dir( ui.data_folder_path->text(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );
    getDataFolderFiles(data_dir, &data_folder_files_);

    if (data_folder_files_.isEmpty())
    {
        log(tr("No files found for embedding in directory: %1 Aborting...").arg(data_dir.absolutePath()));
        enableAllButtons();
        return;
    }

    log("Adding file list into filelist.txt...");

    QTextStream out(&bspzip_filelist_file);
    QString absolute_file_path;
    Q_FOREACH(absolute_file_path, data_folder_files_)
    {
        absolute_file_path = QDir::toNativeSeparators(absolute_file_path);
        QString relative_file_path = absolute_file_path.mid(ui.data_folder_path->text().size() + 1);

        log(relative_file_path);
        log(absolute_file_path);

        // no quotes here as BSPZIP doesn't handle them
        out << relative_file_path << "\n";
        out << absolute_file_path << "\n";
    }
    data_folder_files_.clear(); // must be cleared! or we get bugs

    bspzip_filelist_file.close();
    log(tr("File bspzip_filelist.txt was successfully created"));

    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString filelist_path = QDir::toNativeSeparators(bspzip_filelist_file.fileName());
    QStringList process_arguments;
    process_arguments << "-addorupdatelist";
    process_arguments << bsp_file_path;
    process_arguments << filelist_path;
    process_arguments << bsp_file_path;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

    log(tr("Starting BSPZIP.EXE with following arguments"));
    Q_FOREACH(QString argument, process_arguments)
    {
        log(argument);
    }

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::on_extract_clicked()
{
    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString data_folder = QDir::toNativeSeparators(ui.data_folder_path->text());

    QStringList check_list;
    check_list << ui.bspzip_path->text() << bsp_file_path << data_folder;
    if (!filesExist(check_list))
    {
        return;
    }

    QStringList process_arguments;
    process_arguments << "-extractfiles";
    process_arguments << bsp_file_path;
    process_arguments << data_folder;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

//     bspzip_process_ = new QProcess(this);
//     bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
//    Q_ASSERT(b);

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::getDataFolderFiles(const QDir &dir, QStringList *file_list)
{
    QFileInfoList files = dir.entryInfoList();

    //log(tr("In directory: %1 parsing...").arg(dir.absolutePath()));

    Q_FOREACH(QFileInfo file, files)
    {
        if (file.isDir())
        {
            QDir d( file.absoluteFilePath(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );

            //QString logstr = tr("Found directory: %1 parsing...").arg(d.absolutePath());
            //log(logstr);

            getDataFolderFiles(d, file_list);
        }
        else
        {
            (*file_list) << file.absoluteFilePath();

            //log(tr("Found file: %1").arg(file.absoluteFilePath()));
        }
    }
}

void BspZipGui::log(const QString &logstr)
{
    ui.console->appendPlainText(logstr);
    //std::cout << logstr.toLatin1().constData() << std::endl;
}

void BspZipGui::onBspZipProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    Q_ASSERT(bspzip_process_);
    QByteArray standard_output = bspzip_process_->readAllStandardOutput();
    QByteArray error_output = bspzip_process_->readAllStandardError();

    QString status = exitStatus == QProcess::NormalExit ? "Normal" : "Crashed";

    log(tr("BSPZIP.exe finished with status: %1, exit code: %2").arg(status).arg(exitCode));
    log(tr("BSPZIP.exe output: "));
    log(standard_output);
    if (error_output.size() > 0)
    {
        log(tr("BSPZIP.exe error output: "));
        log(error_output);
    }

    enableAllButtons();

    QMessageBox::information(
        this, tr("Operation Completed"),
        tr("Operation completed. See output window for details"),
        QMessageBox::Ok);
}

bool BspZipGui::filesExist(const QStringList &files)
{
    Q_FOREACH(QString file_path, files)
    {
        QFileInfo fi(file_path);
        if (!fi.exists())
        {
            QMessageBox::warning(this, tr("File Not Found"), tr("The file doesn't exist: %1. Aborting ").arg(file_path));
            return false;
        }
    }
    return true;
}

void BspZipGui::disableAllButtons()
{
    ui.embed->setDisabled(true);
    ui.extract->setDisabled(true);
}

void BspZipGui::enableAllButtons()
{
    ui.embed->setEnabled(true);
    ui.extract->setEnabled(true);
}
<commit_msg>Change default pathes<commit_after>#include "bspzipgui.h"

#include <iostream>

#include <QFile>
#include <qfiledialog>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QTextStream>

BspZipGui::BspZipGui(QWidget *parent, Qt::WindowFlags flags)
    : QDialog(parent, flags),
    bspzip_process_(NULL)
    //progress_dialog_(NULL)
{
    ui.setupUi(this);

    this->setWindowFlags(Qt::Window);

    bspzip_process_ = new QProcess(this);
    bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
    Q_ASSERT(b);

    //progress_dialog_ = new QProgressDialog(tr("Performing operation"),
    //                                       tr("Cancel"), 0, 100, this);
    //progress_dialog_->setMinimumDuration(0);

    QSettings settings("settings.ini", QSettings::IniFormat, this);
    QString bzip = tr("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Nuclear Dawn\\bin\\bspzip.exe");
    QString bsp =  tr("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Nuclear Dawn\\nucleardawn\\maps\\MyMap.bsp");
    QString data_folder = tr("C:\\work\\MyMapProject");
    ui.bspzip_path->setText(settings.value("BSPZIP_PATH", bzip).toString());
    ui.bspfile_path->setText(settings.value("BSP_FILE_PATH", bsp).toString());
    ui.data_folder_path->setText(settings.value("DATA_FOLDER_PATH", data_folder).toString());
    this->resize(settings.value("SIZE", QSize(this->width(), this->height())).toSize());
}

BspZipGui::~BspZipGui()
{
    QSettings settings("settings.ini", QSettings::IniFormat, this);
    settings.setValue("BSPZIP_PATH", ui.bspzip_path->text());
    settings.setValue("BSP_FILE_PATH", ui.bspfile_path->text());
    settings.setValue("DATA_FOLDER_PATH", ui.data_folder_path->text());
    settings.setValue("SIZE", this->size());
}

void BspZipGui::on_browse_bspzip_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspzip_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select bspzip.exe file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspzip_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_bsp_file_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspfile_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select BSP file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspfile_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_data_folder_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.data_folder_path->text());
    if (fi.exists())
    {
        if (fi.isDir())
            default_dir_path = fi.absoluteFilePath();
        else
            default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getExistingDirectory(this, tr("Select folder where to extract BSP or which to embed in BSP"), default_dir_path);

    if (!path.isEmpty())
        ui.data_folder_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_embed_clicked()
{
    disableAllButtons();

    QStringList check_list;
    check_list << ui.bspzip_path->text() << ui.bspfile_path->text() << ui.data_folder_path->text();
    if (!filesExist(check_list))
    {
        enableAllButtons();
        return;
    }

    QFile bspzip_filelist_file(QDir::homePath() + "/bspzip_filelist.txt");
    log(tr("Opening file for writing: %1").arg( bspzip_filelist_file.fileName() ));
    if (!bspzip_filelist_file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        log(tr("Failed to open file for writing: %1").arg(bspzip_filelist_file.fileName()));
        enableAllButtons();
        return;
    }

    QDir data_dir( ui.data_folder_path->text(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );
    getDataFolderFiles(data_dir, &data_folder_files_);

    if (data_folder_files_.isEmpty())
    {
        log(tr("No files found for embedding in directory: %1 Aborting...").arg(data_dir.absolutePath()));
        enableAllButtons();
        return;
    }

    log("Adding file list into filelist.txt...");

    QTextStream out(&bspzip_filelist_file);
    QString absolute_file_path;
    Q_FOREACH(absolute_file_path, data_folder_files_)
    {
        absolute_file_path = QDir::toNativeSeparators(absolute_file_path);
        QString relative_file_path = absolute_file_path.mid(ui.data_folder_path->text().size() + 1);

        log(relative_file_path);
        log(absolute_file_path);

        // no quotes here as BSPZIP doesn't handle them
        out << relative_file_path << "\n";
        out << absolute_file_path << "\n";
    }
    data_folder_files_.clear(); // must be cleared! or we get bugs

    bspzip_filelist_file.close();
    log(tr("File bspzip_filelist.txt was successfully created"));

    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString filelist_path = QDir::toNativeSeparators(bspzip_filelist_file.fileName());
    QStringList process_arguments;
    process_arguments << "-addorupdatelist";
    process_arguments << bsp_file_path;
    process_arguments << filelist_path;
    process_arguments << bsp_file_path;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

    log(tr("Starting BSPZIP.EXE with following arguments"));
    Q_FOREACH(QString argument, process_arguments)
    {
        log(argument);
    }

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::on_extract_clicked()
{
    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString data_folder = QDir::toNativeSeparators(ui.data_folder_path->text());

    QStringList check_list;
    check_list << ui.bspzip_path->text() << bsp_file_path << data_folder;
    if (!filesExist(check_list))
    {
        return;
    }

    QStringList process_arguments;
    process_arguments << "-extractfiles";
    process_arguments << bsp_file_path;
    process_arguments << data_folder;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

//     bspzip_process_ = new QProcess(this);
//     bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
//    Q_ASSERT(b);

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::getDataFolderFiles(const QDir &dir, QStringList *file_list)
{
    QFileInfoList files = dir.entryInfoList();

    //log(tr("In directory: %1 parsing...").arg(dir.absolutePath()));

    Q_FOREACH(QFileInfo file, files)
    {
        if (file.isDir())
        {
            QDir d( file.absoluteFilePath(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );

            //QString logstr = tr("Found directory: %1 parsing...").arg(d.absolutePath());
            //log(logstr);

            getDataFolderFiles(d, file_list);
        }
        else
        {
            (*file_list) << file.absoluteFilePath();

            //log(tr("Found file: %1").arg(file.absoluteFilePath()));
        }
    }
}

void BspZipGui::log(const QString &logstr)
{
    ui.console->appendPlainText(logstr);
    //std::cout << logstr.toLatin1().constData() << std::endl;
}

void BspZipGui::onBspZipProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    Q_ASSERT(bspzip_process_);
    QByteArray standard_output = bspzip_process_->readAllStandardOutput();
    QByteArray error_output = bspzip_process_->readAllStandardError();

    QString status = exitStatus == QProcess::NormalExit ? "Normal" : "Crashed";

    log(tr("BSPZIP.exe finished with status: %1, exit code: %2").arg(status).arg(exitCode));
    log(tr("BSPZIP.exe output: "));
    log(standard_output);
    if (error_output.size() > 0)
    {
        log(tr("BSPZIP.exe error output: "));
        log(error_output);
    }

    enableAllButtons();

    QMessageBox::information(
        this, tr("Operation Completed"),
        tr("Operation completed. See output window for details"),
        QMessageBox::Ok);
}

bool BspZipGui::filesExist(const QStringList &files)
{
    Q_FOREACH(QString file_path, files)
    {
        QFileInfo fi(file_path);
        if (!fi.exists())
        {
            QMessageBox::warning(this, tr("File Not Found"), tr("The file doesn't exist: %1. Aborting ").arg(file_path));
            return false;
        }
    }
    return true;
}

void BspZipGui::disableAllButtons()
{
    ui.embed->setDisabled(true);
    ui.extract->setDisabled(true);
}

void BspZipGui::enableAllButtons()
{
    ui.embed->setEnabled(true);
    ui.extract->setEnabled(true);
}
<|endoftext|>


<commit_before>// Copyright 2013 Sean McKenna
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//

// a ray tracer in C++

// libraries, namespace
#include <thread>
#include <fstream>
#include <string>
#include <cmath>
#include "library/loadXML.cpp"
#include "library/scene.cpp"
using namespace std;

// scene to load (project #) & whether to debug
const char* xml = "scenes/prj5.xml";
bool printXML = false;
bool zBuffer = false;

// for ray tracing
int w;
int h;
int size;
Color24* img;
float* zImg;

// for threading
static const int numThreads = 8;
void rayTracing(int i);

// for camera ray generation
void cameraRayVars();
Point *imageTopLeftV;
Point *dXV;
Point *dYV;
Point firstPixel;
Transformation* c;
Point cameraRay(int pX, int pY);

// ray tracer
int main(){

  // load scene: root node, camera, image
  loadScene(xml, printXML);

  // set the scene as the root node
  setScene(rootNode);

  // set variables for ray tracing
  w = render.getWidth();
  h = render.getHeight();
  size = render.getSize();
  img = render.getRender();
  zImg = render.getZBuffer();

  // set variables for generating camera rays
  cameraRayVars();

  // start ray tracing loop (in parallel with threads)
  thread t[numThreads];
  for(int i = 0; i < numThreads; i++)
    t[i] = thread(rayTracing, i);

  // when finished, join all threads back to main
  for(int i = 0; i < numThreads; i++)
    t[i].join();

  // output ray-traced image & z-buffer (if set)
  render.save("images/image.ppm");
  if(zBuffer){
    render.computeZBuffer();
    render.saveZBuffer("images/imageZ.ppm");
  }
}

// ray tracing loop (for an individual pixel)
void rayTracing(int i){

  // initial starting pixel
  int pixel = i;

  // thread continuation condition
  while(pixel < size){

    // establish pixel location
    int pX = pixel % w;
    int pY = pixel / w;

    // transform ray into world space
    Point rayDir = cameraRay(pX, pY);
    Ray *ray = new Ray();
    ray->pos = camera.pos;
    ray->dir = c->transformFrom(rayDir);

    // traverse through scene DOM
    // transform rays into model space
    // detect ray intersections and get back HitInfo
    HitInfo h = HitInfo();
    bool hit = traceRay(*ray, h);

    // update z-buffer, if necessary
    if(zBuffer)
      zImg[pixel] = h.z;

    // color for the pixel
    Color24 c;

    // if hit, get the node's material
    if(hit){
      Node *n = h.node;
      Material *m;
      if(n)
        m = n->getMaterial();

      // if there is a material, shade the pixel
      // 16-passes for reflections and refractions
      if(m)
        c = Color24(m->shade(*ray, h, lights, 16));

      // otherwise color it white (as a hit)
      else
        c.Set(237, 237, 237);

    // if we hit nothing
    }else
      c.Set(0.0, 0.0, 0.0);

    // color the pixel image
    img[pixel] = c;

    // re-assign next pixel (naive, but works)
    pixel += numThreads;
  }
}

// create variables for camera ray generation
void cameraRayVars(){
  float fov = camera.fov * M_PI / 180.0;
  float aspectRatio = (float) w / (float) h;
  float imageDistance = 1.0;
  float imageTipY = imageDistance * tan(fov / 2.0);
  float imageTipX = imageTipY * aspectRatio;
  float dX = (2.0 * imageTipX) / (float) w;
  float dY = (2.0 * imageTipY) / (float) h;
  imageTopLeftV = new Point(-imageTipX, imageTipY, -imageDistance);
  dXV = new Point(dX, 0.0, 0.0);
  dYV = new Point(0.0, -dY, 0.0);
  firstPixel = *imageTopLeftV + (*dXV * 0.5) + (*dYV * 0.5);

  // set up camera transformation (only need to rotate coordinates)
  c = new Transformation();
  Matrix *rotate = new cyMatrix3f();
  rotate->Set(camera.cross, camera.up, -camera.dir);
  c->transform(*rotate);
}

// compute camera rays
Point cameraRay(int pX, int pY){
  Point ray = firstPixel + (*dXV * pX) + (*dYV * pY);
  ray.Normalize();
  return ray;
}
<commit_msg>reduce bounce count to render images faster, no visual change in images thus far<commit_after>// Copyright 2013 Sean McKenna
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//

// a ray tracer in C++

// libraries, namespace
#include <thread>
#include <fstream>
#include <string>
#include <cmath>
#include "library/loadXML.cpp"
#include "library/scene.cpp"
using namespace std;

// scene to load (project #) & whether to debug
const char* xml = "scenes/prj5.xml";
bool printXML = false;
bool zBuffer = false;

// for ray tracing
int w;
int h;
int size;
Color24* img;
float* zImg;

// for threading
static const int numThreads = 8;
void rayTracing(int i);

// for camera ray generation
void cameraRayVars();
Point *imageTopLeftV;
Point *dXV;
Point *dYV;
Point firstPixel;
Transformation* c;
Point cameraRay(int pX, int pY);

// ray tracer
int main(){

  // load scene: root node, camera, image
  loadScene(xml, printXML);

  // set the scene as the root node
  setScene(rootNode);

  // set variables for ray tracing
  w = render.getWidth();
  h = render.getHeight();
  size = render.getSize();
  img = render.getRender();
  zImg = render.getZBuffer();

  // set variables for generating camera rays
  cameraRayVars();

  // start ray tracing loop (in parallel with threads)
  thread t[numThreads];
  for(int i = 0; i < numThreads; i++)
    t[i] = thread(rayTracing, i);

  // when finished, join all threads back to main
  for(int i = 0; i < numThreads; i++)
    t[i].join();

  // output ray-traced image & z-buffer (if set)
  render.save("images/image.ppm");
  if(zBuffer){
    render.computeZBuffer();
    render.saveZBuffer("images/imageZ.ppm");
  }
}

// ray tracing loop (for an individual pixel)
void rayTracing(int i){

  // initial starting pixel
  int pixel = i;

  // thread continuation condition
  while(pixel < size){

    // establish pixel location
    int pX = pixel % w;
    int pY = pixel / w;

    // transform ray into world space
    Point rayDir = cameraRay(pX, pY);
    Ray *ray = new Ray();
    ray->pos = camera.pos;
    ray->dir = c->transformFrom(rayDir);

    // traverse through scene DOM
    // transform rays into model space
    // detect ray intersections and get back HitInfo
    HitInfo h = HitInfo();
    bool hit = traceRay(*ray, h);

    // update z-buffer, if necessary
    if(zBuffer)
      zImg[pixel] = h.z;

    // color for the pixel
    Color24 c;

    // if hit, get the node's material
    if(hit){
      Node *n = h.node;
      Material *m;
      if(n)
        m = n->getMaterial();

      // if there is a material, shade the pixel
      // 16-passes for reflections and refractions
      if(m)
        c = Color24(m->shade(*ray, h, lights, 5));

      // otherwise color it white (as a hit)
      else
        c.Set(237, 237, 237);

    // if we hit nothing
    }else
      c.Set(0.0, 0.0, 0.0);

    // color the pixel image
    img[pixel] = c;

    // re-assign next pixel (naive, but works)
    pixel += numThreads;
  }
}

// create variables for camera ray generation
void cameraRayVars(){
  float fov = camera.fov * M_PI / 180.0;
  float aspectRatio = (float) w / (float) h;
  float imageDistance = 1.0;
  float imageTipY = imageDistance * tan(fov / 2.0);
  float imageTipX = imageTipY * aspectRatio;
  float dX = (2.0 * imageTipX) / (float) w;
  float dY = (2.0 * imageTipY) / (float) h;
  imageTopLeftV = new Point(-imageTipX, imageTipY, -imageDistance);
  dXV = new Point(dX, 0.0, 0.0);
  dYV = new Point(0.0, -dY, 0.0);
  firstPixel = *imageTopLeftV + (*dXV * 0.5) + (*dYV * 0.5);

  // set up camera transformation (only need to rotate coordinates)
  c = new Transformation();
  Matrix *rotate = new cyMatrix3f();
  rotate->Set(camera.cross, camera.up, -camera.dir);
  c->transform(*rotate);
}

// compute camera rays
Point cameraRay(int pX, int pY){
  Point ray = firstPixel + (*dXV * pX) + (*dYV * pY);
  ray.Normalize();
  return ray;
}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <tuple>
#include <exception>
#include <algorithm>
#include <string.h>
#include "read_param.hpp"

//This function reads the key, value pairs from the config file into a map.
//The argument is only used to check the keys are what we expected.
std::map<std::string, std::string> SpbConfigParser::get_parameter_map(std::map<std::string, ValueTuple> expected_keys)
{
  std::fstream config;
  config.open(m_config.c_str(), std::fstream::in);
  if ( ! config.is_open() ) {
      throw std::runtime_error("Can't open config in file: "+ m_config);
  }

  //Store a name here when it has already been found in the file
  std::map<std::string, std::string> found;

  /* Read the lines */
  while ( config.good() ) {
    std::string line;
    std::getline(config, line);
    std::pair<std::string, std::string> parsed_line = parse_line(line);
    if (!config.good() )
        break;
    if (parsed_line.first.empty())
        continue;
    //Check not a duplicate
    std::map<std::string, std::string>::iterator fit = found.find(parsed_line.first);
    if (fit != found.end()){
        throw std::runtime_error("Key: "+parsed_line.first+" found twice in "+m_config+" with values "+fit->second+" and "+parsed_line.second);
    }
    //Check that we expected this key
    std::map<std::string, ValueTuple>::iterator dit = expected_keys.find(parsed_line.first);
    if (dit == expected_keys.end()){
        throw std::runtime_error(m_config+" contained unexpected key: "+parsed_line.first);
    }
    //Store the name and value in found
    found[parsed_line.first] = parsed_line.second;
  }
  config.close();
  return found;
}

int SpbConfigParser::parameter_parser(std::map<std::string, ValueTuple > datastore)
{
  std::map<std::string, std::string> found = get_parameter_map(datastore);
  //Now we have read the key, value pairs into a map, store them where we want them
  for(std::map<std::string, ValueTuple>::iterator dit = datastore.begin(); dit != datastore.end(); ++dit) {
    //Get the string we want. Use found unless it wasn't, in which case use the default
    std::string value = std::get<2>(dit->second);
    std::map<std::string, std::string>::iterator fit = found.find(dit->first);
    if (fit != found.end() ) {
        value = fit->second;
    }
    else if (m_verbose) {
        std::cout<<"Using default value: "<<value<<" for key: "<<dit->first<<std::endl;
    }
    if (value.empty()) {
        throw std::runtime_error("No value for key: "+dit->first);
    }
    //Switch on the type of the key
    TypeEnum thistype = std::get<1>(dit->second);
    if(thistype == IntType) {
        * (int *) std::get<0>(dit->second) = atoi(value.c_str());
    }
    else if (thistype == StringType) {
        //strcpy is fine here because the conversion from a std::string will always be null-terminated
        strcpy((char *) std::get<0>(dit->second), value.c_str());
    }
    else if (thistype == FloatType) {
        * (double *) std::get<0>(dit->second) = atof(value.c_str());
    }
    else {
        throw std::runtime_error("Unrecognised type for "+dit->first);
    }
  }
  return 0;
}

//Parse a single line into a key-value pair
std::pair<std::string, std::string> SpbConfigParser::parse_line(std::string linein)
{
    std::string key, value;
    //Strip comments
    size_t comment_pos = linein.find_first_of(m_comments);
    linein = linein.substr(0, comment_pos);
    //Strip leading whitespace
    size_t white_pos = linein.find_first_not_of(std::string(" \t"));
    if (white_pos == std::string::npos)
        return std::make_pair(key, value);
    linein = linein.substr(white_pos);
    //Find key/value separator
    size_t separator_pos = linein.find_first_of(m_separators);
    key = linein.substr(0, separator_pos);
    //Set value
    if (separator_pos != std::string::npos)
        value = linein.substr(separator_pos+1);
    //Take out whitespace
    key.erase(std::remove(key.begin(), key.end(), ' '), key.end());
    key.erase(std::remove(key.begin(), key.end(), '\t'), key.end());
    value.erase(std::remove(value.begin(), value.end(), '\t'), value.end());
    value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
    return std::make_pair(key, value);
}
<commit_msg>Be sure to strip out separators, even if repeated. Fixes bug with ' = ' in a line<commit_after>#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <tuple>
#include <exception>
#include <algorithm>
#include <string.h>
#include "read_param.hpp"

//This function reads the key, value pairs from the config file into a map.
//The argument is only used to check the keys are what we expected.
std::map<std::string, std::string> SpbConfigParser::get_parameter_map(std::map<std::string, ValueTuple> expected_keys)
{
  std::fstream config;
  config.open(m_config.c_str(), std::fstream::in);
  if ( ! config.is_open() ) {
      throw std::runtime_error("Can't open config in file: "+ m_config);
  }

  //Store a name here when it has already been found in the file
  std::map<std::string, std::string> found;

  /* Read the lines */
  while ( config.good() ) {
    std::string line;
    std::getline(config, line);
    std::pair<std::string, std::string> parsed_line = parse_line(line);
    if (!config.good() )
        break;
    if (parsed_line.first.empty())
        continue;
    //Check not a duplicate
    std::map<std::string, std::string>::iterator fit = found.find(parsed_line.first);
    if (fit != found.end()){
        throw std::runtime_error("Key: "+parsed_line.first+" found twice in "+m_config+" with values "+fit->second+" and "+parsed_line.second);
    }
    //Check that we expected this key
    std::map<std::string, ValueTuple>::iterator dit = expected_keys.find(parsed_line.first);
    if (dit == expected_keys.end()){
        throw std::runtime_error(m_config+" contained unexpected key: "+parsed_line.first);
    }
    //Store the name and value in found
    found[parsed_line.first] = parsed_line.second;
  }
  config.close();
  return found;
}

int SpbConfigParser::parameter_parser(std::map<std::string, ValueTuple > datastore)
{
  std::map<std::string, std::string> found = get_parameter_map(datastore);
  //Now we have read the key, value pairs into a map, store them where we want them
  for(std::map<std::string, ValueTuple>::iterator dit = datastore.begin(); dit != datastore.end(); ++dit) {
    //Get the string we want. Use found unless it wasn't, in which case use the default
    std::string value = std::get<2>(dit->second);
    std::map<std::string, std::string>::iterator fit = found.find(dit->first);
    if (fit != found.end() ) {
        value = fit->second;
    }
    else if (m_verbose) {
        std::cout<<"Using default value: "<<value<<" for key: "<<dit->first<<std::endl;
    }
    if (value.empty()) {
        throw std::runtime_error("No value for key: "+dit->first);
    }
    //Switch on the type of the key
    TypeEnum thistype = std::get<1>(dit->second);
    if(thistype == IntType) {
        * (int *) std::get<0>(dit->second) = atoi(value.c_str());
    }
    else if (thistype == StringType) {
        //strcpy is fine here because the conversion from a std::string will always be null-terminated
        strcpy((char *) std::get<0>(dit->second), value.c_str());
    }
    else if (thistype == FloatType) {
        * (double *) std::get<0>(dit->second) = atof(value.c_str());
    }
    else {
        throw std::runtime_error("Unrecognised type for "+dit->first);
    }
  }
  return 0;
}

//Parse a single line into a key-value pair
std::pair<std::string, std::string> SpbConfigParser::parse_line(std::string linein)
{
    std::string key, value;
    //Strip comments
    size_t comment_pos = linein.find_first_of(m_comments);
    linein = linein.substr(0, comment_pos);
    //Strip leading whitespace
    size_t white_pos = linein.find_first_not_of(std::string(" \t"));
    if (white_pos == std::string::npos)
        return std::make_pair(key, value);
    linein = linein.substr(white_pos);
    //Find key/value separator
    size_t separator_pos = linein.find_first_of(m_separators);
    key = linein.substr(0, separator_pos);
    //Set value
    if (separator_pos != std::string::npos){
        size_t value_pos = linein.find_first_not_of(m_separators,separator_pos);
        if (value_pos != std::string::npos){
            value = linein.substr(value_pos);
        }
    }
    //Take out whitespace
    key.erase(std::remove(key.begin(), key.end(), ' '), key.end());
    key.erase(std::remove(key.begin(), key.end(), '\t'), key.end());
    value.erase(std::remove(value.begin(), value.end(), '\t'), value.end());
    value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
    return std::make_pair(key, value);
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("Satoshi");

// Client version number
#define CLIENT_VERSION_SUFFIX   ""

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID "99c6a68"
#    define GIT_COMMIT_DATE "$Format:%cD"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<commit_msg>log info<commit_after>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("Satoshi");

// Client version number
#define CLIENT_VERSION_SUFFIX   ""

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID "657c9ed"
#    define GIT_COMMIT_DATE "$Format:%cD"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<|endoftext|>


<commit_before><commit_msg>Make WebHistoryItem serialization include the documentSequenceNumber.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "base/compiler_specific.h"

#include "GenericWorkerTask.h"
#include "KURL.h"
#include "ScriptExecutionContext.h"
#include "SecurityOrigin.h"
#include "SubstituteData.h"
#include "WorkerContext.h"
#include "WorkerThread.h"
#include <wtf/MainThread.h>
#include <wtf/Threading.h>

#undef LOG

#include "base/logging.h"
#include "webkit/api/public/WebScreenInfo.h"
#include "webkit/api/public/WebString.h"
#include "webkit/api/public/WebURL.h"
#include "webkit/api/public/WebWorkerClient.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/webdatasource_impl.h"
#include "webkit/glue/webframe_impl.h"
#include "webkit/glue/webpreferences.h"
#include "webkit/glue/webview.h"
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/webworker_impl.h"

using WebKit::WebWorker;
using WebKit::WebWorkerClient;
using WebKit::WebString;
using WebKit::WebURL;

#if ENABLE(WORKERS)

// Dummy WebViewDelegate - we only need it in Worker process to load a
// 'shadow page' which will initialize WebCore loader.
class WorkerWebViewDelegate : public WebViewDelegate {
 public:
  WorkerWebViewDelegate() {}
  virtual void AddRef() { }
  virtual void Release() { }
  virtual void Blur(WebWidget *webwidget) { }
  virtual void CloseWidgetSoon(WebWidget *webwidget) { }
  virtual void DidInvalidateRect(WebWidget *webwidget,
                                 const WebKit::WebRect &rect) { }
  virtual void DidMove(WebWidget *webwidget, const WebPluginGeometry &move) { }
  virtual void DidScrollRect(WebWidget *webwidget, int dx, int dy,
                             const WebKit::WebRect &clip_rect) { }
  virtual void Focus(WebWidget *webwidget) { }
  virtual gfx::NativeViewId GetContainingView(WebWidget *webwidget) {
    return gfx::NativeViewId();
  }
  virtual void GetRootWindowRect(WebWidget *webwidget,
                                 WebKit::WebRect *rect) { }
  virtual void GetRootWindowResizerRect(WebWidget *webwidget,
                                        WebKit::WebRect *rect) { }
  virtual WebKit::WebScreenInfo GetScreenInfo(WebWidget *webwidget) {
    WebKit::WebScreenInfo info;
    return info;
  }
  virtual void GetWindowRect(WebWidget *webwidget, WebKit::WebRect *rect) { }
  virtual bool IsHidden(WebWidget *webwidget) { return true; }
  virtual void RunModal(WebWidget *webwidget) { }
  virtual void SetCursor(WebWidget *webwidget, const WebCursor &cursor) { }
  virtual void SetWindowRect(WebWidget *webwidget,
                             const WebKit::WebRect &rect) { }
  virtual void Show(WebWidget *webwidget, WindowOpenDisposition disposition) { }
  virtual void ShowAsPopupWithItems(WebWidget *webwidget,
                                    const WebKit::WebRect &bounds,
                                    int item_height,
                                    int selected_index,
                                    const std::vector<WebMenuItem> &items) { }
  // Tell the loader to load the data into the 'shadow page' synchronously,
  // so we can grab the resulting Document right after load.
  virtual void DidCreateDataSource(WebFrame* frame, WebDataSource* ds) {
    static_cast<WebDataSourceImpl*>(ds)->setDeferMainResourceDataLoad(false);
  }
  // Lazy allocate and leak this instance.
  static WorkerWebViewDelegate* worker_delegate() {
    static WorkerWebViewDelegate* worker_delegate = new WorkerWebViewDelegate();
    return worker_delegate;
  }
 private:
  DISALLOW_COPY_AND_ASSIGN(WorkerWebViewDelegate);
};

namespace WebKit {

WebWorker* WebWorker::create(WebWorkerClient* client) {
  return new WebWorkerImpl(client);
}

}

// This function is called on the main thread to force to initialize some static
// values used in WebKit before any worker thread is started. This is because in
// our worker processs, we do not run any WebKit code in main thread and thus
// when multiple workers try to start at the same time, we might hit crash due
// to contention for initializing static values.
void InitializeWebKitStaticValues() {
  static bool initialized = false;
  if (!initialized) {
    initialized= true;
    // Note that we have to pass a URL with valid protocol in order to follow
    // the path to do static value initializations.
    WTF::RefPtr<WebCore::SecurityOrigin> origin =
        WebCore::SecurityOrigin::create(WebCore::KURL("http://localhost"));
    origin.release();
  }
}

WebWorkerImpl::WebWorkerImpl(WebWorkerClient* client)
 : client_(client),
   web_view_(NULL) {
  InitializeWebKitStaticValues();
}

WebWorkerImpl::~WebWorkerImpl() {
  web_view_->Close();
}

void WebWorkerImpl::PostMessageToWorkerContextTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    const WebCore::String& message) {
  DCHECK(context->isWorkerContext());
  WebCore::WorkerContext* worker_context =
      static_cast<WebCore::WorkerContext*>(context);
  worker_context->dispatchMessage(message);

  this_ptr->confirmMessageFromWorkerObject(
      worker_context->hasPendingActivity());
}

// WebWorker -------------------------------------------------------------------

void WebWorkerImpl::startWorkerContext(const WebURL& script_url,
                                       const WebString& user_agent,
                                       const WebString& source_code) {
  // Create 'shadow page'. This page is never displayed, it is used to proxy the
  // loading requests from the worker context to the rest of WebKit and Chromium
  // infrastructure.
  DCHECK(!web_view_);
  web_view_ = WebView::Create(WorkerWebViewDelegate::worker_delegate(),
                              WebPreferences());

  WebFrameImpl* web_frame =
      static_cast<WebFrameImpl*>(web_view_->GetMainFrame());

  // Construct substitute data source for the 'shadow page'. We only need it
  // to have same origin as the worker so the loading checks work correctly.
  WebCore::CString content("Shadow page");
  int len = static_cast<int>(content.length());
  RefPtr<WebCore::SharedBuffer> buf(
      WebCore::SharedBuffer::create(content.data(), len));
  WebCore::SubstituteData subst_data(buf,
                                     WebCore::String("text/html"),
                                     WebCore::String("UTF-8"),
                                     WebCore::KURL());
  WebCore::ResourceRequest request(webkit_glue::GURLToKURL(script_url),
                                   WebCore::CString());
  web_frame->frame()->loader()->load(request, subst_data, false);

  // This document will be used as 'loading context' for the worker.
  loading_document_ = web_frame->frame()->document();

  worker_thread_ = WebCore::WorkerThread::create(
      webkit_glue::WebURLToKURL(script_url),
      webkit_glue::WebStringToString(user_agent),
      webkit_glue::WebStringToString(source_code),
      *this,
      *this);

  // Worker initialization means a pending activity.
  reportPendingActivity(true);

  worker_thread_->start();
}

void WebWorkerImpl::terminateWorkerContext() {
  worker_thread_->stop();
}

void WebWorkerImpl::postMessageToWorkerContext(const WebString& message) {
  worker_thread_->runLoop().postTask(WebCore::createCallbackTask(
      &PostMessageToWorkerContextTask,
      this,
      webkit_glue::WebStringToString(message)));
}

void WebWorkerImpl::workerObjectDestroyed() {
}

void WebWorkerImpl::DispatchTaskToMainThread(
    PassRefPtr<WebCore::ScriptExecutionContext::Task> task) {
  return WTF::callOnMainThread(InvokeTaskMethod, task.releaseRef());
}

void WebWorkerImpl::InvokeTaskMethod(void* param) {
  WebCore::ScriptExecutionContext::Task* task =
      static_cast<WebCore::ScriptExecutionContext::Task*>(param);
  task->performTask(NULL);
  task->deref();
}

// WorkerObjectProxy -----------------------------------------------------------

void WebWorkerImpl::postMessageToWorkerObject(const WebCore::String& message) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &PostMessageTask,
      this,
      message));
}

void WebWorkerImpl::PostMessageTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    WebCore::String message) {
  this_ptr->client_->postMessageToWorkerObject(
      webkit_glue::StringToWebString(message));
}

void WebWorkerImpl::postExceptionToWorkerObject(
    const WebCore::String& error_message,
    int line_number,
    const WebCore::String& source_url) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &PostExceptionTask,
      this,
      error_message,
      line_number,
      source_url));
}

void WebWorkerImpl::PostExceptionTask(
      WebCore::ScriptExecutionContext* context,
      WebWorkerImpl* this_ptr,
      const WebCore::String& error_message,
      int line_number,
      const WebCore::String& source_url) {
  this_ptr->client_->postExceptionToWorkerObject(
      webkit_glue::StringToWebString(error_message),
      line_number,
      webkit_glue::StringToWebString(source_url));
}

void WebWorkerImpl::postConsoleMessageToWorkerObject(
    WebCore::MessageDestination destination,
    WebCore::MessageSource source,
    WebCore::MessageLevel level,
    const WebCore::String& message,
    int line_number,
    const WebCore::String& source_url) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &PostConsoleMessageTask,
      this,
      static_cast<int>(destination),
      static_cast<int>(source),
      static_cast<int>(level),
      message,
      line_number,
      source_url));
}

void WebWorkerImpl::PostConsoleMessageTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    int destination,
    int source,
    int level,
    const WebCore::String& message,
    int line_number,
    const WebCore::String& source_url) {
  this_ptr->client_->postConsoleMessageToWorkerObject(
      destination,
      source,
      level,
      webkit_glue::StringToWebString(message),
      line_number,
      webkit_glue::StringToWebString(source_url));
}

void WebWorkerImpl::confirmMessageFromWorkerObject(bool has_pending_activity) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &ConfirmMessageTask,
      this,
      has_pending_activity));
}

void WebWorkerImpl::ConfirmMessageTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    bool has_pending_activity) {
  this_ptr->client_->confirmMessageFromWorkerObject(has_pending_activity);
}

void WebWorkerImpl::reportPendingActivity(bool has_pending_activity) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &ReportPendingActivityTask,
      this,
      has_pending_activity));
}

void WebWorkerImpl::ReportPendingActivityTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    bool has_pending_activity) {
  this_ptr->client_->reportPendingActivity(has_pending_activity);
}

void WebWorkerImpl::workerContextDestroyed() {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &WorkerContextDestroyedTask,
      this));
}

// WorkerLoaderProxy -----------------------------------------------------------

void WebWorkerImpl::postTaskToLoader(
    PassRefPtr<WebCore::ScriptExecutionContext::Task> task) {
  ASSERT(loading_document_->isDocument());
  loading_document_->postTask(task);
}

void WebWorkerImpl::postTaskForModeToWorkerContext(
    PassRefPtr<WebCore::ScriptExecutionContext::Task> task,
    const WebCore::String& mode) {
  worker_thread_->runLoop().postTaskForMode(task, mode);
}

void WebWorkerImpl::WorkerContextDestroyedTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr) {
  this_ptr->client_->workerContextDestroyed();

  // The lifetime of this proxy is controlled by the worker context.
  delete this_ptr;
}

#else

namespace WebKit {

WebWorker* WebWorker::create(WebWorkerClient* client) {
  return NULL;
}

}

#endif
<commit_msg>Fix for occasional crash in a Worker process caused by 'shadow page' trying to load font for layout. BUG=14194 TEST=none (hard to even repro) Review URL: http://codereview.chromium.org/125213<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "base/compiler_specific.h"

#include "GenericWorkerTask.h"
#include "KURL.h"
#include "ScriptExecutionContext.h"
#include "SecurityOrigin.h"
#include "SubstituteData.h"
#include "WorkerContext.h"
#include "WorkerThread.h"
#include <wtf/MainThread.h>
#include <wtf/Threading.h>

#undef LOG

#include "base/logging.h"
#include "webkit/api/public/WebScreenInfo.h"
#include "webkit/api/public/WebString.h"
#include "webkit/api/public/WebURL.h"
#include "webkit/api/public/WebWorkerClient.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/webdatasource_impl.h"
#include "webkit/glue/webframe_impl.h"
#include "webkit/glue/webpreferences.h"
#include "webkit/glue/webview.h"
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/webworker_impl.h"

using WebKit::WebWorker;
using WebKit::WebWorkerClient;
using WebKit::WebString;
using WebKit::WebURL;

#if ENABLE(WORKERS)

// Dummy WebViewDelegate - we only need it in Worker process to load a
// 'shadow page' which will initialize WebCore loader.
class WorkerWebViewDelegate : public WebViewDelegate {
 public:
  WorkerWebViewDelegate() {}
  virtual void AddRef() { }
  virtual void Release() { }
  virtual void Blur(WebWidget *webwidget) { }
  virtual void CloseWidgetSoon(WebWidget *webwidget) { }
  virtual void DidInvalidateRect(WebWidget *webwidget,
                                 const WebKit::WebRect &rect) { }
  virtual void DidMove(WebWidget *webwidget, const WebPluginGeometry &move) { }
  virtual void DidScrollRect(WebWidget *webwidget, int dx, int dy,
                             const WebKit::WebRect &clip_rect) { }
  virtual void Focus(WebWidget *webwidget) { }
  virtual gfx::NativeViewId GetContainingView(WebWidget *webwidget) {
    return gfx::NativeViewId();
  }
  virtual void GetRootWindowRect(WebWidget *webwidget,
                                 WebKit::WebRect *rect) { }
  virtual void GetRootWindowResizerRect(WebWidget *webwidget,
                                        WebKit::WebRect *rect) { }
  virtual WebKit::WebScreenInfo GetScreenInfo(WebWidget *webwidget) {
    WebKit::WebScreenInfo info;
    return info;
  }
  virtual void GetWindowRect(WebWidget *webwidget, WebKit::WebRect *rect) { }
  virtual bool IsHidden(WebWidget *webwidget) { return true; }
  virtual void RunModal(WebWidget *webwidget) { }
  virtual void SetCursor(WebWidget *webwidget, const WebCursor &cursor) { }
  virtual void SetWindowRect(WebWidget *webwidget,
                             const WebKit::WebRect &rect) { }
  virtual void Show(WebWidget *webwidget, WindowOpenDisposition disposition) { }
  virtual void ShowAsPopupWithItems(WebWidget *webwidget,
                                    const WebKit::WebRect &bounds,
                                    int item_height,
                                    int selected_index,
                                    const std::vector<WebMenuItem> &items) { }
  // Tell the loader to load the data into the 'shadow page' synchronously,
  // so we can grab the resulting Document right after load.
  virtual void DidCreateDataSource(WebFrame* frame, WebDataSource* ds) {
    static_cast<WebDataSourceImpl*>(ds)->setDeferMainResourceDataLoad(false);
  }
  // Lazy allocate and leak this instance.
  static WorkerWebViewDelegate* worker_delegate() {
    static WorkerWebViewDelegate* worker_delegate = new WorkerWebViewDelegate();
    return worker_delegate;
  }
 private:
  DISALLOW_COPY_AND_ASSIGN(WorkerWebViewDelegate);
};

namespace WebKit {

WebWorker* WebWorker::create(WebWorkerClient* client) {
  return new WebWorkerImpl(client);
}

}

// This function is called on the main thread to force to initialize some static
// values used in WebKit before any worker thread is started. This is because in
// our worker processs, we do not run any WebKit code in main thread and thus
// when multiple workers try to start at the same time, we might hit crash due
// to contention for initializing static values.
void InitializeWebKitStaticValues() {
  static bool initialized = false;
  if (!initialized) {
    initialized= true;
    // Note that we have to pass a URL with valid protocol in order to follow
    // the path to do static value initializations.
    WTF::RefPtr<WebCore::SecurityOrigin> origin =
        WebCore::SecurityOrigin::create(WebCore::KURL("http://localhost"));
    origin.release();
  }
}

WebWorkerImpl::WebWorkerImpl(WebWorkerClient* client)
 : client_(client),
   web_view_(NULL) {
  InitializeWebKitStaticValues();
}

WebWorkerImpl::~WebWorkerImpl() {
  web_view_->Close();
}

void WebWorkerImpl::PostMessageToWorkerContextTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    const WebCore::String& message) {
  DCHECK(context->isWorkerContext());
  WebCore::WorkerContext* worker_context =
      static_cast<WebCore::WorkerContext*>(context);
  worker_context->dispatchMessage(message);

  this_ptr->confirmMessageFromWorkerObject(
      worker_context->hasPendingActivity());
}

// WebWorker -------------------------------------------------------------------

void WebWorkerImpl::startWorkerContext(const WebURL& script_url,
                                       const WebString& user_agent,
                                       const WebString& source_code) {
  // Create 'shadow page'. This page is never displayed, it is used to proxy the
  // loading requests from the worker context to the rest of WebKit and Chromium
  // infrastructure.
  DCHECK(!web_view_);
  web_view_ = WebView::Create(WorkerWebViewDelegate::worker_delegate(),
                              WebPreferences());

  WebFrameImpl* web_frame =
      static_cast<WebFrameImpl*>(web_view_->GetMainFrame());

  // Construct substitute data source for the 'shadow page'. We only need it
  // to have same origin as the worker so the loading checks work correctly.
  WebCore::CString content("");
  int len = static_cast<int>(content.length());
  RefPtr<WebCore::SharedBuffer> buf(
      WebCore::SharedBuffer::create(content.data(), len));
  WebCore::SubstituteData subst_data(buf,
                                     WebCore::String("text/html"),
                                     WebCore::String("UTF-8"),
                                     WebCore::KURL());
  WebCore::ResourceRequest request(webkit_glue::GURLToKURL(script_url),
                                   WebCore::CString());
  web_frame->frame()->loader()->load(request, subst_data, false);

  // This document will be used as 'loading context' for the worker.
  loading_document_ = web_frame->frame()->document();

  worker_thread_ = WebCore::WorkerThread::create(
      webkit_glue::WebURLToKURL(script_url),
      webkit_glue::WebStringToString(user_agent),
      webkit_glue::WebStringToString(source_code),
      *this,
      *this);

  // Worker initialization means a pending activity.
  reportPendingActivity(true);

  worker_thread_->start();
}

void WebWorkerImpl::terminateWorkerContext() {
  worker_thread_->stop();
}

void WebWorkerImpl::postMessageToWorkerContext(const WebString& message) {
  worker_thread_->runLoop().postTask(WebCore::createCallbackTask(
      &PostMessageToWorkerContextTask,
      this,
      webkit_glue::WebStringToString(message)));
}

void WebWorkerImpl::workerObjectDestroyed() {
}

void WebWorkerImpl::DispatchTaskToMainThread(
    PassRefPtr<WebCore::ScriptExecutionContext::Task> task) {
  return WTF::callOnMainThread(InvokeTaskMethod, task.releaseRef());
}

void WebWorkerImpl::InvokeTaskMethod(void* param) {
  WebCore::ScriptExecutionContext::Task* task =
      static_cast<WebCore::ScriptExecutionContext::Task*>(param);
  task->performTask(NULL);
  task->deref();
}

// WorkerObjectProxy -----------------------------------------------------------

void WebWorkerImpl::postMessageToWorkerObject(const WebCore::String& message) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &PostMessageTask,
      this,
      message));
}

void WebWorkerImpl::PostMessageTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    WebCore::String message) {
  this_ptr->client_->postMessageToWorkerObject(
      webkit_glue::StringToWebString(message));
}

void WebWorkerImpl::postExceptionToWorkerObject(
    const WebCore::String& error_message,
    int line_number,
    const WebCore::String& source_url) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &PostExceptionTask,
      this,
      error_message,
      line_number,
      source_url));
}

void WebWorkerImpl::PostExceptionTask(
      WebCore::ScriptExecutionContext* context,
      WebWorkerImpl* this_ptr,
      const WebCore::String& error_message,
      int line_number,
      const WebCore::String& source_url) {
  this_ptr->client_->postExceptionToWorkerObject(
      webkit_glue::StringToWebString(error_message),
      line_number,
      webkit_glue::StringToWebString(source_url));
}

void WebWorkerImpl::postConsoleMessageToWorkerObject(
    WebCore::MessageDestination destination,
    WebCore::MessageSource source,
    WebCore::MessageLevel level,
    const WebCore::String& message,
    int line_number,
    const WebCore::String& source_url) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &PostConsoleMessageTask,
      this,
      static_cast<int>(destination),
      static_cast<int>(source),
      static_cast<int>(level),
      message,
      line_number,
      source_url));
}

void WebWorkerImpl::PostConsoleMessageTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    int destination,
    int source,
    int level,
    const WebCore::String& message,
    int line_number,
    const WebCore::String& source_url) {
  this_ptr->client_->postConsoleMessageToWorkerObject(
      destination,
      source,
      level,
      webkit_glue::StringToWebString(message),
      line_number,
      webkit_glue::StringToWebString(source_url));
}

void WebWorkerImpl::confirmMessageFromWorkerObject(bool has_pending_activity) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &ConfirmMessageTask,
      this,
      has_pending_activity));
}

void WebWorkerImpl::ConfirmMessageTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    bool has_pending_activity) {
  this_ptr->client_->confirmMessageFromWorkerObject(has_pending_activity);
}

void WebWorkerImpl::reportPendingActivity(bool has_pending_activity) {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &ReportPendingActivityTask,
      this,
      has_pending_activity));
}

void WebWorkerImpl::ReportPendingActivityTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr,
    bool has_pending_activity) {
  this_ptr->client_->reportPendingActivity(has_pending_activity);
}

void WebWorkerImpl::workerContextDestroyed() {
  DispatchTaskToMainThread(WebCore::createCallbackTask(
      &WorkerContextDestroyedTask,
      this));
}

// WorkerLoaderProxy -----------------------------------------------------------

void WebWorkerImpl::postTaskToLoader(
    PassRefPtr<WebCore::ScriptExecutionContext::Task> task) {
  ASSERT(loading_document_->isDocument());
  loading_document_->postTask(task);
}

void WebWorkerImpl::postTaskForModeToWorkerContext(
    PassRefPtr<WebCore::ScriptExecutionContext::Task> task,
    const WebCore::String& mode) {
  worker_thread_->runLoop().postTaskForMode(task, mode);
}

void WebWorkerImpl::WorkerContextDestroyedTask(
    WebCore::ScriptExecutionContext* context,
    WebWorkerImpl* this_ptr) {
  this_ptr->client_->workerContextDestroyed();

  // The lifetime of this proxy is controlled by the worker context.
  delete this_ptr;
}

#else

namespace WebKit {

WebWorker* WebWorker::create(WebWorkerClient* client) {
  return NULL;
}

}

#endif
<|endoftext|>


<commit_before>#ifndef color_internal_convert_eebe72e3_2da8_4199_b3cc_e5ee4518b7d5
#define color_internal_convert_eebe72e3_2da8_4199_b3cc_e5ee4518b7d5

#include "./trait.hpp"

namespace color
 {
  namespace _internal
   {

    template< typename category_left_name, typename category_right_name>
     struct convert
      {
       public:

         typedef ::color::_internal::trait<category_left_name>    left_trait_type;
         typedef ::color::_internal::trait<category_right_name>   right_trait_type;

         static void process
          (
            typename left_trait_type::container_input_type         left
           ,typename right_trait_type:: container_const_input_type right
          )
          {

          }

       };
   }
 }

#endif
<commit_msg>*new: implemented copy for same color category<commit_after>#ifndef color_internal_convert_eebe72e3_2da8_4199_b3cc_e5ee4518b7d5
#define color_internal_convert_eebe72e3_2da8_4199_b3cc_e5ee4518b7d5

#include "./trait.hpp"

namespace color
 {
  namespace _internal
   {

    template< typename category_left_name, typename category_right_name>
     struct convert
      {
       public:

         typedef ::color::_internal::trait<category_left_name>    left_trait_type;
         typedef ::color::_internal::trait<category_right_name>   right_trait_type;

         static void process
          (
            typename left_trait_type::container_input_type         left
           ,typename right_trait_type:: container_const_input_type right
          )
          {

          }
       };

    template< typename category_name>
     struct convert< category_name >
      {
       public:

         typedef ::color::_internal::trait<category_left_name>    left_trait_type;
         typedef ::color::_internal::trait<category_right_name>   right_trait_type;

         static void process
          (
            typename left_trait_type::container_input_type         left
           ,typename right_trait_type:: container_const_input_type right
          )
          {
           left = right;
          }
       };

   }
 }

#endif
<|endoftext|>