PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/logentry.cpp

http://github.com/acaudwell/Logstalgia
C++ | 286 lines | 194 code | 67 blank | 25 comment | 63 complexity | cc2c21d24f34682f523e606167290738 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com)
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version
  6. 3 of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #include "logentry.h"
  15. #include "settings.h"
  16. #include "core/regex.h"
  17. #include <time.h>
  18. #include <algorithm>
  19. //AccessLog
  20. AccessLog::AccessLog() {
  21. }
  22. //LogEntry
  23. std::vector<std::string> LogEntry::fields;
  24. std::vector<std::string> LogEntry::default_fields;
  25. std::map<std::string, std::string> LogEntry::field_titles;
  26. LogEntry::LogEntry() {
  27. timestamp = 0;
  28. response_size = 0;
  29. successful = false;
  30. response_colour = vec3(1.0, 0.0, 0.0);
  31. }
  32. Regex logentry_ipv6("(?i)^[a-f0-9:]+$");
  33. Regex logentry_hostname_parts("([^.]+)(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?$");
  34. std::string LogEntry::maskHostname(const std::string& hostname) {
  35. std::vector<std::string> parts;
  36. // could be an ipv6 address
  37. if(logentry_ipv6.match(hostname) && hostname.find(":") != std::string::npos) {
  38. size_t c = 0;
  39. size_t last = hostname.size();
  40. size_t colon_count = std::count(hostname.begin(), hostname.end(), ':');
  41. size_t padding = 7 - colon_count;
  42. if(colon_count <= 7) {
  43. size_t previous = 0;
  44. while( (last = hostname.rfind(":",last-1)) != std::string::npos) {
  45. c++;
  46. if(last == (previous-1)) c += padding;
  47. if(c >= 4) {
  48. std::string output = hostname.substr(0, last);
  49. output += '-';
  50. return output;
  51. }
  52. previous = last;
  53. }
  54. }
  55. }
  56. logentry_hostname_parts.match(hostname, &parts);
  57. size_t part_count = parts.size();
  58. //if only 1-2 parts, or 3 parts and a 2 character suffix, pass through unchanged
  59. if( part_count <= 2 || (part_count == 3 && parts[part_count-1].size()==2))
  60. return hostname;
  61. int num = atoi(parts[part_count-1].c_str());
  62. std::string output;
  63. //if last element is numeric, assume it is a numbered ip address
  64. //(ie 192.168.0.1 => 192.168.0-)
  65. if(num != 0) {
  66. for(size_t i=0;i<part_count-1;i++) {
  67. if(i>0) output += '.';
  68. output += parts[i];
  69. }
  70. output += '-';
  71. return output;
  72. }
  73. //hide the first element
  74. //(ie dhcp113.web.com -> web.com
  75. for(size_t i=1;i<part_count;i++) {
  76. if(i>1) output += '.';
  77. output += parts[i];
  78. }
  79. return output;
  80. }
  81. void LogEntry::setSuccess() {
  82. int code = atoi(response_code.c_str());
  83. successful = (code<400) ? true : false;
  84. }
  85. void LogEntry::setResponseColour() {
  86. int code = atoi(response_code.c_str());
  87. //set response colour
  88. if(code<200) {
  89. response_colour = vec3(0.0f, 1.0f, 0.5f);
  90. }
  91. else if(code>= 200 && code < 300) {
  92. response_colour = vec3(1.0f, 1.0f, 0.0f);
  93. }
  94. else if(code>= 300 && code < 400) {
  95. response_colour = vec3(1.0f, 0.5f, 0.0f);
  96. }
  97. else {
  98. response_colour = vec3(1.0f, 0.0f, 0.0f);
  99. }
  100. }
  101. const std::vector<std::string>& LogEntry::getFields() {
  102. if(fields.empty()) {
  103. fields.push_back("pid");
  104. fields.push_back("method");
  105. fields.push_back("protocol");
  106. fields.push_back("path");
  107. fields.push_back("vhost");
  108. fields.push_back("hostname");
  109. fields.push_back("response_code");
  110. fields.push_back("response_size");
  111. fields.push_back("referrer");
  112. fields.push_back("user_agent");
  113. fields.push_back("timestamp");
  114. fields.push_back("log_entry");
  115. }
  116. return fields;
  117. }
  118. const std::vector<std::string>& LogEntry::getDefaultFields() {
  119. if(default_fields.empty()) {
  120. default_fields.push_back("vhost");
  121. default_fields.push_back("timestamp");
  122. default_fields.push_back("hostname");
  123. default_fields.push_back("path");
  124. default_fields.push_back("method");
  125. default_fields.push_back("response_code");
  126. default_fields.push_back("response_size");
  127. default_fields.push_back("referrer");
  128. default_fields.push_back("user_agent");
  129. }
  130. return default_fields;
  131. }
  132. const std::string& LogEntry::getFieldTitle(const std::string& field) {
  133. if(field_titles.empty()) {
  134. field_titles["pid"] = "PID";
  135. field_titles["path"] = "Path";
  136. field_titles["method"] = "Method";
  137. field_titles["protocol"] = "Protocol";
  138. field_titles["vhost"] = "Virtual Host";
  139. field_titles["hostname"] = "Hostname";
  140. field_titles["response_size"] = "Response Size";
  141. field_titles["response_code"] = "Response Code";
  142. field_titles["referrer"] = "Referrer";
  143. field_titles["user_agent"] = "User Agent";
  144. field_titles["timestamp"] = "Timestamp";
  145. field_titles["log_entry"] = "Log Entry";
  146. }
  147. auto it = field_titles.find(field);
  148. assert(it != field_titles.end());
  149. return it->second;
  150. }
  151. bool LogEntry::getValue(const std::string& field, std::string& value) const {
  152. if(field == "pid") {
  153. value = pid;
  154. return true;
  155. }
  156. if(field == "path") {
  157. value = path;
  158. return true;
  159. }
  160. if(field == "method") {
  161. value = method;
  162. return true;
  163. }
  164. if(field == "protocol") {
  165. value = protocol;
  166. return true;
  167. }
  168. if(field == "hostname") {
  169. value = hostname;
  170. return true;
  171. }
  172. if(field == "vhost") {
  173. value = vhost;
  174. return true;
  175. }
  176. if(field == "response_size") {
  177. value = std::to_string(response_size);
  178. return true;
  179. }
  180. if(field == "response_code") {
  181. value = response_code;
  182. return true;
  183. }
  184. if(field == "referrer") {
  185. value = referrer;
  186. return true;
  187. }
  188. if(field == "user_agent") {
  189. value = user_agent;
  190. return true;
  191. }
  192. if(field == "timestamp") {
  193. struct tm* timeinfo = localtime ( &timestamp );
  194. char timestamp_buff[256];
  195. strftime(timestamp_buff, 256, "%Y-%m-%d %H:%M:%S", timeinfo);
  196. value = std::string(timestamp_buff);
  197. return true;
  198. }
  199. if(field == "log_entry") {
  200. value = log_entry;
  201. return true;
  202. }
  203. value = "";
  204. return false;
  205. }
  206. bool LogEntry::validate() {
  207. if(pid == "-") pid = "";
  208. if(referrer == "-") referrer = "";
  209. if(hostname.empty()) return false;
  210. if(settings.mask_hostnames) {
  211. hostname = maskHostname(hostname);
  212. }
  213. if(path.empty()) return false;
  214. if(timestamp == 0) return false;
  215. return true;
  216. }