<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * BP3Writer.cpp
 *
 *  Created on: Dec 19, 2016
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "BP3Writer.h"
#include "BP3Writer.tcc"

#include "adios2/common/ADIOSMacros.h"
#include "adios2/core/IO.h"
#include "adios2/helper/adiosFunctions.h" //CheckIndexRange
#include "adios2/toolkit/profiling/taustubs/tautimer.hpp"
#include "adios2/toolkit/transport/file/FileFStream.h"

namespace adios2
{
namespace core
{
namespace engine
{

BP3Writer::BP3Writer(IO &io, const std::string &name, const Mode mode,
                     helper::Comm comm)
: Engine("BP3", io, name, mode, std::move(comm)), m_BP3Serializer(m_Comm),
  m_FileDataManager(m_Comm), m_FileMetadataManager(m_Comm)
{
    TAU_SCOPED_TIMER("BP3Writer::Open");
    m_IO.m_ReadStreaming = false;
    m_EndMessage = " in call to IO Open BPFileWriter " + m_Name + "\n";
    Init();
}

StepStatus BP3Writer::BeginStep(StepMode mode, const float timeoutSeconds)
{
    TAU_SCOPED_TIMER("BP3Writer::BeginStep");
    m_BP3Serializer.m_DeferredVariables.clear();
    m_BP3Serializer.m_DeferredVariablesDataSize = 0;
    m_IO.m_ReadStreaming = false;
    return StepStatus::OK;
}

size_t BP3Writer::CurrentStep() const
{
    return m_BP3Serializer.m_MetadataSet.CurrentStep;
}

void BP3Writer::PerformPuts()
{
    TAU_SCOPED_TIMER("BP3Writer::PerformPuts");
    if (m_BP3Serializer.m_DeferredVariables.empty())
    {
        return;
    }

    m_BP3Serializer.ResizeBuffer(m_BP3Serializer.m_DeferredVariablesDataSize,
                                 "in call to PerformPuts");

    for (const std::string &variableName : m_BP3Serializer.m_DeferredVariables)
    {
        const DataType type = m_IO.InquireVariableType(variableName);
        if (type == DataType::Compound)
        {
            // not supported
        }
#define declare_template_instantiation(T)                                      \
    else if (type == helper::GetDataType<T>())                                 \
    {                                                                          \
        Variable<T> &variable = FindVariable<T>(                               \
            variableName, "in call to PerformPuts, EndStep or Close");         \
        PerformPutCommon(variable);                                            \
    }

        ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_template_instantiation)
#undef declare_template_instantiation
    }
    m_BP3Serializer.m_DeferredVariables.clear();
    m_BP3Serializer.m_DeferredVariablesDataSize = 0;
}

void BP3Writer::EndStep()
{
    TAU_SCOPED_TIMER("BP3Writer::EndStep");
    if (m_BP3Serializer.m_DeferredVariables.size() > 0)
    {
        PerformPuts();
    }

    // true: advances step
    m_BP3Serializer.SerializeData(m_IO, true);

    const size_t currentStep = CurrentStep();
    const size_t flushStepsCount = m_BP3Serializer.m_Parameters.FlushStepsCount;

    if (currentStep % flushStepsCount == 0)
    {
        Flush();
    }
}

void BP3Writer::Flush(const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::Flush");
    DoFlush(false, transportIndex);
    m_BP3Serializer.ResetBuffer(m_BP3Serializer.m_Data);

    if (m_BP3Serializer.m_Parameters.CollectiveMetadata)
    {
        WriteCollectiveMetadataFile();
    }
}

// PRIVATE
void BP3Writer::Init()
{
    InitParameters();
    InitTransports();
    InitBPBuffer();
}

#define declare_type(T)                                                        \
    void BP3Writer::DoPut(Variable<T> &variable,                               \
                          typename Variable<T>::Span &span,                    \
                          const size_t bufferID, const T &value)               \
    {                                                                          \
        TAU_SCOPED_TIMER("BP3Writer::Put");                                    \
        PutCommon(variable, span, bufferID, value);                            \
    }

ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_type)
#undef declare_type

#define declare_type(T)                                                        \
    void BP3Writer::DoPutSync(Variable<T> &variable, const T *data)            \
    {                                                                          \
        TAU_SCOPED_TIMER("BP3Writer::Put");                                    \
        PutSyncCommon(variable, variable.SetBlockInfo(data, CurrentStep()));   \
        variable.m_BlocksInfo.pop_back();                                      \
    }                                                                          \
    void BP3Writer::DoPutDeferred(Variable<T> &variable, const T *data)        \
    {                                                                          \
        TAU_SCOPED_TIMER("BP3Writer::Put");                                    \
        PutDeferredCommon(variable, data);                                     \
    }

ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type

void BP3Writer::InitParameters()
{
    m_BP3Serializer.Init(m_IO.m_Parameters, "in call to BP3::Open for writing");
}

void BP3Writer::InitTransports()
{
    // TODO need to add support for aggregators here later
    if (m_IO.m_TransportsParameters.empty())
    {
        Params defaultTransportParameters;
        defaultTransportParameters["transport"] = "File";
        m_IO.m_TransportsParameters.push_back(defaultTransportParameters);
    }

    // only consumers will interact with transport managers
    std::vector<std::string> bpSubStreamNames;

    if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
    {
        // Names passed to IO AddTransport option with key "Name"
        const std::vector<std::string> transportsNames =
            m_FileDataManager.GetFilesBaseNames(m_Name,
                                                m_IO.m_TransportsParameters);

        // /path/name.bp.dir/name.bp.rank
        bpSubStreamNames = m_BP3Serializer.GetBPSubStreamNames(transportsNames);
    }

    m_BP3Serializer.m_Profiler.Start("mkdir");
    m_FileDataManager.MkDirsBarrier(bpSubStreamNames,
                                    m_IO.m_TransportsParameters,
                                    m_BP3Serializer.m_Parameters.NodeLocal);
    m_BP3Serializer.m_Profiler.Stop("mkdir");

    if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
    {
        if (m_BP3Serializer.m_Parameters.AsyncTasks)
        {
            for (size_t i = 0; i < m_IO.m_TransportsParameters.size(); ++i)
            {
                m_IO.m_TransportsParameters[i]["asynctasks"] = "true";
            }
        }
        m_FileDataManager.OpenFiles(bpSubStreamNames, m_OpenMode,
                                    m_IO.m_TransportsParameters,
                                    m_BP3Serializer.m_Profiler.m_IsActive);
    }
}

void BP3Writer::InitBPBuffer()
{
    if (m_OpenMode == Mode::Append)
    {
        throw std::invalid_argument(
            "ADIOS2: Mode::Append is only available BP4; it is not implemented for BP3 files.");
        // TODO: Get last pg timestep and update timestep counter in
    }
    else
    {
        m_BP3Serializer.PutProcessGroupIndex(
            m_IO.m_Name, m_IO.m_HostLanguage,
            m_FileDataManager.GetTransportsTypes());
    }
}

void BP3Writer::DoFlush(const bool isFinal, const int transportIndex)
{
    if (m_BP3Serializer.m_Aggregator.m_IsActive)
    {
        AggregateWriteData(isFinal, transportIndex);
    }
    else
    {
        WriteData(isFinal, transportIndex);
    }
}

void BP3Writer::DoClose(const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::Close");
    if (m_BP3Serializer.m_DeferredVariables.size() > 0)
    {
        PerformPuts();
    }

    DoFlush(true, transportIndex);

    if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
    {
        m_FileDataManager.CloseFiles(transportIndex);
    }

    if (m_BP3Serializer.m_Parameters.CollectiveMetadata &&
        m_FileDataManager.AllTransportsClosed())
    {
        WriteCollectiveMetadataFile(true);
    }

    if (m_BP3Serializer.m_Profiler.m_IsActive &&
        m_FileDataManager.AllTransportsClosed())
    {
        WriteProfilingJSONFile();
    }

    m_BP3Serializer.DeleteBuffers();
}

void BP3Writer::WriteProfilingJSONFile()
{
    TAU_SCOPED_TIMER("BP3Writer::WriteProfilingJSONFile");
    auto transportTypes = m_FileDataManager.GetTransportsTypes();

    // find first File type output, where we can write the profile
    int fileTransportIdx = -1;
    for (size_t i = 0; i < transportTypes.size(); ++i)
    {
        if (transportTypes[i].compare(0, 4, "File") == 0)
        {
            fileTransportIdx = static_cast<int>(i);
        }
    }

    auto transportProfilers = m_FileDataManager.GetTransportsProfilers();

    auto transportTypesMD = m_FileMetadataManager.GetTransportsTypes();
    auto transportProfilersMD = m_FileMetadataManager.GetTransportsProfilers();

    transportTypes.insert(transportTypes.end(), transportTypesMD.begin(),
                          transportTypesMD.end());

    transportProfilers.insert(transportProfilers.end(),
                              transportProfilersMD.begin(),
                              transportProfilersMD.end());

    const std::string lineJSON(m_BP3Serializer.GetRankProfilingJSON(
                                   transportTypes, transportProfilers) +
                               ",\n");

    const std::vector<char> profilingJSON(
        m_BP3Serializer.AggregateProfilingJSON(lineJSON));

    if (m_BP3Serializer.m_RankMPI == 0)
    {
        transport::FileFStream profilingJSONStream(m_Comm);
        std::string profileFileName;
        if (fileTransportIdx > -1)
        {
            // write profile to <filename.bp>.dir/profiling.json
            auto bpBaseNames = m_BP3Serializer.GetBPBaseNames({m_Name});
            profileFileName = bpBaseNames[fileTransportIdx] + "/profiling.json";
        }
        else
        {
            // write profile to <filename.bp>_profiling.json
            auto transportsNames = m_FileMetadataManager.GetFilesBaseNames(
                m_Name, m_IO.m_TransportsParameters);

            auto bpMetadataFileNames =
                m_BP3Serializer.GetBPMetadataFileNames(transportsNames);
            profileFileName = bpMetadataFileNames[0] + "_profiling.json";
        }
        profilingJSONStream.Open(profileFileName, Mode::Write);
        profilingJSONStream.Write(profilingJSON.data(), profilingJSON.size());
        profilingJSONStream.Close();
    }
}

void BP3Writer::WriteCollectiveMetadataFile(const bool isFinal)
{
    TAU_SCOPED_TIMER("BP3Writer::WriteCollectiveMetadataFile");
    m_BP3Serializer.AggregateCollectiveMetadata(
        m_Comm, m_BP3Serializer.m_Metadata, true);

    if (m_BP3Serializer.m_RankMPI == 0)
    {
        // first init metadata files
        const std::vector<std::string> transportsNames =
            m_FileMetadataManager.GetFilesBaseNames(
                m_Name, m_IO.m_TransportsParameters);

        const std::vector<std::string> bpMetadataFileNames =
            m_BP3Serializer.GetBPMetadataFileNames(transportsNames);

        m_FileMetadataManager.OpenFiles(bpMetadataFileNames, m_OpenMode,
                                        m_IO.m_TransportsParameters,
                                        m_BP3Serializer.m_Profiler.m_IsActive);

        m_FileMetadataManager.WriteFiles(
            m_BP3Serializer.m_Metadata.m_Buffer.data(),
            m_BP3Serializer.m_Metadata.m_Position);
        m_FileMetadataManager.CloseFiles();

        if (!isFinal)
        {
            m_BP3Serializer.ResetBuffer(m_BP3Serializer.m_Metadata, true);
            m_FileMetadataManager.m_Transports.clear();
        }
    }
}

void BP3Writer::WriteData(const bool isFinal, const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::WriteData");
    size_t dataSize = m_BP3Serializer.m_Data.m_Position;

    if (isFinal)
    {
        m_BP3Serializer.CloseData(m_IO);
        dataSize = m_BP3Serializer.m_Data.m_Position;
    }
    else
    {
        m_BP3Serializer.CloseStream(m_IO);
    }

    m_FileDataManager.WriteFiles(m_BP3Serializer.m_Data.m_Buffer.data(),
                                 dataSize, transportIndex);

    m_FileDataManager.FlushFiles(transportIndex);
}

void BP3Writer::AggregateWriteData(const bool isFinal, const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::AggregateWriteData");
    m_BP3Serializer.CloseStream(m_IO, false);

    // async?
    for (int r = 0; r < m_BP3Serializer.m_Aggregator.m_Size; ++r)
    {
        aggregator::MPIAggregator::ExchangeRequests dataRequests =
            m_BP3Serializer.m_Aggregator.IExchange(m_BP3Serializer.m_Data, r);

        aggregator::MPIAggregator::ExchangeAbsolutePositionRequests
            absolutePositionRequests =
                m_BP3Serializer.m_Aggregator.IExchangeAbsolutePosition(
                    m_BP3Serializer.m_Data, r);

        if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
        {
            const format::Buffer &bufferSTL =
                m_BP3Serializer.m_Aggregator.GetConsumerBuffer(
                    m_BP3Serializer.m_Data);

            m_FileDataManager.WriteFiles(bufferSTL.Data(), bufferSTL.m_Position,
                                         transportIndex);

            m_FileDataManager.FlushFiles(transportIndex);
        }

        m_BP3Serializer.m_Aggregator.WaitAbsolutePosition(
            absolutePositionRequests, r);

        m_BP3Serializer.m_Aggregator.Wait(dataRequests, r);
        m_BP3Serializer.m_Aggregator.SwapBuffers(r);
    }

    m_BP3Serializer.UpdateOffsetsInMetadata();

    if (isFinal) // Write metadata footer
    {
        format::BufferSTL &bufferSTL = m_BP3Serializer.m_Data;
        m_BP3Serializer.ResetBuffer(bufferSTL, false, false);

        m_BP3Serializer.AggregateCollectiveMetadata(
            m_BP3Serializer.m_Aggregator.m_Comm, bufferSTL, false);

        if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
        {
            m_FileDataManager.WriteFiles(bufferSTL.m_Buffer.data(),
                                         bufferSTL.m_Position, transportIndex);

            m_FileDataManager.FlushFiles(transportIndex);
        }

        m_BP3Serializer.m_Aggregator.Close();
    }

    m_BP3Serializer.m_Aggregator.ResetBuffers();
}

#define declare_type(T, L)                                                     \
    T *BP3Writer::DoBufferData_##L(const size_t payloadPosition,               \
                                   const size_t bufferID) noexcept             \
    {                                                                          \
        return BufferDataCommon<T>(payloadPosition, bufferID);                 \
    }

