You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
437 lines
19 KiB
437 lines
19 KiB
From c30bae2994f1e5f33f6da51eb96d423e9bf0f75c Mon Sep 17 00:00:00 2001
|
|
From: Louis Sautier <sautier.louis@gmail.com>
|
|
Date: Thu, 20 Aug 2020 18:25:48 +0200
|
|
Subject: [PATCH] =?UTF-8?q?Fix=20=E2=80=98fs::copy=5Foption=E2=80=99=20has?=
|
|
=?UTF-8?q?=20not=20been=20declared=20with=20boost=201.74.0?=
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
It was deprecated in
|
|
https://github.com/boostorg/filesystem/commit/f199152b7df036ff1606c85e4ea1b28edfeda6cc
|
|
---
|
|
lib/base/utility.cpp | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp
|
|
index 1add7616c6..d8e6f20b0c 100644
|
|
--- a/lib/base/utility.cpp
|
|
+++ b/lib/base/utility.cpp
|
|
@@ -725,7 +725,11 @@ void Utility::CopyFile(const String& source, const String& target)
|
|
{
|
|
namespace fs = boost::filesystem;
|
|
|
|
+#if BOOST_VERSION >= 107400
|
|
+ fs::copy_file(fs::path(source.Begin(), source.End()), fs::path(target.Begin(), target.End()), fs::copy_options::overwrite_existing);
|
|
+#else /* BOOST_VERSION */
|
|
fs::copy_file(fs::path(source.Begin(), source.End()), fs::path(target.Begin(), target.End()), fs::copy_option::overwrite_if_exists);
|
|
+#endif /* BOOST_VERSION */
|
|
}
|
|
|
|
/*
|
|
From 45dd71e0f9a93369e08d6cb26f97940f9c9594aa Mon Sep 17 00:00:00 2001
|
|
From: "Alexander A. Klimov" <alexander.klimov@icinga.com>
|
|
Date: Wed, 26 Aug 2020 13:56:26 +0200
|
|
Subject: [PATCH] Introduce HttpUtility::Set()
|
|
|
|
refs #8185
|
|
---
|
|
lib/cli/consolecommand.cpp | 9 ++++---
|
|
lib/perfdata/elasticsearchwriter.cpp | 13 ++++-----
|
|
lib/perfdata/influxdbwriter.cpp | 7 ++---
|
|
lib/remote/configfileshandler.cpp | 4 +--
|
|
lib/remote/eventshandler.cpp | 2 +-
|
|
lib/remote/httpserverconnection.cpp | 40 ++++++++++++++--------------
|
|
lib/remote/httputility.cpp | 4 +--
|
|
lib/remote/httputility.hpp | 28 +++++++++++++++++++
|
|
lib/remote/infohandler.cpp | 6 ++---
|
|
plugins/check_nscp_api.cpp | 9 ++++---
|
|
10 files changed, 77 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/lib/cli/consolecommand.cpp b/lib/cli/consolecommand.cpp
|
|
index 41b6590e4c..42c5c63133 100644
|
|
--- a/lib/cli/consolecommand.cpp
|
|
+++ b/lib/cli/consolecommand.cpp
|
|
@@ -3,6 +3,7 @@
|
|
#include "cli/consolecommand.hpp"
|
|
#include "config/configcompiler.hpp"
|
|
#include "remote/consolehandler.hpp"
|
|
+#include "remote/httputility.hpp"
|
|
#include "remote/url.hpp"
|
|
#include "base/configwriter.hpp"
|
|
#include "base/serializer.hpp"
|
|
@@ -580,11 +581,11 @@ Dictionary::Ptr ConsoleCommand::SendRequest()
|
|
|
|
http::request<http::string_body> request(http::verb::post, std::string(l_Url->Format(false)), 10);
|
|
|
|
- request.set(http::field::user_agent, "Icinga/DebugConsole/" + Application::GetAppVersion());
|
|
- request.set(http::field::host, l_Url->GetHost() + ":" + l_Url->GetPort());
|
|
+ HttpUtility::Set(request, http::field::user_agent, "Icinga/DebugConsole/" + Application::GetAppVersion());
|
|
+ HttpUtility::Set(request, http::field::host, l_Url->GetHost() + ":" + l_Url->GetPort());
|
|
|
|
- request.set(http::field::accept, "application/json");
|
|
- request.set(http::field::authorization, "Basic " + Base64::Encode(l_Url->GetUsername() + ":" + l_Url->GetPassword()));
|
|
+ HttpUtility::Set(request, http::field::accept, "application/json");
|
|
+ HttpUtility::Set(request, http::field::authorization, "Basic " + Base64::Encode(l_Url->GetUsername() + ":" + l_Url->GetPassword()));
|
|
|
|
try {
|
|
http::write(*l_TlsStream, request);
|
|
diff --git a/lib/perfdata/elasticsearchwriter.cpp b/lib/perfdata/elasticsearchwriter.cpp
|
|
index 6870198e45..3764bf536b 100644
|
|
--- a/lib/perfdata/elasticsearchwriter.cpp
|
|
+++ b/lib/perfdata/elasticsearchwriter.cpp
|
|
@@ -2,6 +2,7 @@
|
|
|
|
#include "perfdata/elasticsearchwriter.hpp"
|
|
#include "perfdata/elasticsearchwriter-ti.cpp"
|
|
+#include "remote/httputility.hpp"
|
|
#include "remote/url.hpp"
|
|
#include "icinga/compatutility.hpp"
|
|
#include "icinga/service.hpp"
|
|
@@ -474,27 +475,27 @@ void ElasticsearchWriter::SendRequest(const String& body)
|
|
|
|
http::request<http::string_body> request (http::verb::post, std::string(url->Format(true)), 10);
|
|
|
|
- request.set(http::field::user_agent, "Icinga/" + Application::GetAppVersion());
|
|
- request.set(http::field::host, url->GetHost() + ":" + url->GetPort());
|
|
+ HttpUtility::Set(request, http::field::user_agent, "Icinga/" + Application::GetAppVersion());
|
|
+ HttpUtility::Set(request, http::field::host, url->GetHost() + ":" + url->GetPort());
|
|
|
|
/* Specify required headers by Elasticsearch. */
|
|
- request.set(http::field::accept, "application/json");
|
|
+ HttpUtility::Set(request, http::field::accept, "application/json");
|
|
|
|
/* Use application/x-ndjson for bulk streams. While ES
|
|
* is able to handle application/json, the newline separator
|
|
* causes problems with Logstash (#6609).
|
|
*/
|
|
- request.set(http::field::content_type, "application/x-ndjson");
|
|
+ HttpUtility::Set(request, http::field::content_type, "application/x-ndjson");
|
|
|
|
/* Send authentication if configured. */
|
|
String username = GetUsername();
|
|
String password = GetPassword();
|
|
|
|
if (!username.IsEmpty() && !password.IsEmpty())
|
|
- request.set(http::field::authorization, "Basic " + Base64::Encode(username + ":" + password));
|
|
+ HttpUtility::Set(request, http::field::authorization, "Basic " + Base64::Encode(username + ":" + password));
|
|
|
|
request.body() = body;
|
|
- request.set(http::field::content_length, request.body().size());
|
|
+ HttpUtility::Set(request, http::field::content_length, request.body().size());
|
|
|
|
/* Don't log the request body to debug log, this is already done above. */
|
|
Log(LogDebug, "ElasticsearchWriter")
|
|
diff --git a/lib/perfdata/influxdbwriter.cpp b/lib/perfdata/influxdbwriter.cpp
|
|
index 4692b8b5df..0ddd582447 100644
|
|
--- a/lib/perfdata/influxdbwriter.cpp
|
|
+++ b/lib/perfdata/influxdbwriter.cpp
|
|
@@ -2,6 +2,7 @@
|
|
|
|
#include "perfdata/influxdbwriter.hpp"
|
|
#include "perfdata/influxdbwriter-ti.cpp"
|
|
+#include "remote/httputility.hpp"
|
|
#include "remote/url.hpp"
|
|
#include "icinga/service.hpp"
|
|
#include "icinga/macroprocessor.hpp"
|
|
@@ -501,11 +502,11 @@ void InfluxdbWriter::Flush()
|
|
|
|
http::request<http::string_body> request (http::verb::post, std::string(url->Format(true)), 10);
|
|
|
|
- request.set(http::field::user_agent, "Icinga/" + Application::GetAppVersion());
|
|
- request.set(http::field::host, url->GetHost() + ":" + url->GetPort());
|
|
+ HttpUtility::Set(request, http::field::user_agent, "Icinga/" + Application::GetAppVersion());
|
|
+ HttpUtility::Set(request, http::field::host, url->GetHost() + ":" + url->GetPort());
|
|
|
|
request.body() = body;
|
|
- request.set(http::field::content_length, request.body().size());
|
|
+ HttpUtility::Set(request, http::field::content_length, request.body().size());
|
|
|
|
try {
|
|
if (stream.first) {
|
|
diff --git a/lib/remote/configfileshandler.cpp b/lib/remote/configfileshandler.cpp
|
|
index d714f4d864..5c2bfdb405 100644
|
|
--- a/lib/remote/configfileshandler.cpp
|
|
+++ b/lib/remote/configfileshandler.cpp
|
|
@@ -82,9 +82,9 @@ bool ConfigFilesHandler::HandleRequest(
|
|
|
|
String content((std::istreambuf_iterator<char>(fp)), std::istreambuf_iterator<char>());
|
|
response.result(http::status::ok);
|
|
- response.set(http::field::content_type, "application/octet-stream");
|
|
+ HttpUtility::Set(response, http::field::content_type, "application/octet-stream");
|
|
response.body() = content;
|
|
- response.set(http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
} catch (const std::exception& ex) {
|
|
HttpUtility::SendJsonError(response, params, 500, "Could not read file.",
|
|
DiagnosticInformation(ex));
|
|
diff --git a/lib/remote/eventshandler.cpp b/lib/remote/eventshandler.cpp
|
|
index e92b14a2d4..e41b4711c6 100644
|
|
--- a/lib/remote/eventshandler.cpp
|
|
+++ b/lib/remote/eventshandler.cpp
|
|
@@ -100,7 +100,7 @@ bool EventsHandler::HandleRequest(
|
|
server.StartStreaming();
|
|
|
|
response.result(http::status::ok);
|
|
- response.set(http::field::content_type, "application/json");
|
|
+ HttpUtility::Set(response, http::field::content_type, "application/json");
|
|
|
|
IoBoundWorkSlot dontLockTheIoThread (yc);
|
|
|
|
diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp
|
|
index d4eac7d074..688392c821 100644
|
|
--- a/lib/remote/httpserverconnection.cpp
|
|
+++ b/lib/remote/httpserverconnection.cpp
|
|
@@ -184,12 +184,12 @@ bool EnsureValidHeaders(
|
|
{ "status", String("Bad Request: ") + errorMsg }
|
|
}));
|
|
} else {
|
|
- response.set(http::field::content_type, "text/html");
|
|
+ HttpUtility::Set(response, http::field::content_type, "text/html");
|
|
response.body() = String("<h1>Bad Request</h1><p><pre>") + errorMsg + "</pre></p>";
|
|
- response.set(http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
}
|
|
|
|
- response.set(http::field::connection, "close");
|
|
+ HttpUtility::Set(response, http::field::connection, "close");
|
|
|
|
boost::system::error_code ec;
|
|
|
|
@@ -247,20 +247,20 @@ bool HandleAccessControl(
|
|
auto& origin (request[http::field::origin]);
|
|
|
|
if (allowedOrigins.find(origin.to_string()) != allowedOrigins.end()) {
|
|
- response.set(http::field::access_control_allow_origin, origin);
|
|
+ HttpUtility::Set(response, http::field::access_control_allow_origin, origin);
|
|
}
|
|
|
|
allowOriginHeader.Done();
|
|
|
|
- response.set(http::field::access_control_allow_credentials, "true");
|
|
+ HttpUtility::Set(response, http::field::access_control_allow_credentials, "true");
|
|
|
|
if (request.method() == http::verb::options && !request[http::field::access_control_request_method].empty()) {
|
|
response.result(http::status::ok);
|
|
- response.set(http::field::access_control_allow_methods, "GET, POST, PUT, DELETE");
|
|
- response.set(http::field::access_control_allow_headers, "Authorization, X-HTTP-Method-Override");
|
|
+ HttpUtility::Set(response, http::field::access_control_allow_methods, "GET, POST, PUT, DELETE");
|
|
+ HttpUtility::Set(response, http::field::access_control_allow_headers, "Authorization, X-HTTP-Method-Override");
|
|
response.body() = "Preflight OK";
|
|
- response.set(http::field::content_length, response.body().size());
|
|
- response.set(http::field::connection, "close");
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::connection, "close");
|
|
|
|
boost::system::error_code ec;
|
|
|
|
@@ -288,10 +288,10 @@ bool EnsureAcceptHeader(
|
|
|
|
if (request.method() != http::verb::get && request[http::field::accept] != "application/json") {
|
|
response.result(http::status::bad_request);
|
|
- response.set(http::field::content_type, "text/html");
|
|
+ HttpUtility::Set(response, http::field::content_type, "text/html");
|
|
response.body() = "<h1>Accept header is missing or not set to 'application/json'.</h1>";
|
|
- response.set(http::field::content_length, response.body().size());
|
|
- response.set(http::field::connection, "close");
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::connection, "close");
|
|
|
|
boost::system::error_code ec;
|
|
|
|
@@ -320,8 +320,8 @@ bool EnsureAuthenticatedUser(
|
|
<< "Unauthorized request: " << request.method_string() << ' ' << request.target();
|
|
|
|
response.result(http::status::unauthorized);
|
|
- response.set(http::field::www_authenticate, "Basic realm=\"Icinga 2\"");
|
|
- response.set(http::field::connection, "close");
|
|
+ HttpUtility::Set(response, http::field::www_authenticate, "Basic realm=\"Icinga 2\"");
|
|
+ HttpUtility::Set(response, http::field::connection, "close");
|
|
|
|
if (request[http::field::accept] == "application/json") {
|
|
HttpUtility::SendJsonBody(response, nullptr, new Dictionary({
|
|
@@ -329,9 +329,9 @@ bool EnsureAuthenticatedUser(
|
|
{ "status", "Unauthorized. Please check your user credentials." }
|
|
}));
|
|
} else {
|
|
- response.set(http::field::content_type, "text/html");
|
|
+ HttpUtility::Set(response, http::field::content_type, "text/html");
|
|
response.body() = "<h1>Unauthorized. Please check your user credentials.</h1>";
|
|
- response.set(http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
}
|
|
|
|
boost::system::error_code ec;
|
|
@@ -421,12 +421,12 @@ bool EnsureValidBody(
|
|
{ "status", String("Bad Request: ") + ec.message() }
|
|
}));
|
|
} else {
|
|
- response.set(http::field::content_type, "text/html");
|
|
+ HttpUtility::Set(response, http::field::content_type, "text/html");
|
|
response.body() = String("<h1>Bad Request</h1><p><pre>") + ec.message() + "</pre></p>";
|
|
- response.set(http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
}
|
|
|
|
- response.set(http::field::connection, "close");
|
|
+ HttpUtility::Set(response, http::field::connection, "close");
|
|
|
|
http::async_write(stream, response, yc[ec]);
|
|
stream.async_flush(yc[ec]);
|
|
@@ -511,7 +511,7 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|
parser.header_limit(1024 * 1024);
|
|
parser.body_limit(-1);
|
|
|
|
- response.set(http::field::server, l_ServerHeader);
|
|
+ HttpUtility::Set(response, http::field::server, l_ServerHeader);
|
|
|
|
if (!EnsureValidHeaders(*m_Stream, buf, parser, response, m_ShuttingDown, yc)) {
|
|
break;
|
|
diff --git a/lib/remote/httputility.cpp b/lib/remote/httputility.cpp
|
|
index 91902ba501..e46e990ecf 100644
|
|
--- a/lib/remote/httputility.cpp
|
|
+++ b/lib/remote/httputility.cpp
|
|
@@ -56,9 +56,9 @@ void HttpUtility::SendJsonBody(boost::beast::http::response<boost::beast::http::
|
|
{
|
|
namespace http = boost::beast::http;
|
|
|
|
- response.set(http::field::content_type, "application/json");
|
|
+ HttpUtility::Set(response, http::field::content_type, "application/json");
|
|
response.body() = JsonEncode(val, params && GetLastParameter(params, "pretty"));
|
|
- response.set(http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
}
|
|
|
|
void HttpUtility::SendJsonError(boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
diff --git a/lib/remote/httputility.hpp b/lib/remote/httputility.hpp
|
|
index 6465b4af92..be600d4090 100644
|
|
--- a/lib/remote/httputility.hpp
|
|
+++ b/lib/remote/httputility.hpp
|
|
@@ -5,8 +5,12 @@
|
|
|
|
#include "remote/url.hpp"
|
|
#include "base/dictionary.hpp"
|
|
+#include "base/string.hpp"
|
|
#include <boost/beast/http.hpp>
|
|
+#include <boost/lexical_cast.hpp>
|
|
#include <string>
|
|
+#include <type_traits>
|
|
+#include <utility>
|
|
|
|
namespace icinga
|
|
{
|
|
@@ -26,6 +30,30 @@ class HttpUtility
|
|
static void SendJsonBody(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const Value& val);
|
|
static void SendJsonError(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const int code,
|
|
const String& verbose = String(), const String& diagnosticInformation = String());
|
|
+
|
|
+ template<class Message, class Key, class Value, typename std::enable_if<std::is_arithmetic<Value>::value, int>::type = 0>
|
|
+ static void Set(Message& message, Key&& key, Value value)
|
|
+ {
|
|
+ Set(message, std::forward<Key>(key), boost::lexical_cast<std::string>(value));
|
|
+ }
|
|
+
|
|
+ template<class Message, class Key>
|
|
+ static void Set(Message& message, Key&& key, const String& value)
|
|
+ {
|
|
+ Set(message, std::forward<Key>(key), value.GetData());
|
|
+ }
|
|
+
|
|
+ template<class Message, class Key>
|
|
+ static void Set(Message& message, Key&& key, String&& value)
|
|
+ {
|
|
+ Set(message, std::forward<Key>(key), value.GetData());
|
|
+ }
|
|
+
|
|
+ template<class Message, class Key, class Value, typename std::enable_if<!std::is_arithmetic<Value>::value, int>::type = 0>
|
|
+ static void Set(Message& message, Key&& key, Value&& value)
|
|
+ {
|
|
+ message.set(std::forward<Key>(key), std::forward<Value>(value));
|
|
+ }
|
|
};
|
|
|
|
}
|
|
diff --git a/lib/remote/infohandler.cpp b/lib/remote/infohandler.cpp
|
|
index 18c18c0e04..daec628047 100644
|
|
--- a/lib/remote/infohandler.cpp
|
|
+++ b/lib/remote/infohandler.cpp
|
|
@@ -29,7 +29,7 @@ bool InfoHandler::HandleRequest(
|
|
|
|
if (url->GetPath().empty()) {
|
|
response.result(http::status::found);
|
|
- response.set(http::field::location, "/v1");
|
|
+ HttpUtility::Set(response, http::field::location, "/v1");
|
|
return true;
|
|
}
|
|
|
|
@@ -74,7 +74,7 @@ bool InfoHandler::HandleRequest(
|
|
|
|
HttpUtility::SendJsonBody(response, params, result);
|
|
} else {
|
|
- response.set(http::field::content_type, "text/html");
|
|
+ HttpUtility::Set(response, http::field::content_type, "text/html");
|
|
|
|
String body = "<html><head><title>Icinga 2</title></head><h1>Hello from Icinga 2 (Version: " + Application::GetAppVersion() + ")!</h1>";
|
|
body += "<p>You are authenticated as <b>" + user->GetName() + "</b>. ";
|
|
@@ -92,7 +92,7 @@ bool InfoHandler::HandleRequest(
|
|
|
|
body += R"(<p>More information about API requests is available in the <a href="https://icinga.com/docs/icinga2/latest/" target="_blank">documentation</a>.</p></html>)";
|
|
response.body() = body;
|
|
- response.set(http::field::content_length, response.body().size());
|
|
+ HttpUtility::Set(response, http::field::content_length, response.body().size());
|
|
}
|
|
|
|
return true;
|
|
diff --git a/plugins/check_nscp_api.cpp b/plugins/check_nscp_api.cpp
|
|
index 3f6843ec29..ad15e62527 100644
|
|
--- a/plugins/check_nscp_api.cpp
|
|
+++ b/plugins/check_nscp_api.cpp
|
|
@@ -16,6 +16,7 @@
|
|
#include "base/tcpsocket.hpp" /* include global icinga::Connect */
|
|
#include "base/tlsstream.hpp"
|
|
#include "base/base64.hpp"
|
|
+#include "remote/httputility.hpp"
|
|
#include "remote/url.hpp"
|
|
#include <remote/url-characters.hpp>
|
|
#include <boost/program_options.hpp>
|
|
@@ -365,11 +366,11 @@ static Dictionary::Ptr FetchData(const String& host, const String& port, const S
|
|
|
|
http::request<http::string_body> request (http::verb::get, std::string(url->Format(true)), 10);
|
|
|
|
- request.set(http::field::user_agent, "Icinga/check_nscp_api/" + String(VERSION));
|
|
- request.set(http::field::host, host + ":" + port);
|
|
+ HttpUtility::Set(request, http::field::user_agent, "Icinga/check_nscp_api/" + String(VERSION));
|
|
+ HttpUtility::Set(request, http::field::host, host + ":" + port);
|
|
|
|
- request.set(http::field::accept, "application/json");
|
|
- request.set("password", password);
|
|
+ HttpUtility::Set(request, http::field::accept, "application/json");
|
|
+ HttpUtility::Set(request, "password", password);
|
|
|
|
if (l_Debug) {
|
|
std::cout << "Sending request to " << url->Format(false, false) << "'.\n";
|
|
From 7e62a68eadada58e762d3f4261750796adffd440 Mon Sep 17 00:00:00 2001
|
|
From: "Alexander A. Klimov" <alexander.klimov@icinga.com>
|
|
Date: Wed, 26 Aug 2020 13:48:39 +0200
|
|
Subject: [PATCH] Define BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
|
|
|
|
refs #8185
|
|
---
|
|
CMakeLists.txt | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|
index 046f23cf22..46e765415e 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -172,6 +172,9 @@ add_definitions(-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
|
|
|
|
add_definitions(-DBOOST_FILESYSTEM_NO_DEPRECATED)
|
|
|
|
+# Required for Boost v1.74+
|
|
+add_definitions(-DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
|
+
|
|
link_directories(${Boost_LIBRARY_DIRS})
|
|
include_directories(${Boost_INCLUDE_DIRS})
|
|
|