diff --git a/components/livestatus/logtable.cpp b/components/livestatus/logtable.cpp index 6aedda052..8af7f13df 100644 --- a/components/livestatus/logtable.cpp +++ b/components/livestatus/logtable.cpp @@ -334,6 +334,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String /* States - TODO refactor */ if (boost::algorithm::contains(type, "INITIAL HOST STATE")) { + if (tokens.size() < 5) + return Dictionary::Ptr(); + log_class = LogClassState; log_type = LogTypeHostInitialState; @@ -344,6 +347,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[4]; } else if (boost::algorithm::contains(type, "CURRENT HOST STATE")) { + if (tokens.size() < 5) + return Dictionary::Ptr(); + log_class = LogClassState; log_type = LogTypeHostCurrentState; @@ -354,6 +360,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[4]; } else if (boost::algorithm::contains(type, "HOST ALERT")) { + if (tokens.size() < 5) + return Dictionary::Ptr(); + log_class = LogClassAlert; log_type = LogTypeHostAlert; @@ -364,6 +373,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[4]; } else if (boost::algorithm::contains(type, "HOST DOWNTIME ALERT")) { + if (tokens.size() < 3) + return Dictionary::Ptr(); + log_class = LogClassAlert; log_type = LogTypeHostDowntimeAlert; @@ -372,6 +384,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String comment = tokens[2]; } else if (boost::algorithm::contains(type, "HOST FLAPPING ALERT")) { + if (tokens.size() < 3) + return Dictionary::Ptr(); + log_class = LogClassAlert; log_type = LogTypeHostFlapping; @@ -380,6 +395,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String comment = tokens[2]; } else if (boost::algorithm::contains(type, "INITIAL SERVICE STATE")) { + if (tokens.size() < 6) + return Dictionary::Ptr(); + log_class = LogClassState; log_type = LogTypeServiceInitialState; @@ -391,6 +409,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[5]; } else if (boost::algorithm::contains(type, "CURRENT SERVICE STATE")) { + if (tokens.size() < 6) + return Dictionary::Ptr(); + log_class = LogClassState; log_type = LogTypeServiceCurrentState; @@ -402,6 +423,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[5]; } else if (boost::algorithm::contains(type, "SERVICE ALERT")) { + if (tokens.size() < 6) + return Dictionary::Ptr(); + log_class = LogClassAlert; log_type = LogTypeServiceAlert; @@ -413,6 +437,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[5]; } else if (boost::algorithm::contains(type, "SERVICE DOWNTIME ALERT")) { + if (tokens.size() < 4) + return Dictionary::Ptr(); + log_class = LogClassAlert; log_type = LogTypeServiceDowntimeAlert; @@ -422,6 +449,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String comment = tokens[3]; } else if (boost::algorithm::contains(type, "SERVICE FLAPPING ALERT")) { + if (tokens.size() < 4) + return Dictionary::Ptr(); + log_class = LogClassAlert; log_type = LogTypeServiceFlapping; @@ -431,6 +461,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String comment = tokens[3]; } else if (boost::algorithm::contains(type, "TIMEPERIOD TRANSITION")) { + if (tokens.size() < 4) + return Dictionary::Ptr(); + log_class = LogClassState; log_type = LogTypeTimeperiodTransition; @@ -441,6 +474,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String } /* Notifications - TODO refactor */ else if (boost::algorithm::contains(type, "HOST NOTIFICATION")) { + if (tokens.size() < 6) + return Dictionary::Ptr(); + log_class = LogClassNotification; log_type = LogTypeHostNotification; @@ -452,6 +488,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[5]; } else if (boost::algorithm::contains(type, "SERVICE NOTIFICATION")) { + if (tokens.size() < 7) + return Dictionary::Ptr(); + log_class = LogClassNotification; log_type = LogTypeHostNotification; @@ -465,6 +504,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String } /* Passive Checks - TODO refactor */ else if (boost::algorithm::contains(type, "PASSIVE HOST CHECK")) { + if (tokens.size() < 3) + return Dictionary::Ptr(); + log_class = LogClassPassive; host_name = tokens[0]; @@ -472,6 +514,9 @@ Dictionary::Ptr LogTable::GetLogEntryAttributes(const String& type, const String plugin_output = tokens[2]; } else if (boost::algorithm::contains(type, "PASSIVE SERVICE CHECK")) { + if (tokens.size() < 4) + return Dictionary::Ptr(); + log_class = LogClassPassive; host_name = tokens[0]; diff --git a/components/livestatus/query.cpp b/components/livestatus/query.cpp index f4a9a100e..7c0bde33d 100644 --- a/components/livestatus/query.cpp +++ b/components/livestatus/query.cpp @@ -59,6 +59,12 @@ Query::Query(const std::vector& lines) return; } + String msg; + BOOST_FOREACH(const String& line, lines) { + msg += line + "\n"; + } + Log(LogDebug, "livestatus", msg); + /* default separators */ m_Separators.push_back("\n"); m_Separators.push_back(";"); @@ -253,8 +259,28 @@ int Query::GetExternalCommands(void) Filter::Ptr Query::ParseFilter(const String& params, unsigned long& from, unsigned long& until) { + /* + * time >= 1382696656 + * type = SERVICE FLAPPING ALERT + */ std::vector tokens; - boost::algorithm::split(tokens, params, boost::is_any_of(" ")); + size_t sp_index; + String temp_buffer = params; + + /* extract attr and op */ + for (int i = 0; i < 2; i++) { + sp_index = temp_buffer.FindFirstOf(" "); + + /* 'attr op' or 'attr op val' is valid */ + if (i < 1 && sp_index == String::NPos) + BOOST_THROW_EXCEPTION(std::runtime_error("Livestatus filter '" + params + "' does not contain all required fields.")); + + tokens.push_back(temp_buffer.SubStr(0, sp_index)); + temp_buffer = temp_buffer.SubStr(sp_index + 1); + } + + /* add the rest as value */ + tokens.push_back(temp_buffer); if (tokens.size() == 2) tokens.push_back(""); @@ -262,8 +288,10 @@ Filter::Ptr Query::ParseFilter(const String& params, unsigned long& from, unsign if (tokens.size() < 3) return Filter::Ptr(); - String op = tokens[1]; bool negate = false; + String attr = tokens[0]; + String op = tokens[1]; + String val = tokens[2]; if (op == "!=") { op = "="; @@ -279,19 +307,21 @@ Filter::Ptr Query::ParseFilter(const String& params, unsigned long& from, unsign negate = true; } - Filter::Ptr filter = boost::make_shared(tokens[0], op, tokens[2]); + Filter::Ptr filter = boost::make_shared(attr, op, val); if (negate) filter = boost::make_shared(filter); /* pre-filter log time duration */ - if (tokens[0] == "time") { + if (attr == "time") { if (op == "<" || op == "<=") { - until = Convert::ToLong(tokens[2]); + until = Convert::ToLong(val); } else if (op == ">" || op == ">=") { - from = Convert::ToLong(tokens[2]); + from = Convert::ToLong(val); } } + + Log(LogDebug, "livestatus", "Parsed filter with attr: '" + attr + "' op: '" + op + "' val: '" + val + "'."); return filter; } @@ -371,7 +401,7 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream) std::vector objects = table->FilterRows(m_Filter); std::vector columns; - + if (m_Columns.size() > 0) columns = m_Columns; else @@ -399,7 +429,7 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream) BOOST_FOREACH(const Value& object, objects) { aggregator->Apply(table, object); } - + stats[index] = aggregator->GetResult(); index++; } @@ -434,6 +464,7 @@ void Query::ExecuteCommandHelper(const Stream::Ptr& stream) void Query::ExecuteErrorHelper(const Stream::Ptr& stream) { + Log(LogDebug, "livestatus", "ERROR: Code: '" + Convert::ToString(m_ErrorCode) + "' Message: '" + m_ErrorMessage + "'."); SendResponse(stream, m_ErrorCode, m_ErrorMessage); }