ADIOS2_FOREACH_PRIMITVE_STDTYPE_2ARGS(declare_type)
#undef declare_type

size_t BP3Writer::DebugGetDataBufferSize() const
{
    return m_BP3Serializer.DebugGetDataBufferSize();
}
} // end namespace engine
} // end namespace core
} // end namespace adios2
<commit_msg>Apply clang-format.<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * BP3Writer.cpp
 *
 *  Created on: Dec 19, 2016
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "BP3Writer.h"
#include "BP3Writer.tcc"

#include "adios2/common/ADIOSMacros.h"
#include "adios2/core/IO.h"
#include "adios2/helper/adiosFunctions.h" //CheckIndexRange
#include "adios2/toolkit/profiling/taustubs/tautimer.hpp"
#include "adios2/toolkit/transport/file/FileFStream.h"

namespace adios2
{
namespace core
{
namespace engine
{

BP3Writer::BP3Writer(IO &io, const std::string &name, const Mode mode,
                     helper::Comm comm)
: Engine("BP3", io, name, mode, std::move(comm)), m_BP3Serializer(m_Comm),
  m_FileDataManager(m_Comm), m_FileMetadataManager(m_Comm)
{
    TAU_SCOPED_TIMER("BP3Writer::Open");
    m_IO.m_ReadStreaming = false;
    m_EndMessage = " in call to IO Open BPFileWriter " + m_Name + "\n";
    Init();
}

StepStatus BP3Writer::BeginStep(StepMode mode, const float timeoutSeconds)
{
    TAU_SCOPED_TIMER("BP3Writer::BeginStep");
    m_BP3Serializer.m_DeferredVariables.clear();
    m_BP3Serializer.m_DeferredVariablesDataSize = 0;
    m_IO.m_ReadStreaming = false;
    return StepStatus::OK;
}

size_t BP3Writer::CurrentStep() const
{
    return m_BP3Serializer.m_MetadataSet.CurrentStep;
}

void BP3Writer::PerformPuts()
{
    TAU_SCOPED_TIMER("BP3Writer::PerformPuts");
    if (m_BP3Serializer.m_DeferredVariables.empty())
    {
        return;
    }

    m_BP3Serializer.ResizeBuffer(m_BP3Serializer.m_DeferredVariablesDataSize,
                                 "in call to PerformPuts");

    for (const std::string &variableName : m_BP3Serializer.m_DeferredVariables)
    {
        const DataType type = m_IO.InquireVariableType(variableName);
        if (type == DataType::Compound)
        {
            // not supported
        }
#define declare_template_instantiation(T)                                      \
    else if (type == helper::GetDataType<T>())                                 \
    {                                                                          \
        Variable<T> &variable = FindVariable<T>(                               \
            variableName, "in call to PerformPuts, EndStep or Close");         \
        PerformPutCommon(variable);                                            \
    }

        ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_template_instantiation)
#undef declare_template_instantiation
    }
    m_BP3Serializer.m_DeferredVariables.clear();
    m_BP3Serializer.m_DeferredVariablesDataSize = 0;
}

void BP3Writer::EndStep()
{
    TAU_SCOPED_TIMER("BP3Writer::EndStep");
    if (m_BP3Serializer.m_DeferredVariables.size() > 0)
    {
        PerformPuts();
    }

    // true: advances step
    m_BP3Serializer.SerializeData(m_IO, true);

    const size_t currentStep = CurrentStep();
    const size_t flushStepsCount = m_BP3Serializer.m_Parameters.FlushStepsCount;

    if (currentStep % flushStepsCount == 0)
    {
        Flush();
    }
}

void BP3Writer::Flush(const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::Flush");
    DoFlush(false, transportIndex);
    m_BP3Serializer.ResetBuffer(m_BP3Serializer.m_Data);

    if (m_BP3Serializer.m_Parameters.CollectiveMetadata)
    {
        WriteCollectiveMetadataFile();
    }
}

// PRIVATE
void BP3Writer::Init()
{
    InitParameters();
    InitTransports();
    InitBPBuffer();
}

#define declare_type(T)                                                        \
    void BP3Writer::DoPut(Variable<T> &variable,                               \
                          typename Variable<T>::Span &span,                    \
                          const size_t bufferID, const T &value)               \
    {                                                                          \
        TAU_SCOPED_TIMER("BP3Writer::Put");                                    \
        PutCommon(variable, span, bufferID, value);                            \
    }

ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_type)
#undef declare_type

#define declare_type(T)                                                        \
    void BP3Writer::DoPutSync(Variable<T> &variable, const T *data)            \
    {                                                                          \
        TAU_SCOPED_TIMER("BP3Writer::Put");                                    \
        PutSyncCommon(variable, variable.SetBlockInfo(data, CurrentStep()));   \
        variable.m_BlocksInfo.pop_back();                                      \
    }                                                                          \
    void BP3Writer::DoPutDeferred(Variable<T> &variable, const T *data)        \
    {                                                                          \
        TAU_SCOPED_TIMER("BP3Writer::Put");                                    \
        PutDeferredCommon(variable, data);                                     \
    }

ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type

void BP3Writer::InitParameters()
{
    m_BP3Serializer.Init(m_IO.m_Parameters, "in call to BP3::Open for writing");
}

void BP3Writer::InitTransports()
{
    // TODO need to add support for aggregators here later
    if (m_IO.m_TransportsParameters.empty())
    {
        Params defaultTransportParameters;
        defaultTransportParameters["transport"] = "File";
        m_IO.m_TransportsParameters.push_back(defaultTransportParameters);
    }

    // only consumers will interact with transport managers
    std::vector<std::string> bpSubStreamNames;

    if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
    {
        // Names passed to IO AddTransport option with key "Name"
        const std::vector<std::string> transportsNames =
            m_FileDataManager.GetFilesBaseNames(m_Name,
                                                m_IO.m_TransportsParameters);

        // /path/name.bp.dir/name.bp.rank
        bpSubStreamNames = m_BP3Serializer.GetBPSubStreamNames(transportsNames);
    }

    m_BP3Serializer.m_Profiler.Start("mkdir");
    m_FileDataManager.MkDirsBarrier(bpSubStreamNames,
                                    m_IO.m_TransportsParameters,
                                    m_BP3Serializer.m_Parameters.NodeLocal);
    m_BP3Serializer.m_Profiler.Stop("mkdir");

    if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
    {
        if (m_BP3Serializer.m_Parameters.AsyncTasks)
        {
            for (size_t i = 0; i < m_IO.m_TransportsParameters.size(); ++i)
            {
                m_IO.m_TransportsParameters[i]["asynctasks"] = "true";
            }
        }
        m_FileDataManager.OpenFiles(bpSubStreamNames, m_OpenMode,
                                    m_IO.m_TransportsParameters,
                                    m_BP3Serializer.m_Profiler.m_IsActive);
    }
}

void BP3Writer::InitBPBuffer()
{
    if (m_OpenMode == Mode::Append)
    {
        throw std::invalid_argument(
            "ADIOS2: Mode::Append is only available BP4; it is not implemented "
            "for BP3 files.");
        // TODO: Get last pg timestep and update timestep counter in
    }
    else
    {
        m_BP3Serializer.PutProcessGroupIndex(
            m_IO.m_Name, m_IO.m_HostLanguage,
            m_FileDataManager.GetTransportsTypes());
    }
}

void BP3Writer::DoFlush(const bool isFinal, const int transportIndex)
{
    if (m_BP3Serializer.m_Aggregator.m_IsActive)
    {
        AggregateWriteData(isFinal, transportIndex);
    }
    else
    {
        WriteData(isFinal, transportIndex);
    }
}

void BP3Writer::DoClose(const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::Close");
    if (m_BP3Serializer.m_DeferredVariables.size() > 0)
    {
        PerformPuts();
    }

    DoFlush(true, transportIndex);

    if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
    {
        m_FileDataManager.CloseFiles(transportIndex);
    }

    if (m_BP3Serializer.m_Parameters.CollectiveMetadata &&
        m_FileDataManager.AllTransportsClosed())
    {
        WriteCollectiveMetadataFile(true);
    }

    if (m_BP3Serializer.m_Profiler.m_IsActive &&
        m_FileDataManager.AllTransportsClosed())
    {
        WriteProfilingJSONFile();
    }

    m_BP3Serializer.DeleteBuffers();
}

void BP3Writer::WriteProfilingJSONFile()
{
    TAU_SCOPED_TIMER("BP3Writer::WriteProfilingJSONFile");
    auto transportTypes = m_FileDataManager.GetTransportsTypes();

    // find first File type output, where we can write the profile
    int fileTransportIdx = -1;
    for (size_t i = 0; i < transportTypes.size(); ++i)
    {
        if (transportTypes[i].compare(0, 4, "File") == 0)
        {
            fileTransportIdx = static_cast<int>(i);
        }
    }

    auto transportProfilers = m_FileDataManager.GetTransportsProfilers();

    auto transportTypesMD = m_FileMetadataManager.GetTransportsTypes();
    auto transportProfilersMD = m_FileMetadataManager.GetTransportsProfilers();

    transportTypes.insert(transportTypes.end(), transportTypesMD.begin(),
                          transportTypesMD.end());

    transportProfilers.insert(transportProfilers.end(),
                              transportProfilersMD.begin(),
                              transportProfilersMD.end());

    const std::string lineJSON(m_BP3Serializer.GetRankProfilingJSON(
                                   transportTypes, transportProfilers) +
                               ",\n");

    const std::vector<char> profilingJSON(
        m_BP3Serializer.AggregateProfilingJSON(lineJSON));

    if (m_BP3Serializer.m_RankMPI == 0)
    {
        transport::FileFStream profilingJSONStream(m_Comm);
        std::string profileFileName;
        if (fileTransportIdx > -1)
        {
            // write profile to <filename.bp>.dir/profiling.json
            auto bpBaseNames = m_BP3Serializer.GetBPBaseNames({m_Name});
            profileFileName = bpBaseNames[fileTransportIdx] + "/profiling.json";
        }
        else
        {
            // write profile to <filename.bp>_profiling.json
            auto transportsNames = m_FileMetadataManager.GetFilesBaseNames(
                m_Name, m_IO.m_TransportsParameters);

            auto bpMetadataFileNames =
                m_BP3Serializer.GetBPMetadataFileNames(transportsNames);
            profileFileName = bpMetadataFileNames[0] + "_profiling.json";
        }
        profilingJSONStream.Open(profileFileName, Mode::Write);
        profilingJSONStream.Write(profilingJSON.data(), profilingJSON.size());
        profilingJSONStream.Close();
    }
}

void BP3Writer::WriteCollectiveMetadataFile(const bool isFinal)
{
    TAU_SCOPED_TIMER("BP3Writer::WriteCollectiveMetadataFile");
    m_BP3Serializer.AggregateCollectiveMetadata(
        m_Comm, m_BP3Serializer.m_Metadata, true);

    if (m_BP3Serializer.m_RankMPI == 0)
    {
        // first init metadata files
        const std::vector<std::string> transportsNames =
            m_FileMetadataManager.GetFilesBaseNames(
                m_Name, m_IO.m_TransportsParameters);

        const std::vector<std::string> bpMetadataFileNames =
            m_BP3Serializer.GetBPMetadataFileNames(transportsNames);

        m_FileMetadataManager.OpenFiles(bpMetadataFileNames, m_OpenMode,
                                        m_IO.m_TransportsParameters,
                                        m_BP3Serializer.m_Profiler.m_IsActive);

        m_FileMetadataManager.WriteFiles(
            m_BP3Serializer.m_Metadata.m_Buffer.data(),
            m_BP3Serializer.m_Metadata.m_Position);
        m_FileMetadataManager.CloseFiles();

        if (!isFinal)
        {
            m_BP3Serializer.ResetBuffer(m_BP3Serializer.m_Metadata, true);
            m_FileMetadataManager.m_Transports.clear();
        }
    }
}

void BP3Writer::WriteData(const bool isFinal, const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::WriteData");
    size_t dataSize = m_BP3Serializer.m_Data.m_Position;

    if (isFinal)
    {
        m_BP3Serializer.CloseData(m_IO);
        dataSize = m_BP3Serializer.m_Data.m_Position;
    }
    else
    {
        m_BP3Serializer.CloseStream(m_IO);
    }

    m_FileDataManager.WriteFiles(m_BP3Serializer.m_Data.m_Buffer.data(),
                                 dataSize, transportIndex);

    m_FileDataManager.FlushFiles(transportIndex);
}

void BP3Writer::AggregateWriteData(const bool isFinal, const int transportIndex)
{
    TAU_SCOPED_TIMER("BP3Writer::AggregateWriteData");
    m_BP3Serializer.CloseStream(m_IO, false);

    // async?
    for (int r = 0; r < m_BP3Serializer.m_Aggregator.m_Size; ++r)
    {
        aggregator::MPIAggregator::ExchangeRequests dataRequests =
            m_BP3Serializer.m_Aggregator.IExchange(m_BP3Serializer.m_Data, r);

        aggregator::MPIAggregator::ExchangeAbsolutePositionRequests
            absolutePositionRequests =
                m_BP3Serializer.m_Aggregator.IExchangeAbsolutePosition(
                    m_BP3Serializer.m_Data, r);

        if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
        {
            const format::Buffer &bufferSTL =
                m_BP3Serializer.m_Aggregator.GetConsumerBuffer(
                    m_BP3Serializer.m_Data);

            m_FileDataManager.WriteFiles(bufferSTL.Data(), bufferSTL.m_Position,
                                         transportIndex);

            m_FileDataManager.FlushFiles(transportIndex);
        }

        m_BP3Serializer.m_Aggregator.WaitAbsolutePosition(
            absolutePositionRequests, r);

        m_BP3Serializer.m_Aggregator.Wait(dataRequests, r);
        m_BP3Serializer.m_Aggregator.SwapBuffers(r);
    }

    m_BP3Serializer.UpdateOffsetsInMetadata();

    if (isFinal) // Write metadata footer
    {
        format::BufferSTL &bufferSTL = m_BP3Serializer.m_Data;
        m_BP3Serializer.ResetBuffer(bufferSTL, false, false);

        m_BP3Serializer.AggregateCollectiveMetadata(
            m_BP3Serializer.m_Aggregator.m_Comm, bufferSTL, false);

        if (m_BP3Serializer.m_Aggregator.m_IsConsumer)
        {
            m_FileDataManager.WriteFiles(bufferSTL.m_Buffer.data(),
                                         bufferSTL.m_Position, transportIndex);

            m_FileDataManager.FlushFiles(transportIndex);
        }

        m_BP3Serializer.m_Aggregator.Close();
    }

    m_BP3Serializer.m_Aggregator.ResetBuffers();
}

#define declare_type(T, L)                                                     \
    T *BP3Writer::DoBufferData_##L(const size_t payloadPosition,               \
                                   const size_t bufferID) noexcept             \
    {                                                                          \
        return BufferDataCommon<T>(payloadPosition, bufferID);                 \
    }

