diff --git a/Makefile.am b/Makefile.am index ac6bea37f..bf5f101b0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,7 @@ ## Created by Anjuta SUBDIRS = ltdl \ + mmatch \ base \ cJSON \ jsonrpc \ diff --git a/base/base.vcxproj b/base/base.vcxproj index 50b13abfa..19037d4f6 100644 --- a/base/base.vcxproj +++ b/base/base.vcxproj @@ -93,7 +93,12 @@ - + + $(SolutionDir)\mmatch;$(IncludePath) + + + $(SolutionDir)\mmatch;$(IncludePath) + diff --git a/base/configcollection.cpp b/base/configcollection.cpp index a4c0d640d..585e0b47f 100644 --- a/base/configcollection.cpp +++ b/base/configcollection.cpp @@ -38,14 +38,7 @@ void ConfigCollection::AddObject(const ConfigObject::Ptr& object) RemoveObject(object); Objects[object->GetName()] = object; - - EventArgs ea; - ea.Source = object; - OnObjectCreated(ea); - - ConfigHive::Ptr hive = m_Hive.lock(); - if (hive) - hive->OnObjectCreated(ea); + object->Commit(); } /** diff --git a/base/configcollection.h b/base/configcollection.h index 6dc1a66ba..989672de9 100644 --- a/base/configcollection.h +++ b/base/configcollection.h @@ -28,9 +28,8 @@ public: void ForEachObject(function callback); - Event OnObjectCreated; + Event OnObjectCommitted; Event OnObjectRemoved; - Event OnPropertyChanged; }; } diff --git a/base/confighive.h b/base/confighive.h index 52701ebfe..b0c89ddef 100644 --- a/base/confighive.h +++ b/base/confighive.h @@ -23,9 +23,8 @@ public: void ForEachObject(const string& type, function callback); - Event OnObjectCreated; + Event OnObjectCommitted; Event OnObjectRemoved; - Event OnPropertyChanged; }; } diff --git a/base/configobject.cpp b/base/configobject.cpp index c0dfbe96e..e34e32520 100644 --- a/base/configobject.cpp +++ b/base/configobject.cpp @@ -30,7 +30,6 @@ void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive) throw InvalidArgumentException("Config object already has a parent hive."); m_Hive = hive; - OnPropertyChanged += bind_weak(&ConfigObject::PropertyChangedHandler, shared_from_this()); } /** @@ -118,21 +117,19 @@ bool ConfigObject::GetReplicated(void) const } /** - * PropertyChangedHandler + * Commit * * Handles changed properties by propagating them to the hive * and collection this object is contained in. * - * @param dpcea The event arguments. - * @returns 0. */ -int ConfigObject::PropertyChangedHandler(const PropertyChangedEventArgs& dpcea) +void ConfigObject::Commit(void) { ConfigHive::Ptr hive = m_Hive.lock(); if (hive) { - hive->GetCollection(m_Type)->OnPropertyChanged(dpcea); - hive->OnPropertyChanged(dpcea); + EventArgs ea; + ea.Source = shared_from_this(); + hive->GetCollection(m_Type)->OnObjectCommitted(ea); + hive->OnObjectCommitted(ea); } - - return 0; } diff --git a/base/configobject.h b/base/configobject.h index 1caee2eb3..b8aae2a10 100644 --- a/base/configobject.h +++ b/base/configobject.h @@ -17,8 +17,6 @@ private: string m_Type; bool m_Replicated; - int PropertyChangedHandler(const PropertyChangedEventArgs& dpcea); - public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; @@ -36,6 +34,8 @@ public: void SetReplicated(bool replicated); bool GetReplicated(void) const; + + void Commit(void); }; } diff --git a/base/utility.cpp b/base/utility.cpp index 4136f81f0..a2a8111f7 100644 --- a/base/utility.cpp +++ b/base/utility.cpp @@ -1,4 +1,5 @@ #include "i2-base.h" +#include using namespace icinga; @@ -137,3 +138,8 @@ shared_ptr Utility::GetX509Certificate(string pemfile) return shared_ptr(cert, X509_free); } + +bool Utility::Match(string pattern, string text) +{ + return (match(pattern.c_str(), text.c_str()) != 0); +} diff --git a/base/utility.h b/base/utility.h index ef95d885f..715722b5a 100644 --- a/base/utility.h +++ b/base/utility.h @@ -47,6 +47,8 @@ public: static shared_ptr MakeSSLContext(string pubkey, string privkey, string cakey); static string GetCertificateCN(const shared_ptr& certificate); static shared_ptr GetX509Certificate(string pemfile); + + static bool Match(string pattern, string text); }; } diff --git a/components/configfile/configfilecomponent.cpp b/components/configfile/configfilecomponent.cpp index 4406e6e8c..c95004824 100644 --- a/components/configfile/configfilecomponent.cpp +++ b/components/configfile/configfilecomponent.cpp @@ -55,13 +55,23 @@ void ConfigFileComponent::Start(void) for (cJSON *property = object->child; property != NULL; property = property->next) { string key = property->string; + + if (property->type == cJSON_String) { + string value = property->valuestring; - if (property->type != cJSON_String) - continue; + cfgobj->SetPropertyString(key, value); + } else if (property->type == cJSON_Array) { + Dictionary::Ptr items = make_shared(); - string value = property->valuestring; + for (cJSON *item = property->child; item != NULL; item = item->next) { + if (item->type != cJSON_String) + continue; - cfgobj->SetPropertyString(key, value); + items->AddUnnamedPropertyString(item->valuestring); + } + + cfgobj->SetPropertyDictionary(key, items); + } } GetApplication()->GetConfigHive()->AddObject(cfgobj); diff --git a/components/configrpc/configrpccomponent.cpp b/components/configrpc/configrpccomponent.cpp index 20a3fccfe..1d67c6300 100644 --- a/components/configrpc/configrpccomponent.cpp +++ b/components/configrpc/configrpccomponent.cpp @@ -19,24 +19,20 @@ void ConfigRpcComponent::Start(void) m_ConfigRpcEndpoint->RegisterMethodHandler("config::FetchObjects", bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this())); - configHive->OnObjectCreated += bind_weak(&ConfigRpcComponent::LocalObjectCreatedHandler, shared_from_this()); + configHive->OnObjectCommitted += bind_weak(&ConfigRpcComponent::LocalObjectCommittedHandler, shared_from_this()); configHive->OnObjectRemoved += bind_weak(&ConfigRpcComponent::LocalObjectRemovedHandler, shared_from_this()); - configHive->OnPropertyChanged += bind_weak(&ConfigRpcComponent::LocalPropertyChangedHandler, shared_from_this()); - m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectCreated"); + m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectCommitted"); m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectRemoved"); - m_ConfigRpcEndpoint->RegisterMethodSource("config::PropertyChanged"); } endpointManager->OnNewEndpoint += bind_weak(&ConfigRpcComponent::NewEndpointHandler, shared_from_this()); m_ConfigRpcEndpoint->RegisterMethodSource("config::FetchObjects"); - m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCreated", - bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this())); + m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCommitted", + bind_weak(&ConfigRpcComponent::RemoteObjectCommittedHandler, shared_from_this())); m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectRemoved", bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this())); - m_ConfigRpcEndpoint->RegisterMethodHandler("config::PropertyChanged", - bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this())); endpointManager->RegisterEndpoint(m_ConfigRpcEndpoint); } @@ -115,7 +111,7 @@ int ConfigRpcComponent::FetchObjectsHandler(const NewRequestEventArgs& ea) return 0; } -int ConfigRpcComponent::LocalObjectCreatedHandler(const EventArgs& ea) +int ConfigRpcComponent::LocalObjectCommittedHandler(const EventArgs& ea) { ConfigObject::Ptr object = static_pointer_cast(ea.Source); @@ -141,32 +137,7 @@ int ConfigRpcComponent::LocalObjectRemovedHandler(const EventArgs& ea) return 0; } -int ConfigRpcComponent::LocalPropertyChangedHandler(const PropertyChangedEventArgs& ea) -{ - ConfigObject::Ptr object = static_pointer_cast(ea.Source); - - if (!ShouldReplicateObject(object)) - return 0; - - JsonRpcRequest msg = MakeObjectMessage(object, "config::PropertyChanged", false); - Message params; - msg.SetParams(params); - - Message properties; - params.GetDictionary()->SetPropertyDictionary("properties", properties.GetDictionary()); - - string value; - if (!object->GetPropertyString(ea.Property, &value)) - return 0; - - properties.GetDictionary()->SetPropertyString(ea.Property, value); - - GetEndpointManager()->SendMulticastRequest(m_ConfigRpcEndpoint, msg); - - return 0; -} - -int ConfigRpcComponent::RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea) +int ConfigRpcComponent::RemoteObjectCommittedHandler(const NewRequestEventArgs& ea) { JsonRpcRequest message = ea.Request; bool was_null = false; diff --git a/components/configrpc/configrpccomponent.h b/components/configrpc/configrpccomponent.h index 27ce4bb3b..cdc4d8d96 100644 --- a/components/configrpc/configrpccomponent.h +++ b/components/configrpc/configrpccomponent.h @@ -12,12 +12,11 @@ private: int NewEndpointHandler(const NewEndpointEventArgs& ea); int SessionEstablishedHandler(const EventArgs& ea); - int LocalObjectCreatedHandler(const EventArgs& ea); + int LocalObjectCommittedHandler(const EventArgs& ea); int LocalObjectRemovedHandler(const EventArgs& ea); - int LocalPropertyChangedHandler(const PropertyChangedEventArgs& ea); int FetchObjectsHandler(const NewRequestEventArgs& ea); - int RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea); + int RemoteObjectCommittedHandler(const NewRequestEventArgs& ea); int RemoteObjectRemovedHandler(const NewRequestEventArgs& ea); static JsonRpcRequest MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties); diff --git a/components/discovery/discoverycomponent.cpp b/components/discovery/discoverycomponent.cpp index 4717f47bb..7dcb34053 100644 --- a/components/discovery/discoverycomponent.cpp +++ b/components/discovery/discoverycomponent.cpp @@ -27,15 +27,16 @@ void DiscoveryComponent::Start(void) GetConfig()->GetPropertyInteger("broker", &isBroker); m_Broker = (isBroker != 0); - if (IsBroker()) { - m_DiscoveryEndpoint->RegisterMethodSource("discovery::NewComponent"); - m_DiscoveryEndpoint->RegisterMethodHandler("discovery::RegisterComponent", - bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this())); - } - m_DiscoveryEndpoint->RegisterMethodSource("discovery::RegisterComponent"); + m_DiscoveryEndpoint->RegisterMethodHandler("discovery::RegisterComponent", + bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this())); + + if (IsBroker()) + m_DiscoveryEndpoint->RegisterMethodSource("discovery::NewComponent"); + m_DiscoveryEndpoint->RegisterMethodHandler("discovery::NewComponent", bind_weak(&DiscoveryComponent::NewComponentMessageHandler, shared_from_this())); + m_DiscoveryEndpoint->RegisterMethodHandler("discovery::Welcome", bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this())); @@ -49,6 +50,9 @@ void DiscoveryComponent::Start(void) m_DiscoveryTimer->SetInterval(30); m_DiscoveryTimer->OnTimerExpired += bind_weak(&DiscoveryComponent::DiscoveryTimerHandler, shared_from_this()); m_DiscoveryTimer->Start(); + + /* call the timer as soon as possible */ + m_DiscoveryTimer->Reschedule(0); } /** @@ -104,10 +108,8 @@ int DiscoveryComponent::NewEndpointHandler(const NewEndpointEventArgs& neea) { neea.Endpoint->OnIdentityChanged += bind_weak(&DiscoveryComponent::NewIdentityHandler, shared_from_this()); - if (IsBroker()) { - /* accept discovery::RegisterComponent messages from any endpoint */ - neea.Endpoint->RegisterMethodSource("discovery::RegisterComponent"); - } + /* accept discovery::RegisterComponent messages from any endpoint */ + neea.Endpoint->RegisterMethodSource("discovery::RegisterComponent"); /* accept discovery::Welcome messages from any endpoint */ neea.Endpoint->RegisterMethodSource("discovery::Welcome"); @@ -231,12 +233,6 @@ int DiscoveryComponent::NewIdentityHandler(const EventArgs& ea) GetEndpointManager()->ForEachEndpoint(bind(&DiscoveryComponent::CheckExistingEndpoint, this, endpoint, _1)); - ConfigCollection::Ptr brokerCollection = GetApplication()->GetConfigHive()->GetCollection("broker"); - if (brokerCollection->GetObject(identity)) { - /* accept discovery::NewComponent messages from brokers */ - endpoint->RegisterMethodSource("discovery::NewComponent"); - } - // we assume the other component _always_ wants // discovery::RegisterComponent messages from us endpoint->RegisterMethodSink("discovery::RegisterComponent"); @@ -394,6 +390,30 @@ void DiscoveryComponent::SendDiscoveryMessage(string method, string identity, En GetEndpointManager()->SendMulticastRequest(m_DiscoveryEndpoint, request); } +bool DiscoveryComponent::HasMessagePermission(Dictionary::Ptr roles, string messageType, string message) +{ + ConfigHive::Ptr configHive = GetApplication()->GetConfigHive(); + ConfigCollection::Ptr roleCollection = configHive->GetCollection("role"); + + for (DictionaryIterator ip = roles->Begin(); ip != roles->End(); ip++) { + ConfigObject::Ptr role = roleCollection->GetObject(ip->second); + + if (!role) + continue; + + Dictionary::Ptr permissions; + if (!role->GetPropertyDictionary(messageType, &permissions)) + continue; + + for (DictionaryIterator is = permissions->Begin(); is != permissions->End(); is++) { + if (Utility::Match(is->second.GetString(), message)) + return true; + } + } + + return false; +} + /** * ProcessDiscoveryMessage * @@ -402,8 +422,9 @@ void DiscoveryComponent::SendDiscoveryMessage(string method, string identity, En * * @param identity The authorative identity of the component. * @param message The discovery message. + * @param trusted Whether the message comes from a trusted source (i.e. a broker). */ -void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessage message) +void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessage message, bool trusted) { /* ignore discovery messages that are about ourselves */ if (identity == GetEndpointManager()->GetIdentity()) @@ -416,14 +437,20 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa message.GetNode(&info->Node); message.GetService(&info->Service); + ConfigHive::Ptr configHive = GetApplication()->GetConfigHive(); + ConfigCollection::Ptr endpointCollection = configHive->GetCollection("endpoint"); + + ConfigObject::Ptr endpointConfig = endpointCollection->GetObject(identity); + Dictionary::Ptr roles; + if (endpointConfig) + endpointConfig->GetPropertyDictionary("roles", &roles); + Message provides; if (message.GetProvides(&provides)) { DictionaryIterator i; for (i = provides.GetDictionary()->Begin(); i != provides.GetDictionary()->End(); i++) { - if (IsBroker()) { - /* TODO: Add authorisation checks here */ - } - info->PublishedMethods.insert(i->second); + if (trusted || HasMessagePermission(roles, "publish", i->second)) + info->PublishedMethods.insert(i->second); } } @@ -431,16 +458,14 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa if (message.GetSubscribes(&subscribes)) { DictionaryIterator i; for (i = subscribes.GetDictionary()->Begin(); i != subscribes.GetDictionary()->End(); i++) { - if (IsBroker()) { - /* TODO: Add authorisation checks here */ - } - info->SubscribedMethods.insert(i->second); + if (trusted || HasMessagePermission(roles, "subscribe", i->second)) + info->SubscribedMethods.insert(i->second); } } map::iterator i; - i = m_Components.find(identity); + i = m_Components.find(identity); if (i != m_Components.end()) m_Components.erase(i); @@ -472,7 +497,7 @@ int DiscoveryComponent::NewComponentMessageHandler(const NewRequestEventArgs& nr if (!message.GetIdentity(&identity)) return 0; - ProcessDiscoveryMessage(identity, message); + ProcessDiscoveryMessage(identity, message, true); return 0; } @@ -486,45 +511,36 @@ int DiscoveryComponent::NewComponentMessageHandler(const NewRequestEventArgs& nr */ int DiscoveryComponent::RegisterComponentMessageHandler(const NewRequestEventArgs& nrea) { - /* ignore discovery::RegisterComponent messages when we're not a broker */ - if (!IsBroker()) - return 0; - DiscoveryMessage message; nrea.Request.GetParams(&message); - ProcessDiscoveryMessage(nrea.Sender->GetIdentity(), message); + ProcessDiscoveryMessage(nrea.Sender->GetIdentity(), message, false); return 0; } /** - * BrokerConfigHandler + * EndpointConfigHandler * - * Processes "broker" config objects. + * Processes "endpoint" config objects. * * @param ea Event arguments for the new config object. * @returns 0 */ -int DiscoveryComponent::BrokerConfigHandler(const EventArgs& ea) +int DiscoveryComponent::EndpointConfigHandler(const EventArgs& ea) { ConfigObject::Ptr object = static_pointer_cast(ea.Source); EndpointManager::Ptr endpointManager = GetEndpointManager(); - /* Check if we're already connected to this broker. */ + /* Check if we're already connected to this endpoint. */ if (endpointManager->GetEndpointByIdentity(object->GetName())) return 0; - string node; - if (!object->GetPropertyString("node", &node)) - throw InvalidArgumentException("'node' property required for 'broker' config object."); - - string service; - if (!object->GetPropertyString("service", &service)) - throw InvalidArgumentException("'service' property required for 'broker' config object."); - - /* reconnect to this broker */ - endpointManager->AddConnection(node, service); + string node, service; + if (object->GetPropertyString("node", &node) && object->GetPropertyString("service", &service)) { + /* reconnect to this endpoint */ + endpointManager->AddConnection(node, service); + } return 0; } @@ -545,9 +561,9 @@ int DiscoveryComponent::DiscoveryTimerHandler(const TimerEventArgs& tea) time_t now; time(&now); - /* check whether we have to reconnect to one of our upstream brokers */ - ConfigCollection::Ptr brokerCollection = GetApplication()->GetConfigHive()->GetCollection("broker"); - brokerCollection->ForEachObject(bind(&DiscoveryComponent::BrokerConfigHandler, this, _1)); + /* check whether we have to reconnect to one of our upstream endpoints */ + ConfigCollection::Ptr endpointCollection = GetApplication()->GetConfigHive()->GetCollection("endpoint"); + endpointCollection->ForEachObject(bind(&DiscoveryComponent::EndpointConfigHandler, this, _1)); map::iterator i; for (i = m_Components.begin(); i != m_Components.end(); ) { diff --git a/components/discovery/discoverycomponent.h b/components/discovery/discoverycomponent.h index a00b90bff..77535ebad 100644 --- a/components/discovery/discoverycomponent.h +++ b/components/discovery/discoverycomponent.h @@ -36,7 +36,7 @@ private: int WelcomeMessageHandler(const NewRequestEventArgs& nrea); void SendDiscoveryMessage(string method, string identity, Endpoint::Ptr recipient); - void ProcessDiscoveryMessage(string identity, DiscoveryMessage message); + void ProcessDiscoveryMessage(string identity, DiscoveryMessage message, bool trusted); bool GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const; @@ -51,7 +51,9 @@ private: void FinishDiscoverySetup(Endpoint::Ptr endpoint); - int BrokerConfigHandler(const EventArgs& ea); + int EndpointConfigHandler(const EventArgs& ea); + + bool HasMessagePermission(Dictionary::Ptr roles, string messageType, string message); static const int RegistrationTTL = 300; diff --git a/configure.ac b/configure.ac index 2f3c619d8..c5b681897 100644 --- a/configure.ac +++ b/configure.ac @@ -56,5 +56,5 @@ components/discovery/Makefile icinga/Makefile icinga-app/Makefile jsonrpc/Makefile - +mmatch/Makefile ]) diff --git a/icinga-app/icinga1.conf b/icinga-app/icinga1.conf index 17d963f91..601ab601f 100644 --- a/icinga-app/icinga1.conf +++ b/icinga-app/icinga1.conf @@ -5,7 +5,7 @@ "privkey": "icinga-c1.key", "pubkey": "icinga-c1.crt", "cakey": "ca.crt", - "node": "10.0.10.3", + "node": "10.0.10.14", "service": "7777" } }, @@ -16,5 +16,8 @@ }, "host": { "localhost": { "node": "127.0.0.1" } + }, + "include": { + "permissions.conf": { "test": [ "hello", "world" ] } } } \ No newline at end of file diff --git a/icinga-app/icinga2.conf b/icinga-app/icinga2.conf index 46d84d8e0..c457b86da 100644 --- a/icinga-app/icinga2.conf +++ b/icinga-app/icinga2.conf @@ -14,7 +14,21 @@ "demo": { "replicate": "0" }, "discovery": { "replicate": "0", "broker": "0" } }, - "broker": { - "icinga-c1": { "replicate": "0", "node": "10.0.10.3", "service": "7777" } + "endpoint": { + "icinga-c1": { + "replicate": "0", + "node": "10.0.10.14", + "service": "7777", + "roles": [ "broker", "demo" ] + } + }, + "role": { + "broker": { + "publish": [ "discovery::NewComponent" ] + }, + "demo": { + "publish": [ "demo::*" ], + "subscribe": [ "demo::*" ] + } } } \ No newline at end of file diff --git a/icinga-app/icinga3.conf b/icinga-app/icinga3.conf index ed9894d89..c6af61273 100644 --- a/icinga-app/icinga3.conf +++ b/icinga-app/icinga3.conf @@ -14,7 +14,21 @@ "demo": { "replicate": "0" }, "discovery": { "replicate": "0", "broker": "0" } }, - "broker": { - "icinga-c1": { "replicate": "0", "node": "10.0.10.3", "service": "7777" } + "endpoint": { + "icinga-c1": { + "replicate": "0", + "node": "10.0.10.14", + "service": "7777", + "roles": [ "broker", "demo" ] + } + }, + "role": { + "broker": { + "publish": [ "discovery::NewComponent" ] + }, + "demo": { + "publish": [ "demo::*" ], + "subscribe": [ "demo::*" ] + } } } \ No newline at end of file diff --git a/icinga.sln b/icinga.sln index e5f25da2f..21ee272ee 100644 --- a/icinga.sln +++ b/icinga.sln @@ -2,6 +2,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "base\base.vcxproj", "{9C92DA90-FD53-43A9-A244-90F2E8AF9677}" + ProjectSection(ProjectDependencies) = postProject + {19CBCE06-3F5C-479A-BD75-E2AB6215D345} = {19CBCE06-3F5C-479A-BD75-E2AB6215D345} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsonrpc", "jsonrpc\jsonrpc.vcxproj", "{8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}" ProjectSection(ProjectDependencies) = postProject @@ -46,6 +49,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "discovery", "components\dis {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mmatch", "mmatch\mmatch.vcxproj", "{19CBCE06-3F5C-479A-BD75-E2AB6215D345}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -88,6 +93,10 @@ Global {EAD41628-BB96-4F99-9070-8A9676801295}.Debug|Win32.Build.0 = Debug|Win32 {EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.ActiveCfg = Release|Win32 {EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.Build.0 = Release|Win32 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.ActiveCfg = Debug|Win32 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.Build.0 = Debug|Win32 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.ActiveCfg = Release|Win32 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 8fd2f318d..1419039c6 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -30,14 +30,14 @@ int IcingaApplication::Main(const vector& args) /* register handler for 'icinga' config objects */ ConfigCollection::Ptr icingaCollection = GetConfigHive()->GetCollection("icinga"); function NewIcingaConfigHandler = bind_weak(&IcingaApplication::NewIcingaConfigHandler, shared_from_this()); - icingaCollection->OnObjectCreated += NewIcingaConfigHandler; + icingaCollection->OnObjectCommitted += NewIcingaConfigHandler; icingaCollection->ForEachObject(NewIcingaConfigHandler); icingaCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedIcingaConfigHandler, shared_from_this()); /* register handler for 'component' config objects */ ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component"); function NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this()); - componentCollection->OnObjectCreated += NewComponentHandler; + componentCollection->OnObjectCommitted += NewComponentHandler; componentCollection->ForEachObject(NewComponentHandler); componentCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this()); diff --git a/mmatch/Makefile.am b/mmatch/Makefile.am new file mode 100644 index 000000000..453ad3640 --- /dev/null +++ b/mmatch/Makefile.am @@ -0,0 +1,9 @@ +## Process this file with automake to produce Makefile.in + + +noinst_LTLIBRARIES = \ + libmmatch.la + +libmmatch_la_SOURCES = \ + mmatch.c \ + mmatch.h diff --git a/mmatch/mmatch.c b/mmatch/mmatch.c new file mode 100644 index 000000000..10b8ce300 --- /dev/null +++ b/mmatch/mmatch.c @@ -0,0 +1,305 @@ +/* + * IRC - Internet Relay Chat, common/match.c + * Copyright (C) 1990 Jarkko Oikarinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: Match.cpp,v 1.2 2005/08/15 10:08:50 shroud23 Exp $ + */ + +#include +#include "mmatch.h" + +#define ToLower tolower + +/* + * mmatch() + * + * Written by Run (carlo@runaway.xs4all.nl), 25-10-96 + * + * + * From: Carlo Wood + * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl> + * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem) + * To: coder-com@mail.undernet.org (coder committee) + * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST) + * + * We need a new function `mmatch(const char *old_mask, const char *new_mask)' + * which returns `true' likewise the current `match' (start with copying it), + * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !) + * as follows: a '*' in `new_mask' does not match a '?' in `old_mask' and + * a '?' in `new_mask' does not match a '\?' in `old_mask'. + * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'... + * And last but not least, '\?' and '\*' in `new_mask' now become one character. + */ + +int mmatch(const char *old_mask, const char *new_mask) +{ + const char *m = old_mask; + const char *n = new_mask; + const char *ma = m; + const char *na = n; + int wild = 0; + int mq = 0, nq = 0; + + while (1) + { + if (*m == '*') + { + while (*m == '*') + m++; + wild = 1; + ma = m; + na = n; + } + + if (!*m) + { + if (!*n) + return 0; + for (m--; (m > old_mask) && (*m == '?'); m--) + ; + if ((*m == '*') && (m > old_mask) && (m[-1] != '\\')) + return 0; + if (!wild) + return 1; + m = ma; + + /* Added to `mmatch' : Because '\?' and '\*' now is one character: */ + if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?'))) + ++na; + + n = ++na; + } + else if (!*n) + { + while (*m == '*') + m++; + return (*m != 0); + } + if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?'))) + { + m++; + mq = 1; + } + else + mq = 0; + + /* Added to `mmatch' : Because '\?' and '\*' now is one character: */ + if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?'))) + { + n++; + nq = 1; + } + else + nq = 0; + +/* + * This `if' has been changed compared to match() to do the following: + * Match when: + * old (m) new (n) boolean expression + * * any (*m == '*' && !mq) || + * ? any except '*' (*m == '?' && !mq && (*n != '*' || nq)) || + * any except * or ? same as m (!((*m == '*' || *m == '?') && !mq) && + * ToLower(*m) == ToLower(*n) && + * !((mq && !nq) || (!mq && nq))) + * + * Here `any' also includes \* and \? ! + * + * After reworking the boolean expressions, we get: + * (Optimized to use boolean shortcircuits, with most frequently occuring + * cases upfront (which took 2 hours!)). + */ + if ((*m == '*' && !mq) || + ((!mq || nq) && ToLower(*m) == ToLower(*n)) || + (*m == '?' && !mq && (*n != '*' || nq))) + { + if (*m) + m++; + if (*n) + n++; + } + else + { + if (!wild) + return 1; + m = ma; + + /* Added to `mmatch' : Because '\?' and '\*' now is one character: */ + if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?'))) + ++na; + + n = ++na; + } + } +} + +/* + * Compare if a given string (name) matches the given + * mask (which can contain wild cards: '*' - match any + * number of chars, '?' - match any single character. + * + * return 0, if match + * 1, if no match + */ + +/* + * match + * + * Rewritten by Andrea Cocito (Nemesi), November 1998. + * + */ + +/****************** Nemesi's match() ***************/ + +int match(const char *mask, const char *string) +{ + const char *m = mask, *s = string; + char ch; + const char *bm, *bs; /* Will be reg anyway on a decent CPU/compiler */ + + /* Process the "head" of the mask, if any */ + while ((ch = *m++) && (ch != '*')) + switch (ch) + { + case '\\': + if (*m == '?' || *m == '*') + ch = *m++; + default: + if (ToLower(*s) != ToLower(ch)) + return 1; + case '?': + if (!*s++) + return 1; + }; + if (!ch) + return *s; + + /* We got a star: quickly find if/where we match the next char */ +got_star: + bm = m; /* Next try rollback here */ + while ((ch = *m++)) + switch (ch) + { + case '?': + if (!*s++) + return 1; + case '*': + bm = m; + continue; /* while */ + case '\\': + if (*m == '?' || *m == '*') + ch = *m++; + default: + goto break_while; /* C is structured ? */ + }; +break_while: + if (!ch) + return 0; /* mask ends with '*', we got it */ + ch = ToLower(ch); + if (!*s) /* String is already empty, don't continue */ + return 1; /* This fixes the #quakenet access denied bug */ + while (ToLower(*s++) != ch) + if (!*s) + return 1; + bs = s; /* Next try start from here */ + + /* Check the rest of the "chunk" */ + while ((ch = *m++)) + { + switch (ch) + { + case '*': + goto got_star; + case '\\': + if (*m == '?' || *m == '*') + ch = *m++; + default: + if (ToLower(*s) != ToLower(ch)) + { + /* If we've run out of string, give up */ + if (!*bs) + return 1; + m = bm; + s = bs; + goto got_star; + }; + case '?': + if (!*s++) + return 1; + }; + }; + if (*s) + { + m = bm; + s = bs; + goto got_star; + }; + return 0; +} + +/* + * collapse() + * Collapse a pattern string into minimal components. + * This particular version is "in place", so that it changes the pattern + * which is to be reduced to a "minimal" size. + * + * (C) Carlo Wood - 6 Oct 1998 + * Speedup rewrite by Andrea Cocito, December 1998. + * Note that this new optimized alghoritm can *only* work in place. + */ + +char *collapse(char *mask) +{ + int star = 0; + char *m = mask; + char *b; + + if (m) + { + do + { + if ((*m == '*') && ((m[1] == '*') || (m[1] == '?'))) + { + b = m; + do + { + if (*m == '*') + star = 1; + else + { + if (star && (*m != '?')) + { + *b++ = '*'; + star = 0; + }; + *b++ = *m; + if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?'))) + *b++ = *++m; + }; + } + while (*m++); + break; + } + else + { + if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?'))) + m++; + }; + } + while (*m++); + }; + return mask; +} \ No newline at end of file diff --git a/mmatch/mmatch.h b/mmatch/mmatch.h new file mode 100644 index 000000000..3a48c202f --- /dev/null +++ b/mmatch/mmatch.h @@ -0,0 +1,16 @@ +#ifndef MMATCH_H +#define MMATCH_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int mmatch(const char *old_mask, const char *new_mask); +int match(const char *ma, const char *na); +char *collapse(char *pattern); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MMATCH_H */ diff --git a/mmatch/mmatch.vcxproj b/mmatch/mmatch.vcxproj new file mode 100644 index 000000000..40d9905b5 --- /dev/null +++ b/mmatch/mmatch.vcxproj @@ -0,0 +1,80 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + {19CBCE06-3F5C-479A-BD75-E2AB6215D345} + Win32Proj + mmatch + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + \ No newline at end of file