├── logo.png ├── .gitignore ├── TODO ├── AUTHORS ├── src ├── goaccess.h ├── options.h ├── xmalloc.h ├── opesys.h ├── browsers.h ├── json.h ├── csv.h ├── geolocation.h ├── gmenu.h ├── gdns.h ├── xmalloc.c ├── sort.h ├── tcbtdb.h ├── error.h ├── util.h ├── glibht.h ├── tcabdb.h ├── error.c ├── gmenu.c ├── settings.h ├── parser.h ├── gstorage.h ├── gdashboard.h ├── gstorage.c ├── commons.c ├── commons.h ├── config.h.in ├── gdns.c ├── tcbtdb.c ├── output.h ├── opesys.c ├── csv.c ├── ui.h ├── settings.c ├── geolocation.c ├── json.c └── browsers.c ├── Makefile.am ├── NEWS ├── README ├── configure.ac ├── compile ├── missing └── config └── goaccess.conf /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackingLab/GoaccessCN/HEAD/logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Copyright (C) 2009-2015 2 | Gerardo Orellana 3 | 4 | For a more comprehensive list of to-do items, please refer to the GitHub site. 5 | https://github.com/allinurl/goaccess/issues 6 | 7 | or visit http://goaccess.io/faq#todo 8 | 9 | If you are interested in working on any of the items listed in there, email 10 | goaccess@prosoftcorp.com or better, open a new issue: 11 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | GoAccess was designed and developed by Gerardo Orellana 2 | 3 | Special thanks to the following individuals for their great contributions: 4 | 5 | * Andrew Minion 6 | * as0n 7 | * Chilledheart 8 | * Daniel Aleksandersen 9 | * Daniel (dmilith) Dettlaff 10 | * Florian Forster 11 | * Francisco Azevedo 12 | * Frederic Cambus 13 | * holys 14 | * Kit Westneat 15 | * Mark J. Berger 16 | * m-r-r 17 | * radoslawc 18 | * Stéphane Péchard 19 | * Viktor Szépe 20 | * Ville Skyttä 21 | * woobee 22 | -------------------------------------------------------------------------------- /src/goaccess.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef GOACCESS_H_INCLUDED 22 | #define GOACCESS_H_INCLUDED 23 | 24 | #include "ui.h" 25 | 26 | extern GSpinner *parsing_spinner; 27 | extern int active_gdns; /* kill dns pthread flag */ 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/options.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef OPTIONS_H_INCLUDED 22 | #define OPTIONS_H_INCLUDED 23 | 24 | void cmd_help (void); 25 | void read_option_args (int argc, char **argv); 26 | void verify_global_config (int argc, char **argv); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/xmalloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef XMALLOC_H_INCLUDED 22 | #define XMALLOC_H_INCLUDED 23 | 24 | char *xstrdup (const char *s); 25 | void *xcalloc (size_t nmemb, size_t size); 26 | void *xmalloc (size_t size); 27 | void *xrealloc (void *oldptr, size_t size); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/opesys.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef OPESYS_H_INCLUDED 22 | #define OPESYS_H_INCLUDED 23 | 24 | #define OPESYS_TYPE_LEN 10 25 | 26 | typedef struct GOpeSys_ 27 | { 28 | char os_type[OPESYS_TYPE_LEN]; 29 | int hits; 30 | } GOpeSys; 31 | 32 | char *verify_os (const char *str, char *os_type); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/browsers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef BROWSERS_H_INCLUDED 22 | #define BROWSERS_H_INCLUDED 23 | 24 | #define BROWSER_TYPE_LEN 13 25 | 26 | typedef struct GBrowser_ 27 | { 28 | char browser_type[BROWSER_TYPE_LEN]; 29 | int hits; 30 | } GBrowser; 31 | 32 | char *verify_browser (char *str, char *browser_type); 33 | int is_crawler (const char *agent); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/json.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef JSON_H_INCLUDED 26 | #define JSON_H_INCLUDED 27 | 28 | #include "parser.h" 29 | 30 | typedef struct GJSON_ 31 | { 32 | GModule module; 33 | void (*render) (FILE * fp, GHolder * h, int processed); 34 | } GJSON; 35 | 36 | void output_json (GLog * logger, GHolder * holder); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/csv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef CSV_H_INCLUDED 26 | #define CSV_H_INCLUDED 27 | 28 | #include 29 | #include "parser.h" 30 | #include "settings.h" 31 | 32 | typedef struct GCSV_ 33 | { 34 | GModule module; 35 | void (*render) (FILE * fp, GHolder * h, int processed); 36 | } GCSV; 37 | 38 | void output_csv (GLog * logger, GHolder * holder); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/geolocation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef GEOLOCATION_H_INCLUDED 26 | #define GEOLOCATION_H_INCLUDED 27 | 28 | #ifdef HAVE_LIBGEOIP 29 | #include 30 | #endif 31 | 32 | #include "commons.h" 33 | 34 | #define CITY_LEN 28 35 | #define CONTINENT_LEN 48 36 | #define COUNTRY_LEN 48 + 3 /* Country + two-letter Code */ 37 | 38 | typedef struct GLocation_ 39 | { 40 | char city[CITY_LEN]; 41 | char continent[CONTINENT_LEN]; 42 | int hits; 43 | } GLocation; 44 | 45 | extern GeoIP *geo_location_data; 46 | 47 | GeoIP *geoip_open_db (const char *db); 48 | void geoip_get_city (const char *ip, char *location, GTypeIP type_ip); 49 | void geoip_get_continent (const char *ip, char *location, GTypeIP type_ip); 50 | void geoip_get_country (const char *ip, char *location, GTypeIP type_ip); 51 | int set_geolocation (char *host, char *continent, char *country, char *city); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/gmenu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifdef HAVE_NCURSESW_NCURSES_H 26 | #include 27 | #elif HAVE_NCURSES_NCURSES_H 28 | #include 29 | #elif HAVE_NCURSES_H 30 | #include 31 | #elif HAVE_CURSES_H 32 | #include 33 | #endif 34 | 35 | #ifndef GMENU_H_INCLUDED 36 | #define GMENU_H_INCLUDED 37 | 38 | enum ACTION 39 | { 40 | REQ_DOWN, 41 | REQ_UP, 42 | REQ_SEL 43 | }; 44 | 45 | typedef struct GMenu_ GMenu; 46 | typedef struct GItem_ GItem; 47 | 48 | struct GItem_ 49 | { 50 | char *name; 51 | int checked; 52 | }; 53 | 54 | struct GMenu_ 55 | { 56 | WINDOW *win; 57 | 58 | int count; 59 | int size; 60 | int idx; 61 | int start; 62 | int h; 63 | int w; 64 | int x; 65 | int y; 66 | unsigned short multiple; 67 | unsigned short selectable; 68 | unsigned short status; 69 | GItem *items; 70 | }; 71 | 72 | GMenu *new_gmenu (WINDOW * parent, int h, int w, int y, int x); 73 | int post_gmenu (GMenu * menu); 74 | void gmenu_driver (GMenu * menu, int c); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/gdns.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef GDNS_H_INCLUDED 22 | #define GDNS_H_INCLUDED 23 | 24 | #define H_SIZE 1025 25 | #define QUEUE_SIZE 400 26 | 27 | typedef struct GDnsThread_ 28 | { 29 | pthread_cond_t not_empty; 30 | pthread_cond_t not_full; 31 | pthread_mutex_t mutex; 32 | pthread_t thread; 33 | } GDnsThread; 34 | 35 | typedef struct GDnsQueue_ 36 | { 37 | int head; 38 | int tail; 39 | int size; 40 | int capacity; 41 | char buffer[QUEUE_SIZE][H_SIZE]; 42 | } GDnsQueue; 43 | 44 | extern GDnsThread gdns_thread; 45 | 46 | char *gqueue_dequeue (GDnsQueue * q); 47 | char *reverse_ip (char *str); 48 | int gqueue_empty (GDnsQueue * q); 49 | int gqueue_enqueue (GDnsQueue * q, char *item); 50 | int gqueue_find (GDnsQueue * q, const char *item); 51 | int gqueue_full (GDnsQueue * q); 52 | int gqueue_size (GDnsQueue * q); 53 | void dns_resolver (char *addr); 54 | void gdns_free_queue (void); 55 | void gdns_init (void); 56 | void gdns_queue_free (void); 57 | void gdns_thread_create (void); 58 | void gqueue_destroy (GDnsQueue * q); 59 | void gqueue_init (GDnsQueue * q, int capacity); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/xmalloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * xmalloc.c -- *alloc functions with error handling 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #include 23 | #if !defined __SUNPRO_C 24 | #include 25 | #endif 26 | #include 27 | #include 28 | 29 | #include "error.h" 30 | #include "xmalloc.h" 31 | 32 | /* self-checking wrapper to malloc() */ 33 | void * 34 | xmalloc (size_t size) 35 | { 36 | void *ptr; 37 | 38 | if ((ptr = malloc (size)) == NULL) 39 | FATAL ("Unable to allocate memory - failed."); 40 | 41 | return (ptr); 42 | } 43 | 44 | char * 45 | xstrdup (const char *s) 46 | { 47 | char *ptr; 48 | size_t len; 49 | 50 | len = strlen (s) + 1; 51 | ptr = xmalloc (len); 52 | 53 | strncpy (ptr, s, len); 54 | return (ptr); 55 | } 56 | 57 | /* self-checking wrapper to calloc() */ 58 | void * 59 | xcalloc (size_t nmemb, size_t size) 60 | { 61 | void *ptr; 62 | 63 | if ((ptr = calloc (nmemb, size)) == NULL) 64 | FATAL ("Unable to calloc memory - failed."); 65 | 66 | return (ptr); 67 | } 68 | 69 | /* self-checking wrapper to realloc() */ 70 | void * 71 | xrealloc (void *oldptr, size_t size) 72 | { 73 | void *newptr; 74 | 75 | if ((newptr = realloc (oldptr, size)) == NULL) 76 | FATAL ("Unable to reallocate memory - failed"); 77 | 78 | return (newptr); 79 | } 80 | -------------------------------------------------------------------------------- /src/sort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef SORT_H_INCLUDED 26 | #define SORT_H_INCLUDED 27 | 28 | #include "commons.h" 29 | #include "parser.h" 30 | 31 | #define SORT_MAX_OPTS 8 32 | #define SORT_MODULE_LEN 9 33 | #define SORT_FIELD_LEN 8 34 | #define SORT_ORDER_LEN 5 35 | 36 | typedef enum GSortField_ 37 | { 38 | SORT_BY_HITS, 39 | SORT_BY_VISITORS, 40 | SORT_BY_DATA, 41 | SORT_BY_BW, 42 | SORT_BY_USEC, 43 | SORT_BY_PROT, 44 | SORT_BY_MTHD, 45 | } GSortField; 46 | 47 | typedef enum GSortOrder_ 48 | { 49 | SORT_ASC, 50 | SORT_DESC 51 | } GSortOrder; 52 | 53 | typedef struct GSort_ 54 | { 55 | GModule module; 56 | GSortField field; 57 | GSortOrder sort; 58 | } GSort; 59 | 60 | extern GSort module_sort[TOTAL_MODULES]; 61 | extern const int sort_choices[][SORT_MAX_OPTS];; 62 | 63 | GRawData *sort_raw_data (GRawData * raw_data, int ht_size); 64 | int can_sort_module (GModule module, int field); 65 | int get_sort_field_enum (const char *str); 66 | int get_sort_order_enum (const char *str); 67 | void parse_initial_sort (void); 68 | void set_initial_sort (const char *smod, const char *sfield, const char *ssort); 69 | void sort_holder_items (GHolderItem * items, int size, GSort sort); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | #AUTOMAKE_OPTIONS = foreign 2 | bin_PROGRAMS = goaccess 3 | AUTOMAKE_OPTIONS = subdir-objects 4 | 5 | confdir = $(sysconfdir) 6 | dist_conf_DATA = config/goaccess.conf 7 | 8 | goaccess_SOURCES = \ 9 | src/browsers.c \ 10 | src/browsers.h \ 11 | src/commons.c \ 12 | src/commons.h \ 13 | src/csv.c \ 14 | src/csv.h \ 15 | src/error.c \ 16 | src/error.h \ 17 | src/gdashboard.c \ 18 | src/gdashboard.h \ 19 | src/gdns.c \ 20 | src/gdns.h \ 21 | src/gmenu.c \ 22 | src/gmenu.h \ 23 | src/goaccess.c \ 24 | src/goaccess.h \ 25 | src/gstorage.c \ 26 | src/gstorage.h \ 27 | src/json.c \ 28 | src/json.h \ 29 | src/opesys.c \ 30 | src/opesys.h \ 31 | src/options.c \ 32 | src/options.h \ 33 | src/output.c \ 34 | src/output.h \ 35 | src/parser.c \ 36 | src/parser.h \ 37 | src/sort.c \ 38 | src/sort.h \ 39 | src/settings.c \ 40 | src/settings.h \ 41 | src/ui.c \ 42 | src/ui.h \ 43 | src/util.c \ 44 | src/util.h \ 45 | src/xmalloc.c \ 46 | src/xmalloc.h 47 | 48 | if TCB 49 | goaccess_SOURCES += \ 50 | src/tcabdb.c \ 51 | src/tcabdb.h \ 52 | src/tcbtdb.c \ 53 | src/tcbtdb.h 54 | else 55 | goaccess_SOURCES += \ 56 | src/glibht.c \ 57 | src/glibht.h 58 | endif 59 | 60 | if GEOLOCATION 61 | goaccess_SOURCES += \ 62 | src/geolocation.c \ 63 | src/geolocation.h 64 | endif 65 | 66 | if DEBUG 67 | AM_CFLAGS = -DDEBUG -O0 -g -DSYSCONFDIR=\"$(sysconfdir)\" 68 | else 69 | AM_CFLAGS = -O2 -DSYSCONFDIR=\"$(sysconfdir)\" 70 | endif 71 | 72 | if WITH_RDYNAMIC 73 | AM_LDFLAGS = -rdynamic 74 | endif 75 | 76 | AM_CFLAGS += @GLIB2_CFLAGS@ 77 | AM_CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 78 | AM_CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations 79 | AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare 80 | AM_CFLAGS += -Wredundant-decls -Wbad-function-cast -Winline -Wcast-align -Wextra 81 | AM_CFLAGS += -Wdeclaration-after-statement -Wno-missing-field-initializers 82 | 83 | goaccess_LDADD = -lm 84 | dist_man_MANS = goaccess.1 85 | -------------------------------------------------------------------------------- /src/tcbtdb.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef TCBTDB_H_INCLUDED 26 | #define TCBTDB_H_INCLUDED 27 | 28 | #include 29 | 30 | #include "commons.h" 31 | #include "gstorage.h" 32 | #include "parser.h" 33 | 34 | #define TC_MMAP 0 35 | #define TC_LCNUM 1024 36 | #define TC_NCNUM 512 37 | #define TC_LMEMB 128 38 | #define TC_NMEMB 256 39 | #define TC_BNUM 32749 40 | #define TC_DBPATH "/tmp/" 41 | #define TC_ZLIB 1 42 | #define TC_BZ2 2 43 | 44 | /* B+ Tree - on-disk databases */ 45 | #define DB_AGENT_KEYS "db_agent_keys.tcb" 46 | #define DB_AGENT_VALS "db_agent_vals.tcb" 47 | #define DB_GEN_STATS "db_gen_stats.tcb" 48 | #define DB_HOSTNAMES "db_hostnames.tcb" 49 | #define DB_UNIQUE_KEYS "db_unique_keys.tcb" 50 | 51 | #define DB_KEYMAP "db_keymap.tcb" 52 | #define DB_DATAMAP "db_datamap.tcb" 53 | #define DB_ROOTMAP "db_rootmap.tcb" 54 | #define DB_UNIQMAP "db_uniqmap.tcb" 55 | #define DB_VISITORS "db_visitors.tcb" 56 | #define DB_HITS "db_hits.tcb" 57 | #define DB_BW "db_bw.tcb" 58 | #define DB_AVGTS "db_avgts.tcb" 59 | #define DB_METHODS "db_methods.tcb" 60 | #define DB_PROTOCOLS "db_protocols.tcb" 61 | #define DB_AGENTS "db_agents.tcb" 62 | 63 | /* *INDENT-OFF* */ 64 | TCBDB * tc_bdb_create (const char *dbname, int module); 65 | 66 | char * tc_db_set_path (const char *dbname, int module); 67 | int tc_bdb_close (void *db, char *dbname); 68 | void tc_db_get_params (char *params, const char *path); 69 | 70 | #ifdef TCB_BTREE 71 | int ht_insert_host_agent (TCBDB * bdb, int data_nkey, int agent_nkey); 72 | #endif 73 | /* *INDENT-ON* */ 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef ERROR_H_INCLUDED 22 | #define ERROR_H_INCLUDED 23 | 24 | #ifndef COMMONS 25 | #include "commons.h" 26 | #endif 27 | 28 | #ifdef HAVE_NCURSESW_NCURSES_H 29 | #include 30 | #elif HAVE_NCURSES_NCURSES_H 31 | #include 32 | #elif HAVE_NCURSES_H 33 | #include 34 | #elif HAVE_CURSES_H 35 | #include 36 | #endif 37 | 38 | #include 39 | 40 | #define TRACE_SIZE 128 41 | 42 | #define FATAL(fmt, ...) do { \ 43 | (void) endwin (); \ 44 | fprintf (stderr, "\nGoAccess - version %s - %s %s\n", GO_VERSION, __DATE__, \ 45 | __TIME__); \ 46 | fprintf (stderr, "Config file: %s\n", conf.iconfigfile ?: NO_CONFIG_FILE); \ 47 | fprintf (stderr, "\nFatal error has occurred"); \ 48 | fprintf (stderr, "\nError occured at: %s - %s - %d\n", __FILE__, \ 49 | __FUNCTION__, __LINE__); \ 50 | fprintf (stderr, fmt, ##__VA_ARGS__); \ 51 | fprintf (stderr, "\n\n"); \ 52 | LOG_DEBUG ((fmt, ##__VA_ARGS__)); \ 53 | exit(EXIT_FAILURE); \ 54 | } while (0) 55 | 56 | 57 | void dbg_fprintf (const char *fmt, ...); 58 | void dbg_log_close (void); 59 | void dbg_log_open (const char *file); 60 | void set_signal_data (void *p); 61 | 62 | #if defined(__GLIBC__) 63 | void sigsegv_handler (int sig); 64 | #endif 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef UTIL_H_INCLUDED 22 | #define UTIL_H_INCLUDED 23 | 24 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 25 | 26 | #define REGEX_ERROR 100 27 | #define KB 1024 28 | #define MB (KB * 1024) 29 | #define GB (MB * 1024) 30 | 31 | #define MILS 1000ULL 32 | #define SECS 1000000ULL 33 | #define MINS 60000000ULL 34 | #define HOUR 3600000000ULL 35 | 36 | /* *INDENT-OFF* */ 37 | #include 38 | #include 39 | #include 40 | 41 | char *alloc_string (const char *str); 42 | char *char_repeat (int n, char c); 43 | char *char_replace (char *str, char o, char n); 44 | char *deblank (char *str); 45 | char *escape_str (const char *src); 46 | char *filesize_str (unsigned long long log_size); 47 | char *float_to_str (float num); 48 | char *get_global_config (void); 49 | char *get_home (void); 50 | char *ints_to_str (int a, int b); 51 | char *int_to_str (int d); 52 | char *left_pad_str (const char *s, int indent); 53 | char *ltrim (char *s); 54 | char *replace_str (const char *str, const char *old, const char *new); 55 | char *rtrim (char *s); 56 | char *secs_to_str (int secs); 57 | char* strtoupper(char* str); 58 | char *substring (const char *str, int begin, int len); 59 | char *trim_str (char *str); 60 | char *unescape_str (const char *src); 61 | char *usecs_to_str (unsigned long long usec); 62 | const char *verify_status_code (char *str); 63 | const char *verify_status_code_type (const char *str); 64 | int convert_date (char *res, char *data, const char *from, const char *to, int size); 65 | int count_matches (const char *s1, char c); 66 | int ignore_referer (const char *ref); 67 | int intlen (int num); 68 | int invalid_ipaddr (char *str, int *ipvx); 69 | int ip_in_range (const char *ip); 70 | int str_to_time (const char *str, const char *fmt, struct tm *tm); 71 | int wc_match(char *wc, char * str); 72 | off_t file_size (const char *filename); 73 | uint32_t ip_to_binary (const char *ip); 74 | void strip_newlines (char *str); 75 | void xstrncpy (char *dest, const char *source, const size_t dest_size); 76 | 77 | /* *INDENT-ON* */ 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Copyright (C) 2009-2015 2 | Gerardo Orellana 3 | 4 | * Version history: 5 | - 0.9.2 [Monday, July 06, 2015] 6 | . GoAccess 0.9.2 Released. See ChangeLog for new features/bug-fixes. 7 | - 0.9.1 [Tuesday, May 26, 2015] 8 | . GoAccess 0.9.1 Released. See ChangeLog for new features/bug-fixes. 9 | - 0.9 [Thursday, March 19, 2015] 10 | . GoAccess 0.9 Released. See ChangeLog for new features/bug-fixes. 11 | - 0.8.5 [Sunday, September 14, 2014] 12 | . GoAccess 0.8.5 Released. See ChangeLog for new features/bug-fixes. 13 | - 0.8.4 [Monday, September 08, 2014] 14 | . GoAccess 0.8.4 Released. See ChangeLog for new features/bug-fixes. 15 | - 0.8.3 [Monday, July 28, 2014] 16 | . GoAccess 0.8.3 Released. See ChangeLog for new features/bug-fixes. 17 | - 0.8.2 [Monday, July 21, 2014] 18 | . GoAccess 0.8.2 Released. See ChangeLog for new features/bug-fixes. 19 | - 0.8.1 [Monday, June 16, 2014] 20 | . GoAccess 0.8.1 Released. See ChangeLog for new features/bug-fixes. 21 | - 0.8 [Monday, May 20, 2013] 22 | . GoAccess 0.8 Released. See ChangeLog for new features/bug-fixes. 23 | - 0.7.1 [Monday, February 17, 2014] 24 | . GoAccess 0.7.1 Released. See ChangeLog for new features/bug-fixes. 25 | - 0.7 [Monday, December 16, 2013] 26 | . GoAccess 0.7 Released. See ChangeLog for new features/bug-fixes. 27 | - 0.6.1 [Monday, October 07, 2013] 28 | . GoAccess 0.6.1 Released. See ChangeLog for new features/bug-fixes. 29 | - 0.6 [Monday, July 15, 2013] 30 | . GoAccess 0.6 Released. See ChangeLog for new features/bug-fixes. 31 | - 0.5 [Monday, June 04, 2012] 32 | . GoAccess 0.5 Released. See ChangeLog for new features/bug-fixes. 33 | - 0.4.2 [Monday, January 03, 2011] 34 | . GoAccess 0.4.2 Released. See ChangeLog for new features/bug-fixes. 35 | - 0.4.1 [Monday, December 13, 2010] 36 | . GoAccess 0.4.1 Released. See ChangeLog for new features/bug-fixes. 37 | - 0.4 [Tuesday, November 30, 2010] 38 | . GoAccess 0.4 Released. See ChangeLog for new features/bug-fixes. 39 | - 0.3.3 [Monday, September 27, 2010] 40 | . GoAccess 0.3.3 Released. See ChangeLog for new features/bug-fixes. 41 | - 0.3.2 [Thursday, September 09 2010] 42 | . GoAccess 0.3.2 Released. See ChangeLog for new features/bug-fixes. 43 | - 0.3.1 [Friday, September 03, 2010] 44 | . GoAccess 0.3.1 Released. See ChangeLog for new features/bug-fixes. 45 | - 0.3 [Sunday, August 29, 2010] 46 | . GoAccess 0.3 Released. See ChangeLog for new features/bug-fixes. 47 | - 0.2 [Sunday, July 25, 2010] 48 | . GoAccess 0.2 Released. See ChangeLog for new features/bug-fixes. 49 | - 0.1.2 [Tuesday, July 13, 2010] 50 | . GoAccess 0.1.2 Released. See ChangeLog for new features/bug-fixes. 51 | - 0.1.1 [Saturday, July 10, 2010] 52 | . GoAccess 0.1.1 Released. See ChangeLog for new features/bug-fixes. 53 | - 0.1 [Wednesday, July 07, 2010] 54 | . Welcome to the GoAccess 0.1 Released. 55 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | What is it? 2 | ------------- 3 | GoAccess is an open source real-time web log analyzer 4 | and interactive viewer that runs in a terminal in *nix systems. 5 | It provides fast and valuable HTTP statistics for system 6 | administrators that require a visual server report on the fly. 7 | 8 | Features 9 | ------------------------------- 10 | GoAccess parses the specified web log file and 11 | outputs the data to the X terminal. Features include: 12 | 13 | * General statistics, bandwidth, etc. 14 | * Time taken to serve the request (useful to track pages that are slowing down your site) 15 | * Top visitors 16 | * Requested files & static files 17 | * 404 or Not Found 18 | * Hosts, Reverse DNS, IP Location 19 | * Operating Systems 20 | * Browsers and Spiders 21 | * Referring Sites & URLs 22 | * Keyphrases 23 | * Geo Location - Continent/Country/City 24 | * Visitors Time Distribution 25 | * HTTP Status Codes 26 | * Ability to output JSON and CSV 27 | * Different Color Schemes 28 | * Support for large datasets + data persistence 29 | * Support for IPv6 30 | * Output statistics to HTML. See report 31 | * and more... 32 | 33 | Nearly all web log formats... 34 | 35 | GoAccess allows any custom log format string. 36 | Predefined options include, but not limited to: 37 | 38 | * Amazon CloudFront (Download Distribution). 39 | * Google Cloud Storage 40 | * Apache virtual hosts 41 | * Combined Log Format (XLF/ELF) Apache & Nginx 42 | * Common Log Format (CLF) Apache 43 | * W3C format (IIS). 44 | 45 | Why GoAccess? 46 | ------------- 47 | The main idea behind GoAccess is being able to quickly analyze and view web 48 | server statistics in real time without having to generate an HTML report (great 49 | if you want to do a quick analysis of your access log via SSH). 50 | 51 | Although it is possible to generate an HTML, JSON, CSV report, by default it 52 | outputs to a terminal. 53 | 54 | You can see it more of a monitor command tool than anything else. 55 | 56 | Keys 57 | ---- 58 | The user can make use of the following keys: 59 | 60 | * ^F1^ or ^h^ Main help, 61 | * ^F5^ Redraw [main window], 62 | * ^q^ Quit the program, current window or module, 63 | * ^o^ or ^ENTER^ Expand selected module, 64 | * ^[Shift]0-9^ Set selected module to active, 65 | * ^Up^ arrow Scroll up main dashboard, 66 | * ^Down^ arrow Scroll down main dashboard, 67 | * ^j^ Scroll down within expanded module, 68 | * ^k^ Scroll up within expanded module, 69 | * ^c^ Set or change scheme color, 70 | * ^CTRL^ + ^f^ Scroll forward one screen within, 71 | * active module, 72 | * ^CTRL^ + ^b^ Scroll backward one screen within, 73 | * active module, 74 | * ^TAB^ Iterate modules (forward), 75 | * ^SHIFT^ + ^TAB^ Iterate modules (backward), 76 | * ^s^ Sort options for current module, 77 | * ^/^ Search across all modules, 78 | * ^n^ Find position of the next occurrence, 79 | * ^g^ Move to the first item or top of screen, 80 | * ^G^ Move to the last item or bottom of screen, 81 | 82 | Examples can be found by running `man goaccess`. 83 | -------------------------------------------------------------------------------- /src/glibht.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef GLIBHT_H_INCLUDED 22 | #define GLIBHT_H_INCLUDED 23 | 24 | #ifdef HAVE_LIBGLIB_2_0 25 | #include 26 | #endif 27 | 28 | #include 29 | #include "parser.h" 30 | #include "gstorage.h" 31 | 32 | /* tables for the whole app */ 33 | extern GHashTable *ht_agent_keys; 34 | extern GHashTable *ht_agent_vals; 35 | extern GHashTable *ht_hostnames; 36 | extern GHashTable *ht_unique_keys; 37 | 38 | /* *INDENT-OFF* */ 39 | GRawData *parse_raw_data (GHashTable * ht, int ht_size, GModule module); 40 | 41 | uint32_t get_ht_size_by_metric (GModule module, GMetric metric); 42 | uint32_t get_ht_size (GHashTable * ht); 43 | 44 | int ht_inc_int_from_int_key (GHashTable * ht, int data_nkey, int inc); 45 | int ht_inc_int_from_str_key (GHashTable * ht, char *key, int inc); 46 | int ht_inc_u64_from_int_key (GHashTable * ht, int data_nkey, uint64_t inc); 47 | int ht_insert_agent(const char *key); 48 | int ht_insert_hit (GHashTable * ht, int data_nkey, int uniq_nkey, int root_nkey); 49 | int ht_insert_keymap(GHashTable *ht, const char *value); 50 | int ht_insert_nkey_nval (GHashTable * ht, int nkey, int nval); 51 | int ht_insert_str_from_int_key (GHashTable * ht, int nkey, const char *value); 52 | int ht_insert_uniqmap (GHashTable * ht, char *uniq_key); 53 | int ht_insert_unique_key (const char *key); 54 | int ht_insert_host_agent (GHashTable * ht, int data_nkey, int agent_nkey); 55 | int ht_insert_agent_key (const char *key); 56 | int ht_insert_agent_val (int nkey, const char *key); 57 | 58 | char *get_host_agent_val (int agent_nkey); 59 | char *get_hostname (const char *host); 60 | char *get_node_from_key (int data_nkey, GModule module, GMetric metric); 61 | char *get_root_from_key (int root_nkey, GModule module); 62 | char * get_str_from_int_key (GHashTable *ht, int nkey); 63 | int get_int_from_keymap (const char *key, GModule module); 64 | int get_int_from_str_key (GHashTable * ht, const char *key); 65 | int get_num_from_key (int data_nkey, GModule module, GMetric metric); 66 | int process_host_agents (char *host, char *agent); 67 | uint64_t get_cumulative_from_key (int data_nkey, GModule module, GMetric metric); 68 | unsigned int get_uint_from_str_key (GHashTable *ht, const char *key); 69 | void free_storage (void); 70 | void *get_host_agent_list (int data_nkey); 71 | void init_storage (void); 72 | 73 | void free_agent_list (void); 74 | 75 | /* *INDENT-ON* */ 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/tcabdb.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef TCABDB_H_INCLUDED 26 | #define TCABDB_H_INCLUDED 27 | 28 | #include 29 | 30 | #include "commons.h" 31 | #include "gstorage.h" 32 | #include "parser.h" 33 | 34 | #define DB_PARAMS 256 35 | 36 | /* tables for the whole app */ 37 | extern TCADB *ht_agent_keys; 38 | extern TCADB *ht_agent_vals; 39 | extern TCADB *ht_general_stats; 40 | extern TCADB *ht_hostnames; 41 | extern TCADB *ht_unique_keys; 42 | 43 | /* *INDENT-OFF* */ 44 | GRawData *parse_raw_data (void *db, int ht_size, GModule module); 45 | 46 | uint32_t get_ht_size_by_metric (GModule module, GMetric metric); 47 | uint32_t get_ht_size (TCADB *adb); 48 | 49 | int agent_list_to_store(void); 50 | int find_host_agent_in_list (void *data, void *needle); 51 | int ht_inc_int_from_int_key (TCADB * adb, int data_nkey, int inc); 52 | int ht_inc_int_from_str_key (TCADB * adb, const char *key, int inc); 53 | int ht_inc_u64_from_int_key (TCADB * adb, int data_nkey, uint64_t inc); 54 | int ht_inc_u64_from_str_key (TCADB * adb, const char *key, uint64_t inc); 55 | int ht_insert_agent_key (const char *key); 56 | int ht_insert_agent_val(int nkey, const char *key); 57 | int ht_insert_hit (TCADB *adb, int data_nkey, int uniq_nkey, int root_nkey); 58 | int ht_insert_keymap (TCADB * adb, const char *value); 59 | int ht_insert_nkey_nval (TCADB * adb, int nkey, int nval); 60 | int ht_insert_str_from_int_key (TCADB *adb, int nkey, const char *value); 61 | int ht_insert_uniqmap (TCADB *adb, char *uniq_key); 62 | int ht_insert_unique_key (const char *key); 63 | 64 | char *get_host_agent_val (int agent_nkey); 65 | char *get_hostname (const char *host); 66 | char *get_node_from_key (int data_nkey, GModule module, GMetric metric); 67 | char *get_root_from_key (int root_nkey, GModule module); 68 | char *get_str_from_int_key (TCADB *adb, int nkey); 69 | int get_int_from_keymap (const char * key, GModule module); 70 | int get_int_from_str_key (TCADB *adb, const char *key); 71 | int get_num_from_key (int data_nkey, GModule module, GMetric metric); 72 | uint64_t get_cumulative_from_key (int data_nkey, GModule module, GMetric metric); 73 | unsigned int get_uint_from_str_key (TCADB * adb, const char *key); 74 | void *get_host_agent_list(int agent_nkey); 75 | 76 | void free_agent_list(void); 77 | void free_db_key (TCADB *adb); 78 | void free_storage (void); 79 | void init_storage (void); 80 | 81 | #ifdef TCB_MEMHASH 82 | int ht_insert_host_agent (TCADB * adb, int data_nkey, int agent_nkey); 83 | #endif 84 | GSLList * tclist_to_gsllist (TCLIST * tclist); 85 | 86 | /* *INDENT-ON* */ 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | /** 2 | * error.c -- error handling 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #if HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #if defined(__GLIBC__) 30 | #include 31 | #endif 32 | #include 33 | #include 34 | 35 | #include "error.h" 36 | #include "parser.h" 37 | 38 | static FILE *log_file; 39 | static GLog *log_data; 40 | 41 | void 42 | dbg_log_open (const char *path) 43 | { 44 | if (path != NULL) { 45 | log_file = fopen (path, "w"); 46 | if (log_file == NULL) 47 | return; 48 | } 49 | } 50 | 51 | void 52 | dbg_log_close (void) 53 | { 54 | if (log_file != NULL) 55 | fclose (log_file); 56 | } 57 | 58 | void 59 | set_signal_data (void *p) 60 | { 61 | log_data = p; 62 | } 63 | 64 | #if defined(__GLIBC__) 65 | static void 66 | dump_struct (FILE * fp) 67 | { 68 | int pid = getpid (); 69 | if (!log_data) 70 | return; 71 | 72 | fprintf (fp, "==%d== VALUES AT CRASH POINT\n", pid); 73 | fprintf (fp, "==%d==\n", pid); 74 | fprintf (fp, "==%d== Line number: %d\n", pid, log_data->process); 75 | fprintf (fp, "==%d== Offset: %d\n", pid, log_data->offset); 76 | fprintf (fp, "==%d== Invalid data: %d\n", pid, log_data->invalid); 77 | fprintf (fp, "==%d== Piping: %d\n", pid, log_data->piping); 78 | fprintf (fp, "==%d== Response size: %lld bytes\n", pid, log_data->resp_size); 79 | fprintf (fp, "==%d==\n", pid); 80 | } 81 | 82 | void 83 | sigsegv_handler (int sig) 84 | { 85 | char **messages; 86 | FILE *fp = stderr; 87 | int pid = getpid (); 88 | size_t size, i; 89 | void *trace_stack[TRACE_SIZE]; 90 | 91 | (void) endwin (); 92 | fprintf (fp, "\n==%d== GoAccess %s crashed by Signal %d\n", pid, GO_VERSION, 93 | sig); 94 | fprintf (fp, "==%d==\n", pid); 95 | 96 | dump_struct (fp); 97 | 98 | size = backtrace (trace_stack, TRACE_SIZE); 99 | messages = backtrace_symbols (trace_stack, size); 100 | 101 | fprintf (fp, "==%d== STACK TRACE:\n", pid); 102 | fprintf (fp, "==%d==\n", pid); 103 | 104 | for (i = 0; i < size; i++) 105 | fprintf (fp, "==%d== %zu %s\n", pid, i, messages[i]); 106 | 107 | fprintf (fp, "==%d==\n", pid); 108 | fprintf (fp, "==%d== Please report it by opening an issue on GitHub:\n", pid); 109 | fprintf (fp, "==%d== https://github.com/allinurl/goaccess/issues\n\n", pid); 110 | exit (EXIT_FAILURE); 111 | } 112 | #endif 113 | 114 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 115 | void 116 | dbg_fprintf (const char *fmt, ...) 117 | { 118 | va_list args; 119 | 120 | if (!log_file) 121 | return; 122 | 123 | va_start (args, fmt); 124 | vfprintf (log_file, fmt, args); 125 | fflush (log_file); 126 | va_end (args); 127 | } 128 | 129 | #pragma GCC diagnostic warning "-Wformat-nonliteral" 130 | -------------------------------------------------------------------------------- /src/gmenu.c: -------------------------------------------------------------------------------- 1 | /** 2 | * gmenu.c -- goaccess menus 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "gmenu.h" 28 | 29 | #include "xmalloc.h" 30 | #include "ui.h" 31 | 32 | /* allocate memory for a new GMenu instance */ 33 | GMenu * 34 | new_gmenu (WINDOW * parent, int h, int w, int y, int x) 35 | { 36 | GMenu *menu = xmalloc (sizeof (GMenu)); 37 | 38 | memset (menu, 0, sizeof *menu); 39 | menu->count = 0; 40 | menu->idx = 0; 41 | menu->multiple = 0; 42 | menu->selectable = 0; 43 | menu->start = 0; 44 | menu->status = 0; 45 | 46 | menu->h = h; 47 | menu->w = w; 48 | menu->x = x; 49 | menu->y = y; 50 | menu->win = derwin (parent, menu->h, menu->w, menu->y, menu->x); 51 | 52 | return menu; 53 | } 54 | 55 | /* render an actual menu item */ 56 | static void 57 | draw_menu_item (GMenu * menu, char *s, int x, int y, int w, int color, 58 | int checked) 59 | { 60 | char check, *lbl = NULL; 61 | if (menu->selectable) { 62 | check = checked ? 'x' : ' '; 63 | lbl = xmalloc (snprintf (NULL, 0, "[%c] %s", check, s) + 1); 64 | sprintf (lbl, "[%c] %s", check, s); 65 | draw_header (menu->win, lbl, "%s", y, x, w, color, 0); 66 | free (lbl); 67 | } else { 68 | draw_header (menu->win, s, "%s", y, x, w, color, 0); 69 | } 70 | } 71 | 72 | /* displays a menu to its associated window */ 73 | int 74 | post_gmenu (GMenu * menu) 75 | { 76 | int i = 0, j = 0, k = 0, start, end, height, total, checked = 0; 77 | if (menu == NULL) 78 | return 1; 79 | 80 | werase (menu->win); 81 | 82 | height = menu->h; 83 | start = menu->start; 84 | total = menu->size; 85 | end = height < total ? start + height : total; 86 | for (i = start; i < end; i++, j++) { 87 | k = i == menu->idx ? 1 : 0; 88 | checked = menu->items[i].checked ? 1 : 0; 89 | draw_menu_item (menu, menu->items[i].name, 0, j, menu->w, k, checked); 90 | } 91 | wrefresh (menu->win); 92 | return 0; 93 | } 94 | 95 | /* main work horse of the menu system processing input events */ 96 | void 97 | gmenu_driver (GMenu * menu, int c) 98 | { 99 | int i; 100 | switch (c) { 101 | case REQ_DOWN: 102 | if (menu->idx >= menu->size - 1) 103 | break; 104 | ++menu->idx; 105 | if (menu->idx >= menu->h && menu->idx >= menu->start + menu->h) 106 | menu->start++; 107 | post_gmenu (menu); 108 | break; 109 | case REQ_UP: 110 | if (menu->idx <= 0) 111 | break; 112 | --menu->idx; 113 | if (menu->idx < menu->start) 114 | --menu->start; 115 | post_gmenu (menu); 116 | break; 117 | case REQ_SEL: 118 | if (!menu->multiple) { 119 | for (i = 0; i < menu->size; i++) 120 | menu->items[i].checked = 0; 121 | } 122 | if (menu->items[menu->idx].checked) 123 | menu->items[menu->idx].checked = 0; 124 | else 125 | menu->items[menu->idx].checked = 1; 126 | post_gmenu (menu); 127 | break; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef SETTINGS_H_INCLUDED 22 | #define SETTINGS_H_INCLUDED 23 | 24 | #include 25 | #include "commons.h" 26 | 27 | #define MAX_LINE_CONF 512 28 | #define MAX_EXTENSIONS 64 29 | #define MAX_IGNORE_IPS 64 30 | #define MAX_IGNORE_REF 64 31 | #define NO_CONFIG_FILE "No config file used" 32 | 33 | typedef enum 34 | { 35 | COMBINED, 36 | VCOMBINED, 37 | COMMON, 38 | VCOMMON, 39 | W3C, 40 | CLOUDFRONT, 41 | CLOUDSTORAGE, 42 | } LOGTYPE; 43 | 44 | /* predefined log dates */ 45 | typedef struct GPreConfTime_ 46 | { 47 | const char *fmt24; 48 | const char *usec; 49 | } GPreConfTime; 50 | 51 | /* predefined log dates */ 52 | typedef struct GPreConfDate_ 53 | { 54 | const char *apache; 55 | const char *w3c; 56 | const char *usec; 57 | } GPreConfDate; 58 | 59 | /* predefined log formats */ 60 | typedef struct GPreConfLog_ 61 | { 62 | const char *combined; 63 | const char *vcombined; 64 | const char *common; 65 | const char *vcommon; 66 | const char *w3c; 67 | const char *cloudfront; 68 | const char *cloudstorage; 69 | } GPreConfLog; 70 | 71 | typedef struct GConfKeyword_ 72 | { 73 | const unsigned short key_id; 74 | const char *keyword; 75 | } GConfKeyword; 76 | 77 | typedef struct GConf_ 78 | { 79 | char *date_format; 80 | char *debug_log; 81 | char *geoip_database; 82 | char *html_report_title; 83 | char *iconfigfile; 84 | char *ifile; 85 | char *ignore_ips[MAX_IGNORE_IPS]; 86 | char *ignore_panels[TOTAL_MODULES]; 87 | char *ignore_referers[MAX_IGNORE_REF]; 88 | char *log_format; 89 | char *output_format; 90 | char *sort_panels[TOTAL_MODULES]; 91 | char *static_files[MAX_EXTENSIONS]; 92 | char *time_format; 93 | 94 | int append_method; 95 | int append_protocol; 96 | int bandwidth; 97 | int client_err_to_unique_count; 98 | int code444_as_404; 99 | int color_scheme; 100 | int double_decode; 101 | int enable_html_resolver; 102 | int geo_db; 103 | int hl_header; 104 | int ignore_crawlers; 105 | int ignore_qstr; 106 | int list_agents; 107 | int load_conf_dlg; 108 | int load_global_config; 109 | int mouse_support; 110 | int no_color; 111 | int no_csv_summary; 112 | int no_progress; 113 | int output_html; 114 | int real_os; 115 | int serve_usecs; 116 | int skip_term_resolver; 117 | 118 | int ignore_ip_idx; 119 | int ignore_panel_idx; 120 | int ignore_referer_idx; 121 | int sort_panel_idx; 122 | int static_file_idx; 123 | 124 | size_t static_file_max_len; 125 | 126 | /* TokyoCabinet */ 127 | char *db_path; 128 | int64_t xmmap; 129 | int cache_lcnum; 130 | int cache_ncnum; 131 | int compression; 132 | int keep_db_files; 133 | int load_from_disk; 134 | int tune_bnum; 135 | int tune_lmemb; 136 | int tune_nmemb; 137 | } GConf; 138 | 139 | char *get_selected_date_str (size_t idx); 140 | char *get_selected_time_str (size_t idx); 141 | char *get_selected_format_str (size_t idx); 142 | size_t get_selected_format_idx (void); 143 | 144 | extern GConf conf; 145 | 146 | int parse_conf_file (int *argc, char ***argv); 147 | int ignore_panel (GModule mod); 148 | void free_cmd_args (void); 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef PARSER_H_INCLUDED 22 | #define PARSER_H_INCLUDED 23 | 24 | #define LINE_BUFFER 4096 25 | #define BW_HASHTABLES 3 26 | #define KEY_FOUND 1 27 | #define KEY_NOT_FOUND -1 28 | #define REF_SITE_LEN 512 29 | 30 | #include "commons.h" 31 | 32 | typedef struct GLogItem_ 33 | { 34 | char *agent; 35 | char *browser; 36 | char *browser_type; 37 | char *continent; 38 | char *country; 39 | char *date; 40 | char *host; 41 | char *keyphrase; 42 | char *method; 43 | char *os; 44 | char *os_type; 45 | char *protocol; 46 | char *ref; 47 | char *req; 48 | char *req_key; 49 | char *status; 50 | char *time; 51 | char *uniq_key; 52 | 53 | char site[REF_SITE_LEN]; 54 | 55 | uint64_t resp_size; 56 | uint64_t serve_time; 57 | 58 | int type_ip; 59 | int is_404; 60 | int is_static; 61 | int uniq_nkey; 62 | int agent_nkey; 63 | } GLogItem; 64 | 65 | typedef struct GLog_ 66 | { 67 | unsigned int exclude_ip; 68 | unsigned int invalid; 69 | unsigned int offset; 70 | unsigned int process; 71 | unsigned long long resp_size; 72 | unsigned short piping; 73 | GLogItem *items; 74 | } GLog; 75 | 76 | typedef struct GRawDataItem_ 77 | { 78 | void *key; 79 | void *value; 80 | } GRawDataItem; 81 | 82 | typedef struct GRawData_ 83 | { 84 | GRawDataItem *items; /* data */ 85 | GModule module; /* current module */ 86 | int idx; /* first level index */ 87 | int size; /* total num of items on ht */ 88 | } GRawData; 89 | 90 | /* Each record contains a data value, i.e., Windows XP, and it may contain a 91 | * root value, i.e., Windows, and a unique key which is the combination of 92 | * date, IP and user agent */ 93 | typedef struct GKeyData_ 94 | { 95 | void *data; 96 | void *data_key; 97 | int data_nkey; 98 | 99 | void *root; 100 | void *root_key; 101 | int root_nkey; 102 | 103 | void *uniq_key; 104 | int uniq_nkey; 105 | } GKeyData; 106 | 107 | typedef struct GParse_ 108 | { 109 | GModule module; 110 | int (*key_data) (GKeyData * kdata, GLogItem * glog); 111 | 112 | /* data field */ 113 | void (*datamap) (int data_nkey, const char *data, GModule module); 114 | void (*rootmap) (int root_nkey, const char *root, GModule module); 115 | 116 | /* metrics */ 117 | void (*hits) (int data_nkey, int uniq_nkey, int root_nkey, GModule module); 118 | void (*visitor) (int uniq_nkey, GModule module); 119 | void (*bw) (int data_nkey, uint64_t size, GModule module); 120 | void (*avgts) (int data_nkey, uint64_t ts, GModule module); 121 | void (*method) (int data_nkey, const char *method, GModule module); 122 | void (*protocol) (int data_nkey, const char *proto, GModule module); 123 | void (*agent) (int data_nkey, int agent_nkey, GModule module); 124 | } GParse; 125 | 126 | GLog *init_log (void); 127 | GLogItem *init_log_item (GLog * logger); 128 | GRawDataItem *new_grawdata_item (unsigned int size); 129 | GRawData *new_grawdata (void); 130 | int parse_log (GLog ** logger, char *tail, int n); 131 | int test_format (GLog * logger); 132 | void free_raw_data (GRawData * raw_data); 133 | void reset_struct (GLog * logger); 134 | void verify_formats (void); 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/gstorage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef GSTORAGE_H_INCLUDED 22 | #define GSTORAGE_H_INCLUDED 23 | 24 | #include "commons.h" 25 | 26 | typedef struct GStorageMetrics_ 27 | { 28 | /* Maps keys (string) to numeric values (integer). 29 | * This mitigates the issue of having multiple stores 30 | * with the same string key, and therefore, avoids unnecessary 31 | * memory usage (in most cases). 32 | * HEAD|/index.php -> 1 33 | * POST|/index.php -> 2 34 | * Windows XP -> 3 35 | * Ubuntu 10.10 -> 4 36 | * GET|Ubuntu 10.10 -> 5 37 | * Linux -> 6 38 | * 26/Dec/2014 -> 7 39 | * Windows -> 8 40 | */ 41 | void *keymap; 42 | 43 | /* Maps numeric keys to actual key values (strings), e.g., 44 | * 1 -> /index.php 45 | * 2 -> /index.php 46 | * 3 -> Windows XP 47 | * 4 -> Ubuntu 10.10 48 | * 5 -> Ubuntu 10.10 49 | * 7 -> 26/Dec/2014 50 | */ 51 | void *datamap; 52 | 53 | /* Maps numeric keys of root elements to actual 54 | * key values (strings), e.g., 55 | * 6 -> Linux 56 | * 8 -> Windows 57 | */ 58 | void *rootmap; 59 | 60 | /* Maps a string key made from the numeric key of the IP/date/UA and the 61 | * numeric key from the data field of each module to numeric autoincremented 62 | * values. e.g., 1 -> unique visitor key (concatenated) with 4 -> data key = 14 63 | * "14" -> 1 64 | * "15" -> 2 65 | */ 66 | void *uniqmap; 67 | 68 | /* Numeric key to a structure containing hits/root elements, e.g., 69 | * If root does not exist, it will have the value of 0 70 | * 1 -> hits:10934 , root: 0 , 71 | * 2 -> hits:3231 , root: 0 , 72 | * 3 -> hits:500 , root: 8 , 73 | * 4 -> hits:200 , root: 6 , 74 | * 5 -> hits:200 , root: 6 , 75 | * 5 -> hits:2030 , root: 0 , 76 | */ 77 | void *hits; 78 | 79 | /* Maps numeric keys made from the uniqmap store to autoincremented values 80 | * (counter). 81 | * 10 -> 100 82 | * 40 -> 56 83 | */ 84 | void *visitors; 85 | 86 | /* Maps numeric data keys to bandwidth (in bytes). 87 | * 1 -> 1024 88 | * 2 -> 2048 89 | */ 90 | void *bw; 91 | 92 | /* Maps numeric data keys to average time served (in usecs/msecs). 93 | * 1 -> 187 94 | * 2 -> 208 95 | */ 96 | void *time_served; 97 | 98 | /* Maps numeric data keys to string values. 99 | * 1 -> GET 100 | * 2 -> POST 101 | */ 102 | void *methods; 103 | 104 | /* Maps numeric data keys to string values. 105 | * 1 -> HTTP/1.1 106 | * 2 -> HTTP/1.0 107 | */ 108 | void *protocols; 109 | 110 | /* Maps numeric unique user-agent keys to the 111 | * corresponding numeric value. 112 | * 1 -> 3 113 | * 2 -> 4 114 | */ 115 | void *agents; 116 | 117 | } GStorageMetrics; 118 | 119 | typedef struct GStorage_ 120 | { 121 | GModule module; 122 | GStorageMetrics *metrics; 123 | } GStorage; 124 | 125 | extern GStorage *ht_storage; 126 | 127 | GMetrics *new_gmetrics (void); 128 | GStorageMetrics *get_storage_metrics_by_module (GModule module); 129 | GStorageMetrics *new_ht_metrics (void); 130 | GStorage *new_gstorage (uint32_t size); 131 | int *int2ptr (int val); 132 | uint64_t *uint642ptr (uint64_t val); 133 | void *get_storage_metric_by_module (GModule module, GMetric metric); 134 | void *get_storage_metric (GModule module, GMetric metric); 135 | void set_data_metrics (GMetrics * ometrics, GMetrics ** nmetrics, 136 | int processed); 137 | 138 | #endif // for #ifndef GSTORAGE_H 139 | -------------------------------------------------------------------------------- /src/gdashboard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef GDASHBOARD_H_INCLUDED 26 | #define GDASHBOARD_H_INCLUDED 27 | 28 | #include 29 | 30 | #include "ui.h" 31 | 32 | /* *INDENT-OFF* */ 33 | #define DASH_HEAD_POS 0 /* header line pos */ 34 | #define DASH_DESC_POS 1 /* description line pos */ 35 | #define DASH_EMPTY_POS 2 /* empty line pos */ 36 | #define DASH_DATA_POS 3 /* empty line pos */ 37 | 38 | #define DASH_COLLAPSED 11 /* total lines per module */ 39 | #define DASH_EXPANDED 32 /* total lines when expanded */ 40 | #define DASH_NON_DATA 4 /* items without stats */ 41 | 42 | #define DASH_INIT_X 2 /* x-axis offset */ 43 | #define DASH_BW_LEN 11 /* max bandwidth length */ 44 | #define DASH_SRV_TM_LEN 9 /* max served time length */ 45 | #define DASH_SPACE 1 /* space between data */ 46 | 47 | #define MTRC_ID_COUNTRY 0 48 | #define MTRC_ID_CITY 1 49 | #define MTRC_ID_HOSTNAME 2 50 | 51 | typedef struct GDashStyle_ 52 | { 53 | const int color_visitors; 54 | const int color_hits; 55 | const int color_data; 56 | const int color_bw; 57 | const int color_percent; 58 | const int color_bars; 59 | const int color_usecs; 60 | const int color_method; 61 | const int color_protocol; 62 | } GDashStyle; 63 | 64 | typedef struct GDashRender_ 65 | { 66 | WINDOW *win; 67 | int y; 68 | int w; 69 | int idx; 70 | int sel; 71 | } GDashRender; 72 | 73 | typedef struct GDashData_ 74 | { 75 | GMetrics *metrics; 76 | short is_subitem; 77 | } GDashData; 78 | 79 | typedef struct GDashModule_ 80 | { 81 | GDashData *data; 82 | GModule module; 83 | const char *desc; 84 | const char *head; 85 | 86 | int alloc_data; /* alloc data items */ 87 | int dash_size; /* dashboard size */ 88 | int data_len; 89 | int hits_len; 90 | int holder_size; /* hash table size */ 91 | int ht_size; /* hash table size */ 92 | int idx_data; /* idx data */ 93 | int max_hits; 94 | int method_len; 95 | int perc_len; 96 | int visitors_len; 97 | unsigned short pos_y; 98 | } GDashModule; 99 | 100 | typedef struct GDash_ 101 | { 102 | int total_alloc; 103 | GDashModule module[TOTAL_MODULES]; 104 | } GDash; 105 | 106 | typedef struct GPanel_ 107 | { 108 | GModule module; 109 | void (*insert) (GRawDataItem item, GHolder *h, const struct GPanel_ *); 110 | void (*holder_callback) (GHolder *h); 111 | void (*lookup) (GRawDataItem item); 112 | } GPanel; 113 | 114 | GDashData * new_gdata (uint32_t size); 115 | GDash *new_gdash (void); 116 | GHolder *new_gholder (uint32_t size); 117 | int perform_next_find (GHolder * h, GScroll * scroll); 118 | int render_find_dialog (WINDOW * main_win, GScroll * scroll); 119 | int set_module_from_mouse_event (GScroll *scroll, GDash *dash, int y); 120 | uint32_t get_ht_size_by_module (GModule module); 121 | void *add_hostname_node (void *ptr_holder); 122 | void display_content (WINDOW * win, GLog * logger, GDash * dash, GScroll * scroll); 123 | void free_dashboard (GDash * dash); 124 | void free_holder_by_module (GHolder ** holder, GModule module); 125 | void free_holder (GHolder ** holder); 126 | void load_data_to_dash (GHolder * h, GDash * dash, GModule module, GScroll * scroll); 127 | void load_holder_data (GRawData * raw_data, GHolder * h, GModule module, GSort sort); 128 | void load_host_to_holder (GHolder * h, char *ip); 129 | void reset_find (void); 130 | void reset_scroll_offsets (GScroll * scroll); 131 | /* *INDENT-ON* */ 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /src/gstorage.c: -------------------------------------------------------------------------------- 1 | /** 2 | * gstorage.c -- common storage handling 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #include 23 | #if !defined __SUNPRO_C 24 | #include 25 | #endif 26 | #include 27 | #include 28 | 29 | #include "gstorage.h" 30 | 31 | #include "error.h" 32 | #include "xmalloc.h" 33 | 34 | GStorage * 35 | new_gstorage (uint32_t size) 36 | { 37 | GStorage *store = xcalloc (size, sizeof (GStorage)); 38 | return store; 39 | } 40 | 41 | GMetrics * 42 | new_gmetrics (void) 43 | { 44 | GMetrics *metrics = xcalloc (1, sizeof (GMetrics)); 45 | 46 | return metrics; 47 | } 48 | 49 | GStorageMetrics * 50 | new_ht_metrics (void) 51 | { 52 | GStorageMetrics *metrics = xmalloc (sizeof (GStorageMetrics)); 53 | 54 | memset (metrics, 0, sizeof *metrics); 55 | 56 | /* maps */ 57 | metrics->keymap = NULL; 58 | metrics->datamap = NULL; 59 | metrics->rootmap = NULL; 60 | metrics->uniqmap = NULL; 61 | 62 | /* metrics */ 63 | metrics->hits = NULL; 64 | metrics->visitors = NULL; 65 | metrics->bw = NULL; 66 | metrics->time_served = NULL; 67 | metrics->protocols = NULL; 68 | metrics->methods = NULL; 69 | metrics->agents = NULL; 70 | 71 | return metrics; 72 | } 73 | 74 | GStorageMetrics * 75 | get_storage_metrics_by_module (GModule module) 76 | { 77 | return ht_storage[module].metrics; 78 | } 79 | 80 | int * 81 | int2ptr (int val) 82 | { 83 | int *ptr = xmalloc (sizeof (int)); 84 | *ptr = val; 85 | return ptr; 86 | } 87 | 88 | uint64_t * 89 | uint642ptr (uint64_t val) 90 | { 91 | uint64_t *ptr = xmalloc (sizeof (uint64_t)); 92 | *ptr = val; 93 | return ptr; 94 | } 95 | 96 | void * 97 | get_storage_metric_by_module (GModule module, GMetric metric) 98 | { 99 | void *ht; 100 | GStorageMetrics *metrics; 101 | 102 | metrics = get_storage_metrics_by_module (module); 103 | switch (metric) { 104 | case MTRC_KEYMAP: 105 | ht = metrics->keymap; 106 | break; 107 | case MTRC_ROOTMAP: 108 | ht = metrics->rootmap; 109 | break; 110 | case MTRC_DATAMAP: 111 | ht = metrics->datamap; 112 | break; 113 | case MTRC_UNIQMAP: 114 | ht = metrics->uniqmap; 115 | break; 116 | case MTRC_HITS: 117 | ht = metrics->hits; 118 | break; 119 | case MTRC_VISITORS: 120 | ht = metrics->visitors; 121 | break; 122 | case MTRC_BW: 123 | ht = metrics->bw; 124 | break; 125 | case MTRC_TIME_SERVED: 126 | ht = metrics->time_served; 127 | break; 128 | case MTRC_METHODS: 129 | ht = metrics->methods; 130 | break; 131 | case MTRC_PROTOCOLS: 132 | ht = metrics->protocols; 133 | break; 134 | case MTRC_AGENTS: 135 | ht = metrics->agents; 136 | break; 137 | default: 138 | ht = NULL; 139 | } 140 | 141 | return ht; 142 | } 143 | 144 | void 145 | set_data_metrics (GMetrics * ometrics, GMetrics ** nmetrics, int processed) 146 | { 147 | GMetrics *metrics; 148 | float percent = get_percentage (processed, ometrics->hits); 149 | 150 | metrics = new_gmetrics (); 151 | metrics->bw.nbw = ometrics->bw.nbw; 152 | metrics->id = ometrics->id; 153 | metrics->data = ometrics->data; 154 | metrics->hits = ometrics->hits; 155 | metrics->percent = percent < 0 ? 0 : percent; 156 | metrics->visitors = ometrics->visitors; 157 | 158 | if (conf.serve_usecs && ometrics->hits > 0) 159 | metrics->avgts.nts = ometrics->avgts.nts; 160 | 161 | if (conf.append_method && ometrics->method) 162 | metrics->method = ometrics->method; 163 | 164 | if (conf.append_method && ometrics->protocol) 165 | metrics->protocol = ometrics->protocol; 166 | 167 | *nmetrics = metrics; 168 | } 169 | 170 | void * 171 | get_storage_metric (GModule module, GMetric metric) 172 | { 173 | return get_storage_metric_by_module (module, metric); 174 | } 175 | -------------------------------------------------------------------------------- /src/commons.c: -------------------------------------------------------------------------------- 1 | /** 2 | * commons.c -- holds different data types 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #if HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "commons.h" 32 | #include "error.h" 33 | #include "util.h" 34 | #include "xmalloc.h" 35 | 36 | /* processing time */ 37 | time_t end_proc; 38 | time_t timestamp; 39 | time_t start_proc; 40 | 41 | /* resizing/scheme */ 42 | size_t real_size_y = 0; 43 | size_t term_h = 0; 44 | size_t term_w = 0; 45 | 46 | static GEnum MODULES[] = { 47 | {"VISITORS", VISITORS}, 48 | {"REQUESTS", REQUESTS}, 49 | {"REQUESTS_STATIC", REQUESTS_STATIC}, 50 | {"NOT_FOUND", NOT_FOUND}, 51 | {"HOSTS", HOSTS}, 52 | {"OS", OS}, 53 | {"BROWSERS", BROWSERS}, 54 | {"VISIT_TIMES", VISIT_TIMES}, 55 | {"REFERRERS", REFERRERS}, 56 | {"REFERRING_SITES", REFERRING_SITES}, 57 | {"KEYPHRASES", KEYPHRASES}, 58 | #ifdef HAVE_LIBGEOIP 59 | {"GEO_LOCATION", GEO_LOCATION}, 60 | #endif 61 | {"STATUS_CODES", STATUS_CODES}, 62 | }; 63 | 64 | /* calculate hits percentage */ 65 | float 66 | get_percentage (unsigned long long total, unsigned long long hit) 67 | { 68 | return ((float) (hit * 100) / (total)); 69 | } 70 | 71 | void 72 | display_storage (void) 73 | { 74 | #ifdef TCB_BTREE 75 | fprintf (stdout, "Built using Tokyo Cabinet On-Disk B+ Tree.\n"); 76 | #elif TCB_MEMHASH 77 | fprintf (stdout, "Built using Tokyo Cabinet On-Memory Hash database.\n"); 78 | #else 79 | fprintf (stdout, "Built using GLib On-Memory Hash database.\n"); 80 | #endif 81 | } 82 | 83 | void 84 | display_version (void) 85 | { 86 | fprintf (stdout, "GoAccess - %s.\n", GO_VERSION); 87 | fprintf (stdout, "For more details visit: http://goaccess.io\n"); 88 | fprintf (stdout, "Copyright (C) 2009-2015 GNU GPL'd, by Gerardo Orellana\n"); 89 | } 90 | 91 | int 92 | get_module_enum (const char *str) 93 | { 94 | return str2enum (MODULES, ARRAY_SIZE (MODULES), str); 95 | } 96 | 97 | int 98 | str2enum (const GEnum map[], int len, const char *str) 99 | { 100 | int i; 101 | 102 | for (i = 0; i < len; ++i) { 103 | if (!strcmp (str, map[i].str)) 104 | return map[i].idx; 105 | } 106 | 107 | return -1; 108 | } 109 | 110 | GSLList * 111 | list_create (void *data) 112 | { 113 | GSLList *node = xmalloc (sizeof (GSLList)); 114 | node->data = data; 115 | node->next = NULL; 116 | 117 | return node; 118 | } 119 | 120 | GSLList * 121 | list_insert_append (GSLList * node, void *data) 122 | { 123 | GSLList *newnode; 124 | newnode = list_create (data); 125 | newnode->next = node->next; 126 | node->next = newnode; 127 | 128 | return newnode; 129 | } 130 | 131 | GSLList * 132 | list_insert_prepend (GSLList * list, void *data) 133 | { 134 | GSLList *newnode; 135 | newnode = list_create (data); 136 | newnode->next = list; 137 | 138 | return newnode; 139 | } 140 | 141 | GSLList * 142 | list_find (GSLList * node, int (*func) (void *, void *), void *data) 143 | { 144 | while (node) { 145 | if (func (node->data, data) > 0) 146 | return node; 147 | node = node->next; 148 | } 149 | 150 | return NULL; 151 | } 152 | 153 | int 154 | list_remove_nodes (GSLList * list) 155 | { 156 | GSLList *tmp; 157 | while (list != NULL) { 158 | tmp = list->next; 159 | if (list->data) 160 | free (list->data); 161 | free (list); 162 | list = tmp; 163 | } 164 | 165 | return 0; 166 | } 167 | 168 | int 169 | list_foreach (GSLList * node, int (*func) (void *, void *), void *user_data) 170 | { 171 | while (node) { 172 | if (func (node->data, user_data) != 0) 173 | return -1; 174 | node = node->next; 175 | } 176 | 177 | return 0; 178 | } 179 | 180 | int 181 | list_count (GSLList * node) 182 | { 183 | int count = 0; 184 | while (node != 0) { 185 | count++; 186 | node = node->next; 187 | } 188 | return count; 189 | } 190 | 191 | GAgents * 192 | new_gagents (void) 193 | { 194 | GAgents *agents = xmalloc (sizeof (GAgents)); 195 | memset (agents, 0, sizeof *agents); 196 | 197 | return agents; 198 | } 199 | 200 | GAgentItem * 201 | new_gagent_item (uint32_t size) 202 | { 203 | GAgentItem *item = xcalloc (size, sizeof (GAgentItem)); 204 | 205 | return item; 206 | } 207 | 208 | void 209 | format_date_visitors (GMetrics * metrics) 210 | { 211 | char date[DATE_LEN] = ""; /* Ymd */ 212 | char *datum = metrics->data; 213 | 214 | memset (date, 0, sizeof *date); 215 | /* verify we have a valid date conversion */ 216 | if (convert_date (date, datum, "%Y%m%d", "%d/%b/%Y", DATE_LEN) == 0) { 217 | free (datum); 218 | metrics->data = xstrdup (date); 219 | return; 220 | } 221 | LOG_DEBUG (("invalid date: %s", datum)); 222 | 223 | free (datum); 224 | metrics->data = xstrdup ("---"); 225 | } 226 | 227 | int 228 | has_timestamp (const char *fmt) 229 | { 230 | if (strcmp ("%s", fmt) == 0) 231 | return 1; 232 | return 0; 233 | } 234 | -------------------------------------------------------------------------------- /src/commons.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef COMMONS_H_INCLUDED 26 | #define COMMONS_H_INCLUDED 27 | 28 | #ifdef HAVE_LIBGEOIP 29 | #include 30 | #endif 31 | 32 | #include 33 | #include 34 | 35 | /* Remove the __attribute__ stuff when the compiler is not GCC. */ 36 | #if !__GNUC__ 37 | #define __attribute__(x) /**/ 38 | #endif 39 | #define GO_UNUSED __attribute__((unused)) 40 | #define GO_VERSION "0.9.2" 41 | #define GO_WEBSITE "http://goaccess.hackinglab.cn/" 42 | struct tm *now_tm; 43 | 44 | #define INT_TO_PTR(i) ((void *) (long) (i)) 45 | #define PTR_TO_INT(p) ((int) (long) (p)) 46 | 47 | /* Processing time */ 48 | extern time_t end_proc; 49 | extern time_t timestamp; 50 | extern time_t start_proc; 51 | 52 | /* resizing */ 53 | extern size_t real_size_y; 54 | extern size_t term_h; 55 | extern size_t term_w; 56 | 57 | #ifdef DEBUG 58 | #define LOG_DEBUG(x, ...) do { dbg_fprintf x; } while (0) 59 | #else 60 | #define LOG_DEBUG(x, ...) do { } while (0) 61 | #endif 62 | 63 | #ifdef HAVE_LIBGEOIP 64 | #define TOTAL_MODULES 13 65 | #else 66 | #define TOTAL_MODULES 12 67 | #endif 68 | 69 | #define DATE_TIME 20 70 | #define DATE_LEN 12 /* date length */ 71 | #define HOUR_LEN 3 /* hour length */ 72 | 73 | #define REQ_PROTO_LEN 9 74 | #define REQ_METHOD_LEN 8 75 | 76 | typedef enum 77 | { 78 | TYPE_IPINV, 79 | TYPE_IPV4, 80 | TYPE_IPV6 81 | } GTypeIP; 82 | 83 | typedef enum 84 | { 85 | REQUEST, 86 | REQUEST_METHOD, 87 | REQUEST_PROTOCOL 88 | } GReqMeta; 89 | 90 | typedef enum METRICS 91 | { 92 | MTRC_KEYMAP, 93 | MTRC_ROOTMAP, 94 | MTRC_DATAMAP, 95 | MTRC_UNIQMAP, 96 | MTRC_HITS, 97 | MTRC_VISITORS, 98 | MTRC_BW, 99 | MTRC_TIME_SERVED, 100 | MTRC_METHODS, 101 | MTRC_PROTOCOLS, 102 | MTRC_AGENTS, 103 | } GMetric; 104 | 105 | typedef enum MODULES 106 | { 107 | VISITORS, 108 | REQUESTS, 109 | REQUESTS_STATIC, 110 | NOT_FOUND, 111 | HOSTS, 112 | OS, 113 | BROWSERS, 114 | VISIT_TIMES, 115 | REFERRERS, 116 | REFERRING_SITES, 117 | KEYPHRASES, 118 | #ifdef HAVE_LIBGEOIP 119 | GEO_LOCATION, 120 | #endif 121 | STATUS_CODES, 122 | } GModule; 123 | 124 | typedef struct GMetrics 125 | { 126 | /* metric id can be used to identified 127 | * a specific data field */ 128 | uint8_t id; 129 | char *data; 130 | char *method; 131 | char *protocol; 132 | 133 | float percent; 134 | int hits; 135 | int visitors; 136 | /* holder has a numeric value, while 137 | * dashboard has a displayable string value */ 138 | union 139 | { 140 | char *sbw; 141 | uint64_t nbw; 142 | } bw; 143 | /* holder has a numeric value, while 144 | * dashboard has a displayable string value */ 145 | union 146 | { 147 | char *sts; 148 | uint64_t nts; 149 | } avgts; 150 | } GMetrics; 151 | 152 | typedef struct GSubItem_ 153 | { 154 | GModule module; 155 | GMetrics *metrics; 156 | struct GSubItem_ *prev; 157 | struct GSubItem_ *next; 158 | } GSubItem; 159 | 160 | typedef struct GSubList_ 161 | { 162 | int size; 163 | struct GSubItem_ *head; 164 | struct GSubItem_ *tail; 165 | } GSubList; 166 | 167 | typedef struct GHolderItem_ 168 | { 169 | GSubList *sub_list; 170 | GMetrics *metrics; 171 | } GHolderItem; 172 | 173 | typedef struct GHolder_ 174 | { 175 | GHolderItem *items; /* items */ 176 | GModule module; /* current module */ 177 | int idx; /* index */ 178 | int holder_size; /* total number of allocated items */ 179 | int ht_size; /* total number of data items */ 180 | int sub_items_size; /* total number of sub items */ 181 | } GHolder; 182 | 183 | typedef struct GEnum_ 184 | { 185 | const char *str; 186 | int idx; 187 | } GEnum; 188 | 189 | typedef struct GDataMap_ 190 | { 191 | int data; 192 | int uniq; 193 | int root; 194 | } GDataMap; 195 | 196 | typedef struct GAgentItem_ 197 | { 198 | char *agent; 199 | } GAgentItem; 200 | 201 | typedef struct GAgents_ 202 | { 203 | int size; 204 | struct GAgentItem_ *items; 205 | } GAgents; 206 | 207 | /* single linked-list */ 208 | typedef struct GSLList_ 209 | { 210 | void *data; 211 | struct GSLList_ *next; 212 | } GSLList; 213 | 214 | /* *INDENT-OFF* */ 215 | GAgents *new_gagents (void); 216 | GAgentItem *new_gagent_item (uint32_t size); 217 | 218 | float get_percentage (unsigned long long total, unsigned long long hit); 219 | int get_module_enum (const char *str); 220 | int has_timestamp (const char *fmt); 221 | int str2enum (const GEnum map[], int len, const char *str); 222 | void display_storage (void); 223 | void display_version (void); 224 | 225 | /* single linked-list */ 226 | GSLList *list_create (void *data); 227 | GSLList *list_find (GSLList * node, int (*func) (void *, void *), void *data); 228 | GSLList *list_insert_append (GSLList * node, void *data); 229 | GSLList *list_insert_prepend (GSLList * list, void *data); 230 | int list_count (GSLList * list); 231 | int list_foreach (GSLList * node, int (*func) (void *, void *), void *user_data); 232 | int list_remove_nodes (GSLList * list); 233 | void format_date_visitors (GMetrics * metrics); 234 | /* *INDENT-ON* */ 235 | 236 | #endif 237 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_ARPA_INET_H 5 | 6 | /* "Build using BZ2" */ 7 | #undef HAVE_BZ2 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_CURSES_H 11 | 12 | /* Define to 1 if you have the `floor' function. */ 13 | #undef HAVE_FLOOR 14 | 15 | /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ 16 | #undef HAVE_FSEEKO 17 | 18 | /* Define to 1 if you have the `gethostbyaddr' function. */ 19 | #undef HAVE_GETHOSTBYADDR 20 | 21 | /* Define to 1 if you have the `gethostbyname' function. */ 22 | #undef HAVE_GETHOSTBYNAME 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_INTTYPES_H 26 | 27 | /* Define to 1 if you have the `GeoIP' library (-lGeoIP). */ 28 | #undef HAVE_LIBGEOIP 29 | 30 | /* Define to 1 if you have the `glib-2.0' library (-lglib-2.0). */ 31 | #undef HAVE_LIBGLIB_2_0 32 | 33 | /* Define to 1 if you have the `ncurses' library (-lncurses). */ 34 | #undef HAVE_LIBNCURSES 35 | 36 | /* Define to 1 if you have the `ncursesw' library (-lncursesw). */ 37 | #undef HAVE_LIBNCURSESW 38 | 39 | /* Define to 1 if you have the `nsl' library (-lnsl). */ 40 | #undef HAVE_LIBNSL 41 | 42 | /* Define to 1 if you have the `pthread' library (-lpthread). */ 43 | #undef HAVE_LIBPTHREAD 44 | 45 | /* Define to 1 if you have the `socket' library (-lsocket). */ 46 | #undef HAVE_LIBSOCKET 47 | 48 | /* Define to 1 if you have the `tokyocabinet' library (-ltokyocabinet). */ 49 | #undef HAVE_LIBTOKYOCABINET 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_LOCALE_H 53 | 54 | /* Define to 1 if you have the `malloc' function. */ 55 | #undef HAVE_MALLOC 56 | 57 | /* Define to 1 if you have the `memmove' function. */ 58 | #undef HAVE_MEMMOVE 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_MEMORY_H 62 | 63 | /* Define to 1 if you have the `memset' function. */ 64 | #undef HAVE_MEMSET 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #undef HAVE_NCURSESW_NCURSES_H 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_NCURSES_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_NCURSES_NCURSES_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_NETDB_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_NETINET_IN_H 80 | 81 | /* Define to 1 if the system has the type `ptrdiff_t'. */ 82 | #undef HAVE_PTRDIFF_T 83 | 84 | /* Define to 1 if you have the `realloc' function. */ 85 | #undef HAVE_REALLOC 86 | 87 | /* Define to 1 if you have the `realpath' function. */ 88 | #undef HAVE_REALPATH 89 | 90 | /* Define to 1 if you have the `regcomp' function. */ 91 | #undef HAVE_REGCOMP 92 | 93 | /* Define to 1 if you have the `setlocale' function. */ 94 | #undef HAVE_SETLOCALE 95 | 96 | /* Define to 1 if `stat' has the bug that it succeeds when given the 97 | zero-length file name argument. */ 98 | #undef HAVE_STAT_EMPTY_STRING_BUG 99 | 100 | /* Define to 1 if you have the header file. */ 101 | #undef HAVE_STDDEF_H 102 | 103 | /* Define to 1 if you have the header file. */ 104 | #undef HAVE_STDINT_H 105 | 106 | /* Define to 1 if you have the header file. */ 107 | #undef HAVE_STDLIB_H 108 | 109 | /* Define to 1 if you have the `strchr' function. */ 110 | #undef HAVE_STRCHR 111 | 112 | /* Define to 1 if you have the `strdup' function. */ 113 | #undef HAVE_STRDUP 114 | 115 | /* Define to 1 if you have the `strerror' function. */ 116 | #undef HAVE_STRERROR 117 | 118 | /* Define to 1 if you have the `strftime' function. */ 119 | #undef HAVE_STRFTIME 120 | 121 | /* Define to 1 if you have the header file. */ 122 | #undef HAVE_STRINGS_H 123 | 124 | /* Define to 1 if you have the header file. */ 125 | #undef HAVE_STRING_H 126 | 127 | /* Define to 1 if you have the `strrchr' function. */ 128 | #undef HAVE_STRRCHR 129 | 130 | /* Define to 1 if you have the `strstr' function. */ 131 | #undef HAVE_STRSTR 132 | 133 | /* Define to 1 if you have the `strtol' function. */ 134 | #undef HAVE_STRTOL 135 | 136 | /* Define to 1 if you have the `strtoull' function. */ 137 | #undef HAVE_STRTOULL 138 | 139 | /* Define to 1 if you have the header file. */ 140 | #undef HAVE_SYS_SOCKET_H 141 | 142 | /* Define to 1 if you have the header file. */ 143 | #undef HAVE_SYS_STAT_H 144 | 145 | /* Define to 1 if you have the header file. */ 146 | #undef HAVE_SYS_TYPES_H 147 | 148 | /* Define to 1 if you have the header file. */ 149 | #undef HAVE_UNISTD_H 150 | 151 | /* "Build using ZLIB" */ 152 | #undef HAVE_ZLIB 153 | 154 | /* Define to 1 if `lstat' dereferences a symlink specified with a trailing 155 | slash. */ 156 | #undef LSTAT_FOLLOWS_SLASHED_SYMLINK 157 | 158 | /* Define to 1 if your C compiler doesn't accept -c and -o together. */ 159 | #undef NO_MINUS_C_MINUS_O 160 | 161 | /* Name of package */ 162 | #undef PACKAGE 163 | 164 | /* Define to the address where bug reports for this package should be sent. */ 165 | #undef PACKAGE_BUGREPORT 166 | 167 | /* Define to the full name of this package. */ 168 | #undef PACKAGE_NAME 169 | 170 | /* Define to the full name and version of this package. */ 171 | #undef PACKAGE_STRING 172 | 173 | /* Define to the one symbol short name of this package. */ 174 | #undef PACKAGE_TARNAME 175 | 176 | /* Define to the home page for this package. */ 177 | #undef PACKAGE_URL 178 | 179 | /* Define to the version of this package. */ 180 | #undef PACKAGE_VERSION 181 | 182 | /* Define to 1 if you have the ANSI C header files. */ 183 | #undef STDC_HEADERS 184 | 185 | /* "Build using on-disk B+ Tree database" */ 186 | #undef TCB_BTREE 187 | 188 | /* "Build using on-memory hash database" */ 189 | #undef TCB_MEMHASH 190 | 191 | /* Define to 1 if your declares `struct tm'. */ 192 | #undef TM_IN_SYS_TIME 193 | 194 | /* Version number of package */ 195 | #undef VERSION 196 | 197 | /* Debug option */ 198 | #undef _DEBUG 199 | 200 | /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ 201 | #undef _LARGEFILE_SOURCE 202 | 203 | /* Define to empty if `const' does not conform to ANSI C. */ 204 | #undef const 205 | 206 | /* Define to `long int' if does not define. */ 207 | #undef off_t 208 | 209 | /* Define to `unsigned int' if does not define. */ 210 | #undef size_t 211 | -------------------------------------------------------------------------------- /src/gdns.c: -------------------------------------------------------------------------------- 1 | /** 2 | * gdns.c -- hosts resolver 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #define _MULTI_THREADED 23 | #ifdef __FreeBSD__ 24 | #include 25 | #endif 26 | 27 | #if HAVE_CONFIG_H 28 | #include 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "gdns.h" 47 | 48 | #ifdef HAVE_LIBTOKYOCABINET 49 | #include "tcabdb.h" 50 | #else 51 | #include "glibht.h" 52 | #endif 53 | 54 | #include "error.h" 55 | #include "goaccess.h" 56 | #include "util.h" 57 | #include "xmalloc.h" 58 | 59 | GDnsThread gdns_thread; 60 | static GDnsQueue *gdns_queue; 61 | 62 | /* initialize queue */ 63 | void 64 | gqueue_init (GDnsQueue * q, int capacity) 65 | { 66 | q->head = 0; 67 | q->tail = -1; 68 | q->size = 0; 69 | q->capacity = capacity; 70 | } 71 | 72 | /* get current size of queue */ 73 | int 74 | gqueue_size (GDnsQueue * q) 75 | { 76 | return q->size; 77 | } 78 | 79 | /* is the queue empty */ 80 | int 81 | gqueue_empty (GDnsQueue * q) 82 | { 83 | return q->size == 0; 84 | } 85 | 86 | /* is the queue full */ 87 | int 88 | gqueue_full (GDnsQueue * q) 89 | { 90 | return q->size == q->capacity; 91 | } 92 | 93 | /* destroy queue */ 94 | void 95 | gqueue_destroy (GDnsQueue * q) 96 | { 97 | free (q); 98 | } 99 | 100 | /* add item to the queue */ 101 | int 102 | gqueue_enqueue (GDnsQueue * q, char *item) 103 | { 104 | if (gqueue_full (q)) 105 | return -1; 106 | 107 | q->tail = (q->tail + 1) % q->capacity; 108 | strcpy (q->buffer[q->tail], item); 109 | q->size++; 110 | return 0; 111 | } 112 | 113 | int 114 | gqueue_find (GDnsQueue * q, const char *item) 115 | { 116 | int i; 117 | if (gqueue_empty (q)) 118 | return 0; 119 | 120 | for (i = 0; i < q->size; i++) { 121 | if (strcmp (item, q->buffer[i]) == 0) 122 | return 1; 123 | } 124 | return 0; 125 | } 126 | 127 | /* remove an item from the queue */ 128 | char * 129 | gqueue_dequeue (GDnsQueue * q) 130 | { 131 | char *item; 132 | if (gqueue_empty (q)) 133 | return NULL; 134 | 135 | item = q->buffer[q->head]; 136 | q->head = (q->head + 1) % q->capacity; 137 | q->size--; 138 | return item; 139 | } 140 | 141 | /* get the corresponding host given an address */ 142 | static char * 143 | reverse_host (const struct sockaddr *a, socklen_t length) 144 | { 145 | char h[H_SIZE]; 146 | int flags, st; 147 | 148 | flags = NI_NAMEREQD; 149 | st = getnameinfo (a, length, h, H_SIZE, NULL, 0, flags); 150 | if (!st) 151 | return alloc_string (h); 152 | return alloc_string (gai_strerror (st)); 153 | } 154 | 155 | /* determine if IPv4 or IPv6 and resolve */ 156 | char * 157 | reverse_ip (char *str) 158 | { 159 | union 160 | { 161 | struct sockaddr addr; 162 | struct sockaddr_in6 addr6; 163 | struct sockaddr_in addr4; 164 | } a; 165 | 166 | if (str == NULL || *str == '\0') 167 | return NULL; 168 | 169 | memset (&a, 0, sizeof (a)); 170 | if (1 == inet_pton (AF_INET, str, &a.addr4.sin_addr)) { 171 | a.addr4.sin_family = AF_INET; 172 | return reverse_host (&a.addr, sizeof (a.addr4)); 173 | } else if (1 == inet_pton (AF_INET6, str, &a.addr6.sin6_addr)) { 174 | a.addr6.sin6_family = AF_INET6; 175 | return reverse_host (&a.addr, sizeof (a.addr6)); 176 | } 177 | return NULL; 178 | } 179 | 180 | /* producer */ 181 | void 182 | dns_resolver (char *addr) 183 | { 184 | pthread_mutex_lock (&gdns_thread.mutex); 185 | if (!gqueue_full (gdns_queue) && !gqueue_find (gdns_queue, addr)) { 186 | #ifndef HAVE_LIBTOKYOCABINET 187 | g_hash_table_replace (ht_hostnames, g_strdup (addr), NULL); 188 | #endif 189 | gqueue_enqueue (gdns_queue, addr); 190 | pthread_cond_broadcast (&gdns_thread.not_empty); 191 | } 192 | pthread_mutex_unlock (&gdns_thread.mutex); 193 | } 194 | 195 | /* consumer */ 196 | static void 197 | dns_worker (void GO_UNUSED (*ptr_data)) 198 | { 199 | char *ip = NULL, *host = NULL; 200 | 201 | while (1) { 202 | pthread_mutex_lock (&gdns_thread.mutex); 203 | /* wait until an item has been added to the queue */ 204 | while (gqueue_empty (gdns_queue)) 205 | pthread_cond_wait (&gdns_thread.not_empty, &gdns_thread.mutex); 206 | 207 | ip = gqueue_dequeue (gdns_queue); 208 | 209 | pthread_mutex_unlock (&gdns_thread.mutex); 210 | host = reverse_ip (ip); 211 | pthread_mutex_lock (&gdns_thread.mutex); 212 | 213 | if (!active_gdns) { 214 | if (host) 215 | free (host); 216 | break; 217 | } 218 | #ifdef HAVE_LIBTOKYOCABINET 219 | tcadbput2 (ht_hostnames, ip, host); 220 | free (host); 221 | #else 222 | if (host != NULL && active_gdns) 223 | g_hash_table_replace (ht_hostnames, g_strdup (ip), host); 224 | #endif 225 | 226 | pthread_cond_signal (&gdns_thread.not_full); 227 | pthread_mutex_unlock (&gdns_thread.mutex); 228 | } 229 | } 230 | 231 | /* init queue and dns thread */ 232 | void 233 | gdns_init (void) 234 | { 235 | gdns_queue = xmalloc (sizeof (GDnsQueue)); 236 | gqueue_init (gdns_queue, QUEUE_SIZE); 237 | 238 | if (pthread_cond_init (&(gdns_thread.not_empty), NULL)) 239 | FATAL ("Failed init thread condition"); 240 | 241 | if (pthread_cond_init (&(gdns_thread.not_full), NULL)) 242 | FATAL ("Failed init thread condition"); 243 | 244 | if (pthread_mutex_init (&(gdns_thread.mutex), NULL)) 245 | FATAL ("Failed init thread mutex"); 246 | } 247 | 248 | /* destroy queue */ 249 | void 250 | gdns_free_queue (void) 251 | { 252 | gqueue_destroy (gdns_queue); 253 | } 254 | 255 | /* create a dns thread */ 256 | void 257 | gdns_thread_create (void) 258 | { 259 | int thread; 260 | 261 | active_gdns = 1; 262 | thread = 263 | pthread_create (&(gdns_thread.thread), NULL, (void *) &dns_worker, NULL); 264 | if (thread) 265 | FATAL ("Return code from pthread_create(): %d", thread); 266 | pthread_detach (gdns_thread.thread); 267 | } 268 | -------------------------------------------------------------------------------- /src/tcbtdb.c: -------------------------------------------------------------------------------- 1 | /** 2 | * tcbtdb.c -- Tokyo Cabinet database functions 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "tcbtdb.h" 30 | #include "tcabdb.h" 31 | 32 | #ifdef HAVE_LIBGEOIP 33 | #include "geolocation.h" 34 | #endif 35 | 36 | #include "error.h" 37 | #include "xmalloc.h" 38 | 39 | #ifdef TCB_BTREE 40 | char * 41 | tc_db_set_path (const char *dbname, int module) 42 | { 43 | char *path; 44 | 45 | if (conf.db_path != NULL) { 46 | path = 47 | xmalloc (snprintf (NULL, 0, "%s%dm%s", conf.db_path, module, dbname) + 1); 48 | sprintf (path, "%s%dm%s", conf.db_path, module, dbname); 49 | } else { 50 | path = 51 | xmalloc (snprintf (NULL, 0, "%s%dm%s", TC_DBPATH, module, dbname) + 1); 52 | sprintf (path, "%s%dm%s", TC_DBPATH, module, dbname); 53 | } 54 | return path; 55 | } 56 | 57 | /* set database parameters */ 58 | void 59 | tc_db_get_params (char *params, const char *path) 60 | { 61 | int len = 0; 62 | uint32_t lcnum, ncnum, lmemb, nmemb, bnum; 63 | 64 | /* copy path name to buffer */ 65 | len += snprintf (params + len, DB_PARAMS - len, "%s", path); 66 | 67 | /* caching parameters of a B+ tree database object */ 68 | lcnum = conf.cache_lcnum > 0 ? conf.cache_lcnum : TC_LCNUM; 69 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%d", "lcnum", lcnum); 70 | 71 | ncnum = conf.cache_ncnum > 0 ? conf.cache_ncnum : TC_NCNUM; 72 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%d", "ncnum", ncnum); 73 | 74 | /* set the size of the extra mapped memory */ 75 | if (conf.xmmap > 0) 76 | len += 77 | snprintf (params + len, DB_PARAMS - len, "#%s=%ld", "xmsiz", 78 | (long) conf.xmmap); 79 | 80 | lmemb = conf.tune_lmemb > 0 ? conf.tune_lmemb : TC_LMEMB; 81 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%d", "lmemb", lmemb); 82 | 83 | nmemb = conf.tune_nmemb > 0 ? conf.tune_nmemb : TC_NMEMB; 84 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%d", "nmemb", nmemb); 85 | 86 | bnum = conf.tune_bnum > 0 ? conf.tune_bnum : TC_BNUM; 87 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%d", "bnum", bnum); 88 | 89 | /* compression */ 90 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%c", "opts", 'l'); 91 | 92 | if (conf.compression == TC_BZ2) { 93 | len += snprintf (params + len, DB_PARAMS - len, "%c", 'b'); 94 | } else if (conf.compression == TC_ZLIB) { 95 | len += snprintf (params + len, DB_PARAMS - len, "%c", 'd'); 96 | } 97 | 98 | /* open flags */ 99 | len += snprintf (params + len, DB_PARAMS - len, "#%s=%s", "mode", "wc"); 100 | if (!conf.load_from_disk) 101 | len += snprintf (params + len, DB_PARAMS - len, "%c", 't'); 102 | 103 | LOG_DEBUG (("%s\n", path)); 104 | LOG_DEBUG (("params: %s\n", params)); 105 | } 106 | 107 | /* Open the database handle */ 108 | TCBDB * 109 | tc_bdb_create (const char *dbname, int module) 110 | { 111 | TCBDB *bdb; 112 | char *path = NULL; 113 | int ecode; 114 | uint32_t lcnum, ncnum, lmemb, nmemb, bnum, flags; 115 | 116 | path = tc_db_set_path (dbname, module); 117 | bdb = tcbdbnew (); 118 | 119 | lcnum = conf.cache_lcnum > 0 ? conf.cache_lcnum : TC_LCNUM; 120 | ncnum = conf.cache_ncnum > 0 ? conf.cache_ncnum : TC_NCNUM; 121 | 122 | /* set the caching parameters of a B+ tree database object */ 123 | if (!tcbdbsetcache (bdb, lcnum, ncnum)) { 124 | free (path); 125 | FATAL ("Unable to set TCB cache"); 126 | } 127 | 128 | /* set the size of the extra mapped memory */ 129 | if (conf.xmmap > 0 && !tcbdbsetxmsiz (bdb, conf.xmmap)) { 130 | free (path); 131 | FATAL ("Unable to set TCB xmmap."); 132 | } 133 | 134 | lmemb = conf.tune_lmemb > 0 ? conf.tune_lmemb : TC_LMEMB; 135 | nmemb = conf.tune_nmemb > 0 ? conf.tune_nmemb : TC_NMEMB; 136 | bnum = conf.tune_bnum > 0 ? conf.tune_bnum : TC_BNUM; 137 | 138 | /* compression */ 139 | flags = BDBTLARGE; 140 | if (conf.compression == TC_BZ2) { 141 | flags |= BDBTBZIP; 142 | } else if (conf.compression == TC_ZLIB) { 143 | flags |= BDBTDEFLATE; 144 | } 145 | 146 | /* set the tuning parameters */ 147 | tcbdbtune (bdb, lmemb, nmemb, bnum, 8, 10, flags); 148 | 149 | /* open flags */ 150 | flags = BDBOWRITER | BDBOCREAT; 151 | if (!conf.load_from_disk) 152 | flags |= BDBOTRUNC; 153 | 154 | /* attempt to open the database */ 155 | if (!tcbdbopen (bdb, path, flags)) { 156 | free (path); 157 | ecode = tcbdbecode (bdb); 158 | 159 | FATAL ("%s", tcbdberrmsg (ecode)); 160 | } 161 | free (path); 162 | 163 | return bdb; 164 | } 165 | 166 | /* Close the database handle */ 167 | int 168 | tc_bdb_close (void *db, char *dbname) 169 | { 170 | TCBDB *bdb = db; 171 | int ecode; 172 | 173 | if (bdb == NULL) 174 | return 1; 175 | 176 | /* close the database */ 177 | if (!tcbdbclose (bdb)) { 178 | ecode = tcbdbecode (bdb); 179 | FATAL ("%s", tcbdberrmsg (ecode)); 180 | } 181 | /* delete the object */ 182 | tcbdbdel (bdb); 183 | 184 | /* remove database file */ 185 | if (!conf.keep_db_files && !conf.load_from_disk && !tcremovelink (dbname)) 186 | LOG_DEBUG (("Unable to remove DB: %s\n", dbname)); 187 | free (dbname); 188 | 189 | return 0; 190 | } 191 | 192 | static int 193 | is_value_in_tclist (TCLIST * tclist, void *value) 194 | { 195 | int i, sz; 196 | int *val; 197 | 198 | if (!tclist) 199 | return 0; 200 | 201 | for (i = 0; i < tclistnum (tclist); ++i) { 202 | val = (int *) tclistval (tclist, i, &sz); 203 | if (find_host_agent_in_list (value, val)) 204 | return 1; 205 | } 206 | 207 | return 0; 208 | } 209 | 210 | int 211 | ht_insert_host_agent (TCBDB * bdb, int data_nkey, int agent_nkey) 212 | { 213 | TCLIST *list; 214 | int in_list = 0; 215 | 216 | if (bdb == NULL) 217 | return (EINVAL); 218 | 219 | if ((list = tcbdbget4 (bdb, &data_nkey, sizeof (int))) != NULL) { 220 | if (is_value_in_tclist (list, &agent_nkey)) 221 | in_list = 1; 222 | tclistdel (list); 223 | } 224 | 225 | if (!in_list && 226 | tcbdbputdup (bdb, &data_nkey, sizeof (int), &agent_nkey, sizeof (int))) 227 | return 0; 228 | 229 | return 1; 230 | } 231 | #endif 232 | -------------------------------------------------------------------------------- /src/output.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #if HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #ifndef OUTPUT_H_INCLUDED 26 | #define OUTPUT_H_INCLUDED 27 | 28 | #define OUTPUT_N 10 29 | #define REP_TITLE "Server Statistics" 30 | 31 | #include "commons.h" 32 | #include "parser.h" 33 | 34 | #define GO_LOGO "iVBORw0KGgoAAAANSUhEUgAAAMgAAAAeCAYAAABpP1GsAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAABkBJREFUeNrsXMtV40gUvcyZfWsmAdQRoIkAMYvaYiJAjsAmghYR4I4AEQFmW4uxiABNBC0SGJyBZ+Fb4+dHlZHdxoNN3XN0LImn+t73K5U4ms1miIiI8OOXOAQREWH8uu8dMMbsopobABmAKwDNAcz71vpjrY0e5IMpxMwYE4oLvwGY8XebyADkAJIVMkMAL5R7L2yrf136ExFDrK3ilITL4lDEECviNfoAvgOo41BEBdkn5LTuLvSpSeRpQPacXqAF8ABgvCKk+gLgb8r0ABzzuRZACuASwCOvByz3AUDlqT/1yAwAPPO8K1y9GT1aA+BuRa5RsM8Q9XZBAeDUGJO6Oqy1jTGmAHBsrb3m+Tn7emet3Tvj8RlCrFuSpSZRSwA/PPH3LYAJJ94py8kKctxQKdykX7LsVBC1ZL7wg+VlfG7iyQmeqHQJn5nw+csN8pQeSduwrU+B3OiGR8JnbnmsQsLybkWZhRjPSwClMWbCslP+fWKM6UUPsrtkfRKwnhp/KGs9JRELACNBqoKEOhPySSDBvaHMWcATaa/Up2V25HJJslOue/5Nyk02HJor1aZHlj/whH8JgK+Uz4SBuFsRKt5TtgLQd6tYxpjEV7a1dmqMGXLMBis8cvQg7xA66cOnIJrAD/w9V+ESAFx4lElPurOwXZQDVLpKlDcWST1Eu7Xc9Ybjotvk6vNZ72shL+s/D5TtFLulMv8Ha62u91rcq0RfY4i1C1hrj6y1RwDkUQZCgiGt4ywQ3rhYve0Qvjjr2WxIWH19qogcklsHBS39C/scQhswHtkKo4SOXmC6QnmignwQuJDmhmS4YAiiZboSMqVcEfBWHwH39HIJ+3q2xbK/bEF5Yw7ygfBNJMvXATffrshffPH9Mcu73RL5nteo/y30xMLBJm1LA57lPdoaPcgHQCYSVQQS7xaLZdm3VllaKlpDRRtuoY21ILds2+UGZZ2oMkMLDTq803U+qvws87T1UyjJoXsQR2S3gpMz3PJ5BheanJAgqUqqtfyEHmrcIXd5S+lGJOIT85u3lNWX7D5i/k7G5SDf1aKCD0Px7IDlymR9iMWK3W+qrRMA18aYlgpUW2ubQyPQoXsQZ+17TFbv4V8dGjM/AcOniVCWkNUfdSBgV1yx3kT89t9QkFIdp+yHU7AXzN+/NAgv2fYF2V1oduFJtKeetqZYvDu6wYHu6zra9+9BOu7mzTiB9Rqyzf+cjPao0NUbyhLKJdI1+pCLUNM3Hi3COw+wj2/IY4j1OtR6D9ltIfEQ0JcPrBO2rRP21RuOR33o293jZsWPgQE9xlhY5pzEreLwRAX57HimBymFByiZaEfscw6yoy/6Dg2JyBEifgLvHeJFD7KMckWMXpPU7heYr4wdqeS46FBuxnt5IPEd8SiUTC6eG7GcjGHYEIv3FY1QxEwl67UnxxjGqfcjflG4jG+CQC1JlZP4OQnr3qSngnCjgIKkguA5FcrtBzsV15K0Tjkqz/M5FkvBA/72hAIWfNYpxFi1FVjeZ5XEKY8eZB08YvEx01Tcb7FYFeqTqFPhHbRsqSy+U6SvJGtGMg+VVa+w/KKuFCRv+GyiPAqEVxl6PI3GVNSX4hPtq9qqghhj3OD+A+B3MbiJOvfd27Vsi+V9RPp8KixmSLYWFrzgdSHI2tLDuBeNkozSAzjPIJVOErrwhF7ufob5y8lUhUDubz2Rv0jvtU6IlAjFSbC8Fy3d0XxKTvn41blcY8ymbWitte3PeBA3eX8B+FNMVqbOffd2LVsJ4vnOGxFehGRzRZQ04GFc/F9iviGwUEryqMKiUoU3lQiTXC6S8H4tiJ+KZ0uhIC2W90ZN0e0FaAL/NvZUhJHFjuZTcsrHr120oUKHJfS4ivU6YU2EVa7FdUuCDjmw7rwQYVWuLLojdY7FZ78jZb2HWHzRBzFphVCaSniPQtThFDNXCqBDOGdFR0KmxWLfGbCHHzPFVazd44R5QsvYP8d8v9GIBC2E0iTC8raBEEZ6IqcgTinGQsFcblELso4x/7LPKcxYJekjlZOkyltN1XVP5U0VywytvEVED/IKOp9IBVmnnvsVlv9bissPmg716OTfkbhWq2eVp95WhGEFwsvTGoWnL7LO6EG2rSAREYeMfwcAaP5CPgSdRcIAAAAASUVORK5CYII=" 35 | 36 | typedef struct GOutput_ 37 | { 38 | GModule module; 39 | void (*render) (FILE * fp, GHolder * h, int processed, int max_hit, 40 | int max_vis, const struct GOutput_ *); 41 | void (*metrics_callback) (GMetrics * metrics); 42 | const char *clabel; /* column label */ 43 | int8_t visitors; 44 | int8_t hits; 45 | int8_t percent; 46 | int8_t bw; 47 | int8_t avgts; 48 | int8_t protocol; 49 | int8_t method; 50 | int8_t data; 51 | int8_t graph; 52 | int8_t sub_graph; 53 | } GOutput; 54 | 55 | void output_html (GLog * logger, GHolder * holder); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.59) 5 | AC_INIT([goaccess], [0.9.2], [goaccess@prosoftcorp.com], [], [http://goaccess.io]) 6 | AM_INIT_AUTOMAKE 7 | AC_CONFIG_SRCDIR([src/goaccess.c]) 8 | AC_CONFIG_HEADERS([src/config.h]) 9 | 10 | # Use empty CFLAGS by default so autoconf does not add 11 | # CFLAGS="-O2 -g" 12 | : ${CFLAGS=""} 13 | 14 | # Checks for programs. 15 | AC_PROG_CC 16 | AM_PROG_CC_C_O 17 | 18 | # pthread 19 | AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([pthread is missing])]) 20 | CFLAGS="-pthread" 21 | 22 | # DEBUG 23 | AC_ARG_ENABLE(debug, [ --enable-debug Create a debug build. Default is disabled], 24 | [debug="$enableval"], debug=no) 25 | 26 | if test "$debug" = "yes"; then 27 | AC_DEFINE([_DEBUG], 1, [Debug option]) 28 | fi 29 | AM_CONDITIONAL([DEBUG], [test "x$debug" = "xyes"]) 30 | 31 | # Handle rdynamic only on systems using GNU ld 32 | AC_CANONICAL_HOST 33 | AC_MSG_CHECKING([whether to build with rdynamic for GNU ld]) 34 | AS_CASE([$host_os], 35 | [*darwin*|*cygwin*|*aix*|*mingw*], [with_rdyanimc=no], 36 | [with_rdyanimc=yes]) 37 | AC_MSG_RESULT([$with_rdyanimc]) 38 | AM_CONDITIONAL([WITH_RDYNAMIC], [test "x$with_rdyanimc" = "xyes"]) 39 | 40 | # GeoIP 41 | AC_ARG_ENABLE(geoip, [ --enable-geoip Enable GeoIP country lookup. Default is disabled], 42 | [geoip="$enableval"], geoip=no) 43 | 44 | if test "$geoip" = "yes"; then 45 | AC_CHECK_LIB([GeoIP], [GeoIP_new], [], 46 | [AC_MSG_ERROR([*** Missing development files for the GeoIP library])]) 47 | fi 48 | AM_CONDITIONAL([GEOLOCATION], [test "x$geoip" = "xyes"]) 49 | 50 | # UTF8 51 | AC_ARG_ENABLE(utf8, [ --enable-utf8 Enable ncurses library that handles wide characters], 52 | [utf8="$enableval"], utf8=no) 53 | 54 | if test "$utf8" = "yes"; then 55 | AC_CHECK_LIB([ncursesw], [mvaddwstr], [], 56 | [AC_MSG_ERROR([*** Missing development libraries for ncursesw])]) 57 | 58 | have_ncurses="yes" 59 | AC_CHECK_HEADERS([ncursesw/ncurses.h],[have_ncurses=yes], [], [ 60 | #ifdef HAVE_NCURSESW_NCURSES_H 61 | #include 62 | #endif 63 | ]) 64 | 65 | AC_CHECK_HEADERS([ncurses.h],[have_ncurses=yes], [], [ 66 | #ifdef HAVE_NCURSES_H 67 | #include 68 | #endif 69 | ]) 70 | 71 | if test "$have_ncurses" != "yes"; then 72 | AC_MSG_ERROR([Missing ncursesw header file]) 73 | fi 74 | else 75 | AC_CHECK_LIB([ncurses], [refresh], [], 76 | [AC_MSG_ERROR([*** Missing development libraries for ncurses])]) 77 | 78 | have_ncurses="yes" 79 | AC_CHECK_HEADERS([ncurses/ncurses.h],[have_ncurses=yes], [], [ 80 | #ifdef HAVE_NCURSES_NCURSES_H 81 | #include 82 | #endif 83 | ]) 84 | 85 | AC_CHECK_HEADERS([ncurses.h],[have_ncurses=yes], [], [ 86 | #ifdef HAVE_NCURSES_H 87 | #include 88 | #endif 89 | ]) 90 | 91 | AC_CHECK_HEADERS([curses.h],[have_ncurses=yes], [], [ 92 | #ifdef HAVE_CURSES_H 93 | #include 94 | #endif 95 | ]) 96 | 97 | if test "$have_ncurses" != "yes"; then 98 | AC_MSG_ERROR([Missing ncursesw header file]) 99 | fi 100 | fi 101 | 102 | # Tokyo Cabinet 103 | AC_ARG_ENABLE(tcb, [ --enable-tcb Enable TokyoCabinet database. Default is disabled], 104 | [tcb="$enableval"], tcb=no) 105 | 106 | WITH_TC=no 107 | if test "$tcb" = "memhash"; then 108 | WITH_TC=yes 109 | AC_DEFINE([TCB_MEMHASH], [1], ["Build using on-memory hash database"]) 110 | elif test "$tcb" = "btree"; then 111 | AC_DEFINE([TCB_BTREE], [1], ["Build using on-disk B+ Tree database"]) 112 | WITH_TC=yes 113 | fi 114 | 115 | if test "$WITH_TC" = "yes"; then 116 | AC_CHECK_LIB([tokyocabinet], [tchdbnew], [], 117 | [AC_MSG_ERROR([*** Missing development libraries for Tokyo Cabinet Database])]) 118 | 119 | AC_ARG_ENABLE([zlib], [ --disable-zlib Build without ZLIB compression], 120 | [zlib="$enableval"], zlib=yes) 121 | 122 | if test "$zlib" = "yes"; then 123 | AC_CHECK_LIB(z, gzread, [Z_FLAG=-lz], AC_MSG_ERROR([ 124 | *** zlib is required. If zlib compression is not needed 125 | *** you can use --disable-zlib. 126 | *** Debian based distributions zlib1g-dev 127 | *** Red Hat based distributions zlib-devel 128 | ])) 129 | AC_DEFINE([HAVE_ZLIB], [1], ["Build using ZLIB"]) 130 | CFLAGS="$CFLAGS $Z_FLAG" 131 | fi 132 | 133 | AC_ARG_ENABLE([bzip], [ --disable-bzip Build without BZIP2 compression], 134 | [bz2="$enableval"], bz2=yes) 135 | 136 | if test "$bz2" = "yes"; then 137 | AC_CHECK_LIB(bz2, BZ2_bzopen, [BZ2_FLAG=-lbz2], AC_MSG_ERROR([ 138 | *** BZIP2 is required. If BZIP2 compression is not needed 139 | *** you can use --disable-bzip. 140 | *** Debian based distributions libbz2-dev 141 | *** Red Hat based distributions bzip2-devel 142 | ])) 143 | AC_DEFINE([HAVE_BZ2], [1], ["Build using BZ2"]) 144 | CFLAGS="$CFLAGS $BZ2_FLAG" 145 | fi 146 | 147 | CFLAGS="$CFLAGS -ltokyocabinet -lrt -lc" 148 | 149 | # GLib otherwise 150 | else 151 | # Check for pkg-config program, used for configuring some libraries. 152 | m4_define_default([PKG_PROG_PKG_CONFIG], 153 | [AC_MSG_CHECKING([pkg-config]) 154 | AC_MSG_RESULT([no])]) 155 | 156 | PKG_PROG_PKG_CONFIG 157 | 158 | # If pkg-config autoconf support isn't installed, define its autoconf macro. 159 | m4_define_default([PKG_CHECK_MODULES], 160 | [AC_MSG_CHECKING([$1]) 161 | AC_MSG_RESULT([no]) 162 | $4]) 163 | 164 | AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no]) 165 | 166 | AS_IF([test "x$PKG_CONFIG" = "xno"],[ 167 | AC_MSG_ERROR([ 168 | *** pkg-config script could not be found. Make sure it is 169 | *** in your path, or set the PKG_CONFIG environment variable 170 | *** to the full path to pkg-config. Otherwise, reinstall glib2 171 | *** development files (libglib2.0-dev)]) 172 | ]) 173 | 174 | PKG_CHECK_MODULES(GLIB2, glib-2.0, [], AC_MSG_ERROR([*** Missing development libraries for GLib])) 175 | AC_SUBST(GLIB2_CFLAGS) 176 | AC_SUBST(GLIB2_LIBS) 177 | AC_CHECK_LIB([glib-2.0], [g_list_append], [], [AC_MSG_ERROR([*** Missing development libraries for GLib])]) 178 | fi 179 | AM_CONDITIONAL([TCB], [test "$WITH_TC" = "yes"]) 180 | 181 | if test "$tcb" = "memhash"; then 182 | storage="On-memory Hash Database (Tokyo Cabinet)" 183 | elif test "$tcb" = "btree"; then 184 | storage="On-disk B+ Tree Database (Tokyo Cabinet)" 185 | else 186 | storage="On-memory Hash Database (GLib)" 187 | fi 188 | 189 | # Solaris 190 | AC_CHECK_LIB([socket], [socket]) 191 | AC_CHECK_LIB([nsl], [gethostbyname]) 192 | 193 | # Checks for header files. 194 | AC_HEADER_STDC 195 | AC_CHECK_HEADERS([netinet/in.h]) 196 | AC_CHECK_HEADERS([sys/socket.h]) 197 | AC_CHECK_HEADERS([arpa/inet.h]) 198 | AC_CHECK_HEADERS([locale.h]) 199 | AC_CHECK_HEADERS([netdb.h]) 200 | AC_CHECK_HEADERS([stdint.h]) 201 | AC_CHECK_HEADERS([stdlib.h]) 202 | AC_CHECK_HEADERS([string.h]) 203 | AC_CHECK_HEADERS([unistd.h]) 204 | AC_CHECK_HEADERS([stddef.h]) 205 | 206 | # Checks for typedefs, structures, and compiler characteristics. 207 | AC_C_CONST 208 | AC_TYPE_OFF_T 209 | AC_TYPE_SIZE_T 210 | AC_STRUCT_TM 211 | AC_CHECK_TYPES([ptrdiff_t]) 212 | 213 | # Checks for library functions. 214 | AC_FUNC_STRTOD 215 | AC_FUNC_FSEEKO 216 | AC_FUNC_MEMCMP 217 | AC_FUNC_STAT 218 | AC_FUNC_STRFTIME 219 | AC_CHECK_FUNCS([regcomp]) 220 | AC_CHECK_FUNCS([strtoull]) 221 | AC_CHECK_FUNCS([memmove]) 222 | AC_CHECK_FUNCS([floor]) 223 | AC_CHECK_FUNCS([gethostbyaddr]) 224 | AC_CHECK_FUNCS([gethostbyname]) 225 | AC_CHECK_FUNCS([memset]) 226 | AC_CHECK_FUNCS([setlocale]) 227 | AC_CHECK_FUNCS([strchr]) 228 | AC_CHECK_FUNCS([strdup]) 229 | AC_CHECK_FUNCS([strerror]) 230 | AC_CHECK_FUNCS([strrchr]) 231 | AC_CHECK_FUNCS([strstr]) 232 | AC_CHECK_FUNCS([strtol]) 233 | AC_CHECK_FUNCS([realpath]) 234 | AC_CHECK_FUNCS([malloc]) 235 | AC_CHECK_FUNCS([realloc]) 236 | 237 | AC_CONFIG_FILES([Makefile]) 238 | AC_OUTPUT 239 | 240 | cat << EOF 241 | 242 | Your build configuration: 243 | 244 | CFLAGS = $CFLAGS 245 | storage: $storage 246 | prefix: $prefix 247 | package: $PACKAGE_NAME 248 | version: $VERSION 249 | bugs: $PACKAGE_BUGREPORT 250 | 251 | EOF 252 | -------------------------------------------------------------------------------- /src/opesys.c: -------------------------------------------------------------------------------- 1 | /** 2 | * opesys.c -- functions for dealing with operating systems 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "opesys.h" 29 | 30 | #include "settings.h" 31 | #include "util.h" 32 | #include "xmalloc.h" 33 | 34 | /* {"search string", "belongs to"} */ 35 | static const char *os[][2] = { 36 | {"Android", "Android"}, 37 | {"Windows NT 6.4", "Windows"}, 38 | {"Windows NT 6.3; ARM", "Windows"}, 39 | {"Windows NT 6.3", "Windows"}, 40 | {"Windows NT 6.2; ARM", "Windows"}, 41 | {"Windows NT 6.2", "Windows"}, 42 | {"Windows NT 6.1", "Windows"}, 43 | {"Windows NT 6.0", "Windows"}, 44 | {"Windows NT 5.2", "Windows"}, 45 | {"Windows NT 5.1", "Windows"}, 46 | {"Windows NT 5.01", "Windows"}, 47 | {"Windows NT 5.0", "Windows"}, 48 | {"Windows NT 4.0", "Windows"}, 49 | {"Windows NT", "Windows"}, 50 | {"Win 9x 4.90", "Windows"}, 51 | {"Windows 98", "Windows"}, 52 | {"Windows 95", "Windows"}, 53 | {"Windows CE", "Windows"}, 54 | {"Windows Phone 8.1", "Windows"}, 55 | {"Windows Phone 8.0", "Windows"}, 56 | 57 | {"Googlebot", "Unix-like"}, 58 | {"bingbot", "Windows"}, 59 | 60 | {"iPad", "iOS"}, 61 | {"iPod", "iOS"}, 62 | {"iPhone", "iOS"}, 63 | {"AppleTV", "iOS"}, 64 | {"iTunes", "Macintosh"}, 65 | {"OS X", "Macintosh"}, 66 | 67 | {"Debian", "Linux"}, 68 | {"Ubuntu", "Linux"}, 69 | {"Fedora", "Linux"}, 70 | {"Mint", "Linux"}, 71 | {"SUSE", "Linux"}, 72 | {"Mandriva", "Linux"}, 73 | {"Red Hat", "Linux"}, 74 | {"Gentoo", "Linux"}, 75 | {"CentOS", "Linux"}, 76 | {"PCLinuxOS", "Linux"}, 77 | {"Linux", "Linux"}, 78 | 79 | {"FreeBSD", "BSD"}, 80 | {"NetBSD", "BSD"}, 81 | {"OpenBSD", "BSD"}, 82 | {"PlayStation", "BSD"}, 83 | 84 | {"CrOS", "Chrome OS"}, 85 | {"SunOS", "Unix-like"}, 86 | {"QNX", "Unix-like"}, 87 | {"BB10", "Unix-like"}, 88 | 89 | {"BlackBerry", "Others"}, 90 | {"Sony", "Others"}, 91 | {"AmigaOS", "Others"}, 92 | {"SymbianOS", "Others"}, 93 | {"Nokia", "Others"}, 94 | {"Nintendo", "Others"}, 95 | {"Apache", "Others"}, 96 | {"Xbox One", "Windows"}, 97 | {"Xbox", "Windows"}, 98 | }; 99 | 100 | /* get Android Codename */ 101 | static char * 102 | get_real_android (const char *droid) 103 | { 104 | if (strstr (droid, "5.0") || strstr (droid, "5.1")) 105 | return alloc_string ("Lollipop"); 106 | else if (strstr (droid, "4.4")) 107 | return alloc_string ("KitKat"); 108 | else if (strstr (droid, "4.3") || strstr (droid, "4.2") || 109 | strstr (droid, "4.1")) 110 | return alloc_string ("Jelly Bean"); 111 | else if (strstr (droid, "4.0")) 112 | return alloc_string ("Ice Cream Sandwich"); 113 | else if (strstr (droid, "3.")) 114 | return alloc_string ("Honeycomb"); 115 | else if (strstr (droid, "2.3")) 116 | return alloc_string ("Gingerbread"); 117 | else if (strstr (droid, "2.2")) 118 | return alloc_string ("Froyo"); 119 | else if (strstr (droid, "2.0") || strstr (droid, "2.1")) 120 | return alloc_string ("Eclair"); 121 | else if (strstr (droid, "1.6")) 122 | return alloc_string ("Donut"); 123 | else if (strstr (droid, "1.5")) 124 | return alloc_string ("Cupcake"); 125 | return alloc_string (droid); 126 | } 127 | 128 | /* get Windows marketing name */ 129 | static char * 130 | get_real_win (const char *win) 131 | { 132 | if (strstr (win, "6.4")) 133 | return alloc_string ("Windows 10"); 134 | else if (strstr (win, "6.3")) 135 | return alloc_string ("Windows 8.1"); 136 | else if (strstr (win, "6.3; ARM")) 137 | return alloc_string ("Windows RT"); 138 | else if (strstr (win, "6.2; ARM")) 139 | return alloc_string ("Windows RT"); 140 | else if (strstr (win, "6.2")) 141 | return alloc_string ("Windows 8"); 142 | else if (strstr (win, "6.1")) 143 | return alloc_string ("Windows 7"); 144 | else if (strstr (win, "6.0")) 145 | return alloc_string ("Windows Vista"); 146 | else if (strstr (win, "5.2")) 147 | return alloc_string ("Windows XP x64"); 148 | else if (strstr (win, "5.1")) 149 | return alloc_string ("Windows XP"); 150 | else if (strstr (win, "5.0")) 151 | return alloc_string ("Windows 2000"); 152 | return NULL; 153 | } 154 | 155 | /* get Mac OS X Codename */ 156 | static char * 157 | get_real_mac_osx (const char *osx) 158 | { 159 | if (strstr (osx, "10.10")) 160 | return alloc_string ("OS X Yosemite"); 161 | else if (strstr (osx, "10.9")) 162 | return alloc_string ("OS X Mavericks"); 163 | else if (strstr (osx, "10.8")) 164 | return alloc_string ("OS X Mountain Lion"); 165 | else if (strstr (osx, "10.7")) 166 | return alloc_string ("OS X Lion"); 167 | else if (strstr (osx, "10.6")) 168 | return alloc_string ("OS X Snow Leopard"); 169 | else if (strstr (osx, "10.5")) 170 | return alloc_string ("OS X Leopard"); 171 | else if (strstr (osx, "10.4")) 172 | return alloc_string ("OS X Tiger"); 173 | else if (strstr (osx, "10.3")) 174 | return alloc_string ("OS X Panther"); 175 | else if (strstr (osx, "10.2")) 176 | return alloc_string ("OS X Jaguar"); 177 | else if (strstr (osx, "10.1")) 178 | return alloc_string ("OS X Puma"); 179 | else if (strstr (osx, "10.0")) 180 | return alloc_string ("OS X Cheetah"); 181 | return alloc_string (osx); 182 | } 183 | 184 | static char * 185 | parse_others (char *agent, int spaces) 186 | { 187 | char *p; 188 | int space = 0; 189 | p = agent; 190 | while (*p != ';' && *p != ')' && *p != '(' && *p != '\0') { 191 | if (*p == ' ') 192 | space++; 193 | if (space > spaces) 194 | break; 195 | p++; 196 | } 197 | *p = 0; 198 | 199 | return agent; 200 | } 201 | 202 | static char * 203 | parse_osx (char *agent) 204 | { 205 | int space = 0; 206 | char *p; 207 | 208 | p = agent; 209 | while (*p != ';' && *p != ')' && *p != '(' && *p != '\0') { 210 | if (*p == '_') 211 | *p = '.'; 212 | if (*p == ' ') 213 | space++; 214 | if (space > 3) 215 | break; 216 | p++; 217 | } 218 | *p = 0; 219 | 220 | return agent; 221 | } 222 | 223 | static char * 224 | parse_android (char *agent) 225 | { 226 | char *p; 227 | p = agent; 228 | while (*p != ';' && *p != ')' && *p != '(' && *p != '\0') 229 | p++; 230 | *p = 0; 231 | 232 | return agent; 233 | } 234 | 235 | char * 236 | verify_os (const char *str, char *os_type) 237 | { 238 | char *a, *b; 239 | int spaces = 0; 240 | size_t i; 241 | 242 | if (str == NULL || *str == '\0') 243 | return NULL; 244 | 245 | for (i = 0; i < ARRAY_SIZE (os); i++) { 246 | if ((a = strstr (str, os[i][0])) == NULL) 247 | continue; 248 | 249 | xstrncpy (os_type, os[i][1], OPESYS_TYPE_LEN); 250 | /* Windows */ 251 | if ((strstr (str, "Windows")) != NULL) { 252 | return conf.real_os && (b = get_real_win (a)) ? b : xstrdup (os[i][0]); 253 | } 254 | /* Android */ 255 | if ((strstr (a, "Android")) != NULL) { 256 | a = parse_android (a); 257 | return conf.real_os ? get_real_android (a) : xstrdup (a); 258 | } 259 | /* Mac OS X */ 260 | if ((strstr (a, "OS X")) != NULL) { 261 | a = parse_osx (a); 262 | return conf.real_os ? get_real_mac_osx (a) : xstrdup (a); 263 | } 264 | /* all others */ 265 | spaces = count_matches (os[i][0], ' '); 266 | return alloc_string (parse_others (a, spaces)); 267 | } 268 | xstrncpy (os_type, "Unknown", OPESYS_TYPE_LEN); 269 | 270 | return alloc_string ("Unknown"); 271 | } 272 | -------------------------------------------------------------------------------- /src/csv.c: -------------------------------------------------------------------------------- 1 | /** 2 | * output.c -- output csv to the standard output stream 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #define _LARGEFILE_SOURCE 23 | #define _LARGEFILE64_SOURCE 24 | #define _FILE_OFFSET_BITS 64 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "csv.h" 37 | 38 | #ifdef HAVE_LIBTOKYOCABINET 39 | #include "tcabdb.h" 40 | #else 41 | #include "glibht.h" 42 | #endif 43 | 44 | #include "ui.h" 45 | #include "util.h" 46 | 47 | static void print_csv_data (FILE * fp, GHolder * h, int processed); 48 | 49 | static GCSV paneling[] = { 50 | {VISITORS, print_csv_data}, 51 | {REQUESTS, print_csv_data}, 52 | {REQUESTS_STATIC, print_csv_data}, 53 | {NOT_FOUND, print_csv_data}, 54 | {HOSTS, print_csv_data}, 55 | {OS, print_csv_data}, 56 | {BROWSERS, print_csv_data}, 57 | {VISIT_TIMES, print_csv_data}, 58 | {REFERRERS, print_csv_data}, 59 | {REFERRING_SITES, print_csv_data}, 60 | {KEYPHRASES, print_csv_data}, 61 | #ifdef HAVE_LIBGEOIP 62 | {GEO_LOCATION, print_csv_data}, 63 | #endif 64 | {STATUS_CODES, print_csv_data}, 65 | }; 66 | 67 | static GCSV * 68 | panel_lookup (GModule module) 69 | { 70 | int i, num_panels = ARRAY_SIZE (paneling); 71 | 72 | for (i = 0; i < num_panels; i++) { 73 | if (paneling[i].module == module) 74 | return &paneling[i]; 75 | } 76 | return NULL; 77 | } 78 | 79 | static void 80 | escape_cvs_output (FILE * fp, char *s) 81 | { 82 | while (*s) { 83 | switch (*s) { 84 | case '"': 85 | fprintf (fp, "\"\""); 86 | break; 87 | default: 88 | fputc (*s, fp); 89 | break; 90 | } 91 | s++; 92 | } 93 | } 94 | 95 | static void 96 | print_csv_sub_items (FILE * fp, GHolder * h, int idx, int processed) 97 | { 98 | GSubList *sub_list = h->items[idx].sub_list; 99 | GSubItem *iter; 100 | float percent; 101 | int i = 0; 102 | 103 | if (sub_list == NULL) 104 | return; 105 | 106 | for (iter = sub_list->head; iter; iter = iter->next, i++) { 107 | percent = get_percentage (processed, iter->metrics->hits); 108 | percent = percent < 0 ? 0 : percent; 109 | 110 | fprintf (fp, "\"%d\",", i); /* idx */ 111 | fprintf (fp, "\"%d\",", idx); /* parent idx */ 112 | fprintf (fp, "\"%s\",", module_to_id (h->module)); 113 | fprintf (fp, "\"%d\",", iter->metrics->hits); 114 | fprintf (fp, "\"%d\",", iter->metrics->visitors); 115 | fprintf (fp, "\"%4.2f%%\",", percent); 116 | fprintf (fp, "\"%lld\",", (long long) iter->metrics->bw.nbw); 117 | 118 | if (conf.serve_usecs) 119 | fprintf (fp, "\"%lld\"", (long long) iter->metrics->avgts.nts); 120 | fprintf (fp, ","); 121 | 122 | if (conf.append_method && iter->metrics->method) 123 | fprintf (fp, "\"%s\"", iter->metrics->method); 124 | fprintf (fp, ","); 125 | 126 | if (conf.append_protocol && iter->metrics->protocol) 127 | fprintf (fp, "\"%s\"", iter->metrics->protocol); 128 | fprintf (fp, ","); 129 | 130 | fprintf (fp, "\""); 131 | escape_cvs_output (fp, iter->metrics->data); 132 | fprintf (fp, "\","); 133 | fprintf (fp, "\r\n"); /* parent idx */ 134 | } 135 | } 136 | 137 | /* generate CSV unique visitors stats */ 138 | static void 139 | print_csv_data (FILE * fp, GHolder * h, int processed) 140 | { 141 | GMetrics *nmetrics; 142 | int i; 143 | 144 | for (i = 0; i < h->idx; i++) { 145 | set_data_metrics (h->items[i].metrics, &nmetrics, processed); 146 | 147 | fprintf (fp, "\"%d\",", i); /* idx */ 148 | fprintf (fp, ","); /* no parent */ 149 | fprintf (fp, "\"%s\",", module_to_id (h->module)); 150 | fprintf (fp, "\"%d\",", nmetrics->hits); 151 | fprintf (fp, "\"%d\",", nmetrics->visitors); 152 | fprintf (fp, "\"%4.2f%%\",", nmetrics->percent); 153 | fprintf (fp, "\"%lld\",", (long long) nmetrics->bw.nbw); 154 | 155 | if (conf.serve_usecs) 156 | fprintf (fp, "\"%lld\"", (long long) nmetrics->avgts.nts); 157 | fprintf (fp, ","); 158 | 159 | if (conf.append_method && nmetrics->method) 160 | fprintf (fp, "\"%s\"", nmetrics->method); 161 | fprintf (fp, ","); 162 | 163 | if (conf.append_protocol && nmetrics->protocol) 164 | fprintf (fp, "\"%s\"", nmetrics->protocol); 165 | fprintf (fp, ","); 166 | 167 | fprintf (fp, "\""); 168 | escape_cvs_output (fp, nmetrics->data); 169 | fprintf (fp, "\"\r\n"); 170 | 171 | if (h->sub_items_size) 172 | print_csv_sub_items (fp, h, i, processed); 173 | 174 | free (nmetrics); 175 | } 176 | } 177 | 178 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 179 | /* general statistics info */ 180 | static void 181 | print_csv_summary (FILE * fp, GLog * logger) 182 | { 183 | long long t = 0LL; 184 | int i = 0, total = 0; 185 | off_t log_size = 0; 186 | char now[DATE_TIME]; 187 | const char *fmt; 188 | 189 | generate_time (); 190 | strftime (now, DATE_TIME, "%Y-%m-%d %H:%M:%S", now_tm); 191 | 192 | /* generated date time */ 193 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%s\",\"%s\"\r\n"; 194 | fprintf (fp, fmt, i++, GENER_ID, now, OVERALL_DATETIME); 195 | 196 | /* total requests */ 197 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%d\",\"%s\"\r\n"; 198 | total = logger->process; 199 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_REQ); 200 | 201 | /* invalid requests */ 202 | total = logger->invalid; 203 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_FAILED); 204 | 205 | /* generated time */ 206 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%llu\",\"%s\"\r\n"; 207 | t = (long long) end_proc - start_proc; 208 | fprintf (fp, fmt, i++, GENER_ID, t, OVERALL_GENTIME); 209 | 210 | /* visitors */ 211 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%d\",\"%s\"\r\n"; 212 | total = get_ht_size_by_metric (VISITORS, MTRC_UNIQMAP); 213 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_VISITORS); 214 | 215 | /* files */ 216 | total = get_ht_size_by_metric (REQUESTS, MTRC_DATAMAP); 217 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_FILES); 218 | 219 | /* excluded hits */ 220 | total = logger->exclude_ip; 221 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_EXCL_HITS); 222 | 223 | /* referrers */ 224 | total = get_ht_size_by_metric (REFERRERS, MTRC_DATAMAP); 225 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_REF); 226 | 227 | /* not found */ 228 | total = get_ht_size_by_metric (NOT_FOUND, MTRC_DATAMAP); 229 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_NOTFOUND); 230 | 231 | /* static files */ 232 | total = get_ht_size_by_metric (REQUESTS_STATIC, MTRC_DATAMAP); 233 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_STATIC); 234 | 235 | /* log size */ 236 | if (!logger->piping) 237 | log_size = file_size (conf.ifile); 238 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%jd\",\"%s\"\r\n"; 239 | fprintf (fp, fmt, i++, GENER_ID, (intmax_t) log_size, OVERALL_LOGSIZE); 240 | 241 | /* bandwidth */ 242 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%lld\",\"%s\"\r\n"; 243 | fprintf (fp, fmt, i++, GENER_ID, logger->resp_size, OVERALL_BANDWIDTH); 244 | 245 | /* log path */ 246 | if (conf.ifile == NULL) 247 | conf.ifile = (char *) "STDIN"; 248 | 249 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%s\",\"%s\"\r\n"; 250 | fprintf (fp, fmt, i++, GENER_ID, conf.ifile, OVERALL_LOG); 251 | } 252 | 253 | #pragma GCC diagnostic warning "-Wformat-nonliteral" 254 | 255 | /* entry point to generate a a csv report writing it to the fp */ 256 | void 257 | output_csv (GLog * logger, GHolder * holder) 258 | { 259 | GModule module; 260 | FILE *fp = stdout; 261 | 262 | if (!conf.no_csv_summary) 263 | print_csv_summary (fp, logger); 264 | 265 | for (module = 0; module < TOTAL_MODULES; module++) { 266 | const GCSV *panel = panel_lookup (module); 267 | if (!panel) 268 | continue; 269 | if (ignore_panel (module)) 270 | continue; 271 | panel->render (fp, holder + module, logger->process); 272 | } 273 | 274 | fclose (fp); 275 | } 276 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2012-03-05.13; # UTC 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free 7 | # Software Foundation, Inc. 8 | # Written by Tom Tromey . 9 | # 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # This file is maintained in Automake, please report 29 | # bugs to or send patches to 30 | # . 31 | 32 | nl=' 33 | ' 34 | 35 | # We need space, tab and new line, in precisely that order. Quoting is 36 | # there to prevent tools from complaining about whitespace usage. 37 | IFS=" "" $nl" 38 | 39 | file_conv= 40 | 41 | # func_file_conv build_file lazy 42 | # Convert a $build file to $host form and store it in $file 43 | # Currently only supports Windows hosts. If the determined conversion 44 | # type is listed in (the comma separated) LAZY, no conversion will 45 | # take place. 46 | func_file_conv () 47 | { 48 | file=$1 49 | case $file in 50 | / | /[!/]*) # absolute file, and not a UNC file 51 | if test -z "$file_conv"; then 52 | # lazily determine how to convert abs files 53 | case `uname -s` in 54 | MINGW*) 55 | file_conv=mingw 56 | ;; 57 | CYGWIN*) 58 | file_conv=cygwin 59 | ;; 60 | *) 61 | file_conv=wine 62 | ;; 63 | esac 64 | fi 65 | case $file_conv/,$2, in 66 | *,$file_conv,*) 67 | ;; 68 | mingw/*) 69 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 70 | ;; 71 | cygwin/*) 72 | file=`cygpath -m "$file" || echo "$file"` 73 | ;; 74 | wine/*) 75 | file=`winepath -w "$file" || echo "$file"` 76 | ;; 77 | esac 78 | ;; 79 | esac 80 | } 81 | 82 | # func_cl_dashL linkdir 83 | # Make cl look for libraries in LINKDIR 84 | func_cl_dashL () 85 | { 86 | func_file_conv "$1" 87 | if test -z "$lib_path"; then 88 | lib_path=$file 89 | else 90 | lib_path="$lib_path;$file" 91 | fi 92 | linker_opts="$linker_opts -LIBPATH:$file" 93 | } 94 | 95 | # func_cl_dashl library 96 | # Do a library search-path lookup for cl 97 | func_cl_dashl () 98 | { 99 | lib=$1 100 | found=no 101 | save_IFS=$IFS 102 | IFS=';' 103 | for dir in $lib_path $LIB 104 | do 105 | IFS=$save_IFS 106 | if $shared && test -f "$dir/$lib.dll.lib"; then 107 | found=yes 108 | lib=$dir/$lib.dll.lib 109 | break 110 | fi 111 | if test -f "$dir/$lib.lib"; then 112 | found=yes 113 | lib=$dir/$lib.lib 114 | break 115 | fi 116 | done 117 | IFS=$save_IFS 118 | 119 | if test "$found" != yes; then 120 | lib=$lib.lib 121 | fi 122 | } 123 | 124 | # func_cl_wrapper cl arg... 125 | # Adjust compile command to suit cl 126 | func_cl_wrapper () 127 | { 128 | # Assume a capable shell 129 | lib_path= 130 | shared=: 131 | linker_opts= 132 | for arg 133 | do 134 | if test -n "$eat"; then 135 | eat= 136 | else 137 | case $1 in 138 | -o) 139 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 140 | eat=1 141 | case $2 in 142 | *.o | *.[oO][bB][jJ]) 143 | func_file_conv "$2" 144 | set x "$@" -Fo"$file" 145 | shift 146 | ;; 147 | *) 148 | func_file_conv "$2" 149 | set x "$@" -Fe"$file" 150 | shift 151 | ;; 152 | esac 153 | ;; 154 | -I) 155 | eat=1 156 | func_file_conv "$2" mingw 157 | set x "$@" -I"$file" 158 | shift 159 | ;; 160 | -I*) 161 | func_file_conv "${1#-I}" mingw 162 | set x "$@" -I"$file" 163 | shift 164 | ;; 165 | -l) 166 | eat=1 167 | func_cl_dashl "$2" 168 | set x "$@" "$lib" 169 | shift 170 | ;; 171 | -l*) 172 | func_cl_dashl "${1#-l}" 173 | set x "$@" "$lib" 174 | shift 175 | ;; 176 | -L) 177 | eat=1 178 | func_cl_dashL "$2" 179 | ;; 180 | -L*) 181 | func_cl_dashL "${1#-L}" 182 | ;; 183 | -static) 184 | shared=false 185 | ;; 186 | -Wl,*) 187 | arg=${1#-Wl,} 188 | save_ifs="$IFS"; IFS=',' 189 | for flag in $arg; do 190 | IFS="$save_ifs" 191 | linker_opts="$linker_opts $flag" 192 | done 193 | IFS="$save_ifs" 194 | ;; 195 | -Xlinker) 196 | eat=1 197 | linker_opts="$linker_opts $2" 198 | ;; 199 | -*) 200 | set x "$@" "$1" 201 | shift 202 | ;; 203 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 204 | func_file_conv "$1" 205 | set x "$@" -Tp"$file" 206 | shift 207 | ;; 208 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 209 | func_file_conv "$1" mingw 210 | set x "$@" "$file" 211 | shift 212 | ;; 213 | *) 214 | set x "$@" "$1" 215 | shift 216 | ;; 217 | esac 218 | fi 219 | shift 220 | done 221 | if test -n "$linker_opts"; then 222 | linker_opts="-link$linker_opts" 223 | fi 224 | exec "$@" $linker_opts 225 | exit 1 226 | } 227 | 228 | eat= 229 | 230 | case $1 in 231 | '') 232 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 233 | exit 1; 234 | ;; 235 | -h | --h*) 236 | cat <<\EOF 237 | Usage: compile [--help] [--version] PROGRAM [ARGS] 238 | 239 | Wrapper for compilers which do not understand '-c -o'. 240 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 241 | arguments, and rename the output as expected. 242 | 243 | If you are trying to build a whole package this is not the 244 | right script to run: please start by reading the file 'INSTALL'. 245 | 246 | Report bugs to . 247 | EOF 248 | exit $? 249 | ;; 250 | -v | --v*) 251 | echo "compile $scriptversion" 252 | exit $? 253 | ;; 254 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) 255 | func_cl_wrapper "$@" # Doesn't return... 256 | ;; 257 | esac 258 | 259 | ofile= 260 | cfile= 261 | 262 | for arg 263 | do 264 | if test -n "$eat"; then 265 | eat= 266 | else 267 | case $1 in 268 | -o) 269 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 270 | # So we strip '-o arg' only if arg is an object. 271 | eat=1 272 | case $2 in 273 | *.o | *.obj) 274 | ofile=$2 275 | ;; 276 | *) 277 | set x "$@" -o "$2" 278 | shift 279 | ;; 280 | esac 281 | ;; 282 | *.c) 283 | cfile=$1 284 | set x "$@" "$1" 285 | shift 286 | ;; 287 | *) 288 | set x "$@" "$1" 289 | shift 290 | ;; 291 | esac 292 | fi 293 | shift 294 | done 295 | 296 | if test -z "$ofile" || test -z "$cfile"; then 297 | # If no '-o' option was seen then we might have been invoked from a 298 | # pattern rule where we don't need one. That is ok -- this is a 299 | # normal compilation that the losing compiler can handle. If no 300 | # '.c' file was seen then we are probably linking. That is also 301 | # ok. 302 | exec "$@" 303 | fi 304 | 305 | # Name of file we expect compiler to create. 306 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 307 | 308 | # Create the lock directory. 309 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 310 | # that we are using for the .o file. Also, base the name on the expected 311 | # object file name, since that is what matters with a parallel build. 312 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 313 | while true; do 314 | if mkdir "$lockdir" >/dev/null 2>&1; then 315 | break 316 | fi 317 | sleep 1 318 | done 319 | # FIXME: race condition here if user kills between mkdir and trap. 320 | trap "rmdir '$lockdir'; exit 1" 1 2 15 321 | 322 | # Run the compile. 323 | "$@" 324 | ret=$? 325 | 326 | if test -f "$cofile"; then 327 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 328 | elif test -f "${cofile}bj"; then 329 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 330 | fi 331 | 332 | rmdir "$lockdir" 333 | exit $ret 334 | 335 | # Local Variables: 336 | # mode: shell-script 337 | # sh-indentation: 2 338 | # eval: (add-hook 'write-file-hooks 'time-stamp) 339 | # time-stamp-start: "scriptversion=" 340 | # time-stamp-format: "%:y-%02m-%02d.%02H" 341 | # time-stamp-time-zone: "UTC" 342 | # time-stamp-end: "; # UTC" 343 | # End: 344 | -------------------------------------------------------------------------------- /src/ui.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2009-2014 by Gerardo Orellana 3 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * A copy of the GNU General Public License is attached to this 16 | * source distribution for its full text. 17 | * 18 | * Visit http://goaccess.prosoftcorp.com for new releases. 19 | */ 20 | 21 | #ifndef UI_H_INCLUDED 22 | #define UI_H_INCLUDED 23 | 24 | #ifdef HAVE_NCURSESW_NCURSES_H 25 | #include 26 | #elif HAVE_NCURSES_NCURSES_H 27 | #include 28 | #elif HAVE_NCURSES_H 29 | #include 30 | #elif HAVE_CURSES_H 31 | #include 32 | #endif 33 | 34 | #ifdef HAVE_LIBPTHREAD 35 | #include 36 | #endif 37 | 38 | /* overall stats */ 39 | #define T_DASH "仪表盘(网站访问日志分析报表)" 40 | #define T_HEAD "日志分析报表总览" 41 | 42 | #define T_DATETIME "Date/Time" 43 | #define T_REQUESTS "请求综述" 44 | #define T_GEN_TIME "耗时" 45 | #define T_FAILED "分析失败数" 46 | #define T_UNIQUE_VIS "独立访客" 47 | #define T_UNIQUE_FIL "访问页面数" 48 | #define T_EXCLUDE_IP "排除IP的访问数" 49 | #define T_REFERRER "来源URLs数" 50 | #define T_UNIQUE404 "404页面数" 51 | #define T_STATIC_FIL "静态资源数" 52 | #define T_LOG "日志文件大小" 53 | #define T_BW "流量耗费总量" 54 | #define T_LOG_PATH "日志文件位置" 55 | 56 | /* spinner label format */ 57 | #define SPIN_FMT "%s" 58 | #define SPIN_FMTM "%s [%'d] [%'lld/s]" 59 | #define SPIN_LBL 50 60 | 61 | #define INCLUDE_BOTS " - Including spiders" 62 | 63 | /* modules */ 64 | #define VISIT_HEAD "每日独立访客" 65 | #define VISIT_DESC "相同IP/UA/DATE的访客称为独立访客" 66 | #define VISIT_ID "visitors" 67 | #define VISIT_LABEL "Visitors" 68 | 69 | #define REQUE_HEAD "请求最多的地址(URLs)" 70 | #define REQUE_DESC "按照点击数排序 - [avg. time served | protocol | method]" 71 | #define REQUE_ID "requests" 72 | #define REQUE_LABEL "Requests" 73 | 74 | #define STATI_HEAD "请求最多的静态资源 (如:jpg, png, js, css等)" 75 | #define STATI_DESC "按照点击数排序 - [avg. time served | protocol | method]" 76 | #define STATI_ID "static_requests" 77 | #define STATI_LABEL "Static Requests" 78 | 79 | #define VTIME_HEAD "时间分布" 80 | #define VTIME_DESC "按小时排序 - [avg. time served]" 81 | #define VTIME_ID "visit_time" 82 | #define VTIME_LABEL "Time" 83 | 84 | #define FOUND_HEAD "404未找到的地址(URLs)" 85 | #define FOUND_DESC "按照点击数排序- [avg. time served | protocol | method]" 86 | #define FOUND_ID "not_found" 87 | #define FOUND_LABEL "Not Found" 88 | 89 | #define HOSTS_HEAD "访客主机名或IP" 90 | #define HOSTS_DESC "按照点击数排序 - [avg. time served]" 91 | #define HOSTS_ID "hosts" 92 | #define HOSTS_LABEL "Hosts" 93 | 94 | #define OPERA_HEAD "操作系统" 95 | #define OPERA_DESC "按照点击数排序 - [avg. time served]" 96 | #define OPERA_ID "os" 97 | #define OPERA_LABEL "OS" 98 | 99 | #define BROWS_HEAD "浏览器" 100 | #define BROWS_DESC "按照点击数排序- [avg. time served]" 101 | #define BROWS_ID "browsers" 102 | #define BROWS_LABEL "Browsers" 103 | 104 | #define REFER_HEAD "来源地址(URLs)" 105 | #define REFER_DESC "按照点击数排序- [avg. time served]" 106 | #define REFER_ID "referrers" 107 | #define REFER_LABEL "Referrers" 108 | 109 | #define SITES_HEAD "来源网站域名" 110 | #define SITES_DESC "按照点击数排序 - [avg. time served]" 111 | #define SITES_ID "referring_sites" 112 | #define SITES_LABEL "Referring Sites" 113 | 114 | #define KEYPH_HEAD "Google搜索关键字" 115 | #define KEYPH_DESC "按照点击数排序 - [avg. time served]" 116 | #define KEYPH_ID "keyphrases" 117 | #define KEYPH_LABEL "Keyphrases" 118 | 119 | #define GEOLO_HEAD "访客地址分布" 120 | #define GEOLO_DESC "按照点击数排序 - [avg. time served]" 121 | #define GEOLO_ID "geolocation" 122 | #define GEOLO_LABEL "Geo Location" 123 | 124 | #define CODES_HEAD "HTTP状态码" 125 | #define CODES_DESC "按照点击数排序- [avg. time served]" 126 | #define CODES_ID "status_codes" 127 | #define CODES_LABEL "Status Codes" 128 | 129 | #define GENER_ID "general" 130 | 131 | /* overall statistics */ 132 | #define OVERALL_DATETIME "date_time" 133 | #define OVERALL_REQ "total_requests" 134 | #define OVERALL_GENTIME "generation_time" 135 | #define OVERALL_FAILED "failed_requests" 136 | #define OVERALL_VISITORS "unique_visitors" 137 | #define OVERALL_FILES "unique_files" 138 | #define OVERALL_EXCL_HITS "excluded_hits" 139 | #define OVERALL_REF "unique_referrers" 140 | #define OVERALL_NOTFOUND "unique_not_found" 141 | #define OVERALL_STATIC "unique_static_files" 142 | #define OVERALL_LOGSIZE "log_size" 143 | #define OVERALL_BANDWIDTH "bandwidth" 144 | #define OVERALL_LOG "log_path" 145 | 146 | #define FIND_HEAD "Find pattern in all views" 147 | #define FIND_DESC "Regex allowed - ^g to cancel - TAB switch case" 148 | 149 | #define MAX_CHOICES 366 150 | #define MIN_HEIGHT 7 151 | #define MIN_WIDTH 0 152 | #define MAX_HEIGHT_FOOTER 1 153 | #define MAX_HEIGHT_HEADER 6 154 | 155 | /* CONFIG DIALOG */ 156 | #define CONF_MENU_H 6 157 | #define CONF_MENU_W 48 158 | #define CONF_MENU_X 2 159 | #define CONF_MENU_Y 4 160 | #define CONF_WIN_H 20 161 | #define CONF_WIN_W 52 162 | 163 | /* FIND DIALOG */ 164 | #define FIND_DLG_HEIGHT 8 165 | #define FIND_DLG_WIDTH 50 166 | #define FIND_MAX_MATCHES 1 167 | 168 | /* COLOR SCHEME DIALOG */ 169 | #define SCHEME_MENU_H 2 170 | #define SCHEME_MENU_W 38 171 | #define SCHEME_MENU_X 2 172 | #define SCHEME_MENU_Y 4 173 | #define SCHEME_WIN_H 8 174 | #define SCHEME_WIN_W 42 175 | 176 | /* SORT DIALOG */ 177 | #define SORT_MENU_H 6 178 | #define SORT_MENU_W 38 179 | #define SORT_MENU_X 2 180 | #define SORT_MENU_Y 4 181 | #define SORT_WIN_H 13 182 | #define SORT_WIN_W 42 183 | 184 | /* AGENTS DIALOG */ 185 | #define AGENTS_MENU_X 2 186 | #define AGENTS_MENU_Y 4 187 | 188 | /* HELP DIALOG */ 189 | #define HELP_MENU_HEIGHT 12 190 | #define HELP_MENU_WIDTH 60 191 | #define HELP_MENU_X 2 192 | #define HELP_MENU_Y 4 193 | #define HELP_WIN_HEIGHT 17 194 | #define HELP_WIN_WIDTH 64 195 | 196 | /* COLORS */ 197 | #define COL_WHITE 0 198 | #define COL_BLUE 1 199 | #define COL_RED 3 200 | #define COL_BLACK 4 201 | #define COL_CYAN 5 202 | #define COL_YELLOW 6 203 | #define COL_GREEN 11 204 | #define COL_PURPLE 97 205 | 206 | #define YELLOW_BLACK 12 207 | #define BLUE_GREEN 7 208 | #define BLACK_GREEN 8 209 | #define BLACK_CYAN 9 210 | #define WHITE_RED 10 211 | 212 | #define HIGHLIGHT 1 213 | 214 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 215 | 216 | #include "commons.h" 217 | #include "sort.h" 218 | 219 | typedef enum SCHEMES 220 | { 221 | NO_COLOR, 222 | MONOCHROME, 223 | STD_GREEN 224 | } GShemes; 225 | 226 | typedef struct GFind_ 227 | { 228 | GModule module; 229 | char *pattern; 230 | int next_idx; 231 | int next_parent_idx; 232 | int next_sub_idx; 233 | int look_in_sub; 234 | int done; 235 | int icase; 236 | } GFind; 237 | 238 | typedef struct GScrollModule_ 239 | { 240 | int scroll; 241 | int offset; 242 | } GScrollModule; 243 | 244 | typedef struct GScroll_ 245 | { 246 | GScrollModule module[TOTAL_MODULES]; 247 | GModule current; 248 | int dash; 249 | int expanded; 250 | } GScroll; 251 | 252 | typedef struct GSpinner_ 253 | { 254 | const char *label; 255 | int color; 256 | int curses; 257 | int spin_x; 258 | int w; 259 | int x; 260 | int y; 261 | pthread_mutex_t mutex; 262 | pthread_t thread; 263 | unsigned int *process; 264 | WINDOW *win; 265 | enum 266 | { 267 | SPN_RUN, 268 | SPN_END 269 | } state; 270 | } GSpinner; 271 | 272 | /* *INDENT-OFF* */ 273 | GSpinner *new_gspinner (void); 274 | 275 | char *get_browser_type (char *line); 276 | char *input_string (WINDOW * win, int pos_y, int pos_x, size_t max_width, const char *str, int enable_case, int *toggle_case); 277 | const char *module_to_desc (GModule module); 278 | const char *module_to_head (GModule module); 279 | const char *module_to_id (GModule module); 280 | const char *module_to_label (GModule module); 281 | int set_host_agents (const char *addr, void (*func) (void *, void *, int), void *arr); 282 | int render_confdlg(GLog * logger, GSpinner * spinner); 283 | void close_win (WINDOW * w); 284 | void display_general (WINDOW * header_win, char *ifile, GLog *logger); 285 | void draw_header (WINDOW * win, const char *s, const char *fmt, int y, int x, int w, int color, int max_width); 286 | void end_spinner (void); 287 | void generate_time (void); 288 | void init_colors (void); 289 | void init_windows (WINDOW ** header_win, WINDOW ** main_win); 290 | void load_agent_list (WINDOW * main_win, char *addr); 291 | void load_help_popup (WINDOW * main_win); 292 | void load_schemes_win (WINDOW * main_win); 293 | void load_sort_win (WINDOW * main_win, GModule module, GSort * sort); 294 | void set_curses_spinner (GSpinner *spinner); 295 | void set_input_opts (void); 296 | void term_size (WINDOW * main_win); 297 | void ui_spinner_create (GSpinner * spinner); 298 | void update_active_module (WINDOW * header_win, GModule current); 299 | void update_header (WINDOW * header_win, int current); 300 | 301 | /* *INDENT-ON* */ 302 | #endif 303 | -------------------------------------------------------------------------------- /src/settings.c: -------------------------------------------------------------------------------- 1 | /** 2 | * settings.c -- goaccess configuration 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "settings.h" 32 | 33 | #include "error.h" 34 | #include "util.h" 35 | #include "xmalloc.h" 36 | 37 | static char **nargv; 38 | static int nargc = 0; 39 | 40 | /* *INDENT-OFF* */ 41 | static const GPreConfLog logs = { 42 | "%h %^[%d:%t %^] \"%r\" %s %b \"%R\" \"%u\"", /* NCSA */ 43 | "%^:%^ %h %^[%d:%t %^] \"%r\" %s %b \"%R\" \"%u\"", /* NCSA + VHost */ 44 | "%h %^[%d:%t %^] \"%r\" %s %b", /* CLF */ 45 | "%^:%^ %h %^[%d:%t %^] \"%r\" %s %b", /* CLF+VHost */ 46 | "%d %t %h %^ %^ %^ %m %r %^ %s %b %^ %^ %u %R", /* W3C */ 47 | "%d\\t%t\\t%^\\t%b\\t%h\\t%m\\t%^\\t%r\\t%s\\t%R\\t%u\\t%^", /* CloudFront */ 48 | "\"%x\",\"%h\",%^,%^,\"%m\",\"%U\",\"%s\",%^,\"%b\",\"%D\",%^,\"%R\",\"%u\"", /* Cloud Storage */ 49 | }; 50 | 51 | static const GPreConfDate dates = { 52 | "%d/%b/%Y", /* Apache */ 53 | "%Y-%m-%d", /* W3C */ 54 | "%f", /* Cloud Storage*/ 55 | }; 56 | 57 | static const GPreConfTime times = { 58 | "%H:%M:%S", 59 | "%f", /* Cloud Storage*/ 60 | }; 61 | /* *INDENT-ON* */ 62 | 63 | /* Ignore the following options */ 64 | static const char *ignore_cmd_opts[] = { 65 | "help", 66 | "storage", 67 | "version", 68 | }; 69 | 70 | static int 71 | in_ignore_cmd_opts (const char *val) 72 | { 73 | size_t i; 74 | for (i = 0; i < ARRAY_SIZE (ignore_cmd_opts); i++) { 75 | if (strstr (val, ignore_cmd_opts[i]) != NULL) 76 | return 1; 77 | } 78 | return 0; 79 | } 80 | 81 | static char * 82 | get_config_file_path (void) 83 | { 84 | char *upath = NULL, *rpath = NULL; 85 | 86 | /* determine which config file to open, default or custom */ 87 | if (conf.iconfigfile != NULL) { 88 | rpath = realpath (conf.iconfigfile, NULL); 89 | if (rpath == NULL) 90 | FATAL ("Unable to open the specified config file. %s", strerror (errno)); 91 | } 92 | /* otherwise, fallback to global config file, or 93 | * attempt to use the user's config file */ 94 | else { 95 | /* global config file */ 96 | if (conf.load_global_config) { 97 | upath = get_global_config (); 98 | rpath = realpath (upath, NULL); 99 | if (upath) { 100 | free (upath); 101 | } 102 | } 103 | /* user's config file */ 104 | if (rpath == NULL) { 105 | upath = get_home (); 106 | rpath = realpath (upath, NULL); 107 | if (upath) { 108 | free (upath); 109 | } 110 | } 111 | } 112 | 113 | return rpath; 114 | } 115 | 116 | /* clean command line arguments */ 117 | void 118 | free_cmd_args (void) 119 | { 120 | int i; 121 | if (nargc == 0) 122 | return; 123 | for (i = 0; i < nargc; i++) 124 | free (nargv[i]); 125 | free (nargv); 126 | } 127 | 128 | /* append extra value to argv */ 129 | static void 130 | append_to_argv (int *argc, char ***argv, char *val) 131 | { 132 | char **_argv = xrealloc (*argv, (*argc + 2) * sizeof (*_argv)); 133 | _argv[*argc] = val; 134 | _argv[*argc + 1] = '\0'; 135 | (*argc)++; 136 | *argv = _argv; 137 | } 138 | 139 | /* parses configuration file to feed getopt_long */ 140 | int 141 | parse_conf_file (int *argc, char ***argv) 142 | { 143 | char line[MAX_LINE_CONF + 1]; 144 | char *path = NULL, *val, *opt, *p; 145 | FILE *file; 146 | int i; 147 | size_t idx; 148 | 149 | /* assumes program name is on argv[0], though, it is not guaranteed */ 150 | append_to_argv (&nargc, &nargv, xstrdup ((char *) *argv[0])); 151 | 152 | /* determine which config file to open, default or custom */ 153 | path = get_config_file_path (); 154 | if (path == NULL) 155 | return ENOENT; 156 | 157 | /* could not open conf file, if so prompt conf dialog */ 158 | if ((file = fopen (path, "r")) == NULL) { 159 | free (path); 160 | return ENOENT; 161 | } 162 | 163 | while (fgets (line, sizeof line, file) != NULL) { 164 | if (line[0] == '\n' || line[0] == '\r' || line[0] == '#') 165 | continue; 166 | 167 | /* key */ 168 | idx = strcspn (line, " \t"); 169 | if (strlen (line) == idx) 170 | FATAL ("Malformed config key at line: %s", line); 171 | 172 | line[idx] = '\0'; 173 | 174 | /* make old config options backwards compatible by 175 | * substituting underscores with dashes */ 176 | while ((p = strpbrk (line, "_")) != NULL) 177 | *p = '-'; 178 | 179 | /* Ignore the following options when reading the config file */ 180 | if (in_ignore_cmd_opts (line)) 181 | continue; 182 | 183 | /* value */ 184 | val = line + (idx + 1); 185 | idx = strspn (val, " \t"); 186 | if (strlen (line) == idx) 187 | FATAL ("Malformed config value at line: %s", line); 188 | val = val + idx; 189 | val = trim_str (val); 190 | 191 | if (strcmp ("false", val) == 0) 192 | continue; 193 | 194 | /* set it as command line options */ 195 | opt = xmalloc (snprintf (NULL, 0, "--%s", line) + 1); 196 | sprintf (opt, "--%s", line); 197 | 198 | append_to_argv (&nargc, &nargv, opt); 199 | if (strcmp ("true", val) != 0) 200 | append_to_argv (&nargc, &nargv, xstrdup (val)); 201 | } 202 | 203 | /* give priority to command line arguments */ 204 | for (i = 1; i < *argc; i++) 205 | append_to_argv (&nargc, &nargv, xstrdup ((char *) (*argv)[i])); 206 | 207 | *argc = nargc; 208 | *argv = (char **) nargv; 209 | 210 | fclose (file); 211 | 212 | if (conf.iconfigfile == NULL) 213 | conf.iconfigfile = xstrdup (path); 214 | 215 | free (path); 216 | return 0; 217 | } 218 | 219 | /* return the index of the matched item, or -1 if no such item exists */ 220 | size_t 221 | get_selected_format_idx (void) 222 | { 223 | if (conf.log_format == NULL) 224 | return -1; 225 | if (strcmp (conf.log_format, logs.common) == 0) 226 | return COMMON; 227 | else if (strcmp (conf.log_format, logs.vcommon) == 0) 228 | return VCOMMON; 229 | else if (strcmp (conf.log_format, logs.combined) == 0) 230 | return COMBINED; 231 | else if (strcmp (conf.log_format, logs.vcombined) == 0) 232 | return VCOMBINED; 233 | else if (strcmp (conf.log_format, logs.w3c) == 0) 234 | return W3C; 235 | else if (strcmp (conf.log_format, logs.cloudfront) == 0) 236 | return CLOUDFRONT; 237 | else if (strcmp (conf.log_format, logs.cloudstorage) == 0) 238 | return CLOUDSTORAGE; 239 | else 240 | return -1; 241 | } 242 | 243 | /* return the string of the matched item, or NULL if no such item exists */ 244 | char * 245 | get_selected_format_str (size_t idx) 246 | { 247 | char *fmt = NULL; 248 | switch (idx) { 249 | case COMMON: 250 | fmt = alloc_string (logs.common); 251 | break; 252 | case VCOMMON: 253 | fmt = alloc_string (logs.vcommon); 254 | break; 255 | case COMBINED: 256 | fmt = alloc_string (logs.combined); 257 | break; 258 | case VCOMBINED: 259 | fmt = alloc_string (logs.vcombined); 260 | break; 261 | case W3C: 262 | fmt = alloc_string (logs.w3c); 263 | break; 264 | case CLOUDFRONT: 265 | fmt = alloc_string (logs.cloudfront); 266 | break; 267 | case CLOUDSTORAGE: 268 | fmt = alloc_string (logs.cloudstorage); 269 | break; 270 | } 271 | 272 | return fmt; 273 | } 274 | 275 | char * 276 | get_selected_date_str (size_t idx) 277 | { 278 | char *fmt = NULL; 279 | switch (idx) { 280 | case COMMON: 281 | case VCOMMON: 282 | case COMBINED: 283 | case VCOMBINED: 284 | fmt = alloc_string (dates.apache); 285 | break; 286 | case CLOUDFRONT: 287 | case W3C: 288 | fmt = alloc_string (dates.w3c); 289 | break; 290 | case CLOUDSTORAGE: 291 | fmt = alloc_string (dates.usec); 292 | break; 293 | } 294 | 295 | return fmt; 296 | } 297 | 298 | char * 299 | get_selected_time_str (size_t idx) 300 | { 301 | char *fmt = NULL; 302 | switch (idx) { 303 | case COMMON: 304 | case VCOMMON: 305 | case COMBINED: 306 | case VCOMBINED: 307 | case W3C: 308 | case CLOUDFRONT: 309 | fmt = alloc_string (times.fmt24); 310 | break; 311 | case CLOUDSTORAGE: 312 | fmt = alloc_string (times.usec); 313 | break; 314 | } 315 | 316 | return fmt; 317 | } 318 | 319 | int 320 | ignore_panel (GModule mod) 321 | { 322 | int i; 323 | int module; 324 | char *view; 325 | for (i = 0; i < conf.ignore_panel_idx; ++i) { 326 | view = conf.ignore_panels[i]; 327 | if ((module = get_module_enum (view)) == -1) 328 | continue; 329 | if (mod == (unsigned int) module) 330 | return 1; 331 | } 332 | 333 | return 0; 334 | } 335 | -------------------------------------------------------------------------------- /src/geolocation.c: -------------------------------------------------------------------------------- 1 | /** 2 | * geolocation.c -- GeoLocation related functions 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #if HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #ifdef HAVE_LIBGEOIP 27 | #include 28 | #include 29 | #endif 30 | 31 | #include "geolocation.h" 32 | 33 | #include "error.h" 34 | #include "util.h" 35 | 36 | GeoIP *geo_location_data; 37 | 38 | /* Get continent name concatenated with code */ 39 | static const char * 40 | get_continent_name_and_code (const char *continentid) 41 | { 42 | if (memcmp (continentid, "NA", 2) == 0) 43 | return "NA North America"; 44 | else if (memcmp (continentid, "OC", 2) == 0) 45 | return "OC Oceania"; 46 | else if (memcmp (continentid, "EU", 2) == 0) 47 | return "EU Europe"; 48 | else if (memcmp (continentid, "SA", 2) == 0) 49 | return "SA South America"; 50 | else if (memcmp (continentid, "AF", 2) == 0) 51 | return "AF Africa"; 52 | else if (memcmp (continentid, "AN", 2) == 0) 53 | return "AN Antarctica"; 54 | else if (memcmp (continentid, "AS", 2) == 0) 55 | return "AS Asia"; 56 | else 57 | return "-- Location Unknown"; 58 | } 59 | 60 | /* Geolocation data */ 61 | GeoIP * 62 | geoip_open_db (const char *db) 63 | { 64 | GeoIP *geoip; 65 | geoip = GeoIP_open (db, GEOIP_MEMORY_CACHE); 66 | 67 | if (geoip == NULL) 68 | FATAL ("Unable to open GeoIP database: %s\n", db); 69 | 70 | GeoIP_set_charset (geoip, GEOIP_CHARSET_UTF8); 71 | LOG_DEBUG (("Opened GeoIP City database: %s\n", db)); 72 | 73 | return geoip; 74 | } 75 | 76 | static void 77 | geoip_set_country (const char *country, const char *code, char *loc) 78 | { 79 | if (country && code) 80 | sprintf (loc, "%s %s", code, country); 81 | else 82 | sprintf (loc, "%s", "Country Unknown"); 83 | } 84 | 85 | static void 86 | geoip_set_city (const char *city, const char *region, char *loc) 87 | { 88 | sprintf (loc, "%s, %s", city ? city : "N/A City", 89 | region ? region : "N/A Region"); 90 | } 91 | 92 | static void 93 | geoip_set_continent (const char *continent, char *loc) 94 | { 95 | if (continent) 96 | sprintf (loc, "%s", get_continent_name_and_code (continent)); 97 | else 98 | sprintf (loc, "%s", "Continent Unknown"); 99 | } 100 | 101 | static GeoIPRecord * 102 | get_geoip_record (const char *addr, GTypeIP type_ip) 103 | { 104 | GeoIPRecord *rec = NULL; 105 | 106 | if (TYPE_IPV4 == type_ip) 107 | rec = GeoIP_record_by_name (geo_location_data, addr); 108 | else if (TYPE_IPV6 == type_ip) 109 | rec = GeoIP_record_by_name_v6 (geo_location_data, addr); 110 | 111 | return rec; 112 | } 113 | 114 | static void 115 | geoip_set_country_by_record (const char *ip, char *location, GTypeIP type_ip) 116 | { 117 | GeoIPRecord *rec = NULL; 118 | const char *country = NULL, *code = NULL, *addr = ip; 119 | 120 | if (conf.geoip_database == NULL || geo_location_data == NULL) 121 | return; 122 | 123 | /* Custom GeoIP database */ 124 | if ((rec = get_geoip_record (addr, type_ip))) { 125 | country = rec->country_name; 126 | code = rec->country_code; 127 | } 128 | 129 | geoip_set_country (country, code, location); 130 | if (rec != NULL) { 131 | GeoIPRecord_delete (rec); 132 | } 133 | } 134 | 135 | static int 136 | geoip_get_geoid (const char *addr, GTypeIP type_ip) 137 | { 138 | int geoid = 0; 139 | 140 | if (TYPE_IPV4 == type_ip) 141 | geoid = GeoIP_id_by_name (geo_location_data, addr); 142 | else if (TYPE_IPV6 == type_ip) 143 | geoid = GeoIP_id_by_name_v6 (geo_location_data, addr); 144 | 145 | return geoid; 146 | } 147 | 148 | static const char * 149 | geoip_get_country_by_geoid (const char *addr, GTypeIP type_ip) 150 | { 151 | const char *country = NULL; 152 | 153 | if (TYPE_IPV4 == type_ip) 154 | country = GeoIP_country_name_by_name (geo_location_data, addr); 155 | else if (TYPE_IPV6 == type_ip) 156 | country = GeoIP_country_name_by_name_v6 (geo_location_data, addr); 157 | 158 | return country; 159 | } 160 | 161 | static void 162 | geoip_set_country_by_geoid (const char *ip, char *location, GTypeIP type_ip) 163 | { 164 | const char *country = NULL, *code = NULL, *addr = ip; 165 | int geoid = 0; 166 | 167 | if (geo_location_data == NULL) 168 | return; 169 | 170 | geoid = geoip_get_geoid (addr, type_ip); 171 | country = geoip_get_country_by_geoid (addr, type_ip); 172 | code = GeoIP_code_by_id (geoid); 173 | 174 | geoip_set_country (country, code, location); 175 | } 176 | 177 | void 178 | geoip_get_country (const char *ip, char *location, GTypeIP type_ip) 179 | { 180 | unsigned char rec = GeoIP_database_edition (geo_location_data); 181 | 182 | switch (rec) { 183 | case GEOIP_COUNTRY_EDITION: 184 | if (TYPE_IPV4 == type_ip) 185 | geoip_set_country_by_geoid (ip, location, TYPE_IPV4); 186 | break; 187 | case GEOIP_COUNTRY_EDITION_V6: 188 | if (TYPE_IPV6 == type_ip) 189 | geoip_set_country_by_geoid (ip, location, TYPE_IPV6); 190 | break; 191 | case GEOIP_CITY_EDITION_REV0: 192 | case GEOIP_CITY_EDITION_REV1: 193 | if (TYPE_IPV4 == type_ip) 194 | geoip_set_country_by_record (ip, location, TYPE_IPV4); 195 | break; 196 | case GEOIP_CITY_EDITION_REV0_V6: 197 | case GEOIP_CITY_EDITION_REV1_V6: 198 | if (TYPE_IPV6 == type_ip) 199 | geoip_set_country_by_record (ip, location, TYPE_IPV6); 200 | break; 201 | } 202 | } 203 | 204 | static void 205 | geoip_set_continent_by_record (const char *ip, char *location, GTypeIP type_ip) 206 | { 207 | GeoIPRecord *rec = NULL; 208 | const char *continent = NULL, *addr = ip; 209 | 210 | if (conf.geoip_database == NULL || geo_location_data == NULL) 211 | return; 212 | 213 | /* Custom GeoIP database */ 214 | if ((rec = get_geoip_record (addr, type_ip))) 215 | continent = rec->continent_code; 216 | 217 | geoip_set_continent (continent, location); 218 | if (rec != NULL) { 219 | GeoIPRecord_delete (rec); 220 | } 221 | } 222 | 223 | static void 224 | geoip_set_continent_by_geoid (const char *ip, char *location, GTypeIP type_ip) 225 | { 226 | const char *continent = NULL, *addr = ip; 227 | int geoid = 0; 228 | 229 | if (geo_location_data == NULL) 230 | return; 231 | 232 | geoid = geoip_get_geoid (addr, type_ip); 233 | continent = GeoIP_continent_by_id (geoid); 234 | geoip_set_continent (continent, location); 235 | } 236 | 237 | 238 | void 239 | geoip_get_continent (const char *ip, char *location, GTypeIP type_ip) 240 | { 241 | unsigned char rec = GeoIP_database_edition (geo_location_data); 242 | 243 | switch (rec) { 244 | case GEOIP_COUNTRY_EDITION: 245 | if (TYPE_IPV4 == type_ip) 246 | geoip_set_continent_by_geoid (ip, location, TYPE_IPV4); 247 | break; 248 | case GEOIP_COUNTRY_EDITION_V6: 249 | if (TYPE_IPV6 == type_ip) 250 | geoip_set_continent_by_geoid (ip, location, TYPE_IPV6); 251 | break; 252 | case GEOIP_CITY_EDITION_REV0: 253 | case GEOIP_CITY_EDITION_REV1: 254 | if (TYPE_IPV4 == type_ip) 255 | geoip_set_continent_by_record (ip, location, TYPE_IPV4); 256 | break; 257 | case GEOIP_CITY_EDITION_REV0_V6: 258 | case GEOIP_CITY_EDITION_REV1_V6: 259 | if (TYPE_IPV6 == type_ip) 260 | geoip_set_continent_by_record (ip, location, TYPE_IPV6); 261 | break; 262 | } 263 | } 264 | 265 | static void 266 | geoip_set_city_by_record (const char *ip, char *location, GTypeIP type_ip) 267 | { 268 | GeoIPRecord *rec = NULL; 269 | const char *city = NULL, *region = NULL, *addr = ip; 270 | 271 | /* Custom GeoIP database */ 272 | if ((rec = get_geoip_record (addr, type_ip))) { 273 | city = rec->city; 274 | region = rec->region; 275 | } 276 | 277 | geoip_set_city (city, region, location); 278 | if (rec != NULL) { 279 | GeoIPRecord_delete (rec); 280 | } 281 | } 282 | 283 | /* Custom GeoIP database - i.e., GeoLiteCity.dat */ 284 | void 285 | geoip_get_city (const char *ip, char *location, GTypeIP type_ip) 286 | { 287 | unsigned char rec = GeoIP_database_edition (geo_location_data); 288 | 289 | if (conf.geoip_database == NULL || geo_location_data == NULL) 290 | return; 291 | 292 | switch (rec) { 293 | case GEOIP_CITY_EDITION_REV0: 294 | case GEOIP_CITY_EDITION_REV1: 295 | if (TYPE_IPV4 == type_ip) 296 | geoip_set_city_by_record (ip, location, TYPE_IPV4); 297 | break; 298 | case GEOIP_CITY_EDITION_REV0_V6: 299 | case GEOIP_CITY_EDITION_REV1_V6: 300 | if (TYPE_IPV6 == type_ip) 301 | geoip_set_city_by_record (ip, location, TYPE_IPV6); 302 | break; 303 | } 304 | } 305 | 306 | int 307 | set_geolocation (char *host, char *continent, char *country, char *city) 308 | { 309 | int type_ip = 0; 310 | 311 | if (geo_location_data == NULL) 312 | return 1; 313 | 314 | if (invalid_ipaddr (host, &type_ip)) 315 | return 1; 316 | 317 | geoip_get_country (host, country, type_ip); 318 | geoip_get_continent (host, continent, type_ip); 319 | if (conf.geoip_database) 320 | geoip_get_city (host, city, type_ip); 321 | 322 | return 0; 323 | } 324 | -------------------------------------------------------------------------------- /src/json.c: -------------------------------------------------------------------------------- 1 | /** 2 | * output.c -- output json to the standard output stream 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | #define _LARGEFILE_SOURCE 22 | #define _LARGEFILE64_SOURCE 23 | #define _FILE_OFFSET_BITS 64 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "json.h" 35 | 36 | #ifdef HAVE_LIBTOKYOCABINET 37 | #include "tcabdb.h" 38 | #else 39 | #include "glibht.h" 40 | #endif 41 | 42 | #include "settings.h" 43 | #include "ui.h" 44 | #include "util.h" 45 | 46 | static void print_json_data (FILE * fp, GHolder * h, int processed); 47 | static void print_json_host_data (FILE * fp, GHolder * h, int processed); 48 | 49 | static GJSON paneling[] = { 50 | {VISITORS, print_json_data}, 51 | {REQUESTS, print_json_data}, 52 | {REQUESTS_STATIC, print_json_data}, 53 | {NOT_FOUND, print_json_data}, 54 | {HOSTS, print_json_host_data}, 55 | {OS, print_json_data}, 56 | {BROWSERS, print_json_data}, 57 | {VISIT_TIMES, print_json_data}, 58 | {REFERRERS, print_json_data}, 59 | {REFERRING_SITES, print_json_data}, 60 | {KEYPHRASES, print_json_data}, 61 | #ifdef HAVE_LIBGEOIP 62 | {GEO_LOCATION, print_json_data}, 63 | #endif 64 | {STATUS_CODES, print_json_data}, 65 | }; 66 | 67 | static GJSON * 68 | panel_lookup (GModule module) 69 | { 70 | int i, num_panels = ARRAY_SIZE (paneling); 71 | 72 | for (i = 0; i < num_panels; i++) { 73 | if (paneling[i].module == module) 74 | return &paneling[i]; 75 | } 76 | return NULL; 77 | } 78 | 79 | static void 80 | escape_json_output (FILE * fp, char *s) 81 | { 82 | while (*s) { 83 | switch (*s) { 84 | case '"': 85 | fprintf (fp, "\\\""); 86 | break; 87 | case '\\': 88 | fprintf (fp, "\\\\"); 89 | break; 90 | case '\b': 91 | fprintf (fp, "\\\b"); 92 | break; 93 | case '\f': 94 | fprintf (fp, "\\\f"); 95 | break; 96 | case '\n': 97 | fprintf (fp, "\\\n"); 98 | break; 99 | case '\r': 100 | fprintf (fp, "\\\r"); 101 | break; 102 | case '\t': 103 | fprintf (fp, "\\\t"); 104 | break; 105 | case '/': 106 | fprintf (fp, "\\/"); 107 | break; 108 | default: 109 | if ((uint8_t) * s <= 0x1f) { 110 | /* Control characters (U+0000 through U+001F) */ 111 | char buf[8]; 112 | snprintf (buf, sizeof buf, "\\u%04x", *s); 113 | fprintf (fp, "%s", buf); 114 | } else if ((uint8_t) * s == 0xe2 && (uint8_t) * (s + 1) == 0x80 && 115 | (uint8_t) * (s + 2) == 0xa8) { 116 | /* Line separator (U+2028) */ 117 | fprintf (fp, "\\u2028"); 118 | s += 2; 119 | } else if ((uint8_t) * s == 0xe2 && (uint8_t) * (s + 1) == 0x80 && 120 | (uint8_t) * (s + 2) == 0xa9) { 121 | /* Paragraph separator (U+2019) */ 122 | fprintf (fp, "\\u2029"); 123 | s += 2; 124 | } else { 125 | fputc (*s, fp); 126 | } 127 | break; 128 | } 129 | s++; 130 | } 131 | } 132 | 133 | static void 134 | print_json_block (FILE * fp, GMetrics * nmetrics, char *sep) 135 | { 136 | fprintf (fp, "%s\t\"hits\": %d,\n", sep, nmetrics->hits); 137 | fprintf (fp, "%s\t\"visitors\": %d,\n", sep, nmetrics->visitors); 138 | fprintf (fp, "%s\t\"percent\": %4.2f,\n", sep, nmetrics->percent); 139 | fprintf (fp, "%s\t\"bytes\": %lld,\n", sep, (long long) nmetrics->bw.nbw); 140 | 141 | if (conf.serve_usecs) 142 | fprintf (fp, "%s\t\"time_served\": %lld,\n", sep, 143 | (long long) nmetrics->avgts.nts); 144 | 145 | if (conf.append_method && nmetrics->method) 146 | fprintf (fp, "%s\t\"method\": \"%s\",\n", sep, nmetrics->method); 147 | 148 | if (conf.append_protocol && nmetrics->protocol) 149 | fprintf (fp, "%s\t\"protocol\": \"%s\",\n", sep, nmetrics->protocol); 150 | 151 | fprintf (fp, "%s\t\"data\": \"", sep); 152 | escape_json_output (fp, nmetrics->data); 153 | fprintf (fp, "\""); 154 | } 155 | 156 | static void 157 | print_json_host_geo (FILE * fp, GSubList * sub_list, char *sep) 158 | { 159 | GSubItem *iter; 160 | static const char *key[] = { 161 | "country", 162 | "city", 163 | "hostname", 164 | }; 165 | 166 | int i; 167 | if (sub_list == NULL) 168 | return; 169 | 170 | fprintf (fp, ",\n"); 171 | for (i = 0, iter = sub_list->head; iter; iter = iter->next, i++) { 172 | fprintf (fp, "%s\t\"%s\": \"", sep, key[iter->metrics->id]); 173 | escape_json_output (fp, iter->metrics->data); 174 | fprintf (fp, (i != sub_list->size - 1) ? "\",\n" : "\""); 175 | } 176 | } 177 | 178 | static void 179 | print_json_host_data (FILE * fp, GHolder * h, int processed) 180 | { 181 | GMetrics *nmetrics; 182 | char *sep = char_repeat (2, '\t'); 183 | int i; 184 | 185 | fprintf (fp, "\t\"%s\": [\n", module_to_id (h->module)); 186 | for (i = 0; i < h->idx; i++) { 187 | set_data_metrics (h->items[i].metrics, &nmetrics, processed); 188 | 189 | fprintf (fp, "%s{\n", sep); 190 | print_json_block (fp, nmetrics, sep); 191 | print_json_host_geo (fp, h->items[i].sub_list, sep); 192 | fprintf (fp, (i != h->idx - 1) ? "\n%s},\n" : "\n%s}\n", sep); 193 | 194 | free (nmetrics); 195 | } 196 | fprintf (fp, "\t]"); 197 | 198 | free (sep); 199 | } 200 | 201 | static void 202 | print_json_sub_items (FILE * fp, GHolder * h, int idx, int processed) 203 | { 204 | GMetrics *nmetrics; 205 | GSubItem *iter; 206 | GSubList *sub_list = h->items[idx].sub_list; 207 | char *sep = char_repeat (3, '\t'); 208 | int i = 0; 209 | 210 | if (sub_list == NULL) 211 | return; 212 | 213 | fprintf (fp, ",\n%s\"items\": [\n", sep); 214 | for (iter = sub_list->head; iter; iter = iter->next, i++) { 215 | set_data_metrics (iter->metrics, &nmetrics, processed); 216 | 217 | fprintf (fp, "%s{\n", sep); 218 | print_json_block (fp, nmetrics, sep); 219 | fprintf (fp, (i != sub_list->size - 1) ? "\n%s},\n" : "\n%s}\n", sep); 220 | free (nmetrics); 221 | } 222 | fprintf (fp, "\t\t\t]"); 223 | 224 | free (sep); 225 | } 226 | 227 | static void 228 | print_json_data (FILE * fp, GHolder * h, int processed) 229 | { 230 | GMetrics *nmetrics; 231 | char *sep = char_repeat (2, '\t'); 232 | int i; 233 | 234 | fprintf (fp, "\t\"%s\": [\n", module_to_id (h->module)); 235 | for (i = 0; i < h->idx; i++) { 236 | set_data_metrics (h->items[i].metrics, &nmetrics, processed); 237 | 238 | fprintf (fp, "%s{\n", sep); 239 | print_json_block (fp, nmetrics, sep); 240 | if (h->sub_items_size) 241 | print_json_sub_items (fp, h, i, processed); 242 | fprintf (fp, (i != h->idx - 1) ? "\n%s},\n" : "\n%s}\n", sep); 243 | 244 | free (nmetrics); 245 | } 246 | fprintf (fp, "\t]"); 247 | 248 | free (sep); 249 | } 250 | 251 | static void 252 | print_json_summary (FILE * fp, GLog * logger) 253 | { 254 | long long t = 0LL; 255 | int total = 0; 256 | off_t log_size = 0; 257 | char now[DATE_TIME]; 258 | 259 | generate_time (); 260 | strftime (now, DATE_TIME, "%Y-%m-%d %H:%M:%S", now_tm); 261 | 262 | fprintf (fp, "\t\"%s\": {\n", GENER_ID); 263 | 264 | /* generated date time */ 265 | fprintf (fp, "\t\t\"%s\": \"%s\",\n", OVERALL_DATETIME, now); 266 | 267 | /* total requests */ 268 | total = logger->process; 269 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_REQ, total); 270 | 271 | /* invalid requests */ 272 | total = logger->invalid; 273 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_FAILED, total); 274 | 275 | /* generated time */ 276 | t = (long long) end_proc - start_proc; 277 | fprintf (fp, "\t\t\"%s\": %llu,\n", OVERALL_GENTIME, t); 278 | 279 | /* visitors */ 280 | total = get_ht_size_by_metric (VISITORS, MTRC_UNIQMAP); 281 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_VISITORS, total); 282 | 283 | /* files */ 284 | total = get_ht_size_by_metric (REQUESTS, MTRC_DATAMAP); 285 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_FILES, total); 286 | 287 | /* excluded hits */ 288 | total = logger->exclude_ip; 289 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_EXCL_HITS, total); 290 | 291 | /* referrers */ 292 | total = get_ht_size_by_metric (REFERRERS, MTRC_DATAMAP); 293 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_REF, total); 294 | 295 | /* not found */ 296 | total = get_ht_size_by_metric (NOT_FOUND, MTRC_DATAMAP); 297 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_NOTFOUND, total); 298 | 299 | /* static files */ 300 | total = get_ht_size_by_metric (REQUESTS_STATIC, MTRC_DATAMAP); 301 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_STATIC, total); 302 | 303 | /* log size */ 304 | if (!logger->piping) 305 | log_size = file_size (conf.ifile); 306 | fprintf (fp, "\t\t\"%s\": %jd,\n", OVERALL_LOGSIZE, (intmax_t) log_size); 307 | 308 | /* bandwidth */ 309 | fprintf (fp, "\t\t\"%s\": %lld,\n", OVERALL_BANDWIDTH, logger->resp_size); 310 | 311 | /* log path */ 312 | if (conf.ifile == NULL) 313 | conf.ifile = (char *) "STDIN"; 314 | fprintf (fp, "\t\t\"%s\": \"", OVERALL_LOG); 315 | escape_json_output (fp, conf.ifile); 316 | fprintf (fp, "\"\n"); 317 | 318 | fprintf (fp, "\t},\n"); 319 | } 320 | 321 | /* entry point to generate a a json report writing it to the fp */ 322 | /* follow the JSON style similar to http://developer.github.com/v3/ */ 323 | void 324 | output_json (GLog * logger, GHolder * holder) 325 | { 326 | GModule module; 327 | FILE *fp = stdout; 328 | 329 | fprintf (fp, "{\n"); 330 | print_json_summary (fp, logger); 331 | for (module = 0; module < TOTAL_MODULES; module++) { 332 | const GJSON *panel = panel_lookup (module); 333 | if (!panel) 334 | continue; 335 | if (ignore_panel (module)) 336 | continue; 337 | panel->render (fp, holder + module, logger->process); 338 | module != TOTAL_MODULES - 1 ? fprintf (fp, ",\n") : fprintf (fp, "\n"); 339 | } 340 | fprintf (fp, "}"); 341 | 342 | fclose (fp); 343 | } 344 | -------------------------------------------------------------------------------- /src/browsers.c: -------------------------------------------------------------------------------- 1 | /** 2 | * browsers.c -- functions for dealing with browsers 3 | * Copyright (C) 2009-2014 by Gerardo Orellana 4 | * GoAccess - An Ncurses apache weblog analyzer & interactive viewer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * A copy of the GNU General Public License is attached to this 17 | * source distribution for its full text. 18 | * 19 | * Visit http://goaccess.prosoftcorp.com for new releases. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "browsers.h" 27 | 28 | #include "util.h" 29 | #include "error.h" 30 | #include "xmalloc.h" 31 | 32 | /* {"search string", "belongs to"} */ 33 | static const char *browsers[][2] = { 34 | /* Game systems: most of them are based of major browsers, 35 | * thus they need to go before. */ 36 | {"Xbox One", "Game Systems"}, 37 | {"Xbox", "Game Systems"}, 38 | {"PlayStation", "Game Systems"}, 39 | {"NintendoBrowser", "Game Systems"}, 40 | {"Valve Steam", "Game Systems"}, 41 | {"Origin", "Game Systems"}, 42 | {"Raptr", "Game Systems"}, 43 | 44 | /* Based on Internet Explorer */ 45 | {"America Online Browser", "Others"}, 46 | {"Avant Browser", "Others"}, 47 | /* Internet Explorer */ 48 | {"IEMobile", "MSIE"}, 49 | {"MSIE", "MSIE"}, 50 | /* IE11 */ 51 | {"Trident/7.0", "MSIE"}, 52 | /* Microsoft Edge */ 53 | {"Edge", "MSIE"}, 54 | 55 | /* Opera */ 56 | {"Opera Mini", "Opera"}, 57 | {"Opera Mobi", "Opera"}, 58 | {"Opera", "Opera"}, 59 | {"OPR", "Opera"}, 60 | {"OPiOS", "Opera"}, 61 | {"Coast", "Opera"}, 62 | 63 | /* Others */ 64 | {"Homebrew", "Others"}, 65 | {"APT-HTTP", "Others"}, 66 | {"Apt-Cacher", "Others"}, 67 | {"Chef Client", "Others"}, 68 | {"Huawei", "Others"}, 69 | {"HUAWEI", "Others"}, 70 | {"BlackBerry", "Others"}, 71 | {"BrowserX", "Others"}, 72 | {"Dalvik", "Others"}, 73 | {"Dillo", "Others"}, 74 | {"ELinks", "Others"}, 75 | {"Epiphany", "Others"}, 76 | {"Firebird", "Others"}, 77 | {"Galeon", "Others"}, 78 | {"GranParadiso", "Others"}, 79 | {"IBrowse", "Others"}, 80 | {"K-Meleon", "Others"}, 81 | {"Kazehakase", "Others"}, 82 | {"Konqueror", "Others"}, 83 | {"Links", "Others"}, 84 | {"Lynx", "Others"}, 85 | {"Midori", "Others"}, 86 | {"Minefield", "Others"}, 87 | {"Mosaic", "Others"}, 88 | {"Netscape", "Others"}, 89 | {"SeaMonkey", "Others"}, 90 | {"UCBrowser", "Others"}, 91 | {"Wget", "Others"}, 92 | {"libfetch", "Others"}, 93 | {"check_http", "Others"}, 94 | {"curl", "Others"}, 95 | {"midori", "Others"}, 96 | {"w3m", "Others"}, 97 | {"Apache", "Others"}, 98 | 99 | /* Feed-reader-as-a-service */ 100 | {"Bloglines", "Feeds"}, 101 | {"Feedly", "Feeds"}, 102 | {"Flipboard", "Feeds"}, 103 | {"Netvibes", "Feeds"}, 104 | {"NewsBlur", "Feeds"}, 105 | {"YandexBlogs", "Feeds"}, 106 | 107 | /* Based on Firefox */ 108 | {"Camino", "Others"}, 109 | /* Rebranded Firefox but is really unmodified 110 | * Firefox (Debian trademark policy) */ 111 | {"Iceweasel", "Firefox"}, 112 | /* Mozilla Firefox */ 113 | {"Firefox", "Firefox"}, 114 | 115 | /* Based on Chromium */ 116 | {"YaBrowser", "Others"}, 117 | {"Flock", "Others"}, 118 | /* Chrome has to go before Safari */ 119 | {"Chrome", "Chrome"}, 120 | 121 | {"CriOS", "Chrome"}, 122 | {"Safari", "Safari"}, 123 | 124 | /* Crawlers/Bots */ 125 | {"AdsBot-Google", "Crawlers"}, 126 | {"Mediapartners-Google", "Crawlers"}, 127 | {"AppEngine-Google", "Crawlers"}, 128 | {"Google", "Crawlers"}, 129 | {"bingbot", "Crawlers"}, 130 | {"msnbot", "Crawlers"}, 131 | {"Yandex", "Crawlers"}, 132 | {"Baidu", "Crawlers"}, 133 | {"Ezooms", "Crawlers"}, 134 | {"Twitter", "Crawlers"}, 135 | {"Slurp", "Crawlers"}, 136 | {"Yahoo", "Crawlers"}, 137 | {"AppleBot", "Crawlers"}, 138 | {"AhrefsBot", "Crawlers"}, 139 | {"Abonti", "Crawlers"}, 140 | {"MJ12bot", "Crawlers"}, 141 | {"SISTRIX", "Crawlers"}, 142 | {"facebook", "Crawlers"}, 143 | {"DotBot", "Crawlers"}, 144 | {"Speedy Spider", "Crawlers"}, 145 | {"Sosospider", "Crawlers"}, 146 | {"BPImageWalker", "Crawlers"}, 147 | {"Sogou", "Crawlers"}, 148 | {"Java", "Crawlers"}, 149 | {"Jakarta Commons-HttpClient", "Crawlers"}, 150 | {"WBSearchBot", "Crawlers"}, 151 | {"SeznamBot", "Crawlers"}, 152 | {"DoCoMo", "Crawlers"}, 153 | {"TurnitinBot", "Crawlers"}, 154 | {"GSLFbot", "Crawlers"}, 155 | {"YodaoBot", "Crawlers"}, 156 | {"AddThis", "Crawlers"}, 157 | {"Purebot", "Crawlers"}, 158 | {"ia_archiver", "Crawlers"}, 159 | {"Wotbox", "Crawlers"}, 160 | {"CCBot", "Crawlers"}, 161 | {"findlinks", "Crawlers"}, 162 | {"Yeti", "Crawlers"}, 163 | {"ichiro", "Crawlers"}, 164 | {"Linguee Bot", "Crawlers"}, 165 | {"Gigabot", "Crawlers"}, 166 | {"BacklinkCrawler", "Crawlers"}, 167 | {"netEstate", "Crawlers"}, 168 | {"distilator", "Crawlers"}, 169 | {"Aboundex", "Crawlers"}, 170 | {"UnwindFetchor", "Crawlers"}, 171 | {"SEOkicks-Robot", "Crawlers"}, 172 | {"psbot", "Crawlers"}, 173 | {"SBIder", "Crawlers"}, 174 | {"TestNutch", "Crawlers"}, 175 | {"DomainCrawler", "Crawlers"}, 176 | {"NextGenSearchBot", "Crawlers"}, 177 | {"SEOENGWorldBot", "Crawlers"}, 178 | {"PiplBot", "Crawlers"}, 179 | {"IstellaBot", "Crawlers"}, 180 | {"Cityreview", "Crawlers"}, 181 | {"heritrix", "Crawlers"}, 182 | {"PagePeeker", "Crawlers"}, 183 | {"JS-Kit", "Crawlers"}, 184 | {"ScreenerBot", "Crawlers"}, 185 | {"PagesInventory", "Crawlers"}, 186 | {"ShowyouBot", "Crawlers"}, 187 | {"SolomonoBot", "Crawlers"}, 188 | {"rogerbot", "Crawlers"}, 189 | {"fastbot", "Crawlers"}, 190 | {"Domnutch", "Crawlers"}, 191 | {"MaxPoint", "Crawlers"}, 192 | {"NCBot", "Crawlers"}, 193 | {"TosCrawler", "Crawlers"}, 194 | {"Updownerbot", "Crawlers"}, 195 | {"urlwatch", "Crawlers"}, 196 | {"IstellaBot", "Crawlers"}, 197 | {"OpenWebSpider", "Crawlers"}, 198 | {"WordPress", "Crawlers"}, 199 | {"yacybot", "Crawlers"}, 200 | {"PEAR", "Crawlers"}, 201 | {"ZumBot", "Crawlers"}, 202 | {"YisouSpider", "Crawlers"}, 203 | {"W3C", "Crawlers"}, 204 | {"vcheck", "Crawlers"}, 205 | {"PycURL", "Crawlers"}, 206 | {"PHP", "Crawlers"}, 207 | {"PercolateCrawler", "Crawlers"}, 208 | {"NING", "Crawlers"}, 209 | {"gvfs", "Crawlers"}, 210 | {"Crowsnest", "Crawlers"}, 211 | {"CatchBot", "Crawlers"}, 212 | {"Combine", "Crawlers"}, 213 | {"A6-Indexer", "Crawlers"}, 214 | {"Altresium", "Crawlers"}, 215 | {"AndroidDownloadManager", "Crawlers"}, 216 | {"Apache-HttpClient", "Crawlers"}, 217 | {"Comodo", "Crawlers"}, 218 | {"crawler4j", "Crawlers"}, 219 | {"Cricket", "Crawlers"}, 220 | {"EC2LinkFinder", "Crawlers"}, 221 | {"Embedly", "Crawlers"}, 222 | {"envolk", "Crawlers"}, 223 | {"libwww-perl", "Crawlers"}, 224 | {"ruby", "Crawlers"}, 225 | {"Ruby", "Crawlers"}, 226 | {"python", "Crawlers"}, 227 | {"Python", "Crawlers"}, 228 | {"LinkedIn", "Crawlers"}, 229 | {"GeoHasher", "Crawlers"}, 230 | {"HTMLParser", "Crawlers"}, 231 | {"MLBot", "Crawlers"}, 232 | {"Jaxified Bot", "Crawlers"}, 233 | {"LinkWalker", "Crawlers"}, 234 | {"Microsoft-WebDAV", "Crawlers"}, 235 | {"nutch", "Crawlers"}, 236 | {"PostRank", "Crawlers"}, 237 | {"Image", "Crawlers"}, 238 | 239 | /* Podcast fetchers */ 240 | {"Downcast", "Podcasts"}, 241 | {"gPodder", "Podcasts"}, 242 | {"Instacast", "Podcasts"}, 243 | {"iTunes", "Podcasts"}, 244 | {"Miro", "Podcasts"}, 245 | {"Pocket Casts", "Podcasts"}, 246 | {"BashPodder", "Podcasts"}, 247 | 248 | /* Feed reader clients */ 249 | {"Akregator", "Feeds"}, 250 | {"Apple-PubSub", "Feeds"}, 251 | {"FeedDemon", "Feeds"}, 252 | {"Feedy", "Feeds"}, 253 | {"Liferea", "Feeds"}, 254 | {"NetNewsWire", "Feeds"}, 255 | {"RSSOwl", "Feeds"}, 256 | {"Thunderbird", "Feeds"}, 257 | {"Vienna", "Feeds"}, 258 | {"Windows-RSS-Platform", "Feeds"}, 259 | {"newsbeuter", "Feeds"}, 260 | {"Fever", "Feeds"}, 261 | 262 | {"Pingdom.com", "Uptime"}, 263 | {"UptimeRobot", "Uptime"}, 264 | {"jetmon", "Uptime"}, 265 | {"NodeUptime", "Uptime"}, 266 | {"NewRelicPinger", "Uptime"}, 267 | {"StatusCake", "Uptime"}, 268 | {"internetVista", "Uptime"}, 269 | 270 | {"Mozilla", "Others"} 271 | }; 272 | 273 | int 274 | is_crawler (const char *agent) 275 | { 276 | char type[BROWSER_TYPE_LEN]; 277 | char *browser, *a; 278 | 279 | if (agent == NULL || *agent == '\0') 280 | return 0; 281 | 282 | if ((a = xstrdup (agent), browser = verify_browser (a, type)) != NULL) 283 | free (browser); 284 | free (a); 285 | 286 | return strcmp (type, "Crawlers") == 0 ? 1 : 0; 287 | } 288 | 289 | /* Return the Opera 15 and Beyond */ 290 | static char * 291 | parse_opera (char *token) 292 | { 293 | char *val = xmalloc (snprintf (NULL, 0, "Opera%s", token) + 1); 294 | sprintf (val, "Opera%s", token); 295 | 296 | return val; 297 | } 298 | 299 | char * 300 | verify_browser (char *str, char *type) 301 | { 302 | char *a, *b, *ptr, *slash; 303 | size_t i; 304 | 305 | if (str == NULL || *str == '\0') 306 | return NULL; 307 | 308 | for (i = 0; i < ARRAY_SIZE (browsers); i++) { 309 | if ((a = strstr (str, browsers[i][0])) == NULL) 310 | continue; 311 | 312 | /* check if there is a space char in the token string, that way strpbrk 313 | * does not stop at the first space within the token string */ 314 | if ((strchr (browsers[i][0], ' ')) != NULL && (b = strchr (a, ' ')) != NULL) 315 | b++; 316 | else 317 | b = a; 318 | 319 | xstrncpy (type, browsers[i][1], BROWSER_TYPE_LEN); 320 | /* Internet Explorer 11 */ 321 | if (strstr (a, "rv:11") && strstr (a, "Trident/7.0")) { 322 | return alloc_string ("MSIE/11.0"); 323 | } 324 | /* Opera +15 uses OPR/# */ 325 | if (strstr (a, "OPR") != NULL && (slash = strrchr (a, '/'))) { 326 | return parse_opera (slash); 327 | } 328 | /* Opera has the version number at the end */ 329 | if (strstr (a, "Opera") && (slash = strrchr (a, '/')) && a < slash) { 330 | memmove (a + 5, slash, strlen (slash) + 1); 331 | } 332 | /* IE Old */ 333 | if (strstr (a, "MSIE") != NULL) { 334 | if ((ptr = strpbrk (a, ";)-")) != NULL) 335 | *ptr = '\0'; 336 | a = char_replace (a, ' ', '/'); 337 | } 338 | /* all others */ 339 | else if ((ptr = strpbrk (b, ";) ")) != NULL) { 340 | *ptr = '\0'; 341 | } 342 | 343 | return alloc_string (a); 344 | } 345 | xstrncpy (type, "Unknown", BROWSER_TYPE_LEN); 346 | 347 | return alloc_string ("Unknown"); 348 | } 349 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | 4 | scriptversion=2012-01-06.13; # UTC 5 | 6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 7 | # 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 8 | # Originally by Fran,cois Pinard , 1996. 9 | 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | if test $# -eq 0; then 29 | echo 1>&2 "Try \`$0 --help' for more information" 30 | exit 1 31 | fi 32 | 33 | run=: 34 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' 35 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p' 36 | 37 | # In the cases where this matters, `missing' is being run in the 38 | # srcdir already. 39 | if test -f configure.ac; then 40 | configure_ac=configure.ac 41 | else 42 | configure_ac=configure.in 43 | fi 44 | 45 | msg="missing on your system" 46 | 47 | case $1 in 48 | --run) 49 | # Try to run requested program, and just exit if it succeeds. 50 | run= 51 | shift 52 | "$@" && exit 0 53 | # Exit code 63 means version mismatch. This often happens 54 | # when the user try to use an ancient version of a tool on 55 | # a file that requires a minimum version. In this case we 56 | # we should proceed has if the program had been absent, or 57 | # if --run hadn't been passed. 58 | if test $? = 63; then 59 | run=: 60 | msg="probably too old" 61 | fi 62 | ;; 63 | 64 | -h|--h|--he|--hel|--help) 65 | echo "\ 66 | $0 [OPTION]... PROGRAM [ARGUMENT]... 67 | 68 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 69 | error status if there is no known handling for PROGRAM. 70 | 71 | Options: 72 | -h, --help display this help and exit 73 | -v, --version output version information and exit 74 | --run try to run the given command, and emulate it if it fails 75 | 76 | Supported PROGRAM values: 77 | aclocal touch file \`aclocal.m4' 78 | autoconf touch file \`configure' 79 | autoheader touch file \`config.h.in' 80 | autom4te touch the output file, or create a stub one 81 | automake touch all \`Makefile.in' files 82 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 83 | flex create \`lex.yy.c', if possible, from existing .c 84 | help2man touch the output file 85 | lex create \`lex.yy.c', if possible, from existing .c 86 | makeinfo touch the output file 87 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 88 | 89 | Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and 90 | \`g' are ignored when checking the name. 91 | 92 | Send bug reports to ." 93 | exit $? 94 | ;; 95 | 96 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 97 | echo "missing $scriptversion (GNU Automake)" 98 | exit $? 99 | ;; 100 | 101 | -*) 102 | echo 1>&2 "$0: Unknown \`$1' option" 103 | echo 1>&2 "Try \`$0 --help' for more information" 104 | exit 1 105 | ;; 106 | 107 | esac 108 | 109 | # normalize program name to check for. 110 | program=`echo "$1" | sed ' 111 | s/^gnu-//; t 112 | s/^gnu//; t 113 | s/^g//; t'` 114 | 115 | # Now exit if we have it, but it failed. Also exit now if we 116 | # don't have it and --version was passed (most likely to detect 117 | # the program). This is about non-GNU programs, so use $1 not 118 | # $program. 119 | case $1 in 120 | lex*|yacc*) 121 | # Not GNU programs, they don't have --version. 122 | ;; 123 | 124 | *) 125 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 126 | # We have it, but it failed. 127 | exit 1 128 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 129 | # Could not run --version or --help. This is probably someone 130 | # running `$TOOL --version' or `$TOOL --help' to check whether 131 | # $TOOL exists and not knowing $TOOL uses missing. 132 | exit 1 133 | fi 134 | ;; 135 | esac 136 | 137 | # If it does not exist, or fails to run (possibly an outdated version), 138 | # try to emulate it. 139 | case $program in 140 | aclocal*) 141 | echo 1>&2 "\ 142 | WARNING: \`$1' is $msg. You should only need it if 143 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 144 | to install the \`Automake' and \`Perl' packages. Grab them from 145 | any GNU archive site." 146 | touch aclocal.m4 147 | ;; 148 | 149 | autoconf*) 150 | echo 1>&2 "\ 151 | WARNING: \`$1' is $msg. You should only need it if 152 | you modified \`${configure_ac}'. You might want to install the 153 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 154 | archive site." 155 | touch configure 156 | ;; 157 | 158 | autoheader*) 159 | echo 1>&2 "\ 160 | WARNING: \`$1' is $msg. You should only need it if 161 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 162 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 163 | from any GNU archive site." 164 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 165 | test -z "$files" && files="config.h" 166 | touch_files= 167 | for f in $files; do 168 | case $f in 169 | *:*) touch_files="$touch_files "`echo "$f" | 170 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 171 | *) touch_files="$touch_files $f.in";; 172 | esac 173 | done 174 | touch $touch_files 175 | ;; 176 | 177 | automake*) 178 | echo 1>&2 "\ 179 | WARNING: \`$1' is $msg. You should only need it if 180 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 181 | You might want to install the \`Automake' and \`Perl' packages. 182 | Grab them from any GNU archive site." 183 | find . -type f -name Makefile.am -print | 184 | sed 's/\.am$/.in/' | 185 | while read f; do touch "$f"; done 186 | ;; 187 | 188 | autom4te*) 189 | echo 1>&2 "\ 190 | WARNING: \`$1' is needed, but is $msg. 191 | You might have modified some files without having the 192 | proper tools for further handling them. 193 | You can get \`$1' as part of \`Autoconf' from any GNU 194 | archive site." 195 | 196 | file=`echo "$*" | sed -n "$sed_output"` 197 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 198 | if test -f "$file"; then 199 | touch $file 200 | else 201 | test -z "$file" || exec >$file 202 | echo "#! /bin/sh" 203 | echo "# Created by GNU Automake missing as a replacement of" 204 | echo "# $ $@" 205 | echo "exit 0" 206 | chmod +x $file 207 | exit 1 208 | fi 209 | ;; 210 | 211 | bison*|yacc*) 212 | echo 1>&2 "\ 213 | WARNING: \`$1' $msg. You should only need it if 214 | you modified a \`.y' file. You may need the \`Bison' package 215 | in order for those modifications to take effect. You can get 216 | \`Bison' from any GNU archive site." 217 | rm -f y.tab.c y.tab.h 218 | if test $# -ne 1; then 219 | eval LASTARG=\${$#} 220 | case $LASTARG in 221 | *.y) 222 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 223 | if test -f "$SRCFILE"; then 224 | cp "$SRCFILE" y.tab.c 225 | fi 226 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 227 | if test -f "$SRCFILE"; then 228 | cp "$SRCFILE" y.tab.h 229 | fi 230 | ;; 231 | esac 232 | fi 233 | if test ! -f y.tab.h; then 234 | echo >y.tab.h 235 | fi 236 | if test ! -f y.tab.c; then 237 | echo 'main() { return 0; }' >y.tab.c 238 | fi 239 | ;; 240 | 241 | lex*|flex*) 242 | echo 1>&2 "\ 243 | WARNING: \`$1' is $msg. You should only need it if 244 | you modified a \`.l' file. You may need the \`Flex' package 245 | in order for those modifications to take effect. You can get 246 | \`Flex' from any GNU archive site." 247 | rm -f lex.yy.c 248 | if test $# -ne 1; then 249 | eval LASTARG=\${$#} 250 | case $LASTARG in 251 | *.l) 252 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 253 | if test -f "$SRCFILE"; then 254 | cp "$SRCFILE" lex.yy.c 255 | fi 256 | ;; 257 | esac 258 | fi 259 | if test ! -f lex.yy.c; then 260 | echo 'main() { return 0; }' >lex.yy.c 261 | fi 262 | ;; 263 | 264 | help2man*) 265 | echo 1>&2 "\ 266 | WARNING: \`$1' is $msg. You should only need it if 267 | you modified a dependency of a manual page. You may need the 268 | \`Help2man' package in order for those modifications to take 269 | effect. You can get \`Help2man' from any GNU archive site." 270 | 271 | file=`echo "$*" | sed -n "$sed_output"` 272 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 273 | if test -f "$file"; then 274 | touch $file 275 | else 276 | test -z "$file" || exec >$file 277 | echo ".ab help2man is required to generate this page" 278 | exit $? 279 | fi 280 | ;; 281 | 282 | makeinfo*) 283 | echo 1>&2 "\ 284 | WARNING: \`$1' is $msg. You should only need it if 285 | you modified a \`.texi' or \`.texinfo' file, or any other file 286 | indirectly affecting the aspect of the manual. The spurious 287 | call might also be the consequence of using a buggy \`make' (AIX, 288 | DU, IRIX). You might want to install the \`Texinfo' package or 289 | the \`GNU make' package. Grab either from any GNU archive site." 290 | # The file to touch is that specified with -o ... 291 | file=`echo "$*" | sed -n "$sed_output"` 292 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 293 | if test -z "$file"; then 294 | # ... or it is the one specified with @setfilename ... 295 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 296 | file=`sed -n ' 297 | /^@setfilename/{ 298 | s/.* \([^ ]*\) *$/\1/ 299 | p 300 | q 301 | }' $infile` 302 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 303 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 304 | fi 305 | # If the file does not exist, the user really needs makeinfo; 306 | # let's fail without touching anything. 307 | test -f $file || exit 1 308 | touch $file 309 | ;; 310 | 311 | *) 312 | echo 1>&2 "\ 313 | WARNING: \`$1' is needed, and is $msg. 314 | You might have modified some files without having the 315 | proper tools for further handling them. Check the \`README' file, 316 | it often tells you about the needed prerequisites for installing 317 | this package. You may also peek at any GNU archive site, in case 318 | some other package would contain this missing \`$1' program." 319 | exit 1 320 | ;; 321 | esac 322 | 323 | exit 0 324 | 325 | # Local variables: 326 | # eval: (add-hook 'write-file-hooks 'time-stamp) 327 | # time-stamp-start: "scriptversion=" 328 | # time-stamp-format: "%:y-%02m-%02d.%02H" 329 | # time-stamp-time-zone: "UTC" 330 | # time-stamp-end: "; # UTC" 331 | # End: 332 | -------------------------------------------------------------------------------- /config/goaccess.conf: -------------------------------------------------------------------------------- 1 | ###################################### 2 | # Format Options 3 | ###################################### 4 | 5 | # The time as %H:%M:%S 6 | # 7 | # The hour (24-hour clock) [00,23]; leading zeros are permitted but not required. 8 | # The minute [00,59]; leading zeros are permitted but not required. 9 | # The seconds [00,60]; leading zeros are permitted but not required. 10 | # See `man strftime` for more details 11 | # 12 | #time-format %H:%M:%S 13 | # 14 | # Google Cloud Storage or 15 | # The time that the request was completed, in microseconds since the Unix 16 | # epoch. 17 | # 18 | #time-format %f 19 | # 20 | # The date_format variable followed by a space, specifies 21 | # the log format date containing any combination of regular 22 | # characters and special format specifiers. They all begin with a 23 | # percentage (%) sign. See `man strftime` 24 | # 25 | # Apache log date format. The following date format works with any 26 | # of the Apache's log formats below. 27 | # 28 | #date-format %d/%b/%Y 29 | # 30 | # W3C (IIS) & AWS | Amazon CloudFront (Download Distribution) 31 | # 32 | #date-format %Y-%m-%d 33 | # 34 | # Google Cloud Storage or 35 | # The time that the request was completed, in microseconds since the Unix 36 | # epoch. 37 | # 38 | #time-format %f 39 | 40 | # The log_format variable followed by a space or \t for 41 | # tab-delimited, specifies the log format string. 42 | # 43 | # NOTE: If the time/date is a timestamp in seconds or microseconds 44 | # %x must be used instead of %d & %t to represent the date & time. 45 | # 46 | # NCSA Combined Log Format 47 | # 48 | #log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u" 49 | # 50 | # NCSA Combined Log Format with Virtual Host 51 | # 52 | #log-format %^:%^ %h %^[%d:%t %^] "%r" %s %b "%R" "%u" 53 | # 54 | # Common Log Format (CLF) 55 | # 56 | #log-format %h %^[%d:%t %^] "%r" %s %b 57 | # 58 | # Common Log Format (CLF) with Virtual Host 59 | # 60 | #log-format %^:%^ %h %^[%d:%t %^] "%r" %s %b 61 | # 62 | # W3C 63 | # 64 | #log-format %d %t %h %^ %^ %^ %^ %r %^ %s %b %^ %^ %u %R 65 | # 66 | # AWS | Amazon CloudFront (Download Distribution) 67 | # 68 | #log-format %d\t%t\t%^\t%b\t%h\t%m\t%^\t%r\t%s\t%R\t%u\t%^ 69 | # 70 | # Google Cloud Storage 71 | # 72 | #log-format "%x","%h",%^,%^,"%m","%U","%s",%^,"%b","%D",%^,"%R","%u" 73 | 74 | ###################################### 75 | # UI Options 76 | ###################################### 77 | 78 | # Prompt log/date configuration window on program start. 79 | # 80 | config-dialog false 81 | 82 | # Choose among color schemes 83 | # 1 : Default grey scheme 84 | # 2 : Green scheme 85 | # 86 | color-scheme 1 87 | 88 | # Color highlight active panel. 89 | # 90 | hl-header true 91 | 92 | # Set HTML report page title and header. 93 | # 94 | #html-report-title My Awesome Web Stats 95 | 96 | # Turn off colored output. This is the default output on 97 | # terminals that do not support colors. 98 | # true : for no color output 99 | # false : use color-scheme 100 | # 101 | no-color false 102 | 103 | # Disable progress metrics. 104 | # 105 | no-progress false 106 | 107 | # Enable mouse support on main dashboard. 108 | # 109 | with-mouse false 110 | 111 | # Disable summary metrics on the CSV output.. 112 | # 113 | no-csv-summary false 114 | 115 | ###################################### 116 | # File Options 117 | ###################################### 118 | 119 | # Specify the path to the input log file. If set, it will take 120 | # priority over -f from the command line. 121 | # 122 | #log-file /var/log/apache2/access.log 123 | 124 | # Send all debug messages to the specified file. Needs to configured 125 | # with --enable-debug 126 | # 127 | #debug-file debug.log 128 | 129 | # Specify a custom configuration file to use. If set, it will take 130 | # priority over the global configuration file (if any). 131 | # 132 | #config-file 133 | 134 | # Do not load the global configuration file. 135 | # 136 | #no-global-config false 137 | 138 | ###################################### 139 | # Parse Options 140 | ###################################### 141 | 142 | # Consider the following extensions as static files 143 | # The actual '.' is required and extensions are case sensitive 144 | # 145 | static-file .css 146 | static-file .CSS 147 | static-file .dae 148 | static-file .DAE 149 | static-file .eot 150 | static-file .EOT 151 | static-file .gif 152 | static-file .GIF 153 | static-file .ico 154 | static-file .ICO 155 | static-file .jpeg 156 | static-file .JPEG 157 | static-file .jpg 158 | static-file .JPG 159 | static-file .js 160 | static-file .JS 161 | static-file .map 162 | static-file .MAP 163 | static-file .mp3 164 | static-file .MP3 165 | static-file .pdf 166 | static-file .PDF 167 | static-file .png 168 | static-file .PNG 169 | static-file .svg 170 | static-file .SVG 171 | static-file .swf 172 | static-file .SWF 173 | static-file .ttf 174 | static-file .TTF 175 | static-file .txt 176 | static-file .TXT 177 | static-file .woff 178 | static-file .WOFF 179 | 180 | # Exclude an IPv4 or IPv6 from being counted. 181 | # Ranges can be included as well using a dash in between 182 | # the IPs (start-end). 183 | # 184 | #exclude-ip 127.0.0.1 185 | #exclude-ip 192.168.0.1-192.168.0.100 186 | #exclude-ip ::1 187 | #exclude-ip 0:0:0:0:0:ffff:808:804-0:0:0:0:0:ffff:808:808 188 | 189 | # Enable a list of user-agents by host. For faster parsing, do not 190 | # enable this flag. 191 | # 192 | agent-list false 193 | 194 | # Include HTTP request method if found. This will create a 195 | # request key containing the request method + the actual request. 196 | # 197 | http-method true 198 | 199 | # Include HTTP request protocol if found. This will create a 200 | # request key containing the request protocol + the actual request. 201 | # 202 | http-protocol true 203 | 204 | # Ignore request's query string. 205 | # i.e., www.google.com/page.htm?query => www.google.com/page.htm 206 | # 207 | # Note: Removing the query string can greatly decrease memory 208 | # consumption, especially on timestamped requests. 209 | # 210 | no-query-string false 211 | 212 | # Disable IP resolver on terminal output. 213 | # 214 | no-term-resolver false 215 | 216 | # Write output to stdout given one of the following formats: 217 | # csv : A comma-separated values (CSV) 218 | # json : JSON (JavaScript Object Notation) 219 | # html : HTML report 220 | # 221 | #output-format json 222 | 223 | # Display real OS names. e.g, Windows XP, Snow Leopard. 224 | # 225 | real-os true 226 | 227 | # Enable IP resolver on HTML|JSON output. 228 | # 229 | with-output-resolver false 230 | 231 | # Treat non-standard status code 444 as 404. 232 | # 233 | 444-as-404 false 234 | 235 | # Add 4xx client errors to the unique visitors count. 236 | # 237 | 4xx-to-unique-count false 238 | 239 | # Decode double-encoded values. 240 | # 241 | double-decode false 242 | 243 | # Ignore crawlers from being counted. 244 | # This will ignore robots listed under browsers.c 245 | # Note that it will count them towards the total 246 | # number of requests, but excluded from any of the panels. 247 | # 248 | ignore-crawlers false 249 | 250 | # Ignore parsing and displaying the given panel. 251 | # 252 | #ignore-panel VISITORS 253 | #ignore-panel REQUESTS 254 | #ignore-panel REQUESTS_STATIC 255 | #ignore-panel NOT_FOUND 256 | #ignore-panel HOSTS 257 | #ignore-panel OS 258 | #ignore-panel BROWSERS 259 | #ignore-panel VISIT_TIMES 260 | #ignore-panel REFERRERS 261 | #ignore-panel REFERRING_SITES 262 | ignore-panel KEYPHRASES 263 | #ignore-panel GEO_LOCATION 264 | #ignore-panel STATUS_CODES 265 | 266 | # Ignore referers from being counted. 267 | # This supports wild cards. For instance, 268 | # '*' matches 0 or more characters (including spaces) 269 | # '?' matches exactly one character 270 | # 271 | #ignore-referer *.domain.com 272 | #ignore-referer ww?.domain.* 273 | 274 | # Sort panel on initial load. 275 | # Sort options are separated by comma. 276 | # Options are in the form: PANEL,METRIC,ORDER 277 | # 278 | # Available metrics: 279 | # BY_HITS 280 | # BY_VISITORS 281 | # BY_DATA 282 | # BY_BW 283 | # BY_USEC 284 | # BY_PROT 285 | # BY_MTHD 286 | # Available orders: 287 | # ASC 288 | # DESC 289 | # 290 | #sort-panel VISITORS,BY_DATA,ASC 291 | #sort-panel REQUESTS,BY_HITS,ASC 292 | #sort-panel REQUESTS_STATIC,BY_HITS,ASC 293 | #sort-panel NOT_FOUND,BY_HITS,ASC 294 | #sort-panel HOSTS,BY_HITS,ASC 295 | #sort-panel OS,BY_HITS,ASC 296 | #sort-panel BROWSERS,BY_HITS,ASC 297 | #sort-panel VISIT_TIMES,BY_DATA,DESC 298 | #sort-panel REFERRERS,BY_HITS,ASC 299 | #sort-panel REFERRING_SITES,BY_HITS,ASC 300 | #sort-panel KEYPHRASES,BY_HITS,ASC 301 | #sort-panel GEO_LOCATION,BY_HITS,ASC 302 | #sort-panel STATUS_CODES,BY_HITS,ASC 303 | 304 | ###################################### 305 | # GeoIP Options 306 | # Only if configured with --enable-geoip 307 | ###################################### 308 | 309 | # Standard GeoIP database for less memory usage. 310 | # 311 | #std-geoip false 312 | 313 | # Specify path to GeoIP database file. i.e., GeoLiteCity.dat 314 | # .dat file needs to be downloaded from maxmind.com. 315 | # 316 | # For IPv4 City database: 317 | # wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz 318 | # gunzip GeoLiteCity.dat.gz 319 | # 320 | # For IPv6 City database: 321 | # wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz 322 | # gunzip GeoLiteCityv6.dat.gz 323 | # 324 | # For IPv6 Country database: 325 | # wget -N http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz 326 | # gunzip GeoIPv6.dat.gz 327 | # 328 | # Note: `geoip-city-data` is an alias of `geoip-database` 329 | # 330 | #geoip-database /usr/local/share/GeoIP/GeoLiteCity.dat 331 | 332 | ###################################### 333 | # Tokyo Cabinet Options 334 | # Only if configured with --enable-tcb=btree 335 | ###################################### 336 | 337 | # On-disk B+ Tree 338 | # Persist parsed data into disk. This should be set to 339 | # the first dataset prior to use `load-from-disk`. 340 | # Setting it to false will delete all database files 341 | # when exiting the program. 342 | #keep-db-files true 343 | 344 | # On-disk B+ Tree 345 | # Load previously stored data from disk. 346 | # Database files need to exist. See `keep-db-files`. 347 | #load-from-disk false 348 | 349 | # On-disk B+ Tree 350 | # Path where the on-disk database files are stored. 351 | # The default value is the /tmp directory. 352 | # 353 | #db-path /tmp 354 | 355 | # On-disk B+ Tree 356 | # Set the size in bytes of the extra mapped memory. 357 | # The default value is 0. 358 | # 359 | #xmmap 0 360 | 361 | # On-disk B+ Tree 362 | # Max number of leaf nodes to be cached. 363 | # Specifies the maximum number of leaf nodes to be cached. 364 | # If it is not more than 0, the default value is specified. 365 | # The default value is 1024. 366 | # 367 | #cache-lcnum 1024 368 | 369 | # On-disk B+ Tree 370 | # Specifies the maximum number of non-leaf nodes to be cached. 371 | # If it is not more than 0, the default value is specified. 372 | # The default value is 512. 373 | # 374 | #cache-ncnum 512 375 | 376 | # On-disk B+ Tree 377 | # Specifies the number of members in each leaf page. 378 | # If it is not more than 0, the default value is specified. 379 | # The default value is 128. 380 | # 381 | #tune-lmemb 128 382 | 383 | # On-disk B+ Tree 384 | # Specifies the number of members in each non-leaf page. 385 | # If it is not more than 0, the default value is specified. 386 | # The default value is 256. 387 | # 388 | #tune-nmemb 256 389 | 390 | # On-disk B+ Tree 391 | # Specifies the number of elements of the bucket array. 392 | # If it is not more than 0, the default value is specified. 393 | # The default value is 32749. 394 | # Suggested size of the bucket array is about from 1 to 4 395 | # times of the number of all pages to be stored. 396 | # 397 | #tune-bnum 32749 398 | 399 | # On-disk B+ Tree 400 | # Specifies that each page is compressed with ZLIB|BZ2 encoding. 401 | # Disabled by default. 402 | # 403 | #compression zlib 404 | --------------------------------------------------------------------------------