ADIOS2_FOREACH_PRIMITVE_STDTYPE_2ARGS(declare_type)
#undef declare_type

size_t BP3Writer::DebugGetDataBufferSize() const
{
    return m_BP3Serializer.DebugGetDataBufferSize();
}
} // end namespace engine
} // end namespace core
} // end namespace adios2
<|endoftext|>


<commit_before>/*! @file wavelet_filter_bank.cc
 *  @brief Wavelet filter bank tree (mid level).
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include "src/primitives/wavelet_filter_bank.h"
#include <cassert>
#include <string.h>
#include <algorithm>
#include <list>
#include <memory>
#include <string>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/regex.hpp>  // NOLINT(build/include_order)
#pragma GCC diagnostic pop
#include <simd/wavelet.h>

namespace SoundFeatureExtraction {
namespace Primitives {

const std::unordered_map<std::string, WaveletType>
    WaveletFilterBank::kWaveletTypeStrMap = {
  { "daub", WAVELET_TYPE_DAUBECHIES },
  { "coif", WAVELET_TYPE_COIFLET },
  { "sym", WAVELET_TYPE_SYMLET }
};

WaveletFilterBank::WaveletFilterBank(WaveletType type, int order,
                                     const std::vector<int>& treeDescription)
    : type_(type),
      order_(order),
      tree_(treeDescription) {

  ValidateDescription(treeDescription);
}

WaveletFilterBank::WaveletFilterBank(WaveletType type, int order,
                                     std::vector<int>&& treeDescription)
    : type_(type),
      order_(order),
      tree_(treeDescription) {
  ValidateDescription(treeDescription);
}

void WaveletFilterBank::ValidateOrder(WaveletType type,
                                      int order) {
  if (!wavelet_validate_order(type, order)) {
    throw WaveletTreeInvalidOrderException(type, order);
  }
}

std::string WaveletFilterBank::WaveletTypeToString(WaveletType type) noexcept {
  for (auto wtstrp : kWaveletTypeStrMap) {
    if (wtstrp.second == type) {
      return wtstrp.first;
    }
  }
  return "";
}

WaveletType WaveletFilterBank::ParseWaveletType(const std::string& value) {
  auto it = kWaveletTypeStrMap.find(value);
  if (it == kWaveletTypeStrMap.end()) {
    throw WaveletTreeWaveletTypeParseException(value);
  }
  return it->second;
}

void WaveletFilterBank::ValidateDescription(
    const std::vector<int>& treeDescription) {
  if (treeDescription.size() < 2) {
    throw WaveletTreeInvalidDescriptionException(treeDescription);
  }
  std::list<int> tree(treeDescription.begin(), treeDescription.end());
  while (!tree.empty()) {
    // Reduce the tree using a simple grammar:
    // (n) (n) -> (n - 1)
    bool reduced = false;
    for (auto it = tree.begin(); it != tree.end(); it++) {
       auto next = it;
       next++;
       if (next != tree.end() && *it == *next) {
         if (*it == 1 && tree.size() == 2) {
           tree.erase(it, tree.end());
         } else {
           *it = *it - 1;
           tree.erase(next);
         }
         reduced = true;
         break;
       }
    }
    if (!reduced) {
      throw WaveletTreeInvalidDescriptionException(treeDescription);
    }
  }
}

std::vector<int> WaveletFilterBank::ParseDescription(const std::string& str) {
  static const boost::regex allRegex("^\\s*(\\d+\\s*(\\s|$))+");
  static const boost::regex intRegex("(\\d+\\s*(\\s|$))");
  static const boost::sregex_token_iterator empty;

  boost::smatch match;
  if (!boost::regex_match(str, match, allRegex)) {
    throw WaveletTreeDescriptionParseException(str);
  }
  boost::sregex_token_iterator intIterator(
          str.begin(), str.end(), intRegex, 1);

  std::vector<int> res;
  while (intIterator != empty) {
    std::string intstr = *intIterator++;
    int val;
    try {
      val = std::stoi(intstr);
    }
    catch(const std::invalid_argument& e) {
      throw WaveletTreeDescriptionParseException(str);
    }
    res.push_back(val);
  }
  if (res.empty()) {
    throw WaveletTreeDescriptionParseException(str);
  }
  ValidateDescription(res);
  return res;
}

std::string WaveletFilterBank::DescriptionToString(
    const std::vector<int>& treeDescription) noexcept {
  std::string str;
  for (int i : treeDescription) {
    str += std::to_string(i) + " ";
  }
  if (str != "") {
    str.resize(str.size() - 1);
  }
  return str;
}

void WaveletFilterBank::ValidateLength(
    const std::vector<int>& tree, size_t length) {
  int max = *std::max_element(tree.begin(), tree.end());
  // length / 2^max >= 1
  if (length == 0 || length % (1 << max) != 0) {
    throw WaveletTreeInvalidSourceLengthException(tree, length);
  }
}

void WaveletFilterBank::Apply(const float* source, size_t length,
                              float *result) noexcept {
  assert(source && result);
  ValidateLength(tree_, length);

  // Support zero-copy
  auto lsrc =
#ifndef __AVX__
      (source == result)? result :
#endif
      wavelet_prepare_array(order_, source, length);
  ApplyInternal(lsrc, length, result);
#ifndef __AVX__
  if (source != result) {
#endif
  free(lsrc);
#ifndef __AVX__
  }
#endif
}

void WaveletFilterBank::ApplyInternal(float* source, size_t length,
                                      float *result) noexcept {
  assert(source && result);
  ValidateLength(tree_, length);

  std::vector<int> tree(tree_);
  std::reverse(tree.begin(), tree.end());
  std::vector<int> workingTree;
  workingTree.reserve(tree.size());

  auto ldesthi = std::unique_ptr<float, void(*)(void*)>(
      wavelet_allocate_destination(order_, length), free);
  auto ldestlo = std::unique_ptr<float, void(*)(void*)>(
      wavelet_allocate_destination(order_, length), free);
  wavelet_apply(type_, order_, source, length,
                ldesthi.get(), ldestlo.get());
  float *desthihi, *desthilo, *destlohi, *destlolo;
  wavelet_recycle_source(order_, source, length,
                         &desthihi, &desthilo,
                         &destlohi, &destlolo);
  workingTree.push_back(1);
  workingTree.push_back(1);

  while (!tree.empty()) {
    RecursivelyIterate(type_, order_, length / 2, &tree, &workingTree,
                       ldesthi.get(), desthihi, desthilo, &result);
    RecursivelyIterate(type_, order_, length / 2, &tree, &workingTree,
                       ldestlo.get(), destlohi, destlolo, &result);
  }
}

void WaveletFilterBank::RecursivelyIterate(
    WaveletType type, int order, size_t length,
    std::vector<int> *tree, std::vector<int>* workingTree, float* source,
    float* desthi, float* destlo, float** result) noexcept {
  if (tree->back() != workingTree->back()) {
    wavelet_apply(type, order, source, length, desthi, destlo);
    float *desthihi, *desthilo, *destlohi, *destlolo;
    wavelet_recycle_source(order, source, length,
                           &desthihi, &desthilo,
                           &destlohi, &destlolo);
    int next = workingTree->back() + 1;
    workingTree->pop_back();
    workingTree->push_back(next);
    workingTree->push_back(next);
    RecursivelyIterate(type, order, length / 2, tree, workingTree,
                       desthi, desthihi, desthilo, result);
    RecursivelyIterate(type, order, length / 2, tree, workingTree,
                       destlo, destlohi, destlolo, result);
  } else {
    memcpy(*result, source, length * sizeof(source[0]));
    *result += length;
    tree->pop_back();
    workingTree->pop_back();
  }
}

}  // namespace Primitives
}  // namespace SoundFeatureExtraction
<commit_msg>Updated WaveletFilterBank to set signal extension type<commit_after>/*! @file wavelet_filter_bank.cc
 *  @brief Wavelet filter bank tree (mid level).
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include "src/primitives/wavelet_filter_bank.h"
#include <cassert>
#include <string.h>
#include <algorithm>
#include <list>
#include <memory>
#include <string>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/regex.hpp>  // NOLINT(build/include_order)
#pragma GCC diagnostic pop
#include <simd/wavelet.h>

namespace SoundFeatureExtraction {
namespace Primitives {

const std::unordered_map<std::string, WaveletType>
    WaveletFilterBank::kWaveletTypeStrMap = {
  { "daub", WAVELET_TYPE_DAUBECHIES },
  { "coif", WAVELET_TYPE_COIFLET },
  { "sym", WAVELET_TYPE_SYMLET }
};

WaveletFilterBank::WaveletFilterBank(WaveletType type, int order,
                                     const std::vector<int>& treeDescription)
    : type_(type),
      order_(order),
      tree_(treeDescription) {

  ValidateDescription(treeDescription);
}

WaveletFilterBank::WaveletFilterBank(WaveletType type, int order,
                                     std::vector<int>&& treeDescription)
    : type_(type),
      order_(order),
      tree_(treeDescription) {
  ValidateDescription(treeDescription);
}

void WaveletFilterBank::ValidateOrder(WaveletType type,
                                      int order) {
  if (!wavelet_validate_order(type, order)) {
    throw WaveletTreeInvalidOrderException(type, order);
  }
}

std::string WaveletFilterBank::WaveletTypeToString(WaveletType type) noexcept {
  for (auto wtstrp : kWaveletTypeStrMap) {
    if (wtstrp.second == type) {
      return wtstrp.first;
    }
  }
  return "";
}

WaveletType WaveletFilterBank::ParseWaveletType(const std::string& value) {
  auto it = kWaveletTypeStrMap.find(value);
  if (it == kWaveletTypeStrMap.end()) {
    throw WaveletTreeWaveletTypeParseException(value);
  }
  return it->second;
}

void WaveletFilterBank::ValidateDescription(
    const std::vector<int>& treeDescription) {
  if (treeDescription.size() < 2) {
    throw WaveletTreeInvalidDescriptionException(treeDescription);
  }
  std::list<int> tree(treeDescription.begin(), treeDescription.end());
  while (!tree.empty()) {
    // Reduce the tree using a simple grammar:
    // (n) (n) -> (n - 1)
    bool reduced = false;
    for (auto it = tree.begin(); it != tree.end(); it++) {
       auto next = it;
       next++;
       if (next != tree.end() && *it == *next) {
         if (*it == 1 && tree.size() == 2) {
           tree.erase(it, tree.end());
         } else {
           *it = *it - 1;
           tree.erase(next);
         }
         reduced = true;
         break;
       }
    }
    if (!reduced) {
      throw WaveletTreeInvalidDescriptionException(treeDescription);
    }
  }
}

std::vector<int> WaveletFilterBank::ParseDescription(const std::string& str) {
  static const boost::regex allRegex("^\\s*(\\d+\\s*(\\s|$))+");
  static const boost::regex intRegex("(\\d+\\s*(\\s|$))");
  static const boost::sregex_token_iterator empty;

  boost::smatch match;
  if (!boost::regex_match(str, match, allRegex)) {
    throw WaveletTreeDescriptionParseException(str);
  }
  boost::sregex_token_iterator intIterator(
          str.begin(), str.end(), intRegex, 1);

  std::vector<int> res;
  while (intIterator != empty) {
    std::string intstr = *intIterator++;
    int val;
    try {
      val = std::stoi(intstr);
    }
    catch(const std::invalid_argument& e) {
      throw WaveletTreeDescriptionParseException(str);
    }
    res.push_back(val);
  }
  if (res.empty()) {
    throw WaveletTreeDescriptionParseException(str);
  }
  ValidateDescription(res);
  return res;
}

std::string WaveletFilterBank::DescriptionToString(
    const std::vector<int>& treeDescription) noexcept {
  std::string str;
  for (int i : treeDescription) {
    str += std::to_string(i) + " ";
  }
  if (str != "") {
    str.resize(str.size() - 1);
  }
  return str;
}

void WaveletFilterBank::ValidateLength(
    const std::vector<int>& tree, size_t length) {
  int max = *std::max_element(tree.begin(), tree.end());
  // length / 2^max >= 1
  if (length == 0 || length % (1 << max) != 0) {
    throw WaveletTreeInvalidSourceLengthException(tree, length);
  }
}

void WaveletFilterBank::Apply(const float* source, size_t length,
                              float *result) noexcept {
  assert(source && result);
  ValidateLength(tree_, length);

  // Support zero-copy
  auto lsrc =
#ifndef __AVX__
      (source == result)? result :
#endif
      wavelet_prepare_array(order_, source, length);
  ApplyInternal(lsrc, length, result);
#ifndef __AVX__
  if (source != result) {
#endif
  free(lsrc);
#ifndef __AVX__
  }
#endif
}

void WaveletFilterBank::ApplyInternal(float* source, size_t length,
                                      float *result) noexcept {
  assert(source && result);
  ValidateLength(tree_, length);

  std::vector<int> tree(tree_);
  std::reverse(tree.begin(), tree.end());
  std::vector<int> workingTree;
  workingTree.reserve(tree.size());

  auto ldesthi = std::unique_ptr<float, void(*)(void*)>(
      wavelet_allocate_destination(order_, length), free);
  auto ldestlo = std::unique_ptr<float, void(*)(void*)>(
      wavelet_allocate_destination(order_, length), free);
  wavelet_apply(type_, order_, EXTENSION_TYPE_PERIODIC, source, length,
                ldesthi.get(), ldestlo.get());
  float *desthihi, *desthilo, *destlohi, *destlolo;
  wavelet_recycle_source(order_, source, length,
                         &desthihi, &desthilo,
                         &destlohi, &destlolo);
  workingTree.push_back(1);
  workingTree.push_back(1);

  while (!tree.empty()) {
    RecursivelyIterate(type_, order_, length / 2, &tree, &workingTree,
                       ldesthi.get(), desthihi, desthilo, &result);
    RecursivelyIterate(type_, order_, length / 2, &tree, &workingTree,
                       ldestlo.get(), destlohi, destlolo, &result);
  }
}

void WaveletFilterBank::RecursivelyIterate(
    WaveletType type, int order, size_t length,
    std::vector<int> *tree, std::vector<int>* workingTree, float* source,
    float* desthi, float* destlo, float** result) noexcept {
  if (tree->back() != workingTree->back()) {
    wavelet_apply(type, order, EXTENSION_TYPE_PERIODIC, source, length, desthi, destlo);
    float *desthihi, *desthilo, *destlohi, *destlolo;
    wavelet_recycle_source(order, source, length,
                           &desthihi, &desthilo,
                           &destlohi, &destlolo);
    int next = workingTree->back() + 1;
    workingTree->pop_back();
    workingTree->push_back(next);
    workingTree->push_back(next);
    RecursivelyIterate(type, order, length / 2, tree, workingTree,
                       desthi, desthihi, desthilo, result);
    RecursivelyIterate(type, order, length / 2, tree, workingTree,
                       destlo, destlohi, destlolo, result);
  } else {
    memcpy(*result, source, length * sizeof(source[0]));
    *result += length;
    tree->pop_back();
    workingTree->pop_back();
  }
}

}  // namespace Primitives
}  // namespace SoundFeatureExtraction
<|endoftext|>


<commit_before>#include <Poco/JSON/Parser.h>
#include <Poco/JSON/Object.h>
#include <Poco/Logger.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/HTMLForm.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/URI.h>

#include "di/Injectable.h"
#include "ssl/SSLClient.h"
#include "provider/FacebookAuthProvider.h"
#include "util/JsonUtil.h"
#include "util/Sanitize.h"

BEEEON_OBJECT_BEGIN(BeeeOn, FacebookAuthProvider)
BEEEON_OBJECT_CASTABLE(AuthProvider)
BEEEON_OBJECT_CASTABLE(OAuth2AuthProvider)
BEEEON_OBJECT_REF("sslConfig", &FacebookAuthProvider::setSSLConfig)
BEEEON_OBJECT_TEXT("clientId", &FacebookAuthProvider::setClientId)
BEEEON_OBJECT_TEXT("clientSecret", &FacebookAuthProvider::setClientSecret)
BEEEON_OBJECT_TEXT("redirectUri", &FacebookAuthProvider::setRedirectURI)
BEEEON_OBJECT_TEXT("id", &FacebookAuthProvider::setID)
BEEEON_OBJECT_END(BeeeOn, FacebookAuthProvider)

using namespace BeeeOn;
using namespace Poco;
using namespace Poco::JSON;
using namespace Poco::Net;
using namespace std;

bool FacebookAuthProvider::verifyAuthCode(
		const AuthCodeCredentials &credentials,
		AuthResult &info)
{
	string accessToken;

	try {
		accessToken = requestAccessToken(credentials.authCode());
	} catch (const Exception &e) {
		logger().log(e, __FILE__, __LINE__);
		return false;
	}

	return processAccessToken(accessToken, info);
}

bool FacebookAuthProvider::verifyAuthCode(
		const AccessTokenCredentials &credentials,
		AuthResult &info)
{
	return processAccessToken(credentials.accessToken(), info);
}

string FacebookAuthProvider::requestAccessToken(const string &authCode) const
{
	HTMLForm form;
	form.setEncoding(HTMLForm::ENCODING_URL);
	form.set("client_id", m_clientId);
	form.set("redirect_uri", m_redirectURI);
	form.set("client_secret", m_clientSecret);
	form.set("code", authCode);

	URI host(m_requestTokenUrl);
	string response = makeRequest(HTTPRequest::HTTP_POST, host, form);
	Object::Ptr data = JsonUtil::parse(response);

	if (data->has("error")) {
		string message = data->getObject("error")->getValue<string>("message");
		throw NotAuthenticatedException(message);
	}

	string accessToken = data->optValue<string>("access_token", "");
	string type = data->optValue<string>("token_type", "");
	unsigned int expires = data->optValue<unsigned int>("expires_in", 0);

	if (accessToken.empty())
		throw NotAuthenticatedException("missing access_token");
	if (type != "bearer")
		throw NotAuthenticatedException("incompatible token type: " +  type);
	if (expires == 0)
		throw NotAuthenticatedException("token has expired");

	return accessToken;
}

bool FacebookAuthProvider::processAccessToken(const string &accessToken, AuthResult &info) const
{
	string userData;

	try {
		verifyAccessToken(accessToken);
		userData = fetchUserData(accessToken);
	} catch (const Exception &e) {
		logger().log(e, __FILE__, __LINE__);
		return false;
	}

	return parseIdentity(userData, accessToken, info);
}

void FacebookAuthProvider::verifyAccessToken(const string& accessToken) const
{
	HTMLForm form;
	form.setEncoding(HTMLForm::ENCODING_URL);
	form.set("input_token", accessToken);
	form.set("access_token", m_clientId + "|" + m_clientSecret);

	URI host(m_inspectTokenUrl);
	string response = makeRequest(HTTPRequest::HTTP_GET, host, form);
	Object::Ptr data = JsonUtil::parse(response)->getObject("data");

	if (data->has("error")) {
		string message = data->getObject("error")->getValue<string>("message");
		throw NotAuthenticatedException(message);
	}

	string appId = data->getValue<string>("app_id");

	if (appId != m_clientId)
		throw NotAuthenticatedException("Unexpected app_id: " + appId);

}

string FacebookAuthProvider::fetchUserData(const string &accessToken) const
{
	HTMLForm form;
	form.setEncoding(HTMLForm::ENCODING_URL);
	form.set("access_token", accessToken);
	form.set("fields", "name,picture,email,first_name,last_name,locale");

	URI host(m_userInfoUrl);
	string response = makeRequest(HTTPRequest::HTTP_POST, host, form);
	Object::Ptr data = JsonUtil::parse(response);

	if (data->has("error"))	{
		string message = data->getObject("error")->getValue<string>("message");
		throw NotAuthenticatedException(message);
	}

	return response;
}

bool FacebookAuthProvider::parseIdentity(const string &userInfo, const string &accessToken, AuthResult &result) const
{
	Object::Ptr info = JsonUtil::parse(userInfo);

	if (info->has("id"))
		result.setProviderID(info->getValue<string>("id"));

	if (info->has("email"))
		result.setEmail(Sanitize::email(info->getValue<string>("email")));

	if (info->has("first_name"))
		result.setFirstName(Sanitize::common(info->getValue<string>("first_name")));

	if (info->has("last_name"))
		result.setLastName(Sanitize::common(info->getValue<string>("last_name")));

	if (info->has("locale"))
		result.setLocale(info->getValue<string>("locale"));

	if (info->has("picture")) {
		Object::Ptr pictData = info->getObject("picture");
		if (pictData->has("data")) {
			Object::Ptr picture  = pictData->getObject("data");
			if (picture->has("url"))
				result.setPicture(Sanitize::uri(picture->getValue<string>("url")));
		}
	}

	result.setAccessToken(accessToken);

	if (result.email().empty())
		throw NotAuthenticatedException("missing email");

	if (result.providerID().empty())
		throw NotAuthenticatedException("missing user_id");

	return true;

}
<commit_msg>FacebookAuthProvider: sanitize locale<commit_after>#include <Poco/JSON/Parser.h>
#include <Poco/JSON/Object.h>
#include <Poco/Logger.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/HTMLForm.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/URI.h>

#include "di/Injectable.h"
#include "ssl/SSLClient.h"
#include "provider/FacebookAuthProvider.h"
#include "util/JsonUtil.h"
#include "util/Sanitize.h"

BEEEON_OBJECT_BEGIN(BeeeOn, FacebookAuthProvider)
BEEEON_OBJECT_CASTABLE(AuthProvider)
BEEEON_OBJECT_CASTABLE(OAuth2AuthProvider)
BEEEON_OBJECT_REF("sslConfig", &FacebookAuthProvider::setSSLConfig)
BEEEON_OBJECT_TEXT("clientId", &FacebookAuthProvider::setClientId)
BEEEON_OBJECT_TEXT("clientSecret", &FacebookAuthProvider::setClientSecret)
BEEEON_OBJECT_TEXT("redirectUri", &FacebookAuthProvider::setRedirectURI)
BEEEON_OBJECT_TEXT("id", &FacebookAuthProvider::setID)
BEEEON_OBJECT_END(BeeeOn, FacebookAuthProvider)

using namespace BeeeOn;
using namespace Poco;
using namespace Poco::JSON;
using namespace Poco::Net;
using namespace std;

bool FacebookAuthProvider::verifyAuthCode(
		const AuthCodeCredentials &credentials,
		AuthResult &info)
{
	string accessToken;

	try {
		accessToken = requestAccessToken(credentials.authCode());
	} catch (const Exception &e) {
		logger().log(e, __FILE__, __LINE__);
		return false;
	}

	return processAccessToken(accessToken, info);
}

bool FacebookAuthProvider::verifyAuthCode(
		const AccessTokenCredentials &credentials,
		AuthResult &info)
{
	return processAccessToken(credentials.accessToken(), info);
}

string FacebookAuthProvider::requestAccessToken(const string &authCode) const
{
	HTMLForm form;
	form.setEncoding(HTMLForm::ENCODING_URL);
	form.set("client_id", m_clientId);
	form.set("redirect_uri", m_redirectURI);
	form.set("client_secret", m_clientSecret);
	form.set("code", authCode);

	URI host(m_requestTokenUrl);
	string response = makeRequest(HTTPRequest::HTTP_POST, host, form);
	Object::Ptr data = JsonUtil::parse(response);

	if (data->has("error")) {
		string message = data->getObject("error")->getValue<string>("message");
		throw NotAuthenticatedException(message);
	}

	string accessToken = data->optValue<string>("access_token", "");
	string type = data->optValue<string>("token_type", "");
	unsigned int expires = data->optValue<unsigned int>("expires_in", 0);

	if (accessToken.empty())
		throw NotAuthenticatedException("missing access_token");
	if (type != "bearer")
		throw NotAuthenticatedException("incompatible token type: " +  type);
	if (expires == 0)
		throw NotAuthenticatedException("token has expired");

	return accessToken;
}

bool FacebookAuthProvider::processAccessToken(const string &accessToken, AuthResult &info) const
{
	string userData;

	try {
		verifyAccessToken(accessToken);
		userData = fetchUserData(accessToken);
	} catch (const Exception &e) {
		logger().log(e, __FILE__, __LINE__);
		return false;
	}

	return parseIdentity(userData, accessToken, info);
}

void FacebookAuthProvider::verifyAccessToken(const string& accessToken) const
{
	HTMLForm form;
	form.setEncoding(HTMLForm::ENCODING_URL);
	form.set("input_token", accessToken);
	form.set("access_token", m_clientId + "|" + m_clientSecret);

	URI host(m_inspectTokenUrl);
	string response = makeRequest(HTTPRequest::HTTP_GET, host, form);
	Object::Ptr data = JsonUtil::parse(response)->getObject("data");

	if (data->has("error")) {
		string message = data->getObject("error")->getValue<string>("message");
		throw NotAuthenticatedException(message);
	}

	string appId = data->getValue<string>("app_id");

	if (appId != m_clientId)
		throw NotAuthenticatedException("Unexpected app_id: " + appId);

}

string FacebookAuthProvider::fetchUserData(const string &accessToken) const
{
	HTMLForm form;
	form.setEncoding(HTMLForm::ENCODING_URL);
	form.set("access_token", accessToken);
	form.set("fields", "name,picture,email,first_name,last_name,locale");

	URI host(m_userInfoUrl);
	string response = makeRequest(HTTPRequest::HTTP_POST, host, form);
	Object::Ptr data = JsonUtil::parse(response);

	if (data->has("error"))	{
		string message = data->getObject("error")->getValue<string>("message");
		throw NotAuthenticatedException(message);
	}

	return response;
}

bool FacebookAuthProvider::parseIdentity(const string &userInfo, const string &accessToken, AuthResult &result) const
{
	Object::Ptr info = JsonUtil::parse(userInfo);

	if (info->has("id"))
		result.setProviderID(info->getValue<string>("id"));

	if (info->has("email"))
		result.setEmail(Sanitize::email(info->getValue<string>("email")));

	if (info->has("first_name"))
		result.setFirstName(Sanitize::common(info->getValue<string>("first_name")));

	if (info->has("last_name"))
		result.setLastName(Sanitize::common(info->getValue<string>("last_name")));

	if (info->has("locale"))
		result.setLocale(Sanitize::locale(info->getValue<string>("locale")));

	if (info->has("picture")) {
		Object::Ptr pictData = info->getObject("picture");
		if (pictData->has("data")) {
			Object::Ptr picture  = pictData->getObject("data");
			if (picture->has("url"))
				result.setPicture(Sanitize::uri(picture->getValue<string>("url")));
		}
	}

	result.setAccessToken(accessToken);

	if (result.email().empty())
		throw NotAuthenticatedException("missing email");

	if (result.providerID().empty())
		throw NotAuthenticatedException("missing user_id");

	return true;

}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include <cmath>

#include "hlstrafe.hpp"
#include "util.hpp"

namespace HLStrafe
{
	double MaxAccelTheta(const PlayerData& player, const MovementVars& vars, PositionType postype, double wishspeed)
	{
		assert(postype != PositionType::WATER);

		bool onground = (postype == PositionType::GROUND);
		double accel = onground ? vars.Accelerate : vars.Airaccelerate;
		double accelspeed = accel * wishspeed * vars.EntFriction * vars.Frametime;
		if (accelspeed <= 0.0)
			return M_PI;

		double wishspeed_capped = onground ? wishspeed : 30;
		double tmp = wishspeed_capped - accelspeed;
		if (tmp <= 0.0)
			return M_PI / 2;

		double speed = Length<float, 2>(player.Velocity);
		if (tmp < speed)
			return std::acos(tmp / speed);

		return 0.0;
	}

	double MaxAngleTheta(const PlayerData& player, const MovementVars& vars, PositionType postype, double wishspeed)
	{
		assert(postype != PositionType::WATER);

		bool onground = (postype == PositionType::GROUND);
		double wishspeed_capped = onground ? wishspeed : 30;
		double speed = Length<float, 2>(player.Velocity);
		double accel = onground ? vars.Accelerate : vars.Airaccelerate;
		double accelspeed = accel * wishspeed * vars.EntFriction * vars.Frametime;
		if (accelspeed <= 0.0) {
			accelspeed *= -1;
			if (accelspeed >= speed) {
				if (wishspeed_capped >= speed)
					return 0.0;
				else
					return std::acos(wishspeed_capped / speed); // The actual angle needs to be _less_ than this.
			} else {
				if (wishspeed_capped >= speed)
					return std::acos(accelspeed / speed);
				else
					return std::acos(std::max(accelspeed, wishspeed_capped) / speed); // The actual angle needs to be _less_ than this if wishspeed_capped >= accelspeed.
			}
		} else {
			double tmp = wishspeed_capped - accelspeed;
		}
	}

	void VectorFME(PlayerData& player, const MovementVars& vars, PositionType postype, const double a[2], double wishspeed)
	{
		assert(postype != PositionType::WATER);

		bool onground = (postype == PositionType::GROUND);
		double wishspeed_capped = onground ? wishspeed : 30;
		double tmp = wishspeed_capped - DotProduct<float, double, 2>(player.Velocity, a);
		if (tmp <= 0.0)
			return;

		double accel = onground ? vars.Accelerate : vars.Airaccelerate;
		double accelspeed = accel * wishspeed * vars.EntFriction * vars.Frametime;
		if (accelspeed <= tmp)
			tmp = accelspeed;

		player.Velocity[0] += a[0] * tmp;
		player.Velocity[1] += a[1] * tmp;
	}
}
<commit_msg>MaxAngleTheta, probably can be simplified.<commit_after>#include <algorithm>
#include <cassert>
#include <cmath>

#include "hlstrafe.hpp"
#include "util.hpp"

namespace HLStrafe
{
	double MaxAccelTheta(const PlayerData& player, const MovementVars& vars, PositionType postype, double wishspeed)
	{
		assert(postype != PositionType::WATER);

		bool onground = (postype == PositionType::GROUND);
		double accel = onground ? vars.Accelerate : vars.Airaccelerate;
		double accelspeed = accel * wishspeed * vars.EntFriction * vars.Frametime;
		if (accelspeed <= 0.0)
			return M_PI;

		double wishspeed_capped = onground ? wishspeed : 30;
		double tmp = wishspeed_capped - accelspeed;
		if (tmp <= 0.0)
			return M_PI / 2;

		double speed = Length<float, 2>(player.Velocity);
		if (tmp < speed)
			return std::acos(tmp / speed);

		return 0.0;
	}

	double MaxAngleTheta(const PlayerData& player, const MovementVars& vars, PositionType postype, double wishspeed)
	{
		assert(postype != PositionType::WATER);

		bool onground = (postype == PositionType::GROUND);
		double speed = Length<float, 2>(player.Velocity);
		double accel = onground ? vars.Accelerate : vars.Airaccelerate;
		double accelspeed = accel * wishspeed * vars.EntFriction * vars.Frametime;
		if (accelspeed <= 0.0) {
			double wishspeed_capped = onground ? wishspeed : 30;
			accelspeed *= -1;
			if (accelspeed >= speed) {
				accelspeed = 0;
			}
			if (wishspeed_capped >= speed)
				return std::acos(accelspeed / speed);
			else
				return std::acos(std::max(accelspeed, wishspeed_capped) / speed); // The actual angle needs to be _less_ than this if wishspeed_capped >= accelspeed.
		} else {
			if (accelspeed >= speed) {
				return M_PI;
			} else {
				return std::acos(-1 * accelspeed / speed);
			}
		}
	}

	void VectorFME(PlayerData& player, const MovementVars& vars, PositionType postype, const double a[2], double wishspeed)
	{
		assert(postype != PositionType::WATER);

		bool onground = (postype == PositionType::GROUND);
		double wishspeed_capped = onground ? wishspeed : 30;
		double tmp = wishspeed_capped - DotProduct<float, double, 2>(player.Velocity, a);
		if (tmp <= 0.0)
			return;

		double accel = onground ? vars.Accelerate : vars.Airaccelerate;
		double accelspeed = accel * wishspeed * vars.EntFriction * vars.Frametime;
		if (accelspeed <= tmp)
			tmp = accelspeed;

		player.Velocity[0] += a[0] * tmp;
		player.Velocity[1] += a[1] * tmp;
	}
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 2016 Boris Pek <tehnick-8@yandex.ru>                       *
 *                                                                           *
 *  Permission is hereby granted, free of charge, to any person obtaining    *
 *  a copy of this software and associated documentation files (the          *
 *  "Software"), to deal in the Software without restriction, including      *
 *  without limitation the rights to use, copy, modify, merge, publish,      *
 *  distribute, sublicense, and/or sell copies of the Software, and to       *
 *  permit persons to whom the Software is furnished to do so, subject to    *
 *  the following conditions:                                                *
 *                                                                           *
 *  The above copyright notice and this permission notice shall be included  *
 *  in all copies or substantial portions of the Software.                   *
 *                                                                           *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,          *
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF       *
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY     *
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,     *
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE        *
 *  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                   *
 *                                                                           *
 *****************************************************************************/

