// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/api/log_private/syslog_parser.h" #include #include #include "base/logging.h" #include "base/memory/linked_ptr.h" #include "base/memory/singleton.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "base/time/time.h" #include "chrome/browser/extensions/api/log_private/filter_handler.h" #include "chrome/browser/extensions/api/log_private/log_parser.h" #include "chrome/browser/extensions/api/log_private/log_private_api.h" #include "chrome/common/extensions/api/log_private.h" namespace extensions { namespace { const int kExpectedTimeTokenNum = 7; const char kLogEntryDelimiters[] = "-:T"; const char kProcessInfoDelimiters[] = "[]"; } // namespace SyslogParser::SyslogParser() {} SyslogParser::~SyslogParser() {} SyslogParser::Error SyslogParser::ParseEntry( const std::string& input, std::vector >* output, FilterHandler* filter_handler) const { linked_ptr entry(new api::log_private::LogEntry); base::StringTokenizer tokenizer(input, " "); if (!tokenizer.GetNext()) { LOG(ERROR) << "Error when parsing data. Expect: At least 3 tokens. Actual: 0"; return TOKENIZE_ERROR; } std::string time = tokenizer.token(); if (ParseTime(time, &(entry->timestamp)) != SyslogParser::SUCCESS) { return SyslogParser::PARSE_ERROR; } // Skips "localhost" field. if (!tokenizer.GetNext()) { LOG(ERROR) << "Error when parsing data. Expect: At least 3 tokens. Actual: 1"; return TOKENIZE_ERROR; } if (!tokenizer.GetNext()) { LOG(ERROR) << "Error when parsing data. Expect: At least 3 tokens. Actual: 2"; return TOKENIZE_ERROR; } ParseProcess(tokenizer.token(), entry.get()); ParseLevel(input, entry.get()); entry->full_entry = input; if (filter_handler->IsValidLogEntry(*(entry.get()))) { output->push_back(entry); } return SyslogParser::SUCCESS; } SyslogParser::Error ParseTimeHelper(base::StringTokenizer* tokenizer, std::string* output) { if (!tokenizer->GetNext()) { LOG(ERROR) << "Error when parsing time"; return SyslogParser::PARSE_ERROR; } *output = tokenizer->token(); return SyslogParser::SUCCESS; } SyslogParser::Error SyslogParser::ParseTime(const std::string& input, double* output) const { base::StringTokenizer tokenizer(input, kLogEntryDelimiters); std::string tokens[kExpectedTimeTokenNum]; for (int i = 0; i < kExpectedTimeTokenNum; i++) { if (ParseTimeHelper(&tokenizer, &(tokens[i])) != SyslogParser::SUCCESS) return SyslogParser::PARSE_ERROR; } std::string buffer = tokens[1] + '-' + tokens[2] + '-' + tokens[0] + ' ' + tokens[3] + ':' + tokens[4] + ":00"; base::Time parsed_time; if (!base::Time::FromString(buffer.c_str(), &parsed_time)) { LOG(ERROR) << "Error when parsing time"; return SyslogParser::PARSE_ERROR; } double seconds; base::StringToDouble(tokens[5], &seconds); *output = parsed_time.ToJsTime() + (seconds * base::Time::kMillisecondsPerSecond); return SyslogParser::SUCCESS; } SyslogParser::Error SyslogParser::ParseProcess( const std::string& input, api::log_private::LogEntry* entry) const { base::StringTokenizer tokenizer(input, kProcessInfoDelimiters); if (!tokenizer.GetNext()) { LOG(ERROR) << "Error when parsing data. Expect: At least 1 token. Actual: 0"; return SyslogParser::PARSE_ERROR; } entry->process = tokenizer.token(); entry->process_id = "unknown"; if (tokenizer.GetNext()) { std::string token = tokenizer.token(); int tmp; if (base::StringToInt(token, &tmp)) { entry->process_id = token; } } return SyslogParser::SUCCESS; } void SyslogParser::ParseLevel(const std::string& input, api::log_private::LogEntry* entry) const { if (input.find("ERROR") != std::string::npos) { entry->level = "error"; } else if (input.find("WARN") != std::string::npos) { entry->level = "warning"; } else if (input.find("INFO") != std::string::npos) { entry->level = "info"; } else { entry->level = "unknown"; } } } // namespace extensions