1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/log_private/syslog_parser.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/logging.h" 11 #include "base/memory/linked_ptr.h" 12 #include "base/memory/singleton.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_split.h" 15 #include "base/strings/string_tokenizer.h" 16 #include "base/time/time.h" 17 #include "chrome/browser/extensions/api/log_private/filter_handler.h" 18 #include "chrome/browser/extensions/api/log_private/log_parser.h" 19 #include "chrome/browser/extensions/api/log_private/log_private_api.h" 20 #include "chrome/common/extensions/api/log_private.h" 21 22 namespace extensions { 23 24 namespace { 25 26 const int kExpectedTimeTokenNum = 7; 27 const char kLogEntryDelimiters[] = "-:T"; 28 const char kProcessInfoDelimiters[] = "[]"; 29 30 } // namespace 31 32 SyslogParser::SyslogParser() {} 33 34 SyslogParser::~SyslogParser() {} 35 36 SyslogParser::Error SyslogParser::ParseEntry( 37 const std::string& input, 38 std::vector<linked_ptr<api::log_private::LogEntry> >* output, 39 FilterHandler* filter_handler) const { 40 linked_ptr<api::log_private::LogEntry> entry(new api::log_private::LogEntry); 41 42 base::StringTokenizer tokenizer(input, " "); 43 if (!tokenizer.GetNext()) { 44 LOG(ERROR) 45 << "Error when parsing data. Expect: At least 3 tokens. Actual: 0"; 46 return TOKENIZE_ERROR; 47 } 48 std::string time = tokenizer.token(); 49 if (ParseTime(time, &(entry->timestamp)) != SyslogParser::SUCCESS) { 50 return SyslogParser::PARSE_ERROR; 51 } 52 // Skips "localhost" field. 53 if (!tokenizer.GetNext()) { 54 LOG(ERROR) 55 << "Error when parsing data. Expect: At least 3 tokens. Actual: 1"; 56 return TOKENIZE_ERROR; 57 } 58 if (!tokenizer.GetNext()) { 59 LOG(ERROR) 60 << "Error when parsing data. Expect: At least 3 tokens. Actual: 2"; 61 return TOKENIZE_ERROR; 62 } 63 ParseProcess(tokenizer.token(), entry.get()); 64 ParseLevel(input, entry.get()); 65 entry->full_entry = input; 66 67 if (filter_handler->IsValidLogEntry(*(entry.get()))) { 68 output->push_back(entry); 69 } 70 71 return SyslogParser::SUCCESS; 72 } 73 74 SyslogParser::Error ParseTimeHelper(base::StringTokenizer* tokenizer, 75 std::string* output) { 76 if (!tokenizer->GetNext()) { 77 LOG(ERROR) << "Error when parsing time"; 78 return SyslogParser::PARSE_ERROR; 79 } 80 *output = tokenizer->token(); 81 return SyslogParser::SUCCESS; 82 } 83 84 SyslogParser::Error SyslogParser::ParseTime(const std::string& input, 85 double* output) const { 86 base::StringTokenizer tokenizer(input, kLogEntryDelimiters); 87 std::string tokens[kExpectedTimeTokenNum]; 88 for (int i = 0; i < kExpectedTimeTokenNum; i++) { 89 if (ParseTimeHelper(&tokenizer, &(tokens[i])) != SyslogParser::SUCCESS) 90 return SyslogParser::PARSE_ERROR; 91 } 92 93 std::string buffer = tokens[1] + '-' + tokens[2] + '-' + tokens[0] + ' ' + 94 tokens[3] + ':' + tokens[4] + ":00"; 95 96 base::Time parsed_time; 97 if (!base::Time::FromString(buffer.c_str(), &parsed_time)) { 98 LOG(ERROR) << "Error when parsing time"; 99 return SyslogParser::PARSE_ERROR; 100 } 101 102 double seconds; 103 base::StringToDouble(tokens[5], &seconds); 104 *output = parsed_time.ToJsTime() + 105 (seconds * base::Time::kMillisecondsPerSecond); 106 107 return SyslogParser::SUCCESS; 108 } 109 110 SyslogParser::Error SyslogParser::ParseProcess( 111 const std::string& input, 112 api::log_private::LogEntry* entry) const { 113 base::StringTokenizer tokenizer(input, kProcessInfoDelimiters); 114 if (!tokenizer.GetNext()) { 115 LOG(ERROR) 116 << "Error when parsing data. Expect: At least 1 token. Actual: 0"; 117 return SyslogParser::PARSE_ERROR; 118 } 119 entry->process = tokenizer.token(); 120 entry->process_id = "unknown"; 121 if (tokenizer.GetNext()) { 122 std::string token = tokenizer.token(); 123 int tmp; 124 if (base::StringToInt(token, &tmp)) { 125 entry->process_id = token; 126 } 127 } 128 return SyslogParser::SUCCESS; 129 } 130 131 void SyslogParser::ParseLevel(const std::string& input, 132 api::log_private::LogEntry* entry) const { 133 if (input.find("ERROR") != std::string::npos) { 134 entry->level = "error"; 135 } else if (input.find("WARN") != std::string::npos) { 136 entry->level = "warning"; 137 } else if (input.find("INFO") != std::string::npos) { 138 entry->level = "info"; 139 } else { 140 entry->level = "unknown"; 141 } 142 } 143 144 } // namespace extensions 145