#include <QStringList>

#include "applicationsettings.h"
#include "resourcemanager.h"
#include "sessionsmanager.h"
#include "localization.h"
#include "htmlpage.h"

struct HtmlPage::HtmlPagePrivate
{
    bool admin = false;
    bool autorized = false;

    QByteArray page;
    QByteArray head;
    QByteArray body;
    QByteArray title;
    QByteArray content;
    QByteArray redirect;
    QByteArray prefix;

    CommonSettings commonSettings;
    UserSettings   userSettings;
    Localization   localization;
};

HtmlPage::HtmlPage(const Request &request) :
    d(new HtmlPagePrivate)
{
    d->prefix = ApplicationSettings::instance().prefixString().toUtf8();
    d->redirect = request.scriptName().toUtf8();

    if (request.get("ajax").isEmpty()) {
        const ResourceManager res;
        setPage(res.read("/html/page-template.html"));
        setTitle("%basic_title%");
        setHead(res.read("/html/head-template.html"));
        setBody(res.read("/html/body-template.html"));
        setContent(res.read("/html/404-template.html"));
    }

    checkAutorization(request);

    if (request.get("ajax").isEmpty()) {
        d->localization.setFileName(d->commonSettings.l10nFile());
        d->localization.readSettings();

        setContentType("text/html");
        update();
    }
}

