std::string getProfile(RESPONSE_CALLBACK_ARGS)
{
    std::string &argument = request.argument;
    int *status_code = &response.status_code;

    std::string name = urlDecode(getUrlArg(argument, "name")), token = urlDecode(getUrlArg(argument, "token"));
    string_array profiles = split(name, "|");
    name = profiles[0];
    if(token.empty() || name.empty())
    {
        *status_code = 403;
        return "Forbidden";
    }
    std::string profile_content;
    /*if(vfs::vfs_exist(name))
    {
        profile_content = vfs::vfs_get(name);
    }
    else */if(fileExist(name))
    {
        profile_content = fileGet(name, true);
    }
    else
    {
        *status_code = 404;
        return "Profile not found";
    }
    //std::cerr<<"Trying to load profile '" + name + "'.\n";
    writeLog(0, "Trying to load profile '" + name + "'.", LOG_LEVEL_INFO);
    INIReader ini;
    if(ini.Parse(profile_content) != INIREADER_EXCEPTION_NONE && !ini.SectionExist("Profile"))
    {
        //std::cerr<<"Load profile failed! Reason: "<<ini.GetLastError()<<"\n";
        writeLog(0, "Load profile failed! Reason: " + ini.GetLastError(), LOG_LEVEL_ERROR);
        *status_code = 500;
        return "Broken profile!";
    }
    //std::cerr<<"Trying to parse profile '" + name + "'.\n";
    writeLog(0, "Trying to parse profile '" + name + "'.", LOG_LEVEL_INFO);
    string_multimap contents;
    ini.GetItems("Profile", contents);
    if(!contents.size())
    {
        //std::cerr<<"Load profile failed! Reason: Empty Profile section\n";
        writeLog(0, "Load profile failed! Reason: Empty Profile section", LOG_LEVEL_ERROR);
        *status_code = 500;
        return "Broken profile!";
    }
    auto profile_token = contents.find("profile_token");
    if(profiles.size() == 1 && profile_token != contents.end())
    {
        if(token != profile_token->second)
        {
            *status_code = 403;
            return "Forbidden";
        }
        token = global.accessToken;
    }
    else
    {
        if(token != global.accessToken)
        {
            *status_code = 403;
            return "Forbidden";
        }
    }
    /// check if more than one profile is provided
    if(profiles.size() > 1)
    {
        writeLog(0, "Multiple profiles are provided. Trying to combine profiles...", LOG_TYPE_INFO);
        std::string all_urls, url;
        auto iter = contents.find("url");
        if(iter != contents.end())
            all_urls = iter->second;
        for(size_t i = 1; i < profiles.size(); i++)
        {
            name = profiles[i];
            if(!fileExist(name))
            {
                writeLog(0, "Ignoring non-exist profile '" + name + "'...", LOG_LEVEL_WARNING);
                continue;
            }
            if(ini.ParseFile(name) != INIREADER_EXCEPTION_NONE && !ini.SectionExist("Profile"))
            {
                writeLog(0, "Ignoring broken profile '" + name + "'...", LOG_LEVEL_WARNING);
                continue;
            }
            url = ini.Get("Profile", "url");
            if(url.size())
            {
                all_urls += "|" + url;
                writeLog(0, "Profile url from '" + name + "' added.", LOG_LEVEL_INFO);
            }
            else
            {
                writeLog(0, "Profile '" + name + "' does not have url key. Skipping...", LOG_LEVEL_INFO);
            }
        }
        iter->second = all_urls;
    }

    contents.emplace("token", token);
    contents.emplace("profile_data", base64Encode(global.managedConfigPrefix + "/getprofile?" + argument));
    std::string query = std::accumulate(contents.begin(), contents.end(), std::string(), [](const std::string &x, auto y){ return x + y.first + "=" + urlEncode(y.second) + "&"; });
    query += argument;
    request.argument = query;
    return subconverter(request, response);
}
std::string getProfile(RESPONSE_CALLBACK_ARGS)
{
    std::string &argument = request.argument;
    int *status_code = &response.status_code;

    std::string name = urlDecode(getUrlArg(argument, "name")), token = urlDecode(getUrlArg(argument, "token"));
    string_array profiles = split(name, "|");
    name = profiles[0];
    if(token.empty() || name.empty())
    {
        *status_code = 403;
        return "Forbidden";
    }
    std::string profile_content;
     if(fileExist(name))
    {
        profile_content = fileGet(name, true);
    }
    else
    {
        *status_code = 404;
        return "Profile not found";
    }
     
    writeLog(0, "Trying to load profile '" + name + "'.", LOG_LEVEL_INFO);
    INIReader ini;
    if(ini.Parse(profile_content) != INIREADER_EXCEPTION_NONE && !ini.SectionExist("Profile"))
    {
         
        writeLog(0, "Load profile failed! Reason: " + ini.GetLastError(), LOG_LEVEL_ERROR);
        *status_code = 500;
        return "Broken profile!";
    }
     
    writeLog(0, "Trying to parse profile '" + name + "'.", LOG_LEVEL_INFO);
    string_multimap contents;
    ini.GetItems("Profile", contents);
    if(!contents.size())
    {
         
        writeLog(0, "Load profile failed! Reason: Empty Profile section", LOG_LEVEL_ERROR);
        *status_code = 500;
        return "Broken profile!";
    }
    auto profile_token = contents.find("profile_token");
    if(profiles.size() == 1 && profile_token != contents.end())
    {
        if(token != profile_token->second)
        {
            *status_code = 403;
            return "Forbidden";
        }
        token = global.accessToken;
    }
    else
    {
        if(token != global.accessToken)
        {
            *status_code = 403;
            return "Forbidden";
        }
    }
     
    if(profiles.size() > 1)
    {
        writeLog(0, "Multiple profiles are provided. Trying to combine profiles...", LOG_TYPE_INFO);
        std::string all_urls, url;
        auto iter = contents.find("url");
        if(iter != contents.end())
            all_urls = iter->second;
        for(size_t i = 1; i < profiles.size(); i++)
        {
            name = profiles[i];
            if(!fileExist(name))
            {
                writeLog(0, "Ignoring non-exist profile '" + name + "'...", LOG_LEVEL_WARNING);
                continue;
            }
            if(ini.ParseFile(name) != INIREADER_EXCEPTION_NONE && !ini.SectionExist("Profile"))
            {
                writeLog(0, "Ignoring broken profile '" + name + "'...", LOG_LEVEL_WARNING);
                continue;
            }
            url = ini.Get("Profile", "url");
            if(url.size())
            {
                all_urls += "|" + url;
                writeLog(0, "Profile url from '" + name + "' added.", LOG_LEVEL_INFO);
            }
            else
            {
                writeLog(0, "Profile '" + name + "' does not have url key. Skipping...", LOG_LEVEL_INFO);
            }
        }
        iter->second = all_urls;
    }

    contents.emplace("token", token);
    contents.emplace("profile_data", base64Encode(global.managedConfigPrefix + "/getprofile?" + argument));
    std::string query = std::accumulate(contents.begin(), contents.end(), std::string(), [](const std::string &x, auto y){ return x + y.first + "=" + urlEncode(y.second) + "&"; });
    query += argument;
    request.argument = query;
    return subconverter(request, response);
}