mirror of
https://github.com/epi052/feroxbuster.git
synced 2026-06-07 18:21:13 -03:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d57a83956c | ||
|
|
71efd78f03 | ||
|
|
139006d0a7 | ||
|
|
b5abb8b6e8 | ||
|
|
a076a333df | ||
|
|
461ed0a9ff | ||
|
|
4381569a0f | ||
|
|
a52bd10340 | ||
|
|
56a1144865 | ||
|
|
23ab009c08 | ||
|
|
fa4e3d5d88 | ||
|
|
ad7a1ffe44 | ||
|
|
0e4f8893f8 | ||
|
|
8e0b801ec5 | ||
|
|
97889f917d | ||
|
|
cedb3ccc8d | ||
|
|
d7cfd8ff60 | ||
|
|
223e75923d | ||
|
|
dd9f2f72c0 | ||
|
|
8ffea2500d | ||
|
|
5ed890e3fd | ||
|
|
8fe458263d | ||
|
|
6de36585a9 | ||
|
|
30538c366c | ||
|
|
89a0ac8aa4 |
5
.cargo/config
Normal file
5
.cargo/config
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[target.armv7-unknown-linux-gnueabihf]
|
||||||
|
linker = "arm-linux-gnueabihf-gcc"
|
||||||
|
|
||||||
|
[target.aarch64-unknown-linux-gnu]
|
||||||
|
linker = "aarch64-linux-gnu-gcc"
|
||||||
18
.github/workflows/build.yml
vendored
18
.github/workflows/build.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
|||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
type: [ubuntu-x64, ubuntu-x86]
|
type: [ubuntu-x64, ubuntu-x86, armv7, aarch64]
|
||||||
include:
|
include:
|
||||||
- type: ubuntu-x64
|
- type: ubuntu-x64
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
@@ -22,12 +22,24 @@ jobs:
|
|||||||
name: x86-linux-feroxbuster
|
name: x86-linux-feroxbuster
|
||||||
path: target/i686-unknown-linux-musl/release/feroxbuster
|
path: target/i686-unknown-linux-musl/release/feroxbuster
|
||||||
pkg_config_path: /usr/lib/i686-linux-gnu/pkgconfig
|
pkg_config_path: /usr/lib/i686-linux-gnu/pkgconfig
|
||||||
|
- type: armv7
|
||||||
|
os: ubuntu-latest
|
||||||
|
target: armv7-unknown-linux-gnueabihf
|
||||||
|
name: armv7-feroxbuster
|
||||||
|
path: target/armv7-unknown-linux-gnueabihf/release/feroxbuster
|
||||||
|
pkg_config_path: /usr/lib/x86_64-linux-gnu/pkgconfig
|
||||||
|
- type: aarch64
|
||||||
|
os: ubuntu-latest
|
||||||
|
target: aarch64-unknown-linux-gnu
|
||||||
|
name: aarch64-feroxbuster
|
||||||
|
path: target/aarch64-unknown-linux-gnu/release/feroxbuster
|
||||||
|
pkg_config_path: /usr/lib/x86_64-linux-gnu/pkgconfig
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install System Dependencies
|
- name: Install System Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends libssl-dev pkg-config
|
sudo apt-get install -y --no-install-recommends libssl-dev pkg-config gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
@@ -43,7 +55,7 @@ jobs:
|
|||||||
args: --release --target=${{ matrix.target }}
|
args: --release --target=${{ matrix.target }}
|
||||||
- name: Strip symbols from binary
|
- name: Strip symbols from binary
|
||||||
run: |
|
run: |
|
||||||
strip -s ${{ matrix.path }}
|
strip -s ${{ matrix.path }} || arm-linux-gnueabihf-strip -s ${{ matrix.path }} || aarch64-linux-gnu-strip -s ${{ matrix.path }}
|
||||||
- name: Build tar.gz for homebrew installs
|
- name: Build tar.gz for homebrew installs
|
||||||
if: matrix.type == 'ubuntu-x64'
|
if: matrix.type == 'ubuntu-x64'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
59
Cargo.lock
generated
59
Cargo.lock
generated
@@ -473,9 +473,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.1.7"
|
version = "3.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b57a92e9749e10f25a171adcebfafe72991d45e7ec2dcb853e8f83d9dafaeb08"
|
checksum = "c15b8ec3b5755a188c141c1f6a98e76de31b936209bf066b647979e2a84764a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -633,7 +633,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "feroxbuster"
|
name = "feroxbuster"
|
||||||
version = "2.2.1"
|
version = "2.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
@@ -724,9 +724,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150"
|
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -739,9 +739,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846"
|
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@@ -749,15 +749,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65"
|
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9"
|
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@@ -766,9 +766,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500"
|
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
@@ -787,9 +787,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
|
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -799,24 +799,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6"
|
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86"
|
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b"
|
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -1298,13 +1295,13 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.18.0"
|
version = "0.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055"
|
checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1753,9 +1750,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rlimit"
|
name = "rlimit"
|
||||||
version = "0.5.3"
|
version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e7148757b4951f04391d2b301b2e3597d504c4d2434212d542b73c1a6b3f847"
|
checksum = "81a9ed03edbed449d6897c2092c71ab5f7b5fb80f6f0b1a3ed6d40a6f9fc0720"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -1839,9 +1836,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.62"
|
version = "1.0.64"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
|||||||
13
Cargo.toml
13
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "feroxbuster"
|
name = "feroxbuster"
|
||||||
version = "2.2.1"
|
version = "2.2.3"
|
||||||
authors = ["Ben 'epi' Risher <epibar052@gmail.com>"]
|
authors = ["Ben 'epi' Risher <epibar052@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
@@ -21,7 +21,7 @@ regex = "1"
|
|||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = { version = "0.3"}
|
futures = { version = "0.3.13"}
|
||||||
tokio = { version = "1.2.0", features = ["full"] }
|
tokio = { version = "1.2.0", features = ["full"] }
|
||||||
tokio-util = {version = "0.6.3", features = ["codec"]}
|
tokio-util = {version = "0.6.3", features = ["codec"]}
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
@@ -31,7 +31,7 @@ clap = "2.33"
|
|||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||||
serde_json = "1.0.62"
|
serde_json = "1.0.64"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
indicatif = "0.15"
|
indicatif = "0.15"
|
||||||
console = "0.14"
|
console = "0.14"
|
||||||
@@ -39,8 +39,8 @@ openssl = { version = "0.10", features = ["vendored"] }
|
|||||||
dirs = "3.0"
|
dirs = "3.0"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
crossterm = "0.19"
|
crossterm = "0.19"
|
||||||
rlimit = "0.5"
|
rlimit = "0.5.4"
|
||||||
ctrlc = "3.1"
|
ctrlc = "3.1.8"
|
||||||
fuzzyhash = "0.2.1"
|
fuzzyhash = "0.2.1"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
leaky-bucket = "0.10.0"
|
leaky-bucket = "0.10.0"
|
||||||
@@ -63,4 +63,7 @@ conf-files = ["/etc/feroxbuster/ferox-config.toml"]
|
|||||||
assets = [
|
assets = [
|
||||||
["target/release/feroxbuster", "/usr/bin/", "755"],
|
["target/release/feroxbuster", "/usr/bin/", "755"],
|
||||||
["ferox-config.toml.example", "/etc/feroxbuster/ferox-config.toml", "644"],
|
["ferox-config.toml.example", "/etc/feroxbuster/ferox-config.toml", "644"],
|
||||||
|
["shell_completions/feroxbuster.bash", "/usr/share/bash-completion/completions/feroxbuster.bash", "644"],
|
||||||
|
["shell_completions/feroxbuster.fish", "/usr/share/fish/completions/feroxbuster.fish", "644"],
|
||||||
|
["shell_completions/_feroxbuster", "/usr/share/zsh/vendor-completions/_feroxbuster", "644"],
|
||||||
]
|
]
|
||||||
|
|||||||
47
Makefile
47
Makefile
@@ -6,12 +6,16 @@ datarootdir = $(prefix)/share
|
|||||||
datadir = $(datarootdir)
|
datadir = $(datarootdir)
|
||||||
example_config = ferox-config.toml.example
|
example_config = ferox-config.toml.example
|
||||||
config_file = ferox-config.toml
|
config_file = ferox-config.toml
|
||||||
|
completion_dir = shell_completions
|
||||||
|
completion_prefix = $(completion_dir)/$(BIN)
|
||||||
|
|
||||||
|
BIN=feroxbuster
|
||||||
SHR_SOURCES = $(shell find src -type f -wholename '*src/*.rs') Cargo.toml Cargo.lock
|
SHR_SOURCES = $(shell find src -type f -wholename '*src/*.rs') Cargo.toml Cargo.lock
|
||||||
|
|
||||||
RELEASE = debug
|
RELEASE = debug
|
||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
ifeq (0,$(DEBUG))
|
|
||||||
|
ifeq (0, $(DEBUG))
|
||||||
ARGS = --release
|
ARGS = --release
|
||||||
RELEASE = release
|
RELEASE = release
|
||||||
endif
|
endif
|
||||||
@@ -23,54 +27,47 @@ endif
|
|||||||
|
|
||||||
TARGET = target/$(RELEASE)
|
TARGET = target/$(RELEASE)
|
||||||
|
|
||||||
.PHONY: all clean distclean install uninstall update
|
.PHONY: all clean install uninstall
|
||||||
|
|
||||||
BIN=feroxbuster
|
|
||||||
DESKTOP=$(APPID).desktop
|
|
||||||
|
|
||||||
all: cli
|
all: cli
|
||||||
|
|
||||||
cli: $(TARGET)/$(BIN) $(TARGET)/$(BIN).1.gz $(SHR_SOURCES)
|
cli: $(TARGET)/$(BIN) $(TARGET)/$(BIN).1.gz $(SHR_SOURCES)
|
||||||
|
install: all install-cli
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cargo clean
|
cargo clean
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
rm -rf .cargo vendor Cargo.lock vendor.tar
|
|
||||||
|
|
||||||
vendor: vendor.tar
|
vendor: vendor.tar
|
||||||
|
|
||||||
vendor.tar:
|
vendor.tar:
|
||||||
mkdir -p .cargo
|
cargo vendor
|
||||||
cargo vendor | head -n -1 > .cargo/config
|
|
||||||
echo 'directory = "vendor"' >> .cargo/config
|
|
||||||
tar pcf vendor.tar vendor
|
tar pcf vendor.tar vendor
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
|
|
||||||
install-cli: cli
|
install-cli: cli
|
||||||
install -Dm 0755 "$(TARGET)/$(BIN)" "$(DESTDIR)$(bindir)/$(BIN)"
|
install -Dm 0644 "$(completion_prefix).bash" "$(DESTDIR)/usr/share/bash-completion/completions/$(BIN).bash"
|
||||||
|
install -Dm 0644 "$(completion_prefix).fish" "$(DESTDIR)/usr/share/fish/completions/$(BIN).fish"
|
||||||
|
install -Dm 0644 "$(completion_dir)/_$(BIN)" "$(DESTDIR)/usr/share/zsh/vendor-completions/_$(BIN)"
|
||||||
|
install -sDm 0755 "$(TARGET)/$(BIN)" "$(DESTDIR)$(bindir)/$(BIN)"
|
||||||
install -Dm 0644 "$(TARGET)/$(BIN).1.gz" "$(DESTDIR)$(datadir)/man/man1/$(BIN).1.gz"
|
install -Dm 0644 "$(TARGET)/$(BIN).1.gz" "$(DESTDIR)$(datadir)/man/man1/$(BIN).1.gz"
|
||||||
install -Dm 0644 "$(example_config)" "/etc/$(BIN)/$(config_File)"
|
install -Dm 0644 "$(example_config)" "$(DESTDIR)/etc/$(BIN)/$(config_file)"
|
||||||
|
|
||||||
install: all install-cli
|
uninstall:
|
||||||
|
|
||||||
uninstall-cli:
|
|
||||||
rm -f "$(DESTDIR)$(bindir)/$(BIN)"
|
rm -f "$(DESTDIR)$(bindir)/$(BIN)"
|
||||||
rm -f "$(DESTDIR)$(datadir)/man/man1/$(BIN).1.gz"
|
rm -f "$(DESTDIR)$(datadir)/man/man1/$(BIN).1.gz"
|
||||||
rm -rf "/etc/$(BIN)/"
|
rm -rf "$(DESTDIR)/etc/$(BIN)/"
|
||||||
|
rm -f "$(DESTDIR)/usr/share/bash-completion/completions/$(BIN).bash"
|
||||||
uninstall: uninstall-cli
|
rm -f "$(DESTDIR)/usr/share/zsh/vendor-completions/_$(BIN)"
|
||||||
|
rm -f "$(DESTDIR)/usr/share/fish/completions/$(BIN).fish"
|
||||||
update:
|
|
||||||
cargo update
|
|
||||||
|
|
||||||
extract:
|
extract:
|
||||||
ifeq ($(VENDORED),1)
|
ifeq (1, $(VENDORED))
|
||||||
tar pxf vendor.tar
|
tar pxf vendor.tar
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(TARGET)/$(BIN): extract
|
$(TARGET)/$(BIN): extract
|
||||||
cargo build --manifest-path Cargo.toml $(ARGS)
|
mkdir -p .cargo
|
||||||
|
cp debian/cargo.config .cargo/config.toml
|
||||||
|
cargo build $(ARGS)
|
||||||
|
|
||||||
$(TARGET)/$(BIN).1.gz: $(TARGET)/$(BIN)
|
$(TARGET)/$(BIN).1.gz: $(TARGET)/$(BIN)
|
||||||
help2man --no-info $< | gzip -c > $@.partial
|
help2man --no-info $< | gzip -c > $@.partial
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -70,6 +70,7 @@ Enumeration.
|
|||||||
- [Snap Install](#snap-install)
|
- [Snap Install](#snap-install)
|
||||||
- [Homebrew on MacOS and Linux](#homebrew-on-macos-and-linux)
|
- [Homebrew on MacOS and Linux](#homebrew-on-macos-and-linux)
|
||||||
- [Cargo Install](#cargo-install)
|
- [Cargo Install](#cargo-install)
|
||||||
|
- [Kali Install](#kali-install)
|
||||||
- [apt Install](#apt-install)
|
- [apt Install](#apt-install)
|
||||||
- [AUR Install](#aur-install)
|
- [AUR Install](#aur-install)
|
||||||
- [Docker Install](#docker-install)
|
- [Docker Install](#docker-install)
|
||||||
@@ -118,8 +119,9 @@ Enumeration.
|
|||||||
|
|
||||||
### Download a Release
|
### Download a Release
|
||||||
|
|
||||||
Releases for multiple architectures can be found in the [Releases](https://github.com/epi052/feroxbuster/releases)
|
Releases for `armv7`, `aarch64`, and an `x86_64 .deb` can be found in the [Releases](https://github.com/epi052/feroxbuster/releases) section.
|
||||||
section. The latest release for each of the following systems can be downloaded and executed as shown below.
|
|
||||||
|
All other OS/architecture combinations can be installed dynamically using one of the methods shown below.
|
||||||
|
|
||||||
#### Linux (32 and 64-bit) & MacOS
|
#### Linux (32 and 64-bit) & MacOS
|
||||||
|
|
||||||
@@ -194,6 +196,16 @@ brew install feroxbuster
|
|||||||
cargo install feroxbuster
|
cargo install feroxbuster
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Kali Install
|
||||||
|
|
||||||
|
🥳 `feroxbuster` was recently added to the official Kali Linux repos 🥳
|
||||||
|
|
||||||
|
If you're using kali, this is the preferred install method. Installing from the repos adds a [**ferox-config.toml**](#ferox-config.toml) in `/etc/feroxbuster/`, adds command completion for bash, fish, and zsh, includes a man page entry, and installs `feroxbuster` itself.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt update && sudo apt install -y feroxbuster
|
||||||
|
```
|
||||||
|
|
||||||
### apt Install
|
### apt Install
|
||||||
|
|
||||||
Download `feroxbuster_amd64.deb` from the [Releases](https://github.com/epi052/feroxbuster/releases) section. After
|
Download `feroxbuster_amd64.deb` from the [Releases](https://github.com/epi052/feroxbuster/releases) section. After
|
||||||
@@ -949,7 +961,7 @@ few of the use-cases in which feroxbuster may be a better fit:
|
|||||||
| fast | ✔ | ✔ | ✔ |
|
| fast | ✔ | ✔ | ✔ |
|
||||||
| allows recursion | ✔ | | ✔ |
|
| allows recursion | ✔ | | ✔ |
|
||||||
| can specify query parameters | ✔ | | ✔ |
|
| can specify query parameters | ✔ | | ✔ |
|
||||||
| SOCKS proxy support | ✔ | | |
|
| SOCKS proxy support | ✔ | | ✔ |
|
||||||
| multiple target scan (via stdin or multiple -u) | ✔ | | ✔ |
|
| multiple target scan (via stdin or multiple -u) | ✔ | | ✔ |
|
||||||
| configuration file for default value override | ✔ | | ✔ |
|
| configuration file for default value override | ✔ | | ✔ |
|
||||||
| can accept urls via STDIN as part of a pipeline | ✔ | | ✔ |
|
| can accept urls via STDIN as part of a pipeline | ✔ | | ✔ |
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
@@ -53,7 +52,7 @@ pub enum Command {
|
|||||||
TryRecursion(Box<FeroxResponse>),
|
TryRecursion(Box<FeroxResponse>),
|
||||||
|
|
||||||
/// Send a pointer to the wordlist to the recursion handler
|
/// Send a pointer to the wordlist to the recursion handler
|
||||||
UpdateWordlist(Arc<HashSet<String>>),
|
UpdateWordlist(Arc<Vec<String>>),
|
||||||
|
|
||||||
/// Instruct the ScanHandler to join on all known scans, use sender to notify main when done
|
/// Instruct the ScanHandler to join on all known scans, use sender to notify main when done
|
||||||
JoinTasks(Sender<bool>),
|
JoinTasks(Sender<bool>),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
@@ -54,7 +53,7 @@ pub struct ScanHandler {
|
|||||||
receiver: CommandReceiver,
|
receiver: CommandReceiver,
|
||||||
|
|
||||||
/// wordlist (re)used for each scan
|
/// wordlist (re)used for each scan
|
||||||
wordlist: std::sync::Mutex<Option<Arc<HashSet<String>>>>,
|
wordlist: std::sync::Mutex<Option<Arc<Vec<String>>>>,
|
||||||
|
|
||||||
/// group of scans that need to be joined
|
/// group of scans that need to be joined
|
||||||
tasks: Vec<Arc<FeroxScan>>,
|
tasks: Vec<Arc<FeroxScan>>,
|
||||||
@@ -105,7 +104,7 @@ impl ScanHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the wordlist
|
/// Set the wordlist
|
||||||
fn wordlist(&self, wordlist: Arc<HashSet<String>>) {
|
fn wordlist(&self, wordlist: Arc<Vec<String>>) {
|
||||||
if let Ok(mut guard) = self.wordlist.lock() {
|
if let Ok(mut guard) = self.wordlist.lock() {
|
||||||
if guard.is_none() {
|
if guard.is_none() {
|
||||||
let _ = std::mem::replace(&mut *guard, Some(wordlist));
|
let _ = std::mem::replace(&mut *guard, Some(wordlist));
|
||||||
@@ -175,7 +174,7 @@ impl ScanHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper to easily get the (locked) underlying wordlist
|
/// Helper to easily get the (locked) underlying wordlist
|
||||||
pub fn get_wordlist(&self) -> Result<Arc<HashSet<String>>> {
|
pub fn get_wordlist(&self) -> Result<Arc<Vec<String>>> {
|
||||||
if let Ok(guard) = self.wordlist.lock().as_ref() {
|
if let Ok(guard) = self.wordlist.lock().as_ref() {
|
||||||
if let Some(list) = guard.as_ref() {
|
if let Some(list) = guard.as_ref() {
|
||||||
return Ok(list.clone());
|
return Ok(list.clone());
|
||||||
|
|||||||
13
src/main.rs
13
src/main.rs
@@ -1,5 +1,4 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
|
||||||
env::args,
|
env::args,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{stderr, BufRead, BufReader},
|
io::{stderr, BufRead, BufReader},
|
||||||
@@ -41,14 +40,14 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a HashSet of Strings from the given wordlist then stores it inside an Arc
|
/// Create a HashSet of Strings from the given wordlist then stores it inside an Arc
|
||||||
fn get_unique_words_from_wordlist(path: &str) -> Result<Arc<HashSet<String>>> {
|
fn get_unique_words_from_wordlist(path: &str) -> Result<Arc<Vec<String>>> {
|
||||||
log::trace!("enter: get_unique_words_from_wordlist({})", path);
|
log::trace!("enter: get_unique_words_from_wordlist({})", path);
|
||||||
|
|
||||||
let file = File::open(&path).with_context(|| format!("Could not open {}", path))?;
|
let file = File::open(&path).with_context(|| format!("Could not open {}", path))?;
|
||||||
|
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
|
|
||||||
let mut words = HashSet::new();
|
let mut words = Vec::new();
|
||||||
|
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
let result = match line {
|
let result = match line {
|
||||||
@@ -60,7 +59,7 @@ fn get_unique_words_from_wordlist(path: &str) -> Result<Arc<HashSet<String>>> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
words.insert(result);
|
words.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
@@ -78,11 +77,7 @@ async fn scan(targets: Vec<String>, handles: Arc<Handles>) -> Result<()> {
|
|||||||
// so that will allow for cheap/safe sharing of a single wordlist across multi-target scans
|
// so that will allow for cheap/safe sharing of a single wordlist across multi-target scans
|
||||||
// as well as additional directories found as part of recursion
|
// as well as additional directories found as part of recursion
|
||||||
|
|
||||||
let words = {
|
let words = get_unique_words_from_wordlist(&handles.config.wordlist)?;
|
||||||
let words_handles = handles.clone();
|
|
||||||
tokio::spawn(async move { get_unique_words_from_wordlist(&words_handles.config.wordlist) })
|
|
||||||
.await??
|
|
||||||
};
|
|
||||||
|
|
||||||
if words.len() == 0 {
|
if words.len() == 0 {
|
||||||
bail!("Did not find any words in {}", handles.config.wordlist);
|
bail!("Did not find any words in {}", handles.config.wordlist);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashSet, ops::Deref, sync::atomic::Ordering, sync::Arc, time::Instant};
|
use std::{ops::Deref, sync::atomic::Ordering, sync::Arc, time::Instant};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use futures::{stream, StreamExt};
|
use futures::{stream, StreamExt};
|
||||||
@@ -40,7 +40,7 @@ pub struct FeroxScanner {
|
|||||||
order: ScanOrder,
|
order: ScanOrder,
|
||||||
|
|
||||||
/// wordlist that's already been read from disk
|
/// wordlist that's already been read from disk
|
||||||
wordlist: Arc<HashSet<String>>,
|
wordlist: Arc<Vec<String>>,
|
||||||
|
|
||||||
/// limiter that restricts the number of active FeroxScanners
|
/// limiter that restricts the number of active FeroxScanners
|
||||||
scan_limiter: Arc<Semaphore>,
|
scan_limiter: Arc<Semaphore>,
|
||||||
@@ -52,7 +52,7 @@ impl FeroxScanner {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
target_url: &str,
|
target_url: &str,
|
||||||
order: ScanOrder,
|
order: ScanOrder,
|
||||||
wordlist: Arc<HashSet<String>>,
|
wordlist: Arc<Vec<String>>,
|
||||||
scan_limiter: Arc<Semaphore>,
|
scan_limiter: Arc<Semaphore>,
|
||||||
handles: Arc<Handles>,
|
handles: Arc<Handles>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
convert::TryFrom,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::BufReader,
|
io::BufReader,
|
||||||
sync::{
|
sync::{
|
||||||
@@ -9,7 +11,8 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
traits::FeroxSerialize,
|
traits::FeroxSerialize,
|
||||||
@@ -19,9 +22,8 @@ use crate::{
|
|||||||
use super::{error::StatError, field::StatField};
|
use super::{error::StatError, field::StatField};
|
||||||
|
|
||||||
/// Data collection of statistics related to a scan
|
/// Data collection of statistics related to a scan
|
||||||
#[derive(Default, Deserialize, Debug, Serialize)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
#[serde(rename = "type")]
|
|
||||||
/// Name of this type of struct, used for serialization, i.e. `{"type":"statistics"}`
|
/// Name of this type of struct, used for serialization, i.e. `{"type":"statistics"}`
|
||||||
kind: String,
|
kind: String,
|
||||||
|
|
||||||
@@ -125,11 +127,9 @@ pub struct Stats {
|
|||||||
total_runtime: Mutex<Vec<f64>>,
|
total_runtime: Mutex<Vec<f64>>,
|
||||||
|
|
||||||
/// tracker for the number of extensions the user specified
|
/// tracker for the number of extensions the user specified
|
||||||
#[serde(skip)]
|
|
||||||
num_extensions: usize,
|
num_extensions: usize,
|
||||||
|
|
||||||
/// tracker for whether to use json during serialization or not
|
/// tracker for whether to use json during serialization or not
|
||||||
#[serde(skip)]
|
|
||||||
json: bool,
|
json: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +147,301 @@ impl FeroxSerialize for Stats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serialize implementation for Stats
|
||||||
|
impl Serialize for Stats {
|
||||||
|
/// Function that handles serialization of Stats
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut state = serializer.serialize_struct("Stats", 32)?;
|
||||||
|
|
||||||
|
state.serialize_field("type", &self.kind)?;
|
||||||
|
state.serialize_field("timeouts", &atomic_load!(self.timeouts))?;
|
||||||
|
state.serialize_field("requests", &atomic_load!(self.requests))?;
|
||||||
|
state.serialize_field("expected_per_scan", &atomic_load!(self.expected_per_scan))?;
|
||||||
|
state.serialize_field("total_expected", &atomic_load!(self.total_expected))?;
|
||||||
|
state.serialize_field("errors", &atomic_load!(self.errors))?;
|
||||||
|
state.serialize_field("successes", &atomic_load!(self.successes))?;
|
||||||
|
state.serialize_field("redirects", &atomic_load!(self.redirects))?;
|
||||||
|
state.serialize_field("client_errors", &atomic_load!(self.client_errors))?;
|
||||||
|
state.serialize_field("server_errors", &atomic_load!(self.server_errors))?;
|
||||||
|
state.serialize_field("total_scans", &atomic_load!(self.total_scans))?;
|
||||||
|
state.serialize_field("initial_targets", &atomic_load!(self.initial_targets))?;
|
||||||
|
state.serialize_field("links_extracted", &atomic_load!(self.links_extracted))?;
|
||||||
|
state.serialize_field("status_200s", &atomic_load!(self.status_200s))?;
|
||||||
|
state.serialize_field("status_301s", &atomic_load!(self.status_301s))?;
|
||||||
|
state.serialize_field("status_302s", &atomic_load!(self.status_302s))?;
|
||||||
|
state.serialize_field("status_401s", &atomic_load!(self.status_401s))?;
|
||||||
|
state.serialize_field("status_403s", &atomic_load!(self.status_403s))?;
|
||||||
|
state.serialize_field("status_429s", &atomic_load!(self.status_429s))?;
|
||||||
|
state.serialize_field("status_500s", &atomic_load!(self.status_500s))?;
|
||||||
|
state.serialize_field("status_503s", &atomic_load!(self.status_503s))?;
|
||||||
|
state.serialize_field("status_504s", &atomic_load!(self.status_504s))?;
|
||||||
|
state.serialize_field("status_508s", &atomic_load!(self.status_508s))?;
|
||||||
|
state.serialize_field("wildcards_filtered", &atomic_load!(self.wildcards_filtered))?;
|
||||||
|
state.serialize_field("responses_filtered", &atomic_load!(self.responses_filtered))?;
|
||||||
|
state.serialize_field(
|
||||||
|
"resources_discovered",
|
||||||
|
&atomic_load!(self.resources_discovered),
|
||||||
|
)?;
|
||||||
|
state.serialize_field("url_format_errors", &atomic_load!(self.url_format_errors))?;
|
||||||
|
state.serialize_field("redirection_errors", &atomic_load!(self.redirection_errors))?;
|
||||||
|
state.serialize_field("connection_errors", &atomic_load!(self.connection_errors))?;
|
||||||
|
state.serialize_field("request_errors", &atomic_load!(self.request_errors))?;
|
||||||
|
state.serialize_field("directory_scan_times", &self.directory_scan_times)?;
|
||||||
|
state.serialize_field("total_runtime", &self.total_runtime)?;
|
||||||
|
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize implementation for Stats
|
||||||
|
impl<'a> Deserialize<'a> for Stats {
|
||||||
|
/// Deserialize a Stats object from a serde_json::Value
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'a>,
|
||||||
|
{
|
||||||
|
let stats = Self::new(0, false);
|
||||||
|
|
||||||
|
let map: HashMap<String, Value> = HashMap::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
for (key, value) in &map {
|
||||||
|
match key.as_str() {
|
||||||
|
"timeouts" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.timeouts, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"requests" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.requests, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"expected_per_scan" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.expected_per_scan, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"total_expected" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.total_expected, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"successes" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.successes, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"redirects" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.redirects, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"client_errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.client_errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"server_errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.server_errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"total_scans" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.total_scans, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"initial_targets" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.initial_targets, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"links_extracted" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.links_extracted, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_200s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_200s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_301s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_301s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_302s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_302s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_401s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_401s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_403s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_403s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_429s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_429s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_500s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_500s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_503s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_503s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_504s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_504s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"status_508s" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.status_508s, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"wildcards_filtered" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.wildcards_filtered, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"responses_filtered" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.responses_filtered, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"resources_discovered" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.resources_discovered, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"url_format_errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.url_format_errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"redirection_errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.redirection_errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"connection_errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.connection_errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"request_errors" => {
|
||||||
|
if let Some(num) = value.as_u64() {
|
||||||
|
if let Ok(parsed) = usize::try_from(num) {
|
||||||
|
atomic_increment!(stats.request_errors, parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"directory_scan_times" => {
|
||||||
|
if let Some(arr) = value.as_array() {
|
||||||
|
for val in arr {
|
||||||
|
if let Some(parsed) = val.as_f64() {
|
||||||
|
if let Ok(mut guard) = stats.directory_scan_times.lock() {
|
||||||
|
guard.push(parsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"total_runtime" => {
|
||||||
|
if let Some(arr) = value.as_array() {
|
||||||
|
for val in arr {
|
||||||
|
if let Some(parsed) = val.as_f64() {
|
||||||
|
if let Ok(mut guard) = stats.total_runtime.lock() {
|
||||||
|
guard.push(parsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(stats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// implementation of statistics data collection struct
|
/// implementation of statistics data collection struct
|
||||||
impl Stats {
|
impl Stats {
|
||||||
/// Small wrapper for default to set `kind` to "statistics" and `total_runtime` to have at least
|
/// Small wrapper for default to set `kind` to "statistics" and `total_runtime` to have at least
|
||||||
|
|||||||
Reference in New Issue
Block a user