HtmlPage::~HtmlPage()
{
    delete d;
}

void HtmlPage::setHead(const QByteArray &head)
{
    d->head = head;
}

void HtmlPage::setBody(const QByteArray &body)
{
    d->body = body;
}

void HtmlPage::setTitle(const QByteArray &title)
{
    d->title = title;
}

void HtmlPage::setContent(const QByteArray &content)
{
    d->content = content;
}

void HtmlPage::addToHead(const QByteArray &head)
{
    setHead(d->head + "\n" + head);
}

void HtmlPage::addToBody(const QByteArray &body)
{
    setBody(d->body + "\n" + body);
}

void HtmlPage::addToTitle(const QByteArray &title)
{
    setTitle(d->title + title);
}

void HtmlPage::addToContent(const QByteArray &content)
{
    setContent(d->content + "\n" + content);
}

bool HtmlPage::isAutorizedUser() const
{
    return d->autorized;
}

bool HtmlPage::isAdmin() const
{
    return d->admin;
}

void HtmlPage::setPage(const QByteArray &page)
{
    d->page = page;
}

void HtmlPage::checkAutorization(const Request &request)
{
    QByteArray out;
    out += "        <script>\n";

    SessionsManager sm(request);
    if (sm.isAutorized()) {
        d->autorized = true;
        d->userSettings.setFileName("users/" + sm.get("user_name") + ".json");
        d->userSettings.readSettings();
    }
    else if (d->userSettings.isValidAutorizationRequest(request)) {
        d->autorized = true;
        sm.setFileName(d->userSettings.get("user_id") + ".json");
        if (sm.beginNewSession(d->userSettings.get("user_name"))) {
            const bool httpsOnly = d->commonSettings.getBool("https_only");
            setCookie("user_id", d->userSettings.get("user_id"),
                      "", "/", "", httpsOnly, httpsOnly);
            setCookie("session_id", sm.get("session_id"),
                      "", "/", "", httpsOnly, httpsOnly);
        }
    }
    else {
        if (request.isPost()) {
            if (!request.post().isEmpty()) {
                if (!request.post("user_name").isEmpty() &&
                        !request.post("password").isEmpty()) {
                    out += "            show_auth_error();\n";
                }
            }
        }
    }
    if (d->autorized) {
        out += "            authorized_user();\n";
        d->admin = d->userSettings.getBool("admin");
        if (!d->admin) {
            out += "            not_admin();\n";
        }
        if (d->userSettings.get("user_email").isEmpty()) {
            out += "            email_is_unknown();\n";
        }
    }
    else {
        out += "            unauthorized_user();\n";
    }

    out += "        </script>";
    addToBody(out);
}

