├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── ChangeLog ├── Makefile.am ├── NEWS ├── README ├── README.md ├── TODO ├── config └── goaccess.conf ├── configure.ac ├── goaccess.1 └── src ├── browsers.c ├── browsers.h ├── commons.c ├── commons.h ├── csv.c ├── csv.h ├── error.c ├── error.h ├── gdashboard.c ├── gdashboard.h ├── gdns.c ├── gdns.h ├── geolocation.c ├── geolocation.h ├── glibht.c ├── glibht.h ├── gmenu.c ├── gmenu.h ├── goaccess.c ├── goaccess.h ├── gstorage.c ├── gstorage.h ├── json.c ├── json.h ├── opesys.c ├── opesys.h ├── options.c ├── options.h ├── output.c ├── output.h ├── parser.c ├── parser.h ├── settings.c ├── settings.h ├── sort.c ├── sort.h ├── tcabdb.c ├── tcabdb.h ├── tcbtdb.c ├── tcbtdb.h ├── ui.c ├── ui.h ├── util.c ├── util.h ├── xmalloc.c └── xmalloc.h /.gitignore: -------------------------------------------------------------------------------- 1 | #custom section 2 | config.status 3 | config.guess 4 | config.sub 5 | /.deps 6 | /INSTALL 7 | /Makefile 8 | src/.dirstamp 9 | src/config.h 10 | src/config.h.in 11 | src/config.h.in~ 12 | src/config.log 13 | src/config.status 14 | src/.deps/ 15 | src/stamp-h1 16 | goaccess 17 | #merged from https://raw.github.com/github/gitignore/master/Autotools.gitignore 18 | # http://www.gnu.org/software/automake 19 | 20 | Makefile.in 21 | 22 | # http://www.gnu.org/software/autoconf 23 | 24 | /autom4te.cache 25 | /aclocal.m4 26 | /compile 27 | /configure 28 | /depcomp 29 | /install-sh 30 | /missing 31 | 32 | # VIM 33 | *.*.swp 34 | *.log 35 | 36 | # Object files 37 | *.o 38 | *.ko 39 | *.obj 40 | *.elf 41 | 42 | # Precompiled Headers 43 | *.gch 44 | *.pch 45 | 46 | # Libraries 47 | *.lib 48 | *.a 49 | *.la 50 | *.lo 51 | 52 | # Shared objects (inc. Windows DLLs) 53 | *.dll 54 | *.so 55 | *.so.* 56 | *.dylib 57 | 58 | # Executables 59 | *.exe 60 | *.out 61 | *.app 62 | *.i*86 63 | *.x86_64 64 | *.hex 65 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - clang 4 | - gcc 5 | before_install: 6 | - sudo apt-get update -qq 7 | - sudo apt-get install -qq libglib2.0-dev libncurses5-dev libgeoip-dev autoconf autotools-dev libtokyocabinet-dev 8 | install: 9 | - autoreconf -fiv 10 | - ./configure 11 | - make 12 | - make distclean 13 | - autoreconf -fiv 14 | - ./configure --enable-geoip --enable-utf8 15 | - make 16 | - make distclean 17 | - autoreconf -fiv 18 | - ./configure --enable-geoip --enable-utf8 --enable-tcb=btree --disable-bzip --disable-zlib 19 | - make 20 | - make distclean 21 | - autoreconf -fiv 22 | - ./configure --enable-geoip --enable-utf8 --enable-tcb=memhash --disable-bzip --disable-zlib 23 | - make 24 | - make distclean 25 | - autoreconf -fiv 26 | - ./configure 27 | - make 28 | branches: 29 | only: 30 | - master 31 | script: "echo done" 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GoAccess [![Build Status](https://travis-ci.org/allinurl/goaccess.svg?branch=master)](http://travis-ci.org/allinurl/goaccess) 2 | ======== 3 | 4 | ## What is it? ## 5 | GoAccess is an open source **real-time web log analyzer** and interactive 6 | viewer that **runs in a terminal in *nix systems**. It provides fast and 7 | valuable HTTP statistics for system administrators that require a visual server 8 | report on the fly. 9 | More info at: [http://goaccess.io](http://goaccess.io/?src=gh). 10 | 11 | ![GoAccess Main Dashboard](http://goaccess.io/images/goaccess_screenshot1M-03L.png?20150705220000) 12 | 13 | ## Features ## 14 | GoAccess parses the specified web log file and outputs the data to the X 15 | terminal. Features include: 16 | 17 | * General Statistics, bandwidth, etc. 18 | * Time taken to serve the request (_useful to track pages that are slowing down your site_) 19 | * Top Visitors 20 | * Requested files 21 | * Requested static files, images, swf, js, etc. 22 | * 404 or Not Found 23 | * Hosts, Reverse DNS, IP Location 24 | * Operating Systems 25 | * Browsers and Spiders 26 | * Referring Sites 27 | * Referrers URLs 28 | * Keyphrases 29 | * Geo Location - Continent/Country/City 30 | * Visitors Time Distribution 31 | * HTTP Status Codes 32 | * Ability to output `HTML`, `JSON` and `CSV` 33 | * Different Color Schemes 34 | * Support for large datasets and data persistence 35 | * Support for IPv6 36 | * Output statistics to HTML. See [**report**](http://goaccess.io/goaccess_html_report.html?src=gh). 37 | 38 | ### Nearly all web log formats... ### 39 | GoAccess allows any custom log format string. Predefined options include, but 40 | not limited to: 41 | 42 | * Amazon CloudFront (Download Distribution). 43 | * Apache virtual hosts 44 | * Combined Log Format (XLF/ELF) Apache | Nginx 45 | * Common Log Format (CLF) Apache 46 | * Google Cloud Storage. 47 | * W3C format (IIS). 48 | 49 | ## Why GoAccess? ## 50 | The main idea behind GoAccess is being able to quickly analyze and view web 51 | server statistics in real time without having to generate an HTML report (_great 52 | if you want to do a quick analysis of your access log via SSH_). 53 | 54 | Although it is possible to generate an `HTML`, `JSON`, `CSV` report, by default it 55 | outputs to a terminal. 56 | 57 | You can see it more of a monitor command tool than anything else. 58 | 59 | ## Installation ## 60 | GoAccess can be compiled and used on *nix systems. 61 | 62 | Download, extract and compile GoAccess with: 63 | 64 | $ wget http://tar.goaccess.io/goaccess-0.9.2.tar.gz 65 | $ tar -xzvf goaccess-0.9.2.tar.gz 66 | $ cd goaccess-0.9.2/ 67 | $ ./configure --enable-geoip --enable-utf8 68 | $ make 69 | # make install 70 | 71 | ### Build from GitHub (Development) ### 72 | 73 | $ git clone https://github.com/allinurl/goaccess.git 74 | $ cd goaccess 75 | $ autoreconf -fiv 76 | $ ./configure --enable-geoip --enable-utf8 77 | $ make 78 | # make install 79 | 80 | ## Distributions ## 81 | 82 | It is easiest to install GoAccess on Linux using the preferred package manager 83 | of your Linux distribution. 84 | 85 | Please note that not all distributions will have the lastest version of 86 | GoAccess available 87 | 88 | #### Debian/Ubuntu #### 89 | 90 | # apt-get install goaccess 91 | 92 | **NOTE:** It is likely this will install an outdated version of GoAccess. To 93 | make sure that you're running the latest stable version of GoAccess see 94 | alternative option below. 95 | 96 | #### Official GoAccess Debian & Ubuntu repository #### 97 | 98 | $ echo "deb http://deb.goaccess.io $(lsb_release -cs) main" | sudo tee -a /etc/apt/sources.list 99 | $ wget -O - http://deb.goaccess.io/gnugpg.key | sudo apt-key add - 100 | $ sudo apt-get update 101 | $ sudo apt-get install goaccess 102 | 103 | #### Fedora #### 104 | 105 | # yum install goaccess 106 | 107 | #### Arch Linux #### 108 | 109 | # pacman -S goaccess 110 | 111 | #### Gentoo #### 112 | 113 | # emerge net-analyzer/goaccess 114 | 115 | #### OS X / Homebrew #### 116 | 117 | # brew install goaccess 118 | 119 | #### FreeBSD #### 120 | 121 | # cd /usr/ports/sysutils/goaccess/ && make install clean 122 | # pkg install sysutils/goaccess 123 | 124 | #### OpenBSD #### 125 | 126 | # cd /usr/ports/www/goaccess && make install clean 127 | # pkg_add goaccess 128 | 129 | #### pkgsrc (NetBSD, Solaris, SmartOS, ...) #### 130 | 131 | # pkgin install goaccess 132 | 133 | #### Windows #### 134 | 135 | GoAccess can be used in Windows through Cygwin. 136 | 137 | ## Storage ## 138 | 139 | There are three storage options that can be used with GoAccess. Choosing one 140 | will depend on your environment and needs. 141 | 142 | #### GLib Hash Tables #### 143 | 144 | On-memory storage provides better performance at the cost of limiting the 145 | dataset size to the amount of available physical memory. By default GoAccess 146 | uses GLib Hash Tables. If your dataset can fit in memory, then this will 147 | perform fine. It has average memory usage and pretty good performance. For 148 | better performance with memory trade-off see Tokyo Cabinet on-memory hash 149 | database. 150 | 151 | #### Tokyo Cabinet On-Disk B+ Tree #### 152 | 153 | Use this storage method for large datasets where it is not possible to fit 154 | everything in memory. The B+ tree database is slower than any of the hash 155 | databases since data has to be committed to disk. However, using an SSD greatly 156 | increases the performance. You may also use this storage method if you need 157 | data persistence to quickly load statistics at a later date. 158 | 159 | #### Tokyo Cabinet On-Memory Hash Database #### 160 | 161 | Although this may vary across different systems, in general the on-memory hash 162 | database should perform slightly better than GLib Hash Tables. 163 | 164 | ## Command Line / Config Options ## 165 | The following options can be supplied to the command or specified in the 166 | configuration file. If specified in the configuration file, long options need 167 | to be used without prepending `--`. 168 | 169 | | Command Line Option | Description | 170 | | -----------------------------------|---------------------------------------------------------------| 171 | | `-a --agent-list` | Enable a list of user-agents by host. | 172 | | `-c --config-dialog` | Prompt log/date configuration window. | 173 | | `-d --with-output-resolver` | Enable IP resolver on HTML|JSON output. | 174 | | `-e --exclude-ip=` | Exclude one or multiple IPv4/v6 including IP ranges. | 175 | | `-f --log-file=` | Path to input log file. | 176 | | `-g --std-geoip` | Standard GeoIP database for less memory usage. | 177 | | `-h --help` | This help. | 178 | | `-H --http-protocol ` | Include HTTP request protocol if found. | 179 | | `-i --hl-header` | Color highlight active panel. | 180 | | `-M --http-method` | Include HTTP request method if found. | 181 | | `-m --with-mouse ` | Enable mouse support on main dashboard. | 182 | | `-o --output-format=csv,json` | Output format: `-o csv` for CSV. `-o json` for JSON. | 183 | | `-p --config-file=` | Custom configuration file. | 184 | | `-q --no-query-string` | Remove request's query string. Can reduce mem usage. | 185 | | `-r --no-term-resolver` | Disable IP resolver on terminal output. | 186 | | `-s --storage` | Display current storage method. i.e., B+ Tree, Hash. | 187 | | `-V --version` | Display version information and exit. | 188 | | `--444-as-404` | Treat non-standard status code 444 as 404. | 189 | | `--4xx-to-unique-count` | Add 4xx client errors to the unique visitors count. | 190 | | `--color-scheme=<1,2>` | Color schemes: `1 => Default grey`, `2 => Green`. | 191 | | `--date-format=` | Specify log date format. | 192 | | `--double-decode` | Decode double-encoded values. | 193 | | `--geoip-city-data=` | Same as using `--geoip-database`. | 194 | | `--geoip-database=` | Path to GeoIP database v4/v6. i.e., GeoLiteCity.dat | 195 | | `--html-report-title` | Set HTML report page title and header. | 196 | | `--ignore-crawlers` | Ignore crawlers. | 197 | | `--ignore-panel=` | Ignore parsing and displaying the given panel. | 198 | | `--ignore-referer=` | Ignore referers from being counted. Wildcards allowed. | 199 | | `--log-format=""` | Specify log format. Inner quotes need to be escaped. | 200 | | `--no-color` | Disable colored output. | 201 | | `--no-csv-summary` | Disable summary metrics on the CSV output. | 202 | | `--no-global-config` | Do not load the global configuration file. | 203 | | `--no-progress` | Disable progress metrics. | 204 | | `--real-os` | Display real OS names. e.g, Windows XP, Snow Leopard. | 205 | | `--sort-panel=PANEL,METRIC,ORDER` | Sort panel on initial load. See manpage for metrics. | 206 | | `--static-file=` | Add static file extension. e.g.: .mp3, Case sensitive. | 207 | | `--time-format=` | Specify log time format. | 208 | | `--keep-db-files` | Persist parsed data into disk. | 209 | | `--load-from-disk` | Load previously stored data from disk. | 210 | | `--cache-lcnum=` | Max number of leaf nodes to be cached. [1024] | 211 | | `--cache-ncnum=` | Max number of non-leaf nodes to be cached. [512] | 212 | | `--compression=` | Each page is compressed with ZLIB|BZ2 encoding. | 213 | | `--db-path=` | Path of the database file. [/tmp/] | 214 | | `--tune-bnum=` | Number of elements of the bucket array. [32749] | 215 | | `--tune-lmemb=` | Number of members in each leaf page. [128] | 216 | | `--tune-nmemb=` | Number of members in each non-leaf page. [256] | 217 | | `--xmmap=` | Set the size in bytes of the extra mapped memory. [0] | 218 | 219 | ## Usage ## 220 | 221 | The simplest and fastest usage would be: 222 | 223 | # goaccess -f access.log 224 | That will generate an interactive text-only output. 225 | 226 | To generate full statistics we can run GoAccess as: 227 | 228 | # goaccess -f access.log -a 229 | To generate an HTML report: 230 | 231 | # goaccess -f access.log -a > report.html 232 | To generate a JSON file: 233 | 234 | # goaccess -f access.log -a -d -o json > report.json 235 | To generate a CSV file: 236 | 237 | # goaccess -f access.log -o csv > report.csv 238 | 239 | The `-a` flag indicates that we want to process an agent-list for every host 240 | parsed. 241 | 242 | The `-d` flag indicates that we want to enable the IP resolver on the HTML | 243 | JSON output. (It will take longer time to output since it has to resolve all 244 | queries.) 245 | 246 | The `-c` flag will prompt the date and log format configuration window. Only 247 | when curses is initialized. 248 | 249 | Filtering can be done through the use of pipes. For instance, using grep to 250 | filter specific data and then pipe the output into GoAccess. This adds a great 251 | amount of flexibility to what GoAccess can display. For example: 252 | 253 | If we would like to process all `access.log.*.gz` we can do: 254 | 255 | # zcat access.log.*.gz | goaccess 256 | OR 257 | # zcat -f access.log* | goaccess 258 | 259 | (On Mac OS X, use `gunzip -c` instead of `zcat`). 260 | 261 | Another useful pipe would be filtering dates out of the web log 262 | 263 | The following will get all HTTP requests starting on 05/Dec/2010 until the end 264 | of the file. 265 | 266 | # sed -n '/05\/Dec\/2010/,$ p' access.log | goaccess -a 267 | 268 | If we want to parse only a certain time-frame from DATE a to DATE b, we can do: 269 | 270 | # sed -n '/5\/Nov\/2010/,/5\/Dec\/2010/ p' access.log | goaccess -a 271 | 272 | To exclude a list of virtual hosts you can do the following: 273 | 274 | # grep -v "`cat exclude_vhost_list_file`" vhost_access.log | goaccess 275 | 276 | For more examples, please check GoAccess' man page: 277 | http://goaccess.io/man 278 | 279 | ## Contributing ## 280 | 281 | Any help on GoAccess is welcome. The most helpful way is to try it out and give 282 | feedback. Feel free to use the Github issue tracker and pull requests to 283 | discuss and submit code changes. 284 | 285 | Enjoy! 286 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/goaccess.conf: -------------------------------------------------------------------------------- 1 | ###################################### 2 | # Date/Time 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 | #date-format %f 39 | 40 | ###################################### 41 | # Log Format Options 42 | ###################################### 43 | 44 | # The log_format variable followed by a space or \t for 45 | # tab-delimited, specifies the log format string. 46 | # 47 | # NOTE: If the time/date is a timestamp in seconds or microseconds 48 | # %x must be used instead of %d & %t to represent the date & time. 49 | # 50 | # NCSA Combined Log Format 51 | # 52 | #log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u" 53 | # 54 | # NCSA Combined Log Format with Virtual Host 55 | # 56 | #log-format %^:%^ %h %^[%d:%t %^] "%r" %s %b "%R" "%u" 57 | # 58 | # Common Log Format (CLF) 59 | # 60 | #log-format %h %^[%d:%t %^] "%r" %s %b 61 | # 62 | # Common Log Format (CLF) with Virtual Host 63 | # 64 | #log-format %^:%^ %h %^[%d:%t %^] "%r" %s %b 65 | # 66 | # W3C 67 | # 68 | #log-format %d %t %h %^ %^ %^ %^ %r %^ %s %b %^ %^ %u %R 69 | # 70 | # AWS | Amazon CloudFront (Download Distribution) 71 | # 72 | #log-format %d\t%t\t%^\t%b\t%h\t%m\t%^\t%r\t%s\t%R\t%u\t%^ 73 | # 74 | # Google Cloud Storage 75 | # 76 | #log-format "%x","%h",%^,%^,"%m","%U","%s",%^,"%b","%D",%^,"%R","%u" 77 | 78 | ###################################### 79 | # UI Options 80 | ###################################### 81 | 82 | # Prompt log/date configuration window on program start. 83 | # 84 | config-dialog false 85 | 86 | # Choose among color schemes 87 | # 1 : Default grey scheme 88 | # 2 : Green scheme 89 | # 90 | color-scheme 1 91 | 92 | # Color highlight active panel. 93 | # 94 | hl-header true 95 | 96 | # Set HTML report page title and header. 97 | # 98 | #html-report-title My Awesome Web Stats 99 | 100 | # Turn off colored output. This is the default output on 101 | # terminals that do not support colors. 102 | # true : for no color output 103 | # false : use color-scheme 104 | # 105 | no-color false 106 | 107 | # Disable progress metrics. 108 | # 109 | no-progress false 110 | 111 | # Enable mouse support on main dashboard. 112 | # 113 | with-mouse false 114 | 115 | # Disable summary metrics on the CSV output.. 116 | # 117 | no-csv-summary false 118 | 119 | ###################################### 120 | # File Options 121 | ###################################### 122 | 123 | # Specify the path to the input log file. If set, it will take 124 | # priority over -f from the command line. 125 | # 126 | #log-file /var/log/apache2/access.log 127 | 128 | # Send all debug messages to the specified file. Needs to configured 129 | # with --enable-debug 130 | # 131 | #debug-file debug.log 132 | 133 | # Specify a custom configuration file to use. If set, it will take 134 | # priority over the global configuration file (if any). 135 | # 136 | #config-file 137 | 138 | # Do not load the global configuration file. 139 | # 140 | #no-global-config false 141 | 142 | ###################################### 143 | # Parse Options 144 | ###################################### 145 | 146 | # Consider the following extensions as static files 147 | # The actual '.' is required and extensions are case sensitive 148 | # 149 | static-file .css 150 | static-file .CSS 151 | static-file .dae 152 | static-file .DAE 153 | static-file .eot 154 | static-file .EOT 155 | static-file .gif 156 | static-file .GIF 157 | static-file .ico 158 | static-file .ICO 159 | static-file .jpeg 160 | static-file .JPEG 161 | static-file .jpg 162 | static-file .JPG 163 | static-file .js 164 | static-file .JS 165 | static-file .map 166 | static-file .MAP 167 | static-file .mp3 168 | static-file .MP3 169 | static-file .pdf 170 | static-file .PDF 171 | static-file .png 172 | static-file .PNG 173 | static-file .svg 174 | static-file .SVG 175 | static-file .swf 176 | static-file .SWF 177 | static-file .ttf 178 | static-file .TTF 179 | static-file .txt 180 | static-file .TXT 181 | static-file .woff 182 | static-file .WOFF 183 | 184 | # Exclude an IPv4 or IPv6 from being counted. 185 | # Ranges can be included as well using a dash in between 186 | # the IPs (start-end). 187 | # 188 | #exclude-ip 127.0.0.1 189 | #exclude-ip 192.168.0.1-192.168.0.100 190 | #exclude-ip ::1 191 | #exclude-ip 0:0:0:0:0:ffff:808:804-0:0:0:0:0:ffff:808:808 192 | 193 | # Enable a list of user-agents by host. For faster parsing, do not 194 | # enable this flag. 195 | # 196 | agent-list false 197 | 198 | # Include HTTP request method if found. This will create a 199 | # request key containing the request method + the actual request. 200 | # 201 | http-method true 202 | 203 | # Include HTTP request protocol if found. This will create a 204 | # request key containing the request protocol + the actual request. 205 | # 206 | http-protocol true 207 | 208 | # Ignore request's query string. 209 | # i.e., www.google.com/page.htm?query => www.google.com/page.htm 210 | # 211 | # Note: Removing the query string can greatly decrease memory 212 | # consumption, especially on timestamped requests. 213 | # 214 | no-query-string false 215 | 216 | # Disable IP resolver on terminal output. 217 | # 218 | no-term-resolver false 219 | 220 | # Write output to stdout given one of the following formats: 221 | # csv : A comma-separated values (CSV) 222 | # json : JSON (JavaScript Object Notation) 223 | # html : HTML report 224 | # 225 | #output-format json 226 | 227 | # Display real OS names. e.g, Windows XP, Snow Leopard. 228 | # 229 | real-os true 230 | 231 | # Enable IP resolver on HTML|JSON output. 232 | # 233 | with-output-resolver false 234 | 235 | # Treat non-standard status code 444 as 404. 236 | # 237 | 444-as-404 false 238 | 239 | # Add 4xx client errors to the unique visitors count. 240 | # 241 | 4xx-to-unique-count false 242 | 243 | # Decode double-encoded values. 244 | # 245 | double-decode false 246 | 247 | # Ignore crawlers from being counted. 248 | # This will ignore robots listed under browsers.c 249 | # Note that it will count them towards the total 250 | # number of requests, but excluded from any of the panels. 251 | # 252 | ignore-crawlers false 253 | 254 | # Ignore parsing and displaying the given panel. 255 | # 256 | #ignore-panel VISITORS 257 | #ignore-panel REQUESTS 258 | #ignore-panel REQUESTS_STATIC 259 | #ignore-panel NOT_FOUND 260 | #ignore-panel HOSTS 261 | #ignore-panel OS 262 | #ignore-panel BROWSERS 263 | #ignore-panel VISIT_TIMES 264 | #ignore-panel REFERRERS 265 | #ignore-panel REFERRING_SITES 266 | ignore-panel KEYPHRASES 267 | #ignore-panel GEO_LOCATION 268 | #ignore-panel STATUS_CODES 269 | 270 | # Ignore referers from being counted. 271 | # This supports wild cards. For instance, 272 | # '*' matches 0 or more characters (including spaces) 273 | # '?' matches exactly one character 274 | # 275 | #ignore-referer *.domain.com 276 | #ignore-referer ww?.domain.* 277 | 278 | # Sort panel on initial load. 279 | # Sort options are separated by comma. 280 | # Options are in the form: PANEL,METRIC,ORDER 281 | # 282 | # Available metrics: 283 | # BY_HITS 284 | # BY_VISITORS 285 | # BY_DATA 286 | # BY_BW 287 | # BY_AVGTS 288 | # BY_PROT 289 | # BY_MTHD 290 | # Available orders: 291 | # ASC 292 | # DESC 293 | # 294 | #sort-panel VISITORS,BY_DATA,ASC 295 | #sort-panel REQUESTS,BY_HITS,ASC 296 | #sort-panel REQUESTS_STATIC,BY_HITS,ASC 297 | #sort-panel NOT_FOUND,BY_HITS,ASC 298 | #sort-panel HOSTS,BY_HITS,ASC 299 | #sort-panel OS,BY_HITS,ASC 300 | #sort-panel BROWSERS,BY_HITS,ASC 301 | #sort-panel VISIT_TIMES,BY_DATA,DESC 302 | #sort-panel REFERRERS,BY_HITS,ASC 303 | #sort-panel REFERRING_SITES,BY_HITS,ASC 304 | #sort-panel KEYPHRASES,BY_HITS,ASC 305 | #sort-panel GEO_LOCATION,BY_HITS,ASC 306 | #sort-panel STATUS_CODES,BY_HITS,ASC 307 | 308 | ###################################### 309 | # GeoIP Options 310 | # Only if configured with --enable-geoip 311 | ###################################### 312 | 313 | # Standard GeoIP database for less memory usage. 314 | # 315 | #std-geoip false 316 | 317 | # Specify path to GeoIP database file. i.e., GeoLiteCity.dat 318 | # .dat file needs to be downloaded from maxmind.com. 319 | # 320 | # For IPv4 City database: 321 | # wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz 322 | # gunzip GeoLiteCity.dat.gz 323 | # 324 | # For IPv6 City database: 325 | # wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz 326 | # gunzip GeoLiteCityv6.dat.gz 327 | # 328 | # For IPv6 Country database: 329 | # wget -N http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz 330 | # gunzip GeoIPv6.dat.gz 331 | # 332 | # Note: `geoip-city-data` is an alias of `geoip-database` 333 | # 334 | #geoip-database /usr/local/share/GeoIP/GeoLiteCity.dat 335 | 336 | ###################################### 337 | # Tokyo Cabinet Options 338 | # Only if configured with --enable-tcb=btree 339 | ###################################### 340 | 341 | # On-disk B+ Tree 342 | # Persist parsed data into disk. This should be set to 343 | # the first dataset prior to use `load-from-disk`. 344 | # Setting it to false will delete all database files 345 | # when exiting the program. 346 | #keep-db-files true 347 | 348 | # On-disk B+ Tree 349 | # Load previously stored data from disk. 350 | # Database files need to exist. See `keep-db-files`. 351 | #load-from-disk false 352 | 353 | # On-disk B+ Tree 354 | # Path where the on-disk database files are stored. 355 | # The default value is the /tmp directory. 356 | # 357 | #db-path /tmp 358 | 359 | # On-disk B+ Tree 360 | # Set the size in bytes of the extra mapped memory. 361 | # The default value is 0. 362 | # 363 | #xmmap 0 364 | 365 | # On-disk B+ Tree 366 | # Max number of leaf nodes to be cached. 367 | # Specifies the maximum number of leaf nodes to be cached. 368 | # If it is not more than 0, the default value is specified. 369 | # The default value is 1024. 370 | # 371 | #cache-lcnum 1024 372 | 373 | # On-disk B+ Tree 374 | # Specifies the maximum number of non-leaf nodes to be cached. 375 | # If it is not more than 0, the default value is specified. 376 | # The default value is 512. 377 | # 378 | #cache-ncnum 512 379 | 380 | # On-disk B+ Tree 381 | # Specifies the number of members in each leaf page. 382 | # If it is not more than 0, the default value is specified. 383 | # The default value is 128. 384 | # 385 | #tune-lmemb 128 386 | 387 | # On-disk B+ Tree 388 | # Specifies the number of members in each non-leaf page. 389 | # If it is not more than 0, the default value is specified. 390 | # The default value is 256. 391 | # 392 | #tune-nmemb 256 393 | 394 | # On-disk B+ Tree 395 | # Specifies the number of elements of the bucket array. 396 | # If it is not more than 0, the default value is specified. 397 | # The default value is 32749. 398 | # Suggested size of the bucket array is about from 1 to 4 399 | # times of the number of all pages to be stored. 400 | # 401 | #tune-bnum 32749 402 | 403 | # On-disk B+ Tree 404 | # Specifies that each page is compressed with ZLIB|BZ2 encoding. 405 | # Disabled by default. 406 | # 407 | #compression zlib 408 | -------------------------------------------------------------------------------- /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/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 | /* ###NOTE: The size of the list is proportional to the run time, 33 | * which makes this pretty slow */ 34 | 35 | /* {"search string", "belongs to"} */ 36 | static const char *browsers[][2] = { 37 | /* Game systems: most of them are based of major browsers, 38 | * thus they need to go before. */ 39 | {"Xbox One", "Game Systems"}, 40 | {"Xbox", "Game Systems"}, 41 | {"PlayStation", "Game Systems"}, 42 | {"NintendoBrowser", "Game Systems"}, 43 | {"Valve Steam", "Game Systems"}, 44 | {"Origin", "Game Systems"}, 45 | {"Raptr", "Game Systems"}, 46 | 47 | /* Based on Internet Explorer */ 48 | {"America Online Browser", "Others"}, 49 | {"Avant Browser", "Others"}, 50 | /* Internet Explorer */ 51 | {"IEMobile", "MSIE"}, 52 | {"MSIE", "MSIE"}, 53 | /* IE11 */ 54 | {"Trident/7.0", "MSIE"}, 55 | /* Microsoft Edge */ 56 | {"Edge", "MSIE"}, 57 | 58 | /* Opera */ 59 | {"Opera Mini", "Opera"}, 60 | {"Opera Mobi", "Opera"}, 61 | {"Opera", "Opera"}, 62 | {"OPR", "Opera"}, 63 | {"OPiOS", "Opera"}, 64 | {"Coast", "Opera"}, 65 | 66 | /* Others */ 67 | {"Homebrew", "Others"}, 68 | {"APT-HTTP", "Others"}, 69 | {"Apt-Cacher", "Others"}, 70 | {"Chef Client", "Others"}, 71 | {"Huawei", "Others"}, 72 | {"HUAWEI", "Others"}, 73 | {"BlackBerry", "Others"}, 74 | {"BrowserX", "Others"}, 75 | {"Dalvik", "Others"}, 76 | {"Dillo", "Others"}, 77 | {"ELinks", "Others"}, 78 | {"Epiphany", "Others"}, 79 | {"Firebird", "Others"}, 80 | {"Galeon", "Others"}, 81 | {"GranParadiso", "Others"}, 82 | {"IBrowse", "Others"}, 83 | {"K-Meleon", "Others"}, 84 | {"Kazehakase", "Others"}, 85 | {"Konqueror", "Others"}, 86 | {"Links", "Others"}, 87 | {"Lynx", "Others"}, 88 | {"Midori", "Others"}, 89 | {"Minefield", "Others"}, 90 | {"Mosaic", "Others"}, 91 | {"Netscape", "Others"}, 92 | {"SeaMonkey", "Others"}, 93 | {"UCBrowser", "Others"}, 94 | {"Wget", "Others"}, 95 | {"libfetch", "Others"}, 96 | {"check_http", "Others"}, 97 | {"curl", "Others"}, 98 | {"midori", "Others"}, 99 | {"w3m", "Others"}, 100 | {"Apache", "Others"}, 101 | 102 | /* Feed-reader-as-a-service */ 103 | {"Bloglines", "Feeds"}, 104 | {"Feedly", "Feeds"}, 105 | {"Flipboard", "Feeds"}, 106 | {"Netvibes", "Feeds"}, 107 | {"NewsBlur", "Feeds"}, 108 | {"YandexBlogs", "Feeds"}, 109 | 110 | /* Based on Firefox */ 111 | {"Camino", "Others"}, 112 | /* Rebranded Firefox but is really unmodified 113 | * Firefox (Debian trademark policy) */ 114 | {"Iceweasel", "Firefox"}, 115 | /* Mozilla Firefox */ 116 | {"Firefox", "Firefox"}, 117 | 118 | /* Based on Chromium */ 119 | {"YaBrowser", "Others"}, 120 | {"Flock", "Others"}, 121 | /* Chrome has to go before Safari */ 122 | {"Chrome", "Chrome"}, 123 | 124 | {"CriOS", "Chrome"}, 125 | {"Safari", "Safari"}, 126 | 127 | /* Crawlers/Bots */ 128 | {"AdsBot-Google", "Crawlers"}, 129 | {"Mediapartners-Google", "Crawlers"}, 130 | {"AppEngine-Google", "Crawlers"}, 131 | {"Google", "Crawlers"}, 132 | {"bingbot", "Crawlers"}, 133 | {"msnbot", "Crawlers"}, 134 | {"Yandex", "Crawlers"}, 135 | {"Baidu", "Crawlers"}, 136 | {"Ezooms", "Crawlers"}, 137 | {"Twitter", "Crawlers"}, 138 | {"Slurp", "Crawlers"}, 139 | {"Yahoo", "Crawlers"}, 140 | {"AppleBot", "Crawlers"}, 141 | {"AhrefsBot", "Crawlers"}, 142 | {"Abonti", "Crawlers"}, 143 | {"MJ12bot", "Crawlers"}, 144 | {"SISTRIX", "Crawlers"}, 145 | {"facebook", "Crawlers"}, 146 | {"DotBot", "Crawlers"}, 147 | {"Speedy Spider", "Crawlers"}, 148 | {"Sosospider", "Crawlers"}, 149 | {"BPImageWalker", "Crawlers"}, 150 | {"Sogou", "Crawlers"}, 151 | {"Java", "Crawlers"}, 152 | {"Jakarta Commons-HttpClient", "Crawlers"}, 153 | {"WBSearchBot", "Crawlers"}, 154 | {"SeznamBot", "Crawlers"}, 155 | {"DoCoMo", "Crawlers"}, 156 | {"TurnitinBot", "Crawlers"}, 157 | {"GSLFbot", "Crawlers"}, 158 | {"YodaoBot", "Crawlers"}, 159 | {"AddThis", "Crawlers"}, 160 | {"Purebot", "Crawlers"}, 161 | {"ia_archiver", "Crawlers"}, 162 | {"Wotbox", "Crawlers"}, 163 | {"CCBot", "Crawlers"}, 164 | {"findlinks", "Crawlers"}, 165 | {"Yeti", "Crawlers"}, 166 | {"ichiro", "Crawlers"}, 167 | {"Linguee Bot", "Crawlers"}, 168 | {"Gigabot", "Crawlers"}, 169 | {"BacklinkCrawler", "Crawlers"}, 170 | {"netEstate", "Crawlers"}, 171 | {"distilator", "Crawlers"}, 172 | {"Aboundex", "Crawlers"}, 173 | {"UnwindFetchor", "Crawlers"}, 174 | {"SEOkicks-Robot", "Crawlers"}, 175 | {"psbot", "Crawlers"}, 176 | {"SBIder", "Crawlers"}, 177 | {"TestNutch", "Crawlers"}, 178 | {"DomainCrawler", "Crawlers"}, 179 | {"NextGenSearchBot", "Crawlers"}, 180 | {"SEOENGWorldBot", "Crawlers"}, 181 | {"PiplBot", "Crawlers"}, 182 | {"IstellaBot", "Crawlers"}, 183 | {"Cityreview", "Crawlers"}, 184 | {"heritrix", "Crawlers"}, 185 | {"PagePeeker", "Crawlers"}, 186 | {"JS-Kit", "Crawlers"}, 187 | {"ScreenerBot", "Crawlers"}, 188 | {"PagesInventory", "Crawlers"}, 189 | {"ShowyouBot", "Crawlers"}, 190 | {"SolomonoBot", "Crawlers"}, 191 | {"rogerbot", "Crawlers"}, 192 | {"fastbot", "Crawlers"}, 193 | {"Domnutch", "Crawlers"}, 194 | {"MaxPoint", "Crawlers"}, 195 | {"NCBot", "Crawlers"}, 196 | {"TosCrawler", "Crawlers"}, 197 | {"Updownerbot", "Crawlers"}, 198 | {"urlwatch", "Crawlers"}, 199 | {"IstellaBot", "Crawlers"}, 200 | {"OpenWebSpider", "Crawlers"}, 201 | {"WordPress", "Crawlers"}, 202 | {"yacybot", "Crawlers"}, 203 | {"PEAR", "Crawlers"}, 204 | {"ZumBot", "Crawlers"}, 205 | {"YisouSpider", "Crawlers"}, 206 | {"W3C", "Crawlers"}, 207 | {"vcheck", "Crawlers"}, 208 | {"PycURL", "Crawlers"}, 209 | {"PHP", "Crawlers"}, 210 | {"PercolateCrawler", "Crawlers"}, 211 | {"NING", "Crawlers"}, 212 | {"gvfs", "Crawlers"}, 213 | {"Crowsnest", "Crawlers"}, 214 | {"CatchBot", "Crawlers"}, 215 | {"Combine", "Crawlers"}, 216 | {"A6-Indexer", "Crawlers"}, 217 | {"Altresium", "Crawlers"}, 218 | {"AndroidDownloadManager", "Crawlers"}, 219 | {"Apache-HttpClient", "Crawlers"}, 220 | {"Comodo", "Crawlers"}, 221 | {"crawler4j", "Crawlers"}, 222 | {"Cricket", "Crawlers"}, 223 | {"EC2LinkFinder", "Crawlers"}, 224 | {"Embedly", "Crawlers"}, 225 | {"envolk", "Crawlers"}, 226 | {"libwww-perl", "Crawlers"}, 227 | {"ruby", "Crawlers"}, 228 | {"Ruby", "Crawlers"}, 229 | {"python", "Crawlers"}, 230 | {"Python", "Crawlers"}, 231 | {"LinkedIn", "Crawlers"}, 232 | {"GeoHasher", "Crawlers"}, 233 | {"HTMLParser", "Crawlers"}, 234 | {"MLBot", "Crawlers"}, 235 | {"Jaxified Bot", "Crawlers"}, 236 | {"LinkWalker", "Crawlers"}, 237 | {"Microsoft-WebDAV", "Crawlers"}, 238 | {"nutch", "Crawlers"}, 239 | {"PostRank", "Crawlers"}, 240 | {"Image", "Crawlers"}, 241 | 242 | /* Podcast fetchers */ 243 | {"Downcast", "Podcasts"}, 244 | {"gPodder", "Podcasts"}, 245 | {"Instacast", "Podcasts"}, 246 | {"iTunes", "Podcasts"}, 247 | {"Miro", "Podcasts"}, 248 | {"Pocket Casts", "Podcasts"}, 249 | {"BashPodder", "Podcasts"}, 250 | 251 | /* Feed reader clients */ 252 | {"Akregator", "Feeds"}, 253 | {"Apple-PubSub", "Feeds"}, 254 | {"FeedDemon", "Feeds"}, 255 | {"Feedy", "Feeds"}, 256 | {"Liferea", "Feeds"}, 257 | {"NetNewsWire", "Feeds"}, 258 | {"RSSOwl", "Feeds"}, 259 | {"Thunderbird", "Feeds"}, 260 | {"Vienna", "Feeds"}, 261 | {"Windows-RSS-Platform", "Feeds"}, 262 | {"newsbeuter", "Feeds"}, 263 | {"Fever", "Feeds"}, 264 | 265 | {"Pingdom.com", "Uptime"}, 266 | {"UptimeRobot", "Uptime"}, 267 | {"jetmon", "Uptime"}, 268 | {"NodeUptime", "Uptime"}, 269 | {"NewRelicPinger", "Uptime"}, 270 | {"StatusCake", "Uptime"}, 271 | {"internetVista", "Uptime"}, 272 | 273 | {"Mozilla", "Others"} 274 | }; 275 | 276 | int 277 | is_crawler (const char *agent) 278 | { 279 | char type[BROWSER_TYPE_LEN]; 280 | char *browser, *a; 281 | 282 | if (agent == NULL || *agent == '\0') 283 | return 0; 284 | 285 | if ((a = xstrdup (agent), browser = verify_browser (a, type)) != NULL) 286 | free (browser); 287 | free (a); 288 | 289 | return strcmp (type, "Crawlers") == 0 ? 1 : 0; 290 | } 291 | 292 | /* Return the Opera 15 and Beyond */ 293 | static char * 294 | parse_opera (char *token) 295 | { 296 | char *val = xmalloc (snprintf (NULL, 0, "Opera%s", token) + 1); 297 | sprintf (val, "Opera%s", token); 298 | 299 | return val; 300 | } 301 | 302 | char * 303 | verify_browser (char *str, char *type) 304 | { 305 | char *a, *b, *ptr, *slash; 306 | size_t i; 307 | 308 | if (str == NULL || *str == '\0') 309 | return NULL; 310 | 311 | for (i = 0; i < ARRAY_SIZE (browsers); i++) { 312 | if ((a = strstr (str, browsers[i][0])) == NULL) 313 | continue; 314 | 315 | /* check if there is a space char in the token string, that way strpbrk 316 | * does not stop at the first space within the token string */ 317 | if ((strchr (browsers[i][0], ' ')) != NULL && (b = strchr (a, ' ')) != NULL) 318 | b++; 319 | else 320 | b = a; 321 | 322 | xstrncpy (type, browsers[i][1], BROWSER_TYPE_LEN); 323 | /* Internet Explorer 11 */ 324 | if (strstr (a, "rv:11") && strstr (a, "Trident/7.0")) { 325 | return alloc_string ("MSIE/11.0"); 326 | } 327 | /* Opera +15 uses OPR/# */ 328 | if (strstr (a, "OPR") != NULL && (slash = strrchr (a, '/'))) { 329 | return parse_opera (slash); 330 | } 331 | /* Opera has the version number at the end */ 332 | if (strstr (a, "Opera") && (slash = strrchr (a, '/')) && a < slash) { 333 | memmove (a + 5, slash, strlen (slash) + 1); 334 | } 335 | /* IE Old */ 336 | if (strstr (a, "MSIE") != NULL) { 337 | if ((ptr = strpbrk (a, ";)-")) != NULL) 338 | *ptr = '\0'; 339 | a = char_replace (a, ' ', '/'); 340 | } 341 | /* all others */ 342 | else if ((ptr = strpbrk (b, ";) ")) != NULL) { 343 | *ptr = '\0'; 344 | } 345 | 346 | return alloc_string (a); 347 | } 348 | xstrncpy (type, "Unknown", BROWSER_TYPE_LEN); 349 | 350 | return alloc_string ("Unknown"); 351 | } 352 | -------------------------------------------------------------------------------- /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/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.io/" 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_AVGTS, 100 | MTRC_MAXTS, 101 | MTRC_METHODS, 102 | MTRC_PROTOCOLS, 103 | MTRC_AGENTS, 104 | } GMetric; 105 | 106 | typedef enum MODULES 107 | { 108 | VISITORS, 109 | REQUESTS, 110 | REQUESTS_STATIC, 111 | NOT_FOUND, 112 | HOSTS, 113 | OS, 114 | BROWSERS, 115 | VISIT_TIMES, 116 | REFERRERS, 117 | REFERRING_SITES, 118 | KEYPHRASES, 119 | #ifdef HAVE_LIBGEOIP 120 | GEO_LOCATION, 121 | #endif 122 | STATUS_CODES, 123 | } GModule; 124 | 125 | typedef struct GMetrics 126 | { 127 | /* metric id can be used to identified 128 | * a specific data field */ 129 | uint8_t id; 130 | char *data; 131 | char *method; 132 | char *protocol; 133 | 134 | float percent; 135 | int hits; 136 | int visitors; 137 | /* holder has a numeric value, while 138 | * dashboard has a displayable string value */ 139 | union 140 | { 141 | char *sbw; 142 | uint64_t nbw; 143 | } bw; 144 | /* holder has a numeric value, while 145 | * dashboard has a displayable string value */ 146 | union 147 | { 148 | char *sts; 149 | uint64_t nts; 150 | } avgts; 151 | 152 | /* holder has a numeric value, while 153 | * dashboard has a displayable string value */ 154 | union 155 | { 156 | char *sts; 157 | uint64_t nts; 158 | } maxts; 159 | } GMetrics; 160 | 161 | typedef struct GSubItem_ 162 | { 163 | GModule module; 164 | GMetrics *metrics; 165 | struct GSubItem_ *prev; 166 | struct GSubItem_ *next; 167 | } GSubItem; 168 | 169 | typedef struct GSubList_ 170 | { 171 | int size; 172 | struct GSubItem_ *head; 173 | struct GSubItem_ *tail; 174 | } GSubList; 175 | 176 | typedef struct GHolderItem_ 177 | { 178 | GSubList *sub_list; 179 | GMetrics *metrics; 180 | } GHolderItem; 181 | 182 | typedef struct GHolder_ 183 | { 184 | GHolderItem *items; /* items */ 185 | GModule module; /* current module */ 186 | int idx; /* index */ 187 | int holder_size; /* total number of allocated items */ 188 | int ht_size; /* total number of data items */ 189 | int sub_items_size; /* total number of sub items */ 190 | } GHolder; 191 | 192 | typedef struct GEnum_ 193 | { 194 | const char *str; 195 | int idx; 196 | } GEnum; 197 | 198 | typedef struct GDataMap_ 199 | { 200 | int data; 201 | int uniq; 202 | int root; 203 | } GDataMap; 204 | 205 | typedef struct GAgentItem_ 206 | { 207 | char *agent; 208 | } GAgentItem; 209 | 210 | typedef struct GAgents_ 211 | { 212 | int size; 213 | struct GAgentItem_ *items; 214 | } GAgents; 215 | 216 | /* single linked-list */ 217 | typedef struct GSLList_ 218 | { 219 | void *data; 220 | struct GSLList_ *next; 221 | } GSLList; 222 | 223 | /* *INDENT-OFF* */ 224 | GAgents *new_gagents (void); 225 | GAgentItem *new_gagent_item (uint32_t size); 226 | 227 | float get_percentage (unsigned long long total, unsigned long long hit); 228 | int get_module_enum (const char *str); 229 | int has_timestamp (const char *fmt); 230 | int str2enum (const GEnum map[], int len, const char *str); 231 | void display_storage (void); 232 | void display_version (void); 233 | 234 | /* single linked-list */ 235 | GSLList *list_create (void *data); 236 | GSLList *list_find (GSLList * node, int (*func) (void *, void *), void *data); 237 | GSLList *list_insert_append (GSLList * node, void *data); 238 | GSLList *list_insert_prepend (GSLList * list, void *data); 239 | int list_count (GSLList * list); 240 | int list_foreach (GSLList * node, int (*func) (void *, void *), void *user_data); 241 | int list_remove_nodes (GSLList * list); 242 | void format_date_visitors (GMetrics * metrics); 243 | /* *INDENT-ON* */ 244 | 245 | #endif 246 | -------------------------------------------------------------------------------- /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, "\"%lld\",", (long long) iter->metrics->maxts.nts); 121 | } 122 | 123 | if (conf.append_method && iter->metrics->method) 124 | fprintf (fp, "\"%s\"", iter->metrics->method); 125 | fprintf (fp, ","); 126 | 127 | if (conf.append_protocol && iter->metrics->protocol) 128 | fprintf (fp, "\"%s\"", iter->metrics->protocol); 129 | fprintf (fp, ","); 130 | 131 | fprintf (fp, "\""); 132 | escape_cvs_output (fp, iter->metrics->data); 133 | fprintf (fp, "\","); 134 | fprintf (fp, "\r\n"); /* parent idx */ 135 | } 136 | } 137 | 138 | /* generate CSV unique visitors stats */ 139 | static void 140 | print_csv_data (FILE * fp, GHolder * h, int processed) 141 | { 142 | GMetrics *nmetrics; 143 | int i; 144 | 145 | for (i = 0; i < h->idx; i++) { 146 | set_data_metrics (h->items[i].metrics, &nmetrics, processed); 147 | 148 | fprintf (fp, "\"%d\",", i); /* idx */ 149 | fprintf (fp, ","); /* no parent */ 150 | fprintf (fp, "\"%s\",", module_to_id (h->module)); 151 | fprintf (fp, "\"%d\",", nmetrics->hits); 152 | fprintf (fp, "\"%d\",", nmetrics->visitors); 153 | fprintf (fp, "\"%4.2f%%\",", nmetrics->percent); 154 | fprintf (fp, "\"%lld\",", (long long) nmetrics->bw.nbw); 155 | 156 | if (conf.serve_usecs) { 157 | fprintf (fp, "\"%lld\",", (long long) nmetrics->avgts.nts); 158 | fprintf (fp, "\"%lld\",", (long long) nmetrics->maxts.nts); 159 | } 160 | 161 | if (conf.append_method && nmetrics->method) 162 | fprintf (fp, "\"%s\"", nmetrics->method); 163 | fprintf (fp, ","); 164 | 165 | if (conf.append_protocol && nmetrics->protocol) 166 | fprintf (fp, "\"%s\"", nmetrics->protocol); 167 | fprintf (fp, ","); 168 | 169 | fprintf (fp, "\""); 170 | escape_cvs_output (fp, nmetrics->data); 171 | fprintf (fp, "\"\r\n"); 172 | 173 | if (h->sub_items_size) 174 | print_csv_sub_items (fp, h, i, processed); 175 | 176 | free (nmetrics); 177 | } 178 | } 179 | 180 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 181 | /* general statistics info */ 182 | static void 183 | print_csv_summary (FILE * fp, GLog * logger) 184 | { 185 | long long t = 0LL; 186 | int i = 0, total = 0; 187 | off_t log_size = 0; 188 | char now[DATE_TIME]; 189 | const char *fmt; 190 | 191 | generate_time (); 192 | strftime (now, DATE_TIME, "%Y-%m-%d %H:%M:%S", now_tm); 193 | 194 | /* generated date time */ 195 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%s\",\"%s\"\r\n"; 196 | fprintf (fp, fmt, i++, GENER_ID, now, OVERALL_DATETIME); 197 | 198 | /* total requests */ 199 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%d\",\"%s\"\r\n"; 200 | total = logger->process; 201 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_REQ); 202 | 203 | /* invalid requests */ 204 | total = logger->invalid; 205 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_FAILED); 206 | 207 | /* generated time */ 208 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%llu\",\"%s\"\r\n"; 209 | t = (long long) end_proc - start_proc; 210 | fprintf (fp, fmt, i++, GENER_ID, t, OVERALL_GENTIME); 211 | 212 | /* visitors */ 213 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%d\",\"%s\"\r\n"; 214 | total = get_ht_size_by_metric (VISITORS, MTRC_UNIQMAP); 215 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_VISITORS); 216 | 217 | /* files */ 218 | total = get_ht_size_by_metric (REQUESTS, MTRC_DATAMAP); 219 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_FILES); 220 | 221 | /* excluded hits */ 222 | total = logger->exclude_ip; 223 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_EXCL_HITS); 224 | 225 | /* referrers */ 226 | total = get_ht_size_by_metric (REFERRERS, MTRC_DATAMAP); 227 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_REF); 228 | 229 | /* not found */ 230 | total = get_ht_size_by_metric (NOT_FOUND, MTRC_DATAMAP); 231 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_NOTFOUND); 232 | 233 | /* static files */ 234 | total = get_ht_size_by_metric (REQUESTS_STATIC, MTRC_DATAMAP); 235 | fprintf (fp, fmt, i++, GENER_ID, total, OVERALL_STATIC); 236 | 237 | /* log size */ 238 | if (!logger->piping) 239 | log_size = file_size (conf.ifile); 240 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%jd\",\"%s\"\r\n"; 241 | fprintf (fp, fmt, i++, GENER_ID, (intmax_t) log_size, OVERALL_LOGSIZE); 242 | 243 | /* bandwidth */ 244 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%lld\",\"%s\"\r\n"; 245 | fprintf (fp, fmt, i++, GENER_ID, logger->resp_size, OVERALL_BANDWIDTH); 246 | 247 | /* log path */ 248 | if (conf.ifile == NULL) 249 | conf.ifile = (char *) "STDIN"; 250 | 251 | fmt = "\"%d\",,\"%s\",,,,,,,,\"%s\",\"%s\"\r\n"; 252 | fprintf (fp, fmt, i++, GENER_ID, conf.ifile, OVERALL_LOG); 253 | } 254 | 255 | #pragma GCC diagnostic warning "-Wformat-nonliteral" 256 | 257 | /* entry point to generate a a csv report writing it to the fp */ 258 | void 259 | output_csv (GLog * logger, GHolder * holder) 260 | { 261 | GModule module; 262 | FILE *fp = stdout; 263 | 264 | if (!conf.no_csv_summary) 265 | print_csv_summary (fp, logger); 266 | 267 | for (module = 0; module < TOTAL_MODULES; module++) { 268 | const GCSV *panel = panel_lookup (module); 269 | if (!panel) 270 | continue; 271 | if (ignore_panel (module)) 272 | continue; 273 | panel->render (fp, holder + module, logger->process); 274 | } 275 | 276 | fclose (fp); 277 | } 278 | -------------------------------------------------------------------------------- /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/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/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/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_avgts; 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/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/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/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/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/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_agent_key (const char *key); 49 | int ht_insert_agent_val (int nkey, const char *key); 50 | int ht_insert_hit (GHashTable * ht, int data_nkey, int uniq_nkey, int root_nkey); 51 | int ht_insert_host_agent (GHashTable * ht, int data_nkey, int agent_nkey); 52 | int ht_insert_keymap(GHashTable *ht, const char *value); 53 | int ht_insert_nkey_nval (GHashTable * ht, int nkey, int nval); 54 | int ht_insert_str_from_int_key (GHashTable * ht, int nkey, const char *value); 55 | int ht_insert_uniqmap (GHashTable * ht, char *uniq_key); 56 | int ht_insert_unique_key (const char *key); 57 | int ht_max_u64_from_int_key (GHashTable * ht, int data_nkey, uint64_t newval); 58 | 59 | char *get_host_agent_val (int agent_nkey); 60 | char *get_hostname (const char *host); 61 | char *get_node_from_key (int data_nkey, GModule module, GMetric metric); 62 | char *get_root_from_key (int root_nkey, GModule module); 63 | char * get_str_from_int_key (GHashTable *ht, int nkey); 64 | int get_int_from_keymap (const char *key, GModule module); 65 | int get_int_from_str_key (GHashTable * ht, const char *key); 66 | int get_num_from_key (int data_nkey, GModule module, GMetric metric); 67 | int process_host_agents (char *host, char *agent); 68 | uint64_t get_cumulative_from_key (int data_nkey, GModule module, GMetric metric); 69 | unsigned int get_uint_from_str_key (GHashTable *ht, const char *key); 70 | void free_storage (void); 71 | void *get_host_agent_list (int data_nkey); 72 | void init_storage (void); 73 | 74 | void free_agent_list (void); 75 | 76 | /* *INDENT-ON* */ 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /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/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/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/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->avgts = 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_AVGTS: 126 | ht = metrics->avgts; 127 | break; 128 | case MTRC_MAXTS: 129 | ht = metrics->maxts; 130 | break; 131 | case MTRC_METHODS: 132 | ht = metrics->methods; 133 | break; 134 | case MTRC_PROTOCOLS: 135 | ht = metrics->protocols; 136 | break; 137 | case MTRC_AGENTS: 138 | ht = metrics->agents; 139 | break; 140 | default: 141 | ht = NULL; 142 | } 143 | 144 | return ht; 145 | } 146 | 147 | void 148 | set_data_metrics (GMetrics * ometrics, GMetrics ** nmetrics, int processed) 149 | { 150 | GMetrics *metrics; 151 | float percent = get_percentage (processed, ometrics->hits); 152 | 153 | metrics = new_gmetrics (); 154 | metrics->bw.nbw = ometrics->bw.nbw; 155 | metrics->id = ometrics->id; 156 | metrics->data = ometrics->data; 157 | metrics->hits = ometrics->hits; 158 | metrics->percent = percent < 0 ? 0 : percent; 159 | metrics->visitors = ometrics->visitors; 160 | 161 | if (conf.serve_usecs && ometrics->hits > 0) { 162 | metrics->avgts.nts = ometrics->avgts.nts; 163 | metrics->maxts.nts = ometrics->maxts.nts; 164 | } 165 | 166 | if (conf.append_method && ometrics->method) 167 | metrics->method = ometrics->method; 168 | 169 | if (conf.append_method && ometrics->protocol) 170 | metrics->protocol = ometrics->protocol; 171 | 172 | *nmetrics = metrics; 173 | } 174 | 175 | void * 176 | get_storage_metric (GModule module, GMetric metric) 177 | { 178 | return get_storage_metric_by_module (module, metric); 179 | } 180 | -------------------------------------------------------------------------------- /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 *avgts; 97 | 98 | /* Slowest running requests */ 99 | void *maxts; 100 | 101 | /* Maps numeric data keys to string values. 102 | * 1 -> GET 103 | * 2 -> POST 104 | */ 105 | void *methods; 106 | 107 | /* Maps numeric data keys to string values. 108 | * 1 -> HTTP/1.1 109 | * 2 -> HTTP/1.0 110 | */ 111 | void *protocols; 112 | 113 | /* Maps numeric unique user-agent keys to the 114 | * corresponding numeric value. 115 | * 1 -> 3 116 | * 2 -> 4 117 | */ 118 | void *agents; 119 | 120 | } GStorageMetrics; 121 | 122 | typedef struct GStorage_ 123 | { 124 | GModule module; 125 | GStorageMetrics *metrics; 126 | } GStorage; 127 | 128 | extern GStorage *ht_storage; 129 | 130 | GMetrics *new_gmetrics (void); 131 | GStorageMetrics *get_storage_metrics_by_module (GModule module); 132 | GStorageMetrics *new_ht_metrics (void); 133 | GStorage *new_gstorage (uint32_t size); 134 | int *int2ptr (int val); 135 | uint64_t *uint642ptr (uint64_t val); 136 | void *get_storage_metric_by_module (GModule module, GMetric metric); 137 | void *get_storage_metric (GModule module, GMetric metric); 138 | void set_data_metrics (GMetrics * ometrics, GMetrics ** nmetrics, 139 | int processed); 140 | 141 | #endif // for #ifndef GSTORAGE_H 142 | -------------------------------------------------------------------------------- /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\"avgts\": %lld,\n", sep, 143 | (long long) nmetrics->avgts.nts); 144 | fprintf (fp, "%s\t\"maxts\": %lld,\n", sep, 145 | (long long) nmetrics->maxts.nts); 146 | } 147 | 148 | if (conf.append_method && nmetrics->method) 149 | fprintf (fp, "%s\t\"method\": \"%s\",\n", sep, nmetrics->method); 150 | 151 | if (conf.append_protocol && nmetrics->protocol) 152 | fprintf (fp, "%s\t\"protocol\": \"%s\",\n", sep, nmetrics->protocol); 153 | 154 | fprintf (fp, "%s\t\"data\": \"", sep); 155 | escape_json_output (fp, nmetrics->data); 156 | fprintf (fp, "\""); 157 | } 158 | 159 | static void 160 | print_json_host_geo (FILE * fp, GSubList * sub_list, char *sep) 161 | { 162 | GSubItem *iter; 163 | static const char *key[] = { 164 | "country", 165 | "city", 166 | "hostname", 167 | }; 168 | 169 | int i; 170 | if (sub_list == NULL) 171 | return; 172 | 173 | fprintf (fp, ",\n"); 174 | for (i = 0, iter = sub_list->head; iter; iter = iter->next, i++) { 175 | fprintf (fp, "%s\t\"%s\": \"", sep, key[iter->metrics->id]); 176 | escape_json_output (fp, iter->metrics->data); 177 | fprintf (fp, (i != sub_list->size - 1) ? "\",\n" : "\""); 178 | } 179 | } 180 | 181 | static void 182 | print_json_host_data (FILE * fp, GHolder * h, int processed) 183 | { 184 | GMetrics *nmetrics; 185 | char *sep = char_repeat (2, '\t'); 186 | int i; 187 | 188 | fprintf (fp, "\t\"%s\": [\n", module_to_id (h->module)); 189 | for (i = 0; i < h->idx; i++) { 190 | set_data_metrics (h->items[i].metrics, &nmetrics, processed); 191 | 192 | fprintf (fp, "%s{\n", sep); 193 | print_json_block (fp, nmetrics, sep); 194 | print_json_host_geo (fp, h->items[i].sub_list, sep); 195 | fprintf (fp, (i != h->idx - 1) ? "\n%s},\n" : "\n%s}\n", sep); 196 | 197 | free (nmetrics); 198 | } 199 | fprintf (fp, "\t]"); 200 | 201 | free (sep); 202 | } 203 | 204 | static void 205 | print_json_sub_items (FILE * fp, GHolder * h, int idx, int processed) 206 | { 207 | GMetrics *nmetrics; 208 | GSubItem *iter; 209 | GSubList *sub_list = h->items[idx].sub_list; 210 | char *sep = char_repeat (3, '\t'); 211 | int i = 0; 212 | 213 | if (sub_list == NULL) 214 | return; 215 | 216 | fprintf (fp, ",\n%s\"items\": [\n", sep); 217 | for (iter = sub_list->head; iter; iter = iter->next, i++) { 218 | set_data_metrics (iter->metrics, &nmetrics, processed); 219 | 220 | fprintf (fp, "%s{\n", sep); 221 | print_json_block (fp, nmetrics, sep); 222 | fprintf (fp, (i != sub_list->size - 1) ? "\n%s},\n" : "\n%s}\n", sep); 223 | free (nmetrics); 224 | } 225 | fprintf (fp, "\t\t\t]"); 226 | 227 | free (sep); 228 | } 229 | 230 | static void 231 | print_json_data (FILE * fp, GHolder * h, int processed) 232 | { 233 | GMetrics *nmetrics; 234 | char *sep = char_repeat (2, '\t'); 235 | int i; 236 | 237 | fprintf (fp, "\t\"%s\": [\n", module_to_id (h->module)); 238 | for (i = 0; i < h->idx; i++) { 239 | set_data_metrics (h->items[i].metrics, &nmetrics, processed); 240 | 241 | fprintf (fp, "%s{\n", sep); 242 | print_json_block (fp, nmetrics, sep); 243 | if (h->sub_items_size) 244 | print_json_sub_items (fp, h, i, processed); 245 | fprintf (fp, (i != h->idx - 1) ? "\n%s},\n" : "\n%s}\n", sep); 246 | 247 | free (nmetrics); 248 | } 249 | fprintf (fp, "\t]"); 250 | 251 | free (sep); 252 | } 253 | 254 | static void 255 | print_json_summary (FILE * fp, GLog * logger) 256 | { 257 | long long t = 0LL; 258 | int total = 0; 259 | off_t log_size = 0; 260 | char now[DATE_TIME]; 261 | 262 | generate_time (); 263 | strftime (now, DATE_TIME, "%Y-%m-%d %H:%M:%S", now_tm); 264 | 265 | fprintf (fp, "\t\"%s\": {\n", GENER_ID); 266 | 267 | /* generated date time */ 268 | fprintf (fp, "\t\t\"%s\": \"%s\",\n", OVERALL_DATETIME, now); 269 | 270 | /* total requests */ 271 | total = logger->process; 272 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_REQ, total); 273 | 274 | /* invalid requests */ 275 | total = logger->invalid; 276 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_FAILED, total); 277 | 278 | /* generated time */ 279 | t = (long long) end_proc - start_proc; 280 | fprintf (fp, "\t\t\"%s\": %llu,\n", OVERALL_GENTIME, t); 281 | 282 | /* visitors */ 283 | total = get_ht_size_by_metric (VISITORS, MTRC_UNIQMAP); 284 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_VISITORS, total); 285 | 286 | /* files */ 287 | total = get_ht_size_by_metric (REQUESTS, MTRC_DATAMAP); 288 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_FILES, total); 289 | 290 | /* excluded hits */ 291 | total = logger->exclude_ip; 292 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_EXCL_HITS, total); 293 | 294 | /* referrers */ 295 | total = get_ht_size_by_metric (REFERRERS, MTRC_DATAMAP); 296 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_REF, total); 297 | 298 | /* not found */ 299 | total = get_ht_size_by_metric (NOT_FOUND, MTRC_DATAMAP); 300 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_NOTFOUND, total); 301 | 302 | /* static files */ 303 | total = get_ht_size_by_metric (REQUESTS_STATIC, MTRC_DATAMAP); 304 | fprintf (fp, "\t\t\"%s\": %d,\n", OVERALL_STATIC, total); 305 | 306 | /* log size */ 307 | if (!logger->piping) 308 | log_size = file_size (conf.ifile); 309 | fprintf (fp, "\t\t\"%s\": %jd,\n", OVERALL_LOGSIZE, (intmax_t) log_size); 310 | 311 | /* bandwidth */ 312 | fprintf (fp, "\t\t\"%s\": %lld,\n", OVERALL_BANDWIDTH, logger->resp_size); 313 | 314 | /* log path */ 315 | if (conf.ifile == NULL) 316 | conf.ifile = (char *) "STDIN"; 317 | fprintf (fp, "\t\t\"%s\": \"", OVERALL_LOG); 318 | escape_json_output (fp, conf.ifile); 319 | fprintf (fp, "\"\n"); 320 | 321 | fprintf (fp, "\t},\n"); 322 | } 323 | 324 | /* entry point to generate a a json report writing it to the fp */ 325 | /* follow the JSON style similar to http://developer.github.com/v3/ */ 326 | void 327 | output_json (GLog * logger, GHolder * holder) 328 | { 329 | GModule module; 330 | FILE *fp = stdout; 331 | 332 | fprintf (fp, "{\n"); 333 | print_json_summary (fp, logger); 334 | for (module = 0; module < TOTAL_MODULES; module++) { 335 | const GJSON *panel = panel_lookup (module); 336 | if (!panel) 337 | continue; 338 | if (ignore_panel (module)) 339 | continue; 340 | panel->render (fp, holder + module, logger->process); 341 | module != TOTAL_MODULES - 1 ? fprintf (fp, ",\n") : fprintf (fp, "\n"); 342 | } 343 | fprintf (fp, "}"); 344 | 345 | fclose (fp); 346 | } 347 | -------------------------------------------------------------------------------- /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/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 | /* ###NOTE: The size of the list is proportional to the run time, 35 | * which makes this pretty slow */ 36 | 37 | /* {"search string", "belongs to"} */ 38 | static const char *os[][2] = { 39 | {"Android", "Android"}, 40 | {"Windows NT 10.0", "Windows"}, 41 | {"Windows NT 6.3; ARM", "Windows"}, 42 | {"Windows NT 6.3", "Windows"}, 43 | {"Windows NT 6.2; ARM", "Windows"}, 44 | {"Windows NT 6.2", "Windows"}, 45 | {"Windows NT 6.1", "Windows"}, 46 | {"Windows NT 6.0", "Windows"}, 47 | {"Windows NT 5.2", "Windows"}, 48 | {"Windows NT 5.1", "Windows"}, 49 | {"Windows NT 5.01", "Windows"}, 50 | {"Windows NT 5.0", "Windows"}, 51 | {"Windows NT 4.0", "Windows"}, 52 | {"Windows NT", "Windows"}, 53 | {"Win 9x 4.90", "Windows"}, 54 | {"Windows 98", "Windows"}, 55 | {"Windows 95", "Windows"}, 56 | {"Windows CE", "Windows"}, 57 | {"Windows Phone 8.1", "Windows"}, 58 | {"Windows Phone 8.0", "Windows"}, 59 | 60 | {"Googlebot", "Unix-like"}, 61 | {"bingbot", "Windows"}, 62 | 63 | {"iPad", "iOS"}, 64 | {"iPod", "iOS"}, 65 | {"iPhone", "iOS"}, 66 | {"AppleTV", "iOS"}, 67 | {"iTunes", "Macintosh"}, 68 | {"OS X", "Macintosh"}, 69 | 70 | {"Debian", "Linux"}, 71 | {"Ubuntu", "Linux"}, 72 | {"Fedora", "Linux"}, 73 | {"Mint", "Linux"}, 74 | {"SUSE", "Linux"}, 75 | {"Mandriva", "Linux"}, 76 | {"Red Hat", "Linux"}, 77 | {"Gentoo", "Linux"}, 78 | {"CentOS", "Linux"}, 79 | {"PCLinuxOS", "Linux"}, 80 | {"Linux", "Linux"}, 81 | 82 | {"FreeBSD", "BSD"}, 83 | {"NetBSD", "BSD"}, 84 | {"OpenBSD", "BSD"}, 85 | {"DragonFly", "BSD"}, 86 | {"PlayStation", "BSD"}, 87 | 88 | {"CrOS", "Chrome OS"}, 89 | {"SunOS", "Unix-like"}, 90 | {"QNX", "Unix-like"}, 91 | {"BB10", "Unix-like"}, 92 | 93 | {"BlackBerry", "Others"}, 94 | {"Sony", "Others"}, 95 | {"AmigaOS", "Others"}, 96 | {"SymbianOS", "Others"}, 97 | {"Nokia", "Others"}, 98 | {"Nintendo", "Others"}, 99 | {"Apache", "Others"}, 100 | {"Xbox One", "Windows"}, 101 | {"Xbox", "Windows"}, 102 | }; 103 | 104 | /* get Android Codename */ 105 | static char * 106 | get_real_android (const char *droid) 107 | { 108 | if (strstr (droid, "5.0") || strstr (droid, "5.1")) 109 | return alloc_string ("Lollipop"); 110 | else if (strstr (droid, "4.4")) 111 | return alloc_string ("KitKat"); 112 | else if (strstr (droid, "4.3") || strstr (droid, "4.2") || 113 | strstr (droid, "4.1")) 114 | return alloc_string ("Jelly Bean"); 115 | else if (strstr (droid, "4.0")) 116 | return alloc_string ("Ice Cream Sandwich"); 117 | else if (strstr (droid, "3.")) 118 | return alloc_string ("Honeycomb"); 119 | else if (strstr (droid, "2.3")) 120 | return alloc_string ("Gingerbread"); 121 | else if (strstr (droid, "2.2")) 122 | return alloc_string ("Froyo"); 123 | else if (strstr (droid, "2.0") || strstr (droid, "2.1")) 124 | return alloc_string ("Eclair"); 125 | else if (strstr (droid, "1.6")) 126 | return alloc_string ("Donut"); 127 | else if (strstr (droid, "1.5")) 128 | return alloc_string ("Cupcake"); 129 | return alloc_string (droid); 130 | } 131 | 132 | /* get Windows marketing name */ 133 | static char * 134 | get_real_win (const char *win) 135 | { 136 | if (strstr (win, "10.0")) 137 | return alloc_string ("Windows 10"); 138 | else if (strstr (win, "6.3")) 139 | return alloc_string ("Windows 8.1"); 140 | else if (strstr (win, "6.3; ARM")) 141 | return alloc_string ("Windows RT"); 142 | else if (strstr (win, "6.2; ARM")) 143 | return alloc_string ("Windows RT"); 144 | else if (strstr (win, "6.2")) 145 | return alloc_string ("Windows 8"); 146 | else if (strstr (win, "6.1")) 147 | return alloc_string ("Windows 7"); 148 | else if (strstr (win, "6.0")) 149 | return alloc_string ("Windows Vista"); 150 | else if (strstr (win, "5.2")) 151 | return alloc_string ("Windows XP x64"); 152 | else if (strstr (win, "5.1")) 153 | return alloc_string ("Windows XP"); 154 | else if (strstr (win, "5.0")) 155 | return alloc_string ("Windows 2000"); 156 | return NULL; 157 | } 158 | 159 | /* get Mac OS X Codename */ 160 | static char * 161 | get_real_mac_osx (const char *osx) 162 | { 163 | if (strstr (osx, "10.10")) 164 | return alloc_string ("OS X Yosemite"); 165 | else if (strstr (osx, "10.9")) 166 | return alloc_string ("OS X Mavericks"); 167 | else if (strstr (osx, "10.8")) 168 | return alloc_string ("OS X Mountain Lion"); 169 | else if (strstr (osx, "10.7")) 170 | return alloc_string ("OS X Lion"); 171 | else if (strstr (osx, "10.6")) 172 | return alloc_string ("OS X Snow Leopard"); 173 | else if (strstr (osx, "10.5")) 174 | return alloc_string ("OS X Leopard"); 175 | else if (strstr (osx, "10.4")) 176 | return alloc_string ("OS X Tiger"); 177 | else if (strstr (osx, "10.3")) 178 | return alloc_string ("OS X Panther"); 179 | else if (strstr (osx, "10.2")) 180 | return alloc_string ("OS X Jaguar"); 181 | else if (strstr (osx, "10.1")) 182 | return alloc_string ("OS X Puma"); 183 | else if (strstr (osx, "10.0")) 184 | return alloc_string ("OS X Cheetah"); 185 | return alloc_string (osx); 186 | } 187 | 188 | static char * 189 | parse_others (char *agent, int spaces) 190 | { 191 | char *p; 192 | int space = 0; 193 | p = agent; 194 | while (*p != ';' && *p != ')' && *p != '(' && *p != '\0') { 195 | if (*p == ' ') 196 | space++; 197 | if (space > spaces) 198 | break; 199 | p++; 200 | } 201 | *p = 0; 202 | 203 | return agent; 204 | } 205 | 206 | static char * 207 | parse_osx (char *agent) 208 | { 209 | int space = 0; 210 | char *p; 211 | 212 | p = agent; 213 | while (*p != ';' && *p != ')' && *p != '(' && *p != '\0') { 214 | if (*p == '_') 215 | *p = '.'; 216 | if (*p == ' ') 217 | space++; 218 | if (space > 3) 219 | break; 220 | p++; 221 | } 222 | *p = 0; 223 | 224 | return agent; 225 | } 226 | 227 | static char * 228 | parse_android (char *agent) 229 | { 230 | char *p; 231 | p = agent; 232 | while (*p != ';' && *p != ')' && *p != '(' && *p != '\0') 233 | p++; 234 | *p = 0; 235 | 236 | return agent; 237 | } 238 | 239 | char * 240 | verify_os (const char *str, char *os_type) 241 | { 242 | char *a, *b; 243 | int spaces = 0; 244 | size_t i; 245 | 246 | if (str == NULL || *str == '\0') 247 | return NULL; 248 | 249 | for (i = 0; i < ARRAY_SIZE (os); i++) { 250 | if ((a = strstr (str, os[i][0])) == NULL) 251 | continue; 252 | 253 | xstrncpy (os_type, os[i][1], OPESYS_TYPE_LEN); 254 | /* Windows */ 255 | if ((strstr (str, "Windows")) != NULL) { 256 | return conf.real_os && (b = get_real_win (a)) ? b : xstrdup (os[i][0]); 257 | } 258 | /* Android */ 259 | if ((strstr (a, "Android")) != NULL) { 260 | a = parse_android (a); 261 | return conf.real_os ? get_real_android (a) : xstrdup (a); 262 | } 263 | /* Mac OS X */ 264 | if ((strstr (a, "OS X")) != NULL) { 265 | a = parse_osx (a); 266 | return conf.real_os ? get_real_mac_osx (a) : xstrdup (a); 267 | } 268 | /* all others */ 269 | spaces = count_matches (os[i][0], ' '); 270 | return alloc_string (parse_others (a, spaces)); 271 | } 272 | xstrncpy (os_type, "Unknown", OPESYS_TYPE_LEN); 273 | 274 | return alloc_string ("Unknown"); 275 | } 276 | -------------------------------------------------------------------------------- /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/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/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 "" \ 35 | "iVBORw0KGgoAAAANSUhEUgAAAMgAAAAeCAYAAABpP1GsAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI" \ 36 | "WXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wIOBC8F0NxENwAAFlpJREFUeNrtfHmUHdV55+8udWt9" \ 37 | "S+9amlavkrq1IDVSa7FGaAEbMIYBDIaxjBPZeAKYY4yTmDkmiWMnZxIPYYkdMoODDsYiTjAYRgZr" \ 38 | "hKRuhCy0oD4IgUBqtVpCQmrUWrrf67fVq7r3zh+81zw1CtgTRraU/p3zTr+q993v3lv17V9VA2MY" \ 39 | "wxj+42KhZX3k74tt+989R319/cfSNDU1jd2M8xDkQt3YcsfBxkwGghAy17Kutwn5gkXIFE5IDQUG" \ 40 | "Qq37FfBWRuuu3lxu42Gl0kWFeTmb/a3nmzhxIrNtew7n/F5KaSkDBuDwO++88+10Oq3GRG5MQX4v" \ 41 | "MNUwSCVjs11Kf1XDWE0FYzAIGdmwAqAB5LXGsFJIK/XcU6nUdf+v8zU2NlY4jvNAPB6/1TRNaK3f" \ 42 | "v8CEQGt9LAiCP9i8efP6MZE7v0AvxE3VUEqqOZ8VZ2zbVCFqJnIOkxDQgkUgBbPOATiEoIaxoMEw" \ 43 | "guL4BR8Rli0dFZI1NDQAAEzTjDDGbrAsC5RSMMbAGCt+rzAM4/MA0NHRMVqx/s25Wlpazpjj48K3" \ 44 | "+vp6TJs27eyh5OLFZ4R5HzVvKc/flO5CBb+QNrPAsrA1l8M004yahDzRwLnhEAL98UPTAH5RPNia" \ 45 | "y2GBZc21Kf2vNiHzDUKqKTAkte7Oab0awAu76+ow8/BhHDx4EJWVlQLAYsuyXErpiPcogUkpXVJX" \ 46 | "V2fu2LHDLwpeX18f8vm82dTU9CXDML5oGEYjpZRrrQ8qpV7L5/OrAWw/ePAgGhoapnLOvyWEWMAY" \ 47 | "qyaEnFZK7ZVS/vLIkSNPAsgdOnQI9fX11S0tLXdxzi/nnNdRSgOt9bYTJ048ceDAgReKC1JKxZqb" \ 48 | "m79mGMb1nPNJBbpDWutjUsptuVyuE8AbSqmyAt11hmFMIoT4Wut3lFJHlVJbc7lc5/jx4/f29/fL" \ 49 | "sRDrPMA002TjGLtqHGNr6jgvVY5jCvjqDwYH1wLArdFoWYTSFhNYTIE2X+tv/TCRGFxgWa5FyN9X" \ 50 | "MrZyfInnKYZlea2RUOqVg/n8VZtyuUTBitbYtv1EZWXlpw3DAIC01vp1pVQrY6ysMPxEGIbf6urq" \ 51 | "+unMmTOxe/duNDQ01Jmm+VQ0Gp3neR4opcWQDFprBEGAbDa7cXBw8MeO4/xLPB6HEAKEvH/btNaQ" \ 52 | "UsL3/f5MJnPr8PCwadv2mlgsRi3LAiFkhF8Yhshms2t6e3tv8Dyv1nGcVdFodKnneWfQaa2hlEIY" \ 53 | "hlv6+/u/LYT4XjQaXea67lnpgiDYMjg4eO2ePXtOjYVY5wHKCbEE8Ok4Y6WnByVwzQ8GB9feE48D" \ 54 | "AJ5IJgeV1jseGBq6//6hoZU/TCQG55qm61D6J7WGsbLJMOAQAjYqLLPfD8kWzDDNNUXmQogKwzAu" \ 55 | "LygHAKSllGsymczmEm9STgi5FgB2796N+vr6cZZl3V9eXj4vHo+DMTYi+IQQUEphmuYp13XDysrK" \ 56 | "JysrK1EU+hHrRgg45/A870AQBHnP835RVVVFXdcdUbYinWEYiEQiV7S2tq6yLOvySCSyNBaLfYiO" \ 57 | "UgrOeSCE2C+EmBGJRJZFo9F/i07atv3qnj17Ti1atGgsxDofYFLKDUJm2IUkvPCn938MDnYvtCy+" \ 58 | "I5frWOY4V1Gtw/35PC77IKfIg5BklNK7x32gXApAjwaeU0A7AT5dyGOIS+nUr8diV/6ouflFks1+" \ 59 | "xrIsUrSuAIaTyeRPlFKnLcu6pqA4jFJ68Zw5c6p37tw5YNt2q23bN7quWxyjAOwF8LTWOqa1XgBg" \ 60 | "mtbatm2bMcZGeAN4GsARpdQMAK1Syj2Msas9zxOGYUBrrQCszefzdyil2jjnD3LOpxJChBDiirKy" \ 61 | "shbrgzxrGMBjQRD8mBAyi1K6GMC4XC73hmmaHfYH1ycB4NEgCB4nhLQX6MYD2AQAv/71r8cU5LxQ" \ 62 | "EIAIQlz6gaUNJbCvoCk8xtjCizj/jvvh3CQTAq+EWsf4B8p1LKv1vIeHhpI3e16ZR+lTFYxdVuAc" \ 63 | "sYDLQcgWSulNtm0XBTgEsKu7u/u9Sy655JVcLgchBLTWIIRURKPRmwH8iDE2z7ZtlCjVm5lMZs6W" \ 64 | "LVtGigUXX3xxk23bWz3PK546DeD769evf6h04ZMnT57sed4zlmUVeb3NGPvmpk2bDgM43NHRUWPb" \ 65 | "9uOmaYJSWuW6blVJrhQJguCWRCJhpVKpZ/fv3387AF1XVzehurr6gRK6WBAEKxKJhDs8PPxsb2/v" \ 66 | "10YKF0uXoqura6yKdR4lVXLUKa8QG4AWrIIgZPTHMQm5zKa0VHEOPzw0lASAfimDIaW25LUuhlyC" \ 67 | "UNoUB2qEEPPZB15nkBDyZOH7O0qpF5UaaX+UEUI+A4BTShsL1h4AfK319i1btgRLliwZmVxrXRaG" \ 68 | "YRWlI7dpQEq57kNWjnOPEFJbpNNaT0un0z3t7e26vb1da60fp5TqQniUIITsLVkTDMOoKS8v/6MJ" \ 69 | "Eyasmz9/vpw9e/YPgyDIE0JeDsNwJLQyDGN8eXn5HRMnTlxfoHuooaEheqEqxwXpQRQgCXBQAfMK" \ 70 | "YsUJMG++YYi0UmEFpXsV8LQEAg1UU2B50dewwmek0AOMNPxyWqtAaz/UGigITEhIdbVSnxvlCary" \ 71 | "+fwvLrnkEmitz8gtAIBSOqW9vX2BUoqXCL7SWvsA8NJLL5XSshIaANBhGPqj98wYo5RSq7gGQggs" \ 72 | "y0JJeAStNSmGckqpZ4MgsIUQdxf5U0ohhIAQgjiO83XP82oHBgZuF0LMkVL+4VnoqOM433Bd96KD" \ 73 | "Bw/eMNYHOU+Q0jofAtvCklIrASrmuO6ju30/fD6dfv6RROLGHwwO/pf9+fz3h5Qqep1QA4dKvAcl" \ 74 | "wEgDQhBiaeBiVkxUgXzAecozzZtLG4MFS4uKigpUVlaiJDwqosJ13c9prXtKxtgA2s8i+KcKOUJR" \ 75 | "yGOU0rmFsKpU+DOEkP4SfoeVUitzudzMXC43J5fLzQnDcJaUclY2m73a9/0HNm/e/E3f95uCIPg7" \ 76 | "pdTh0vUzxmCaZltNTc3MLVu2rPR9f3IQBA8qpd4dtT5YljX50ksvXXyhKsgF2Um/JRKZ4FJ6oIpS" \ 77 | "q3jbJYDTUvqnldoaam1SoNWhNF7DmLYJIRrIhsD2vNZLivmJBnIJKX/+ehA8YhOyrJKxv27gvHjR" \ 78 | "ho7H4y/uq629yf2Y570+5OWU2n7q1Kk/9Txvk+M4xbJpJpPJ/OuxY8ceoZTWcc6vNE3z+lgsVl6k" \ 79 | "AYAwDPedPHny3mQy+Z5hGIsL/Ykqz/N2OI5zS8GLyDAMO48ePfoX+Xw+zxirNQzjaiHEFYZhbMjl" \ 80 | "coeEEPcBeDiZTP6kr6/vjUWLFl3GGFtfouyD2Wx2KJPJlEspHx0eHv5JX1/fnkWLFn2WMfZ8Cd0+" \ 81 | "AN9Yv379ujEFOU/wWdc1Y5TeMZ7zB4xRvxUEf6R0WwI/ANYnpTxWxtjXSnsfaaUgAUQoHQnBQsbe" \ 82 | "2zZ58gvMML4ihCjykFrrE2fxzCYhJFZyfCidTt+nlPpKJBJZWuIJ4Ps+lFIwDAOc8wBACkCMEDLC" \ 83 | "MwgCBEEwEu4QQo75vr+dMXZdsSCgtUY+nx+h45zDMAxIKQez2exBx3HaKaXwfR+5XA5aa7iui1Jv" \ 84 | "WKiG0SKvXC4HAHAcp5Ruq5Tyi52dnQfHcpDzAFe7Lp5Pp/2Vkcg/DEkZL2Psz/koi3A2q6CBHQz4" \ 85 | "y6RS73FClsYobSnGoJEz8wAQrY8O2PbdvpQPxxyntCS8dsOGDZ8bzXvevHmtQoi3SipdVaZpXpxM" \ 86 | "Ju/yfX+baZpesb9gnemNDAApKWUXpfT6kmQZJT0XAIhzzo8GQfAdxthfF3sWpmnCNM0znBdjTNu2" \ 87 | "3VIsKliWNdJfKSoWgNNKqf1a6+mMMbe4rrPQZQD8qrOz8+CyZcvQ2dk5loP8vuP5dBo3eR5WDQ/n" \ 88 | "H0sm/2JQylk+8IIE8mdRim4NfDcAJv3t4OBiAN3/mkq9m1Jq5rBS/y0Ajo4qBSc18HdHOZ+1s6yM" \ 89 | "UGBCSRKttdZrz7ambDY77Pv+qyWVI5cxdlN3d/dbvu+35PP5x5RSuVHDdmit7zxy5Mikt99++6Zs" \ 90 | "NntjGIb7Rj3GMqi1fkxrvbCrq+uu4eHh+3O53PVSyt1nedxlvdb6ug0bNlSkUqnx+Xz+dinlRqVU" \ 91 | "pui9Cn+7tda3bdy4cX4qlZqQz+e/LqXsUkplR9Ht0Frfsn79+r8CcEEqxwWP22KxM44vdxzx1Wi0" \ 92 | "5guue8YTh3cXuuuF/AUPVVefMW5lNFpzqWn+Rt728ssvP+N41qxZv/F6Z86cac+bN6+s9NzSpUvx" \ 93 | "qU99arRHqhZCjGjmsmXLAOBDdB0dHdUdHR3R0nNLliz5EF1ZWRmbP39+xcfNW1tby89GN4YxjGEM" \ 94 | "YxjDGM5bnO2diNbW1t/JHA0NDV5jY+MNzc3N7f+/9z36fYvW1taRGkNzc/MZv02dOvWcVCV/V/P+" \ 95 | "LvB7u7GmpiaTEPLHnPPSco0vpXzPsqxVlNIlr7/++qZPet4JEyYYnufdaJrmk5zzL7722mv/XF9f" \ 96 | "zwDUAogPDQ3trq2tbWaM9cRisQdffvnle86BQE42DOMF0zQHd+3adcYbVy0tLdM55//HNM2+Xbt2" \ 97 | "nbOGXUtLyyLDMJ4TQry0a9euz1+oCvJ7W+YVQoyzbfuvysrKSisnb58+ffpn8Xg85/s+b2lpuUcp" \ 98 | "9dyBAwf6Ghsbr+WczwjD8Km+vr6egpLZAL5EKQ2VUkOMsXd93z9sGMaXKaXHenp6ftrQ0GAQQj7D" \ 99 | "OZ+ilHqbUtohhHBisVjCtu23AIAxNtU0zZ9FIpHm8vLy65LJ5FtCiO8lk8l1LS0tKwEYSqmjlNKa" \ 100 | "bDb7vGman6eU7t6/f//mhoaGRsbYTZTSvp6enqcKAj8ewB2c884gCE5SShfncrlVpml+lXN+aO/e" \ 101 | "vS80NTV9gTE20ff9J03TZKZpmrFYbKC1tfWLQRBkent7nwUA0zQt0zSN8vLy7sKeb2aMNSilXuzt" \ 102 | "7e1ubGxsoJReSQgZKHTih3p6ep4BgMbGxqbCbwmttUMpHZBS9lBKrwbQo7WuopR2Z7PZvUKIayil" \ 103 | "ca31ECGECyGytm1nPM+jM2bM+Ibv+51BEJzinN9MKe0Pw7CPENKC99tOCUrpjlwulxdCfJ4QwoMg" \ 104 | "eIpSWk0pvYIQclprPcw5f2Xv3r3HzzsFWbFiBQHwZQD152BNEsDW1atXbwBA5s2b92PP827ZuHGj" \ 105 | "V6gKPU0ptUzT3DBu3LhAa72Uc77L87z7HMfp0lrfF41GJ+3ateu4bdsRzvkD8XjcDcNQhmH4tVQq" \ 106 | "1RWLxd5ljIny8vJFJ0+efDYSifwyFosFUkqDUprK5/Mvcc79IAjejUajwjTNpdFodEYkEkEQBPf7" \ 107 | "vn+v67p3CyEOUUq/F41GJ0opUWy8McZgGMbr2Wz2Rsdx9pSVlR2ilLKKiopLtm7d+m3P88oYY192" \ 108 | "HKdmaGjIi0Qic1Op1Huc8791Xfc+SukjjuPc5jhOt9b6K0NDQ3cwxi6ilF5UVVV1FaX0aFVVVWbr" \ 109 | "1q3rOOcOIaQ6CAI2bdq0VY7j/KHjOEcA3O553oNBEFwTi8WWcM6hlAo45w/19PQ809DQMNW27VWx" \ 110 | "WGxB4aHJrNb6x4lE4iLXdf/GNE1IKUEI2XD8+PFnPM/7R8/zlFKKMsbWJJPJNZTSOAAajUa/zhir" \ 111 | "OXny5GHHce4VQvyvXC53p+M4nyqUwbcnEokfGIbxB47jLLZt+4RS6qpEIvGibdsPOo6DMAzXO46z" \ 112 | "uaOjY7lSajnOUpb/pG0wgM2rV69e+0l4kKKCLDkHChIAeBDAhra2NjebzbZ6npcAgLa2tohSqpZS" \ 113 | "epgQchWANznnfiwWu9V13TeGh4e3CSH+U0VFRTuAtYQQhzHmCiH+dxAEd+Xz+S/FYjGTMbYpnU5P" \ 114 | "9zxvgeu6JBqNDkgpZ0spHxFCfFZKySmlYWdn50kAiEajTwO4W2u97qWXXrpz5syZ3zYMI6eUOkYp" \ 115 | "reGcPxYEwRuGYfyZbdu3BUHwp5RSu7y8/FrP8xQhZFMmk5kdiUSmA4BSymeMDVBKZ7muO9227UBr" \ 116 | "fZdhGAdTqdQrlmXdF4lEtqZSqTcMw7ghGo1eIaVMcc6/mUql3jVN8+loNOoVeDVxzk9rrbXjOFdH" \ 117 | "o9E/TyQSa0zT3B6NRi/1fX+G53l/PDQ0tFYI8YYQYgAAXNedaJrmbM/z7k0kEuuFEDsZYz5jrIlz" \ 118 | "vocQ8jeEkNsopWWxWOxqx3E2ZLPZe4QQjzPGPK21wRhLaq1fVUrFGWMrXNd9x7KsHZs3b/6zcePG" \ 119 | "uZMmTXrItu1rHMf5bn9/fxCLxZa4rrspk8kEhmG0RSKRgFI6aJrmdw8fPvyP8+fPt5VSVwL41jly" \ 120 | "EBEAH6kg9LdQEO8cLdrA+w/vgVJKCSHjtdZ7C6EOI4Q0AtjV39+vMpkMKKUHGGO1jLGEbduCc75K" \ 121 | "SrkFAA3DcCrnXBJCntq2bdvxIAhqDMNQjLFhx3FeU0r9TyFEJWOMDQ4OtqXT6bla6yNa67jWel9x" \ 122 | "Qdls1s3n801a68qpU6fOB1DHOVf5fJ4zxpTW+sDw8HCzlDKbSqWOZzKZCVrrQ5zzWiGE5Jwnbdve" \ 123 | "ppT6JwAIwzAPIMsYm2vb9jtKqT7LsuYKIV7M5XKnGWNljLGMZVk5xtg/h2F4kjFmpNPpBZlM5ptK" \ 124 | "qROU0jcACELIeErpsNb6KOe8TErZls/nby+EfK9yzqO+71/r+/7DSqkBSmkvABiGwTnnIgiCi9Lp" \ 125 | "9M1BEBxXSp0mhDRxzo8PDAz0pdPpiFLqPcaYRym1kslkezabbVRKnSSEVFJKh8Mw3B6GYTel9KJI" \ 126 | "JFJnmuY/RaPR6vLy8ie11l8G8Oi2bds2u647kXPucc5D0zSPEUKe0VonAfQSQp7v6+sLCt7GPocR" \ 127 | "lP3vDrFWrFiB1atXSwBzz3n8xzknhDRSSncCACHEZoxVEUL6AbQWwoZuKeV/l1J+hxCySCn1xMsv" \ 128 | "v5ysra01CCF1jDGmlHpXSpkvKM9NjLF7tNZvSil/EYZhbxiG11VUVPwcQJwQsh1AOyHk5yNWhNIM" \ 129 | "53w/IeTG8vLyQ9lsdialFEEQxAzDEEEQ9FNKr2SM8VQqNeC6bh1j7GcA/kVKeWthvlfDMFxdsPoB" \ 130 | "gAQhRCqlns7lcte7rqsppc/4vv9eNBpdJaVcCWBJGIaPB0FQJoQwhRCfrqioqOWc/8natWt76uvr" \ 131 | "awgh0xljhpRyA4BJhJA7ysrKhhhj97755puPNzc3+4yxqysqKmoIIckwDA8BgJRyL6X0VwDuLCsr" \ 132 | "SwghTqVSqRSldDpjbFcYhooQMo1zviafzx+VUj5aXV19CSEESqlMYd4wnU4fUEoNK6Vgmubz69at" \ 133 | "e66tre1213WvjcfjCILgvtbW1rknTpz4I9d1fyml/M8ABoMg+CmAGsMwlJTyFACsXr06CeDOwuec" \ 134 | "YMWKFSjMfX5VD9rbz6ygLl++/DceO7oDDACXXnrpb72GZcuWkTlz5nyi+5o9e/YnwmfhwoUfW4Gc" \ 135 | "MmXK3La2trc6Ojp2LFy4UC1fvvyZT/o+TZ8+/ftz5szRy5Yt+9FH0Z3l0ZczUPqi2FiZdwznBNOm" \ 136 | "TavyPO8yx3FaCCFvaq2f6+rq+kT+u+OUKVOwb98+zJ07d6LWum7nzp1bL7vsMmzYsGHswo9hDP9R" \ 137 | "8H8BM/XVggoDbGIAAAAASUVORK5CYII=" 138 | 139 | typedef struct GOutput_ 140 | { 141 | GModule module; 142 | void (*render) (FILE * fp, GHolder * h, int processed, int max_hit, 143 | int max_vis, const struct GOutput_ *); 144 | void (*metrics_callback) (GMetrics * metrics); 145 | const char *clabel; /* column label */ 146 | int8_t visitors; 147 | int8_t hits; 148 | int8_t percent; 149 | int8_t bw; 150 | int8_t avgts; 151 | int8_t maxts; 152 | int8_t protocol; 153 | int8_t method; 154 | int8_t data; 155 | int8_t graph; 156 | int8_t sub_graph; 157 | } GOutput; 158 | 159 | void output_html (GLog * logger, GHolder * holder); 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /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 (*maxts) (int data_nkey, uint64_t ts, GModule module); 122 | void (*method) (int data_nkey, const char *method, GModule module); 123 | void (*protocol) (int data_nkey, const char *proto, GModule module); 124 | void (*agent) (int data_nkey, int agent_nkey, GModule module); 125 | } GParse; 126 | 127 | GLog *init_log (void); 128 | GLogItem *init_log_item (GLog * logger); 129 | GRawDataItem *new_grawdata_item (unsigned int size); 130 | GRawData *new_grawdata (void); 131 | int parse_log (GLog ** logger, char *tail, int n); 132 | int test_format (GLog * logger); 133 | void free_raw_data (GRawData * raw_data); 134 | void reset_struct (GLog * logger); 135 | void verify_formats (void); 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /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/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/sort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sort.c -- functions related to sort functionality 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 | #include 31 | 32 | #include "settings.h" 33 | #include "util.h" 34 | 35 | #include "sort.h" 36 | 37 | /* *INDENT-OFF* */ 38 | const int sort_choices[][SORT_MAX_OPTS] = { 39 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 40 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, SORT_BY_PROT, SORT_BY_MTHD, -1}, 41 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, SORT_BY_PROT, SORT_BY_MTHD, -1}, 42 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, SORT_BY_PROT, SORT_BY_MTHD, -1}, 43 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 44 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 45 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 46 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 47 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 48 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 49 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 50 | #ifdef HAVE_LIBGEOIP 51 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 52 | #endif 53 | {SORT_BY_HITS, SORT_BY_VISITORS, SORT_BY_DATA, SORT_BY_BW, SORT_BY_AVGTS, SORT_BY_MAXTS, -1}, 54 | }; 55 | 56 | static GEnum FIELD[] = { 57 | {"BY_HITS" , SORT_BY_HITS } , 58 | {"BY_VISITORS" , SORT_BY_VISITORS } , 59 | {"BY_DATA" , SORT_BY_DATA } , 60 | {"BY_BW" , SORT_BY_BW } , 61 | {"BY_AVGTS" , SORT_BY_AVGTS } , 62 | {"BY_MAXTS" , SORT_BY_MAXTS } , 63 | {"BY_PROT" , SORT_BY_PROT } , 64 | {"BY_MTHD" , SORT_BY_MTHD } , 65 | }; 66 | 67 | static GEnum ORDER[] = { 68 | {"ASC" , SORT_ASC } , 69 | {"DESC" , SORT_DESC } , 70 | }; 71 | 72 | GSort module_sort[TOTAL_MODULES] = { 73 | {VISITORS , SORT_BY_DATA , SORT_DESC } , 74 | {REQUESTS , SORT_BY_HITS , SORT_DESC } , 75 | {REQUESTS_STATIC , SORT_BY_HITS , SORT_DESC } , 76 | {NOT_FOUND , SORT_BY_HITS , SORT_DESC } , 77 | {HOSTS , SORT_BY_HITS , SORT_DESC } , 78 | {OS , SORT_BY_HITS , SORT_DESC } , 79 | {BROWSERS , SORT_BY_HITS , SORT_DESC } , 80 | {VISIT_TIMES , SORT_BY_DATA , SORT_ASC } , 81 | {REFERRERS , SORT_BY_HITS , SORT_DESC } , 82 | {REFERRING_SITES , SORT_BY_HITS , SORT_DESC } , 83 | {KEYPHRASES , SORT_BY_HITS , SORT_DESC } , 84 | #ifdef HAVE_LIBGEOIP 85 | {GEO_LOCATION , SORT_BY_HITS , SORT_DESC } , 86 | #endif 87 | {STATUS_CODES , SORT_BY_HITS , SORT_DESC } , 88 | }; 89 | /* *INDENT-ON* */ 90 | 91 | /* sort data ascending */ 92 | static int 93 | cmp_data_asc (const void *a, const void *b) 94 | { 95 | const GHolderItem *ia = a; 96 | const GHolderItem *ib = b; 97 | return strcmp (ia->metrics->data, ib->metrics->data); 98 | } 99 | 100 | /* sort data descending */ 101 | static int 102 | cmp_data_desc (const void *a, const void *b) 103 | { 104 | const GHolderItem *ia = a; 105 | const GHolderItem *ib = b; 106 | return strcmp (ib->metrics->data, ia->metrics->data); 107 | } 108 | 109 | /* sort numeric descending */ 110 | static int 111 | cmp_num_desc (const void *a, const void *b) 112 | { 113 | const GHolderItem *ia = a; 114 | const GHolderItem *ib = b; 115 | 116 | int va = ia->metrics->hits; 117 | int vb = ib->metrics->hits; 118 | 119 | return (va < vb) - (va > vb); 120 | } 121 | 122 | /* sort numeric ascending */ 123 | static int 124 | cmp_num_asc (const void *a, const void *b) 125 | { 126 | const GHolderItem *ia = a; 127 | const GHolderItem *ib = b; 128 | 129 | int va = ia->metrics->hits; 130 | int vb = ib->metrics->hits; 131 | 132 | return (va > vb) - (va < vb); 133 | } 134 | 135 | /* sort numeric descending */ 136 | static int 137 | cmp_vis_desc (const void *a, const void *b) 138 | { 139 | const GHolderItem *ia = a; 140 | const GHolderItem *ib = b; 141 | 142 | int va = ia->metrics->visitors; 143 | int vb = ib->metrics->visitors; 144 | 145 | return (va < vb) - (va > vb); 146 | } 147 | 148 | /* sort numeric ascending */ 149 | static int 150 | cmp_vis_asc (const void *a, const void *b) 151 | { 152 | const GHolderItem *ia = a; 153 | const GHolderItem *ib = b; 154 | 155 | int va = ia->metrics->visitors; 156 | int vb = ib->metrics->visitors; 157 | 158 | return (va > vb) - (va < vb); 159 | } 160 | 161 | /* sort raw numeric descending */ 162 | static int 163 | cmp_raw_num_desc (const void *a, const void *b) 164 | { 165 | const GRawDataItem *ia = a; 166 | const GRawDataItem *ib = b; 167 | 168 | GDataMap *amap = ia->value; 169 | GDataMap *bmap = ib->value; 170 | 171 | int va = amap->data; 172 | int vb = bmap->data; 173 | 174 | return (va < vb) - (va > vb); 175 | } 176 | 177 | /* sort bandwidth descending */ 178 | static int 179 | cmp_bw_desc (const void *a, const void *b) 180 | { 181 | const GHolderItem *ia = a; 182 | const GHolderItem *ib = b; 183 | 184 | uint64_t va = ia->metrics->bw.nbw; 185 | uint64_t vb = ib->metrics->bw.nbw; 186 | 187 | return (va < vb) - (va > vb); 188 | } 189 | 190 | /* sort bandwidth ascending */ 191 | static int 192 | cmp_bw_asc (const void *a, const void *b) 193 | { 194 | const GHolderItem *ia = a; 195 | const GHolderItem *ib = b; 196 | 197 | uint64_t va = ia->metrics->bw.nbw; 198 | uint64_t vb = ib->metrics->bw.nbw; 199 | 200 | return (va > vb) - (va < vb); 201 | } 202 | 203 | /* sort usec descending */ 204 | static int 205 | cmp_avgts_desc (const void *a, const void *b) 206 | { 207 | const GHolderItem *ia = a; 208 | const GHolderItem *ib = b; 209 | 210 | uint64_t va = ia->metrics->avgts.nts; 211 | uint64_t vb = ib->metrics->avgts.nts; 212 | 213 | return (va < vb) - (va > vb); 214 | } 215 | 216 | /* sort usec ascending */ 217 | static int 218 | cmp_avgts_asc (const void *a, const void *b) 219 | { 220 | const GHolderItem *ia = a; 221 | const GHolderItem *ib = b; 222 | 223 | uint64_t va = ia->metrics->avgts.nts; 224 | uint64_t vb = ib->metrics->avgts.nts; 225 | 226 | return (va > vb) - (va < vb); 227 | } 228 | 229 | /* sort usec descending */ 230 | static int 231 | cmp_maxts_desc (const void *a, const void *b) 232 | { 233 | const GHolderItem *ia = a; 234 | const GHolderItem *ib = b; 235 | 236 | uint64_t va = ia->metrics->maxts.nts; 237 | uint64_t vb = ib->metrics->maxts.nts; 238 | 239 | return (va < vb) - (va > vb); 240 | } 241 | 242 | /* sort usec ascending */ 243 | static int 244 | cmp_maxts_asc (const void *a, const void *b) 245 | { 246 | const GHolderItem *ia = a; 247 | const GHolderItem *ib = b; 248 | 249 | uint64_t va = ia->metrics->maxts.nts; 250 | uint64_t vb = ib->metrics->maxts.nts; 251 | 252 | return (va > vb) - (va < vb); 253 | } 254 | 255 | /* sort protocol ascending */ 256 | static int 257 | cmp_proto_asc (const void *a, const void *b) 258 | { 259 | const GHolderItem *ia = a; 260 | const GHolderItem *ib = b; 261 | return strcmp (ia->metrics->protocol, ib->metrics->protocol); 262 | } 263 | 264 | /* sort protocol descending */ 265 | static int 266 | cmp_proto_desc (const void *a, const void *b) 267 | { 268 | const GHolderItem *ia = a; 269 | const GHolderItem *ib = b; 270 | return strcmp (ib->metrics->protocol, ia->metrics->protocol); 271 | } 272 | 273 | /* sort method ascending */ 274 | static int 275 | cmp_mthd_asc (const void *a, const void *b) 276 | { 277 | const GHolderItem *ia = a; 278 | const GHolderItem *ib = b; 279 | return strcmp (ia->metrics->method, ib->metrics->method); 280 | } 281 | 282 | /* sort method descending */ 283 | static int 284 | cmp_mthd_desc (const void *a, const void *b) 285 | { 286 | const GHolderItem *ia = a; 287 | const GHolderItem *ib = b; 288 | return strcmp (ib->metrics->method, ia->metrics->method); 289 | } 290 | 291 | int 292 | get_sort_field_enum (const char *str) 293 | { 294 | return str2enum (FIELD, ARRAY_SIZE (FIELD), str); 295 | } 296 | 297 | int 298 | get_sort_order_enum (const char *str) 299 | { 300 | return str2enum (ORDER, ARRAY_SIZE (ORDER), str); 301 | } 302 | 303 | void 304 | set_initial_sort (const char *smod, const char *sfield, const char *ssort) 305 | { 306 | int module, field, order; 307 | if ((module = get_module_enum (smod)) == -1) 308 | return; 309 | 310 | if ((field = get_sort_field_enum (sfield)) == -1) 311 | return; 312 | if ((order = get_sort_order_enum (ssort)) == -1) 313 | return; 314 | if (!can_sort_module (module, field)) 315 | return; 316 | 317 | module_sort[module].field = field; 318 | module_sort[module].sort = order; 319 | } 320 | 321 | int 322 | can_sort_module (GModule module, int field) 323 | { 324 | int i, can_sort = 0; 325 | for (i = 0; -1 != sort_choices[module][i]; i++) { 326 | if (sort_choices[module][i] != field) 327 | continue; 328 | if (SORT_BY_AVGTS == field && !conf.serve_usecs) 329 | continue; 330 | if (SORT_BY_MAXTS == field && !conf.serve_usecs) 331 | continue; 332 | else if (SORT_BY_BW == field && !conf.bandwidth) 333 | continue; 334 | else if (SORT_BY_PROT == field && !conf.append_protocol) 335 | continue; 336 | else if (SORT_BY_MTHD == field && !conf.append_method) 337 | continue; 338 | 339 | can_sort = 1; 340 | break; 341 | } 342 | 343 | return can_sort; 344 | } 345 | 346 | void 347 | parse_initial_sort (void) 348 | { 349 | int i; 350 | char *view; 351 | char module[SORT_MODULE_LEN], field[SORT_FIELD_LEN], order[SORT_ORDER_LEN]; 352 | for (i = 0; i < conf.sort_panel_idx; ++i) { 353 | view = conf.sort_panels[i]; 354 | if (sscanf (view, "%8[^','],%7[^','],%4s", module, field, order) != 3) 355 | continue; 356 | set_initial_sort (module, field, order); 357 | } 358 | } 359 | 360 | /* apply user defined sort */ 361 | void 362 | sort_holder_items (GHolderItem * items, int size, GSort sort) 363 | { 364 | switch (sort.field) { 365 | case SORT_BY_HITS: 366 | if (sort.sort == SORT_DESC) 367 | qsort (items, size, sizeof (GHolderItem), cmp_num_desc); 368 | else 369 | qsort (items, size, sizeof (GHolderItem), cmp_num_asc); 370 | break; 371 | case SORT_BY_VISITORS: 372 | if (sort.sort == SORT_DESC) 373 | qsort (items, size, sizeof (GHolderItem), cmp_vis_desc); 374 | else 375 | qsort (items, size, sizeof (GHolderItem), cmp_vis_asc); 376 | break; 377 | case SORT_BY_DATA: 378 | if (sort.sort == SORT_DESC) 379 | qsort (items, size, sizeof (GHolderItem), cmp_data_desc); 380 | else 381 | qsort (items, size, sizeof (GHolderItem), cmp_data_asc); 382 | break; 383 | case SORT_BY_BW: 384 | if (sort.sort == SORT_DESC) 385 | qsort (items, size, sizeof (GHolderItem), cmp_bw_desc); 386 | else 387 | qsort (items, size, sizeof (GHolderItem), cmp_bw_asc); 388 | break; 389 | case SORT_BY_AVGTS: 390 | if (sort.sort == SORT_DESC) 391 | qsort (items, size, sizeof (GHolderItem), cmp_avgts_desc); 392 | else 393 | qsort (items, size, sizeof (GHolderItem), cmp_avgts_asc); 394 | break; 395 | case SORT_BY_MAXTS: 396 | if (sort.sort == SORT_DESC) 397 | qsort (items, size, sizeof (GHolderItem), cmp_maxts_desc); 398 | else 399 | qsort (items, size, sizeof (GHolderItem), cmp_maxts_asc); 400 | break; 401 | case SORT_BY_PROT: 402 | if (sort.sort == SORT_DESC) 403 | qsort (items, size, sizeof (GHolderItem), cmp_proto_desc); 404 | else 405 | qsort (items, size, sizeof (GHolderItem), cmp_proto_asc); 406 | break; 407 | case SORT_BY_MTHD: 408 | if (sort.sort == SORT_DESC) 409 | qsort (items, size, sizeof (GHolderItem), cmp_mthd_desc); 410 | else 411 | qsort (items, size, sizeof (GHolderItem), cmp_mthd_asc); 412 | break; 413 | } 414 | } 415 | 416 | /* sort raw data for the first run (default sort) */ 417 | GRawData * 418 | sort_raw_data (GRawData * raw, int ht_size) 419 | { 420 | qsort (raw->items, ht_size, sizeof (GRawDataItem), cmp_raw_num_desc); 421 | return raw; 422 | } 423 | -------------------------------------------------------------------------------- /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 9 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_AVGTS, 43 | SORT_BY_MAXTS, 44 | SORT_BY_PROT, 45 | SORT_BY_MTHD, 46 | } GSortField; 47 | 48 | typedef enum GSortOrder_ 49 | { 50 | SORT_ASC, 51 | SORT_DESC 52 | } GSortOrder; 53 | 54 | typedef struct GSort_ 55 | { 56 | GModule module; 57 | GSortField field; 58 | GSortOrder sort; 59 | } GSort; 60 | 61 | extern GSort module_sort[TOTAL_MODULES]; 62 | extern const int sort_choices[][SORT_MAX_OPTS];; 63 | 64 | GRawData *sort_raw_data (GRawData * raw_data, int ht_size); 65 | int can_sort_module (GModule module, int field); 66 | int get_sort_field_enum (const char *str); 67 | int get_sort_order_enum (const char *str); 68 | void parse_initial_sort (void); 69 | void set_initial_sort (const char *smod, const char *sfield, const char *ssort); 70 | void sort_holder_items (GHolderItem * items, int size, GSort sort); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /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 | int ht_max_u64_from_int_key (TCADB * adb, int data_nkey, uint64_t newval); 64 | 65 | char *get_host_agent_val (int agent_nkey); 66 | char *get_hostname (const char *host); 67 | char *get_node_from_key (int data_nkey, GModule module, GMetric metric); 68 | char *get_root_from_key (int root_nkey, GModule module); 69 | char *get_str_from_int_key (TCADB *adb, int nkey); 70 | int get_int_from_keymap (const char * key, GModule module); 71 | int get_int_from_str_key (TCADB *adb, const char *key); 72 | int get_num_from_key (int data_nkey, GModule module, GMetric metric); 73 | uint64_t get_cumulative_from_key (int data_nkey, GModule module, GMetric metric); 74 | unsigned int get_uint_from_str_key (TCADB * adb, const char *key); 75 | void *get_host_agent_list(int agent_nkey); 76 | 77 | void free_agent_list(void); 78 | void free_db_key (TCADB *adb); 79 | void free_storage (void); 80 | void init_storage (void); 81 | 82 | #ifdef TCB_MEMHASH 83 | int ht_insert_host_agent (TCADB * adb, int data_nkey, int agent_nkey); 84 | #endif 85 | GSLList * tclist_to_gsllist (TCLIST * tclist); 86 | 87 | /* *INDENT-ON* */ 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /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/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_MAXTS "db_maxts.tcb" 60 | #define DB_METHODS "db_methods.tcb" 61 | #define DB_PROTOCOLS "db_protocols.tcb" 62 | #define DB_AGENTS "db_agents.tcb" 63 | 64 | /* *INDENT-OFF* */ 65 | TCBDB * tc_bdb_create (const char *dbname, int module); 66 | 67 | char * tc_db_set_path (const char *dbname, int module); 68 | int tc_bdb_close (void *db, char *dbname); 69 | void tc_db_get_params (char *params, const char *path); 70 | 71 | #ifdef TCB_BTREE 72 | int ht_insert_host_agent (TCBDB * bdb, int data_nkey, int agent_nkey); 73 | #endif 74 | /* *INDENT-ON* */ 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /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 "Dashboard" 40 | #define T_HEAD "Overall Analyzed Requests" 41 | 42 | #define T_DATETIME "Date/Time" 43 | #define T_REQUESTS "Total Requests" 44 | #define T_GEN_TIME "Generation Time" 45 | #define T_FAILED "Failed Requests" 46 | #define T_UNIQUE_VIS "Unique Visitors" 47 | #define T_UNIQUE_FIL "Unique Files" 48 | #define T_EXCLUDE_IP "Excl. IP Hits" 49 | #define T_REFERRER "Referrers" 50 | #define T_UNIQUE404 "Unique 404" 51 | #define T_STATIC_FIL "Static Files" 52 | #define T_LOG "Log Size" 53 | #define T_BW "Bandwidth" 54 | #define T_LOG_PATH "Log File" 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 "Unique visitors per day" 65 | #define VISIT_DESC "Hits having the same IP, date and agent are a unique visit." 66 | #define VISIT_ID "visitors" 67 | #define VISIT_LABEL "Visitors" 68 | 69 | #define REQUE_HEAD "Top requests (URLs)" 70 | #define REQUE_DESC "Top requests sorted by hits - [avg. time served | protocol | method]" 71 | #define REQUE_ID "requests" 72 | #define REQUE_LABEL "Requests" 73 | 74 | #define STATI_HEAD "Top static requests (e.g. jpg, png, js, css..)" 75 | #define STATI_DESC "Top static requests sorted by hits - [avg. time served | protocol | method]" 76 | #define STATI_ID "static_requests" 77 | #define STATI_LABEL "Static Requests" 78 | 79 | #define VTIME_HEAD "Time Distribution" 80 | #define VTIME_DESC "Data sorted by hour - [avg. time served]" 81 | #define VTIME_ID "visit_time" 82 | #define VTIME_LABEL "Time" 83 | 84 | #define FOUND_HEAD "HTTP 404 Not Found URLs" 85 | #define FOUND_DESC "Top 404 Not Found URLs sorted by hits - [avg. time served | protocol | method]" 86 | #define FOUND_ID "not_found" 87 | #define FOUND_LABEL "Not Found" 88 | 89 | #define HOSTS_HEAD "Visitor hostnames and IPs" 90 | #define HOSTS_DESC "Top visitor hosts sorted by hits - [avg. time served]" 91 | #define HOSTS_ID "hosts" 92 | #define HOSTS_LABEL "Hosts" 93 | 94 | #define OPERA_HEAD "Operating Systems" 95 | #define OPERA_DESC "Top Operating Systems sorted by hits - [avg. time served]" 96 | #define OPERA_ID "os" 97 | #define OPERA_LABEL "OS" 98 | 99 | #define BROWS_HEAD "Browsers" 100 | #define BROWS_DESC "Top Browsers sorted by hits - [avg. time served]" 101 | #define BROWS_ID "browsers" 102 | #define BROWS_LABEL "Browsers" 103 | 104 | #define REFER_HEAD "Referrers URLs" 105 | #define REFER_DESC "Top Requested Referrers sorted by hits - [avg. time served]" 106 | #define REFER_ID "referrers" 107 | #define REFER_LABEL "Referrers" 108 | 109 | #define SITES_HEAD "Referring Sites" 110 | #define SITES_DESC "Top Referring Sites sorted by hits - [avg. time served]" 111 | #define SITES_ID "referring_sites" 112 | #define SITES_LABEL "Referring Sites" 113 | 114 | #define KEYPH_HEAD "Keyphrases from Google's search engine" 115 | #define KEYPH_DESC "Top Keyphrases sorted by hits - [avg. time served]" 116 | #define KEYPH_ID "keyphrases" 117 | #define KEYPH_LABEL "Keyphrases" 118 | 119 | #define GEOLO_HEAD "Geo Location" 120 | #define GEOLO_DESC "Continent > Country sorted by unique hits - [avg. time served]" 121 | #define GEOLO_ID "geolocation" 122 | #define GEOLO_LABEL "Geo Location" 123 | 124 | #define CODES_HEAD "HTTP Status Codes" 125 | #define CODES_DESC "Top HTTP Status Codes sorted by hits - [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/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 | -------------------------------------------------------------------------------- /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/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 | --------------------------------------------------------------------------------