diff --git a/.github/workflows/Linux build template.yml b/.github/workflows/Linux build template.yml index d492db1df..81f52d83d 100644 --- a/.github/workflows/Linux build template.yml +++ b/.github/workflows/Linux build template.yml @@ -26,9 +26,9 @@ jobs: sudo apt-spy2 fix --commit --launchpad --country=US echo "deb http://archive.ubuntu.com/ubuntu/ jammy main universe restricted multiverse" | sudo tee -a /etc/apt/sources.list echo "deb http://archive.ubuntu.com/ubuntu/ jammy-updates main universe restricted multiverse" | sudo tee -a /etc/apt/sources.list - sudo dpkg --add-architecture i386 + ${{matrix.architecture == '32' && 'sudo dpkg --add-architecture i386' || ':'}} sudo apt-get update - sudo apt install python3-pip build-essential cmake ninja-build libusb-1.0-0-dev zlib1g-dev zlib1g-dev:i386 libssl-dev gcc-11-multilib g++-11-multilib + sudo apt install python3-pip build-essential cmake ninja-build libusb-1.0-0-dev ${{matrix.architecture == '32' && 'zlib1g-dev:i386 libssl-dev:i386 libsbc-dev:i386 gcc-11-multilib g++-11-multilib' || 'zlib1g-dev libssl-dev libsbc-dev'}} sudo pip install jsonref # ----- Checkout & DependsOn regex ----- @@ -85,6 +85,7 @@ jobs: # ----- Installing generators & Options regex ----- - name: Install generators run: | + ${{matrix.architecture == '32' && 'export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig:$PKG_CONFIG_PATH' || 'PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH'}} cmake -G Ninja -S ThunderTools -B ${{matrix.build_type}}/build/ThunderTools \ -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic -Werror -m${{matrix.architecture}}" \ -DCMAKE_C_FLAGS="-Wall -Wextra -Wpedantic -Werror -m${{matrix.architecture}}" \ @@ -103,6 +104,7 @@ jobs: # ----- Building & uploading artifacts ----- - name: Build Thunder run: | + ${{matrix.architecture == '32' && 'export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig:$PKG_CONFIG_PATH' || 'PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH'}} cmake -G Ninja -S Thunder -B ${{matrix.build_type}}/build/Thunder \ -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic -Werror -m${{matrix.architecture}}" \ -DCMAKE_C_FLAGS="-Wall -Wextra -Wpedantic -Werror -m${{matrix.architecture}}" \ @@ -117,6 +119,11 @@ jobs: -DPROXYSTUB_PATH="${PWD}/${{matrix.build_type}}/install/usr/lib/wpeframework/proxystubs" \ -DSYSTEM_PATH="${PWD}/${{matrix.build_type}}/install/usr/lib/wpeframework/plugins" \ -DVOLATILE_PATH="tmp" \ + -DBLUETOOTH_SUPPORT=ON \ + -DBLUETOOTH=ON \ + -DDOWNLOAD_BLUEZ_UTIL_HEADERS=ON \ + -DBLUETOOTH_AUDIO_SUPPORT=ON \ + -DBLUETOOTH_GATT_SUPPORT=ON \ -DLOCALTRACER=ON \ -DWARNING_REPORTING=ON \ -DPROCESSCONTAINERS=ON \ diff --git a/Source/Thunder/Config.h b/Source/Thunder/Config.h index d3fc8f160..9152bdd4b 100644 --- a/Source/Thunder/Config.h +++ b/Source/Thunder/Config.h @@ -114,64 +114,6 @@ namespace PluginHost { // Configuration to get a server (PluginHost server) up and running. class JSONConfig : public Core::JSON::Container { public: - class Environment : public Core::JSON::Container { - public: - Environment() - : Core::JSON::Container() - , Key() - , Value() - , Override(false) - { - Add(_T("key"), &Key); - Add(_T("value"), &Value); - Add(_T("override"), &Override); - } - Environment(const Environment& copy) - : Core::JSON::Container() - , Key(copy.Key) - , Value(copy.Value) - , Override(copy.Override) - { - Add(_T("key"), &Key); - Add(_T("value"), &Value); - Add(_T("override"), &Override); - } - Environment(Environment&& move) noexcept - : Core::JSON::Container() - , Key(std::move(move.Key)) - , Value(std::move(move.Value)) - , Override(std::move(move.Override)) - { - Add(_T("key"), &Key); - Add(_T("value"), &Value); - Add(_T("override"), &Override); - } - ~Environment() override = default; - Environment& operator=(const Environment& RHS) - { - Key = RHS.Key; - Value = RHS.Value; - Override = RHS.Override; - - return (*this); - } - Environment& operator=(Environment&& move) noexcept - { - if (this != &move) { - Key = std::move(move.Key); - Value = std::move(move.Value); - Override = std::move(move.Override); - } - - return (*this); - } - - public: - Core::JSON::String Key; - Core::JSON::String Value; - Core::JSON::Boolean Override; - }; - class ProcessSet : public Core::JSON::Container { public: ProcessSet() @@ -526,7 +468,7 @@ namespace PluginHost { Core::JSON::String Configs; Core::JSON::String EthernetCard; Core::JSON::ArrayType Plugins; - Core::JSON::ArrayType Environments; + Core::JSON::ArrayType Environments; Core::JSON::ArrayType> ExitReasons; Core::JSON::DecSInt32 Latitude; Core::JSON::DecSInt32 Longitude; @@ -773,12 +715,12 @@ namespace PluginHost { } bool status = true; - Core::JSON::ArrayType::ConstIterator index(static_cast(config).Environments.Elements()); + Core::JSON::ArrayType::ConstIterator index(static_cast(config).Environments.Elements()); while (index.Next() == true) { if ((index.Current().Key.IsSet() == true) && (index.Current().Value.IsSet() == true)) { string value = _substituter.Substitute(index.Current().Value.Value(), nullptr); if (value.empty() != true) { - status = Core::SystemInfo::SetEnvironment(index.Current().Key.Value(), value, index.Current().Override.Value()); + status = Core::SystemInfo::SetEnvironment(index.Current().Key.Value(), value, ((index.Current().Override.Value() == RPC::Object::Environment::Scope::GLOBAL) ? true : false)); if (status != true) { SYSLOG(Logging::Startup, (_T("Failure in setting Key:Value:[%s]:[%s]\n"), index.Current().Key.Value().c_str(), index.Current().Value.Value().c_str())); } diff --git a/Source/Thunder/Controller.cpp b/Source/Thunder/Controller.cpp index 5664d6e10..f0683b703 100644 --- a/Source/Thunder/Controller.cpp +++ b/Source/Thunder/Controller.cpp @@ -239,12 +239,12 @@ namespace Plugin { Core::hresult Controller::Delete(const string& path) { Core::hresult result = Core::ERROR_UNKNOWN_KEY; - bool valid; - string normalized_path = Core::File::Normalize(path, valid); ASSERT(_service != nullptr); - if (valid == false) { + const string normalized_path = Core::File::Normalize(path, true /* safe paths only */); + + if (normalized_path.empty() == true) { result = Core::ERROR_PRIVILIGED_REQUEST; } else { @@ -681,10 +681,9 @@ namespace Plugin { remainder = index.Remainder().Text(); } - bool valid; - string normalized(Core::File::Normalize(remainder, valid)); + const string normalized(Core::File::Normalize(remainder, true /* safe paths only */)); - if (valid == false) { + if (normalized.empty() == true) { result->Message = "incorrect path"; result->ErrorCode = Web::STATUS_BAD_REQUEST; } @@ -1221,31 +1220,25 @@ namespace Plugin { { Core::hresult result = Core::ERROR_UNKNOWN_KEY; - RPC::Administrator::Proxies collection; - - // Search for the Dangling proxies - if (RPC::Administrator::Instance().Allocations(linkId, collection) == true) { - - using Iterator = IMetadata::Data::IProxiesIterator; - - std::list< IMetadata::Data::Proxy> elements; - - for (const ProxyStub::UnknownProxy* proxy : collection) { + std::vector collection; + bool proxySearch = RPC::Administrator::Instance().Allocations(linkId, [&collection](const std::vector& proxies) { + for (const auto& proxy : proxies) { IMetadata::Data::Proxy data; + data.Count = proxy->ReferenceCount(); data.Instance = proxy->Implementation(); data.Interface = proxy->InterfaceId(); - data.Count = proxy->ReferenceCount(); data.Name = proxy->Name(); - - elements.emplace_back(std::move(data)); - } + collection.emplace_back(std::move(data)); + } + }); - outProxies = Core::ServiceType>::Create(std::move(elements)); - ASSERT(outProxies != nullptr); + if (proxySearch == true) { + using Iterator = IMetadata::Data::IProxiesIterator; + outProxies = Core::ServiceType>::Create(std::move(collection)); + ASSERT(outProxies != nullptr); result = Core::ERROR_NONE; } - return (result); } diff --git a/Source/Thunder/IRemoteInstantiation.h b/Source/Thunder/IRemoteInstantiation.h index f3249295b..169bb4a0a 100644 --- a/Source/Thunder/IRemoteInstantiation.h +++ b/Source/Thunder/IRemoteInstantiation.h @@ -27,6 +27,7 @@ namespace PluginHost { struct IRemoteInstantiation : virtual public Core::IUnknown { enum { ID = RPC::IDS::ID_REMOTE_INSTANTIATION }; + using IEnvironmentIterator = RPC::IIteratorType; ~IRemoteInstantiation() override = default; @@ -56,7 +57,8 @@ namespace PluginHost { const string& systemRootPath, const uint8_t threads, const int8_t priority, - const string configuration) = 0; + const string configuration, + IEnvironmentIterator* const& environments) = 0; }; } } diff --git a/Source/Thunder/PluginHost.cpp b/Source/Thunder/PluginHost.cpp index 307589c5e..be22a0b7a 100644 --- a/Source/Thunder/PluginHost.cpp +++ b/Source/Thunder/PluginHost.cpp @@ -712,15 +712,13 @@ POP_WARNING() printf("Link: %s\n", index.Current().Remote.Value().c_str()); printf("------------------------------------------------------------\n"); - RPC::Administrator::Proxies proxies; - - RPC::Administrator::Instance().Allocations(index.Current().ID.Value(), proxies); - - for (const ProxyStub::UnknownProxy* proxy : proxies) { + RPC::Administrator::Instance().Allocations(index.Current().ID.Value(), [](const std::vector& proxies) { + for (const auto& proxy: proxies) { Core::instance_id instanceId = proxy->Implementation(); printf("[%s] InstanceId: 0x%" PRIx64 ", RefCount: %d, InterfaceId %d [0x%X]\n", proxy->Name().c_str(), static_cast(instanceId), proxy->ReferenceCount(), proxy->InterfaceId(), proxy->InterfaceId()); } printf("\n"); + }); } } break; diff --git a/Source/Thunder/PluginServer.cpp b/Source/Thunder/PluginServer.cpp index 6a5a9f406..379ee0a09 100644 --- a/Source/Thunder/PluginServer.cpp +++ b/Source/Thunder/PluginServer.cpp @@ -581,26 +581,28 @@ namespace PluginHost { Lock(); - if (_jsonrpc != nullptr) { - PluginHost::IShell::IConnectionServer::INotification* sink = nullptr; - _jsonrpc->Detach(sink); - if (sink != nullptr) { - Unregister(sink); - sink->Release(); - } + if (currentState != IShell::state::ACTIVATION) { + SYSLOG(Logging::Shutdown, (_T("Deactivated plugin [%s]:[%s]"), className.c_str(), callSign.c_str())); + +#ifdef THUNDER_RESTFULL_API + Notify(EMPTY_STRING, string(_T("{\"state\":\"deactivated\",\"reason\":\"")) + textReason.Data() + _T("\"}")); +#endif + Notify(_T("statechange"), string(_T("{\"state\":\"deactivated\",\"reason\":\"")) + textReason.Data() + _T("\"}")); } if (_external.Connector().empty() == false) { _external.Close(0); } - if (currentState != IShell::state::ACTIVATION) { - SYSLOG(Logging::Shutdown, (_T("Deactivated plugin [%s]:[%s]"), className.c_str(), callSign.c_str())); + if (_jsonrpc != nullptr) { + PluginHost::IShell::IConnectionServer::INotification* sink = nullptr; - #ifdef THUNDER_RESTFULL_API - Notify(EMPTY_STRING, string(_T("{\"state\":\"deactivated\",\"reason\":\"")) + textReason.Data() + _T("\"}")); - #endif - Notify(_T("statechange"), string(_T("{\"state\":\"deactivated\",\"reason\":\"")) + textReason.Data() + _T("\"}")); + _jsonrpc->Detach(sink); + + if (sink != nullptr) { + Unregister(sink); + sink->Release(); + } } } diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index 769fcb036..5d6af136a 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -377,6 +377,8 @@ namespace PluginHost { DYNAMIC }; + using Services = std::unordered_map; + private: using BaseClass = PluginHost::Service; using Jobs = Core::ThrottleQueueType, ServiceMap&>; @@ -1277,17 +1279,30 @@ namespace PluginHost { string Substitute(const string& input) const override { return (_administrator.Configuration().Substitute(input, PluginHost::Service::Configuration())); } - Core::hresult Metadata(string& info /* @out */) const override { + Core::hresult Metadata(string& info /* @out */) const override { Metadata::Service result; GetMetadata(result); result.ToString(info); return (Core::ERROR_NONE); } + std::vector& SubstituteList(const std::vector& environmentList) const { + std::vector& environments = const_cast&>(environmentList); + for (auto& environment : environments) { + if ((environment.key.empty() != true) && (environment.value.empty() != true)) { + environment.value = Substitute(environment.value); + } else { + SYSLOG(Logging::Startup, (_T("Failure in Substituting Value of Key:Value:[%s]:[%s]\n"), environment.key.c_str(), environment.value.c_str())); + } + } + return environments; + } void* Instantiate(const RPC::Object& object, const uint32_t waitTime, uint32_t& sessionId) override { ASSERT(_connection == nullptr); - void* result(_administrator.Instantiate(object, waitTime, sessionId, DataPath(), PersistentPath(), VolatilePath())); + const_cast(object).Environments(SubstituteList(object.Environments())); + + void* result(_administrator.Instantiate(object, waitTime, sessionId, DataPath(), PersistentPath(), VolatilePath(), _administrator.Configuration().LinkerPluginPaths())); if (result != nullptr) { _connection = _administrator.RemoteConnection(sessionId); @@ -1373,43 +1388,38 @@ namespace PluginHost { RPC::IStringIterator* GetLibrarySearchPaths(const string& locator) const override { - std::vector all_paths; - const std::vector temp = _administrator.Configuration().LinkerPluginPaths(); - string rootPath(PluginHost::Service::Configuration().SystemRootPath.Value()); + std::vector searchPaths; - if (rootPath.empty() == false) { - rootPath = Core::Directory::Normalize(rootPath); - } + const string normalized(Core::File::Normalize(locator)); + const string rootPath(Core::Directory::Normalize(PluginHost::Service::Configuration().SystemRootPath)); - if (!temp.empty()) - { - // additionaly defined user paths - for (const string& s : temp) { - if (rootPath.empty() == true) { - all_paths.push_back(Core::Directory::Normalize(s) + locator); + ASSERT_VERBOSE((normalized.empty() == locator.empty()), "path normalization failed"); + ASSERT_VERBOSE((rootPath.empty() == PluginHost::Service::Configuration().SystemRootPath.Value().empty()), "path normalization failed"); + + if (normalized.empty() == false) { + if (Core::File::IsPathAbsolute(locator) == true) { + searchPaths.push_back(Core::File::Normalize(rootPath + normalized)); + } + else { + const std::vector& linkerPaths = _administrator.Configuration().LinkerPluginPaths(); + + if (linkerPaths.empty() == false) { + // override system paths + for (const string& path : linkerPaths) { + searchPaths.push_back(Core::Directory::Normalize(rootPath + path) + normalized); + } } else { - all_paths.push_back(rootPath + Core::Directory::Normalize(s) + locator); + // system configured paths + searchPaths.push_back(Core::Directory::Normalize(rootPath + DataPath()) + normalized); + searchPaths.push_back(Core::Directory::Normalize(rootPath + PersistentPath()) + normalized); + searchPaths.push_back(Core::Directory::Normalize(rootPath + SystemPath()) + normalized); + searchPaths.push_back(Core::Directory::Normalize(rootPath + PluginPath()) + normalized); } } } - else if (rootPath.empty() == false) - { - // system configured paths - all_paths.push_back(rootPath + DataPath() + locator); - all_paths.push_back(rootPath + PersistentPath() + locator); - all_paths.push_back(rootPath + SystemPath() + locator); - all_paths.push_back(rootPath + PluginPath() + locator); - } - else { - // system configured paths - all_paths.push_back(DataPath() + locator); - all_paths.push_back(PersistentPath() + locator); - all_paths.push_back(SystemPath() + locator); - all_paths.push_back(PluginPath() + locator); - } - return (Core::ServiceType::Create(all_paths)); + return (Core::ServiceType::Create(searchPaths)); } Core::Library LoadLibrary(const string& name) { @@ -1417,10 +1427,15 @@ namespace PluginHost { Core::Library result; RPC::IStringIterator* all_paths = GetLibrarySearchPaths(name); + ASSERT(all_paths != nullptr); + string element; while((all_paths->Next(element) == true) && (progressedState <= 2)) { + + TRACE_L1("attempting to load library %s", element.c_str()); + Core::File libraryToLoad(element); - + if (libraryToLoad.Exists() == true) { if (progressedState == 0) { progressedState = 1; @@ -1499,7 +1514,9 @@ namespace PluginHost { else { uint32_t pid; Core::ServiceAdministrator::Instance().ReleaseLibrary(std::move(_library)); - + string environments; + PluginHost::Service::Configuration().Root.Environments.ToString(environments); + RPC::Object definition(locator, classNameString, Callsign(), @@ -1512,7 +1529,8 @@ namespace PluginHost { PluginHost::Service::Configuration().Root.HostType(), SystemRootPath(), PluginHost::Service::Configuration().Root.RemoteAddress.Value(), - PluginHost::Service::Configuration().Root.Configuration.Value()); + PluginHost::Service::Configuration().Root.Configuration.Value(), + Plugin::Config::Environment::List(PluginHost::Service::Configuration().Root.Environments)); newIF = reinterpret_cast(Instantiate(definition, _administrator.Configuration().OutOfProcessWaitTime(), pid)); if (newIF == nullptr) { @@ -2007,6 +2025,10 @@ namespace PluginHost { if (instantiation == nullptr) { result = Core::ERROR_ILLEGAL_STATE; } else { + + using Iterator = IRemoteInstantiation::IEnvironmentIterator; + Iterator* environment = Core::Service>::Create(_object.Environments()); + result = instantiation->Instantiate( RPC::Communicator::RemoteConnection::Id(), _object.Locator(), @@ -2019,7 +2041,8 @@ namespace PluginHost { _object.SystemRootPath(), _object.Threads(), _object.Priority(), - _object.Configuration()); + _object.Configuration(), + environment); instantiation->Release(); } @@ -2086,6 +2109,7 @@ namespace PluginHost { const string& proxyStubPath, const string& observableProxyStubPath, const string& postMortemPath, + const std::vector& linkerPaths, const uint8_t softKillCheckWaitTime, const uint8_t hardKillCheckWaitTime, const bool delegatedReleases, @@ -2103,6 +2127,7 @@ namespace PluginHost { #else , _application(EXPAND_AND_QUOTE(HOSTING_COMPROCESS)) #endif + , _linkerPaths(linkerPaths) , _adminLock() , _requestObservers() , _proxyStubObserver(*this, observableProxyStubPath) @@ -2141,9 +2166,9 @@ namespace PluginHost { } public: - void* Create(uint32_t& connectionId, const RPC::Object& instance, const uint32_t waitTime, const string& dataPath, const string& persistentPath, const string& volatilePath) + void* Create(uint32_t& connectionId, const RPC::Object& instance, const uint32_t waitTime, const string& dataPath, const string& persistentPath, const string& volatilePath, const std::vector& linkerPaths) { - return (RPC::Communicator::Create(connectionId, instance, RPC::Config(RPC::Communicator::Connector(), _application, persistentPath, _systemPath, dataPath, volatilePath, _appPath, RPC::Communicator::ProxyStubPath(), _postMortemPath), waitTime)); + return (RPC::Communicator::Create(connectionId, instance, RPC::Config(RPC::Communicator::Connector(), _application, persistentPath, _systemPath, dataPath, volatilePath, _appPath, RPC::Communicator::ProxyStubPath(), _postMortemPath, linkerPaths), waitTime)); } const string& PersistentPath() const { @@ -2177,6 +2202,10 @@ namespace PluginHost { { return (_application); } + const std::vector& LinkerPaths() const + { + return (_linkerPaths); + } void Register(RPC::IRemoteConnection::INotification* sink) { RPC::Communicator::Register(sink); @@ -2328,6 +2357,7 @@ namespace PluginHost { const string _observableProxyStubPath; const string _postMortemPath; const string _application; + std::vector _linkerPaths; mutable Core::CriticalSection _adminLock; Observers _requestObservers; ProxyStubObserver _proxyStubObserver; @@ -2392,7 +2422,8 @@ namespace PluginHost { const string& systemRootPath, const uint8_t threads, const int8_t priority, - const string configuration) override + const string configuration, + IRemoteInstantiation::IEnvironmentIterator* const& environments) override { string persistentPath(_comms.PersistentPath()); string dataPath(_comms.DataPath()); @@ -2404,10 +2435,17 @@ namespace PluginHost { volatilePath += callsign + '/'; } - uint32_t id; - RPC::Config config(_connector, _comms.Application(), persistentPath, _comms.SystemPath(), dataPath, volatilePath, _comms.AppPath(), _comms.ProxyStubPath(), _comms.PostMortemPath()); - RPC::Object instance(libraryName, className, callsign, interfaceId, version, user, group, threads, priority, RPC::Object::HostType::LOCAL, systemRootPath, _T(""), configuration); + std::vector _environmentList; + if (environments != nullptr) { + RPC::Object::Environment environment; + while (environments->Next(environment) == true) { + _environmentList.push_back(environment); + } + } + uint32_t id; + RPC::Config config(_connector, _comms.Application(), persistentPath, _comms.SystemPath(), dataPath, volatilePath, _comms.AppPath(), _comms.ProxyStubPath(), _comms.PostMortemPath(), _comms.LinkerPaths()); + RPC::Object instance(libraryName, className, callsign, interfaceId, version, user, group, threads, priority, RPC::Object::HostType::LOCAL, systemRootPath, _T(""), configuration, SubstituteList(callsign, _environmentList)); RPC::Communicator::Process process(requestId, config, instance); return (process.Launch(id)); @@ -2417,6 +2455,16 @@ namespace PluginHost { INTERFACE_ENTRY(IRemoteInstantiation) END_INTERFACE_MAP + private: + std::vector& SubstituteList(const string& callsign, std::vector& environments) const + { + Core::ProxyType service = _parent.GetService(callsign); + if (service.IsValid() == true) { + environments = service->SubstituteList(environments); + } + return environments; + } + private: mutable uint32_t _refCount; ServiceMap& _parent; @@ -2652,6 +2700,7 @@ namespace PluginHost { server._config.ProxyStubPath(), server._config.ObservableProxyStubPath(), server._config.PostMortemPath(), + server._config.LinkerPluginPaths(), server._config.SoftKillCheckWaitTime(), server._config.HardKillCheckWaitTime(), server._config.DelegatedReleases(), @@ -2895,9 +2944,9 @@ namespace PluginHost { return (result); } - void* Instantiate(const RPC::Object& object, const uint32_t waitTime, uint32_t& sessionId, const string& dataPath, const string& persistentPath, const string& volatilePath) + void* Instantiate(const RPC::Object& object, const uint32_t waitTime, uint32_t& sessionId, const string& dataPath, const string& persistentPath, const string& volatilePath, const std::vector& linkerPaths) { - return (_processAdministrator.Create(sessionId, object, waitTime, dataPath, persistentPath, volatilePath)); + return (_processAdministrator.Create(sessionId, object, waitTime, dataPath, persistentPath, volatilePath, linkerPaths)); } void Destroy(const uint32_t id) { _processAdministrator.Destroy(id); @@ -3056,6 +3105,17 @@ namespace PluginHost { _adminLock.Unlock(); } + inline Core::ProxyType GetService(const string& callsign) + { + Core::ProxyType service; + for (std::pair>& entry : _services) { + if (entry.first == callsign) { + service = entry.second; + break; + } + } + return service; + } inline Iterator Services() { Shells workingList; diff --git a/Source/ThunderPlugin/Process.cpp b/Source/ThunderPlugin/Process.cpp index e8510e0ef..e7cab38c8 100644 --- a/Source/ThunderPlugin/Process.cpp +++ b/Source/ThunderPlugin/Process.cpp @@ -81,7 +81,6 @@ POP_WARNING() TRACE_L1("We still have living object [%d].", instances); } else { - TRACE_L1("All living objects are killed. Time for HaraKiri!!."); // Seems there is no more live here, time to signal the @@ -130,7 +129,6 @@ POP_WARNING() } void Run() { - Core::WorkerPool::Run(); Core::WorkerPool::Join(); } @@ -161,7 +159,7 @@ POP_WARNING() class ConsoleOptions : public Core::Options { public: ConsoleOptions(int argumentCount, TCHAR* arguments[]) - : Core::Options(argumentCount, arguments, _T("h:l:c:C:r:p:s:d:a:m:i:u:g:t:e:x:V:v:P:S:")) + : Core::Options(argumentCount, arguments, _T("h:l:c:C:r:p:s:d:a:m:i:u:g:t:e:E:x:V:v:P:S:f:")) , Locator(nullptr) , ClassName(nullptr) , Callsign(nullptr) @@ -180,6 +178,7 @@ POP_WARNING() , User(nullptr) , Group(nullptr) , Threads(1) + , LinkerPaths() { Parse(); } @@ -203,9 +202,11 @@ POP_WARNING() string ProxyStubPath; string PostMortemPath; string SystemRootPath; + std::vector Environments; const TCHAR* User; const TCHAR* Group; uint8_t Threads; + std::vector LinkerPaths; private: string Strip(const TCHAR text[]) const @@ -236,28 +237,35 @@ POP_WARNING() RemoteChannel = argument; break; case 'p': - PersistentPath = Strip(argument); + PersistentPath = Core::Directory::Normalize(Strip(argument)); break; case 's': - SystemPath = Strip(argument); + SystemPath = Core::Directory::Normalize(Strip(argument)); break; case 'd': - DataPath = Strip(argument); + DataPath = Core::Directory::Normalize(Strip(argument)); break; case 'P': - PostMortemPath = Strip(argument); + PostMortemPath = Core::Directory::Normalize(Strip(argument)); break; case 'S': - SystemRootPath = Strip(argument); + SystemRootPath = Core::Directory::Normalize(Strip(argument)); + break; + case 'e': + case 'E': { + Environments.push_back(Plugin::Config::Environment::Info(Strip(argument), + ((option == 'E') ? RPC::Object::Environment::Scope::GLOBAL : + RPC::Object::Environment::Scope::LOCAL))); break; + } case 'v': - VolatilePath = Strip(argument); + VolatilePath = Core::Directory::Normalize(Strip(argument)); break; case 'a': - AppPath = Strip(argument); + AppPath = Core::Directory::Normalize(Strip(argument)); break; case 'm': - ProxyStubPath = Strip(argument); + ProxyStubPath = Core::Directory::Normalize(Strip(argument)); break; case 'u': User = argument; @@ -277,6 +285,9 @@ POP_WARNING() case 't': Threads = Core::NumberType(Core::TextFragment(argument)).Value(); break; + case 'f': + LinkerPaths.push_back(Strip(argument)); + break; case 'h': default: RequestUsage(true); @@ -285,52 +296,59 @@ POP_WARNING() } }; - static void* CheckInstance(const string& path, const TCHAR locator[], const TCHAR className[], const uint32_t ID, const uint32_t version) + static void* CheckInstance(const string& path, const ConsoleOptions& options) { void* result = nullptr; if (path.empty() == false) { - Core::ServiceAdministrator& admin(Core::ServiceAdministrator::Instance()); - string libraryPath = locator; - if (libraryPath.empty() || (libraryPath[0] != '/')) { - // Relative path, prefix with path name. - string pathName(Core::Directory::Normalize(path)); - libraryPath = pathName + locator; - } + TRACE_L1("Attempting to load '%s' from %s...", options.ClassName, path.c_str()); - Core::Library library(libraryPath.c_str()); + Core::Library library(path.c_str()); if (library.IsLoaded() == true) { // Instantiate the object - result = admin.Instantiate(library, className, version, ID); + result = Core::ServiceAdministrator::Instance().Instantiate(library, options.ClassName, options.Version, options.InterfaceId); } } return (result); } - static void* AcquireInterfaces(ConsoleOptions& options) + static void* AcquireInterfaces(const ConsoleOptions& options) { void* result = nullptr; if ((options.Locator != nullptr) && (options.ClassName != nullptr)) { - string path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + options.PersistentPath; - result = CheckInstance(path, options.Locator, options.ClassName, options.InterfaceId, options.Version); - if (result == nullptr) { - path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + options.SystemPath; - result = CheckInstance(path, options.Locator, options.ClassName, options.InterfaceId, options.Version); + const string rootPath = Core::Directory::Normalize(options.SystemRootPath); + + if (Core::File::IsPathAbsolute(options.Locator) == true) { + result = CheckInstance(Core::File::Normalize(rootPath + options.Locator), options); + } + else if (options.LinkerPaths.empty() == false) { + // Linker paths override system paths + for (const string& linkerPath : options.LinkerPaths) { + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + linkerPath) + options.Locator), options); + + if (result != nullptr) { + break; + } + } + } + else { + // System paths + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.PersistentPath) + options.Locator), options); if (result == nullptr) { - path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + options.DataPath; - result = CheckInstance(path, options.Locator, options.ClassName, options.InterfaceId, options.Version); + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.SystemPath) + options.Locator), options); if (result == nullptr) { - string searchPath(options.AppPath.empty() == false ? Core::Directory::Normalize(options.AppPath) : string()); + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.DataPath) + options.Locator), options); - path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + searchPath; - result = CheckInstance((path + _T("Plugins/")), options.Locator, options.ClassName, options.InterfaceId, options.Version); + if (result == nullptr) { + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.AppPath + _T("Plugins")) + options.Locator), options); + } } } } @@ -577,23 +595,28 @@ int main(int argc, char** argv) printf(" [-s ]\n"); printf(" [-d ]\n"); printf(" [-v ]\n"); + printf(" [-f ...\n"); + printf(" [-e/-E ...]\n"); + printf(" e: means set as local scope, E: means set as global scope\n"); printf(" [-a ]\n"); printf(" [-m ]\n"); printf(" [-P ]\n\n"); printf(" [-S ]\n\n"); + printf("\n"); printf("This application spawns a seperate process space for a plugin. The plugins"); printf("are searched in the same order as they are done in process. Starting from:\n"); - printf(" 1) /\n"); - printf(" 2) /\n"); - printf(" 3) /\n"); - printf(" 4) /Plugins/\n\n"); + printf(" 1) [system_path/]/\n"); + printf(" 2) [system_path/]/\n"); + printf(" 3) [system_path/]/\n"); + printf(" 4) [system_path/]/Plugins/\n\n"); + printf("\n"); + printf("Alternatively, if linker paths are specified:\n"); + printf(" 1) [system_path/]/locator\n"); + printf(" 2) [system_path/]/locator, ...\n"); + printf("\n"); printf("Within the DSO, the system looks for an object with , this object must implement "); printf("the interface, indicated byt the Id , and if passed, the object should be of "); printf("version . All these conditions must met for an object to be instantiated and thus run.\n\n"); - - for (uint8_t teller = 0; teller < argc; teller++) { - printf("Argument [%02d]: %s\n", teller, argv[teller]); - } } else { string callsign; if (options.Callsign != nullptr) { @@ -640,7 +663,7 @@ int main(int argc, char** argv) if (remoteNode.IsValid()) { void* base = nullptr; - TRACE_L1("Spawning a new plugin %s.", options.ClassName); + TRACE_L1("Spawning a new plugin %s", options.Callsign); // Firts make sure we apply the correct rights to our selves.. if (options.Group != nullptr) { @@ -651,6 +674,15 @@ int main(int argc, char** argv) Core::ProcessCurrent().User(string(options.User)); } + for (const auto& info : options.Environments) { + if ((info.key.empty() != true) && (info.value.empty() != true)) { + uint32_t status = Core::SystemInfo::SetEnvironment(info.key, info.value.c_str(), ((info.overriding == RPC::Object::Environment::Scope::GLOBAL) ? true : false)); + if (status != true) { + SYSLOG(Logging::Startup, (_T("Failure in setting Key:Value:[%s]:[%s]\n"), info.key.c_str(), info.value.c_str())); + } + } + } + process.Startup(options.Threads, remoteNode, callsign); // Register an interface to handle incoming requests for interfaces. diff --git a/Source/com/Administrator.h b/Source/com/Administrator.h index a378c6244..95b5eeea0 100644 --- a/Source/com/Administrator.h +++ b/Source/com/Administrator.h @@ -147,28 +147,34 @@ namespace RPC { void DelegatedReleases(const bool enabled) { _delegatedReleases = enabled; } - bool Allocations(const uint32_t id, Proxies& proxies) const { + + template + bool Allocations(const uint32_t id, ACTION&& action) const { bool found = false; + _adminLock.Lock(); if (id == 0) { + for (const auto& proxy : _channelProxyMap) { + action(proxy.second); + } + action(_danglingProxies); found = true; - proxies = _danglingProxies; - } + } else { ChannelMap::const_iterator index(_channelProxyMap.begin()); - while ((found == false) && (index != _channelProxyMap.end())) { - if (index->first != id) { index++; } else { found = true; - proxies = index->second; + action(index->second); } } } - return (found); + _adminLock.Unlock(); + return found; } + template void Announce() { diff --git a/Source/com/Communicator.cpp b/Source/com/Communicator.cpp index 266c64772..e8efcac3d 100644 --- a/Source/com/Communicator.cpp +++ b/Source/com/Communicator.cpp @@ -575,4 +575,12 @@ namespace RPC { constexpr uint32_t RPC::ProcessShutdown::DestructionStackSize; } + +ENUM_CONVERSION_BEGIN(RPC::Object::Environment::Scope) + + { RPC::Object::Environment::Scope::LOCAL, _TXT("Local") }, + { RPC::Object::Environment::Scope::GLOBAL, _TXT("Global") }, + +ENUM_CONVERSION_END(RPC::Object::Environment::Scope) + } diff --git a/Source/com/Communicator.h b/Source/com/Communicator.h index 35aea1ced..085e3b237 100644 --- a/Source/com/Communicator.h +++ b/Source/com/Communicator.h @@ -45,12 +45,23 @@ namespace RPC { class EXTERNAL Object { public: + static constexpr const TCHAR EnvironmentSeparator = _T('='); enum class HostType { LOCAL, DISTRIBUTED, CONTAINER }; + struct Environment { + enum class Scope { + LOCAL, + GLOBAL + }; + string key; + string value; + Scope overriding; + }; + Object() : _locator() , _className() @@ -65,6 +76,7 @@ namespace RPC { , _systemRootPath() , _remoteAddress() , _configuration() + , _environments() { } Object(const Object& copy) @@ -81,6 +93,7 @@ namespace RPC { , _systemRootPath(copy._systemRootPath) , _remoteAddress(copy._remoteAddress) , _configuration(copy._configuration) + , _environments(copy._environments) { } Object(Object&& move) noexcept @@ -97,6 +110,7 @@ namespace RPC { , _systemRootPath(std::move(move._systemRootPath)) , _remoteAddress(std::move(move._remoteAddress)) , _configuration(std::move(move._configuration)) + , _environments(std::move(move._environments)) { } Object(const string& locator, @@ -111,7 +125,8 @@ namespace RPC { const HostType type, const string& systemRootPath, const string& remoteAddress, - const string& configuration) + const string& configuration, + const std::vector& environments) : _locator(locator) , _className(className) , _callsign(callsign) @@ -125,6 +140,7 @@ namespace RPC { , _systemRootPath(systemRootPath) , _remoteAddress(remoteAddress) , _configuration(configuration) + , _environments(environments) { } ~Object() @@ -146,11 +162,11 @@ namespace RPC { _type = RHS._type; _remoteAddress = RHS._remoteAddress; _configuration = RHS._configuration; + _environments = RHS._environments; return (*this); } - Object& operator=(Object&& move) noexcept { if (this != &move) { @@ -167,14 +183,15 @@ namespace RPC { _systemRootPath = std::move(move._systemRootPath); _remoteAddress = std::move(move._remoteAddress); _configuration = std::move(move._configuration); + _environments = std::move(move._environments); move._interface = ~0; move._version = ~0; move._threads = 0; move._priority = 0; - } - return (*this); - } + } + return (*this); + } public: inline const string& Locator() const @@ -229,6 +246,13 @@ namespace RPC { { return (_configuration); } + inline const std::vector& Environments() const + { + return (_environments); + } + inline void Environments(const std::vector& environments) { + _environments = std::move(environments); + } private: string _locator; @@ -244,6 +268,7 @@ namespace RPC { string _systemRootPath; string _remoteAddress; string _configuration; + std::vector _environments; }; class EXTERNAL Config { @@ -262,6 +287,7 @@ namespace RPC { , _application() , _proxyStub() , _postMortem() + , _linker() { } Config( @@ -273,7 +299,8 @@ namespace RPC { const string& volatilePath, const string& applicationPath, const string& proxyStubPath, - const string& postMortem) + const string& postMortem, + const std::vector& linker) : _connector(connector) , _hostApplication(hostApplication) , _persistent(persistentPath) @@ -283,6 +310,7 @@ namespace RPC { , _application(applicationPath) , _proxyStub(proxyStubPath) , _postMortem(postMortem) + , _linker(linker) { } Config(const Config& copy) @@ -295,9 +323,10 @@ namespace RPC { , _application(copy._application) , _proxyStub(copy._proxyStub) , _postMortem(copy._postMortem) + , _linker(copy._linker) { } - Config(Config&& move) noexcept + Config(Config&& move) noexcept : _connector(std::move(move._connector)) , _hostApplication(std::move(move._hostApplication)) , _persistent(std::move(move._persistent)) @@ -307,6 +336,7 @@ namespace RPC { , _application(std::move(move._application)) , _proxyStub(std::move(move._proxyStub)) , _postMortem(std::move(move._postMortem)) + , _linker(std::move(move._linker)) { } ~Config() @@ -350,6 +380,10 @@ namespace RPC { { return (_postMortem); } + inline const std::vector& LinkerPaths() const + { + return (_linker); + } private: string _connector; @@ -361,6 +395,7 @@ namespace RPC { string _application; string _proxyStub; string _postMortem; + std::vector _linker; }; struct EXTERNAL IMonitorableProcess : public virtual Core::IUnknown { @@ -490,6 +525,9 @@ namespace RPC { if (config.VolatilePath().empty() == false) { _options.Add(_T("-v")).Add('"' + config.VolatilePath() + '"'); } + for (auto const& path : config.LinkerPaths()) { + _options.Add(_T("-f")).Add('"' + path + '"'); + } if (config.ProxyStubPath().empty() == false) { _options.Add(_T("-m")).Add('"' + config.ProxyStubPath() + '"'); } @@ -503,6 +541,12 @@ namespace RPC { if (instance.Threads() > 1) { _options.Add(_T("-t")).Add(Core::NumberType(instance.Threads()).Text()); } + for (auto const& environment : instance.Environments()) { + string env = environment.key + RPC::Object::EnvironmentSeparator + + "\"" + environment.value + "\""; + string option = (environment.overriding == RPC::Object::Environment::Scope::GLOBAL) ? "-E" : "-e"; + _options.Add(_T(option)).Add('"' + env + '"'); + } _priority = instance.Priority(); } const string& Command() const @@ -865,7 +909,7 @@ namespace RPC { TRACE_L1("Invalid process container configuration"); } else { - std::vector searchPaths(3); + std::vector searchPaths; #ifdef __DEBUG__ if (config.ContainerPath.IsSet() == true) { diff --git a/Source/com/Ids.h b/Source/com/Ids.h index 9c387bdbb..6c1a3b07d 100644 --- a/Source/com/Ids.h +++ b/Source/com/Ids.h @@ -89,6 +89,7 @@ namespace RPC { ID_SUBSYSTEM_DECRYPTION = (ID_OFFSET_INTERNAL + 0x003E), ID_REMOTE_INSTANTIATION = (ID_OFFSET_INTERNAL + 0x003F), ID_SYSTEM_METADATA = (ID_OFFSET_INTERNAL + 0x0040), + ID_ENVIRONMENT_ITERATOR = (ID_OFFSET_INTERNAL + 0x0041), ID_EXTERNAL_INTERFACE_OFFSET = (ID_OFFSET_INTERNAL + 0x0080), ID_EXTERNAL_QA_INTERFACE_OFFSET = (ID_OFFSET_INTERNAL + 0xA000) diff --git a/Source/core/CMakeLists.txt b/Source/core/CMakeLists.txt index 65d9b6cb6..256b202f2 100644 --- a/Source/core/CMakeLists.txt +++ b/Source/core/CMakeLists.txt @@ -206,12 +206,27 @@ endif() if(BLUETOOTH_SUPPORT) target_compile_definitions(${TARGET} PUBLIC __CORE_BLUETOOTH_SUPPORT__) - find_package(Bluez5UtilHeaders REQUIRED) + include(GetBluez5Headers) - target_link_libraries(${TARGET} + GetBluez5UtilHeadersFiles(Bluez5UtilHeadersFiles) + + install(FILES ${Bluez5UtilHeadersFiles} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${NAMESPACE}/core/bluez5 COMPONENT ${NAMESPACE}_Development) + + GetBluez5IncludeDirs(Bluez5IncludeDirs) + + foreach(path ${Bluez5IncludeDirs}) + target_include_directories(${TARGET} PUBLIC - Bluez5UtilHeaders::Bluez5UtilHeaders - ) + $) + endforeach() + + CheckBluez5InclusiveLanguage(INCLUSIVE_LANGUAGE) + + if(NOT ${INCLUSIVE_LANGUAGE}) + #TODO: Remove NO_INCLUSIVE_LANGUAGE define when the plugins are synced to BLUEZ_HAS_NO_INCLUSIVE_LANGUAGE + target_compile_definitions(${TARGET} PUBLIC INTERFACE NO_INCLUSIVE_LANGUAGE BLUEZ_HAS_NO_INCLUSIVE_LANGUAGE) + endif() message(STATUS "Enable bluetooth support.") endif() diff --git a/Source/core/FileSystem.cpp b/Source/core/FileSystem.cpp index e233ffbc0..cdb9f3705 100644 --- a/Source/core/FileSystem.cpp +++ b/Source/core/FileSystem.cpp @@ -72,17 +72,15 @@ namespace Core { Close(); } - /* static */ string File::Normalize(const string& location, bool& valid) + /* static */ string File::Normalize(const string& location, const bool inScopeOnly, const bool allowDirs) { string result(location); - valid = true; - // First see if we are not empy. if (result.empty() == false) { uint32_t index = 0; - while (index < result.length()) { + while (index < result.length()) { #ifdef __WINDOWS__ if (result[index] == '\\') { @@ -90,26 +88,37 @@ namespace Core { } #endif - if ((result[index] == '/') && (index >= 1) ) { + if ((result[index] == '/') && (index >= 1)) { if (result[index - 1] == '/') { - if (index >= 2) { - // We have a double slash, clear all till the beginning - result = result.substr(index - 1); - index = 1; - } + // We have a double slash, trim it + result.erase(index, 1); + index--; } else if (result[index - 1] == '.') { if ((index == 1) || (result[index - 2] == '/')) { - // It is a dot, remove it... - uint32_t offset = (index == 1 ? 0 : index - 2); - result.erase(offset, 2); - index = offset; + if (result.length() != 2) { + // It is a dot, remove it... but not if it's just ./ + result.erase(index - (index == 1 ? 1 : 2), 2); + index -= 2; + } } else if ((result[index - 2] == '.') && ((index == 2) || (result[index - 3] == '/'))) { - if (index <= 3) { - valid = false; + if (index == 2) { + // We're going out of scope! + if (inScopeOnly == true) { + result.clear(); + } + } + else if (index == 3) { + // Going up past / thus invalid result.clear(); } +#ifdef __WINDOWS__ + else if ((index == 5) && (result[1] == ':')) { + // Going up past X:/ thus invalid + result.clear(); + } +#endif else { // Seems like we are moving up a directory... execute that on the result... if we can... // there is data we can drop, drop it, drop it till the '/' is found @@ -117,50 +126,79 @@ namespace Core { while ((offset > 0) && (result[offset] != '/')) { offset--; } - result.erase(offset, index - offset); - index = offset; + + // ...but don't swallow another .. + if ((result[offset] != '.') && (result[offset + 1] != '.')) { + result.erase(offset + (result[offset] == '/' ? 1 : 0), index - offset + (result[offset] == '/' ? 0 : -1)); + index = offset; + } } } } } index++; - } - - // It could be that the last slash is not part of the full line, check the last part, assuming there is such a slash, - // normalization rules applyt than as well.... - if ((result.length() >= 1) && (result[result.length() - 1] == '.')) { - - if (result.length() == 1) { - // We have only a dot... - result.clear(); - } - else if ( (result.length() == 2) && (result[0] == '.') ) { - // We have a ".." and nothing more - valid = false; - result.clear(); - } - else if ((result.length() >= 2) && (result[result.length() - 2] == '/')) { - result = result.substr(0, result.length() - 2); - } - else if ((result.length() >= 3) && (result[result.length() - 2] == '.') && (result[result.length() - 3] == '/')) { - // How about ThisFile/.., it is valid, but /.. would not be, both end up at an empty string... but the difference - // is the fact that the first, had a length > 3 and the second was exactly 3, so a length of 3 is invalid and empty.. - if (result.length() == 3) { - valid = false; - result.clear(); - } - else { - // there is data we can drop, drop it, drop it till the '/' is found - uint32_t offset = static_cast(result.length() - 4); - - while ((offset > 0) && (result[offset] != '/')) { - offset--; + } + + // It could be that the last slash is not part of the full line, check the last part, assuming there is such a slash, + // normalization rules apply than as well.... + if (result.length() >= 1) { + if (result[result.length() - 1] == '/') { + if (allowDirs == false) { + result.clear(); + } + else if ((result.length() == 1) && (result[0] == '/') && (location[0] == '.')) { + // Correct corner case where .//// ends up as / + result = "./"; + } + } + else if (result[result.length() - 1] == '.') { + if (allowDirs == false) { + result.clear(); + } + else if ((result.length() >= 2) && (result[result.length() - 2] == '/')) { + // Ends with /. + result.erase(result.length() - 1, 1); + } + else if ((result.length() >= 3) && (result[result.length() - 2] == '.') && (result[result.length() - 3] == '/')) { + // How about ThisFile/.., it is valid, but /.. would not be, both end up at an empty string... but the difference + // is the fact that the first, had a length > 3 and the second was exactly 3, so a length of 3 is invalid and empty.. + if (result.length() == 3) { + // Invalid /.. + result.clear(); + } +#ifdef __WINDOWS__ + else if ((result.length() == 5) && (result[1] == ':')) { + // Invalid X:/.. + result.clear(); + } +#endif + else { + // there is data we can drop, drop it, drop it till the '/' is found + uint32_t offset = static_cast(result.length() - 4); + + while ((offset > 0) && (result[offset] != '/')) { + offset--; + } + + // again do not swallow another .. + if ((result[offset] != '.') && (result[offset + 1] != '.')) { + result.erase(offset + (result[offset] == '/' ? 1 : 0)); + + if ((result.empty() == true) && (allowDirs == true)) { + // Collapsed everything, so insert current dir + result = "./"; + } + } } - result = result.substr(0, offset); - } - } - } + } + else { + // We have . or .. + result += '/'; + } + } + } } + return (result); } diff --git a/Source/core/FileSystem.h b/Source/core/FileSystem.h index a3d56dbf2..3051d41f5 100644 --- a/Source/core/FileSystem.h +++ b/Source/core/FileSystem.h @@ -199,7 +199,7 @@ namespace Core { return (*this); } - static string Normalize(const string& input, bool& valid); + static string Normalize(const string& input, const bool inScopeOnly = false, const bool allowDirs = false); public: inline static string FileName(const string& name) @@ -666,17 +666,16 @@ POP_WARNING() ~Directory(); public: - static string Normalize(const string& location) + static string Normalize(const string& location, const bool inScopeOnly = false) { string result; // First see if we are not empy. if (location.empty() == false) { - bool valid; - result = File::Normalize(location, valid); + result = File::Normalize(location, inScopeOnly, true /* accept directories */); - if ((valid == true) && ((result.empty() == true) || (result[result.length() - 1] != '/'))) { + if ((result.empty() == false) && (result[result.length() - 1] != '/')) { result += '/'; } } diff --git a/Source/core/JSON.h b/Source/core/JSON.h index c4ba49f78..7fd5a4438 100644 --- a/Source/core/JSON.h +++ b/Source/core/JSON.h @@ -3190,10 +3190,19 @@ namespace Core { bool IsNull() const override { - //TODO: Implement null for Arrays return ((_state & UNDEFINED) != 0); } + void Null(const bool enabled) + { + if (enabled == true) { + _state |= (UNDEFINED | SET); + } + else { + _state &= ~(UNDEFINED | SET); + } + } + void Set(const bool enabled) { if (enabled == true) { @@ -3360,33 +3369,40 @@ namespace Core { { uint16_t loaded = 0; - if (offset == FIND_MARKER) { - _iterator.Reset(); - if (((_state & modus::EXTRACT) == 0) || (_data.size() != 1)) { - stream[loaded++] = '['; - } - offset = (_iterator.Next() == false ? ~0 : PARSE); - } else if (offset == END_MARKER) { - offset = ~0; - } - while ((loaded < maxLength) && (offset != static_cast(~0))) { - if (offset >= PARSE) { - offset -= PARSE; - loaded += static_cast(_iterator.Current()).Serialize(&(stream[loaded]), maxLength - loaded, offset); - offset = (offset != FIND_MARKER ? offset + PARSE : (_iterator.Next() == true ? BEGIN_MARKER : ~0)); - } else if (offset == BEGIN_MARKER) { - stream[loaded++] = ','; - offset = PARSE; - } + if ((_state & modus::UNDEFINED) != 0) { + ASSERT(offset < (sizeof(IElement::NullTag) - 1)); + loaded = std::min(static_cast((sizeof(IElement::NullTag) - 1) - offset), maxLength); + ::memcpy(stream, &(IElement::NullTag[offset]), loaded); } - if (offset == static_cast(~0)) { - if (loaded < maxLength) { + else { + if (offset == FIND_MARKER) { + _iterator.Reset(); if (((_state & modus::EXTRACT) == 0) || (_data.size() != 1)) { - stream[loaded++] = ']'; + stream[loaded++] = '['; + } + offset = (_iterator.Next() == false ? ~0 : PARSE); + } else if (offset == END_MARKER) { + offset = ~0; + } + while ((loaded < maxLength) && (offset != static_cast(~0))) { + if (offset >= PARSE) { + offset -= PARSE; + loaded += static_cast(_iterator.Current()).Serialize(&(stream[loaded]), maxLength - loaded, offset); + offset = (offset != FIND_MARKER ? offset + PARSE : (_iterator.Next() == true ? BEGIN_MARKER : ~0)); + } else if (offset == BEGIN_MARKER) { + stream[loaded++] = ','; + offset = PARSE; + } + } + if (offset == static_cast(~0)) { + if (loaded < maxLength) { + if (((_state & modus::EXTRACT) == 0) || (_data.size() != 1)) { + stream[loaded++] = ']'; + } + offset = FIND_MARKER; + } else { + offset = END_MARKER; } - offset = FIND_MARKER; - } else { - offset = END_MARKER; } } @@ -3482,34 +3498,42 @@ namespace Core { { uint16_t loaded = 0; - if (offset == 0) { - _iterator.Reset(); - if (_data.size() <= 15) { - stream[loaded++] = (0x90 | static_cast(_data.size())); - if (_data.size() > 0) { - offset = PARSE; - } - } else { - stream[loaded++] = 0xDC; - offset = 1; + if ((_state & modus::UNDEFINED) != 0) { + if (offset == 0) { + stream[0] = IMessagePack::NullValue; + loaded = 1; } - _iterator.Next(); } - while ((loaded < maxLength) && (offset > 0) && (offset < PARSE)) { - if (offset == 1) { - stream[loaded++] = (_data.size() >> 8) & 0xFF; - offset = 2; - } else if (offset == 2) { - stream[loaded++] = _data.size() & 0xFF; - offset = PARSE; + else { + if (offset == 0) { + _iterator.Reset(); + if (_data.size() <= 15) { + stream[loaded++] = (0x90 | static_cast(_data.size())); + if (_data.size() > 0) { + offset = PARSE; + } + } else { + stream[loaded++] = 0xDC; + offset = 1; + } + _iterator.Next(); } - } - while ((loaded < maxLength) && (offset >= PARSE)) { - offset -= PARSE; - loaded += static_cast(_iterator.Current()).Serialize(&(stream[loaded]), maxLength - loaded, offset); - offset += PARSE; - if ((offset == PARSE) && (_iterator.Next() != true)) { - offset = 0; + while ((loaded < maxLength) && (offset > 0) && (offset < PARSE)) { + if (offset == 1) { + stream[loaded++] = (_data.size() >> 8) & 0xFF; + offset = 2; + } else if (offset == 2) { + stream[loaded++] = _data.size() & 0xFF; + offset = PARSE; + } + } + while ((loaded < maxLength) && (offset >= PARSE)) { + offset -= PARSE; + loaded += static_cast(_iterator.Current()).Serialize(&(stream[loaded]), maxLength - loaded, offset); + offset += PARSE; + if ((offset == PARSE) && (_iterator.Next() != true)) { + offset = 0; + } } } @@ -3700,9 +3724,18 @@ namespace Core { return (index != _data.end()); } + void Null(const bool enabled) + { + if (enabled == true) { + _state |= UNDEFINED; + } + else { + _state &= ~UNDEFINED; + } + } + bool IsNull() const override { - // TODO: Implement null for conrtainers return ((_state & UNDEFINED) != 0); } @@ -3741,49 +3774,56 @@ namespace Core { { uint16_t loaded = 0; - if (offset == FIND_MARKER) { - _iterator = _data.begin(); - stream[loaded++] = '{'; - - offset = (_iterator == _data.end() ? ~0 : ((_iterator->second->IsSet() == false) && (FindNext() == false)) ? ~0 : BEGIN_MARKER); - if (offset == BEGIN_MARKER) { - _fieldName = string(_iterator->first); - _current.json = &_fieldName; - offset = PARSE; - } - } else if (offset == END_MARKER) { - offset = ~0; + if ((_state & UNDEFINED) != 0) { + ASSERT(offset < (sizeof(IElement::NullTag) - 1)); + loaded = std::min(static_cast((sizeof(IElement::NullTag) - 1) - offset), maxLength); + ::memcpy(stream, &(IElement::NullTag[offset]), loaded); } + else { + if (offset == FIND_MARKER) { + _iterator = _data.begin(); + stream[loaded++] = '{'; - while ((loaded < maxLength) && (offset != static_cast(~0))) { - if (offset >= PARSE) { - offset -= PARSE; - loaded += _current.json->Serialize(&(stream[loaded]), maxLength - loaded, offset); - offset = (offset == FIND_MARKER ? BEGIN_MARKER : offset + PARSE); - } else if (offset == BEGIN_MARKER) { - if (_current.json == &_fieldName) { - stream[loaded++] = ':'; - _current.json = _iterator->second; + offset = (_iterator == _data.end() ? ~0 : ((_iterator->second->IsSet() == false) && (FindNext() == false)) ? ~0 : BEGIN_MARKER); + if (offset == BEGIN_MARKER) { + _fieldName = string(_iterator->first); + _current.json = &_fieldName; offset = PARSE; - } else { - if (FindNext() != false) { - stream[loaded++] = ','; - _fieldName = string(_iterator->first); - _current.json = &_fieldName; + } + } else if (offset == END_MARKER) { + offset = ~0; + } + + while ((loaded < maxLength) && (offset != static_cast(~0))) { + if (offset >= PARSE) { + offset -= PARSE; + loaded += _current.json->Serialize(&(stream[loaded]), maxLength - loaded, offset); + offset = (offset == FIND_MARKER ? BEGIN_MARKER : offset + PARSE); + } else if (offset == BEGIN_MARKER) { + if (_current.json == &_fieldName) { + stream[loaded++] = ':'; + _current.json = _iterator->second; offset = PARSE; } else { - offset = ~0; + if (FindNext() != false) { + stream[loaded++] = ','; + _fieldName = string(_iterator->first); + _current.json = &_fieldName; + offset = PARSE; + } else { + offset = ~0; + } } } } - } - if (offset == static_cast(~0)) { - if (loaded < maxLength) { - stream[loaded++] = '}'; - offset = FIND_MARKER; - _fieldName.Clear(); - } else { - offset = END_MARKER; + if (offset == static_cast(~0)) { + if (loaded < maxLength) { + stream[loaded++] = '}'; + offset = FIND_MARKER; + _fieldName.Clear(); + } else { + offset = END_MARKER; + } } } @@ -3952,60 +3992,68 @@ namespace Core { { uint16_t loaded = 0; - uint16_t elementSize = Size(); - if (offset == 0) { - _iterator = _data.begin(); - if (elementSize <= 15) { - stream[loaded++] = (0x80 | static_cast(Size())); - if (_iterator != _data.end()) { - offset = PARSE; - } - } else { - stream[loaded++] = 0xDE; - offset = 1; + if ((_state & UNDEFINED) != 0) { + if (offset == 0) { + stream[0] = IMessagePack::NullValue; + loaded = 1; } - if (offset != 0) { - if ((_iterator->second->IsSet() == false) && (FindNext() == false)) { - offset = 0; + } + else { + uint16_t elementSize = Size(); + if (offset == 0) { + _iterator = _data.begin(); + if (elementSize <= 15) { + stream[loaded++] = (0x80 | static_cast(Size())); + if (_iterator != _data.end()) { + offset = PARSE; + } } else { - _fieldName = string(_iterator->first); + stream[loaded++] = 0xDE; + offset = 1; + } + if (offset != 0) { + if ((_iterator->second->IsSet() == false) && (FindNext() == false)) { + offset = 0; + } else { + _fieldName = string(_iterator->first); + } } } - } - while ((loaded < maxLength) && (offset > 0) && (offset < PARSE)) { - if (offset == 1) { - stream[loaded++] = (elementSize >> 8) & 0xFF; - offset = 2; - } else if (offset == 2) { - stream[loaded++] = elementSize & 0xFF; - offset = PARSE; - } - } - while ((loaded < maxLength) && (offset >= PARSE)) { - offset -= PARSE; - if (_fieldName.IsSet() == true) { - loaded += static_cast(_fieldName).Serialize(&(stream[loaded]), maxLength - loaded, offset); - if (offset == 0) { - _fieldName.Clear(); + while ((loaded < maxLength) && (offset > 0) && (offset < PARSE)) { + if (offset == 1) { + stream[loaded++] = (elementSize >> 8) & 0xFF; + offset = 2; + } else if (offset == 2) { + stream[loaded++] = elementSize & 0xFF; + offset = PARSE; } - offset += PARSE; - } else { - const IMessagePack* element = dynamic_cast(_iterator->second); - if (element != nullptr) { - loaded += element->Serialize(&(stream[loaded]), maxLength - loaded, offset); + } + while ((loaded < maxLength) && (offset >= PARSE)) { + offset -= PARSE; + if (_fieldName.IsSet() == true) { + loaded += static_cast(_fieldName).Serialize(&(stream[loaded]), maxLength - loaded, offset); if (offset == 0) { _fieldName.Clear(); } + offset += PARSE; } else { - stream[loaded++] = IMessagePack::NullValue; - } - offset += PARSE; - if (offset == PARSE) { - if (FindNext() != false) { - _fieldName = string(_iterator->first); + const IMessagePack* element = dynamic_cast(_iterator->second); + if (element != nullptr) { + loaded += element->Serialize(&(stream[loaded]), maxLength - loaded, offset); + if (offset == 0) { + _fieldName.Clear(); + } } else { - offset = 0; - _fieldName.Clear(); + stream[loaded++] = IMessagePack::NullValue; + } + offset += PARSE; + if (offset == PARSE) { + if (FindNext() != false) { + _fieldName = string(_iterator->first); + } else { + offset = 0; + _fieldName.Clear(); + } } } } diff --git a/Source/core/Library.cpp b/Source/core/Library.cpp index 04575b3c7..4541ba3e0 100644 --- a/Source/core/Library.cpp +++ b/Source/core/Library.cpp @@ -114,8 +114,6 @@ namespace Core { _refCountedHandle->_name = GlobalSymbols; TRACE_L1("Loaded library with global symbols of the program"); } - - TRACE_L1("Loaded library: %s", fileName); } else { #ifdef __LINUX__ _error = dlerror(); diff --git a/Source/core/NodeId.h b/Source/core/NodeId.h index 4acfec44d..433ae1003 100644 --- a/Source/core/NodeId.h +++ b/Source/core/NodeId.h @@ -46,9 +46,11 @@ #endif #ifdef __CORE_BLUETOOTH_SUPPORT__ -#include <../include/bluetooth/bluetooth.h> -#include <../include/bluetooth/hci.h> -#include <../include/bluetooth/l2cap.h> +PUSH_WARNING(DISABLE_WARNING_PEDANTIC) +#include "bluez5/bluetooth.h" +#include "bluez5/hci.h" +#include "bluez5/l2cap.h" +POP_WARNING() #else #ifndef AF_BLUETOOTH #define AF_BLUETOOTH 60000 diff --git a/Source/extensions/bluetooth/CMakeLists.txt b/Source/extensions/bluetooth/CMakeLists.txt index 17afeccb6..fec0ddf61 100644 --- a/Source/extensions/bluetooth/CMakeLists.txt +++ b/Source/extensions/bluetooth/CMakeLists.txt @@ -31,8 +31,6 @@ option(BCM43XX "Select the serial driver for bluetooth modules found on Raspberr option(BLUETOOTH_GATT_SUPPORT "Include GATT support" OFF) option(BLUETOOTH_AUDIO_SUPPORT "Include audio sink/source support" OFF) -find_package(Bluez5UtilHeaders REQUIRED) - add_library(${TARGET} HCISocket.cpp UUID.cpp @@ -62,7 +60,6 @@ target_link_libraries(${TARGET} CompileSettingsDebug::CompileSettingsDebug ${NAMESPACE}Core::${NAMESPACE}Core ${NAMESPACE}Messaging::${NAMESPACE}Messaging - Bluez5UtilHeaders::Bluez5UtilHeaders ) set_target_properties(${TARGET} diff --git a/Source/extensions/bluetooth/HCISocket.h b/Source/extensions/bluetooth/HCISocket.h index 908c28f7c..fa73ac95c 100644 --- a/Source/extensions/bluetooth/HCISocket.h +++ b/Source/extensions/bluetooth/HCISocket.h @@ -23,6 +23,10 @@ #include "UUID.h" #include "BluetoothUtils.h" +PUSH_WARNING(DISABLE_WARNING_PEDANTIC) +#include +POP_WARNING() + namespace Thunder { namespace Bluetooth { diff --git a/Source/extensions/bluetooth/Module.h b/Source/extensions/bluetooth/Module.h index 499c7391b..9c24b5323 100644 --- a/Source/extensions/bluetooth/Module.h +++ b/Source/extensions/bluetooth/Module.h @@ -26,11 +26,6 @@ #include #include -#include <../include/bluetooth/bluetooth.h> -#include <../include/bluetooth/hci.h> -#include <../include/bluetooth/mgmt.h> -#include <../include/bluetooth/l2cap.h> - #include "Debug.h" #if defined(__WINDOWS__) && defined(BLUETOOTH_EXPORTS) diff --git a/Source/extensions/bluetooth/audio/CMakeLists.txt b/Source/extensions/bluetooth/audio/CMakeLists.txt index 267750ba4..1a3d470b2 100644 --- a/Source/extensions/bluetooth/audio/CMakeLists.txt +++ b/Source/extensions/bluetooth/audio/CMakeLists.txt @@ -27,7 +27,6 @@ message("Setup ${TARGET} v${PROJECT_VERSION}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") -find_package(Bluez5UtilHeaders REQUIRED) find_package(SBC REQUIRED) file(GLOB CODEC_HEADERS codecs/*.h) @@ -59,7 +58,6 @@ target_link_libraries(${TARGET} CompileSettingsDebug::CompileSettingsDebug ${NAMESPACE}Core::${NAMESPACE}Core ${NAMESPACE}Messaging::${NAMESPACE}Messaging - Bluez5UtilHeaders::Bluez5UtilHeaders SBC::SBC ) diff --git a/Source/extensions/bluetooth/audio/Module.h b/Source/extensions/bluetooth/audio/Module.h index 9cb529d5a..0aa369927 100644 --- a/Source/extensions/bluetooth/audio/Module.h +++ b/Source/extensions/bluetooth/audio/Module.h @@ -26,9 +26,6 @@ #include #include -#include <../include/bluetooth/bluetooth.h> -#include <../include/bluetooth/l2cap.h> - #include "../Debug.h" #include "../UUID.h" diff --git a/Source/extensions/bluetooth/gatt/CMakeLists.txt b/Source/extensions/bluetooth/gatt/CMakeLists.txt index 89992f9cf..d14b5403a 100644 --- a/Source/extensions/bluetooth/gatt/CMakeLists.txt +++ b/Source/extensions/bluetooth/gatt/CMakeLists.txt @@ -25,8 +25,6 @@ project(${NAMESPACE}BluetoothGATT set(TARGET ${PROJECT_NAME}) message("Setup ${TARGET} v${PROJECT_VERSION}") -find_package(Bluez5UtilHeaders REQUIRED) - set(PUBLIC_HEADERS GATTSocket.h GATTProfile.h @@ -45,7 +43,6 @@ target_link_libraries(${TARGET} CompileSettingsDebug::CompileSettingsDebug ${NAMESPACE}Core::${NAMESPACE}Core ${NAMESPACE}Messaging::${NAMESPACE}Messaging - Bluez5UtilHeaders::Bluez5UtilHeaders ) set_target_properties(${TARGET} diff --git a/Source/extensions/bluetooth/gatt/Module.h b/Source/extensions/bluetooth/gatt/Module.h index a3168d40c..b7e4c669d 100644 --- a/Source/extensions/bluetooth/gatt/Module.h +++ b/Source/extensions/bluetooth/gatt/Module.h @@ -26,8 +26,6 @@ #include #include -#include <../include/bluetooth/bluetooth.h> - #include "../Debug.h" #include "../UUID.h" diff --git a/Source/extensions/processcontainers/implementations/LXCImplementation/LXCImplementation.cpp b/Source/extensions/processcontainers/implementations/LXCImplementation/LXCImplementation.cpp index 2e43d8311..c5d47fb3a 100644 --- a/Source/extensions/processcontainers/implementations/LXCImplementation/LXCImplementation.cpp +++ b/Source/extensions/processcontainers/implementations/LXCImplementation/LXCImplementation.cpp @@ -568,10 +568,7 @@ namespace ProcessContainers { Core::Directory logDir(dirname.c_str()); logDir.CreatePath(); - bool valid{}; - const string filename(Core::File::Normalize(dirname + logFileName, valid)); - - ASSERT(valid == true); + const string filename(dirname + logFileName); const std::string file = Core::ToString(filename); const std::string level = Core::ToString(loggingOptions); diff --git a/Source/plugins/Configuration.h b/Source/plugins/Configuration.h index 3bbf40d04..325f6ed6d 100644 --- a/Source/plugins/Configuration.h +++ b/Source/plugins/Configuration.h @@ -34,6 +34,106 @@ namespace Plugin { */ class EXTERNAL Config : public Core::JSON::Container { public: + class Environment : public Core::JSON::Container { + public: + Environment() + : Core::JSON::Container() + , Key() + , Value() + , Override(RPC::Object::Environment::Scope::LOCAL) + { + Add(_T("key"), &Key); + Add(_T("value"), &Value); + Add(_T("override"), &Override); + } + Environment(const Environment& copy) + : Core::JSON::Container() + , Key(copy.Key) + , Value(copy.Value) + , Override(copy.Override) + { + Add(_T("key"), &Key); + Add(_T("value"), &Value); + Add(_T("override"), &Override); + } + Environment(Environment&& move) noexcept + : Core::JSON::Container() + , Key(std::move(move.Key)) + , Value(std::move(move.Value)) + , Override(std::move(move.Override)) + { + Add(_T("key"), &Key); + Add(_T("value"), &Value); + Add(_T("override"), &Override); + } + ~Environment() override = default; + Environment& operator=(const Environment& RHS) + { + Key = RHS.Key; + Value = RHS.Value; + Override = RHS.Override; + + return (*this); + } + Environment& operator=(Environment&& move) noexcept + { + if (this != &move) { + Key = std::move(move.Key); + Value = std::move(move.Value); + Override = std::move(move.Override); + } + + return (*this); + } + static std::vector List(const Core::JSON::ArrayType& environments) + { + std::vector environmentList; + + if (environments.IsSet() == true) { + Core::JSON::ArrayType::ConstIterator index(environments.Elements()); + while (index.Next() == true) { + if ((index.Current().Key.IsSet() == true) && (index.Current().Value.IsSet() == true)) { + RPC::Object::Environment env; + env.key = index.Current().Key.Value(); + env.value = index.Current().Value.Value(); + env.overriding = index.Current().Override.Value(); + environmentList.push_back(env); + } else { + SYSLOG(Logging::Startup, (_T("Failure in Substituting Value of Key:Value:[%s]:[%s]\n"), index.Current().Key.Value().c_str(), index.Current().Value.Value().c_str())); + } + } + } + return environmentList; + } + static RPC::Object::Environment Info(const string& env, RPC::Object::Environment::Scope overriding) + { + RPC::Object::Environment info; + size_t start = env.find_first_of(RPC::Object::EnvironmentSeparator); + if ((start != string::npos) && (start < env.length())) { + string key = env.substr(0, start); + string value = env.substr(start + 1); + + if ((key.empty() != true) && (value.empty() != true) && (value.length() > 2) && + ((value.at(0) == '\"') && (value.at(value.length() - 1) == '\"'))) { + info.key = key; + info.value = value.substr(1, value.length() - 2); + info.overriding = overriding; + } else { + SYSLOG(Logging::Startup, (_T("Environment key:value fromat is invalid :[%s]:[%s]\n"), key.c_str(), value.c_str())); + } + } else { + SYSLOG(Logging::Startup, (_T("Invalid Enviroment value :[%s]\n"), env.c_str())); + } + return info; + } + + public: + Core::JSON::String Key; + Core::JSON::String Value; + Core::JSON::EnumType Override; + }; + using EnvironmentList = Core::JSON::ArrayType; + class EXTERNAL RootConfig : public Core::JSON::Container { private: class RootObject : public Core::JSON::Container { @@ -73,6 +173,7 @@ namespace Plugin { , Mode(ModeType::LOCAL) , RemoteAddress() , Configuration(false) + , Environments() { Add(_T("locator"), &Locator); Add(_T("user"), &User); @@ -83,6 +184,7 @@ namespace Plugin { Add(_T("mode"), &Mode); Add(_T("remoteaddress"), &RemoteAddress); Add(_T("configuration"), &Configuration); + Add(_T("environments"), &Environments); } RootConfig(const PluginHost::IShell* info) : Core::JSON::Container() @@ -95,6 +197,7 @@ namespace Plugin { , Mode(ModeType::LOCAL) , RemoteAddress() , Configuration(false) + , Environments() { Add(_T("locator"), &Locator); Add(_T("user"), &User); @@ -105,6 +208,7 @@ namespace Plugin { Add(_T("mode"), &Mode); Add(_T("remoteaddress"), &RemoteAddress); Add(_T("configuration"), &Configuration); + Add(_T("environments"), &Environments); RootObject config; Core::OptionalType error; @@ -139,6 +243,7 @@ namespace Plugin { , Mode(copy.Mode) , RemoteAddress(copy.RemoteAddress) , Configuration(copy.Configuration) + , Environments(copy.Environments) { Add(_T("locator"), &Locator); Add(_T("user"), &User); @@ -149,6 +254,7 @@ namespace Plugin { Add(_T("mode"), &Mode); Add(_T("remoteaddress"), &RemoteAddress); Add(_T("configuration"), &Configuration); + Add(_T("environments"), &Environments); } RootConfig(RootConfig&& move) noexcept : Core::JSON::Container() @@ -161,6 +267,7 @@ namespace Plugin { , Mode(std::move(move.Mode)) , RemoteAddress(std::move(move.RemoteAddress)) , Configuration(std::move(move.Configuration)) + , Environments(std::move(move.Environments)) { Add(_T("locator"), &Locator); Add(_T("user"), &User); @@ -171,6 +278,7 @@ namespace Plugin { Add(_T("mode"), &Mode); Add(_T("remoteaddress"), &RemoteAddress); Add(_T("configuration"), &Configuration); + Add(_T("environments"), &Environments); } ~RootConfig() override = default; @@ -186,6 +294,7 @@ namespace Plugin { Mode = RHS.Mode; RemoteAddress = RHS.RemoteAddress; Configuration = RHS.Configuration; + Environments = RHS.Environments; return (*this); } @@ -202,6 +311,7 @@ namespace Plugin { Mode = std::move(move.Mode); RemoteAddress = std::move(move.RemoteAddress); Configuration = std::move(move.Configuration); + Environments = std::move(move.Environments); } return (*this); @@ -233,6 +343,7 @@ namespace Plugin { Core::JSON::EnumType Mode; Core::JSON::String RemoteAddress; Core::JSON::String Configuration; + EnvironmentList Environments; }; public: diff --git a/Source/plugins/Service.cpp b/Source/plugins/Service.cpp index 2ddb8b1f3..0e5361162 100644 --- a/Source/plugins/Service.cpp +++ b/Source/plugins/Service.cpp @@ -76,7 +76,7 @@ namespace PluginHost { _notifierLock.Unlock(); } - void Service::FileToServe(const string& webServiceRequest, Web::Response& response, bool allowUnsafePath) + void Service::FileToServe(const string& webServiceRequest, Web::Response& response, const bool allowUnsafePath) { Web::MIMETypes result; Web::EncodingTypes encoding = Web::ENCODING_UNKNOWN; @@ -91,10 +91,9 @@ namespace PluginHost { response.Body(fileBody); } else { ASSERT(fileToService.length() >= _webServerFilePath.length()); - bool safePath = true; - string normalizedPath = Core::File::Normalize(fileToService.substr(_webServerFilePath.length()), safePath); + string normalizedPath = Core::File::Normalize(fileToService.substr(_webServerFilePath.length()), !allowUnsafePath); - if (allowUnsafePath || safePath ) { + if (normalizedPath.empty() == false) { Core::ProxyType fileBody(IFactories::Instance().FileBody()); *fileBody = fileToService; response.ContentType = result; diff --git a/Source/plugins/Shell.cpp b/Source/plugins/Shell.cpp index edcd0c8b5..e8d052665 100644 --- a/Source/plugins/Shell.cpp +++ b/Source/plugins/Shell.cpp @@ -42,12 +42,15 @@ namespace PluginHost result = Core::ServiceAdministrator::Instance().Instantiate(Core::Library(), className.c_str(), version, interface); } else { RPC::IStringIterator* all_paths = GetLibrarySearchPaths(locator); + ASSERT(all_paths != nullptr); + string element; - while (all_paths->Next(element) == true) { + while ((all_paths->Next(element) == true) && (result == nullptr)) { Core::File file(element.c_str()); if (file.Exists()) { Core::Library resource = Core::ServiceAdministrator::Instance().LoadLibrary(element.c_str()); + if (resource.IsLoaded()) result = Core::ServiceAdministrator::Instance().Instantiate( resource, @@ -78,7 +81,8 @@ namespace PluginHost rootConfig.HostType(), SystemRootPath(), rootConfig.RemoteAddress.Value(), - rootConfig.Configuration.Value()); + rootConfig.Configuration.Value(), + Plugin::Config::Environment::List(rootConfig.Environments)); result = handler->Instantiate(definition, waitTime, pid); } diff --git a/Tests/unit/core/test_filesystem.cpp b/Tests/unit/core/test_filesystem.cpp index ce68d8f0e..2634ec306 100644 --- a/Tests/unit/core/test_filesystem.cpp +++ b/Tests/unit/core/test_filesystem.cpp @@ -120,6 +120,139 @@ namespace Core { system("rm -rf home"); } + TEST (test_file, directory_normalize_path) + { + EXPECT_EQ(::Thunder::Core::Directory::Normalize(""), ""); + + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/"), "/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/."), "/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/././././"), "/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("////"), "/"); + + EXPECT_EQ(::Thunder::Core::Directory::Normalize("."), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("./"), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("././././././././"), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("./././././././."), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize(".////"), "./"); + + EXPECT_EQ(::Thunder::Core::Directory::Normalize(".."), "../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("../"), "../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("../../.."), "../../../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("../../../"), "../../../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("./../"), "../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("././../"), "../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("././../.."), "../../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("..///"), "../"); + + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/bar"), "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/"), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/bar/."), "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/.."), "foo/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/bar/./"), "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/../"), "foo/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/bar/."), "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/.////"), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/././././bar"), "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/quux/../../xyzzy"), "foo/xyzzy/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("../foo/bar/."), "../foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("../foo/bar/.."), "../foo/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/bar/.") , "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo////bar////"), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("///foo////bar////"), "/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("././././foo/bar"), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("./foo/bar"), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo////bar////././././"), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo////bar////././././."), "foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo////bar////././././."), "/foo/bar/"); + + // Cases where navigating upwards compacts completely + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/../.."), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("foo/bar/../.."), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("./foo/../bar/.."), "./"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("./foo/../bar/../.."), "../"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/../bar/.."), "/"); + + // Negative cases navigating past root + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/.."), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/../.."), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/./.."), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/../bar/../.."), ""); + +#ifdef __WINDOWS__ + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\\\bar\\.\\.\\quux\\..\\."), "C:/foo/bar/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\bar\\..\\.."), "C:/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\bar\\.."), "C:/foo"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\bar\\..\\"), "C:/foo"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\bar\\."), "C:/foo/bar"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\bar\\.\\"), "C:/foo/bar"); + + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\.\\foo\\bar\\..\\.."), "C:/"); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\foo\\bar\\..\\..\\.."), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\.."), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\\\"), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("C:\\..\\.."), ""); +#endif + } + + TEST (test_file, file_normalize_path) + { + EXPECT_EQ(::Thunder::Core::File::Normalize("./foo"), "foo"); + EXPECT_EQ(::Thunder::Core::File::Normalize("./../foo"), "../foo"); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo///bar"), "foo/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo///bar"), "/foo/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/../bar"), "bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/../bar"), "/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/.././././bar"), "/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/../../../.././././././bar"), "../../../bar"); + + // Negative test cases, all fail because they point to a directory + EXPECT_EQ(::Thunder::Core::File::Normalize("/"), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("."), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize(".."), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/././././././"), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/.."), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/."), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/.."), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/."), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/bar/"), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/bar///../.."), ""); + } + + TEST (test_file, file_safe_normalize_path) + { + EXPECT_EQ(::Thunder::Core::File::Normalize("./foo", true), "foo"); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo///bar", true), "foo/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo///bar", true), "/foo/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/../bar", true), "bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/../bar", true), "/bar"); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/.././././bar", true), "/bar"); + + // Negative test cases, all fail because they point to a directory + EXPECT_EQ(::Thunder::Core::File::Normalize("/", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize(".", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("..", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/././././././", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/..", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/.", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/..", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/.", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("/foo/bar/", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/bar///../..", true), ""); + + // Negative test cases, all fail because they point past current dir + EXPECT_EQ(::Thunder::Core::File::Normalize("./../foo", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("../foo", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("../../foo", true), ""); + EXPECT_EQ(::Thunder::Core::File::Normalize("foo/../../bar", true), ""); + + // Negative test cases, all fail because they point past root + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/../foo", true), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/../../foo", true), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/./../foo", true), ""); + EXPECT_EQ(::Thunder::Core::Directory::Normalize("/foo/../bar/../../quux", true), ""); + } + + } // Core } // Tests } // Thunder diff --git a/cmake/common/GetBluez5Headers.cmake b/cmake/common/GetBluez5Headers.cmake new file mode 100644 index 000000000..259f242dd --- /dev/null +++ b/cmake/common/GetBluez5Headers.cmake @@ -0,0 +1,80 @@ +option(DOWNLOAD_BLUEZ_UTIL_HEADERS "Download bluez5 headers" OFF) +set(DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION "5.78" CACHE STRING "version of the bluez5 headers to download...") +set(DOWNLOAD_BLUEZ_UTIL_HEADERS_REPO "https://github.com/bluez/bluez.git" CACHE STRING "Repo where to get the bluez5 headers...") + +set(BLUEZ_LOCAL_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/core/bluez5") + +include(CreateLink) + +if(DOWNLOAD_BLUEZ_UTIL_HEADERS) + message(STATUS "Downloaded bluez5 headers are used, assuming your \"the expert\"!") + + include(GetExternalCode) + + + GetExternalCode( + GIT_REPOSITORY "${DOWNLOAD_BLUEZ_UTIL_HEADERS_REPO}" + GIT_VERSION "${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}" + SOURCE_DIR "${CMAKE_BINARY_DIR}/bluez5-${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}" + ) + + CreateLink( + LINK "${BLUEZ_LOCAL_INCLUDE_DIR}" + TARGET "${CMAKE_BINARY_DIR}/bluez5-${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}/lib" + ) + +else() + set(BLUEZ_INCLUDE_DIR) + + # Find the bluez5 headers in a sysroot/staging location + find_path(_header_path bluetooth/bluetooth.h) + if(_header_path) + message(VERBOSE "Found bluetooth.h in ${_header_path}") + set(BLUEZ_INCLUDE_DIR "${_header_path}") + endif() + + CreateLink( + LINK "${BLUEZ_LOCAL_INCLUDE_DIR}" + TARGET "${BLUEZ_INCLUDE_DIR}/bluetooth" + ) +endif() + +function(GetBluez5UtilHeadersFiles var) + file(GLOB Bluez5UtilHeadersFiles "${BLUEZ_LOCAL_INCLUDE_DIR}/*.h") + set(${var} ${Bluez5UtilHeadersFiles} PARENT_SCOPE) +endfunction(GetBluez5UtilHeadersFiles) + +function(GetBluez5IncludeDirs var) + set(${var} "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/core" PARENT_SCOPE) +endfunction(GetBluez5IncludeDirs) + +# +# From Bluez >= v5.64 the mgmt_ltk_info struct is changed due to inclusive language changes. +# https://github.com/bluez/bluez/commit/b7d6a7d25628e9b521a29a5c133fcadcedeb2102 +# This a function so CMAKE_REQUIRED_FLAGS is only valid in this scope +# it sets the `var` variable in the calling scope accordingly. +# +function(CheckBluez5InclusiveLanguage var) + include(CheckStructHasMember) + + # is needed because of pedenic warnings in the bluez headers + set(CMAKE_REQUIRED_FLAGS "-Wno-error") + + check_struct_has_member("struct mgmt_ltk_info" master + "${BLUEZ_LOCAL_INCLUDE_DIR}/bluetooth.h;${BLUEZ_LOCAL_INCLUDE_DIR}/mgmt.h" + INCLUSIVE_LANGUAGE + LANGUAGE C) + + check_struct_has_member("struct mgmt_ltk_info" central + "${BLUEZ_LOCAL_INCLUDE_DIR}/bluetooth.h;${BLUEZ_LOCAL_INCLUDE_DIR}/mgmt.h" + NO_INCLUSIVE_LANGUAGE + LANGUAGE C) + + if(NOT INCLUSIVE_LANGUAGE AND NOT NO_INCLUSIVE_LANGUAGE) + message(FATAL_ERROR "Could not determine the usage of inclusive language, probably due to a compilation error. Please check the cmake error log for details.") + elseif(NO_INCLUSIVE_LANGUAGE) + set(${var} FALSE PARENT_SCOPE) + elseif(INCLUSIVE_LANGUAGE) + set(${var} TRUE PARENT_SCOPE) + endif() +endfunction(CheckBluez5InclusiveLanguage) diff --git a/cmake/modules/FindBluez5UtilHeaders.cmake b/cmake/modules/FindBluez5UtilHeaders.cmake deleted file mode 100644 index 00cd3bbb3..000000000 --- a/cmake/modules/FindBluez5UtilHeaders.cmake +++ /dev/null @@ -1,126 +0,0 @@ -# - Try to find Bluez Utils Headers -# Once done this will define -# Bluez5UtilHeaders::Bluez5UtilHeaders - The bluez include directories -# -# Copyright (C) 2022 Metrological. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS -# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - -option(DOWNLOAD_BLUEZ_UTIL_HEADERS "Download bluez5 headers, only for testing or development..." OFF) -set(DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION "5.78" CACHE STRING "version of the bluez5 headers to download...") -set(DOWNLOAD_BLUEZ_UTIL_HEADERS_REPO "https://github.com/bluez/bluez.git" CACHE STRING "Repo where to get the bluez5 headers...") - -if(Bluez5UtilHeaders_FIND_QUIETLY) - set(_FIND_MODE QUIET) -elseif(Bluez5UtilHeaders_FIND_REQUIRED) - set(_FIND_MODE REQUIRED) -endif() - -set(NEEDED_BLUEZ_HEADERS - bluetooth.h - hci.h - mgmt.h - l2cap.h -) - -if(NOT TARGET Bluez5UtilHeaders) - set(BLUEZ_INCLUDE_DIRS) - - if(DOWNLOAD_BLUEZ_UTIL_HEADERS AND NOT TARGET DownloadedBluez5Headers) - message(STATUS "Downloaded bluez5 headers are used, assuming your \"the expert\"!") - - include(GetExternalCode) - include(CreateLink) - - GetExternalCode( - GIT_REPOSITORY "${DOWNLOAD_BLUEZ_UTIL_HEADERS_REPO}" - GIT_VERSION "${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}" - SOURCE_DIR "${CMAKE_BINARY_DIR}/bluez-${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}" - ) - - add_library(DownloadedBluez5Headers INTERFACE) - - #FIX ME: Hack for weird include paths in the source... - CreateLink( - LINK "${CMAKE_BINARY_DIR}/bluez/include/bluetooth" - TARGET "${CMAKE_BINARY_DIR}/bluez-${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}/lib" - ) - - set(BLUEZ_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/bluez/include") - else() - foreach(_header ${NEEDED_BLUEZ_HEADERS}) - find_path(_header_path bluetooth/${_header}) - if(_header_path) - message(VERBOSE "Found ${_header} in ${_header_path}") - list(APPEND BLUEZ_INCLUDE_DIRS ${_header_path}) - endif() - endforeach() - - list(REMOVE_DUPLICATES BLUEZ_INCLUDE_DIRS) - endif() - - add_library(Bluez5UtilHeaders INTERFACE) - add_library(Bluez5UtilHeaders::Bluez5UtilHeaders ALIAS Bluez5UtilHeaders) - - # - # From Bluez >= v5.64 the mgmt_ltk_info struct is changed due to inclusive language changes. - # https://github.com/bluez/bluez/commit/b7d6a7d25628e9b521a29a5c133fcadcedeb2102 - # - include(CheckStructHasMember) - check_struct_has_member("struct mgmt_ltk_info" central - "${BLUEZ_INCLUDE_DIRS}/bluetooth/bluetooth.h;${BLUEZ_INCLUDE_DIRS}/bluetooth/mgmt.h" - NO_INCLUSIVE_LANGUAGE - LANGUAGE C) - - if(${NO_INCLUSIVE_LANGUAGE}) - message(VERBOSE "Your bluez version does not use inclusive language anymore") - target_compile_definitions(Bluez5UtilHeaders INTERFACE NO_INCLUSIVE_LANGUAGE) - endif() - - if(DOWNLOAD_BLUEZ_UTIL_HEADERS) - target_include_directories(Bluez5UtilHeaders - INTERFACE - $ - $ - ) - - install(TARGETS Bluez5UtilHeaders EXPORT Bluez5UtilHeadersTargets) - - file(GLOB Bluez5UtilHeadersFiles "${CMAKE_BINARY_DIR}/bluez-${DOWNLOAD_BLUEZ_UTIL_HEADERS_VERSION}/lib/*.h") - - install(FILES ${Bluez5UtilHeadersFiles} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${NAMESPACE}/Bluez5UtilHeaders/include/bluetooth COMPONENT ${NAMESPACE}_Development) - - include(HeaderOnlyInstall) - HeaderOnlyInstallCMakeConfig(TARGET Bluez5UtilHeaders TREAT_AS_NORMAL) - else() - target_include_directories(Bluez5UtilHeaders - INTERFACE - ${BLUEZ_INCLUDE_DIRS}) - endif() - - message(TRACE "BLUEZ_INCLUDE_DIRS ${BLUEZ_INCLUDE_DIRS}") - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(Bluez5UtilHeaders DEFAULT_MSG BLUEZ_INCLUDE_DIRS) - mark_as_advanced(BLUEZ_INCLUDE_DIRS) -endif() \ No newline at end of file