void HtmlPage::forceAuthorization()
{
    if (!d->autorized) {
        addToBody("        <script>begin_authorization()</script>");
    }
}

void HtmlPage::forbidAccess()
{
    const ResourceManager res;
    setContent(res.read("/html/403-template.html"));
}

void HtmlPage::update()
{
    QByteArray out = d->page;

    out.replace("%head%",       d->head);
    out.replace("%body%",       d->body);
    out.replace("%title%",      d->title);
    out.replace("%content%",    d->content);
    out.replace("%page_style%", d->userSettings.get("page_style").toUtf8());
    out.replace("%user_email%", d->userSettings.get("user_email").toUtf8());
    out.replace("%gravatar_icon_url%", d->userSettings.gravatarIconUrl());
    if (!d->autorized) {
        const ResourceManager res;
        out.replace("%auth_form%", res.read("/html/auth-template.html"));
    }
    else {
        out.replace("%auth_form%", "");
    }
    const QStringList names = {
        d->userSettings.get("desirable_user_name"),
        d->userSettings.get("full_user_name"),
        d->userSettings.get("user_name")
    };
    for (const QString &name : names) {
        if (!name.isEmpty()) {
            out.replace("%user_name%", name.toUtf8());
        }
    }
    for (const auto &key : d->localization.keys()) {
        out.replace("%" + key.toUtf8() + "%",
                    d->localization.get(key).toUtf8());
    }
    out.replace("%redirect%",   d->redirect);
    out.replace("%prefix%",     d->prefix);

    setData(out);
}

