├── .codespellrc ├── .github ├── FUNDING.yml └── workflows │ ├── build-test.yml │ ├── deb-packaging-buildx.yml │ ├── deb-packaging.yml │ ├── docker-publish.yml │ ├── semgrep.yml │ └── spelling.yml ├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── DOCKER.md ├── Dockerfile ├── Dockerfile.debian-12 ├── Makefile.am ├── NEWS ├── README.md ├── SECURITY.md ├── TODO ├── build-dynamic.sh ├── config ├── browsers.list ├── goaccess.conf └── podcast.list ├── configure.ac ├── docker-compose ├── README.md ├── configs │ ├── goaccess.traefik.conf │ ├── goaccess.vanilla.conf │ └── nginx.conf ├── docker-compose.traefik.yaml └── docker-compose.vanilla.yaml ├── goaccess.1 ├── inlang.config.js ├── po ├── LINGUAS ├── Makevars ├── POTFILES.in ├── de.po ├── es.po ├── fr.po ├── goaccess.pot ├── it.po ├── ja.po ├── ko.po ├── pt_BR.po ├── ru.po ├── sv.po ├── uk.po └── zh_CN.po ├── resources ├── countries-110m.json ├── css │ ├── app.css │ ├── bootstrap.min.css │ └── fa.min.css ├── goaccess.svg ├── js │ ├── app.js │ ├── charts.js │ ├── d3.v7.min.js │ ├── hogan.min.js │ └── topojson.v3.min.js └── tpls.html ├── snap └── snapcraft.yaml └── src ├── base64.c ├── base64.h ├── bin2c.c ├── bitmap.c ├── bitmap.h ├── browsers.c ├── browsers.h ├── color.c ├── color.h ├── commons.c ├── commons.h ├── csv.c ├── csv.h ├── error.c ├── error.h ├── gdashboard.c ├── gdashboard.h ├── gdns.c ├── gdns.h ├── geoip1.c ├── geoip1.h ├── geoip2.c ├── gholder.c ├── gholder.h ├── gkhash.c ├── gkhash.h ├── gkmhash.c ├── gkmhash.h ├── gmenu.c ├── gmenu.h ├── goaccess.c ├── goaccess.h ├── gslist.c ├── gslist.h ├── gstorage.c ├── gstorage.h ├── gwsocket.c ├── gwsocket.h ├── json.c ├── json.h ├── khash.h ├── labels.h ├── opesys.c ├── opesys.h ├── options.c ├── options.h ├── output.c ├── output.h ├── parser.c ├── parser.h ├── pdjson.c ├── pdjson.h ├── persistence.c ├── persistence.h ├── settings.c ├── settings.h ├── sha1.c ├── sha1.h ├── sort.c ├── sort.h ├── tpl.c ├── tpl.h ├── ui.c ├── ui.h ├── util.c ├── util.h ├── websocket.c ├── websocket.h ├── win ├── mman.h └── mmap.c ├── wsauth.c ├── wsauth.h ├── xmalloc.c └── xmalloc.h /.codespellrc: -------------------------------------------------------------------------------- 1 | [codespell] 2 | skip=./.git,./po,./resources/js/*.min.js,./resources/css/*.min.css 3 | check-hidden= 4 | check-filenames= 5 | builtin=clear,rare,informal,usage,code,names 6 | ignore-words-list=master,thead,referer,cros,hastable,musl,stdio 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: allinurl 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/build-test.yml: -------------------------------------------------------------------------------- 1 | name: C build and Test 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ${{ matrix.os }} 12 | 13 | strategy: 14 | matrix: 15 | config_params: ["", "--enable-debug", "--enable-debug", "--with-getline --enable-asan", "--enable-utf8 --enable-debug --with-getline", "--enable-utf8 --with-getline --enable-asan"] 16 | os: [ubuntu-latest, macos-latest, macos-14] 17 | include: 18 | - os: ubuntu-latest 19 | setup-env: sudo apt-get update && sudo apt-get install -y build-essential autoconf gettext autopoint libncursesw5-dev libssl-dev git libmaxminddb-dev jq 20 | - os: macos-latest 21 | setup-env: brew install ncurses gettext autoconf automake libmaxminddb openssl@3 jq 22 | - os: macos-14 23 | setup-env: brew update && brew install ncurses gettext autoconf automake openssl@3 libmaxminddb jq 24 | 25 | steps: 26 | - name: Setup env. 27 | run: ${{ matrix.setup-env }} 28 | 29 | - uses: actions/checkout@v3 30 | 31 | - name: Check Architecture 32 | run: | 33 | echo "Running on $(uname -m) architecture" 34 | 35 | - name: autoreconf 36 | run: autoreconf -fiv 37 | 38 | - name: Configure 39 | run: ./configure ${{ matrix.config_params }} 40 | 41 | - name: Make 42 | run: sudo make 43 | 44 | - name: Make Check 45 | run: sudo make check 46 | 47 | - name: Make Distcheck 48 | run: sudo make distcheck 49 | 50 | - name: Define log 51 | run: | 52 | echo -e 'localhost:80 192.168.0.1 - - [01/Jul/2013:06:20:38 -0500] "GET / HTTP/1.1" 200 3829 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0"\ 53 | google.com:80 ::1 - - [01/Jul/2013:06:25:11 -0500] "OPTIONS * HTTP/1.0" 200 136 "-" "Apache (internal dummy connection)"\ 54 | bing.com:80 142.250.190.142 - - [01/Jul/2013:06:41:31 -0500] "-" 408 0 "-" "-"\ 55 | yahoo.com:80 74.6.143.25 - - [01/Jul/2013:07:20:02 -0500] "HEAD / HTTP/1.1" 200 213 "-" "Wget/1.14 (linux-gnu)"' > access.log 56 | cat access.log 57 | 58 | - name: Set up output directory 59 | run: echo "output_dir=${GITHUB_WORKSPACE}/report" >> $GITHUB_ENV 60 | 61 | - name: Create output directory 62 | run: mkdir -p ${GITHUB_WORKSPACE}/report 63 | 64 | - name: Run goaccess single thread 65 | run: ./goaccess access.log --log-format=VCOMBINED -o ${output_dir}/report.html 66 | 67 | - name: Run goaccess multi-thread 68 | run: ./goaccess access.log --log-format='%v:%^ %h %^[%x] "%r" %s %b "%R" "%u"' --datetime-format='%d/%b/%Y:%H:%M:%S %z' -o ${output_dir}/report.html -j 2 -a --tz="Europe/Berlin" 69 | 70 | - name: Run goaccess multi-thread JSON output 71 | run: | 72 | ./goaccess access.log --log-format=VCOMBINED -o ${output_dir}/report.json -j 2 -a --json-pretty-print 73 | cat ${output_dir}/report.json | jq . 74 | 75 | - name: Make distclean 76 | run: sudo make distclean 77 | -------------------------------------------------------------------------------- /.github/workflows/deb-packaging-buildx.yml: -------------------------------------------------------------------------------- 1 | name: .deb packaging buildx 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build_job: 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | include: 12 | - arch: arm32v7 13 | distro: ubuntu16.04 14 | - arch: arm32v7 15 | distro: ubuntu18.04 16 | - arch: arm32v7 17 | distro: ubuntu22.04 18 | - arch: arm32v7 19 | distro: ubuntu24.04 20 | - arch: arm32v7 21 | distro: ubuntu24.10 22 | - arch: arm32v7 23 | distro: bullseye 24 | - arch: arm32v7 25 | distro: bookworm 26 | - arch: aarch64 27 | distro: ubuntu18.04 28 | - arch: aarch64 29 | distro: ubuntu20.04 30 | - arch: aarch64 31 | distro: ubuntu22.04 32 | - arch: aarch64 33 | distro: ubuntu24.04 34 | - arch: aarch64 35 | distro: ubuntu24.10 36 | - arch: aarch64 37 | distro: buster 38 | - arch: aarch64 39 | distro: bullseye 40 | - arch: aarch64 41 | distro: bookworm 42 | - arch: amd64 43 | distro: buster 44 | - arch: i386 45 | distro: buster 46 | - arch: amd64 47 | distro: bullseye 48 | - arch: amd64 49 | distro: bookworm 50 | - arch: i386 51 | distro: bullseye 52 | - arch: i386 53 | distro: bookworm 54 | - arch: amd64 55 | distro: ubuntu16.04 56 | - arch: i386 57 | distro: ubuntu16.04 58 | - arch: amd64 59 | distro: ubuntu18.04 60 | - arch: i386 61 | distro: ubuntu18.04 62 | - arch: amd64 63 | distro: ubuntu20.04 64 | - arch: amd64 65 | distro: ubuntu22.04 66 | - arch: amd64 67 | distro: ubuntu24.04 68 | - arch: amd64 69 | distro: ubuntu24.10 70 | 71 | steps: 72 | - name: Checkout repository 73 | uses: actions/checkout@v2 74 | 75 | - name: Setup Docker Buildx 76 | uses: docker/setup-buildx-action@v2 77 | 78 | - name: Setup QEMU 79 | uses: docker/setup-qemu-action@v2 80 | 81 | - name: Create artifacts directory 82 | run: mkdir -p "${GITHUB_WORKSPACE}/artifacts" 83 | 84 | - name: Build deb package 85 | run: | 86 | echo "Matrix arch: ${{ matrix.arch }}" 87 | echo "Matrix distro: ${{ matrix.distro }}" 88 | 89 | # Convert the matrix distro into a shell variable. 90 | MY_DISTRO="${{ matrix.distro }}" 91 | if [[ "$MY_DISTRO" == ubuntu* ]]; then 92 | # Remove the 'ubuntu' prefix to get the version tag. 93 | VERSION_TAG="${MY_DISTRO#ubuntu}" 94 | DEFAULT_IMAGE="ubuntu:${VERSION_TAG}" 95 | else 96 | DEFAULT_IMAGE="debian:${MY_DISTRO}" 97 | fi 98 | echo "Default IMAGE: ${DEFAULT_IMAGE}" 99 | 100 | # Determine the base image and platform based on the target architecture. 101 | case "${{ matrix.arch }}" in 102 | arm32v7) 103 | if [[ "$MY_DISTRO" == ubuntu* ]]; then 104 | BASE_IMAGE="arm32v7/ubuntu:${VERSION_TAG}" 105 | else 106 | BASE_IMAGE="arm32v7/debian:${MY_DISTRO}" 107 | fi 108 | PLATFORM="linux/arm/v7" 109 | ;; 110 | aarch64) 111 | if [[ "$MY_DISTRO" == ubuntu* ]]; then 112 | BASE_IMAGE="arm64v8/ubuntu:${VERSION_TAG}" 113 | else 114 | BASE_IMAGE="arm64v8/debian:${MY_DISTRO}" 115 | fi 116 | PLATFORM="linux/arm64" 117 | ;; 118 | i386) 119 | if [[ "$MY_DISTRO" == ubuntu* ]]; then 120 | BASE_IMAGE="i386/ubuntu:${VERSION_TAG}" 121 | else 122 | BASE_IMAGE="i386/debian:${MY_DISTRO}" 123 | fi 124 | PLATFORM="linux/386" 125 | ;; 126 | amd64) 127 | BASE_IMAGE="$DEFAULT_IMAGE" 128 | PLATFORM="linux/amd64" 129 | ;; 130 | *) 131 | echo "Unsupported architecture: ${{ matrix.arch }}" 132 | exit 1 133 | ;; 134 | esac 135 | echo "Using base image: ${BASE_IMAGE}" 136 | echo "Using platform: ${PLATFORM}" 137 | 138 | docker run --rm --platform "${PLATFORM}" \ 139 | -v "${GITHUB_WORKSPACE}/artifacts:/artifacts" \ 140 | "${BASE_IMAGE}" bash -c "\ 141 | apt-get update && \ 142 | apt-get install -y ca-certificates wget curl lsb-release && \ 143 | cd /artifacts && \ 144 | curl -O https://deb.goaccess.io/provision/provision.dpkg.sh && \ 145 | chmod +x provision.dpkg.sh && \ 146 | ./provision.dpkg.sh && \ 147 | ls -lath && \ 148 | echo 'Build Success'" 149 | 150 | - name: Test deb package installation 151 | run: | 152 | DEB_FILE=$(find "${GITHUB_WORKSPACE}/artifacts" -name "goaccess_*.deb") 153 | echo "Found deb package: $DEB_FILE" 154 | 155 | case "${{ matrix.distro }}" in 156 | bookworm) TEST_IMAGE="debian:bookworm" ;; 157 | bullseye) TEST_IMAGE="debian:bullseye" ;; 158 | buster) TEST_IMAGE="debian:buster" ;; 159 | ubuntu16.04) TEST_IMAGE="ubuntu:16.04" ;; 160 | ubuntu18.04) TEST_IMAGE="ubuntu:18.04" ;; 161 | ubuntu20.04) TEST_IMAGE="ubuntu:20.04" ;; 162 | ubuntu22.04) TEST_IMAGE="ubuntu:22.04" ;; 163 | ubuntu24.04) TEST_IMAGE="ubuntu:24.04" ;; 164 | ubuntu24.10) TEST_IMAGE="ubuntu:24.10" ;; 165 | *) echo "Unknown distro: ${{ matrix.distro }}" && exit 1 ;; 166 | esac 167 | echo "Using Docker image for testing: $TEST_IMAGE" 168 | 169 | case "${{ matrix.arch }}" in 170 | arm32v7) TEST_PLATFORM="linux/arm/v7" ;; 171 | aarch64) TEST_PLATFORM="linux/arm64" ;; 172 | i386) TEST_PLATFORM="linux/386" ;; 173 | amd64) TEST_PLATFORM="linux/amd64" ;; 174 | *) echo "Unsupported architecture: ${{ matrix.arch }}" && exit 1 ;; 175 | esac 176 | echo "Using platform for testing: $TEST_PLATFORM" 177 | 178 | docker run --rm --platform "$TEST_PLATFORM" \ 179 | -v "${GITHUB_WORKSPACE}/artifacts:/artifacts" \ 180 | "$TEST_IMAGE" bash -c "\ 181 | apt-get update && \ 182 | apt-get install -y /artifacts/$(basename $DEB_FILE) && \ 183 | goaccess --version && \ 184 | apt-get remove -y goaccess" 185 | 186 | - name: Upload deb package 187 | uses: actions/upload-artifact@v4 188 | with: 189 | name: deb-package-${{ matrix.distro }}-${{ matrix.arch }} 190 | path: artifacts/*.deb 191 | retention-days: 1 192 | -------------------------------------------------------------------------------- /.github/workflows/deb-packaging.yml: -------------------------------------------------------------------------------- 1 | name: .deb packaging 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build_job: 8 | # The host should always be linux 9 | runs-on: ubuntu-latest 10 | name: Build on ${{ matrix.distro }} ${{ matrix.arch }} 11 | 12 | # Run steps on a matrix of arch/distro combinations 13 | strategy: 14 | matrix: 15 | include: 16 | - arch: arm32v7 17 | distro: ubuntu16.04 18 | - arch: arm32v7 19 | distro: ubuntu18.04 20 | - arch: arm32v7 21 | distro: ubuntu22.04 22 | - arch: arm32v7 23 | distro: ubuntu24.04 24 | - arch: arm32v7 25 | distro: ubuntu24.10 26 | - arch: arm32v7 27 | distro: bullseye 28 | - arch: arm32v7 29 | distro: bookworm 30 | - arch: aarch64 31 | distro: ubuntu18.04 32 | - arch: aarch64 33 | distro: ubuntu20.04 34 | - arch: aarch64 35 | distro: ubuntu22.04 36 | - arch: aarch64 37 | distro: ubuntu24.04 38 | - arch: aarch64 39 | distro: ubuntu24.10 40 | - arch: aarch64 41 | distro: buster 42 | - arch: aarch64 43 | distro: bullseye 44 | - arch: aarch64 45 | distro: bookworm 46 | - arch: amd64 47 | distro: buster 48 | - arch: i386 49 | distro: buster 50 | - arch: amd64 51 | distro: bullseye 52 | - arch: amd64 53 | distro: bookworm 54 | - arch: i386 55 | distro: bullseye 56 | - arch: i386 57 | distro: bookworm 58 | - arch: amd64 59 | distro: ubuntu16.04 60 | - arch: i386 61 | distro: ubuntu16.04 62 | - arch: amd64 63 | distro: ubuntu18.04 64 | - arch: i386 65 | distro: ubuntu18.04 66 | - arch: amd64 67 | distro: ubuntu20.04 68 | - arch: amd64 69 | distro: ubuntu22.04 70 | - arch: amd64 71 | distro: ubuntu24.04 72 | - arch: amd64 73 | distro: ubuntu24.10 74 | 75 | steps: 76 | - uses: actions/checkout@v2.1.0 77 | 78 | - uses: allinurl/run-on-arch-action@master 79 | name: Build artifact 80 | id: build 81 | with: 82 | arch: ${{ matrix.arch }} 83 | distro: ${{ matrix.distro }} 84 | # Not required, but speeds up builds 85 | githubToken: ${{ github.token }} 86 | # Create an artifacts directory 87 | setup: | 88 | mkdir -p "${PWD}/artifacts" 89 | # Mount the artifacts directory as /artifacts in the container 90 | dockerRunArgs: | 91 | --volume "${PWD}/artifacts:/artifacts" 92 | # The shell to run commands with in the container 93 | shell: /bin/bash 94 | # Install some dependencies in the container. 95 | install: | 96 | case "${{ matrix.distro }}" in 97 | ubuntu*|jessie|stretch|buster|bullseye|bookworm) 98 | apt-get update && apt-get install -y ca-certificates wget curl lsb-release && apt-get clean all 99 | ;; 100 | esac 101 | # Produce a binary artifact and place it in the mounted volume 102 | run: | 103 | ls -lath "/artifacts" 104 | curl -O https://deb.goaccess.io/provision/provision.dpkg.sh 105 | chmod +x ./provision.dpkg.sh 106 | ./provision.dpkg.sh 107 | echo "Success!!" 108 | 109 | - name: Show the artifact 110 | run: | 111 | pwd 112 | ls -lath "${PWD}/artifacts" 113 | 114 | - name: Test deb package installation 115 | run: | 116 | # Find the generated deb package 117 | DEB_FILE=$(find "${PWD}/artifacts" -name "goaccess_*.deb") 118 | echo "Found deb package: $DEB_FILE" 119 | 120 | # Determine the correct Docker image for the distro 121 | case "${{ matrix.distro }}" in 122 | bookworm) IMAGE="debian:bookworm" ;; 123 | bullseye) IMAGE="debian:bullseye" ;; 124 | buster) IMAGE="debian:buster" ;; 125 | ubuntu16.04) IMAGE="ubuntu:16.04" ;; 126 | ubuntu18.04) IMAGE="ubuntu:18.04" ;; 127 | ubuntu20.04) IMAGE="ubuntu:20.04" ;; 128 | ubuntu22.04) IMAGE="ubuntu:22.04" ;; 129 | ubuntu24.04) IMAGE="ubuntu:24.04" ;; 130 | ubuntu24.10) IMAGE="ubuntu:24.10" ;; 131 | *) echo "Unknown distro: ${{ matrix.distro }}" && exit 1 ;; 132 | esac 133 | 134 | echo "Using Docker image: $IMAGE" 135 | 136 | # Run a container with the correct architecture and test the installation 137 | docker run --rm -v "${PWD}/artifacts:/artifacts" --platform linux/${{ matrix.arch }} "$IMAGE" bash -c " 138 | apt-get update && 139 | apt-get install -y /artifacts/$(basename $DEB_FILE) && 140 | goaccess --version && 141 | apt-get remove -y goaccess" 142 | 143 | - name: Upload deb package 144 | uses: actions/upload-artifact@v4 145 | with: 146 | name: deb-package-${{ matrix.distro }}-${{ matrix.arch }} 147 | path: 'artifacts/*.deb' 148 | retention-days: 1 149 | -------------------------------------------------------------------------------- /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | on: 3 | push: 4 | # Publish `master` as Docker `latest` image. 5 | branches: 6 | - master 7 | # Publish `v1.2.3` tags as releases. 8 | tags: 9 | - v* 10 | # Run tests for any PRs. 11 | pull_request: 12 | env: 13 | IMAGE_NAME: ${{ github.repository }} 14 | jobs: 15 | # Run tests. 16 | # See also https://docs.docker.com/docker-hub/builds/automated-testing/ 17 | test: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Run tests 22 | run: | 23 | if [ -f docker-compose.test.yml ]; then 24 | docker-compose --file docker-compose.test.yml build 25 | docker-compose --file docker-compose.test.yml run sut 26 | else 27 | docker build . --file Dockerfile 28 | fi 29 | # Push image to Docker Hub. 30 | # See also https://docs.docker.com/docker-hub/builds/ 31 | push: 32 | # Ensure test job passes before pushing image. 33 | needs: test 34 | runs-on: ubuntu-latest 35 | if: github.event_name == 'push' 36 | 37 | steps: 38 | - uses: actions/checkout@v2 39 | 40 | - name: Set up Docker Buildx 41 | uses: docker/setup-buildx-action@v2 42 | 43 | - name: Build image 44 | run: docker build . --file Dockerfile --tag $IMAGE_NAME 45 | - name: Login to Docker Hub 46 | uses: docker/login-action@v3 47 | with: 48 | username: ${{ secrets.DOCKERHUB_USERNAME }} 49 | password: ${{ secrets.DOCKERHUB_TOKEN }} 50 | 51 | - name: Push image 52 | run: | 53 | # Change all uppercase to lowercase 54 | IMAGE_ID=$(echo "${{ github.repository }}" | tr '[A-Z]' '[a-z]') 55 | 56 | # Strip git ref prefix from version 57 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 58 | 59 | # Strip "v" prefix from tag name 60 | [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') 61 | # Use Docker `latest` tag convention 62 | [ "$VERSION" == "master" ] && VERSION=latest 63 | 64 | echo IMAGE_ID=$IMAGE_ID 65 | echo VERSION=$VERSION 66 | 67 | docker buildx create --use 68 | docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_ID:$VERSION --push . 69 | 70 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: {} 3 | pull_request: {} 4 | push: 5 | branches: 6 | - main 7 | - master 8 | paths: 9 | - .github/workflows/semgrep.yml 10 | schedule: 11 | # random HH:MM to avoid a load spike on GitHub Actions at 00:00 12 | - cron: 16 18 * * * 13 | name: Semgrep 14 | jobs: 15 | semgrep: 16 | name: Scan 17 | runs-on: ubuntu-20.04 18 | env: 19 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 20 | container: 21 | image: returntocorp/semgrep 22 | steps: 23 | - uses: actions/checkout@v3 24 | - run: semgrep ci 25 | -------------------------------------------------------------------------------- /.github/workflows/spelling.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://json.schemastore.org/github-workflow 2 | 3 | name: "Spelling" 4 | 5 | on: 6 | workflow_dispatch: 7 | # Add [skip ci] to commit message to skip CI. 8 | 9 | permissions: 10 | contents: "read" 11 | 12 | concurrency: 13 | group: "${{ github.workflow }}-${{ github.ref }}" 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | spell_check: 18 | name: "文A Spell check" 19 | runs-on: "ubuntu-22.04" 20 | timeout-minutes: 1 21 | steps: 22 | - 23 | name: "Checkout repository" 24 | uses: "actions/checkout@v3" 25 | - 26 | name: "Cache pip" 27 | uses: "actions/cache@v3" 28 | with: 29 | path: "~/.cache/pip" 30 | key: "${{ runner.os }}-pip-codespell" 31 | - 32 | name: "Install codespell" 33 | run: | 34 | pip install --user 'codespell>=2.2' 35 | - 36 | name: "Search for misspellings" 37 | run: | 38 | "$(python -m site --user-base)/bin/codespell" 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #custom section 2 | config.status 3 | config.guess 4 | config.sub 5 | config.rpath 6 | configure~ 7 | **/.deps/ 8 | /INSTALL 9 | /Makefile 10 | src/.dirstamp 11 | src/config.h 12 | src/config.h.in 13 | src/config.h.in~ 14 | src/config.log 15 | src/config.status 16 | src/.deps/ 17 | src/stamp-h1 18 | goaccess 19 | bin2c 20 | # font selection 21 | selection.json 22 | #merged from https://raw.github.com/github/gitignore/master/Autotools.gitignore 23 | # http://www.gnu.org/software/automake 24 | 25 | Makefile.in 26 | 27 | # http://www.gnu.org/software/autoconf 28 | 29 | /autom4te.cache 30 | /aclocal.m4 31 | /compile 32 | /configure 33 | /depcomp 34 | /install-sh 35 | /missing 36 | 37 | # VIM 38 | *.*.swp 39 | *.log 40 | 41 | # Object files 42 | *.o 43 | *.ko 44 | *.obj 45 | *.elf 46 | 47 | # Precompiled Headers 48 | *.gch 49 | *.pch 50 | 51 | # Libraries 52 | *.lib 53 | *.a 54 | *.la 55 | *.lo 56 | 57 | # Shared objects (inc. Windows DLLs) 58 | *.dll 59 | *.so 60 | *.so.* 61 | *.dylib 62 | 63 | # Executables 64 | *.exe 65 | *.out 66 | *.app 67 | *.i*86 68 | *.x86_64 69 | *.hex 70 | 71 | # Vagrant 72 | .vagrant 73 | 74 | # M4 macros 75 | /m4/* 76 | 77 | # I18n stuff 78 | /ABOUT-NLS 79 | /po/*.gmo 80 | /po/*.header 81 | /po/*.mo 82 | /po/*.sed 83 | /po/*.sin 84 | /po/Makefile.in.in 85 | /po/Makevars.template 86 | /po/POTFILES 87 | /po/Rules-quot 88 | /po/Makefile 89 | /po/stamp-po 90 | 91 | # compiled resources 92 | /src/appcss.h 93 | /src/appjs.h 94 | /src/bootstrapcss.h 95 | /src/chartsjs.h 96 | /src/d3js.h 97 | /src/facss.h 98 | /src/hoganjs.h 99 | /src/tpls.h 100 | /src/countries110m.h 101 | /src/topojsonjs.h 102 | 103 | # intermediate resources 104 | /resources/css/app.css.tmp 105 | /resources/css/bootstrap.min.css.tmp 106 | /resources/css/fa.min.css.tmp 107 | /resources/js/app.js.tmp 108 | /resources/js/charts.js.tmp 109 | /resources/js/d3.v?.min.js.tmp 110 | /resources/js/hogan.min.js.tmp 111 | /resources/tpls.html.tmp 112 | /resources/countries-110m.json.tmp 113 | /resources/js/topojson.v3.min.js.tmp 114 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | GoAccess was designed and developed by Gerardo Orellana 2 | 3 | Special thanks to the following individuals for their great contributions: 4 | 5 | * 0bi-w6n-K3nobi <71027865+0bi-w6n-K3nob@users.noreply.github.com> 6 | * Aaditya Bagga 7 | * abgit 8 | * Adam Monsen 9 | * Adam Števko 10 | * Adam Weinberger 11 | * Adrian 12 | * Ainsley Ellis 13 | * aishikoyo 14 | * Alan Placidina 15 | * Alexander Eifler 16 | * Alexandre GUIOT--VALENTIN 17 | * Alexandre Perrin 18 | * Alexis Lefebvre 19 | * Ali Homafar 20 | * allofmex 21 | * Amos Hayes 22 | * A. Nackov 23 | * Anders Johansson <47452862+tellustheguru@users.noreply.github.com> 24 | * Andreas Sommer 25 | * Andreas Weigel 26 | * Andrew Kvalheim 27 | * Andrew Minion 28 | * Antonio Terceiro 29 | * Arnaud Rebillout 30 | * Arnie97 31 | * as0n 32 | * Aslak Raanes 33 | * Axel Wehner 34 | * bbbboom 35 | * Bbertatum 36 | * Benjamin Bach 37 | * Bjørnar Hansen 38 | * Bob Black 39 | * Bo Cai 40 | * Brandon Coleman 41 | * Carlos Duelo 42 | * Celso Providelo 43 | * ChangMo Yang 44 | * Chang Zhao 45 | * Chilledheart 46 | * Chris Downs 47 | * Christian Göttsche 48 | * Christian Hermann 49 | * Christian Moelders 50 | * Christopher Meng 51 | * Clément Hermann 52 | * cristianpb 53 | * Cthulhux 54 | * Daniel Aleksandersen 55 | * Daniel Aleksandersen 56 | * Daniel (dmilith) Dettlaff 57 | * Danila Vershinin 58 | * Danny Kirkham 59 | * Darek Kay 60 | * David Carlier 61 | * David Geistert 62 | * d_dandrew 63 | * ElXreno 64 | * Enrique Becerra 65 | * evitalis 66 | * Felix Häberle <34959078+felixhaeberle@users.noreply.github.com> 67 | * Florian Forster 68 | * forDream 69 | * fqbuild 70 | * Frederic Cambus 71 | * gemmaro 72 | * Genki Sugawara 73 | * Gerald Combs 74 | * Geraldo Alves 75 | * gitqlt 76 | * Hiroki Kamino <46459949+err931@users.noreply.github.com> 77 | * holys 78 | * Izzy 79 | * JackDesBwa 80 | * Jannes Blobel <72493222+jannesblobel@users.noreply.github.com> 81 | * Jeffery Wilkins 82 | * Jeremy Burks 83 | * Jeremy Lin 84 | * Joaquín de la Zerda 85 | * Joe Groocock 86 | * Joe Winett 87 | * Jonas Kittner 88 | * Joona 89 | * Jordan Trask 90 | * Julian Xhokaxhiu 91 | * Justin Mills 92 | * Kamino Hiroki <37243867+4f8p@users.noreply.github.com> 93 | * Kit Westneat 94 | * kokke 95 | * kyle sloan 96 | * LeoAttn 97 | * Magnus Groß 98 | * Maksim Losev 99 | * mario-donnarumma 100 | * markiewb 101 | * Mark J. Berger 102 | * Martins Polakovs 103 | * Massimiliano Torromeo 104 | * Mathieu Aubin 105 | * Mathieu Thoretton 106 | * Max Christian Pohle 107 | * metrix78 108 | * Michael Vetter 109 | * Mika Raunio 110 | * Moritz Schott 111 | * m-r-r 112 | * mynameiscfed 113 | * Newbe36524 114 | * Nicolas Le Manchet 115 | * Nicolas 116 | * Ophir LOJKINE 117 | * Otto Kekäläinen 118 | * Panos Stavrianos 119 | * pitilux 120 | * Pixelcode <52963327+realpixelcode@users.noreply.github.com> 121 | * Placidina 122 | * pravdomil 123 | * rachid-debu 124 | * radoslawc 125 | * rahra 126 | * Ramires Viana <59319979+ramiresviana@users.noreply.github.com> 127 | * rgriebl 128 | * Roy Marples 129 | * rtmkrlv 130 | * Ryow 131 | * schoonc 132 | * Sean Cross 133 | * Sean Wei 134 | * Sebastian Wiedenroth 135 | * Simon Gardling 136 | * SjonHortensius 137 | * Steely Wing 138 | * Stéphane Péchard 139 | * Stephen Wade 140 | * Stoyan Dimov 141 | * Stuart Henderson 142 | * Sveinbjorn Thordarson 143 | * Tatsuyuki Ishi 144 | * Thomas Gläßle 145 | * Thomas Jost 146 | * Thomas Lange 147 | * throwaway1037 148 | * Tim Gates 149 | * Timothy Quilling 150 | * Tom Samstag 151 | * ugola 152 | * Ulrich Schwarz 153 | * Viktor Szépe 154 | * Viktor Szépe 155 | * Ville Skyttä 156 | * Vincent Bernat 157 | * Vladimir Pavljuchenkov 158 | * William Muir 159 | * Wladimir Palant 160 | * wodev 161 | * woobee 162 | * Yuri D'Elia 163 | * Yuriy M. Kaminskiy 164 | * zeke 165 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2009-2022 Gerardo Orellana 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /DOCKER.md: -------------------------------------------------------------------------------- 1 | 2 | # Docker image features 3 | 4 | * This command uses the language set for this system. If that does not support it will be output in English. [**Supported Language**](https://github.com/allinurl/goaccess/raw/master/po/LINGUAS) 5 | 6 | * This image supports building on the ARM architecture (e.g. Raspberry Pi) 7 | 8 | * Do you want to change the timezone? Use the `-e` option to pass the time-zone setting to Docker. (e.g. `-e TZ="America/New_York"`) 9 | 10 | * The container is built with geo-location support (see [the manual](https://goaccess.io/man#options)). To enable the respective panel, mount the geolocation database using `-v /path/to/GeoLite2-City.mmdb:/GeoLite2-City.mmdb` and specify `--geoip-database /GeoLite2-City.mmdb` when running GoAccess. 11 | 12 | * If you made changes to the config file after building the image, you don't have to rebuild from scratch. Simply restart the container: 13 | 14 | ``` 15 | docker restart goaccess 16 | ``` 17 | 18 | * If you had already run the container, you may have to stop and remove it first: 19 | 20 | ``` 21 | docker stop goaccess 22 | docker rm goaccess 23 | ``` 24 | 25 | * The container and image can be completely removed as follows: 26 | 27 | ``` 28 | docker stop goaccess 29 | docker rm goaccess 30 | docker rmi allinurl/goaccess 31 | ``` 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3 AS builds 2 | RUN apk add --no-cache \ 3 | autoconf \ 4 | automake \ 5 | build-base \ 6 | clang \ 7 | clang-static \ 8 | gettext-dev \ 9 | gettext-static \ 10 | git \ 11 | libmaxminddb-dev \ 12 | libmaxminddb-static \ 13 | libressl-dev \ 14 | linux-headers \ 15 | ncurses-dev \ 16 | ncurses-static \ 17 | tzdata 18 | 19 | # GoAccess 20 | COPY . /goaccess 21 | WORKDIR /goaccess 22 | RUN autoreconf -fiv 23 | RUN CC="clang" CFLAGS="-O3 -static" LIBS="$(pkg-config --libs openssl)" ./configure --prefix="" --enable-utf8 --with-openssl --enable-geoip=mmdb 24 | RUN make && make DESTDIR=/dist install 25 | 26 | # Container 27 | FROM busybox:musl 28 | COPY --from=builds /dist / 29 | COPY --from=builds /usr/share/zoneinfo /usr/share/zoneinfo 30 | VOLUME /var/www/goaccess 31 | EXPOSE 7890 32 | ENTRYPOINT ["/bin/goaccess"] 33 | CMD ["--help"] 34 | -------------------------------------------------------------------------------- /Dockerfile.debian-12: -------------------------------------------------------------------------------- 1 | # Used to have all compile dependencies isolated in a container image. 2 | FROM debian:12 3 | 4 | RUN apt update -qqq 5 | RUN apt install -y \ 6 | libncurses-dev \ 7 | libssl-dev \ 8 | libmaxminddb-dev \ 9 | build-essential \ 10 | autoconf \ 11 | gettext \ 12 | autopoint 13 | 14 | # GoAccess 15 | WORKDIR /goaccess 16 | 17 | ENTRYPOINT ["./build-dynamic.sh"] 18 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Copyright (C) 2009-2025 2 | Gerardo Orellana 3 | 4 | * Version history: 5 | - 1.9.4 [Monday, Mar 31, 2025] 6 | . GoAccess 1.9.4 Released. See ChangeLog for new features/bug-fixes. 7 | - 1.9.3 [Friday, May 31, 2024] 8 | . GoAccess 1.9.3 Released. See ChangeLog for new features/bug-fixes. 9 | - 1.9.2 [Friday, April 12, 2024] 10 | . GoAccess 1.9.2 Released. See ChangeLog for new features/bug-fixes. 11 | - 1.9.1 [Tuesday, February 05, 2024] 12 | . GoAccess 1.9.1 Released. See ChangeLog for new features/bug-fixes. 13 | - 1.9 [Tuesday, January 30, 2024] 14 | . GoAccess 1.9 Released. See ChangeLog for new features/bug-fixes. 15 | - 1.8.1 [Tuesday, October 31, 2023] 16 | . GoAccess 1.8.1 Released. See ChangeLog for new features/bug-fixes. 17 | - 1.8 [Saturday, September 30, 2023] 18 | . GoAccess 1.8 Released. See ChangeLog for new features/bug-fixes. 19 | - 1.7.2 [Friday, March 31, 2023] 20 | . GoAccess 1.7.2 Released. See ChangeLog for new features/bug-fixes. 21 | - 1.7.1 [Tuesday, February 28, 2023] 22 | . GoAccess 1.7.1 Released. See ChangeLog for new features/bug-fixes. 23 | - 1.7 [Saturday, December 31 , 2022] 24 | . GoAccess 1.7 Released. See ChangeLog for new features/bug-fixes. 25 | - 1.6.5 [Monday, October 31 , 2022] 26 | . GoAccess 1.6.5 Released. See ChangeLog for new features/bug-fixes. 27 | - 1.6.4 [Friday, September 30 , 2022] 28 | . GoAccess 1.6.4 Released. See ChangeLog for new features/bug-fixes. 29 | - 1.6.3 [Thursday, August 31 , 2022] 30 | . GoAccess 1.6.3 Released. See ChangeLog for new features/bug-fixes. 31 | - 1.6.2 [Thursday, July 14 , 2022] 32 | . GoAccess 1.6.2 Released. See ChangeLog for new features/bug-fixes. 33 | - 1.6.1 [Thursday, June 30 , 2022] 34 | . GoAccess 1.6.1 Released. See ChangeLog for new features/bug-fixes. 35 | - 1.6 [Tuesday, May 31 , 2022] 36 | . GoAccess 1.6 Released. See ChangeLog for new features/bug-fixes. 37 | - 1.5.7 [Thursday, April 28 , 2022] 38 | . GoAccess 1.5.7 Released. See ChangeLog for new features/bug-fixes. 39 | - 1.5.6 [Wednesday, March 30, 2022] 40 | . GoAccess 1.5.6 Released. See ChangeLog for new features/bug-fixes. 41 | - 1.5.5 [Monday, January 31, 2022] 42 | . GoAccess 1.5.5 Released. See ChangeLog for new features/bug-fixes. 43 | - 1.5.4 [Saturday, December 25, 2021] 44 | . GoAccess 1.5.4 Released. See ChangeLog for new features/bug-fixes. 45 | - 1.5.3 [Thursday, November 25, 2021] 46 | . GoAccess 1.5.3 Released. See ChangeLog for new features/bug-fixes. 47 | - 1.5.2 [Tuesday, Sep 28, 2021] 48 | . GoAccess 1.5.2 Released. See ChangeLog for new features/bug-fixes. 49 | - 1.5.1 [Wednesday, Jun 30, 2021] 50 | . GoAccess 1.5.1 Released. See ChangeLog for new features/bug-fixes. 51 | - 1.5 [Wednesday, May 26, 2021] 52 | . GoAccess 1.5 Released. See ChangeLog for new features/bug-fixes. 53 | - 1.4.6 [Sunday, February 28, 2021] 54 | . GoAccess 1.4.6 Released. See ChangeLog for new features/bug-fixes. 55 | - 1.4.5 [Tuesday, January 26, 2021] 56 | . GoAccess 1.4.5 Released. See ChangeLog for new features/bug-fixes. 57 | - 1.4.4 [Monday, January 25, 2021] 58 | . GoAccess 1.4.4 Released. See ChangeLog for new features/bug-fixes. 59 | - 1.4.3 [Friday, December 04, 2020] 60 | . GoAccess 1.4.3 Released. See ChangeLog for new features/bug-fixes. 61 | - 1.4.2 [Monday, November 16, 2020] 62 | . GoAccess 1.4.2 Released. See ChangeLog for new features/bug-fixes. 63 | - 1.4.1 [Monday, November 09, 2020] 64 | . GoAccess 1.4.1 Released. See ChangeLog for new features/bug-fixes. 65 | - 1.4 [Monday, May 18, 2020] 66 | . GoAccess 1.4 Released. See ChangeLog for new features/bug-fixes. 67 | - 1.3 [Friday, November 23, 2018] 68 | . GoAccess 1.3 Released. See ChangeLog for new features/bug-fixes. 69 | - 1.2 [Tuesday, March 07, 2017] 70 | . GoAccess 1.2 Released. See ChangeLog for new features/bug-fixes. 71 | - 1.1.1 [Wednesday, November 23, 2016] 72 | . GoAccess 1.1.1 Released. See ChangeLog for new features/bug-fixes. 73 | - 1.1 [Tuesday, November 08, 2016] 74 | . GoAccess 1.1 Released. See ChangeLog for new features/bug-fixes. 75 | - 1.0.2 [Tuesday, July 05, 2016] 76 | . GoAccess 1.0.2 Released. See ChangeLog for new features/bug-fixes. 77 | - 1.0.1 [Friday, June 17, 2016] 78 | . GoAccess 1.0.1 Released. See ChangeLog for new features/bug-fixes. 79 | - 1.0 [Thursday, June 09, 2016] 80 | . GoAccess 1.0 Released. See ChangeLog for new features/bug-fixes. 81 | - 0.9.8 [Monday, February 29, 2016] 82 | . GoAccess 0.9.8 Released. See ChangeLog for new features/bug-fixes. 83 | - 0.9.7 [Monday, December 21, 2015] 84 | . GoAccess 0.9.7 Released. See ChangeLog for new features/bug-fixes. 85 | - 0.9.6 [Tuesday, October 27, 2015] 86 | . GoAccess 0.9.6 Released. See ChangeLog for new features/bug-fixes. 87 | - 0.9.5 [Thursday, October 22, 2015] 88 | . GoAccess 0.9.5 Released. See ChangeLog for new features/bug-fixes. 89 | - 0.9.4 [Tuesday, September 08 , 2015] 90 | . GoAccess 0.9.4 Released. See ChangeLog for new features/bug-fixes. 91 | - 0.9.3 [Wednesday, August 28, 2015] 92 | . GoAccess 0.9.3 Released. See ChangeLog for new features/bug-fixes. 93 | - 0.9.2 [Monday, July 06, 2015] 94 | . GoAccess 0.9.2 Released. See ChangeLog for new features/bug-fixes. 95 | - 0.9.1 [Tuesday, May 26, 2015] 96 | . GoAccess 0.9.1 Released. See ChangeLog for new features/bug-fixes. 97 | - 0.9 [Thursday, March 19, 2015] 98 | . GoAccess 0.9 Released. See ChangeLog for new features/bug-fixes. 99 | - 0.8.5 [Sunday, September 14, 2014] 100 | . GoAccess 0.8.5 Released. See ChangeLog for new features/bug-fixes. 101 | - 0.8.4 [Monday, September 08, 2014] 102 | . GoAccess 0.8.4 Released. See ChangeLog for new features/bug-fixes. 103 | - 0.8.3 [Monday, July 28, 2014] 104 | . GoAccess 0.8.3 Released. See ChangeLog for new features/bug-fixes. 105 | - 0.8.2 [Monday, July 21, 2014] 106 | . GoAccess 0.8.2 Released. See ChangeLog for new features/bug-fixes. 107 | - 0.8.1 [Monday, June 16, 2014] 108 | . GoAccess 0.8.1 Released. See ChangeLog for new features/bug-fixes. 109 | - 0.8 [Monday, May 20, 2013] 110 | . GoAccess 0.8 Released. See ChangeLog for new features/bug-fixes. 111 | - 0.7.1 [Monday, February 17, 2014] 112 | . GoAccess 0.7.1 Released. See ChangeLog for new features/bug-fixes. 113 | - 0.7 [Monday, December 16, 2013] 114 | . GoAccess 0.7 Released. See ChangeLog for new features/bug-fixes. 115 | - 0.6.1 [Monday, October 07, 2013] 116 | . GoAccess 0.6.1 Released. See ChangeLog for new features/bug-fixes. 117 | - 0.6 [Monday, July 15, 2013] 118 | . GoAccess 0.6 Released. See ChangeLog for new features/bug-fixes. 119 | - 0.5 [Monday, June 04, 2012] 120 | . GoAccess 0.5 Released. See ChangeLog for new features/bug-fixes. 121 | - 0.4.2 [Monday, January 03, 2011] 122 | . GoAccess 0.4.2 Released. See ChangeLog for new features/bug-fixes. 123 | - 0.4.1 [Monday, December 13, 2010] 124 | . GoAccess 0.4.1 Released. See ChangeLog for new features/bug-fixes. 125 | - 0.4 [Tuesday, November 30, 2010] 126 | . GoAccess 0.4 Released. See ChangeLog for new features/bug-fixes. 127 | - 0.3.3 [Monday, September 27, 2010] 128 | . GoAccess 0.3.3 Released. See ChangeLog for new features/bug-fixes. 129 | - 0.3.2 [Thursday, September 09 2010] 130 | . GoAccess 0.3.2 Released. See ChangeLog for new features/bug-fixes. 131 | - 0.3.1 [Friday, September 03, 2010] 132 | . GoAccess 0.3.1 Released. See ChangeLog for new features/bug-fixes. 133 | - 0.3 [Sunday, August 29, 2010] 134 | . GoAccess 0.3 Released. See ChangeLog for new features/bug-fixes. 135 | - 0.2 [Sunday, July 25, 2010] 136 | . GoAccess 0.2 Released. See ChangeLog for new features/bug-fixes. 137 | - 0.1.2 [Tuesday, July 13, 2010] 138 | . GoAccess 0.1.2 Released. See ChangeLog for new features/bug-fixes. 139 | - 0.1.1 [Saturday, July 10, 2010] 140 | . GoAccess 0.1.1 Released. See ChangeLog for new features/bug-fixes. 141 | - 0.1 [Wednesday, July 07, 2010] 142 | . Welcome to the GoAccess 0.1 Released. 143 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Found a security issue in [GoAccess](https://github.com/allinurl/goaccess)? 4 | Read on. 5 | 6 | ## Reporting a Vulnerability 7 | 8 | GoAccess takes all security bugs seriously. Thank you for improving the 9 | security of `goaccess`. I appreciate your efforts and responsible disclosure 10 | and will make every effort to acknowledge your contributions. 11 | 12 | Vulnerabilities should be reported to [hello@goaccess.io](mailto:hello@goaccess.io) which is a private, 13 | maintainer-only email address. 14 | 15 | 16 | When I receive a security bug report, I will work on the fix and prepare a 17 | release including the following steps: 18 | 19 | * Confirm the problem and determine the affected versions. 20 | * Audit the code to find any potential similar problems. 21 | 22 | ## Comments on this Policy 23 | 24 | If you have suggestions on how this process could be improved please submit a 25 | pull request. 26 | 27 | When reporting an issue, where possible, please provide the following (if 28 | possible): 29 | 30 | * Commit version where the issue was introduced. 31 | * A proof of concept (plaintext; or ideally send a patch to same email address) 32 | * Steps to reproduce 33 | * Your recommended fixes, if any. 34 | 35 | > Note: Please do not open public issues for security issues, as GitHub does 36 | > not provide facility for private issues, and deleting the issue makes it hard 37 | > to triage/respond back to the reporter. 38 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 1Copyright (C) 2009-2024 2 | 6erardo 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 https://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 | -------------------------------------------------------------------------------- /build-dynamic.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Build dynamic linked binaries on Debian. 3 | set -o nounset ## set -u : exit the script if you try to use an uninitialised variable 4 | set -o errexit ## set -e : exit the script if any statement returns a non-true return value 5 | 6 | # should be either of "mmdb" or "legacy" 7 | geoip=${1:-"mmdb"} 8 | 9 | autoreconf -fi > /dev/null 2>&1 10 | ./configure CFLAGS=-Werror --enable-utf8 --with-openssl --with-getline --enable-geoip="$geoip" >/dev/null 11 | make -j > /dev/null 12 | cat goaccess 13 | -------------------------------------------------------------------------------- /config/browsers.list: -------------------------------------------------------------------------------- 1 | # List of browsers and their categories 2 | # e.g., WORD delimited by tab(s) TYPE 3 | # TYPE can be any type and it's not limited to the ones below. 4 | # 5 | # **IMPORTANT NOTE**: 6 | # --------------------- 7 | # The SIZE of the list is proportional to the run time. 8 | # Thus, the longer the list, the more time GoAccess will take to parse it. 9 | # 10 | # Also, you should note that the higher the browser/item is on the list, the 11 | # faster the parsing will be. 12 | # 13 | # The list needs to be specified using --browsers-file=. This file is not 14 | # parsed by default. 15 | # 16 | # The items below are sample crawlers, adjust as needed. 17 | 18 | Chef Client Crawlers 19 | Abonti Crawlers 20 | SISTRIX Crawlers 21 | DotBot Crawlers 22 | Speedy Spider Crawlers 23 | Sosospider Crawlers 24 | BPImageWalker Crawlers 25 | DoCoMo Crawlers 26 | GSLFbot Crawlers 27 | YodaoBot Crawlers 28 | AddThis Crawlers 29 | Purebot Crawlers 30 | CCBot Crawlers 31 | findlinks Crawlers 32 | ichiro Crawlers 33 | Linguee Bot Crawlers 34 | Gigabot Crawlers 35 | BacklinkCrawler Crawlers 36 | distilator Crawlers 37 | Aboundex Crawlers 38 | UnwindFetchor Crawlers 39 | SBIder Crawlers 40 | TestNutch Crawlers 41 | DomainCrawler Crawlers 42 | NextGenSearchBot Crawlers 43 | SEOENGWorldBot Crawlers 44 | Cityreview Crawlers 45 | PagePeeker Crawlers 46 | JS-Kit Crawlers 47 | ScreenerBot Crawlers 48 | ShowyouBot Crawlers 49 | SolomonoBot Crawlers 50 | Domnutch Crawlers 51 | MaxPoint Crawlers 52 | NCBot Crawlers 53 | TosCrawler Crawlers 54 | Updownerbot Crawlers 55 | OpenWebSpider Crawlers 56 | WordPress Crawlers 57 | PEAR Crawlers 58 | ZumBot Crawlers 59 | YisouSpider Crawlers 60 | W3C Crawlers 61 | vcheck Crawlers 62 | PercolateCrawler Crawlers 63 | NING Crawlers 64 | gvfs Crawlers 65 | CatchBot Crawlers 66 | Combine Crawlers 67 | A6-Indexer Crawlers 68 | Altresium Crawlers 69 | Comodo Crawlers 70 | crawler4j Crawlers 71 | Cricket Crawlers 72 | EC2LinkFinder Crawlers 73 | envolk Crawlers 74 | GeoHasher Crawlers 75 | HTMLParser Crawlers 76 | MLBot Crawlers 77 | Jaxified Crawlers 78 | LinkWalker Crawlers 79 | nutch Crawlers 80 | PostRank Crawlers 81 | keybase-proofs Crawlers 82 | CommonCrawler Crawlers 83 | X-CAD-SE Crawlers 84 | Safeassign Crawlers 85 | Nmap Crawlers 86 | sqlmap Crawlers 87 | Jorgee Crawlers 88 | PxBroker Crawlers 89 | Seekport Crawlers 90 | adscanner Crawlers 91 | AfD-Verbotsverfahren_JETZT! Crawlers 92 | DuckDuckGo-favicons-Bot Crawlers 93 | bingbot Crawlers 94 | PetalBot Crawlers 95 | Discordbot Crawlers 96 | ZoominfoBot Crawlers 97 | Googlebot Crawlers 98 | AhrefsBot Crawlers 99 | SemrushBot Crawlers 100 | Adsbot Crawlers 101 | BLEXBot Crawlers 102 | NetcraftSurveyAgent Crawlers 103 | Netcraft Web Server Survey Crawlers 104 | masscan Crawlers 105 | MJ12bot Crawlers 106 | Pandalytics Crawlers 107 | YandexBot Crawlers 108 | Nimbostratus-Bot Crawlers 109 | SeznamBot Crawlers 110 | AppleBot Crawlers 111 | 112 | Vienna Feeds 113 | Windows-RSS-Platform Feeds 114 | newsbeuter Feeds 115 | Wrangler Feeds 116 | Fever Feeds 117 | Tiny Feeds 118 | FreshRSS Feeds 119 | KrISS Feeds 120 | SimplePie Feeds 121 | Feedsubs Feeds 122 | UniversalFeedParser Feeds 123 | -------------------------------------------------------------------------------- /config/podcast.list: -------------------------------------------------------------------------------- 1 | # vim: set noexpandtab: 2 | #1 This file is a user agent list of various podcast-related agents (but not 3 | #2 limited to). It was distilled from the user agents of a web page which hosts 4 | #3 a Wordpress blog and a podcast. 5 | #4 \author Bernhard R. Fischer, 6 | #5 \date 2019/09/26 7 | AntennaPod Podcasts 8 | AppleCoreMedia Mediaplayer 9 | atc Podcasts 10 | BacklinkCrawler Crawlers 11 | Baiduspider Crawlers 12 | Bullhorn Server PodCrawlers 13 | Castbox Podcasts 14 | CastBox Podcasts 15 | Castro Podcasts 16 | CCBot Crawlers 17 | com.evolve.podcast Podcasts 18 | cortex Facebook 19 | ExoPlayerLib Mediaplayer 20 | facebookexternalhit Facebook 21 | fyyd image poller PodCrawlers 22 | fyyd-poll PodCrawlers 23 | icatcher Podcasts 24 | iCatcher! Podcasts 25 | iTMS PodCrawlers 26 | itunesstored PodCrawlers 27 | Kodi Mediaplayer 28 | Lavf Mediaplayer 29 | LCC Crawlers 30 | Luminary Podcasts 31 | Mediatoolkitbot Crawlers 32 | mindUpBot Crawlers 33 | msnbot Crawlers 34 | NSPlayer Mediaplayer 35 | Overcast Podcasts 36 | Photon Crawlers 37 | Player FM Podcasts 38 | PlayerFM Podcasts 39 | Plex Mediaplayer 40 | Podbean Podcasts 41 | podcast Podcasts 42 | Podcast Podcasts 43 | PodcastRepublic Podcasts 44 | Podcasts Podcasts 45 | Podchaser PodCrawlers 46 | Podchaser-Parser PodCrawlers 47 | Podnews.net PodCrawlers 48 | PodParadise PodCrawlers 49 | Procast Podcasts 50 | ProCast Podcasts 51 | Procast (iOS) Podcasts 52 | ProcastProCast Podcasts 53 | radio.at PodCrawlers 54 | RadioPublic PodCrawlers 55 | RadioPublicImageResizer PodCrawlers 56 | RSSRadio Podcasts 57 | Sonos Mediaplayer 58 | Spotify PodCrawlers 59 | stagefright Mediaplayer 60 | Stitcher PodCrawlers 61 | UniversalFeedParser Feeds 62 | WinampMPEG Mediaplayer 63 | XING FeedReader Feeds 64 | XING-contenttabreceiver Feeds 65 | -------------------------------------------------------------------------------- /docker-compose/README.md: -------------------------------------------------------------------------------- 1 | # Docker-compose configuration 2 | 3 | Here are two docker-compose configurations for goaccess which 4 | combine a static site with a real-time report of goaccess. 5 | The directories used are: 6 | 7 | - `configs` - for the nginx and goaccess configuration 8 | - `public` - the files served by nginx - put your static site here 9 | - `logs` - nginx logs - there is no log rotation in place! 10 | 11 | There are two flavors of the docker-compose files and the goaccess files: 12 | - `*.vanilla.*` which need you to take care of the TLS certificates 13 | - `*.traefik.*` using traefik for TLS and domain routing 14 | 15 | ## Vanilla 16 | 17 | For the vanilla version, you'll have to do the following: 18 | 19 | - put the TLS certificates into `configs/certs`, following the naming scheme 20 | in `goaccess.vanilla.conf` 21 | - route requests for the static webpage to port `8080` 22 | 23 | ## Traefik 24 | 25 | The traefik version is setup to make it easier to do the routing. 26 | You don't need to take care of the TLS certificates, and the 27 | goaccess websocket gets its own subdomain. 28 | 29 | To put it all together, the following environment is needed: 30 | - traefik configured according to [Traefik-101](https://ineiti.ch/posts/traefik-101/traefik-101/) 31 | - DNS configuration for two domain names pointing to your server's IP: 32 | - `yourdomain` for the static pages, e.g., a blog-post using [Hugo](https://gohugo.io/) 33 | - `goaccess.yourdomain` for the stats with goaccess 34 | 35 | -------------------------------------------------------------------------------- /docker-compose/configs/goaccess.traefik.conf: -------------------------------------------------------------------------------- 1 | tz Europe/Zurich 2 | time-format %H:%M:%S 3 | date-format %Y-%m-%d 4 | log-format COMBINED 5 | log-file /srv/logs/access.log 6 | output /srv/report/report.html 7 | real-time-html true 8 | ws-url wss://goaccess.yourdomain 9 | port 443 10 | -------------------------------------------------------------------------------- /docker-compose/configs/goaccess.vanilla.conf: -------------------------------------------------------------------------------- 1 | tz Europe/Zurich 2 | time-format %H:%M:%S 3 | date-format %Y-%m-%d 4 | log-format COMBINED 5 | log-file /srv/logs/access.log 6 | output /srv/report/report.html 7 | real-time-html true 8 | ws-url wss://yourdomain 9 | ssl-cert /srv/certs/yourdomain.crt 10 | ssl-key /srv/certs/yourdomain.key 11 | -------------------------------------------------------------------------------- /docker-compose/configs/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes auto; 3 | 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | #tcp_nopush on; 25 | 26 | keepalive_timeout 65; 27 | 28 | #gzip on; 29 | 30 | include /etc/nginx/conf.d/*.conf; 31 | } 32 | -------------------------------------------------------------------------------- /docker-compose/docker-compose.traefik.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | image: nginx 4 | volumes: 5 | - ./logs:/var/log/nginx 6 | - ./config/nginx.conf:/etc/nginx/nginx.conf 7 | - ./public:/usr/share/nginx/html 8 | labels: 9 | - "traefik.enable=true" 10 | - "fqdn=yourdomain" 11 | networks: 12 | - traefik 13 | 14 | goaccess: 15 | image: allinurl/goaccess 16 | container_name: goaccess 17 | volumes: 18 | - ./configs/goaccess.traefik.conf:/srv/config/goaccess.conf 19 | - ./logs:/srv/logs 20 | - ./public:/srv/report 21 | command: ["--no-global-config", "--config-file=/srv/config/goaccess.conf"] 22 | labels: 23 | - "traefik.enable=true" 24 | - "fqdn=goaccess.yourdomain" 25 | - "traefik.http.services.yourdomain-goaccess.loadbalancer.server.port=443" 26 | restart: unless-stopped 27 | networks: 28 | - traefik 29 | 30 | networks: 31 | traefik: 32 | external: 33 | name: traefik_traefik 34 | -------------------------------------------------------------------------------- /docker-compose/docker-compose.vanilla.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | image: nginx 4 | ports: 5 | - 8080:80 6 | volumes: 7 | - ./logs:/var/log/nginx 8 | - ./config/nginx.conf:/etc/nginx/nginx.conf 9 | - ./public:/usr/share/nginx/html 10 | 11 | goaccess: 12 | image: allinurl/goaccess 13 | ports: 14 | - 7890:7890 15 | volumes: 16 | - ./configs/goaccess.vanilla.conf:/srv/config/goaccess.conf 17 | - ./logs:/srv/logs 18 | - ./public:/srv/report 19 | - ./configs/certs:/srv/certs 20 | command: ["--no-global-config", "--config-file=/srv/config/goaccess.conf"] 21 | restart: unless-stopped 22 | -------------------------------------------------------------------------------- /inlang.config.js: -------------------------------------------------------------------------------- 1 | // init the inlang.config 2 | 3 | /** 4 | * @type {import("@inlang/core/config").DefineConfig} 5 | */ 6 | export async function defineConfig(env) { 7 | // importing plugin from local file for testing purposes 8 | const plugin = await env.$import( 9 | "https://cdn.jsdelivr.net/gh/jannesblobel/inlang-plugin-po@1/dist/index.js" 10 | ); 11 | const pluginConfig = { 12 | // language mean the name of you file 13 | pathPattern: "./po/{language}.po", 14 | referenceResourcePath: "./po/goaccess.pot", 15 | }; 16 | 17 | return { 18 | // if your project use a pot file use the pot as the reference Language 19 | // !! do not add the pot file in the Languages array 20 | /** 21 | * @example 22 | * example files: en.pot, de.po, es.po, fr.po 23 | * referenceLanguage: "en", 24 | languages: ["de","es","fr"], 25 | */ 26 | referenceLanguage: "en", 27 | languages: await getLanguages(env), 28 | readResources: (args) => 29 | plugin.readResources({ ...args, ...env, pluginConfig }), 30 | writeResources: (args) => 31 | plugin.writeResources({ ...args, ...env, pluginConfig }), 32 | }; 33 | } 34 | 35 | /** 36 | * Automatically derives the languages in this repository. 37 | */ 38 | async function getLanguages(env) { 39 | const files = await env.$fs.readdir("./po"); 40 | // files that end with .json 41 | // remove the .json extension to only get language name 42 | const languages = files 43 | .filter((name) => name.endsWith(".po")) 44 | .map((name) => name.replace(".po", "")); 45 | return languages; 46 | } 47 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | de 2 | es 3 | fr 4 | ja 5 | ko 6 | sv 7 | zh_CN 8 | pt_BR 9 | ru 10 | uk 11 | it 12 | 13 | -------------------------------------------------------------------------------- /po/Makevars: -------------------------------------------------------------------------------- 1 | # Makefile variables for PO directory in any package using GNU gettext. 2 | 3 | # Usually the message domain is the same as the package name. 4 | DOMAIN = $(PACKAGE) 5 | 6 | # These two variables depend on the location of this directory. 7 | subdir = po 8 | top_builddir = .. 9 | AM_CPPFLAGS = -I. -I$(srcdir) 10 | 11 | # These options get passed to xgettext. 12 | XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ 13 | 14 | # This is the copyright holder that gets inserted into the header of the 15 | # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding 16 | # package. (Note that the msgstr strings, extracted from the package's 17 | # sources, belong to the copyright holder of the package.) Translators are 18 | # expected to transfer the copyright for their translations to this person 19 | # or entity, or to disclaim their copyright. The empty string stands for 20 | # the public domain; in this case the translators are expected to disclaim 21 | # their copyright. 22 | COPYRIGHT_HOLDER = Free Software Foundation, Inc. 23 | 24 | # This tells whether or not to prepend "GNU " prefix to the package 25 | # name that gets inserted into the header of the $(DOMAIN).pot file. 26 | # Possible values are "yes", "no", or empty. If it is empty, try to 27 | # detect it automatically by scanning the files in $(top_srcdir) for 28 | # "GNU packagename" string. 29 | PACKAGE_GNU = 30 | 31 | # This is the email address or URL to which the translators shall report 32 | # bugs in the untranslated strings: 33 | # - Strings which are not entire sentences, see the maintainer guidelines 34 | # in the GNU gettext documentation, section 'Preparing Strings'. 35 | # - Strings which use unclear terms or require additional context to be 36 | # understood. 37 | # - Strings which make invalid assumptions about notation of date, time or 38 | # money. 39 | # - Pluralisation problems. 40 | # - Incorrect English spelling. 41 | # - Incorrect formatting. 42 | # It can be your email address, or a mailing list address where translators 43 | # can write to without being subscribed, or the URL of a web page through 44 | # which the translators can contact you. 45 | MSGID_BUGS_ADDRESS = hello@goaccess.io 46 | 47 | # This is the list of locale categories, beyond LC_MESSAGES, for which the 48 | # message catalogs shall be used. It is usually empty. 49 | EXTRA_LOCALE_CATEGORIES = 50 | 51 | # This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' 52 | # context. Possible values are "yes" and "no". Set this to yes if the 53 | # package uses functions taking also a message context, like pgettext(), or 54 | # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. 55 | USE_MSGCTXT = no 56 | 57 | # These options get passed to msgmerge. 58 | # Useful options are in particular: 59 | # --previous to keep previous msgids of translated messages, 60 | # --quiet to reduce the verbosity. 61 | MSGMERGE_OPTIONS = 62 | 63 | # These options get passed to msginit. 64 | # If you want to disable line wrapping when writing PO files, add 65 | # --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and 66 | # MSGINIT_OPTIONS. 67 | MSGINIT_OPTIONS = 68 | 69 | # This tells whether or not to regenerate a PO file when $(DOMAIN).pot 70 | # has changed. Possible values are "yes" and "no". Set this to no if 71 | # the POT file is checked in the repository and the version control 72 | # program ignores timestamps. 73 | PO_DEPENDS_ON_POT = yes 74 | 75 | # This tells whether or not to forcibly update $(DOMAIN).pot and 76 | # regenerate PO files on "make dist". Possible values are "yes" and 77 | # "no". Set this to no if the POT file and PO files are maintained 78 | # externally. 79 | DIST_DEPENDS_ON_UPDATE_PO = yes 80 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files which contain translatable strings. 2 | src/labels.h 3 | -------------------------------------------------------------------------------- /resources/goaccess.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /resources/js/hogan.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright 2012 Twitter, Inc. 3 | * @license http://www.apache.org/licenses/LICENSE-2.0.txt 4 | */ 5 | var Hogan={};!function(t){function n(t,n,e){var i;return n&&"object"==typeof n&&(void 0!==n[t]?i=n[t]:e&&n.get&&"function"==typeof n.get&&(i=n.get(t))),i}function e(t,n,e,i,r,s){function a(){}function o(){}a.prototype=t,o.prototype=t.subs;var u,c=new a;c.subs=new o,c.subsText={},c.buf="",i=i||{},c.stackSubs=i,c.subsText=s;for(u in n)i[u]||(i[u]=n[u]);for(u in i)c.subs[u]=i[u];r=r||{},c.stackPartials=r;for(u in e)r[u]||(r[u]=e[u]);for(u in r)c.partials[u]=r[u];return c}function i(t){return String(null===t||void 0===t?"":t)}function r(t){return t=i(t),l.test(t)?t.replace(s,"&").replace(a,"<").replace(o,">").replace(u,"'").replace(c,"""):t}t.Template=function(t,n,e,i){t=t||{},this.r=t.code||this.r,this.c=e,this.options=i||{},this.text=n||"",this.partials=t.partials||{},this.subs=t.subs||{},this.buf=""},t.Template.prototype={r:function(){return""},v:r,t:i,render:function(t,n,e){return this.ri([t],n||{},e)},ri:function(t,n,e){return this.r(t,n,e)},ep:function(t,n){var i=this.partials[t],r=n[i.name];if(i.instance&&i.base==r)return i.instance;if("string"==typeof r){if(!this.c)throw new Error("No compiler available.");r=this.c.compile(r,this.options)}if(!r)return null;if(this.partials[t].base=r,i.subs){n.stackText||(n.stackText={});for(key in i.subs)n.stackText[key]||(n.stackText[key]=void 0!==this.activeSub&&n.stackText[this.activeSub]?n.stackText[this.activeSub]:this.text);r=e(r,i.subs,i.partials,this.stackSubs,this.stackPartials,n.stackText)}return this.partials[t].instance=r,r},rp:function(t,n,e,i){var r=this.ep(t,e);return r?r.ri(n,e,i):""},rs:function(t,n,e){var i=t[t.length-1];if(!f(i))return void e(t,n,this);for(var r=0;r=0;c--)if(a=e[c],s=n(t,a,u),void 0!==s){o=!0;break}return o?(r||"function"!=typeof s||(s=this.mv(s,e,i)),s):r?!1:""},ls:function(t,n,e,r,s){var a=this.options.delimiters;return this.options.delimiters=s,this.b(this.ct(i(t.call(n,r)),n,e)),this.options.delimiters=a,!1},ct:function(t,n,e){if(this.options.disableLambda)throw new Error("Lambda features disabled.");return this.c.compile(t,this.options).render(n,e)},b:function(t){this.buf+=t},fl:function(){var t=this.buf;return this.buf="",t},ms:function(t,n,e,i,r,s,a){var o,u=n[n.length-1],c=t.call(u);return"function"==typeof c?i?!0:(o=this.activeSub&&this.subsText&&this.subsText[this.activeSub]?this.subsText[this.activeSub]:this.text,this.ls(c,u,e,o.substring(r,s),a)):c},mv:function(t,n,e){var r=n[n.length-1],s=t.call(r);return"function"==typeof s?this.ct(i(s.call(r)),r,e):s},sub:function(t,n,e,i){var r=this.subs[t];r&&(this.activeSub=t,r(n,e,this,i),this.activeSub=!1)}};var s=/&/g,a=//g,u=/\'/g,c=/\"/g,l=/[&<>\"\']/,f=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)}}("undefined"!=typeof exports?exports:Hogan),function(t){function n(t){"}"===t.n.substr(t.n.length-1)&&(t.n=t.n.substring(0,t.n.length-1))}function e(t){return t.trim?t.trim():t.replace(/^\s*|\s*$/g,"")}function i(t,n,e){if(n.charAt(e)!=t.charAt(0))return!1;for(var i=1,r=t.length;r>i;i++)if(n.charAt(e+i)!=t.charAt(i))return!1;return!0}function r(n,e,i,o){var u=[],c=null,l=null,f=null;for(l=i[i.length-1];n.length>0;){if(f=n.shift(),l&&"<"==l.tag&&!(f.tag in k))throw new Error("Illegal content in < super tag.");if(t.tags[f.tag]<=t.tags.$||s(f,o))i.push(f),f.nodes=r(n,f.tag,i,o);else{if("/"==f.tag){if(0===i.length)throw new Error("Closing tag without opener: /"+f.n);if(c=i.pop(),f.n!=c.n&&!a(f.n,c.n,o))throw new Error("Nesting error: "+c.n+" vs. "+f.n);return c.end=f.i,u}"\n"==f.tag&&(f.last=0==n.length||"\n"==n[0].tag)}u.push(f)}if(i.length>0)throw new Error("missing closing tag: "+i.pop().n);return u}function s(t,n){for(var e=0,i=n.length;i>e;e++)if(n[e].o==t.n)return t.tag="#",!0}function a(t,n,e){for(var i=0,r=e.length;r>i;i++)if(e[i].c==t&&e[i].o==n)return!0}function o(t){var n=[];for(var e in t)n.push('"'+c(e)+'": function(c,p,t,i) {'+t[e]+"}");return"{ "+n.join(",")+" }"}function u(t){var n=[];for(var e in t.partials)n.push('"'+c(e)+'":{name:"'+c(t.partials[e].name)+'", '+u(t.partials[e])+"}");return"partials: {"+n.join(",")+"}, subs: "+o(t.subs)}function c(t){return t.replace(m,"\\\\").replace(v,'\\"').replace(b,"\\n").replace(d,"\\r").replace(x,"\\u2028").replace(w,"\\u2029")}function l(t){return~t.indexOf(".")?"d":"f"}function f(t,n){var e="<"+(n.prefix||""),i=e+t.n+y++;return n.partials[i]={name:t.n,partials:{}},n.code+='t.b(t.rp("'+c(i)+'",c,p,"'+(t.indent||"")+'"));',i}function h(t,n){n.code+="t.b(t.t(t."+l(t.n)+'("'+c(t.n)+'",c,p,0)));'}function p(t){return"t.b("+t+");"}var g=/\S/,v=/\"/g,b=/\n/g,d=/\r/g,m=/\\/g,x=/\u2028/,w=/\u2029/;t.tags={"#":1,"^":2,"<":3,$:4,"/":5,"!":6,">":7,"=":8,_v:9,"{":10,"&":11,_t:12},t.scan=function(r,s){function a(){m.length>0&&(x.push({tag:"_t",text:new String(m)}),m="")}function o(){for(var n=!0,e=y;e"==e.tag&&(e.indent=x[i].text.toString()),x.splice(i,1));else n||x.push({tag:"\n"});w=!1,y=x.length}function c(t,n){var i="="+S,r=t.indexOf(i,n),s=e(t.substring(t.indexOf("=",n)+1,r)).split(" ");return T=s[0],S=s[s.length-1],r+i.length-1}var l=r.length,f=0,h=1,p=2,v=f,b=null,d=null,m="",x=[],w=!1,k=0,y=0,T="{{",S="}}";for(s&&(s=s.split(" "),T=s[0],S=s[1]),k=0;l>k;k++)v==f?i(T,r,k)?(--k,a(),v=h):"\n"==r.charAt(k)?u(w):m+=r.charAt(k):v==h?(k+=T.length-1,d=t.tags[r.charAt(k+1)],b=d?r.charAt(k+1):"_v","="==b?(k=c(r,k),v=f):(d&&k++,v=p),w=k):i(S,r,k)?(x.push({tag:b,n:e(m),otag:T,ctag:S,i:"/"==b?w-T.length:k+S.length}),m="",k+=S.length-1,v=f,"{"==b&&("}}"==S?k++:n(x[x.length-1]))):m+=r.charAt(k);return u(w,!0),x};var k={_t:!0,"\n":!0,$:!0,"/":!0};t.stringify=function(n){return"{code: function (c,p,i) { "+t.wrapMain(n.code)+" },"+u(n)+"}"};var y=0;t.generate=function(n,e,i){y=0;var r={code:"",subs:{},partials:{}};return t.walk(n,r),i.asString?this.stringify(r,e,i):this.makeTemplate(r,e,i)},t.wrapMain=function(t){return'var t=this;t.b(i=i||"");'+t+"return t.fl();"},t.template=t.Template,t.makeTemplate=function(t,n,e){var i=this.makePartials(t);return i.code=new Function("c","p","i",this.wrapMain(t.code)),new this.template(i,n,this,e)},t.makePartials=function(t){var n,e={subs:{},partials:t.partials,name:t.name};for(n in e.partials)e.partials[n]=this.makePartials(e.partials[n]);for(n in t.subs)e.subs[n]=new Function("c","p","t","i",t.subs[n]);return e},t.codegen={"#":function(n,e){e.code+="if(t.s(t."+l(n.n)+'("'+c(n.n)+'",c,p,1),c,p,0,'+n.i+","+n.end+',"'+n.otag+" "+n.ctag+'")){t.rs(c,p,function(c,p,t){',t.walk(n.nodes,e),e.code+="});c.pop();}"},"^":function(n,e){e.code+="if(!t.s(t."+l(n.n)+'("'+c(n.n)+'",c,p,1),c,p,1,0,0,"")){',t.walk(n.nodes,e),e.code+="};"},">":f,"<":function(n,e){var i={partials:{},code:"",subs:{},inPartial:!0};t.walk(n.nodes,i);var r=e.partials[f(n,e)];r.subs=i.subs,r.partials=i.partials},$:function(n,e){var i={subs:{},code:"",partials:e.partials,prefix:n.n};t.walk(n.nodes,i),e.subs[n.n]=i.code,e.inPartial||(e.code+='t.sub("'+c(n.n)+'",c,p,i);')},"\n":function(t,n){n.code+=p('"\\n"'+(t.last?"":" + i"))},_v:function(t,n){n.code+="t.b(t.v(t."+l(t.n)+'("'+c(t.n)+'",c,p,0)));'},_t:function(t,n){n.code+=p('"'+c(t.text)+'"')},"{":h,"&":h},t.walk=function(n,e){for(var i,r=0,s=n.length;s>r;r++)i=t.codegen[n[r].tag],i&&i(n[r],e);return e},t.parse=function(t,n,e){return e=e||{},r(t,"",[],e.sectionTags||[])},t.cache={},t.cacheKey=function(t,n){return[t,!!n.asString,!!n.disableLambda,n.delimiters,!!n.modelGet].join("||")},t.compile=function(n,e){e=e||{};var i=t.cacheKey(n,e),r=this.cache[i];if(r){var s=r.partials;for(var a in s)delete s[a].instance;return r}return r=this.generate(this.parse(this.scan(n,e.delimiters),n,e),n,e),this.cache[i]=r}}("undefined"!=typeof exports?exports:Hogan); -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: goaccess 2 | version: git 3 | summary: Real-time web log analyzer and interactive viewer 4 | description: | 5 | GoAccess is a real-time web log analyzer and interactive viewer that runs 6 | in a terminal in *nix systems or through your browser. 7 | confinement: classic 8 | grade: devel 9 | 10 | apps: 11 | goaccess: 12 | command: bin/goaccess 13 | 14 | parts: 15 | goaccess: 16 | plugin: autotools 17 | source: . 18 | configflags: 19 | - --enable-utf8 20 | - --enable-geoip=legacy 21 | build-packages: 22 | - gettext 23 | - libncurses-dev 24 | - libncursesw5-dev 25 | - libgeoip-dev 26 | stage-packages: 27 | - libgeoip-dev 28 | 29 | -------------------------------------------------------------------------------- /src/base64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * base64.c -- A basic base64 encode implementation 3 | * _______ _______ __ __ 4 | * / ____/ | / / ___/____ _____/ /_____ / /_ 5 | * / / __ | | /| / /\__ \/ __ \/ ___/ //_/ _ \/ __/ 6 | * / /_/ / | |/ |/ /___/ / /_/ / /__/ ,< / __/ /_ 7 | * \____/ |__/|__//____/\____/\___/_/|_|\___/\__/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "base64.h" 36 | #include "xmalloc.h" 37 | 38 | /* Encodes the given data with base64. 39 | * 40 | * On success, the encoded nul-terminated data, as a string is returned. */ 41 | char * 42 | base64_encode (const void *buf, size_t size) { 43 | static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 44 | 45 | char *str = (char *) xmalloc ((size + 3) * 4 / 3 + 1); 46 | 47 | char *p = str; 48 | const unsigned char *q = (const unsigned char *) buf; 49 | size_t i = 0; 50 | 51 | while (i < size) { 52 | int c = q[i++]; 53 | c *= 256; 54 | if (i < size) 55 | c += q[i]; 56 | i++; 57 | 58 | c *= 256; 59 | if (i < size) 60 | c += q[i]; 61 | i++; 62 | 63 | *p++ = base64[(c & 0x00fc0000) >> 18]; 64 | *p++ = base64[(c & 0x0003f000) >> 12]; 65 | 66 | if (i > size + 1) 67 | *p++ = '='; 68 | else 69 | *p++ = base64[(c & 0x00000fc0) >> 6]; 70 | 71 | if (i > size) 72 | *p++ = '='; 73 | else 74 | *p++ = base64[c & 0x0000003f]; 75 | } 76 | 77 | *p = 0; 78 | 79 | return str; 80 | } 81 | 82 | /* 83 | * base64_decode 84 | * 85 | * Given a Base64 encoded string in 'data', this function decodes it into 86 | * a newly allocated binary buffer. The length of the decoded data is stored 87 | * in *out_len. The caller is responsible for freeing the returned buffer. 88 | * 89 | * Returns NULL on error (for example, if the data's length is not a multiple 90 | * of 4). 91 | */ 92 | char * 93 | base64_decode (const char *data, size_t *out_len) { 94 | size_t decoded_len = 0, i = 0, j = 0, pad = 0, len = 0; 95 | char *out = NULL; 96 | uint32_t triple = 0; 97 | 98 | /* Create a lookup table for decoding. 99 | * For valid Base64 characters 'A'-'Z', 'a'-'z', '0'-'9', '+', '/', 100 | * we place their value; for '=' we simply return 0. 101 | * All other characters are marked as 0x80 (an invalid marker). 102 | */ 103 | static const unsigned char dtable[256] = { 104 | ['A'] = 0,['B'] = 1,['C'] = 2,['D'] = 3, 105 | ['E'] = 4,['F'] = 5,['G'] = 6,['H'] = 7, 106 | ['I'] = 8,['J'] = 9,['K'] = 10,['L'] = 11, 107 | ['M'] = 12,['N'] = 13,['O'] = 14,['P'] = 15, 108 | ['Q'] = 16,['R'] = 17,['S'] = 18,['T'] = 19, 109 | ['U'] = 20,['V'] = 21,['W'] = 22,['X'] = 23, 110 | ['Y'] = 24,['Z'] = 25, 111 | ['a'] = 26,['b'] = 27,['c'] = 28,['d'] = 29, 112 | ['e'] = 30,['f'] = 31,['g'] = 32,['h'] = 33, 113 | ['i'] = 34,['j'] = 35,['k'] = 36,['l'] = 37, 114 | ['m'] = 38,['n'] = 39,['o'] = 40,['p'] = 41, 115 | ['q'] = 42,['r'] = 43,['s'] = 44,['t'] = 45, 116 | ['u'] = 46,['v'] = 47,['w'] = 48,['x'] = 49, 117 | ['y'] = 50,['z'] = 51, 118 | ['0'] = 52,['1'] = 53,['2'] = 54,['3'] = 55, 119 | ['4'] = 56,['5'] = 57,['6'] = 58,['7'] = 59, 120 | ['8'] = 60,['9'] = 61, 121 | ['+'] = 62,['/'] = 63, 122 | ['='] = 0, 123 | /* All other values are implicitly 0 (or you can mark them as invalid 124 | by setting them to 0x80 if you prefer stricter checking). */ 125 | }; 126 | 127 | len = strlen (data); 128 | /* Validate length: Base64 encoded data must be a multiple of 4 */ 129 | if (len % 4 != 0) 130 | return NULL; 131 | 132 | /* Count padding characters at the end */ 133 | if (len) { 134 | if (data[len - 1] == '=') 135 | pad++; 136 | if (len > 1 && data[len - 2] == '=') 137 | pad++; 138 | } 139 | 140 | /* Calculate the length of the decoded data */ 141 | decoded_len = (len / 4) * 3 - pad; 142 | out = (char *) xmalloc (decoded_len + 1); /* +1 for a null terminator if needed */ 143 | 144 | for (i = 0, j = 0; i < len;) { 145 | unsigned int sextet_a = data[i] == '=' ? 0 : dtable[(unsigned char) data[i]]; 146 | unsigned int sextet_b = data[i + 1] == '=' ? 0 : dtable[(unsigned char) data[i + 1]]; 147 | unsigned int sextet_c = data[i + 2] == '=' ? 0 : dtable[(unsigned char) data[i + 2]]; 148 | unsigned int sextet_d = data[i + 3] == '=' ? 0 : dtable[(unsigned char) data[i + 3]]; 149 | i += 4; 150 | 151 | triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d; 152 | if (j < decoded_len) 153 | out[j++] = (triple >> 16) & 0xFF; 154 | if (j < decoded_len) 155 | out[j++] = (triple >> 8) & 0xFF; 156 | if (j < decoded_len) 157 | out[j++] = triple & 0xFF; 158 | } 159 | 160 | out[decoded_len] = '\0'; /* Null-terminate the output buffer */ 161 | if (out_len) 162 | *out_len = decoded_len; 163 | return out; 164 | } 165 | 166 | /* 167 | * base64UrlEncode - Converts a standard Base64 encoded string 168 | * into Base64Url format. 169 | * 170 | * This replaces '+' with '-', '/' with '_', and removes '=' padding. 171 | */ 172 | char * 173 | base64UrlEncode (const char *base64) { 174 | char *url = NULL; 175 | size_t len = 0; 176 | if (!base64) 177 | return NULL; 178 | 179 | // Duplicate the input string to modify it in-place. 180 | url = strdup (base64); 181 | if (!url) 182 | return NULL; 183 | 184 | // Replace characters: '+' => '-', '/' => '_' 185 | for (char *p = url; *p; p++) { 186 | if (*p == '+') 187 | *p = '-'; 188 | else if (*p == '/') 189 | *p = '_'; 190 | } 191 | 192 | // Remove trailing '=' characters. 193 | len = strlen (url); 194 | while (len && url[len - 1] == '=') { 195 | url[len - 1] = '\0'; 196 | len--; 197 | } 198 | return url; 199 | } 200 | 201 | /* 202 | * base64UrlDecode - Converts a Base64Url encoded string into standard Base64 format. 203 | * 204 | * This replaces '-' with '+', '_' with '/', and adds the necessary '=' padding. 205 | * Caller is responsible for freeing the returned string. 206 | */ 207 | char * 208 | base64UrlDecode (const char *base64Url) { 209 | size_t len = 0, padding = 0, i = 0; 210 | char *padded = NULL, *base64 = NULL; 211 | 212 | if (!base64Url) 213 | return NULL; 214 | 215 | // Duplicate the input so we can modify it. 216 | base64 = strdup (base64Url); 217 | if (!base64) 218 | return NULL; 219 | 220 | // Replace '-' with '+' and '_' with '/' 221 | for (char *p = base64; *p; p++) { 222 | if (*p == '-') 223 | *p = '+'; 224 | else if (*p == '_') 225 | *p = '/'; 226 | } 227 | 228 | // Calculate the padding required (base64 length must be a multiple of 4) 229 | len = strlen (base64); 230 | padding = (4 - (len % 4)) % 4; 231 | padded = xmalloc (len + padding + 1); 232 | if (!padded) { 233 | free (base64); 234 | return NULL; 235 | } 236 | strcpy (padded, base64); 237 | for (i = 0; i < padding; i++) { 238 | padded[len + i] = '='; 239 | } 240 | padded[len + padding] = '\0'; 241 | free (base64); 242 | return padded; 243 | } 244 | -------------------------------------------------------------------------------- /src/base64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * _______ _______ __ __ 3 | * / ____/ | / / ___/____ _____/ /_____ / /_ 4 | * / / __ | | /| / /\__ \/ __ \/ ___/ //_/ _ \/ __/ 5 | * / /_/ / | |/ |/ /___/ / /_/ / /__/ ,< / __/ /_ 6 | * \____/ |__/|__//____/\____/\___/_/|_|\___/\__/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef BASE64_H_INCLUDED 31 | #define BASE64_H_INCLUDED 32 | 33 | #include 34 | 35 | char *base64_encode (const void *buf, size_t size); 36 | char *base64_decode (const char *data, size_t *out_len); 37 | char *base64UrlDecode (const char *base64Url); 38 | char *base64UrlEncode (const char *base64); 39 | 40 | #endif // for #ifndef BASE64_H 41 | -------------------------------------------------------------------------------- /src/bin2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is bin2c program, which allows you to convert binary file to 3 | * C language array, for use as embedded resource, for instance you can 4 | * embed graphics or audio file directly into your program. 5 | * This is public domain software, use it on your own risk. 6 | * Contact Serge Fukanchik at fuxx@mail.ru if you have any questions. 7 | * 8 | * Some modifications were made by Gwilym Kuiper (kuiper.gwilym@gmail.com) 9 | * I have decided not to change the licence. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef USE_BZ2 17 | #include 18 | #endif 19 | 20 | int 21 | main (int argc, char *argv[]) { 22 | char *buf; 23 | char *ident; 24 | int need_comma; 25 | long file_size_orig; 26 | size_t file_size, i; 27 | FILE *f_input, *f_output; 28 | 29 | #ifdef USE_BZ2 30 | int status; 31 | char *bz2_buf; 32 | unsigned int uncompressed_size, bz2_size; 33 | #endif 34 | 35 | if (argc < 4) { 36 | fprintf (stderr, "Usage: %s binary_file output_file array_name\n", argv[0]); 37 | return -1; 38 | } 39 | 40 | f_input = fopen (argv[1], "rb"); 41 | if (f_input == NULL) { 42 | fprintf (stderr, "%s: can't open %s for reading\n", argv[0], argv[1]); 43 | return -1; 44 | } 45 | // Get the file length 46 | fseek (f_input, 0, SEEK_END); 47 | file_size_orig = ftell (f_input); 48 | if (file_size_orig < 0) { 49 | fprintf (stderr, "%s: can't get size of file %s\n", argv[0], argv[1]); 50 | fclose (f_input); 51 | return -1; 52 | } 53 | file_size = (size_t) file_size_orig; 54 | fseek (f_input, 0, SEEK_SET); 55 | 56 | if ((buf = malloc (file_size)) == NULL) { 57 | fprintf (stderr, "Unable to malloc bin2c.c buffer\n"); 58 | fclose (f_input); 59 | return -1; 60 | } 61 | 62 | if (fread (buf, file_size, 1, f_input) != 1) { 63 | fprintf (stderr, "%s: can't read from %s\n", argv[0], argv[1]); 64 | free (buf); 65 | fclose (f_input); 66 | return -1; 67 | } 68 | 69 | if (fgetc (f_input) != EOF) { 70 | fprintf (stderr, "%s: can't read complete file %s\n", argv[0], argv[1]); 71 | free (buf); 72 | fclose (f_input); 73 | return -1; 74 | } 75 | 76 | if (ferror (f_input)) { 77 | fprintf (stderr, "%s: error while reading from %s\n", argv[0], argv[1]); 78 | free (buf); 79 | fclose (f_input); 80 | return -1; 81 | } 82 | 83 | fclose (f_input); 84 | 85 | #ifdef USE_BZ2 86 | // allocate for bz2. 87 | bz2_size = (file_size + file_size / 100 + 1) + 600; // as per the documentation 88 | 89 | if ((bz2_buf = malloc (bz2_size)) == NULL) { 90 | fprintf (stderr, "Unable to malloc bin2c.c buffer\n"); 91 | free (buf); 92 | return -1; 93 | } 94 | // compress the data 95 | status = BZ2_bzBuffToBuffCompress (bz2_buf, &bz2_size, buf, file_size, 9, 1, 0); 96 | if (status != BZ_OK) { 97 | fprintf (stderr, "Failed to compress data: error %i\n", status); 98 | free (buf); 99 | free (bz2_buf); 100 | return -1; 101 | } 102 | // and be very lazy 103 | free (buf); 104 | uncompressed_size = file_size; 105 | file_size = bz2_size; 106 | buf = bz2_buf; 107 | #endif 108 | 109 | f_output = fopen (argv[2], "w"); 110 | if (f_output == NULL) { 111 | fprintf (stderr, "%s: can't open %s for writing\n", argv[0], argv[1]); 112 | free (buf); 113 | return -1; 114 | } 115 | 116 | ident = argv[3]; 117 | need_comma = 0; 118 | 119 | fprintf (f_output, "const char %s[%lu] = {", ident, file_size); 120 | for (i = 0; i < file_size; ++i) { 121 | if (buf[i] == '\0') { 122 | fprintf (stderr, 123 | "%s: writing a null character terminates the content prematurely\n", argv[0]); 124 | fclose (f_output); 125 | free (buf); 126 | return -1; 127 | } 128 | if (need_comma) 129 | fprintf (f_output, ", "); 130 | else 131 | need_comma = 1; 132 | if ((i % 11) == 0) 133 | fprintf (f_output, "\n\t"); 134 | fprintf (f_output, "0x%.2x", buf[i] & 0xff); 135 | } 136 | fprintf (f_output, "\n};\n\n"); 137 | fprintf (f_output, "const int %s_length = %lu;\n", ident, file_size); 138 | 139 | #ifdef USE_BZ2 140 | fprintf (f_output, "const int %s_length_uncompressed = %u;\n", ident, uncompressed_size); 141 | #endif 142 | 143 | if (ferror (f_output)) { 144 | fprintf (stderr, "%s: error while writing to %s\n", argv[0], argv[2]); 145 | fclose (f_output); 146 | free (buf); 147 | return -1; 148 | } 149 | 150 | fclose (f_output); 151 | free (buf); 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /src/bitmap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * bitmap.c -- A quick bitmap implementation 3 | * ______ ___ 4 | * / ____/___ / | _____________ __________ 5 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 6 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 7 | * \____/\____/_/ |_\___/\___/\___/____/____/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "error.h" 36 | #include "xmalloc.h" 37 | 38 | #include "bitmap.h" 39 | 40 | /* 41 | * Returns the hamming weight (i.e. the number of bits set) in a word. 42 | * NOTE: This routine borrowed from Linux 2.4.9 . 43 | */ 44 | static uint32_t 45 | hweight (uint32_t w) { 46 | uint32_t res; 47 | 48 | res = (w & 0x55555555) + ((w >> 1) & 0x55555555); 49 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); 50 | res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); 51 | res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); 52 | res = (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); 53 | 54 | return res; 55 | } 56 | 57 | 58 | /* Returns the number of bytes required for bm->len bits. */ 59 | inline uint32_t 60 | bitmap_sizeof (uint32_t i) { 61 | return bitmap_word (i) * sizeof (word_t); 62 | } 63 | 64 | void 65 | free_bitmap (bitmap *bm) { 66 | free ((uint32_t *) bm->bmp); 67 | free (bm); 68 | } 69 | 70 | int 71 | bitmap_set_bit (word_t *words, uint32_t n) { 72 | words[WORD_OFFSET (n)] |= ((word_t) 1 << BIT_OFFSET (n)); 73 | return 0; 74 | } 75 | 76 | int 77 | bitmap_get_bit (word_t *words, uint32_t n) { 78 | word_t bit = words[WORD_OFFSET (n)] & ((word_t) 1 << BIT_OFFSET (n)); 79 | return bit != 0; 80 | } 81 | 82 | uint32_t 83 | bitmap_count_set (const bitmap *bm) { 84 | uint32_t i, n = 0, len = 0; 85 | 86 | if (!bm) 87 | return 0; 88 | 89 | len = bitmap_word (bm->len); 90 | for (i = 0; i < len; ++i) 91 | n += hweight (bm->bmp[i]); 92 | 93 | return n; 94 | } 95 | 96 | uint32_t 97 | bitmap_ffs (bitmap *bm) { 98 | uint32_t i, pos = 1, len = 0; 99 | uint32_t __bitset; 100 | 101 | if (!bm) 102 | return 0; 103 | 104 | len = bitmap_word (bm->len); 105 | for (i = 0; i < len; ++i) { 106 | __bitset = bm->bmp[i]; 107 | if ((pos = __builtin_ffs (__bitset))) 108 | break; 109 | } 110 | 111 | return (BITS_PER_WORD * i) + pos; 112 | } 113 | 114 | bitmap * 115 | bitmap_create (uint32_t bit) { 116 | bitmap *bm = xcalloc (1, sizeof (bitmap)); 117 | uint32_t bytes = bitmap_sizeof (bit); 118 | 119 | bm->bmp = xmalloc (bytes); 120 | memset (bm->bmp, 0, bytes); 121 | bm->len = bit; 122 | 123 | return bm; 124 | } 125 | 126 | int 127 | bitmap_realloc (bitmap *bm, uint32_t bit) { 128 | uint32_t *tmp = NULL; 129 | uint32_t oldlen = 0, newlen = 0; 130 | 131 | newlen = bitmap_sizeof (bit); 132 | oldlen = bitmap_sizeof (bm->len); 133 | if (newlen <= oldlen) 134 | return 1; 135 | 136 | tmp = realloc (bm->bmp, newlen); 137 | if ((tmp == NULL && newlen > 0) || bit < bm->len) 138 | FATAL ("Unable to realloc bitmap hash value %u %u", newlen, bm->len); 139 | 140 | LOG_DEBUG (("bit: %d, bm->len: %d, oldlen: %d, newlen: %d\n", bit, bm->len, oldlen, newlen)); 141 | memset (tmp + bitmap_word (bm->len), 0, (newlen - oldlen)); 142 | bm->len = bit; 143 | bm->bmp = tmp; 144 | 145 | return 0; 146 | } 147 | 148 | bitmap * 149 | bitmap_copy (const bitmap *bm) { 150 | bitmap *ret; 151 | 152 | if (!bm) 153 | return NULL; 154 | if (!(ret = bitmap_create (bm->len))) 155 | return NULL; 156 | 157 | memcpy (ret->bmp, bm->bmp, bitmap_sizeof (bm->len)); 158 | 159 | return ret; 160 | } 161 | 162 | int 163 | bitmap_key_exists (bitmap *bm, uint32_t bit) { 164 | if (bm->len < bit) 165 | bitmap_realloc (bm, bit); 166 | 167 | /* if bit set, then it's the same visitor */ 168 | if (bitmap_get_bit (bm->bmp, bit - 1)) 169 | return 1; 170 | bitmap_set_bit (bm->bmp, bit - 1); 171 | 172 | return 0; 173 | } 174 | -------------------------------------------------------------------------------- /src/bitmap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | 31 | #ifndef BITMAP_H_INCLUDED 32 | #define BITMAP_H_INCLUDED 33 | 34 | #include /* for CHAR_BIT */ 35 | 36 | typedef uint32_t word_t; // I want to change this, from uint32_t to uint64_t 37 | enum { BITS_PER_WORD = sizeof (word_t) * CHAR_BIT }; 38 | #define WORD_OFFSET(b) ((b) / BITS_PER_WORD) 39 | #define BIT_OFFSET(b) ((b) % BITS_PER_WORD) 40 | 41 | typedef struct bitmap_ { 42 | uint32_t *bmp; 43 | uint32_t len; /** Length of the bitmap, in bits */ 44 | } bitmap; 45 | 46 | static inline uint32_t 47 | bitmap_word (uint32_t i) { 48 | return (((i) + (BITS_PER_WORD) - 1) / (BITS_PER_WORD)); 49 | } 50 | 51 | #define BITMAP_FOREACH(bm, pos, code) { size_t __k; \ 52 | int __r; uint32_t __bitset, __t; \ 53 | uint32_t __len = bitmap_word(bm->len); \ 54 | for (__k = 0; __k < __len; ++__k) { \ 55 | __bitset = bm->bmp[__k]; \ 56 | while (__bitset != 0) { \ 57 | __t = __bitset & -__bitset; \ 58 | __r = __builtin_ctzl (__bitset); \ 59 | pos = (__k * 32) + __r + 1; \ 60 | code; \ 61 | __bitset ^= __t; \ 62 | } \ 63 | } } 64 | 65 | bitmap *bitmap_copy (const bitmap * bm); 66 | bitmap *bitmap_create (uint32_t bit); 67 | int bitmap_get_bit (word_t * words, uint32_t n); 68 | int bitmap_key_exists (bitmap * bm, uint32_t bit); 69 | int bitmap_realloc (bitmap * bm, uint32_t bit); 70 | int bitmap_set_bit (word_t * words, uint32_t n); 71 | uint32_t bitmap_count_set (const bitmap * bm); 72 | uint32_t bitmap_ffs (bitmap * bm); 73 | uint32_t bitmap_sizeof (uint32_t nbits); 74 | void free_bitmap (bitmap * bm); 75 | 76 | #endif // for #ifndef BITMAP_H 77 | -------------------------------------------------------------------------------- /src/browsers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef BROWSERS_H_INCLUDED 31 | #define BROWSERS_H_INCLUDED 32 | 33 | #define BROWSER_TYPE_LEN 24 34 | #define MAX_LINE_BROWSERS 128 35 | #define MAX_CUSTOM_BROWSERS 256 36 | 37 | /* Each Browser contains the number of hits and the Browser's type */ 38 | typedef struct GBrowser_ { 39 | char browser_type[BROWSER_TYPE_LEN]; 40 | int hits; 41 | } GBrowser; 42 | 43 | char *verify_browser (char *str, char *browser_type); 44 | int is_crawler (const char *agent); 45 | void free_browsers_hash (void); 46 | void parse_browsers_file (void); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/color.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef COLOR_H_INCLUDED 31 | #define COLOR_H_INCLUDED 32 | 33 | #define COLOR_STR_LEN 9 34 | 35 | /* Color Items/Fields */ 36 | typedef enum CSTM_COLORS { 37 | COLOR_NORMAL, 38 | COLOR_MTRC_HITS, 39 | COLOR_MTRC_VISITORS, 40 | COLOR_MTRC_DATA, 41 | COLOR_MTRC_BW, 42 | COLOR_MTRC_AVGTS, 43 | COLOR_MTRC_CUMTS, 44 | COLOR_MTRC_MAXTS, 45 | COLOR_MTRC_PROT, 46 | COLOR_MTRC_MTHD, 47 | COLOR_MTRC_HITS_PERC, 48 | COLOR_MTRC_HITS_PERC_MAX, 49 | COLOR_MTRC_VISITORS_PERC, 50 | COLOR_MTRC_VISITORS_PERC_MAX, 51 | COLOR_PANEL_COLS, 52 | COLOR_BARS, 53 | COLOR_ERROR, 54 | COLOR_SELECTED, 55 | COLOR_PANEL_ACTIVE, 56 | COLOR_PANEL_HEADER, 57 | COLOR_PANEL_DESC, 58 | COLOR_OVERALL_LBLS, 59 | COLOR_OVERALL_VALS, 60 | COLOR_OVERALL_PATH, 61 | COLOR_ACTIVE_LABEL, 62 | COLOR_BG, 63 | COLOR_DEFAULT, 64 | COLOR_PROGRESS, 65 | } GColorItem; 66 | 67 | /* Default Color Schemes */ 68 | typedef enum SCHEMES { 69 | NO_COLOR, 70 | MONOCHROME, 71 | STD_GREEN, 72 | MONOKAI, 73 | } GSchemes; 74 | 75 | #include "commons.h" 76 | 77 | /* Each color properties */ 78 | typedef struct GColorPair_ { 79 | short idx; /* color pair index identifier */ 80 | short fg; /* foreground color */ 81 | short bg; /* background color */ 82 | } GColorPair; 83 | 84 | /* Color */ 85 | typedef struct GColors_ { 86 | GColorItem item; /* screen item */ 87 | GColorPair *pair; /* color pair */ 88 | int attr; /* color attributes, e.g., bold */ 89 | short module; /* panel */ 90 | } GColors; 91 | 92 | GColors *color_default (void); 93 | GColors *color_error (void); 94 | GColors *color_overall_lbls (void); 95 | GColors *color_overall_path (void); 96 | GColors *color_overall_vals (void); 97 | GColors *color_panel_active (void); 98 | GColors *color_panel_desc (void); 99 | GColors *color_panel_header (void); 100 | GColors *color_progress (void); 101 | GColors *color_selected (void); 102 | GColors *get_color_by_item_module (GColorItem item, GModule module); 103 | GColors *get_color (GColorItem item); 104 | GColors *get_color_normal (void); 105 | void free_color_lists (void); 106 | void set_colors (int force); 107 | void set_normal_color (void); 108 | 109 | #endif // for #ifndef COLOR_H 110 | -------------------------------------------------------------------------------- /src/commons.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef COMMONS_H_INCLUDED 35 | #define COMMONS_H_INCLUDED 36 | 37 | #include 38 | #include 39 | #include "gslist.h" 40 | 41 | /* Remove the __attribute__ stuff when the compiler is not GCC. */ 42 | #if !__GNUC__ 43 | #define __attribute__(x) /**/ 44 | #endif 45 | #define GO_UNUSED __attribute__((unused)) 46 | #define GO_VERSION "1.9.4" 47 | #define GO_WEBSITE "https://goaccess.io/" 48 | extern struct tm now_tm; 49 | 50 | /* common char array buffer size */ 51 | #define INIT_BUF_SIZE 1024 52 | 53 | /* total number of modules */ 54 | #ifdef HAVE_GEOLOCATION 55 | #define TOTAL_MODULES 19 56 | #else 57 | #define TOTAL_MODULES 17 58 | #endif 59 | 60 | /* maximum number of items within a panel */ 61 | #define MAX_CHOICES 366 62 | /* real-time */ 63 | #define MAX_CHOICES_RT 50 64 | /* max default items when date-spec = min */ 65 | #define MAX_CHOICES_MINUTE 1440 /* 24hrs */ 66 | 67 | /* date and time length - e.g., 2016/12/12 12:12:12 -0600 */ 68 | #define DATE_TIME 25 + 1 69 | /* date length - e.g., 2016/12/12 */ 70 | #define DATE_LEN 10 + 1 71 | /* date length - e.g., 12:12:12 */ 72 | #define TIME_LEN 8 + 1 73 | /* hour + ':' + min length - e.g., 12:12 */ 74 | #define HRMI_LEN 4 + 1 + 1 75 | 76 | #define YR_FMT "%Y" 77 | #define MO_FMT "%M" 78 | #define DT_FMT "%d" 79 | 80 | /* maximum protocol string length */ 81 | #define REQ_PROTO_LEN 9 82 | 83 | #define IGNORE_LEVEL_PANEL 1 84 | #define IGNORE_LEVEL_REQ 2 85 | 86 | /* Type of IP */ 87 | typedef enum { 88 | TYPE_IPINV, 89 | TYPE_IPV4, 90 | TYPE_IPV6 91 | } GTypeIP; 92 | 93 | /* Type of Modules */ 94 | typedef enum MODULES { 95 | VISITORS, 96 | REQUESTS, 97 | REQUESTS_STATIC, 98 | NOT_FOUND, 99 | HOSTS, 100 | OS, 101 | BROWSERS, 102 | VISIT_TIMES, 103 | VIRTUAL_HOSTS, 104 | REFERRERS, 105 | REFERRING_SITES, 106 | KEYPHRASES, 107 | STATUS_CODES, 108 | REMOTE_USER, 109 | CACHE_STATUS, 110 | #ifdef HAVE_GEOLOCATION 111 | GEO_LOCATION, 112 | ASN, 113 | #endif 114 | MIME_TYPE, 115 | TLS_TYPE, 116 | } GModule; 117 | 118 | /* Total number of storage metrics (GSMetric) */ 119 | #define GSMTRC_TOTAL 19 120 | 121 | /* Enumerated Storage Metrics */ 122 | typedef enum GSMetric_ { 123 | MTRC_KEYMAP, 124 | MTRC_ROOTMAP, 125 | MTRC_DATAMAP, 126 | MTRC_UNIQMAP, 127 | MTRC_ROOT, 128 | MTRC_HITS, 129 | MTRC_VISITORS, 130 | MTRC_BW, 131 | MTRC_CUMTS, 132 | MTRC_MAXTS, 133 | MTRC_METHODS, 134 | MTRC_PROTOCOLS, 135 | MTRC_AGENTS, 136 | MTRC_METADATA, 137 | MTRC_UNIQUE_KEYS, 138 | MTRC_AGENT_KEYS, 139 | MTRC_AGENT_VALS, 140 | MTRC_CNT_VALID, 141 | MTRC_CNT_BW, 142 | } GSMetric; 143 | 144 | /* Metric totals. These are metrics that have a percent value and are 145 | * calculated values. */ 146 | typedef struct GPercTotals_ { 147 | uint32_t hits; /* total valid hits */ 148 | uint32_t visitors; /* total visitors */ 149 | uint64_t bw; /* total bandwidth */ 150 | } GPercTotals; 151 | 152 | /* Metrics within GHolder or GDashData */ 153 | typedef struct GMetrics { 154 | /* metric id can be used to identify 155 | * a specific data field */ 156 | uint8_t id; 157 | char *data; 158 | char *method; 159 | char *protocol; 160 | 161 | float hits_perc; 162 | float visitors_perc; 163 | float bw_perc; 164 | 165 | uint64_t hits; 166 | uint64_t visitors; 167 | 168 | /* holder has a numeric value, while 169 | * dashboard has a displayable string value */ 170 | union { 171 | char *sbw; 172 | uint64_t nbw; 173 | } bw; 174 | 175 | /* holder has a numeric value, while 176 | * dashboard has a displayable string value */ 177 | union { 178 | char *sts; 179 | uint64_t nts; 180 | } avgts; 181 | 182 | /* holder has a numeric value, while 183 | * dashboard has a displayable string value */ 184 | union { 185 | char *sts; 186 | uint64_t nts; 187 | } cumts; 188 | 189 | /* holder has a numeric value, while 190 | * dashboard has a displayable string value */ 191 | union { 192 | char *sts; 193 | uint64_t nts; 194 | } maxts; 195 | } GMetrics; 196 | 197 | /* Holder sub item */ 198 | typedef struct GSubItem_ { 199 | GModule module; 200 | GMetrics *metrics; 201 | struct GSubItem_ *prev; 202 | struct GSubItem_ *next; 203 | } GSubItem; 204 | 205 | /* Double linked-list of sub items */ 206 | typedef struct GSubList_ { 207 | int size; 208 | struct GSubItem_ *head; 209 | struct GSubItem_ *tail; 210 | } GSubList; 211 | 212 | /* Holder item */ 213 | typedef struct GHolderItem_ { 214 | GSubList *sub_list; 215 | GMetrics *metrics; 216 | } GHolderItem; 217 | 218 | /* Holder of GRawData */ 219 | typedef struct GHolder_ { 220 | GHolderItem *items; /* holder items */ 221 | GModule module; /* current module */ 222 | int idx; /* holder index */ 223 | int holder_size; /* number of allocated items */ 224 | uint32_t ht_size; /* size of the hash table/store */ 225 | int sub_items_size; /* number of sub items */ 226 | } GHolder; 227 | 228 | /* Enum-to-string */ 229 | typedef struct GEnum_ { 230 | const char *str; 231 | int idx; 232 | } GEnum; 233 | 234 | /* A metric can contain a root/data/uniq node id */ 235 | typedef struct GDataMap_ { 236 | int data; 237 | int root; 238 | } GDataMap; 239 | 240 | typedef struct GAgentItem_ { 241 | char *agent; 242 | } GAgentItem; 243 | 244 | typedef struct GAgents_ { 245 | int size; 246 | int idx; 247 | struct GAgentItem_ *items; 248 | } GAgents; 249 | 250 | #define FOREACH_MODULE(item, array) \ 251 | for (; (item < ARRAY_SIZE(array)) && array[item] != -1; ++item) 252 | 253 | /* Processing time */ 254 | extern time_t end_proc; 255 | extern time_t timestamp; 256 | extern time_t start_proc; 257 | 258 | /* list of available modules/panels */ 259 | extern int module_list[TOTAL_MODULES]; 260 | 261 | /* *INDENT-OFF* */ 262 | GAgents *new_gagents (uint32_t size); 263 | void free_agents_array (GAgents *agents); 264 | 265 | const char *enum2str (const GEnum map[], int len, int idx); 266 | const char *get_module_str (GModule module); 267 | float get_percentage (unsigned long long total, unsigned long long hit); 268 | int get_max_choices (void); 269 | int get_module_enum (const char *str); 270 | int has_timestamp (const char *fmt); 271 | int str2enum (const GEnum map[], int len, const char *str); 272 | 273 | int enable_panel (GModule mod); 274 | int get_module_index (int module); 275 | int get_next_module (GModule module); 276 | int get_prev_module (GModule module); 277 | int ignore_panel (GModule mod); 278 | int init_modules (void); 279 | int remove_module(GModule module); 280 | uint32_t get_num_modules (void); 281 | void verify_panels (void); 282 | 283 | char *get_log_source_str (int max_len); 284 | intmax_t get_log_sizes (void); 285 | 286 | void display_default_config_file (void); 287 | void display_storage (void); 288 | void display_version (void); 289 | /* *INDENT-ON* */ 290 | 291 | #endif 292 | -------------------------------------------------------------------------------- /src/csv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef CSV_H_INCLUDED 35 | #define CSV_H_INCLUDED 36 | 37 | #include 38 | #include "parser.h" 39 | #include "settings.h" 40 | 41 | void output_csv (GHolder * holder, const char *filename); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | /** 2 | * error.c -- error handling 3 | * ______ ___ 4 | * / ____/___ / | _____________ __________ 5 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 6 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 7 | * \____/\____/_/ |_\___/\___/\___/____/____/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #if HAVE_CONFIG_H 32 | #include 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #if defined(__GLIBC__) 40 | #include 41 | #endif 42 | #include 43 | #include 44 | #include 45 | 46 | #include "error.h" 47 | #include "labels.h" 48 | #include "parser.h" 49 | 50 | static FILE *access_log; 51 | static FILE *log_file; 52 | static FILE *log_invalid; 53 | static FILE *log_unknowns; 54 | static Logs *log_data; 55 | static struct sigaction old_sigsegv_handler; 56 | 57 | /* Open a debug file whose name is specified in the given path. */ 58 | void 59 | dbg_log_open (const char *path) { 60 | if (path != NULL) { 61 | log_file = fopen (path, "w"); 62 | if (log_file == NULL) 63 | return; 64 | } 65 | } 66 | 67 | /* Close the debug file. */ 68 | void 69 | dbg_log_close (void) { 70 | if (log_file != NULL) 71 | fclose (log_file); 72 | } 73 | 74 | /* Open the invalid requests log file whose name is specified in the 75 | * given path. */ 76 | void 77 | invalid_log_open (const char *path) { 78 | if (path != NULL) { 79 | log_invalid = fopen (path, "w"); 80 | if (log_invalid == NULL) 81 | return; 82 | } 83 | } 84 | 85 | /* Close the invalid requests log file. */ 86 | void 87 | invalid_log_close (void) { 88 | if (log_invalid != NULL) 89 | fclose (log_invalid); 90 | } 91 | 92 | /* Open the unknowns log file whose name is specified in the 93 | * given path. */ 94 | void 95 | unknowns_log_open (const char *path) { 96 | if (path != NULL) { 97 | log_unknowns = fopen (path, "w"); 98 | if (log_unknowns == NULL) 99 | return; 100 | } 101 | } 102 | 103 | /* Close the unknowns log file. */ 104 | void 105 | unknowns_log_close (void) { 106 | if (log_unknowns != NULL) 107 | fclose (log_unknowns); 108 | } 109 | 110 | /* Set current overall parsed log data. */ 111 | void 112 | set_signal_data (void *p) { 113 | log_data = p; 114 | } 115 | 116 | /* Open the WebSocket access log file whose name is specified in the 117 | * given path. */ 118 | int 119 | access_log_open (const char *path) { 120 | if (path == NULL) 121 | return 0; 122 | 123 | access_log = fopen (path, "a"); 124 | 125 | if (access_log == NULL) 126 | return 1; 127 | 128 | return 0; 129 | } 130 | 131 | /* Close the WebSocket access log file. */ 132 | void 133 | access_log_close (void) { 134 | if (access_log != NULL) 135 | fclose (access_log); 136 | } 137 | 138 | /* Set up sigsegv handler. */ 139 | void 140 | setup_sigsegv_handler (void) { 141 | struct sigaction act; 142 | 143 | sigemptyset (&act.sa_mask); 144 | act.sa_flags = (int) SA_RESETHAND; 145 | act.sa_handler = sigsegv_handler; 146 | 147 | sigaction (SIGSEGV, &act, &old_sigsegv_handler); 148 | } 149 | 150 | static void 151 | dump_struct_data (FILE *fp, GLog *glog, int pid) { 152 | fprintf (fp, "==%d== FILE: %s\n", pid, glog->props.filename); 153 | fprintf (fp, "==%d== Line number: %" PRIu64 "\n", pid, glog->processed); 154 | fprintf (fp, "==%d== Invalid data: %" PRIu64 "\n", pid, glog->invalid); 155 | fprintf (fp, "==%d== Piping: %d\n", pid, glog->piping); 156 | fprintf (fp, "==%d==\n", pid); 157 | } 158 | 159 | /* Dump to the standard output the values of the overall parsed log 160 | * data. */ 161 | static void 162 | dump_struct (FILE *fp) { 163 | int pid = getpid (), i; 164 | 165 | if (!log_data) 166 | return; 167 | 168 | fprintf (fp, "==%d== VALUES AT CRASH POINT\n", pid); 169 | fprintf (fp, "==%d==\n", pid); 170 | 171 | for (i = 0; i < log_data->size; ++i) 172 | dump_struct_data (fp, &log_data->glog[i], pid); 173 | 174 | } 175 | 176 | /* Custom SIGSEGV handler. */ 177 | void 178 | sigsegv_handler (int sig) { 179 | FILE *fp = stderr; 180 | int pid = getpid (); 181 | 182 | #if defined(__GLIBC__) 183 | char **messages; 184 | size_t size, i; 185 | void *trace_stack[TRACE_SIZE]; 186 | #endif 187 | 188 | (void) endwin (); 189 | fprintf (fp, "\n"); 190 | fprintf (fp, "==%d== GoAccess %s crashed by Sig %d\n", pid, GO_VERSION, sig); 191 | fprintf (fp, "==%d==\n", pid); 192 | 193 | dump_struct (fp); 194 | 195 | #if defined(__GLIBC__) 196 | size = backtrace (trace_stack, TRACE_SIZE); 197 | messages = backtrace_symbols (trace_stack, size); 198 | 199 | fprintf (fp, "==%d== STACK TRACE:\n", pid); 200 | fprintf (fp, "==%d==\n", pid); 201 | 202 | for (i = 0; i < size; i++) 203 | fprintf (fp, "==%d== %zu %s\n", pid, i, messages[i]); 204 | #endif 205 | 206 | fprintf (fp, "==%d==\n", pid); 207 | fprintf (fp, "==%d== %s:\n", pid, ERR_PLEASE_REPORT); 208 | fprintf (fp, "==%d== https://github.com/allinurl/goaccess/issues\n\n", pid); 209 | fflush (fp); 210 | 211 | /* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */ 212 | sigaction (SIGSEGV, &old_sigsegv_handler, NULL); 213 | } 214 | 215 | /* Write formatted debug log data to the logfile. */ 216 | void 217 | dbg_fprintf (const char *fmt, ...) { 218 | va_list args; 219 | 220 | if (!log_file) 221 | return; 222 | 223 | va_start (args, fmt); 224 | vfprintf (log_file, fmt, args); 225 | fflush (log_file); 226 | va_end (args); 227 | } 228 | 229 | /* Write formatted invalid requests log data to the logfile. */ 230 | void 231 | invalid_fprintf (const char *fmt, ...) { 232 | va_list args; 233 | 234 | if (!log_invalid) 235 | return; 236 | 237 | va_start (args, fmt); 238 | vfprintf (log_invalid, fmt, args); 239 | fflush (log_invalid); 240 | va_end (args); 241 | } 242 | 243 | /* Write formatted unknown browsers/OSs log data to the logfile. */ 244 | void 245 | unknowns_fprintf (const char *fmt, ...) { 246 | va_list args; 247 | 248 | if (!log_unknowns) 249 | return; 250 | 251 | va_start (args, fmt); 252 | vfprintf (log_unknowns, fmt, args); 253 | fflush (log_unknowns); 254 | va_end (args); 255 | } 256 | 257 | /* Debug output */ 258 | void 259 | dbg_printf (const char *fmt, ...) { 260 | va_list args; 261 | va_start (args, fmt); 262 | vfprintf (stderr, fmt, args); 263 | va_end (args); 264 | } 265 | 266 | /* Write formatted access log data to the logfile. */ 267 | void 268 | access_fprintf (const char *fmt, ...) { 269 | va_list args; 270 | 271 | if (!access_log) 272 | return; 273 | 274 | va_start (args, fmt); 275 | vfprintf (access_log, fmt, args); 276 | fflush (access_log); 277 | va_end (args); 278 | } 279 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef ERROR_H_INCLUDED 31 | #define ERROR_H_INCLUDED 32 | 33 | #ifndef COMMONS 34 | #include "commons.h" 35 | #endif 36 | 37 | #ifdef HAVE_NCURSESW_NCURSES_H 38 | #include 39 | #elif HAVE_NCURSES_NCURSES_H 40 | #include 41 | #elif HAVE_NCURSES_H 42 | #include 43 | #elif HAVE_CURSES_H 44 | #include 45 | #endif 46 | 47 | #include 48 | #include "settings.h" 49 | 50 | #define TRACE_SIZE 128 51 | 52 | #define FATAL(fmt, ...) do { \ 53 | (void) endwin (); \ 54 | fprintf (stderr, "\nGoAccess - version %s - %s %s\n", GO_VERSION, __DATE__, __TIME__); \ 55 | fprintf (stderr, "Config file: %s\n", conf.iconfigfile ?: NO_CONFIG_FILE); \ 56 | fprintf (stderr, "\nFatal error has occurred"); \ 57 | fprintf (stderr, "\nError occurred at: %s - %s - %d\n", __FILE__, __FUNCTION__, __LINE__); \ 58 | fprintf (stderr, fmt, ##__VA_ARGS__); \ 59 | fprintf (stderr, "\n\n"); \ 60 | LOG_DEBUG ((fmt, ##__VA_ARGS__)); \ 61 | exit(EXIT_FAILURE); \ 62 | } while (0) 63 | 64 | #ifdef DEBUG 65 | #define DEBUG_TEST 1 66 | #else 67 | #define DEBUG_TEST 0 68 | #endif 69 | 70 | /* access requests log */ 71 | #define ACCESS_LOG(x, ...) do { access_fprintf x; } while (0) 72 | /* debug log */ 73 | #define LOG_DEBUG(x, ...) do { dbg_fprintf x; } while (0) 74 | /* invalid requests log */ 75 | #define LOG_INVALID(x, ...) do { invalid_fprintf x; } while (0) 76 | /* unknown browser log */ 77 | #define LOG_UNKNOWNS(x, ...) do { unknowns_fprintf x; } while (0) 78 | /* log debug wrapper */ 79 | #define LOG(x) do { if (DEBUG_TEST) dbg_printf x; } while (0) 80 | 81 | int access_log_open (const char *path); 82 | void access_fprintf (const char *fmt, ...) __attribute__((format (printf, 1, 2))); 83 | void access_log_close (void); 84 | void dbg_fprintf (const char *fmt, ...) __attribute__((format (printf, 1, 2))); 85 | void dbg_log_close (void); 86 | void dbg_log_open (const char *file); 87 | void dbg_printf (const char *fmt, ...) __attribute__((format (printf, 1, 2))); 88 | void invalid_fprintf (const char *fmt, ...) __attribute__((format (printf, 1, 2))); 89 | void unknowns_fprintf (const char *fmt, ...) __attribute__((format (printf, 1, 2))); 90 | void invalid_log_close (void); 91 | void invalid_log_open (const char *path); 92 | void set_signal_data (void *p); 93 | void setup_sigsegv_handler (void); 94 | void sigsegv_handler (int sig); 95 | void unknowns_log_close (void); 96 | void unknowns_log_open (const char *path); 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /src/gdashboard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef GDASHBOARD_H_INCLUDED 35 | #define GDASHBOARD_H_INCLUDED 36 | 37 | #include 38 | 39 | #include "ui.h" 40 | 41 | #define DASH_HEAD_POS 0 /* position of header line */ 42 | #define DASH_EMPTY_POS 1 /* empty line position */ 43 | #define DASH_COLS_POS 2 /* position of column names */ 44 | #define DASH_DASHES_POS 3 /* position of dashes under column names */ 45 | #define DASH_DATA_POS 4 /* data line position */ 46 | 47 | #define DASH_NON_DATA 5 /* number of rows without data stats */ 48 | #define DASH_COL_ROWS 2 /* number of rows for column values + dashed lines */ 49 | 50 | #define DASH_COLLAPSED 12 /* number of rows per panel (collapsed) */ 51 | #define DASH_EXPANDED 32 /* number of rows per panel (expanded) */ 52 | 53 | #define DASH_INIT_X 1 /* start position (x-axis) */ 54 | 55 | #define DASH_BW_LEN 11 /* max bandwidth string length, e.g., 151.69 MiB */ 56 | #define DASH_SRV_TM_LEN 9 /* max time served length, e.g., 483.00 us */ 57 | #define DASH_SPACE 1 /* space between columns (metrics) */ 58 | 59 | /* Common render data line fields */ 60 | typedef struct GDashRender_ { 61 | WINDOW *win; 62 | int y; 63 | int w; 64 | int idx; 65 | int sel; 66 | } GDashRender; 67 | 68 | /* Dashboard panel item */ 69 | typedef struct GDashData_ { 70 | GMetrics *metrics; 71 | short is_subitem; 72 | } GDashData; 73 | 74 | /* Dashboard panel meta data */ 75 | typedef struct GDashMeta_ { 76 | uint64_t max_hits; /* maximum value on the hits column */ 77 | uint64_t max_visitors; /* maximum value on the visitors column */ 78 | 79 | /* determine the maximum metric's length of these metrics */ 80 | /* for instance, 1022 is the max value for the hits column and its length = 4 */ 81 | int hits_len; 82 | int hits_perc_len; 83 | int visitors_len; 84 | int visitors_perc_len; 85 | int bw_len; 86 | int avgts_len; 87 | int cumts_len; 88 | int maxts_len; 89 | int method_len; 90 | int protocol_len; 91 | int data_len; 92 | } GDashMeta; 93 | 94 | /* Dashboard panel */ 95 | typedef struct GDashModule_ { 96 | GDashData *data; /* data metrics */ 97 | GModule module; /* module */ 98 | GDashMeta meta; /* meta data */ 99 | 100 | const char *head; /* panel header */ 101 | const char *desc; /* panel description */ 102 | 103 | int alloc_data; /* number of data items allocated. */ 104 | /* e.g., MAX_CHOICES or holder size */ 105 | int dash_size; /* dashboard size */ 106 | int holder_size; /* hash table size */ 107 | int ht_size; /* hash table size */ 108 | int idx_data; /* idx data */ 109 | 110 | unsigned short pos_y; /* dashboard current Y position */ 111 | } GDashModule; 112 | 113 | /* Dashboard */ 114 | typedef struct GDash_ { 115 | int total_alloc; /* number of allocated dashboard lines */ 116 | GDashModule module[TOTAL_MODULES]; 117 | } GDash; 118 | 119 | /* Function Prototypes */ 120 | GDashData *new_gdata (uint32_t size); 121 | GDash *new_gdash (void); 122 | int get_num_collapsed_data_rows (void); 123 | int get_num_expanded_data_rows (void); 124 | int perform_next_find (GHolder * h, GScroll * scroll); 125 | int render_find_dialog (WINDOW * main_win, GScroll * scroll); 126 | int set_module_from_mouse_event (GScroll * scroll, GDash * dash, int y); 127 | uint32_t get_ht_size_by_module (GModule module); 128 | void display_content (WINDOW * win, GDash * dash, GScroll * scroll); 129 | void free_dashboard (GDash * dash); 130 | void load_data_to_dash (GHolder * h, GDash * dash, GModule module, GScroll * scroll); 131 | void reset_find (void); 132 | void reset_scroll_offsets (GScroll * scroll); 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /src/gdns.c: -------------------------------------------------------------------------------- 1 | /** 2 | * gdns.c -- hosts resolver 3 | * ______ ___ 4 | * / ____/___ / | _____________ __________ 5 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 6 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 7 | * \____/\____/_/ |_\___/\___/\___/____/____/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #define _MULTI_THREADED 32 | #ifdef __FreeBSD__ 33 | #include 34 | #endif 35 | 36 | #if HAVE_CONFIG_H 37 | #include 38 | #endif 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #include "gdns.h" 52 | 53 | #include "error.h" 54 | #include "gkhash.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 the queue. */ 63 | void 64 | gqueue_init (GDnsQueue *q, int capacity) { 65 | q->head = 0; 66 | q->tail = -1; 67 | q->size = 0; 68 | q->capacity = capacity; 69 | } 70 | 71 | /* Get the current size of queue. 72 | * 73 | * Returns the size of the queue. */ 74 | int 75 | gqueue_size (GDnsQueue *q) { 76 | return q->size; 77 | } 78 | 79 | /* Determine if the queue is empty. 80 | * 81 | * Returns true if empty, otherwise false. */ 82 | int 83 | gqueue_empty (GDnsQueue *q) { 84 | return q->size == 0; 85 | } 86 | 87 | /* Determine if the queue is full. 88 | * 89 | * Returns true if full, otherwise false. */ 90 | int 91 | gqueue_full (GDnsQueue *q) { 92 | return q->size == q->capacity; 93 | } 94 | 95 | /* Free the queue. */ 96 | void 97 | gqueue_destroy (GDnsQueue *q) { 98 | free (q); 99 | } 100 | 101 | /* Add at the end of the queue a string item. 102 | * 103 | * If the queue is full, -1 is returned. 104 | * If added to the queue, 0 is returned. */ 105 | int 106 | gqueue_enqueue (GDnsQueue *q, const char *item) { 107 | if (gqueue_full (q)) 108 | return -1; 109 | 110 | q->tail = (q->tail + 1) % q->capacity; 111 | strncpy (q->buffer[q->tail], item, sizeof (q->buffer[q->tail])); 112 | q->buffer[q->tail][sizeof (q->buffer[q->tail]) - 1] = '\0'; 113 | q->size++; 114 | return 0; 115 | } 116 | 117 | /* Find a string item in the queue. 118 | * 119 | * If the queue is empty, or the item is not in the queue, 0 is returned. 120 | * If found, 1 is returned. */ 121 | int 122 | gqueue_find (GDnsQueue *q, const char *item) { 123 | int i; 124 | if (gqueue_empty (q)) 125 | return 0; 126 | 127 | for (i = 0; i < q->size; i++) { 128 | if (strcmp (item, q->buffer[i]) == 0) 129 | return 1; 130 | } 131 | return 0; 132 | } 133 | 134 | /* Remove a string item from the head of the queue. 135 | * 136 | * If the queue is empty, NULL is returned. 137 | * If removed, the string item is returned. */ 138 | char * 139 | gqueue_dequeue (GDnsQueue *q) { 140 | char *item; 141 | if (gqueue_empty (q)) 142 | return NULL; 143 | 144 | item = q->buffer[q->head]; 145 | q->head = (q->head + 1) % q->capacity; 146 | q->size--; 147 | return item; 148 | } 149 | 150 | /* Get the corresponding hostname given an IP address. 151 | * 152 | * On error, a string error message is returned. 153 | * On success, a malloc'd hostname is returned. */ 154 | static char * 155 | reverse_host (const struct sockaddr *a, socklen_t length) { 156 | char h[H_SIZE] = { 0 }; 157 | int flags, st; 158 | 159 | flags = NI_NAMEREQD; 160 | st = getnameinfo (a, length, h, H_SIZE, NULL, 0, flags); 161 | if (!st) { 162 | /* BSD returns \0 while Linux . on solve lookups */ 163 | if (*h == '\0') 164 | return alloc_string ("."); 165 | return alloc_string (h); 166 | } 167 | return alloc_string (gai_strerror (st)); 168 | } 169 | 170 | /* Determine if IPv4 or IPv6 and resolve. 171 | * 172 | * On error, NULL is returned. 173 | * On success, a malloc'd hostname is returned. */ 174 | char * 175 | reverse_ip (char *str) { 176 | union { 177 | struct sockaddr addr; 178 | struct sockaddr_in6 addr6; 179 | struct sockaddr_in addr4; 180 | } a; 181 | 182 | if (str == NULL || *str == '\0') 183 | return NULL; 184 | 185 | memset (&a, 0, sizeof (a)); 186 | if (1 == inet_pton (AF_INET, str, &a.addr4.sin_addr)) { 187 | a.addr4.sin_family = AF_INET; 188 | return reverse_host (&a.addr, sizeof (a.addr4)); 189 | } else if (1 == inet_pton (AF_INET6, str, &a.addr6.sin6_addr)) { 190 | a.addr6.sin6_family = AF_INET6; 191 | return reverse_host (&a.addr, sizeof (a.addr6)); 192 | } 193 | return NULL; 194 | } 195 | 196 | /* Producer - Resolve an IP address and add it to the queue. */ 197 | void 198 | dns_resolver (char *addr) { 199 | pthread_mutex_lock (&gdns_thread.mutex); 200 | /* queue is not full and the IP address is not in the queue */ 201 | if (!gqueue_full (gdns_queue) && !gqueue_find (gdns_queue, addr)) { 202 | /* add the IP to the queue */ 203 | gqueue_enqueue (gdns_queue, addr); 204 | pthread_cond_broadcast (&gdns_thread.not_empty); 205 | } 206 | pthread_mutex_unlock (&gdns_thread.mutex); 207 | } 208 | 209 | /* Consumer - Once an IP has been resolved, add it to dwithe hostnames 210 | * hash structure. */ 211 | static void 212 | dns_worker (void GO_UNUSED (*ptr_data)) { 213 | char *ip = NULL, *host = NULL; 214 | 215 | while (1) { 216 | pthread_mutex_lock (&gdns_thread.mutex); 217 | /* wait until an item has been added to the queue */ 218 | while (gqueue_empty (gdns_queue)) 219 | pthread_cond_wait (&gdns_thread.not_empty, &gdns_thread.mutex); 220 | 221 | ip = gqueue_dequeue (gdns_queue); 222 | 223 | pthread_mutex_unlock (&gdns_thread.mutex); 224 | host = reverse_ip (ip); 225 | pthread_mutex_lock (&gdns_thread.mutex); 226 | 227 | if (!active_gdns) { 228 | pthread_mutex_unlock (&gdns_thread.mutex); 229 | free (host); 230 | return; 231 | } 232 | 233 | /* insert the corresponding IP -> hostname map */ 234 | if (host != NULL && active_gdns) { 235 | ht_insert_hostname (ip, host); 236 | free (host); 237 | } 238 | 239 | pthread_cond_signal (&gdns_thread.not_full); 240 | pthread_mutex_unlock (&gdns_thread.mutex); 241 | } 242 | } 243 | 244 | /* Initialize queue and dns thread */ 245 | void 246 | gdns_init (void) { 247 | gdns_queue = xmalloc (sizeof (GDnsQueue)); 248 | gqueue_init (gdns_queue, QUEUE_SIZE); 249 | 250 | if (pthread_cond_init (&(gdns_thread.not_empty), NULL)) 251 | FATAL ("Failed init thread condition"); 252 | 253 | if (pthread_cond_init (&(gdns_thread.not_full), NULL)) 254 | FATAL ("Failed init thread condition"); 255 | 256 | if (pthread_mutex_init (&(gdns_thread.mutex), NULL)) 257 | FATAL ("Failed init thread mutex"); 258 | } 259 | 260 | /* Destroy (free) queue */ 261 | void 262 | gdns_free_queue (void) { 263 | gqueue_destroy (gdns_queue); 264 | } 265 | 266 | /* Create a DNS thread and make it active */ 267 | void 268 | gdns_thread_create (void) { 269 | int th; 270 | 271 | active_gdns = 1; 272 | th = pthread_create (&(gdns_thread.thread), NULL, (void *) &dns_worker, NULL); 273 | if (th) 274 | FATAL ("Return code from pthread_create(): %d", th); 275 | pthread_detach (gdns_thread.thread); 276 | } 277 | -------------------------------------------------------------------------------- /src/gdns.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef GDNS_H_INCLUDED 31 | #define GDNS_H_INCLUDED 32 | 33 | #define H_SIZE 1025 34 | #define QUEUE_SIZE 400 35 | 36 | typedef struct GDnsThread_ { 37 | pthread_cond_t not_empty; /* not empty queue condition */ 38 | pthread_cond_t not_full; /* not full queue condition */ 39 | pthread_mutex_t mutex; 40 | pthread_t thread; 41 | } GDnsThread; 42 | 43 | typedef struct GDnsQueue_ { 44 | int head; /* index to head of queue */ 45 | int tail; /* index to tail of queue */ 46 | int size; /* queue size */ 47 | int capacity; /* length at most */ 48 | char buffer[QUEUE_SIZE][H_SIZE]; /* data item */ 49 | } GDnsQueue; 50 | 51 | extern GDnsThread gdns_thread; 52 | 53 | char *gqueue_dequeue (GDnsQueue * q); 54 | char *reverse_ip (char *str); 55 | int gqueue_empty (GDnsQueue * q); 56 | int gqueue_enqueue (GDnsQueue * q, const char *item); 57 | int gqueue_find (GDnsQueue * q, const char *item); 58 | int gqueue_full (GDnsQueue * q); 59 | int gqueue_size (GDnsQueue * q); 60 | void dns_resolver (char *addr); 61 | void gdns_free_queue (void); 62 | void gdns_init (void); 63 | void gdns_queue_free (void); 64 | void gdns_thread_create (void); 65 | void gqueue_destroy (GDnsQueue * q); 66 | void gqueue_init (GDnsQueue * q, int capacity); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/geoip1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef GEOIP_H_INCLUDED 35 | #define GEOIP_H_INCLUDED 36 | 37 | #include "commons.h" 38 | 39 | #define CITY_LEN 47 + 1 /* max string length for a city */ 40 | #define CONTINENT_LEN 47 + 1 /* max string length for a country */ 41 | #define COUNTRY_LEN 48 + 3 /* Country + two-letter Code */ 42 | #define ASN_LEN 64 + 6 /* ASN + 5 digit/16-bit number/code */ 43 | 44 | /* Type of IP */ 45 | typedef enum { 46 | TYPE_COUNTRY, 47 | TYPE_CITY, 48 | TYPE_ASN 49 | } GO_GEOIP_DB; 50 | 51 | typedef struct GLocation_ { 52 | char city[CITY_LEN]; 53 | char continent[CONTINENT_LEN]; 54 | int hits; 55 | } GLocation; 56 | 57 | int is_geoip_resource (void); 58 | int set_geolocation (char *host, char *continent, char *country, char *city, char *asn); 59 | void geoip_asn (char *host, char *asn); 60 | void geoip_free (void); 61 | void geoip_get_continent (const char *ip, char *location, GTypeIP type_ip); 62 | void geoip_get_country (const char *ip, char *location, GTypeIP type_ip); 63 | void init_geoip (void); 64 | 65 | #endif // for #ifndef GEOIP_H 66 | -------------------------------------------------------------------------------- /src/gholder.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef GHOLDER_H_INCLUDED 31 | #define GHOLDER_H_INCLUDED 32 | 33 | #define MTRC_ID_COUNTRY 0 34 | #define MTRC_ID_CITY 1 35 | #define MTRC_ID_ASN 2 36 | #define MTRC_ID_HOSTNAME 3 37 | 38 | #include "commons.h" 39 | #include "sort.h" 40 | 41 | /* Default Anonymization Levels */ 42 | typedef enum GAnonymizeLevels_ { 43 | ANONYMIZE_DEFAULT = 1, 44 | ANONYMIZE_STRONG, 45 | ANONYMIZE_PEDANTIC, 46 | } GAnonymizeLevels; 47 | 48 | /* Function Prototypes */ 49 | GHolder *new_gholder (uint32_t size); 50 | void *add_hostname_node (void *ptr_holder); 51 | void free_holder_by_module (GHolder ** holder, GModule module); 52 | void free_holder (GHolder ** holder); 53 | void load_holder_data (GRawData * raw_data, GHolder * h, GModule module, GSort sort); 54 | void load_host_to_holder (GHolder * h, char *ip); 55 | int dup_key_list (void *val, GSLList ** user_data); 56 | 57 | #endif // for #ifndef GHOLDER_H 58 | -------------------------------------------------------------------------------- /src/gmenu.c: -------------------------------------------------------------------------------- 1 | /** 2 | * gmenu.c -- goaccess menus 3 | * ______ ___ 4 | * / ____/___ / | _____________ __________ 5 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 6 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 7 | * \____/\____/_/ |_\___/\___/\___/____/____/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "gmenu.h" 37 | 38 | #include "xmalloc.h" 39 | #include "ui.h" 40 | 41 | /* Allocate memory for a new GMenu instance. 42 | * 43 | * On success, the newly allocated GMenu is returned . */ 44 | GMenu * 45 | new_gmenu (WINDOW *parent, int h, int w, int y, int x) { 46 | GMenu *menu = xmalloc (sizeof (GMenu)); 47 | 48 | memset (menu, 0, sizeof *menu); 49 | menu->count = 0; 50 | menu->idx = 0; 51 | menu->multiple = 0; 52 | menu->selectable = 0; 53 | menu->start = 0; 54 | menu->status = 0; 55 | 56 | menu->h = h; 57 | menu->w = w; 58 | menu->x = x; 59 | menu->y = y; 60 | menu->win = derwin (parent, menu->h, menu->w, menu->y, menu->x); 61 | 62 | return menu; 63 | } 64 | 65 | /* Render actual menu item */ 66 | static void 67 | draw_menu_item (GMenu *menu, char *s, int x, int y, int w, int checked, GColors *(*func) (void)) { 68 | char check, *lbl = NULL; 69 | 70 | if (menu->selectable) { 71 | check = checked ? 'x' : ' '; 72 | lbl = xmalloc (snprintf (NULL, 0, "[%c] %s", check, s) + 1); 73 | sprintf (lbl, "[%c] %s", check, s); 74 | draw_header (menu->win, lbl, "%s", y, x, w, (*func)); 75 | free (lbl); 76 | } else { 77 | draw_header (menu->win, s, "%s", y, x, w, (*func)); 78 | } 79 | } 80 | 81 | /* Displays a menu to its associated window. 82 | * 83 | * On error, 1 is returned. 84 | * On success, the newly created menu is added to the window and 0 is 85 | * returned. */ 86 | int 87 | post_gmenu (GMenu *menu) { 88 | GColors *(*func) (void); 89 | int i = 0, j = 0, start, end, height, total, checked = 0; 90 | 91 | if (menu == NULL) 92 | return 1; 93 | 94 | werase (menu->win); 95 | 96 | height = menu->h; 97 | start = menu->start; 98 | total = menu->size; 99 | end = height < total ? start + height : total; 100 | 101 | for (i = start; i < end; i++, j++) { 102 | func = i == menu->idx ? color_selected : color_default; 103 | checked = menu->items[i].checked ? 1 : 0; 104 | draw_menu_item (menu, menu->items[i].name, 0, j, menu->w, checked, func); 105 | } 106 | wrefresh (menu->win); 107 | 108 | return 0; 109 | } 110 | 111 | /* Main work horse of the menu system processing input events */ 112 | void 113 | gmenu_driver (GMenu *menu, int c) { 114 | int i; 115 | 116 | switch (c) { 117 | case REQ_DOWN: 118 | if (menu->idx >= menu->size - 1) 119 | break; 120 | ++menu->idx; 121 | if (menu->idx >= menu->h && menu->idx >= menu->start + menu->h) 122 | menu->start++; 123 | post_gmenu (menu); 124 | break; 125 | case REQ_UP: 126 | if (menu->idx <= 0) 127 | break; 128 | --menu->idx; 129 | if (menu->idx < menu->start) 130 | --menu->start; 131 | post_gmenu (menu); 132 | break; 133 | case REQ_SEL: 134 | if (!menu->multiple) { 135 | for (i = 0; i < menu->size; i++) 136 | menu->items[i].checked = 0; 137 | } 138 | if (menu->items[menu->idx].checked) 139 | menu->items[menu->idx].checked = 0; 140 | else 141 | menu->items[menu->idx].checked = 1; 142 | post_gmenu (menu); 143 | break; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/gmenu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifdef HAVE_NCURSESW_NCURSES_H 35 | #include 36 | #elif HAVE_NCURSES_NCURSES_H 37 | #include 38 | #elif HAVE_NCURSES_H 39 | #include 40 | #elif HAVE_CURSES_H 41 | #include 42 | #endif 43 | 44 | #ifndef GMENU_H_INCLUDED 45 | #define GMENU_H_INCLUDED 46 | 47 | enum ACTION { 48 | REQ_DOWN, 49 | REQ_UP, 50 | REQ_SEL 51 | }; 52 | 53 | typedef struct GMenu_ GMenu; 54 | typedef struct GItem_ GItem; 55 | 56 | /* Menu Item */ 57 | struct GItem_ { 58 | char *name; 59 | int checked; 60 | }; 61 | 62 | /* Menu Panel */ 63 | struct GMenu_ { 64 | WINDOW *win; 65 | 66 | int count; 67 | int size; 68 | int idx; 69 | int start; 70 | int h; 71 | int w; 72 | int x; 73 | int y; 74 | unsigned short multiple; 75 | unsigned short selectable; 76 | unsigned short status; 77 | GItem *items; 78 | }; 79 | 80 | GMenu *new_gmenu (WINDOW * parent, int h, int w, int y, int x); 81 | int post_gmenu (GMenu * menu); 82 | void gmenu_driver (GMenu * menu, int c); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/goaccess.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef GOACCESS_H_INCLUDED 31 | #define GOACCESS_H_INCLUDED 32 | 33 | #include "ui.h" 34 | 35 | #define RAND_FN 7 + 1 36 | 37 | extern GSpinner *parsing_spinner; 38 | extern int active_gdns; /* kill dns pthread flag */ 39 | 40 | void read_client (void *ptr_data); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/gslist.c: -------------------------------------------------------------------------------- 1 | /** 2 | * gslist.c -- A Singly link list implementation 3 | * _______ _______ __ __ 4 | * / ____/ | / / ___/____ _____/ /_____ / /_ 5 | * / / __ | | /| / /\__ \/ __ \/ ___/ //_/ _ \/ __/ 6 | * / /_/ / | |/ |/ /___/ / /_/ / /__/ ,< / __/ /_ 7 | * \____/ |__/|__//____/\____/\___/_/|_|\___/\__/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "gslist.h" 36 | #include "gstorage.h" 37 | #include "xmalloc.h" 38 | 39 | /* Instantiate a new Singly linked-list node. 40 | * 41 | * On error, aborts if node can't be malloc'd. 42 | * On success, the GSLList node. */ 43 | GSLList * 44 | list_create (void *data) { 45 | GSLList *node = xmalloc (sizeof (GSLList)); 46 | node->data = data; 47 | node->next = NULL; 48 | 49 | return node; 50 | } 51 | 52 | /* Create and insert a node after a given node. 53 | * 54 | * On error, aborts if node can't be malloc'd. 55 | * On success, the newly created node. */ 56 | GSLList * 57 | list_insert_append (GSLList *node, void *data) { 58 | GSLList *newnode; 59 | newnode = list_create (data); 60 | newnode->next = node->next; 61 | node->next = newnode; 62 | 63 | return newnode; 64 | } 65 | 66 | /* Create and insert a node in front of the list. 67 | * 68 | * On error, aborts if node can't be malloc'd. 69 | * On success, the newly created node. */ 70 | GSLList * 71 | list_insert_prepend (GSLList *list, void *data) { 72 | GSLList *newnode; 73 | newnode = list_create (data); 74 | newnode->next = list; 75 | 76 | return newnode; 77 | } 78 | 79 | /* Find a node given a pointer to a function that compares them. 80 | * 81 | * If comparison fails, NULL is returned. 82 | * On success, the existing node is returned. */ 83 | GSLList * 84 | list_find (GSLList *node, int (*func) (void *, void *), void *data) { 85 | while (node) { 86 | if (func (node->data, data) > 0) 87 | return node; 88 | node = node->next; 89 | } 90 | 91 | return NULL; 92 | } 93 | 94 | GSLList * 95 | list_copy (GSLList *node) { 96 | GSLList *list = NULL; 97 | 98 | while (node) { 99 | if (!list) 100 | list = list_create (i322ptr ((*(uint32_t *) node->data))); 101 | else 102 | list = list_insert_prepend (list, i322ptr ((*(uint32_t *) node->data))); 103 | node = node->next; 104 | } 105 | 106 | return list; 107 | } 108 | 109 | /* Remove all nodes from the list. 110 | * 111 | * On success, 0 is returned. */ 112 | int 113 | list_remove_nodes (GSLList *list) { 114 | GSLList *tmp; 115 | while (list != NULL) { 116 | tmp = list->next; 117 | if (list->data) 118 | free (list->data); 119 | free (list); 120 | list = tmp; 121 | } 122 | 123 | return 0; 124 | } 125 | 126 | /* Remove the given node from the list. 127 | * 128 | * On error, 1 is returned. 129 | * On success, 0 is returned. */ 130 | int 131 | list_remove_node (GSLList **list, GSLList *node) { 132 | GSLList **current = list, *next = NULL; 133 | for (; *current; current = &(*current)->next) { 134 | if ((*current) != node) 135 | continue; 136 | 137 | next = (*current)->next; 138 | if ((*current)->data) 139 | free ((*current)->data); 140 | free (*current); 141 | *current = next; 142 | return 0; 143 | } 144 | return 1; 145 | } 146 | 147 | /* Iterate over the single linked-list and call function pointer. 148 | * 149 | * If function pointer does not return 0, -1 is returned. 150 | * On success, 0 is returned. */ 151 | int 152 | list_foreach (GSLList *node, int (*func) (void *, void *), void *user_data) { 153 | while (node) { 154 | if (func (node->data, user_data) != 0) 155 | return -1; 156 | node = node->next; 157 | } 158 | 159 | return 0; 160 | } 161 | 162 | /* Count the number of elements on the linked-list. 163 | * 164 | * On success, the number of elements is returned. */ 165 | int 166 | list_count (GSLList *node) { 167 | int count = 0; 168 | while (node != 0) { 169 | count++; 170 | node = node->next; 171 | } 172 | return count; 173 | } 174 | -------------------------------------------------------------------------------- /src/gslist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * _______ _______ __ __ 3 | * / ____/ | / / ___/____ _____/ /_____ / /_ 4 | * / / __ | | /| / /\__ \/ __ \/ ___/ //_/ _ \/ __/ 5 | * / /_/ / | |/ |/ /___/ / /_/ / /__/ ,< / __/ /_ 6 | * \____/ |__/|__//____/\____/\___/_/|_|\___/\__/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef GSLIST_H_INCLUDED 31 | #define GSLIST_H_INCLUDED 32 | 33 | /* Generic Single linked-list */ 34 | typedef struct GSLList_ { 35 | void *data; 36 | struct GSLList_ *next; 37 | } GSLList; 38 | 39 | #define GSLIST_FOREACH(node, data, code) { \ 40 | GSLList *__tmp = node; \ 41 | while (__tmp) { \ 42 | (data) = __tmp->data; \ 43 | code; \ 44 | __tmp = __tmp->next; \ 45 | }} 46 | 47 | /* single linked-list */ 48 | GSLList *list_create (void *data); 49 | GSLList *list_find (GSLList * node, int (*func) (void *, void *), void *data); 50 | GSLList *list_insert_append (GSLList * node, void *data); 51 | GSLList *list_insert_prepend (GSLList * list, void *data); 52 | GSLList *list_copy (GSLList * node); 53 | int list_count (GSLList * list); 54 | int list_foreach (GSLList * node, int (*func) (void *, void *), void *user_data); 55 | int list_remove_node (GSLList ** list, GSLList * node); 56 | int list_remove_nodes (GSLList * list); 57 | 58 | #endif // for #ifndef GSLIST_H 59 | -------------------------------------------------------------------------------- /src/gstorage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef GSTORAGE_H_INCLUDED 31 | #define GSTORAGE_H_INCLUDED 32 | 33 | #include "commons.h" 34 | #include "parser.h" 35 | 36 | #define DB_PATH "/tmp" 37 | 38 | #define GAMTRC_TOTAL 8 39 | /* Enumerated App Metrics */ 40 | typedef enum GAMetric_ { 41 | MTRC_DATES, 42 | MTRC_SEQS, 43 | MTRC_CNT_OVERALL, 44 | MTRC_HOSTNAMES, 45 | MTRC_LAST_PARSE, 46 | MTRC_JSON_LOGFMT, 47 | MTRC_METH_PROTO, 48 | MTRC_DB_PROPS, 49 | } GAMetric; 50 | 51 | /* Enumerated Storage Metrics */ 52 | typedef enum GSMetricType_ { 53 | /* uint32_t key - uint32_t val */ 54 | MTRC_TYPE_II32, 55 | /* uint32_t key - string val */ 56 | MTRC_TYPE_IS32, 57 | /* uint32_t key - uint64_t val */ 58 | MTRC_TYPE_IU64, 59 | /* string key - uint32_t val */ 60 | MTRC_TYPE_SI32, 61 | /* string key - uint8_t val */ 62 | MTRC_TYPE_SI08, 63 | /* uint32_t key - uint8_t val */ 64 | MTRC_TYPE_II08, 65 | /* string key - string val */ 66 | MTRC_TYPE_SS32, 67 | /* uint32_t key - GSLList val */ 68 | MTRC_TYPE_IGSL, 69 | /* string key - uint64_t val */ 70 | MTRC_TYPE_SU64, 71 | /* uint32_t key - GKHashStorage_ val */ 72 | MTRC_TYPE_IGKH, 73 | /* uint64_t key - uint32_t val */ 74 | MTRC_TYPE_U648, 75 | /* uint64_t key - GLastParse val */ 76 | MTRC_TYPE_IGLP, 77 | } GSMetricType; 78 | 79 | typedef struct GKHashMetric_ { 80 | union { 81 | GSMetric storem; 82 | GAMetric dbm; 83 | } metric; 84 | GSMetricType type; 85 | void *(*alloc) (void); 86 | void (*des) (void *, uint8_t free_data); 87 | void (*del) (void *, uint8_t free_data); 88 | uint8_t free_data:1; 89 | void *hash; 90 | const char *filename; 91 | } GKHashMetric; 92 | 93 | /* Each record contains a data value, i.e., Windows XP, and it may contain a 94 | * root value, i.e., Windows, and a unique key which is the combination of 95 | * date, IP and user agent */ 96 | typedef struct GKeyData_ { 97 | const void *data; 98 | uint32_t dhash; 99 | uint32_t data_nkey; 100 | uint32_t cdnkey; /* cache data nkey */ 101 | 102 | uint32_t rhash; 103 | const void *root; 104 | const void *root_key; 105 | uint32_t root_nkey; 106 | uint32_t crnkey; /* cache root nkey */ 107 | 108 | void *uniq_key; 109 | uint32_t uniq_nkey; 110 | 111 | uint32_t numdate; 112 | } GKeyData; 113 | 114 | typedef struct GParse_ { 115 | GModule module; 116 | int (*key_data) (GKeyData * kdata, GLogItem * logitem); 117 | 118 | /* data field */ 119 | void (*datamap) (GModule module, GKeyData * kdata); 120 | void (*rootmap) (GModule module, GKeyData * kdata); 121 | void (*hits) (GModule module, GKeyData * kdata); 122 | void (*visitor) (GModule module, GKeyData * kdata); 123 | void (*bw) (GModule module, GKeyData * kdata, uint64_t size); 124 | void (*cumts) (GModule module, GKeyData * kdata, uint64_t ts); 125 | void (*maxts) (GModule module, GKeyData * kdata, uint64_t ts); 126 | void (*method) (GModule module, GKeyData * kdata, const char *data); 127 | void (*protocol) (GModule module, GKeyData * kdata, const char *data); 128 | void (*agent) (GModule module, GKeyData * kdata, uint32_t agent_nkey); 129 | } GParse; 130 | 131 | typedef struct httpmethods_ { 132 | const char *method; 133 | int len; 134 | } httpmethods; 135 | 136 | typedef struct httpprotocols_ { 137 | const char *protocol; 138 | int len; 139 | } httpprotocols; 140 | 141 | extern const httpmethods http_methods[]; 142 | extern const httpprotocols http_protocols[]; 143 | extern const size_t http_methods_len; 144 | extern const size_t http_protocols_len; 145 | 146 | const char *get_mtr_str (GSMetric metric); 147 | int excluded_ip (GLogItem * logitem); 148 | uint32_t *i322ptr (uint32_t val); 149 | uint64_t *uint642ptr (uint64_t val); 150 | void count_process_and_invalid (GLog * glog, GLogItem * logitem, const char *line); 151 | void count_process (GLog * glog); 152 | void free_gmetrics (GMetrics * metric); 153 | void insert_methods_protocols (void); 154 | void process_log (GLogItem * logitem); 155 | void set_browser_os (GLogItem * logitem); 156 | void set_data_metrics (GMetrics * ometrics, GMetrics ** nmetrics, GPercTotals totals); 157 | void set_module_totals (GPercTotals * totals); 158 | void uncount_invalid (GLog * glog); 159 | void uncount_processed (GLog * glog); 160 | GMetrics *new_gmetrics (void); 161 | 162 | #endif // for #ifndef GSTORAGE_H 163 | -------------------------------------------------------------------------------- /src/gwsocket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * _______ _______ __ __ 3 | * / ____/ | / / ___/____ _____/ /_____ / /_ 4 | * / / __ | | /| / /\__ \/ __ \/ ___/ //_/ _ \/ __/ 5 | * / /_/ / | |/ |/ /___/ / /_/ / /__/ ,< / __/ /_ 6 | * \____/ |__/|__//____/\____/\___/_/|_|\___/\__/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef GWSOCKET_H_INCLUDED 31 | #define GWSOCKET_H_INCLUDED 32 | 33 | #define GW_VERSION "0.1" 34 | 35 | #include 36 | #include "websocket.h" 37 | 38 | typedef struct GWSReader_ { 39 | int fd; 40 | int self_pipe[2]; /* self-pipe */ 41 | 42 | pthread_mutex_t mutex; /* Mutex fifo out */ 43 | pthread_t thread; /* Thread fifo in */ 44 | 45 | WSPacket *packet; /* FIFO data's buffer */ 46 | char hdr[HDR_SIZE]; /* FIFO header's buffer */ 47 | int hlen; /* header length */ 48 | } GWSReader; 49 | 50 | typedef struct GWSWriter_ { 51 | int fd; 52 | 53 | pthread_mutex_t mutex; /* Mutex fifo in */ 54 | pthread_t thread; /* Thread fifo out */ 55 | 56 | WSServer *server; /* WebSocket server */ 57 | } GWSWriter; 58 | 59 | GWSReader *new_gwsreader (void); 60 | GWSWriter *new_gwswriter (void); 61 | int broadcast_holder (int fd, const char *buf, int len); 62 | int open_fifoin (void); 63 | int open_fifoout (void); 64 | int read_fifo (GWSReader * gwsreader, void (*f) (int)); 65 | int send_holder_to_client (int fd, int listener, const char *buf, int len); 66 | int setup_ws_server (GWSWriter * gwswriter, GWSReader * gwsreader); 67 | void set_ready_state (void); 68 | void set_self_pipe (int *self_pipe); 69 | void stop_ws_server (GWSWriter * gwswriter, GWSReader * gwsreader); 70 | 71 | #endif // for #ifndef GWSOCKET_H 72 | -------------------------------------------------------------------------------- /src/json.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef JSON_H_INCLUDED 35 | #define JSON_H_INCLUDED 36 | 37 | #define TAB "\t\t\t\t\t\t\t\t\t\t\t" 38 | #define NL "\n\n\n" 39 | 40 | #include "parser.h" 41 | 42 | typedef struct GJSON_ { 43 | char *buf; /* pointer to buffer */ 44 | size_t size; /* size of malloc'd buffer */ 45 | size_t offset; /* current write offset */ 46 | } GJSON; 47 | 48 | char *get_json (GHolder * holder, int escape_html); 49 | 50 | void output_json (GHolder * holder, const char *filename); 51 | void set_json_nlines (int nl); 52 | 53 | void fpskeyival (FILE * fp, const char *key, int val, int sp, int last); 54 | void fpskeysval (FILE * fp, const char *key, const char *val, int sp, int last); 55 | void fpskeyaval (FILE * fp, const char *key, const char *val, int sp, int last); 56 | 57 | void fpclose_arr (FILE * fp, int sp, int last); 58 | void fpclose_obj (FILE * fp, int iisp, int last); 59 | void fpjson (FILE * fp, const char *fmt, ...) __attribute__((format (printf, 2, 3))); 60 | void fpopen_arr_attr (FILE * fp, const char *attr, int sp); 61 | void fpopen_obj_attr (FILE * fp, const char *attr, int sp); 62 | void fpopen_obj (FILE * fp, int iisp); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/opesys.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef OPESYS_H_INCLUDED 31 | #define OPESYS_H_INCLUDED 32 | 33 | #define OPESYS_TYPE_LEN 10 34 | 35 | /* Each OS contains the number of hits and the OS's type */ 36 | typedef struct GOpeSys_ { 37 | char os_type[OPESYS_TYPE_LEN]; 38 | int hits; 39 | } GOpeSys; 40 | 41 | char *verify_os (char *str, char *os_type); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/options.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef OPTIONS_H_INCLUDED 31 | #define OPTIONS_H_INCLUDED 32 | 33 | #define CYN "\x1B[36m" 34 | #define RESET "\x1B[0m" 35 | #define HTML_REFRESH 1 /* in seconds */ 36 | 37 | void add_dash_filename (void); 38 | void cmd_help (void) __attribute__((noreturn)); 39 | void read_option_args (int argc, char **argv); 40 | void verify_global_config (int argc, char **argv); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/output.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef OUTPUT_H_INCLUDED 35 | #define OUTPUT_H_INCLUDED 36 | 37 | #define MAX_PLOTS 5 /* number of metrics we can plot */ 38 | #define FILENAME_JS "goaccess.js" 39 | #define FILENAME_CSS "goaccess.css" 40 | 41 | #include "commons.h" 42 | #include "parser.h" 43 | 44 | /* Enumerated chart types */ 45 | typedef enum GChartType_ { 46 | CHART_NONE, 47 | CHART_VBAR, 48 | CHART_AREASPLINE, 49 | CHART_WMAP, 50 | CHART_GMAP, 51 | } GChartType; 52 | 53 | /* Chart axis structure */ 54 | typedef struct GChartDef_ { 55 | const char *key; 56 | const char *value; 57 | } GChartDef; 58 | 59 | /* Chart axis structure */ 60 | typedef struct GChart_ { 61 | const char *key; 62 | GChartDef *def; 63 | } GChart; 64 | 65 | /* Chart behavior */ 66 | typedef struct GHTMLPlot_ { 67 | GChartType chart_type; 68 | void (*plot) (FILE * fp, struct GHTMLPlot_ plot, int sp); 69 | int8_t chart_reverse; 70 | int8_t redraw_expand; 71 | char *chart_key; 72 | char *chart_lbl; 73 | } GHTMLPlot; 74 | 75 | /* Controls HTML panel output. */ 76 | typedef struct GHTML_ { 77 | GModule module; 78 | int8_t table; 79 | int8_t has_map; 80 | void (*metrics) (FILE * fp, const struct GHTML_ * def, int sp); 81 | GHTMLPlot chart[MAX_PLOTS]; 82 | } GHTML; 83 | 84 | /* Metric definition . */ 85 | typedef struct GDefMetric_ { 86 | const char *cname; /* metric class name */ 87 | const char *cwidth; /* metric column width */ 88 | const char *datakey; /* metric JSON data key */ 89 | const char *datatype; /* metric data value type */ 90 | const char *lbl; /* metric label (column name) */ 91 | const char *metakey; /* metric JSON meta key */ 92 | const char *metatype; /* metric meta value type */ 93 | const char *metalbl; /* metric meta value label */ 94 | const char *hlregex; /* highlight regex value */ 95 | } GDefMetric; 96 | 97 | void output_html (GHolder * holder, const char *filename); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef PARSER_H_INCLUDED 31 | #define PARSER_H_INCLUDED 32 | 33 | #define KEY_FOUND 1 34 | #define KEY_NOT_FOUND -1 35 | #define LINE_BUFFER 4096 /* read at most this num of chars */ 36 | #define NUM_TESTS 20 /* test this many lines from the log */ 37 | #define MAX_LOG_ERRORS 20 38 | #define READ_BYTES 4096u 39 | #define MAX_BATCH_LINES 8192u /* max number of lines to read per batch before a reflow */ 40 | #define MAX_MIME_OUT 256 41 | 42 | #define LINE_LEN 23 43 | #define ERROR_LEN 255 44 | #define REF_SITE_LEN 511 /* maximum length of a referring site */ 45 | #define CACHE_STATUS_LEN 7 46 | #define HASH_HEX 64 47 | 48 | #define ERR_SPEC_TOKN_NUL 0x1 49 | #define ERR_SPEC_TOKN_INV 0x2 50 | #define ERR_SPEC_SFMT_MIS 0x3 51 | #define ERR_SPEC_LINE_INV 0x4 52 | #define ERR_LOG_NOT_FOUND 0x5 53 | #define ERR_LOG_REALLOC_FAILURE 0x6 54 | 55 | 56 | #include 57 | #include "commons.h" 58 | #include "gslist.h" 59 | 60 | typedef struct GLogProp_ { 61 | char *filename; /* filename including path */ 62 | char *fname; /* basename(filename) */ 63 | uint64_t inode; /* inode of the log */ 64 | uint64_t size; /* original size of log */ 65 | } GLogProp; 66 | 67 | /* Log properties. Note: This is per line parsed */ 68 | typedef struct GLogItem_ { 69 | char *agent; 70 | char *browser; 71 | char *browser_type; 72 | char *continent; 73 | char *country; 74 | char *asn; 75 | char *date; 76 | char *host; 77 | char *keyphrase; 78 | char *method; 79 | char *os; 80 | char *os_type; 81 | char *protocol; 82 | char *qstr; 83 | char *ref; 84 | char *req; 85 | char *req_key; 86 | int status; 87 | char *time; 88 | char *uniq_key; 89 | char *vhost; 90 | char *userid; 91 | char *cache_status; 92 | 93 | char site[REF_SITE_LEN + 1]; 94 | char agent_hex[HASH_HEX]; 95 | 96 | uint64_t resp_size; 97 | uint64_t serve_time; 98 | 99 | uint32_t numdate; 100 | uint32_t agent_hash; 101 | int ignorelevel; 102 | int type_ip; 103 | int is_404; 104 | int is_static; 105 | int uniq_nkey; 106 | int agent_nkey; 107 | 108 | /* UMS */ 109 | char *mime_type; 110 | char *tls_type; 111 | char *tls_cypher; 112 | char *tls_type_cypher; 113 | 114 | char *errstr; 115 | struct tm dt; 116 | } GLogItem; 117 | 118 | typedef struct GLastParse_ { 119 | uint32_t line; 120 | int64_t ts; 121 | uint64_t size; 122 | uint16_t snippetlen; 123 | char snippet[READ_BYTES + 1]; 124 | } GLastParse; 125 | 126 | /* Overall parsed log properties */ 127 | typedef struct GLog_ { 128 | uint8_t piping:1; 129 | uint8_t log_erridx; 130 | uint32_t read; /* lines read/parsed */ 131 | uint64_t bytes; /* bytes read on each iteration */ 132 | uint64_t length; /* length read from the log so far */ 133 | uint64_t invalid; /* invalid lines for this log */ 134 | uint64_t processed; /* lines proceeded for this log */ 135 | 136 | /* file test for persisted/restored data */ 137 | uint16_t snippetlen; 138 | char snippet[READ_BYTES + 1]; 139 | 140 | GLastParse lp; 141 | GLogProp props; 142 | struct tm start_time; 143 | 144 | char *fname_as_vhost; 145 | char **errors; 146 | 147 | FILE *pipe; 148 | } GLog; 149 | 150 | /* Container for all logs */ 151 | typedef struct Logs_ { 152 | uint8_t restored:1; 153 | uint8_t load_from_disk_only:1; 154 | uint64_t *processed; 155 | uint64_t offset; 156 | int size; /* num items */ 157 | int idx; 158 | char *filename; 159 | GLog *glog; 160 | } Logs; 161 | 162 | /* Pthread jobs for multi-thread */ 163 | typedef struct GJob_ { 164 | uint32_t cnt; 165 | int p, test, dry_run, running; 166 | GLog *glog; 167 | GLogItem **logitems; 168 | char **lines; 169 | } GJob; 170 | 171 | /* Raw data field type */ 172 | typedef enum { 173 | U32, 174 | STR 175 | } datatype; 176 | 177 | /* Raw Data extracted from table stores */ 178 | typedef struct GRawDataItem_ { 179 | uint32_t nkey; 180 | union { 181 | const char *data; 182 | uint32_t hits; 183 | }; 184 | } GRawDataItem; 185 | 186 | /* Raw Data per module */ 187 | typedef struct GRawData_ { 188 | GRawDataItem *items; /* data */ 189 | GModule module; /* current module */ 190 | datatype type; 191 | int idx; /* first level index */ 192 | int size; /* total num of items on ht */ 193 | } GRawData; 194 | 195 | 196 | char *extract_by_delim (const char **str, const char *end); 197 | char *fgetline (FILE * fp); 198 | char **test_format (Logs * logs, int *len); 199 | int parse_line (GLog * glog, char *line, int dry_run, GLogItem ** logitem_out); 200 | int parse_log (Logs * logs, int dry_run); 201 | int set_glog (Logs * logs, const char *filename); 202 | int set_initial_persisted_data (GLog * glog, FILE * fp, const char *fn); 203 | int set_log (Logs * logs, const char *value); 204 | void free_glog (GLogItem * logitem); 205 | void free_logerrors (GLog * glog); 206 | void free_logs (Logs * logs); 207 | void free_raw_data (GRawData * raw_data); 208 | void output_logerrors (void); 209 | void *process_lines_thread (void *arg); 210 | void reset_struct (Logs * logs); 211 | 212 | GLogItem *init_log_item (GLog * glog); 213 | GRawDataItem *new_grawdata_item (unsigned int size); 214 | GRawData *new_grawdata (void); 215 | Logs *init_logs (int size); 216 | Logs *new_logs (int size); 217 | 218 | #endif 219 | -------------------------------------------------------------------------------- /src/pdjson.h: -------------------------------------------------------------------------------- 1 | #ifndef PDJSON_H 2 | #define PDJSON_H 3 | 4 | #ifndef PDJSON_SYMEXPORT 5 | # define PDJSON_SYMEXPORT 6 | #endif 7 | 8 | #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) 9 | #include 10 | #else 11 | #ifndef bool 12 | #define bool int 13 | #define true 1 14 | #define false 0 15 | #endif /* bool */ 16 | #endif /* __STDC_VERSION__ */ 17 | 18 | #include 19 | 20 | enum json_type { 21 | JSON_ERROR = 1, JSON_DONE, 22 | JSON_OBJECT, JSON_OBJECT_END, JSON_ARRAY, JSON_ARRAY_END, 23 | JSON_STRING, JSON_NUMBER, JSON_TRUE, JSON_FALSE, JSON_NULL 24 | }; 25 | 26 | struct json_allocator { 27 | void *(*malloc) (size_t); 28 | void *(*realloc) (void *, size_t); 29 | void (*free) (void *); 30 | }; 31 | 32 | typedef int (*json_user_io) (void *user); 33 | 34 | typedef struct json_stream json_stream; 35 | typedef struct json_allocator json_allocator; 36 | 37 | PDJSON_SYMEXPORT void json_open_buffer (json_stream * json, const void *buffer, size_t size); 38 | PDJSON_SYMEXPORT void json_open_string (json_stream * json, const char *string); 39 | PDJSON_SYMEXPORT void json_open_stream (json_stream * json, FILE * stream); 40 | PDJSON_SYMEXPORT void json_open_user (json_stream * json, json_user_io get, json_user_io peek, 41 | void *user); 42 | PDJSON_SYMEXPORT void json_close (json_stream * json); 43 | 44 | PDJSON_SYMEXPORT void json_set_allocator (json_stream * json, json_allocator * a); 45 | PDJSON_SYMEXPORT void json_set_streaming (json_stream * json, bool mode); 46 | 47 | PDJSON_SYMEXPORT enum json_type json_next (json_stream * json); 48 | PDJSON_SYMEXPORT enum json_type json_peek (json_stream * json); 49 | PDJSON_SYMEXPORT void json_reset (json_stream * json); 50 | PDJSON_SYMEXPORT const char *json_get_string (json_stream * json, size_t *length); 51 | PDJSON_SYMEXPORT double json_get_number (json_stream * json); 52 | 53 | PDJSON_SYMEXPORT enum json_type json_skip (json_stream * json); 54 | PDJSON_SYMEXPORT enum json_type json_skip_until (json_stream * json, enum json_type type); 55 | 56 | PDJSON_SYMEXPORT size_t json_get_lineno (json_stream * json); 57 | PDJSON_SYMEXPORT size_t json_get_position (json_stream * json); 58 | PDJSON_SYMEXPORT size_t json_get_depth (json_stream * json); 59 | PDJSON_SYMEXPORT enum json_type json_get_context (json_stream * json, size_t *count); 60 | PDJSON_SYMEXPORT const char *json_get_error (json_stream * json); 61 | 62 | PDJSON_SYMEXPORT int json_source_get (json_stream * json); 63 | PDJSON_SYMEXPORT int json_source_peek (json_stream * json); 64 | PDJSON_SYMEXPORT bool json_isspace (int c); 65 | 66 | /* internal */ 67 | 68 | struct json_source { 69 | int (*get) (struct json_source *); 70 | int (*peek) (struct json_source *); 71 | size_t position; 72 | union { 73 | struct { 74 | FILE *stream; 75 | } stream; 76 | struct { 77 | const char *buffer; 78 | size_t length; 79 | } buffer; 80 | struct { 81 | void *ptr; 82 | json_user_io get; 83 | json_user_io peek; 84 | } user; 85 | } source; 86 | }; 87 | 88 | struct json_stream { 89 | size_t lineno; 90 | 91 | struct json_stack *stack; 92 | size_t stack_top; 93 | size_t stack_size; 94 | enum json_type next; 95 | unsigned flags; 96 | 97 | struct { 98 | char *string; 99 | size_t string_fill; 100 | size_t string_size; 101 | } data; 102 | 103 | size_t ntokens; 104 | 105 | struct json_source source; 106 | struct json_allocator alloc; 107 | char errmsg[128]; 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/persistence.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef PERSISTENCE_H_INCLUDED 31 | #define PERSISTENCE_H_INCLUDED 32 | 33 | void restore_data (void); 34 | void persist_data (void); 35 | void free_persisted_data (void); 36 | 37 | #endif // for #ifndef PERSISTENCE_H 38 | -------------------------------------------------------------------------------- /src/sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | SHA-1 in C 3 | By Steve Reid 4 | 100% Public Domain 5 | 6 | Test Vectors (from FIPS PUB 180-1) 7 | "abc" 8 | A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 9 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 10 | 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 11 | A million repetitions of "a" 12 | 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 13 | */ 14 | 15 | /* #define LITTLE_ENDIAN * This should be #define'd if true. */ 16 | #if __LITTLE_ENDIAN__ 17 | #define LITTLE_ENDIAN 18 | #endif 19 | /* #define SHA1HANDSOFF * Copies data before messing with it. */ 20 | 21 | #include 22 | 23 | #include "sha1.h" 24 | 25 | void SHA1Transform (uint32_t state[5], uint8_t buffer[64]); 26 | 27 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 28 | 29 | /* blk0() and blk() perform the initial expand. */ 30 | /* I got the idea of expanding during the round function from SSLeay */ 31 | #ifdef LITTLE_ENDIAN 32 | #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ 33 | |(rol(block->l[i],8)&0x00FF00FF)) 34 | #else 35 | #define blk0(i) block->l[i] 36 | #endif 37 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 38 | ^block->l[(i+2)&15]^block->l[i&15],1)) 39 | 40 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 41 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 42 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 43 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 44 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 45 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 46 | 47 | 48 | /* Hash a single 512-bit block. This is the core of the algorithm. */ 49 | 50 | void 51 | SHA1Transform (uint32_t state[5], uint8_t buffer[64]) { 52 | uint32_t a, b, c, d, e; 53 | typedef union { 54 | uint8_t c[64]; 55 | uint32_t l[16]; 56 | } CHAR64LONG16; 57 | CHAR64LONG16 *block; 58 | #ifdef SHA1HANDSOFF 59 | static uint8_t workspace[64]; 60 | block = (CHAR64LONG16 *) (void *) workspace; 61 | memcpy (block, buffer, 64); 62 | #else 63 | block = (CHAR64LONG16 *) (void *) buffer; 64 | #endif 65 | /* Copy context->state[] to working vars */ 66 | a = state[0]; 67 | b = state[1]; 68 | c = state[2]; 69 | d = state[3]; 70 | e = state[4]; 71 | /* 4 rounds of 20 operations each. Loop unrolled. */ 72 | R0 (a, b, c, d, e, 0); 73 | R0 (e, a, b, c, d, 1); 74 | R0 (d, e, a, b, c, 2); 75 | R0 (c, d, e, a, b, 3); 76 | R0 (b, c, d, e, a, 4); 77 | R0 (a, b, c, d, e, 5); 78 | R0 (e, a, b, c, d, 6); 79 | R0 (d, e, a, b, c, 7); 80 | R0 (c, d, e, a, b, 8); 81 | R0 (b, c, d, e, a, 9); 82 | R0 (a, b, c, d, e, 10); 83 | R0 (e, a, b, c, d, 11); 84 | R0 (d, e, a, b, c, 12); 85 | R0 (c, d, e, a, b, 13); 86 | R0 (b, c, d, e, a, 14); 87 | R0 (a, b, c, d, e, 15); 88 | R1 (e, a, b, c, d, 16); 89 | R1 (d, e, a, b, c, 17); 90 | R1 (c, d, e, a, b, 18); 91 | R1 (b, c, d, e, a, 19); 92 | R2 (a, b, c, d, e, 20); 93 | R2 (e, a, b, c, d, 21); 94 | R2 (d, e, a, b, c, 22); 95 | R2 (c, d, e, a, b, 23); 96 | R2 (b, c, d, e, a, 24); 97 | R2 (a, b, c, d, e, 25); 98 | R2 (e, a, b, c, d, 26); 99 | R2 (d, e, a, b, c, 27); 100 | R2 (c, d, e, a, b, 28); 101 | R2 (b, c, d, e, a, 29); 102 | R2 (a, b, c, d, e, 30); 103 | R2 (e, a, b, c, d, 31); 104 | R2 (d, e, a, b, c, 32); 105 | R2 (c, d, e, a, b, 33); 106 | R2 (b, c, d, e, a, 34); 107 | R2 (a, b, c, d, e, 35); 108 | R2 (e, a, b, c, d, 36); 109 | R2 (d, e, a, b, c, 37); 110 | R2 (c, d, e, a, b, 38); 111 | R2 (b, c, d, e, a, 39); 112 | R3 (a, b, c, d, e, 40); 113 | R3 (e, a, b, c, d, 41); 114 | R3 (d, e, a, b, c, 42); 115 | R3 (c, d, e, a, b, 43); 116 | R3 (b, c, d, e, a, 44); 117 | R3 (a, b, c, d, e, 45); 118 | R3 (e, a, b, c, d, 46); 119 | R3 (d, e, a, b, c, 47); 120 | R3 (c, d, e, a, b, 48); 121 | R3 (b, c, d, e, a, 49); 122 | R3 (a, b, c, d, e, 50); 123 | R3 (e, a, b, c, d, 51); 124 | R3 (d, e, a, b, c, 52); 125 | R3 (c, d, e, a, b, 53); 126 | R3 (b, c, d, e, a, 54); 127 | R3 (a, b, c, d, e, 55); 128 | R3 (e, a, b, c, d, 56); 129 | R3 (d, e, a, b, c, 57); 130 | R3 (c, d, e, a, b, 58); 131 | R3 (b, c, d, e, a, 59); 132 | R4 (a, b, c, d, e, 60); 133 | R4 (e, a, b, c, d, 61); 134 | R4 (d, e, a, b, c, 62); 135 | R4 (c, d, e, a, b, 63); 136 | R4 (b, c, d, e, a, 64); 137 | R4 (a, b, c, d, e, 65); 138 | R4 (e, a, b, c, d, 66); 139 | R4 (d, e, a, b, c, 67); 140 | R4 (c, d, e, a, b, 68); 141 | R4 (b, c, d, e, a, 69); 142 | R4 (a, b, c, d, e, 70); 143 | R4 (e, a, b, c, d, 71); 144 | R4 (d, e, a, b, c, 72); 145 | R4 (c, d, e, a, b, 73); 146 | R4 (b, c, d, e, a, 74); 147 | R4 (a, b, c, d, e, 75); 148 | R4 (e, a, b, c, d, 76); 149 | R4 (d, e, a, b, c, 77); 150 | R4 (c, d, e, a, b, 78); 151 | R4 (b, c, d, e, a, 79); 152 | /* Add the working vars back into context.state[] */ 153 | state[0] += a; 154 | state[1] += b; 155 | state[2] += c; 156 | state[3] += d; 157 | state[4] += e; 158 | /* Wipe variables */ 159 | a = b = c = d = e = 0; 160 | } 161 | 162 | 163 | /* SHA1Init - Initialize new context */ 164 | 165 | void 166 | SHA1Init (SHA1_CTX *context) { 167 | /* SHA1 initialization constants */ 168 | context->state[0] = 0x67452301; 169 | context->state[1] = 0xEFCDAB89; 170 | context->state[2] = 0x98BADCFE; 171 | context->state[3] = 0x10325476; 172 | context->state[4] = 0xC3D2E1F0; 173 | context->count[0] = context->count[1] = 0; 174 | } 175 | 176 | 177 | /* Run your data through this. */ 178 | 179 | void 180 | SHA1Update (SHA1_CTX *context, uint8_t *data, unsigned int len) { 181 | unsigned int i, j; 182 | 183 | j = (context->count[0] >> 3) & 63; 184 | if ((context->count[0] += len << 3) < (len << 3)) 185 | context->count[1]++; 186 | context->count[1] += (len >> 29); 187 | if ((j + len) > 63) { 188 | memcpy (&context->buffer[j], data, (i = 64 - j)); 189 | SHA1Transform (context->state, context->buffer); 190 | for (; i + 63 < len; i += 64) { 191 | SHA1Transform (context->state, &data[i]); 192 | } 193 | j = 0; 194 | } else 195 | i = 0; 196 | memcpy (&context->buffer[j], &data[i], len - i); 197 | } 198 | 199 | 200 | /* Add padding and return the message digest. */ 201 | 202 | void 203 | SHA1Final (uint8_t digest[20], SHA1_CTX *context) { 204 | uint32_t i, j; 205 | uint8_t finalcount[8]; 206 | 207 | for (i = 0; i < 8; i++) { 208 | finalcount[i] = (uint8_t) ((context->count[(i >= 4 ? 0 : 1)] 209 | >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ 210 | } 211 | SHA1Update (context, (uint8_t *) "\200", 1); 212 | while ((context->count[0] & 504) != 448) { 213 | SHA1Update (context, (uint8_t *) "\0", 1); 214 | } 215 | SHA1Update (context, finalcount, 8); /* Should cause a SHA1Transform() */ 216 | for (i = 0; i < 20; i++) { 217 | digest[i] = (uint8_t) 218 | ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); 219 | } 220 | /* Wipe variables */ 221 | i = j = 0; 222 | memset (context->buffer, 0, 64); 223 | memset (context->state, 0, 20); 224 | memset (context->count, 0, 8); 225 | memset (&finalcount, 0, 8); 226 | #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ 227 | SHA1Transform (context->state, context->buffer); 228 | #endif 229 | } 230 | -------------------------------------------------------------------------------- /src/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA1_H_INCLUDED 2 | #define SHA1_H_INCLUDED 3 | 4 | #include 5 | #include 6 | 7 | // From http://www.mirrors.wiretapped.net/security/cryptography/hashes/sha1/sha1.c 8 | 9 | typedef struct { 10 | uint32_t state[5]; 11 | uint32_t count[2]; 12 | uint8_t buffer[64]; 13 | } SHA1_CTX; 14 | 15 | extern void SHA1Init (SHA1_CTX * context); 16 | extern void SHA1Update (SHA1_CTX * context, uint8_t * data, uint32_t len); 17 | extern void SHA1Final (uint8_t digest[20], SHA1_CTX * context); 18 | 19 | #endif // for #ifndef SHA1_H 20 | -------------------------------------------------------------------------------- /src/sort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #if HAVE_CONFIG_H 31 | #include 32 | #endif 33 | 34 | #ifndef SORT_H_INCLUDED 35 | #define SORT_H_INCLUDED 36 | 37 | #include "commons.h" 38 | #include "parser.h" 39 | 40 | #define SORT_MAX_OPTS 11 41 | 42 | /* See GEnum for mapping */ 43 | #define SORT_FIELD_LEN 11 + 1 /* longest metric name */ 44 | #define SORT_MODULE_LEN 15 + 1 /* longest module name */ 45 | #define SORT_ORDER_LEN 4 + 1 /* length of ASC or DESC */ 46 | 47 | /* Enumerated sorting metrics */ 48 | typedef enum GSortField_ { 49 | SORT_BY_HITS, 50 | SORT_BY_VISITORS, 51 | SORT_BY_DATA, 52 | SORT_BY_BW, 53 | SORT_BY_AVGTS, 54 | SORT_BY_CUMTS, 55 | SORT_BY_MAXTS, 56 | SORT_BY_PROT, 57 | SORT_BY_MTHD, 58 | } GSortField; 59 | 60 | /* Enumerated sorting order */ 61 | typedef enum GSortOrder_ { 62 | SORT_ASC, 63 | SORT_DESC 64 | } GSortOrder; 65 | 66 | /* Sorting of each panel, metric and order */ 67 | typedef struct GSort_ { 68 | GModule module; 69 | GSortField field; 70 | GSortOrder sort; 71 | } GSort; 72 | 73 | extern GSort module_sort[TOTAL_MODULES]; 74 | extern const int sort_choices[][SORT_MAX_OPTS]; 75 | 76 | GRawData *sort_raw_num_data (GRawData * raw_data, int ht_size); 77 | GRawData *sort_raw_str_data (GRawData * raw_data, int ht_size); 78 | const char *get_sort_field_key (GSortField field); 79 | const char *get_sort_field_str (GSortField field); 80 | const char *get_sort_order_str (GSortOrder order); 81 | int can_sort_module (GModule module, int field); 82 | int get_sort_field_enum (const char *str); 83 | int get_sort_order_enum (const char *str); 84 | int strcmp_asc (const void *a, const void *b); 85 | int cmp_ui32_asc (const void *a, const void *b); 86 | int cmp_ui32_desc (const void *a, const void *b); 87 | void parse_initial_sort (void); 88 | void set_initial_sort (const char *smod, const char *sfield, const char *ssort); 89 | void sort_holder_items (GHolderItem * items, int size, GSort sort); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/tpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005-2013, Troy D. Hanson http://troydhanson.github.com/tpl/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifndef TPL_H 25 | #define TPL_H 26 | 27 | #include /* size_t */ 28 | 29 | #include /* va_list */ 30 | 31 | #ifdef __INTEL_COMPILER 32 | #include 33 | #endif /* Intel Compiler efficient memcpy etc */ 34 | 35 | #ifdef _MSC_VER 36 | typedef unsigned int uint32_t; 37 | #else 38 | #include /* uint32_t */ 39 | #endif 40 | 41 | #if defined __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #ifdef _WIN32 46 | #ifdef TPL_EXPORTS 47 | #define TPL_API __declspec(dllexport) 48 | #else /* */ 49 | #ifdef TPL_NOLIB 50 | #define TPL_API 51 | #else 52 | #define TPL_API __declspec(dllimport) 53 | #endif /* TPL_NOLIB */ 54 | #endif /* TPL_EXPORTS */ 55 | #else 56 | #define TPL_API 57 | #endif 58 | 59 | /* bit flags (external) */ 60 | #define TPL_FILE (1 << 0) 61 | #define TPL_MEM (1 << 1) 62 | #define TPL_PREALLOCD (1 << 2) 63 | #define TPL_EXCESS_OK (1 << 3) 64 | #define TPL_FD (1 << 4) 65 | #define TPL_UFREE (1 << 5) 66 | #define TPL_DATAPEEK (1 << 6) 67 | #define TPL_FXLENS (1 << 7) 68 | #define TPL_GETSIZE (1 << 8) 69 | /* do not add flags here without renumbering the internal flags! */ 70 | 71 | /* flags for tpl_gather mode */ 72 | #define TPL_GATHER_BLOCKING 1 73 | #define TPL_GATHER_NONBLOCKING 2 74 | #define TPL_GATHER_MEM 3 75 | 76 | /* Hooks for error logging, memory allocation functions and fatal */ 77 | typedef int (tpl_print_fcn) (const char *fmt, ...); 78 | typedef void *(tpl_malloc_fcn) (size_t sz); 79 | typedef void *(tpl_realloc_fcn) (void *ptr, size_t sz); 80 | typedef void (tpl_free_fcn) (void *ptr); 81 | typedef void (tpl_fatal_fcn) (const char *fmt, ...); 82 | 83 | typedef struct tpl_hook_t { 84 | tpl_print_fcn *oops __attribute__((__format__ (printf, 1, 2))); 85 | tpl_malloc_fcn *malloc; 86 | tpl_realloc_fcn *realloc; 87 | tpl_free_fcn *free; 88 | tpl_fatal_fcn *fatal __attribute__((__format__ (printf, 1, 2))) 89 | __attribute__((__noreturn__)); 90 | size_t gather_max; 91 | } tpl_hook_t; 92 | 93 | typedef struct tpl_node { 94 | int type; 95 | void *addr; 96 | void *data; /* r:tpl_root_data*. A:tpl_atyp*. ow:szof type */ 97 | int num; /* length of type if it's a C array */ 98 | size_t ser_osz; /* serialization output size for subtree */ 99 | struct tpl_node *children; /* my children; linked-list */ 100 | struct tpl_node *next, *prev; /* my siblings (next child of my parent) */ 101 | struct tpl_node *parent; /* my parent */ 102 | } tpl_node; 103 | 104 | /* used when un/packing 'B' type (binary buffers) */ 105 | typedef struct tpl_bin { 106 | void *addr; 107 | uint32_t sz; 108 | } tpl_bin; 109 | 110 | /* for async/piecemeal reading of tpl images */ 111 | typedef struct tpl_gather_t { 112 | char *img; 113 | int len; 114 | } tpl_gather_t; 115 | 116 | /* Callback used when tpl_gather has read a full tpl image */ 117 | typedef int (tpl_gather_cb) (void *img, size_t sz, void *data); 118 | 119 | /* Prototypes */ 120 | TPL_API tpl_node *tpl_map (char *fmt, ...); /* define tpl using format */ 121 | TPL_API void tpl_free (tpl_node * r); /* free a tpl map */ 122 | TPL_API int tpl_pack (tpl_node * r, int i); /* pack the n'th packable */ 123 | TPL_API int tpl_unpack (tpl_node * r, int i); /* unpack the n'th packable */ 124 | TPL_API int tpl_dump (tpl_node * r, int mode, ...); /* serialize to mem/file */ 125 | TPL_API int tpl_load (tpl_node * r, int mode, ...); /* set mem/file to unpack */ 126 | TPL_API int tpl_Alen (tpl_node * r, int i); /* array len of packable i */ 127 | TPL_API char *tpl_peek (int mode, ...); /* sneak peek at format string */ 128 | TPL_API int tpl_gather (int mode, ...); /* non-blocking image gather */ 129 | TPL_API int tpl_jot (int mode, ...); /* quick write a simple tpl */ 130 | 131 | TPL_API tpl_node *tpl_map_va (char *fmt, va_list ap); 132 | 133 | #if defined __cplusplus 134 | } 135 | #endif 136 | #endif /* TPL_H */ 137 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef UTIL_H_INCLUDED 31 | #define UTIL_H_INCLUDED 32 | 33 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 34 | 35 | #define REGEX_ERROR 100 36 | 37 | #define KIB(n) (n << 10) 38 | #define MIB(n) (n << 20) 39 | #define GIB(n) (n << 30) 40 | #define TIB(n) (n << 40) 41 | #define PIB(n) (n << 50) 42 | 43 | #define MILS 1000ULL 44 | #define SECS 1000000ULL 45 | #define MINS 60000000ULL 46 | #define HOUR 3600000000ULL 47 | #define DAY 86400000000ULL 48 | #define TZ_NAME_LEN 48 49 | 50 | #define RAND_FN 7 + 1 51 | 52 | /* Convenient macros */ 53 | #define MIN(a,b) \ 54 | ({ __typeof__ (a) _a = (a); \ 55 | __typeof__ (b) _b = (b); \ 56 | _a < _b ? _a : _b; }) 57 | 58 | #define MAX(a,b) (((a)>(b))?(a):(b)) 59 | 60 | /* *INDENT-OFF* */ 61 | #include 62 | #include 63 | #include 64 | 65 | char *alloc_string (const char *str); 66 | char *char_repeat (int n, char c); 67 | char *char_replace (char *str, char o, char n); 68 | char *deblank (char *str); 69 | char *escape_str (const char *src); 70 | char *filesize_str (unsigned long long log_size); 71 | char *float2str (float d, int width); 72 | char *get_global_config (void); 73 | char *get_user_config (void); 74 | char *get_visitors_date (const char *odate, const char *from, const char *to); 75 | char *int2str (int d, int width); 76 | char *left_pad_str (const char *s, int indent); 77 | char *ltrim (char *s); 78 | char *regex_extract_string (const char *str, const char *regex, int max_groups, char const **err); 79 | char *rtrim (char *s); 80 | char *strtoupper (char *str); 81 | char *substring (const char *str, int begin, int len); 82 | char *trim_str (char *str); 83 | char *u322str (uint32_t d, int width); 84 | char *u642str (uint64_t d, int width); 85 | char *unescape_str (const char *src); 86 | char *usecs_to_str (unsigned long long usec); 87 | const char *verify_status_code (int code); 88 | const char *verify_status_code_type (int code); 89 | int convert_date (char *res, const char *data, const char *from, const char *to, int size); 90 | int count_matches (const char *s1, char c); 91 | int find_output_type (char **filename, const char *ext, int alloc); 92 | int hide_referer (const char *host); 93 | int ignore_referer (const char *host); 94 | int intlen (uint64_t num); 95 | int invalid_ipaddr (const char *str, int *ipvx); 96 | int ip_in_range (const char *ip); 97 | int is_valid_http_status (int code); 98 | int is_writable_path (const char *path); 99 | int ptr2int (char *ptr); 100 | int str2int (const char *date); 101 | int str_inarray (const char *s, const char *arr[], int size); 102 | int str_to_time (const char *str, const char *fmt, struct tm *tm, int tz); 103 | int valid_output_type (const char *filename); 104 | off_t file_size (const char *filename); 105 | size_t append_str (char **dest, const char *src); 106 | uint32_t djb2 (const unsigned char *str); 107 | uint64_t u64encode (uint32_t x, uint32_t y); 108 | void decode_hex(char *url, char *out, int decode_plus); 109 | void genstr (char *dest, size_t len); 110 | void set_tz (void); 111 | void strip_newlines (char *str); 112 | void u64decode (uint64_t n, uint32_t * x, uint32_t * y); 113 | void xstrncpy (char *dest, const char *source, const size_t dest_size); 114 | 115 | /* *INDENT-ON* */ 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/win/mman.h: -------------------------------------------------------------------------------- 1 | #ifndef _MMAN_H_ 2 | #define _MMAN_H_ 3 | 4 | /* Protections */ 5 | #define PROT_NONE 0x00 /* no permissions */ 6 | #define PROT_READ 0x01 /* pages can be read */ 7 | #define PROT_WRITE 0x02 /* pages can be written */ 8 | #define PROT_EXEC 0x04 /* pages can be executed */ 9 | 10 | /* Sharing type and options */ 11 | #define MAP_SHARED 0x0001 /* share changes */ 12 | #define MAP_PRIVATE 0x0002 /* changes are private */ 13 | #define MAP_COPY MAP_PRIVATE /* Obsolete */ 14 | #define MAP_FIXED 0x0010 /* map addr must be exactly as requested */ 15 | #define MAP_RENAME 0x0020 /* Sun: rename private pages to file */ 16 | #define MAP_NORESERVE 0x0040 /* Sun: don't reserve needed swap area */ 17 | #define MAP_INHERIT 0x0080 /* region is retained after exec */ 18 | #define MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change file size */ 19 | #define MAP_HASSEMAPHORE 0x0200 /* region may contain semaphores */ 20 | #define MAP_STACK 0x0400 /* region grows down, like a stack */ 21 | 22 | /* Error returned from mmap() */ 23 | #define MAP_FAILED ((void *)-1) 24 | 25 | /* Flags to msync */ 26 | #define MS_ASYNC 0x01 /* perform asynchronous writes */ 27 | #define MS_SYNC 0x02 /* perform synchronous writes */ 28 | #define MS_INVALIDATE 0x04 /* invalidate cached data */ 29 | 30 | /* File modes for 'open' not defined in MinGW32 (not used by mmap) */ 31 | #ifndef S_IWGRP 32 | #define S_IWGRP 0 33 | #define S_IRGRP 0 34 | #define S_IROTH 0 35 | #endif 36 | 37 | /** 38 | * Map a file to a memory region 39 | */ 40 | void *mmap (void *addr, unsigned int len, int prot, int flags, int fd, unsigned int offset); 41 | 42 | /** 43 | * Unmap a memory region 44 | */ 45 | int munmap (void *addr, int len); 46 | 47 | /** 48 | * Synchronize a mapped region 49 | */ 50 | int msync (char *addr, int len, int flags); 51 | 52 | #endif /* _MMAN_H_ */ 53 | -------------------------------------------------------------------------------- /src/win/mmap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifdef _WIN32 4 | #include 5 | #endif 6 | #include 7 | #include "mman.h" 8 | 9 | static const char id[] = "$Id: tpl.c 107 2007-04-20 17:11:29Z thanson $"; 10 | 11 | /** 12 | * @brief Map a file to a memory region 13 | * 14 | * This function emulates the POSIX mmap() using CreateFileMapping() and 15 | * MapViewOfFile() 16 | * 17 | * @param addr the suggested start address (if != 0) 18 | * @param len length of the region 19 | * @param prot region accessibility, bitwise OR of PROT_READ, PROT_WRITE, PROT_EXEC 20 | * @param flags mapping type and options (ignored) 21 | * @param fd object to be mapped into memory 22 | * @param offset offset into mapped object 23 | * @return pointer to the memory region, or NULL in case of error 24 | */ 25 | void * 26 | mmap (void *addr, unsigned int len, int prot, int flags, int fd, unsigned int offset) { 27 | DWORD wprot; 28 | DWORD waccess; 29 | HANDLE h; 30 | void *region; 31 | 32 | /* Translate read/write/exec flags into WIN32 constants */ 33 | switch (prot) { 34 | case PROT_READ: 35 | wprot = PAGE_READONLY; 36 | break; 37 | case PROT_EXEC: 38 | wprot = PAGE_EXECUTE_READ; 39 | break; 40 | case PROT_READ | PROT_EXEC: 41 | wprot = PAGE_EXECUTE_READ; 42 | break; 43 | case PROT_WRITE: 44 | wprot = PAGE_READWRITE; 45 | break; 46 | case PROT_READ | PROT_WRITE: 47 | wprot = PAGE_READWRITE; 48 | break; 49 | case PROT_READ | PROT_WRITE | PROT_EXEC: 50 | wprot = PAGE_EXECUTE_READWRITE; 51 | break; 52 | case PROT_WRITE | PROT_EXEC: 53 | wprot = PAGE_EXECUTE_READWRITE; 54 | break; 55 | } 56 | 57 | /* Obtaing handle to map region */ 58 | h = CreateFileMapping ((HANDLE) _get_osfhandle (fd), 0, wprot, 0, len, 0); 59 | if (h == NULL) { 60 | DWORD error = GetLastError (); 61 | 62 | /* Try and translate some error codes */ 63 | switch (error) { 64 | case ERROR_ACCESS_DENIED: 65 | case ERROR_INVALID_ACCESS: 66 | errno = EACCES; 67 | break; 68 | case ERROR_OUTOFMEMORY: 69 | case ERROR_NOT_ENOUGH_MEMORY: 70 | errno = ENOMEM; 71 | break; 72 | default: 73 | errno = EINVAL; 74 | break; 75 | } 76 | return MAP_FAILED; 77 | } 78 | 79 | 80 | /* Translate sharing options into WIN32 constants */ 81 | switch (wprot) { 82 | case PAGE_READONLY: 83 | waccess = FILE_MAP_READ; 84 | break; 85 | case PAGE_READWRITE: 86 | waccess = FILE_MAP_WRITE; 87 | break; 88 | } 89 | 90 | /* Map file and return pointer */ 91 | region = MapViewOfFile (h, waccess, 0, 0, 0); 92 | if (region == NULL) { 93 | DWORD error = GetLastError (); 94 | 95 | /* Try and translate some error codes */ 96 | switch (error) { 97 | case ERROR_ACCESS_DENIED: 98 | case ERROR_INVALID_ACCESS: 99 | errno = EACCES; 100 | break; 101 | case ERROR_INVALID_HANDLE: 102 | errno = EBADF; 103 | break; 104 | default: 105 | errno = EINVAL; 106 | break; 107 | } 108 | CloseHandle (h); 109 | return MAP_FAILED; 110 | } 111 | CloseHandle (h); /* ok to call UnmapViewOfFile after this */ 112 | 113 | /* All fine */ 114 | return region; 115 | } 116 | 117 | 118 | /** 119 | * @brief Unmap a memory region 120 | * 121 | * This is a wrapper around UnmapViewOfFile in the win32 API 122 | * 123 | * @param addr start address 124 | * @param len length of the region 125 | * @return 0 for success, -1 for error 126 | */ 127 | int 128 | munmap (void *addr, int len) { 129 | if (UnmapViewOfFile (addr)) { 130 | return 0; 131 | } else { 132 | errno = EINVAL; 133 | return -1; 134 | } 135 | } 136 | 137 | 138 | /** 139 | * Synchronize a mapped region 140 | * 141 | * This is a wrapper around FlushViewOfFile 142 | * 143 | * @param addr start address 144 | * @param len number of bytes to flush 145 | * @param flags sync options -- currently ignored 146 | * @return 0 for success, -1 for error 147 | */ 148 | int 149 | msync (char *addr, int len, int flags) { 150 | if (FlushViewOfFile (addr, len) == 0) { 151 | DWORD error = GetLastError (); 152 | 153 | /* Try and translate some error codes */ 154 | switch (error) { 155 | case ERROR_INVALID_PARAMETER: 156 | errno = EINVAL; 157 | break; 158 | case ERROR_WRITE_FAULT: 159 | errno = EIO; 160 | break; 161 | default: 162 | errno = EINVAL; 163 | break; 164 | } 165 | return -1; 166 | } 167 | 168 | /* Success */ 169 | return 0; 170 | } 171 | -------------------------------------------------------------------------------- /src/wsauth.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef WSAUTH_H_INCLUDED 31 | #define WSAUTH_H_INCLUDED 32 | 33 | #define MAX_SECRET_SIZE 256 34 | #define MAX_JWT_PAYLOAD 512 35 | #define DEFAULT_EXPIRE_TIME 28800 // seconds 36 | 37 | char *create_jwt_token (void); 38 | char *generate_jwt (const char *secret, const char *payload); 39 | char *generate_ws_auth_secret (void); 40 | char *read_secret_from_file (const char *path); 41 | int verify_jwt_token (const char *jwt, const char *secret); 42 | 43 | #endif // for #ifndef WSAUTH_H 44 | -------------------------------------------------------------------------------- /src/xmalloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * xmalloc.c -- *alloc functions with error handling 3 | * ______ ___ 4 | * / ____/___ / | _____________ __________ 5 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 6 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 7 | * \____/\____/_/ |_\___/\___/\___/____/____/ 8 | * 9 | * The MIT License (MIT) 10 | * Copyright (c) 2009-2025 Gerardo Orellana 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #if !defined __SUNPRO_C 33 | #include 34 | #endif 35 | #include 36 | #include 37 | 38 | #include "error.h" 39 | #include "xmalloc.h" 40 | 41 | /* Self-checking wrapper to malloc() */ 42 | void * 43 | xmalloc (size_t size) { 44 | void *ptr; 45 | 46 | if ((ptr = malloc (size)) == NULL) 47 | FATAL ("Unable to allocate memory - failed."); 48 | 49 | return (ptr); 50 | } 51 | 52 | char * 53 | xstrdup (const char *s) { 54 | char *ptr; 55 | size_t len; 56 | 57 | len = strlen (s) + 1; 58 | ptr = xmalloc (len); 59 | 60 | strncpy (ptr, s, len); 61 | return (ptr); 62 | } 63 | 64 | /* Self-checking wrapper to calloc() */ 65 | void * 66 | xcalloc (size_t nmemb, size_t size) { 67 | void *ptr; 68 | 69 | if ((ptr = calloc (nmemb, size)) == NULL) 70 | FATAL ("Unable to calloc memory - failed."); 71 | 72 | return (ptr); 73 | } 74 | 75 | /* Self-checking wrapper to realloc() */ 76 | void * 77 | xrealloc (void *oldptr, size_t size) { 78 | void *newptr; 79 | 80 | if ((newptr = realloc (oldptr, size)) == NULL) 81 | FATAL ("Unable to reallocate memory - failed"); 82 | 83 | return (newptr); 84 | } 85 | -------------------------------------------------------------------------------- /src/xmalloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ______ ___ 3 | * / ____/___ / | _____________ __________ 4 | * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ 5 | * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) 6 | * \____/\____/_/ |_\___/\___/\___/____/____/ 7 | * 8 | * The MIT License (MIT) 9 | * Copyright (c) 2009-2025 Gerardo Orellana 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef XMALLOC_H_INCLUDED 31 | #define XMALLOC_H_INCLUDED 32 | 33 | char *xstrdup (const char *s); 34 | void *xcalloc (size_t nmemb, size_t size); 35 | void *xmalloc (size_t size); 36 | void *xrealloc (void *oldptr, size_t size); 37 | 38 | #endif 39 | --------------------------------------------------------------------------------