CommonSettings& HtmlPage::commonSettings()
{
    return d->commonSettings;
}

UserSettings &HtmlPage::userSettings()
{
    return d->userSettings;
}

QString HtmlPage::get(const QString &key) const
{
    return d->commonSettings.get(key);
}

bool HtmlPage::getBool(const QString &key) const
{
    return d->commonSettings.getBool(key);
}

<commit_msg>HtmlPage: cookies should be sent in ajax requests<commit_after>/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 2016 Boris Pek <tehnick-8@yandex.ru>                       *
 *                                                                           *
 *  Permission is hereby granted, free of charge, to any person obtaining    *
 *  a copy of this software and associated documentation files (the          *
 *  "Software"), to deal in the Software without restriction, including      *
 *  without limitation the rights to use, copy, modify, merge, publish,      *
 *  distribute, sublicense, and/or sell copies of the Software, and to       *
 *  permit persons to whom the Software is furnished to do so, subject to    *
 *  the following conditions:                                                *
 *                                                                           *
 *  The above copyright notice and this permission notice shall be included  *
 *  in all copies or substantial portions of the Software.                   *
 *                                                                           *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,          *
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF       *
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY     *
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,     *
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE        *
 *  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                   *
 *                                                                           *
 *****************************************************************************/

#include <QStringList>

#include "applicationsettings.h"
#include "resourcemanager.h"
#include "sessionsmanager.h"
#include "localization.h"
#include "htmlpage.h"

struct HtmlPage::HtmlPagePrivate
{
    bool admin = false;
    bool autorized = false;

    QByteArray page;
    QByteArray head;
    QByteArray body;
    QByteArray title;
    QByteArray content;
    QByteArray redirect;
    QByteArray prefix;

    CommonSettings commonSettings;
    UserSettings   userSettings;
    Localization   localization;
};

HtmlPage::HtmlPage(const Request &request) :
    d(new HtmlPagePrivate)
{
    d->prefix = ApplicationSettings::instance().prefixString().toUtf8();
    d->redirect = request.scriptName().toUtf8();

    if (request.get("ajax").isEmpty()) {
        const ResourceManager res;
        setPage(res.read("/html/page-template.html"));
        setTitle("%basic_title%");
        setHead(res.read("/html/head-template.html"));
        setBody(res.read("/html/body-template.html"));
        setContent(res.read("/html/404-template.html"));
    }

    checkAutorization(request);

    if (request.get("ajax").isEmpty()) {
        d->localization.setFileName(d->commonSettings.l10nFile());
        d->localization.readSettings();

        setContentType("text/html");
        update();
    }
}

HtmlPage::~HtmlPage()
{
    delete d;
}

void HtmlPage::setHead(const QByteArray &head)
{
    d->head = head;
}

void HtmlPage::setBody(const QByteArray &body)
{
    d->body = body;
}

void HtmlPage::setTitle(const QByteArray &title)
{
    d->title = title;
}

void HtmlPage::setContent(const QByteArray &content)
{
    d->content = content;
}

void HtmlPage::addToHead(const QByteArray &head)
{
    setHead(d->head + "\n" + head);
}

void HtmlPage::addToBody(const QByteArray &body)
{
    setBody(d->body + "\n" + body);
}

void HtmlPage::addToTitle(const QByteArray &title)
{
    setTitle(d->title + title);
}

void HtmlPage::addToContent(const QByteArray &content)
{
    setContent(d->content + "\n" + content);
}

bool HtmlPage::isAutorizedUser() const
{
    return d->autorized;
}

bool HtmlPage::isAdmin() const
{
    return d->admin;
}

void HtmlPage::setPage(const QByteArray &page)
{
    d->page = page;
}

void HtmlPage::checkAutorization(const Request &request)
{
    QByteArray out;
    out += "        <script>\n";

    SessionsManager sm(request);
    if (sm.isAutorized()) {
        d->autorized = true;
        d->userSettings.setFileName("users/" + sm.get("user_name") + ".json");
        d->userSettings.readSettings();
    }
    else if (d->userSettings.isValidAutorizationRequest(request)) {
        d->autorized = true;
        sm.setFileName(d->userSettings.get("user_id") + ".json");
        if (sm.beginNewSession(d->userSettings.get("user_name"))) {
            const bool httpsOnly = d->commonSettings.getBool("https_only");
            setCookie("user_id", d->userSettings.get("user_id"),
                      "", "/", "", httpsOnly, false);
            setCookie("session_id", sm.get("session_id"),
                      "", "/", "", httpsOnly, false);
        }
    }
    else {
        if (request.isPost()) {
            if (!request.post().isEmpty()) {
                if (!request.post("user_name").isEmpty() &&
                        !request.post("password").isEmpty()) {
                    out += "            show_auth_error();\n";
                }
            }
        }
    }
    if (d->autorized) {
        out += "            authorized_user();\n";
        d->admin = d->userSettings.getBool("admin");
        if (!d->admin) {
            out += "            not_admin();\n";
        }
        if (d->userSettings.get("user_email").isEmpty()) {
            out += "            email_is_unknown();\n";
        }
    }
    else {
        out += "            unauthorized_user();\n";
    }

    out += "        </script>";
    addToBody(out);
}

void HtmlPage::forceAuthorization()
{
    if (!d->autorized) {
        addToBody("        <script>begin_authorization()</script>");
    }
}

void HtmlPage::forbidAccess()
{
    const ResourceManager res;
    setContent(res.read("/html/403-template.html"));
}

void HtmlPage::update()
{
    QByteArray out = d->page;

    out.replace("%head%",       d->head);
    out.replace("%body%",       d->body);
    out.replace("%title%",      d->title);
    out.replace("%content%",    d->content);
    out.replace("%page_style%", d->userSettings.get("page_style").toUtf8());
    out.replace("%user_email%", d->userSettings.get("user_email").toUtf8());
    out.replace("%gravatar_icon_url%", d->userSettings.gravatarIconUrl());
    if (!d->autorized) {
        const ResourceManager res;
        out.replace("%auth_form%", res.read("/html/auth-template.html"));
    }
    else {
        out.replace("%auth_form%", "");
    }
    const QStringList names = {
        d->userSettings.get("desirable_user_name"),
        d->userSettings.get("full_user_name"),
        d->userSettings.get("user_name")
    };
    for (const QString &name : names) {
        if (!name.isEmpty()) {
            out.replace("%user_name%", name.toUtf8());
        }
    }
    for (const auto &key : d->localization.keys()) {
        out.replace("%" + key.toUtf8() + "%",
                    d->localization.get(key).toUtf8());
    }
    out.replace("%redirect%",   d->redirect);
    out.replace("%prefix%",     d->prefix);

    setData(out);
}

CommonSettings& HtmlPage::commonSettings()
{
    return d->commonSettings;
}

UserSettings &HtmlPage::userSettings()
{
    return d->userSettings;
}

QString HtmlPage::get(const QString &key) const
{
    return d->commonSettings.get(key);
}

bool HtmlPage::getBool(const QString &key) const
{
    return d->commonSettings.getBool(key);
}

<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/ui/certificate_trust.h"

#include <wincrypt.h>
#include <windows.h>

#include "base/callback.h"
#include "net/cert/cert_database.h"

namespace certificate_trust {

void ShowCertificateTrust(atom::NativeWindow* parent_window,
                          const scoped_refptr<net::X509Certificate>& cert,
                          const std::string& message,
                          const ShowTrustCallback& callback) {
    // opening the Trusted Root Certificate store for the current user
    auto hCertStore = CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        0,
        NULL,
        CERT_SYSTEM_STORE_CURRENT_USER,
        // installing into Trusted Root Certificate Authorities, not Personal
        L"Root");

    if (hCertStore == NULL) {
        callback.Run();
        return;
    }

    auto pCertContext = cert->CreateOSCertChainForCert();

    // This is a blocking call which displays a prompt to the user to confirm
    // they trust this certificate
    auto result = CertAddCertificateContextToStore(
        hCertStore,
        pCertContext,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL);

    if (result) {
        auto cert_db = net::CertDatabase::GetInstance();
        // Force Chromium to reload the certificate since it might be trusted
        // now.
        cert_db->NotifyObserversCertDBChanged(cert.get());
    }

    CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

    CertFreeCertificateContext(pCertContext);

    callback.Run();
}

}  // namespace certificate_trust
<commit_msg>actually validate the chain before adding<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/ui/certificate_trust.h"

#include <wincrypt.h>
#include <windows.h>

#include "base/callback.h"
#include "net/cert/cert_database.h"

namespace certificate_trust {

BOOL AddCertificateAndRefresh(
    const HCERTSTORE certStore,
    const PCCERT_CONTEXT certContext,
    const scoped_refptr<net::X509Certificate>& cert) {
    auto result = CertAddCertificateContextToStore(
        certStore,
        certContext,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL);

    if (result) {
        auto cert_db = net::CertDatabase::GetInstance();
        // Force Chromium to reload the certificate since it might be trusted
        // now.
        cert_db->NotifyObserversCertDBChanged(cert.get());
    }

    return result;
}

// Add the provided certificate to the Trusted Root
// Certificate Authorities store for the current user.
//
// This requires prompting the user to confirm they
// trust the certificate.
BOOL AddToTrustedRootStore(const PCCERT_CONTEXT certContext,
                           const scoped_refptr<net::X509Certificate>& cert) {
    auto rootCertStore = CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        0,
        NULL,
        CERT_SYSTEM_STORE_CURRENT_USER,
        L"Root");

    if (rootCertStore == NULL) {
        // could not resolve the certificate store, giving up
        return false;
    }

    auto result = AddCertificateAndRefresh(rootCertStore, certContext, cert);

    CertCloseStore(rootCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

    return result;
}

// Add the provided certificate to the Personal
// certificate store for the current user.
BOOL AddToPersonalStore(const PCCERT_CONTEXT certContext,
                        const scoped_refptr<net::X509Certificate>& cert) {
    auto userCertStore = CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        0,
        NULL,
        CERT_SYSTEM_STORE_CURRENT_USER,
        L"My");

    if (userCertStore == NULL) {
        // could not resolve the certificate store, giving up
        return false;
    }

    auto result = AddCertificateAndRefresh(userCertStore, certContext, cert);

    CertCloseStore(userCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

    return result;
}

CERT_CHAIN_PARA GetCertificateChainParameters() {
    CERT_ENHKEY_USAGE enhkeyUsage;
    enhkeyUsage.cUsageIdentifier = 0;
    enhkeyUsage.rgpszUsageIdentifier = NULL;

    CERT_USAGE_MATCH CertUsage;
    // ensure the rules are applied to the entire chain
    CertUsage.dwType = USAGE_MATCH_TYPE_AND;
    CertUsage.Usage = enhkeyUsage;

    CERT_CHAIN_PARA params = { sizeof(CERT_CHAIN_PARA) };
    params.RequestedUsage = CertUsage;

    return params;
}

void ShowCertificateTrust(atom::NativeWindow* parent_window,
                          const scoped_refptr<net::X509Certificate>& cert,
                          const std::string& message,
                          const ShowTrustCallback& callback) {
    PCCERT_CHAIN_CONTEXT chainContext;

    auto pCertContext = cert->CreateOSCertChainForCert();

    auto params = GetCertificateChainParameters();

    if (CertGetCertificateChain(NULL,
                                pCertContext,
                                NULL,
                                NULL,
                                &params,
                                NULL,
                                NULL,
                                &chainContext)) {
        switch (chainContext->TrustStatus.dwErrorStatus) {
            case CERT_TRUST_NO_ERROR:
                AddToPersonalStore(pCertContext, cert);
                break;

            case CERT_TRUST_IS_UNTRUSTED_ROOT:
            case CERT_TRUST_IS_SELF_SIGNED:
                AddToTrustedRootStore(pCertContext, cert);
                break;

            default:
                // we can't handle other scenarios, giving up
                break;
        }

        CertFreeCertificateChain(chainContext);
    }

    CertFreeCertificateContext(pCertContext);

    callback.Run();
}

}  // namespace certificate_trust
<|endoftext|>